“Spring Boot Actuator in Detail and In-depth Application” is expected to include three chapters. The first chapter focuses on the application and customization of Spring Boot Actuator 1.x. In the second part, compare the differences between Spring Boot Actuator 2.x and 1.x, and apply and customize 2.x endpoints. In chapter 3, the use of Actuator Metric metrics in conjunction with Prometheus and Grafana will be described. This part of the content is very common, and more introductory, welcome your attention.

These reviews

This article is the second part of “Spring Boot Actuator In Detail and In-depth Application”. In the last article: Spring Boot Actuator 1. X mainly describes the application of Spring Boot Actuator 1. The official version of Spring Boot2.0 has been released for some time now and is currently at 2.1.0.release. The features of Spring Boot2.x are not covered in detail here, but the trend in popularity is obvious.

This article compares Spring Boot Actuator 2.x with 1.x, and applies and customizes 2.x endpoints. Focuses on the latest 2.X edition of the Actuator.

Actuator 2.x

Actuator 2.x keeps its basic features, but simplifies its model, expands its features and includes appropriate defaults. First, the version becomes decoupled from a particular framework; In addition, it simplifies its security model by merging it with applications; Finally, some of the changes are dramatic, including HTTP requests/responses and the Java apis provided. In addition, the latest version supports the CRUD model rather than the old RW (read/write) model.

In Actuator 1.x it is bundled with Spring MVC and therefore associated with the Servlet API. In 2.x, the Actuator defines its models as pluggable and extensible, independent of MVC. So with this new model, we can use WebFlux as the underlying Web technology just like MVC. In addition, future frameworks can be added to this model by implementing specific adapters. JMX still supports exposing endpoints without any additional code.

Quick start

Introduce the following dependencies:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
Copy the code

It is the same as the Spring Boot Actuator 1.X in use.

Actuator 2.X changes

Unlike previous versions of the Actuator 1.x, most endpoints of the Actuator 2.x are disabled by default. The default endpoints in skeleton2.x have the prefix/skeleton2.x.

The two endpoints exposed by default are /actuator/health and /actuator/info. We can do this by setting the following properties:

management.endpoints.web.exposure.include=*
Copy the code

All endpoints can be exposed. In addition, we can list endpoints that need to be exposed or exclude certain endpoints. Such as:

management.endpoints.web.exposure.exclude=env,beans
Copy the code

The default endpoint

Let’s look at the available endpoints, most of which already exist in 1.x. Nevertheless, some endpoints were added, some were removed, and some were refactored.

  • / auditEvents: Same as Actuator 1.x, and can be filtered by keywords
  • /beans: Same as Actuator 1.x, cannot be filtered
  • /conditions: Returns the automatic configuration item in the service
  • /configprops: allows us to get@ConfigurationPropertiesThe bean object
  • /env: returns the current environment variable, or we can retrieve a value
  • /flyway: Provides details of the Flyway database migration
  • /health: Same as 2.x
  • /heapdump: returns heapdump information about the JVM used by the application service
  • /info: Same as 2.x
  • /liquibase: Similar to /flyway, but the component tool is liquibase
  • /logfile: returns the common logfile of the application
  • /loggers: allows us to query and modify application log levels
  • /metrics: Same as Actuator 1.x
  • / Prometheus: returns similar to /metrics and is used with Prometheus Server
  • / scheduledTasks: Returns the periodic tasks of the application
  • /sessions: Same as Actuator 1.x
  • /shutdown: Same as 2.x
  • /threaddump: Information about the JVM threads on which the dump depends

Actuator endpoint security

Actuator endpoints are sensitive and must prevent unauthorized access. If Spring Security is present in your application, the endpoint is protected by default using form-based HTTP basic authentication. Use Spring Security to protect the access of endpoints.

Introduction of depend on

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-security</artifactId>
</dependency>
Copy the code

Security configuration

In order to apply the security rules of the Actuator, we add the following configuration:

