Skip to content

Commit 05eca30

Browse files
committed
spring-actuator-demo starter
1 parent a85c4f4 commit 05eca30

File tree

9 files changed

+276
-0
lines changed

9 files changed

+276
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Spring Boot Actuator: Health Check, Auditing, Metrics Gathering and Monitoring
2+
3+
## Tutorials
4+
5+
1. [Spring Boot Actuator: Health check, Auditing, Metrics gathering and Monitoring](https://www.callicoder.com/spring-boot-actuator/)
6+
2. [Spring Boot Actuator metrics monitoring with Prometheus and Grafana](https://www.callicoder.com/spring-boot-actuator-metrics-monitoring-dashboard-prometheus-grafana/)
7+
8+
## Steps to Setup
9+
10+
**1. Clone the application**
11+
12+
```bash
13+
git clone https://github.com/callicoder/spring-boot-actuator-demo.git
14+
```
15+
16+
**2. Build and run the app using maven**
17+
18+
```bash
19+
mvn package
20+
java -jar target/actuator-demo-0.0.1-SNAPSHOT.jar
21+
```
22+
23+
Alternatively, you can run the app directly without packaging like this -
24+
25+
```bash
26+
mvn spring-boot:run
27+
```
28+
29+
The app will start running at <http://localhost:8080>.
30+
31+
## Explore Actuator Endpoints
32+
33+
All the actuator endpoints will be available at <http://localhost:8080/actuator>.
34+
35+
Some of the actuator endpoints are protected with Spring Security's HTTP Basic Authentication. You can use the username `actuator` and password `actuator` for http basic authentication.
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
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+
6+
<groupId>com.example</groupId>
7+
<artifactId>actuator-demo</artifactId>
8+
<version>0.0.1-SNAPSHOT</version>
9+
<packaging>jar</packaging>
10+
11+
<name>actuator-demo</name>
12+
<description>Spring Boot Actuator Demo Project</description>
13+
14+
<parent>
15+
<groupId>org.springframework.boot</groupId>
16+
<artifactId>spring-boot-starter-parent</artifactId>
17+
<version>2.2.1.RELEASE</version>
18+
<relativePath/> <!-- lookup parent from repository -->
19+
</parent>
20+
21+
<properties>
22+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
23+
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
24+
<java.version>1.8</java.version>
25+
</properties>
26+
27+
<dependencies>
28+
<dependency>
29+
<groupId>org.springframework.boot</groupId>
30+
<artifactId>spring-boot-starter-actuator</artifactId>
31+
</dependency>
32+
33+
<dependency>
34+
<groupId>org.springframework.boot</groupId>
35+
<artifactId>spring-boot-starter-security</artifactId>
36+
</dependency>
37+
38+
<dependency>
39+
<groupId>org.springframework.boot</groupId>
40+
<artifactId>spring-boot-starter-web</artifactId>
41+
</dependency>
42+
43+
<!-- Micrometer Prometheus registry -->
44+
<dependency>
45+
<groupId>io.micrometer</groupId>
46+
<artifactId>micrometer-registry-prometheus</artifactId>
47+
</dependency>
48+
49+
<dependency>
50+
<groupId>org.springframework.boot</groupId>
51+
<artifactId>spring-boot-starter-test</artifactId>
52+
<scope>test</scope>
53+
</dependency>
54+
55+
<dependency>
56+
<groupId>org.springframework.security</groupId>
57+
<artifactId>spring-security-test</artifactId>
58+
<scope>test</scope>
59+
</dependency>
60+
</dependencies>
61+
62+
<build>
63+
<plugins>
64+
<plugin>
65+
<groupId>org.springframework.boot</groupId>
66+
<artifactId>spring-boot-maven-plugin</artifactId>
67+
</plugin>
68+
</plugins>
69+
</build>
70+
71+
72+
</project>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.example.actuatordemo;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
6+
@SpringBootApplication
7+
public class ActuatorDemoApplication {
8+
9+
public static void main(String[] args) {
10+
SpringApplication.run(ActuatorDemoApplication.class, args);
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.example.actuatordemo.config;
2+
3+
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
4+
import org.springframework.boot.actuate.context.ShutdownEndpoint;
5+
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
6+
import org.springframework.context.annotation.Configuration;
7+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
8+
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
9+
10+
@Configuration
11+
public class ActuatorSecurityConfig extends WebSecurityConfigurerAdapter {
12+
13+
/*
14+
This spring security configuration does the following
15+
16+
1. Restrict access to the Shutdown endpoint to the ACTUATOR_ADMIN role.
17+
2. Allow access to all other actuator endpoints.
18+
3. Allow access to static resources.
19+
4. Allow access to the home page (/).
20+
5. All other requests need to be authenticated.
21+
5. Enable http basic authentication to make the configuration complete.
22+
You are free to use any other form of authentication.
23+
*/
24+
25+
@Override
26+
protected void configure(HttpSecurity http) throws Exception {
27+
http
28+
.authorizeRequests()
29+
.requestMatchers(EndpointRequest.to(ShutdownEndpoint.class))
30+
.hasRole("ACTUATOR_ADMIN")
31+
.requestMatchers(EndpointRequest.toAnyEndpoint())
32+
.permitAll()
33+
.requestMatchers(PathRequest.toStaticResources().atCommonLocations())
34+
.permitAll()
35+
.antMatchers("/", "/slowApi")
36+
.permitAll()
37+
.antMatchers("/**")
38+
.authenticated()
39+
.and()
40+
.httpBasic();
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.example.actuatordemo.controller;
2+
3+
import org.springframework.web.bind.annotation.GetMapping;
4+
import org.springframework.web.bind.annotation.RequestParam;
5+
import org.springframework.web.bind.annotation.RestController;
6+
7+
import java.util.Random;
8+
import java.util.concurrent.TimeUnit;
9+
10+
@RestController
11+
public class SampleController {
12+
13+
@GetMapping("/")
14+
public String sayHello(@RequestParam(value = "name", defaultValue = "Guest") String name) {
15+
return "Hello " + name + "!!";
16+
}
17+
18+
@GetMapping("/slowApi")
19+
public String timeConsumingAPI(@RequestParam(value = "delay", defaultValue = "0") Integer delay) throws InterruptedException {
20+
if(delay == 0) {
21+
Random random = new Random();
22+
delay = random.nextInt(10);
23+
}
24+
25+
TimeUnit.SECONDS.sleep(delay);
26+
return "Result";
27+
}
28+
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.example.actuatordemo.health;
2+
3+
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
4+
import org.springframework.boot.actuate.health.Health;
5+
import org.springframework.stereotype.Component;
6+
7+
@Component
8+
public class CustomHealthIndicator extends AbstractHealthIndicator {
9+
10+
@Override
11+
protected void doHealthCheck(Health.Builder builder) throws Exception {
12+
// Use the builder to build the health status details that should be reported.
13+
// If you throw an exception, the status will be DOWN with the exception message.
14+
15+
builder.up()
16+
.withDetail("app", "Alive and Kicking")
17+
.withDetail("error", "Nothing! I'm good.");
18+
}
19+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Logging
2+
logging.file=app.log
3+
4+
# Spring Security default user name and password
5+
spring.security.user.name=actuator
6+
spring.security.user.password=actuator
7+
spring.security.user.roles=ACTUATOR_ADMIN
8+
9+
# INFO ENDPOINT CONFIGURATION
10+
info.app.name=@project.name@
11+
info.app.description=@project.description@
12+
info.app.version=@project.version@
13+
info.app.encoding=@project.build.sourceEncoding@
14+
info.app.java.version=@java.version@
15+
16+
# SHUTDOWN ENDPOINT (ShutdownEndpoint)
17+
management.endpoint.shutdown.enabled=true
18+
19+
# HEALTH ENDPOINT
20+
management.endpoint.health.show-details=always
21+
22+
# ENDPOINTS WEB CONFIGURATION
23+
management.endpoints.web.exposure.include=*
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# my global config
2+
global:
3+
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
4+
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
5+
# scrape_timeout is set to the global default (10s).
6+
7+
# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
8+
rule_files:
9+
# - "first_rules.yml"
10+
# - "second_rules.yml"
11+
12+
# A scrape configuration containing exactly one endpoint to scrape:
13+
# Here it's Prometheus itself.
14+
scrape_configs:
15+
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
16+
- job_name: 'prometheus'
17+
18+
# metrics_path defaults to '/metrics'
19+
# scheme defaults to 'http'.
20+
21+
static_configs:
22+
- targets: ['127.0.0.1:9090']
23+
24+
- job_name: 'spring-actuator'
25+
metrics_path: '/actuator/prometheus'
26+
scrape_interval: 5s
27+
static_configs:
28+
- targets: ['HOST_IP:8080']
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.example.actuatordemo;
2+
3+
import org.junit.Test;
4+
import org.junit.runner.RunWith;
5+
import org.springframework.boot.test.context.SpringBootTest;
6+
import org.springframework.test.context.junit4.SpringRunner;
7+
8+
@RunWith(SpringRunner.class)
9+
@SpringBootTest
10+
public class ActuatorDemoApplicationTests {
11+
12+
@Test
13+
public void contextLoads() {
14+
}
15+
16+
}

0 commit comments

Comments
 (0)