Skip to content

Commit 398ef2b

Browse files
committed
Lesson 7: Creating Operations-Friendly Microservices
1 parent 48d1963 commit 398ef2b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1033
-0
lines changed

livelessons-operations/README.adoc

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
:compat-mode:
2+
= Lesson 7: Creating Operations-Friendly Microservices
3+
4+
_Learn how to build production-ready Microservices._
5+
6+
- link:livelessons-operations-logging[Logging]
7+
- link:livelessons-operations-actuator[Actuator]
8+
- link:livelessons-operations-monitoring[Monitoring]
9+
- link:livelessons-operations-cloud-monitoring[Monitoring in the Cloud]
10+
- link:livelessons-operations-metrics[Metrics]
11+
- link:livelessons-operations-cloud-metrics[Metrics in the Cloud]
12+
- link:livelessons-operations-actuator-extensions[Extending Actuator]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
:compat-mode:
2+
= Lesson 3: Creating Operations-Friendly Microservices (Extending Actuator)
3+
4+
== Introduction
5+
Demonstrates how you can add your own actuator endpoints.
6+
7+
== Building and running the sample
8+
Use the following commands to build run the application:
9+
10+
```
11+
$ mvn clean package
12+
$ java -jar target/livelessons-operations-actuator-extensions-1.0.0-SNAPSHOT.jar
13+
```
14+
15+
== Understanding the code
16+
The `WeatherEndpoint` shows how you can easily add actuator endpoints by writing a bean
17+
that implements the `Endpoint` interface (in this case by extending `AbstractEndpoint`).
18+
You can access in the same way as the standard ones (HTTP, SSH, JMX).
19+
20+
The `WeatherMvcEndpoint` shows how you can also write specific extensions to be used
21+
when the endpoint is accessed over HTTP. In this case we are adding a content type
22+
support. If you open http://localhost:8080/weather in a browser you will see red text,
23+
if you use `curl` you don't see any HTML markup.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>livelessons</groupId>
7+
<artifactId>livelessons-operations</artifactId>
8+
<version>1.0.0-SNAPSHOT</version>
9+
</parent>
10+
<artifactId>livelessons-operations-actuator-extensions</artifactId>
11+
<properties>
12+
<main.basedir>../..</main.basedir>
13+
</properties>
14+
<dependencies>
15+
<dependency>
16+
<groupId>org.springframework.boot</groupId>
17+
<artifactId>spring-boot-starter-web</artifactId>
18+
</dependency>
19+
<dependency>
20+
<groupId>org.springframework.boot</groupId>
21+
<artifactId>spring-boot-starter-actuator</artifactId>
22+
</dependency>
23+
</dependencies>
24+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package demo;
2+
3+
import org.springframework.web.bind.annotation.RequestMapping;
4+
import org.springframework.web.bind.annotation.RestController;
5+
6+
@RestController
7+
public class ExampleController {
8+
9+
@RequestMapping("/")
10+
public String hello() {
11+
return "Hello World!";
12+
}
13+
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package demo;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
6+
@SpringBootApplication
7+
public class OperationsActuatorExtensionsApplication {
8+
9+
public static void main(String[] args) {
10+
SpringApplication.run(OperationsActuatorExtensionsApplication.class, args);
11+
}
12+
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package demo;
2+
3+
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
4+
import org.springframework.stereotype.Component;
5+
6+
@Component
7+
public class WeatherEndpoint extends AbstractEndpoint<String> {
8+
9+
public WeatherEndpoint() {
10+
super("weather");
11+
}
12+
13+
@Override
14+
public String invoke() {
15+
return "frightful";
16+
}
17+
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package demo;
2+
3+
import org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter;
4+
import org.springframework.http.MediaType;
5+
import org.springframework.stereotype.Component;
6+
import org.springframework.web.bind.annotation.RequestMapping;
7+
import org.springframework.web.bind.annotation.ResponseBody;
8+
9+
@Component
10+
public class WeatherMvcEndpoint extends EndpointMvcAdapter {
11+
12+
public WeatherMvcEndpoint() {
13+
super(new WeatherEndpoint());
14+
}
15+
16+
@RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
17+
@ResponseBody
18+
public String invokeHtml() {
19+
return "<h1 style=\"color:red\">" + getDelegate().invoke() + "</h1>";
20+
}
21+
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
:compat-mode:
2+
= Lesson 3: Creating Operations-Friendly Microservices (Logging)
3+
4+
== Introduction
5+
Provides an introduction to Spring Boot Actuator.
6+
7+
== Building and running the sample
8+
Use the following commands to build run the application:
9+
10+
```
11+
$ mvn clean package
12+
$ java -jar target/livelessons-operations-actuator-1.0.0-SNAPSHOT.jar
13+
```
14+
15+
== HTTP Endpoints
16+
The following HTTP endpoints can be inspected in a running application:
17+
18+
- http://localhost:8080/autoconfig[/autoconfig]
19+
- http://localhost:8080/beans[/beans]
20+
- http://localhost:8080/configprops[/configprops]
21+
- http://localhost:8080/dump[/dump]
22+
- http://localhost:8080/env[/env]
23+
- http://localhost:8080/health[/health]
24+
- http://localhost:8080/info[/info]
25+
- http://localhost:8080/metrics[/metrics]
26+
- http://localhost:8080/mappings[/mappings]
27+
- http://localhost:8080/trace[/trace]
28+
29+
== JMX
30+
To view the same information using JMX you can use `jconsole`:
31+
32+
```
33+
$ jconsole
34+
```
35+
36+
Select `demo.OperationsActuatorApplication` from the ``local applications'' section (use
37+
insecure connection if asked) then click on the MBeans tab. You can the endpoints under
38+
`org.springframework.boot/Endpoint` pick an endpoint then click the `getData` button
39+
under `operations`.
40+
41+
== SSH
42+
You can ssh into the running application using the following command:
43+
44+
```
45+
$ ssh -p 2000 livelessons@localhost
46+
```
47+
48+
The password is `livelessons` (see `application.properties`).
49+
50+
Type `help` to get a list of commands. Endpoints can be executed using
51+
`endpoint invoke <name>` (for example `endpoint invoke info`). Several endpoints are
52+
also surfaced directly (for example `metrics`). The `dashboard` command is also quite
53+
fun.
54+
55+
56+
== JMX over Jolokia
57+
Jolokia allows you to expose JMX beans over HTTP. Adding the library is all you need to
58+
do to configure it with Spring Boot. It can be useful if you have existing MBeans (or
59+
MBeans exposed by libraries that you use).
60+
61+
Here is an example call that will return `HeapMemoryUsage` information from the `Memory`
62+
MBean in `java/lang`:
63+
64+
```
65+
$ curl http://localhost:8080/jolokia/read/java.lang:type=Memory/HeapMemoryUsage
66+
```
67+
68+
== Using the Git Commit ID
69+
This sample includes the `git-commit-id-plugin`Maven Plugin which will write a
70+
`git.properties` file whenever the project is build. This information is automatically
71+
exposed on the `/info` endpoint.
72+
73+
The commit SHA is very useful when running applications in production as it allows you
74+
to know exactly which commit was used to build the running app. You also use this to
75+
get back to the `POM.xml` or `build.gradle` and know exactly which library versions were
76+
used when the app was built.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>livelessons</groupId>
7+
<artifactId>livelessons-operations</artifactId>
8+
<version>1.0.0-SNAPSHOT</version>
9+
</parent>
10+
<artifactId>livelessons-operations-actuator</artifactId>
11+
<properties>
12+
<main.basedir>../..</main.basedir>
13+
</properties>
14+
<dependencies>
15+
<dependency>
16+
<groupId>org.springframework.boot</groupId>
17+
<artifactId>spring-boot-starter-web</artifactId>
18+
</dependency>
19+
<dependency>
20+
<groupId>org.springframework.boot</groupId>
21+
<artifactId>spring-boot-starter-actuator</artifactId>
22+
</dependency>
23+
<dependency>
24+
<groupId>org.springframework.boot</groupId>
25+
<artifactId>spring-boot-starter-remote-shell</artifactId>
26+
</dependency>
27+
<dependency>
28+
<groupId>org.jolokia</groupId>
29+
<artifactId>jolokia-core</artifactId>
30+
</dependency>
31+
</dependencies>
32+
<build>
33+
<plugins>
34+
<plugin>
35+
<groupId>pl.project13.maven</groupId>
36+
<artifactId>git-commit-id-plugin</artifactId>
37+
<configuration>
38+
<dotGitDirectory>${project.basedir}/../../.git</dotGitDirectory>
39+
</configuration>
40+
</plugin>
41+
</plugins>
42+
</build>
43+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package demo;
2+
3+
import org.springframework.web.bind.annotation.RequestMapping;
4+
import org.springframework.web.bind.annotation.RestController;
5+
6+
@RestController
7+
public class ExampleController {
8+
9+
@RequestMapping("/")
10+
public String hello() {
11+
return "Hello World!";
12+
}
13+
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package demo;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
6+
@SpringBootApplication
7+
public class OperationsActuatorApplication {
8+
9+
public static void main(String[] args) {
10+
SpringApplication.run(OperationsActuatorApplication.class, args);
11+
}
12+
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
shell.auth.simple.user.name=livelessons
2+
shell.auth.simple.user.password=livelessons
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
:compat-mode:
2+
= Lesson 3: Creating Operations-Friendly Microservices (Cloud Metrics)
3+
4+
== Introduction
5+
This sample shows how you can use Spring Boot Actuator metrics to talk to a cloud
6+
service. In this example we will use datadog.com.
7+
8+
== Prerequisites
9+
You need a datadog.com account to run this sample. The offer a free trial. Once you have
10+
signed-up, login and select the integrations tab to get the API key. Then add it to
11+
`src/main/resources/application-secrets.properties`:
12+
13+
```
14+
datadog.apikey=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
15+
16+
```
17+
18+
== Building and running the sample
19+
Use the following commands to build run the application:
20+
21+
```
22+
$ mvn clean package
23+
$ java -jar target/livelessons-operations-cloud-metrics-1.0.0-SNAPSHOT.jar
24+
```
25+
26+
== Understanding the code
27+
Live many cloud metrics services datadog.com offers integration with the
28+
https://dropwizard.github.io/metrics[Dropwizard Metrics] library. Spring Boot also
29+
supports Dropwizard Metrics so you can use the two together with relative ease.
30+
31+
The project `pom.xml` includes dependencies to `io.dropwizard.metrics:metrics-core` and
32+
the `org.coursera:dropwizard-metrics-datadog` integration library. See
33+
`OperationsCloudMetricsApplication` for the actual datadog configuration.
34+
35+
To see the actual request/response HTML you can uncomment the following in
36+
`application.properties`:
37+
38+
```
39+
logging.level.org.coursera.metrics.datadog=DEBUG
40+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
<parent>
6+
<groupId>livelessons</groupId>
7+
<artifactId>livelessons-operations</artifactId>
8+
<version>1.0.0-SNAPSHOT</version>
9+
</parent>
10+
<artifactId>livelessons-operations-cloud-metrics</artifactId>
11+
<properties>
12+
<main.basedir>../..</main.basedir>
13+
</properties>
14+
<dependencies>
15+
<dependency>
16+
<groupId>org.springframework.boot</groupId>
17+
<artifactId>spring-boot-starter-web</artifactId>
18+
</dependency>
19+
<dependency>
20+
<groupId>org.springframework.boot</groupId>
21+
<artifactId>spring-boot-starter-actuator</artifactId>
22+
</dependency>
23+
<dependency>
24+
<groupId>io.dropwizard.metrics</groupId>
25+
<artifactId>metrics-core</artifactId>
26+
</dependency>
27+
<dependency>
28+
<groupId>org.coursera</groupId>
29+
<artifactId>dropwizard-metrics-datadog</artifactId>
30+
<version>1.0.2</version>
31+
<exclusions>
32+
<exclusion>
33+
<groupId>io.dropwizard</groupId>
34+
<artifactId>dropwizard-metrics</artifactId>
35+
</exclusion>
36+
</exclusions>
37+
</dependency>
38+
</dependencies>
39+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package demo;
2+
3+
import org.springframework.web.bind.annotation.RequestMapping;
4+
import org.springframework.web.bind.annotation.RestController;
5+
6+
@RestController
7+
public class ExampleController {
8+
9+
@RequestMapping("/")
10+
public String hello() {
11+
return "Hello World!";
12+
}
13+
14+
}

0 commit comments

Comments
 (0)