@Bean
public SecurityWebFilterChain securityWebFilterChain( ServerHttpSecurity http) {
    return http.authorizeExchange()
      .pathMatchers("/actuator/**").permitAll()
      .anyExchange().authenticated()
      .and().build();
}
Copy the code

This configuration makes the urls at the beginning of all visits/actuators must be logged in. We can also use a more detailed configuration:

@Configuration
public class ActuatorSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                    .requestMatchers(EndpointRequest.to(ShutdownEndpoint.class))
                        .hasRole("ACTUATOR_ADMIN")
                    .requestMatchers(EndpointRequest.toAnyEndpoint())
                        .permitAll()
                    .requestMatchers(PathRequest.toStaticResources().atCommonLocations())
                        .permitAll()
                    .antMatchers("/")
                        .permitAll()
                    .antMatchers("/ * *") .authenticated() .and() .httpBasic(); }}Copy the code

The above configuration mainly implements:

  • The role that restricts access to the Shutdown endpoint can only be ACTUATOR_ADMIN
  • Allow access to all other endpoints
  • Allows access to static resources
  • Allow access to the root directory ‘/’
  • All requests must be authenticated
  • Allow HTTP static authentication (you can use any form of authentication)

test

To be able to test the above configuration using HTTP basic authentication, you can add a default Spring security user:

spring:
  security:
    user:
      name: actuator
      password: actuator
      roles: ACTUATOR_ADMIN
Copy the code

/ health endpoint

As in previous versions, we can easily add custom metrics. The abstraction for creating custom health endpoints remains unchanged. Unlike Spring Boot 1.x, the endPoints.

. Sensitive property has been removed. The health information exposed by the /health endpoint depends on:

management.endpoint.health.show-details
Copy the code

This property can be configured using one of the following values:

  • Never: details are not displayed. The status of up or Down is the default value
  • When -authorized: The details will be displayed to the authenticated user. The authorized role can passmanagement.endpoint.health.rolesConfiguration.
  • Always: Exposes detailed information

The /health endpoint has many auto-configured health indicators: components such as Redis, RabbitMQ, and so on.

management.health.mongo.enabled: false
Copy the code

Or disable all automatically configured health indicators:

management.health.defaults.enabled: false
Copy the code

In addition, a new interface, ReactiveHealthIndicator, has been added to enable responsive health checking.

Introduction of depend on

        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-core</artifactId>
        </dependency>
Copy the code

Customize the Reactive health check

@Component
public class DownstreamServiceHealthIndicator implements ReactiveHealthIndicator {

    @Override
    public Mono<Health> health(a) {
        return checkDownstreamServiceHealth().onErrorResume(
                ex -> Mono.just(new Health.Builder().down(ex).build())
        );
    }

    private Mono<Health> checkDownstreamServiceHealth(a) {
        // we could use WebClient to check health reactively
        return Mono.just(newHealth.Builder().up().build()); }}Copy the code

A convenient feature of health metrics is that we can aggregate them as part of a hierarchy. Therefore, following the example above, we can group all downstream services under the downstream service category. As long as each nested service is accessible, this access is healthy.

/ metrics endpoint

In Spring Boot 2.0, a bean of type MeterRegistry will be automatically configured and the MeterRegistry is included in the dependencies of the Actuator. Here is the /metrics endpoint information we obtained.

{
  "names": [
    "jvm.gc.pause"."jvm.buffer.memory.used"."jvm.memory.used"."jvm.buffer.count",
    // ...
  ]
}
Copy the code

It can be seen that, unlike 1.x, we can no longer see specific indicator information, but only show a list of indicators. In order to get the detailed information to an index, we can request a specific index information, such as/physical/metrics/JVM. Gc. Pause

{
	"name": "jvm.gc.pause"."description": "Time spent in GC pause"."baseUnit": "seconds"."measurements": [{
		"statistic": "COUNT"."value": 2.0
	}, {
		"statistic": "TOTAL_TIME"."value": 0.07300000000000001
	}, {
		"statistic": "MAX"."value": 0.0}]."availableTags": [{
		"tag": "cause"."values": ["Metadata GC Threshold"] {},"tag": "action"."values": ["end of minor GC"."end of major GC"]]}}Copy the code

We can see that the indicators are much more detailed now. It includes not only the different values, but also some associated metadata.

/ info endpoint

There are no changes to the /info endpoint. You can add git details by importing dependencies via Maven or Gradle.

<dependency>
    <groupId>pl.project13.maven</groupId>
    <artifactId>git-commit-id-plugin</artifactId>
</dependency>
Copy the code

Similarly, we can use maven and Gradle plug-ins to get the name, group, and version of the build (with the meta-INF /build-info.properties file in the class path).

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>build-info</goal>
            </goals>
        </execution>
    </executions>
</plugin>
Copy the code

Custom endpoints

We can customize endpoints. Spring Boot 2 has updated the method for customizing endpoints. Now we define an endpoint that can query, turn on, or turn off the Features flag bit.

@Component
@Endpoint(id = "features")
public class FeaturesEndpoint {

    private Map<String, Feature> features = new ConcurrentHashMap<>();

    @ReadOperation
    public Map<String, Feature> features(a) {
        return features;
    }

    @ReadOperation
    public Feature feature(@Selector String name) {
        return features.get(name);
    }

    @WriteOperation
    public void configureFeature(@Selector String name, Feature feature) {
        features.put(name, feature);
    }

    @DeleteOperation
    public void deleteFeature(@Selector String name) {
        features.remove(name);
    }

    public static class Feature {
        private Boolean enabled;

		/ /...}}Copy the code

The defined Endpoint path is determined by the ID attribute in @Endpoint. In the example above, the requested Endpoint address is/skeleton/ features. Define actions with the following method annotations:

  • @readoperation: HTTP GET
  • @ WriteOperation: HTTP POST
  • @ DeleteOperation: HTTP DELETE

Start the application and you can see the following log output on the console:

[...]. .WebFluxEndpointHandlerMapping: Mapped"{[/actuator/features/{name}], methods=[GET], produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"[...]. .WebFluxEndpointHandlerMapping : Mapped"{[/actuator/features], methods=[GET], produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}"[...]. .WebFluxEndpointHandlerMapping : Mapped"{[/actuator/features/{name}], methods=[POST], consumes=[application/vnd.spring-boot.actuator.v2+json || application/json]}"[...]. .WebFluxEndpointHandlerMapping : Mapped"{[/actuator/features/{name}], methods=[DELETE]}"[...].Copy the code

The above log shows how Webflux exposes our endpoints, and as for switching to Spring MVC, we just need to introduce dependencies without changing any code.

The metadata on the previous method (sensitive, enabled) is not used anymore. Enable or disable endpoints using @endpoint (id = “features”, enableByDefault = false). In contrast to the old read/write model, we can define DELETE operations using @deleteOperation.

Extend the endpoint

We can also extend our pre-defined endpoints with the @EndPointextension annotation, or more precisely @EndPointwebextension, @EndpointJMxExtension.

@Component
@EndpointWebExtension(endpoint = InfoEndpoint.class)
public class InfoWebEndpointExtension {
 
    private InfoEndpoint delegate;
 
    @Autowired
    public InfoWebEndpointExtension(InfoEndpoint delegate) {
        this.delegate = delegate;
    }
 
    @ReadOperation
    public WebEndpointResponse<Map> info() {
        Map<String, Object> info = this.delegate.info();
        Integer status = getStatus(info);
        return new WebEndpointResponse<>(info, status);
    }
 
    private Integer getStatus(Map<String, Object> info) {
        // return 5xx if this is a snapshot
        return200; }}Copy the code

conclusion

This article mainly introduces the features and usage of the Actuator 2.x, and compares it with the use of the Actuator 1.x. Actuator 2.X does not rely on a framework component (such as Spring MVC), making it easy to plug and expand. When we want to switch to Webflux, we do so without changing any code using the adapters in Actuator 2.x. Source: github.com/keets2012/S…

Subscribe to the latest articles, welcome to follow my official account

reference

  1. Actuator docs
  2. Spring Boot Actuator