Actuator-Note

May 23, 2025 / Administrator / 0阅读 / 0评论/ 分类: Observerty

reference

https://docs.spring.io/spring-boot/3.3/reference/actuator/enabling.html

To add the actuator to a Maven-based project, add the following starter dependency:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

[API documentation : https://docs.spring.io/spring-boot/3.3/api/rest/actuator/index.html

Endpoints

Actuator endpoints let you monitor and interact with your application. Spring Boot includes a number of built-in endpoints and lets you add your own. For example, the health endpoint provides basic application health information.

You can enable or disable each individual endpoint and expose them (make them remotely accessible) over HTTP or JMX. An endpoint is considered to be available when it is both enabled and exposed. The built-in endpoints are auto-configured only when they are available. Most applications choose exposure over HTTP, where the ID of the endpoint and a prefix of /actuator is mapped to a URL. For example, by default, the health endpoint is mapped to /actuator/health.

The following technology-agnostic endpoints are available:

ID Description
auditevents Exposes audit events information for the current application. Requires anAuditEventRepositorybean.
beans Displays a complete list of all the Spring beans in your application.
caches Exposes available caches.
conditions Shows the conditions that were evaluated on configuration and auto-configuration classes and the reasons why they did or did not match.
configprops Displays a collated list of all@ConfigurationProperties. Subject tosanitization.
env Exposes properties from Spring’sConfigurableEnvironment. Subject tosanitization.
flyway Shows any Flyway database migrations that have been applied. Requires one or moreFlywaybeans.
health Shows application health information.
httpexchanges Displays HTTP exchange information (by default, the last 100 HTTP request-response exchanges). Requires anHttpExchangeRepositorybean.
info Displays arbitrary application info.
integrationgraph Shows the Spring Integration graph. Requires a dependency on spring-integration-core.
loggers Shows and modifies the configuration of loggers in the application.
liquibase Shows any Liquibase database migrations that have been applied. Requires one or moreLiquibasebeans.
metrics Shows “metrics” information for the current application to diagnose the metrics the application has recorded.
mappings Displays a collated list of all@RequestMappingpaths.
quartz Shows information about Quartz Scheduler jobs. Subject tosanitization.
scheduledtasks Displays the scheduled tasks in your application.
sessions Allows retrieval and deletion of user sessions from a Spring Session-backed session store. Requires a servlet-based web application that uses Spring Session.
shutdown Lets the application be gracefully shutdown. Only works when using jar packaging. Disabled by default.
startup Shows thestartup steps datacollected by theApplicationStartup. Requires theSpringApplicationto be configured with aBufferingApplicationStartup.
threaddump Performs a thread dump.

If your application is a web application (Spring MVC, Spring WebFlux, or Jersey), you can use the following additional endpoints:

ID Description
heapdump Returns a heap dump file. On a HotSpot JVM, an HPROF-format file is returned. On an OpenJ9 JVM, a PHD-format file is returned.
logfile Returns the contents of the logfile (if the logging.file.nameor the logging.file.pathproperty has been set). Supports the use of the HTTP Rangeheader to retrieve part of the log file’s content.
prometheus Exposes metrics in a format that can be scraped by a Prometheus server. Requires a dependency on micrometer-registry-prometheus.

Enabling Endpoints

By default, all endpoints except for shutdown are enabled. To configure the enablement of an endpoint, use its management.endpoint.<id>.enabled property. The following example enables the shutdown endpoint:

management:
  endpoint:
    shutdown:
      enabled: true

If you prefer endpoint enablement to be opt-in rather than opt-out, set the management.endpoints.enabled-by-default property to false and use individual endpoint enabled properties to opt back in. The following example enables the info endpoint and disables all other endpoints:

management:
  endpoints:
    enabled-by-default: false
  endpoint:
    info:
      enabled: true

Exposing Endpoints

By default, only the health endpoint is exposed over HTTP and JMX. Since Endpoints may contain sensitive information, you should carefully consider when to expose them.

To change which endpoints are exposed, use the following technology-specific include and exclude properties:

Property Default
management.endpoints.jmx.exposure.exclude
management.endpoints.jmx.exposure.include health
management.endpoints.web.exposure.exclude
management.endpoints.web.exposure.include health

The include property lists the IDs of the endpoints that are exposed. The exclude property lists the IDs of the endpoints that should not be exposed. The exclude property takes precedence over the include property. You can configure both the include and the exclude properties with a list of endpoint IDs.

For example, to only expose the health and info endpoints over JMX, use the following property:

management:
  endpoints:
    jmx:
      exposure:
        include: "health,info"

* can be used to select all endpoints. For example, to expose everything over HTTP except the env and beans endpoints, use the following properties:

management:
  endpoints:
    web:
      exposure:
        include: "*"
        exclude: "env,beans"

* has a special meaning in YAML, so be sure to add quotation marks if you want to include (or exclude) all endpoints.

If your application is exposed publicly, we strongly recommend that you also secure your endpoints.

If you want to implement your own strategy for when endpoints are exposed, you can register an EndpointFilter bean.

Security

For security purposes, only the /health endpoint is exposed over HTTP by default. You can use the management.endpoints.web.exposure.include property to configure the endpoints that are exposed.

If Spring Security is on the classpath and no other SecurityFilterChain bean is present, all actuators other than /health are secured by Spring Boot auto-configuration. If you define a custom SecurityFilterChain bean, Spring Boot auto-configuration backs off and lets you fully control the actuator access rules.

If you wish to configure custom security for HTTP endpoints (for example, to allow only users with a certain role to access them), Spring Boot provides some convenient RequestMatcher objects that you can use in combination with Spring Security.

A typical Spring Security configuration might look something like the following example:

import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

import static org.springframework.security.config.Customizer.withDefaults;

@Configuration(proxyBeanMethods = false)
public class MySecurityConfiguration {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.securityMatcher(EndpointRequest.toAnyEndpoint());
        http.authorizeHttpRequests((requests) -> requests.anyRequest().hasRole("ENDPOINT_ADMIN"));
        http.httpBasic(withDefaults());
        return http.build();
    }

}

The preceding example uses EndpointRequest.toAnyEndpoint() to match a request to any endpoint and then ensures that all have the ENDPOINT_ADMIN role. Several other matcher methods are also available on EndpointRequest. See the API documentation for details.

If you deploy applications behind a firewall, you may prefer that all your actuator endpoints can be accessed without requiring authentication. You can do so by changing the management.endpoints.web.exposure.include property, as follows:

management:
  endpoints:
    web:
      exposure:
        include: "*"

Additionally, if Spring Security is present, you would need to add custom security configuration that allows unauthenticated access to the endpoints, as the following example shows:

import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration(proxyBeanMethods = false)
public class MySecurityConfiguration {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.securityMatcher(EndpointRequest.toAnyEndpoint());
        http.authorizeHttpRequests((requests) -> requests.anyRequest().permitAll());
        return http.build();
    }

}

In both of the preceding examples, the configuration applies only to the actuator endpoints. Since Spring Boot’s security configuration backs off completely in the presence of any SecurityFilterChain bean, you need to configure an additional SecurityFilterChain bean with rules that apply to the rest of the application.

Observability

Observability is the ability to observe the internal state of a running system from the outside. It consists of the three pillars: logging, metrics and traces.

For metrics and traces, Spring Boot uses Micrometer Observation. To create your own observations (which will lead to metrics and traces), you can inject an ObservationRegistry.

Common Tags

Common tags are generally used for dimensional drill-down on the operating environment, such as host, instance, region, stack, and others. Common tags are applied to all observations as low cardinality tags and can be configured, as the following example shows:

management:
  observations:
    key-values:
      region: "us-east-1"
      stack: "prod"

The preceding example adds region and stack tags to all observations with a value of us-east-1 and prod, respectively.

Preventing Observations

If you’d like to prevent some observations from being reported, you can use the management.observations.enable properties:

management:
  observations:
    enable:
      denied:
        prefix: false
      another:
        denied:
          prefix: false

The preceding example will prevent all observations with a name starting with denied.prefix or another.denied.prefix.

Tip: If you want to prevent Spring Security from reporting observations, set the property management.observations.enable.spring.security to false.

If you need greater control over the prevention of observations, you can register beans of type ObservationPredicate. Observations are only reported if all the ObservationPredicate beans return true for that observation.

import io.micrometer.observation.Observation.Context;
import io.micrometer.observation.ObservationPredicate;

import org.springframework.stereotype.Component;

@Component
class MyObservationPredicate implements ObservationPredicate {

    @Override
    public boolean test(String name, Context context) {
        return !name.contains("denied");
    }

}

The preceding example will prevent all observations whose name contains "denied".

OpenTelemetry Support

Spring Boot’s actuator module includes basic support for OpenTelemetry.

It provides a bean of type OpenTelemetry, and if there are beans of type SdkTracerProvider, ContextPropagators, SdkLoggerProvider or SdkMeterProvider in the application context, they automatically get registered. Additionally, it provides a Resource bean. The attributes of the auto-configured Resource can be configured via the management.opentelemetry.resource-attributes configuration property. If you have defined your own Resource bean, this will no longer be the case.

Micrometer Observation Annotations support

To enable scanning of observability annotations like @Observed, @Timed, @Counted, @MeterTag and @NewSpan, you need to set the management.observations.annotations.enabled property to true. This feature is supported by Micrometer directly. Please refer to the Micrometer, Micrometer Observation and Micrometer Tracing reference docs.

Loggers

Spring Boot Actuator includes the ability to view and configure the log levels of your application at runtime. You can view either the entire list or an individual logger’s configuration, which is made up of both the explicitly configured logging level as well as the effective logging level given to it by the logging framework. These levels can be one of:

  • TRACE
  • DEBUG
  • INFO
  • WARN
  • ERROR
  • FATAL
  • OFF
  • null

null indicates that there is no explicit configuration.

Metrics

Spring Boot Actuator provides dependency management and auto-configuration for Micrometer, an application metrics facade that supports numerous monitoring systems, including:

Getting Started

Spring Boot auto-configures a composite MeterRegistry and adds a registry to the composite for each of the supported implementations that it finds on the classpath. Having a dependency on micrometer-registry-{system} in your runtime classpath is enough for Spring Boot to configure the registry.

Most registries share common features. For instance, you can disable a particular registry even if the Micrometer registry implementation is on the classpath. The following example disables Datadog:

management:
  datadog:
    metrics:
      export:
        enabled: false

You can also disable all registries unless stated otherwise by the registry-specific property, as the following example shows:

management:
  defaults:
    metrics:
      export:
        enabled: false

Spring Boot also adds any auto-configured registries to the global static composite registry on the Metrics class, unless you explicitly tell it not to:

management:
  metrics:
    use-global-registry: false

You can register any number of MeterRegistryCustomizer beans to further configure the registry, such as applying common tags, before any meters are registered with the registry:

import io.micrometer.core.instrument.MeterRegistry;

import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyMeterRegistryConfiguration {

    @Bean
    public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
        return (registry) -> registry.config().commonTags("region", "us-east-1");
    }

}

You can apply customizations to particular registry implementations by being more specific about the generic type:

import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.config.NamingConvention;
import io.micrometer.graphite.GraphiteMeterRegistry;

import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyMeterRegistryConfiguration {

    @Bean
    public MeterRegistryCustomizer<GraphiteMeterRegistry> graphiteMetricsNamingConvention() {
        return (registry) -> registry.config().namingConvention(this::name);
    }

    private String name(String name, Meter.Type type, String baseUnit) {
        return ...
    }

}

Supported Monitoring Systems

This section briefly describes each of the supported monitoring systems.

OTLP

By default, metrics are exported over the OpenTelemetry protocol (OTLP) to a consumer running on your local machine. To export to another location, provide the location of the OTLP metrics endpoint using management.otlp.metrics.export.url:

management:
  otlp:
    metrics:
      export:
        url: "https://otlp.example.com:4318/v1/metrics"

Custom headers, for example for authentication, can also be provided using management.otlp.metrics.export.headers.* properties.

Supported Metrics and Meters

Spring Boot provides automatic meter registration for a wide variety of technologies. In most situations, the defaults provide sensible metrics that can be published to any of the supported monitoring systems.

JVM Metrics

Auto-configuration enables JVM Metrics by using core Micrometer classes. JVM metrics are published under the jvm. meter name.

The following JVM metrics are provided:

  • Various memory and buffer pool details
  • Statistics related to garbage collection
  • Thread utilization
  • The number of classes loaded and unloaded
  • JVM version information
  • JIT compilation time

System Metrics

Auto-configuration enables system metrics by using core Micrometer classes. System metrics are published under the system., process., and disk. meter names.

The following system metrics are provided:

  • CPU metrics
  • File descriptor metrics
  • Uptime metrics (both the amount of time the application has been running and a fixed gauge of the absolute start time)
  • Disk space available

Application Startup Metrics

Auto-configuration exposes application startup time metrics:

  • application.started.time: time taken to start the application.
  • application.ready.time: time taken for the application to be ready to service requests.

Metrics are tagged by the fully qualified name of the application class.

Tomcat Metrics

Auto-configuration enables the instrumentation of Tomcat only when an MBean Registry is enabled. By default, the MBean registry is disabled, but you can enable it by setting server.tomcat.mbeanregistry.enabled to true.

Tomcat metrics are published under the tomcat. meter name.

Registering Custom Metrics

To register custom metrics, inject MeterRegistry into your component:

import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tags;

import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final Dictionary dictionary;

    public MyBean(MeterRegistry registry) {
        this.dictionary = Dictionary.load();
        registry.gauge("dictionary.size", Tags.empty(), this.dictionary.getWords().size());
    }

}

If your metrics depend on other beans, we recommend that you use a MeterBinder to register them:

import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.binder.MeterBinder;

import org.springframework.context.annotation.Bean;

public class MyMeterBinderConfiguration {

    @Bean
    public MeterBinder queueSize(Queue queue) {
        return (registry) -> Gauge.builder("queueSize", queue::size).register(registry);
    }

}

Using a MeterBinder ensures that the correct dependency relationships are set up and that the bean is available when the metric’s value is retrieved. A MeterBinder implementation can also be useful if you find that you repeatedly instrument a suite of metrics across components or applications.

By default, metrics from all MeterBinder beans are automatically bound to the Spring-managed MeterRegistry.

Metrics Endpoint

Spring Boot provides a metrics endpoint that you can use diagnostically to examine the metrics collected by an application. The endpoint is not available by default and must be exposed. See exposing endpoints for more details.

Navigating to /actuator/metrics displays a list of available meter names. You can drill down to view information about a particular meter by providing its name as a selector — for example, /actuator/metrics/jvm.memory.max.

tip: The name you use here should match the name used in the code, not the name after it has been naming-convention normalized for a monitoring system to which it is shipped. In other words, if jvm.memory.max appears as jvm_memory_max in Prometheus because of its snake case naming convention, you should still use jvm.memory.max as the selector when inspecting the meter in the metrics endpoint.

You can also add any number of tag=KEY:VALUE query parameters to the end of the URL to dimensionally drill down on a meter — for example, /actuator/metrics/jvm.memory.max?tag=area:nonheap.

The reported measurements are the sum of the statistics of all meters that match the meter name and any tags that have been applied. In the preceding example, the returned Value statistic is the sum of the maximum memory footprints of the “Code Cache”, “Compressed Class Space”, and “Metaspace” areas of the heap. If you wanted to see only the maximum size for the “Metaspace”, you could add an additional tag=id:Metaspace — that is, /actuator/metrics/jvm.memory.max?tag=area:nonheap&tag=id:Metaspace.

Tracing

Spring Boot Actuator provides dependency management and auto-configuration for Micrometer Tracing, a facade for popular tracer libraries.

Supported Tracers

Spring Boot ships auto-configuration for the following tracers:

Getting Started

We need an example application that we can use to get started with tracing. For our purposes, the simple “Hello World!” web application that’s covered in the Developing Your First Spring Boot Application section will suffice. We’re going to use the OpenTelemetry tracer with Zipkin as trace backend.

To recap, our main application code looks like this:

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
public class MyApplication {

    private static final Log logger = LogFactory.getLog(MyApplication.class);

    @RequestMapping("/")
    String home() {
        logger.info("home() has been called");
        return "Hello World!";
    }

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

}

Now we have to add the following dependencies:

  • org.springframework.boot:spring-boot-starter-actuator
  • io.micrometer:micrometer-tracing-bridge-otel - bridges the Micrometer Observation API to OpenTelemetry.
  • io.opentelemetry:opentelemetry-exporter-zipkin - reports traces to Zipkin.

Add the following application properties:

management:
  tracing:
    sampling:
      probability: 1.0

By default, Spring Boot samples only 10% of requests to prevent overwhelming the trace backend. This property switches it to 100% so that every request is sent to the trace backend.

To collect and visualize the traces, we need a running trace backend. We use Zipkin as our trace backend here. The Zipkin Quickstart guide provides instructions how to start Zipkin locally.

After Zipkin is running, you can start your application.

If you open a web browser to [localhost:8080](http://localhost:8080/), you should see the following output:

Hello World!

Behind the scenes, an observation has been created for the HTTP request, which in turn gets bridged to OpenTelemetry, which reports a new trace to Zipkin.

Now open the Zipkin UI at [localhost:9411](http://localhost:9411/) and press the "Run Query" button to list all collected traces. You should see one trace. Press the "Show" button to see the details of that trace.

Logging Correlation IDs

Correlation IDs provide a helpful way to link lines in your log files to spans/traces. If you are using Micrometer Tracing, Spring Boot will include correlation IDs in your logs by default.

The default correlation ID is built from traceId and spanIdMDC values. For example, if Micrometer Tracing has added an MDC traceId of 803B448A0489F84084905D3093480352 and an MDC spanId of 3425F23BB2432450 the log output will include the correlation ID [803B448A0489F84084905D3093480352-3425F23BB2432450].

If you prefer to use a different format for your correlation ID, you can use the logging.pattern.correlation property to define one. For example, the following will provide a correlation ID for Logback in format previously used by Spring Cloud Sleuth:

logging:
  pattern:
    correlation: "[${spring.application.name:},%X{traceId:-},%X{spanId:-}] "
  include-application-name: false

Note: In the example above, logging.include-application-name is set to false to avoid the application name being duplicated in the log messages (logging.pattern.correlation already contains it). It’s also worth mentioning that logging.pattern.correlation contains a trailing space so that it is separated from the logger name that comes right after it by default.

Propagating Traces

To automatically propagate traces over the network, use the auto-configured RestTemplateBuilder, RestClient.Builder or WebClient.Builder to construct the client.

Warning: If you create the RestTemplate, the RestClient or the WebClient without using the auto-configured builders, automatic trace propagation won’t work!

Tracer Implementations

As Micrometer Tracer supports multiple tracer implementations, there are multiple dependency combinations possible with Spring Boot.

All tracer implementations need the org.springframework.boot:spring-boot-starter-actuator dependency.

OpenTelemetry With Zipkin

Tracing with OpenTelemetry and reporting to Zipkin requires the following dependencies:

  • io.micrometer:micrometer-tracing-bridge-otel - bridges the Micrometer Observation API to OpenTelemetry.
  • io.opentelemetry:opentelemetry-exporter-zipkin - reports traces to Zipkin.

Use the management.zipkin.tracing.* configuration properties to configure reporting to Zipkin.

OpenTelemetry With OTLP

Tracing with OpenTelemetry and reporting using OTLP requires the following dependencies:

  • io.micrometer:micrometer-tracing-bridge-otel - bridges the Micrometer Observation API to OpenTelemetry.
  • io.opentelemetry:opentelemetry-exporter-otlp - reports traces to a collector that can accept OTLP.

Use the management.otlp.tracing.* configuration properties to configure reporting using OTLP.

梳理思路

当需要使用到metrics功能的时候,就会涉及到将采集到的各个metrics值,转成各种监控系统的格式,然后发送到各监控系统中,所以需要引入各种监控系统的依赖包,格式是micrometer-registry-{system}

一般来说,只要引入了该监控系统的依赖包,那么将此监控系统,自动配置到CompositeMeterRegistry中,那么,我们在创建自定义的metrics时,只需要注册到CompositeMeterRegistry后,自定义的metrics就会发送到此监控系统中了。

  • OpenTelemetry Protocol (OTLP). OpenTelemetry is a CNCF incubating project for providing standards for telemetry data. Micrometer can publish metrics using the OpenTelemetry protocol (OTLP) to the backends that support it.

当需要使用到tracing功能时,我们需要考虑2个概念:bridge 和 exporter。所以,要引入相关的依赖包。

Tracing with OpenTelemetry and reporting using OTLP requires the following dependencies:

  • io.micrometer:micrometer-tracing-bridge-otel - bridges the Micrometer Observation API to OpenTelemetry.
  • io.opentelemetry:opentelemetry-exporter-otlp - reports traces to a collector that can accept OTLP.

Metrics 示例

Creating and Using Metrics

Micrometer provides several types of meters you can use to measure different aspects of your application. Here are some common ones:

Counters

A counter is a simple incrementing and decrementing metric that represents a count.

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;

@RestController  
public class MyController {
  private final Counter myCounter;  

  public MyController(MeterRegistry registry) {  
    myCounter = Counter.builder("my.counter")  
            .description("Counts something")  
            .tags("region", "us-east")  
            .register(registry);  
  }  

  @GetMapping("/increment")  
  public void incrementCounter() {  
    myCounter.increment();  
  }  
}

Timers

Timers are used to measure the duration of events and the rate at which they occur.

import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.MeterRegistry;

@RestController
public class MyController {

private final Timer myTimer;  

public MyController(MeterRegistry registry) {  
    myTimer = Timer.builder("my.timer")  
            .description("Times something")  
            .tags("region", "us-east")  
            .register(registry);  
}  

@GetMapping("/time")  
public void timeSomething() {  
    myTimer.record(() -> {  
        // perform task to be timed  
    });  
}  

}

Gauges

Gauges are used to measure a value at a specific point in time, such as the size of a collection or the amount of free memory.

import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;

import java.util.concurrent.atomic.AtomicInteger;

@RestController
public class MyController {

private final AtomicInteger myGauge = new AtomicInteger();  

public MyController(MeterRegistry registry) {  
    Gauge.builder("my.gauge", myGauge, AtomicInteger::get)  
            .description("Gauges something")  
            .tags("region", "us-east")  
            .register(registry);  
}  

@GetMapping("/setGauge")  
public void setGauge(@RequestParam int value) {  
    myGauge.set(value);  
}  

}

Customizing Metrics

You can customize metrics by adding tags, descriptions, and more. This provides more context and makes them more meaningful when analyzing the data.

Counter.builder("custom.counter")  
 .description("A custom counter")  
 .tags("env", "production")  
 .register(meterRegistry);

Viewing and Analyzing Metrics

Once you have your metrics in place and your application is running, you can view and analyze them using the backend you’ve configured. For example, if you’re using Prometheus, you can visit the /actuator/prometheus endpoint to see your metrics in a format that Prometheus can scrape.

在 Spring Boot 3.3 中,MeterBinder 是 Micrometer 框架中用于将自定义监控指标与 MeterRegistry 绑定的核心接口。它通过标准化方式将业务逻辑中的度量数据集成到 Spring Boot Actuator 的监控体系中,是自定义指标的核心实现机制。


MeterBinder

MeterBinder 的核心作用

  1. 统一指标注册入口
    通过实现 MeterBinder 接口,开发者可以将自定义的指标(如数据库连接池状态、业务订单量等)统一注册到 MeterRegistry,并由 Spring Boot Actuator 的 /metrics 端点自动暴露。
  2. 解耦业务与监控代码
    将指标绑定逻辑封装在 MeterBinder 实现类中,避免在业务代码中直接操作 MeterRegistry,提升代码可维护性。
  3. 支持动态指标管理
    结合 Spring 的依赖注入机制,可实现动态绑定/解绑指标(例如根据运行时条件注册不同的指标)。

MeterBinder 的工作机制

  1. 接口定义
    MeterBinder 接口仅包含一个方法:
    java
    复制

    void bindTo(MeterRegistry registry);
    

    开发者需实现此方法,并在其中定义指标注册逻辑。

  2. Spring Boot 集成

    • Spring Boot 会自动扫描所有实现 MeterBinder 的 Bean,并在应用启动时调用 bindTo 方法。
    • 指标数据会通过 Actuator 的 /actuator/metrics/actuator/prometheus 端点暴露。

具体示例:监控数据库连接池

步骤 1:实现 MeterBinder 类

java

复制

@Component
public class DataSourceMetricsBinder implements MeterBinder {
    private final DataSource dataSource;

    @Autowired
    public DataSourceMetricsBinder(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Override
    public void bindTo(MeterRegistry registry) {
        // 监控活跃连接数
        Gauge.builder("db.pool.active.connections", dataSource, ds -> {
            try (Connection conn = ds.getConnection()) {
                return conn.unwrap(PoolDataSource.class).getActiveConnections();
            } catch (SQLException e) {
                return 0;
            }
        }).register(registry);

        // 监控连接池总大小
        Gauge.builder("db.pool.total.size", dataSource, ds -> {
            try (Connection conn = ds.getConnection()) {
                return conn.unwrap(PoolDataSource.class).getPoolSize();
            } catch (SQLException e) {
                return 0;
            }
        }).register(registry);
    }
}

步骤 2:通过 Actuator 查看指标

启动应用后,访问 /actuator/metrics/db.pool.active.connections,可获取如下 Prometheus 格式数据:

markdown

复制

db_pool_active_connections{application="order-service", env="prod"} 15

应用场景与最佳实践

1. 业务指标监控(如订单处理)

java

复制

public class OrderMetricsBinder implements MeterBinder {
    private final OrderService orderService;

    public OrderMetricsBinder(OrderService orderService) {
        this.orderService = orderService;
    }

    @Override
    public void bindTo(MeterRegistry registry) {
        // 统计每分钟订单创建量
        Meter.builder("orders.created", orderService, os -> os.getCreatedOrdersCount())
             .tag("type", "realtime")
             .register(registry);
    }
}

此指标可通过 Grafana 仪表盘实时展示订单趋势。

2. 系统资源监控(如线程池)

java

复制

public class ThreadPoolBinder implements MeterBinder {
    private final ThreadPoolExecutor executor;

    public ThreadPoolBinder(ThreadPoolExecutor executor) {
        this.executor = executor;
    }

    @Override
    public void bindTo(MeterRegistry registry) {
        Gauge.builder("thread.pool.active", executor, ThreadPoolExecutor::getActiveCount)
             .description("当前活跃线程数")
             .register(registry);
    }
}

3. 最佳实践

  • 标签规范化:使用一致的标签命名(如 service="payment"),避免因标签维度爆炸导致监控系统压力。
  • 指标生命周期管理:通过 MeterRegistry.remove() 动态清理无用指标,防止内存泄漏。
  • 全局配置:在 MeterBinder 中调用 registry.config().commonTags("region", "us-east") 添加统一标签。

与 Spring Boot 3.3 的深度集成

  • 自动绑定优化
    Spring Boot 3.3 增强了对 MeterBinder 实现类的自动发现机制,即使指标类未标注 @Component,也能通过 META-INF/spring.factories 配置加载。
  • 性能提升
    新版本中 MeterBinder 的指标注册过程采用异步化处理,减少对应用启动速度的影响。

总结

MeterBinder 是 Spring Boot 监控体系中的核心扩展点,通过标准化接口将业务指标无缝集成到 Micrometer 生态中。结合 Spring Boot 3.3 的自动化能力(如依赖注入、端点暴露),开发者可以高效构建多维度的可观测性系统。

实际演练

基础配置

pom.xml

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>


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

application.yaml

spring:
  application:
    name: trace-metric-demo

management:
  endpoints:
    enabled-by-default: false
    web:
      exposure:
        include:
          - info
          - health
          - metrics
  endpoint:
    info:
      enabled: true
    health:
      enabled: true
    metrics:
      enabled: true

上面的例子中,启用并暴露了3个endpoint,访问地址分别如下:

http://localhost:8080/actuator/health

http://localhost:8080/actuator/info

http://localhost:8080/actuator/metrics

其中,在访问health的endpoint时,响应如下:

{"status":"UP"}

在访问metrics的endpoint时,响应如下:

{
    "names": [
        "application.ready.time",
        "application.started.time",
        "disk.free",
        "disk.total",
        "executor.active",
        "executor.completed",
        "executor.pool.core",
        "executor.pool.max",
        "executor.pool.size",
        "executor.queue.remaining",
        "executor.queued",
        "http.server.requests.active",
        "jvm.buffer.count",
        "jvm.buffer.memory.used",
        "jvm.buffer.total.capacity",
        "jvm.classes.loaded",
        "jvm.classes.unloaded",
        "jvm.compilation.time",
        "jvm.gc.live.data.size",
        "jvm.gc.max.data.size",
        "jvm.gc.memory.allocated",
        "jvm.gc.memory.promoted",
        "jvm.gc.overhead",
        "jvm.info",
        "jvm.memory.committed",
        "jvm.memory.max",
        "jvm.memory.usage.after.gc",
        "jvm.memory.used",
        "jvm.threads.daemon",
        "jvm.threads.live",
        "jvm.threads.peak",
        "jvm.threads.started",
        "jvm.threads.states",
        "logback.events",
        "process.cpu.time",
        "process.cpu.usage",
        "process.start.time",
        "process.uptime",
        "system.cpu.count",
        "system.cpu.usage",
        "tomcat.sessions.active.current",
        "tomcat.sessions.active.max",
        "tomcat.sessions.alive.max",
        "tomcat.sessions.created",
        "tomcat.sessions.expired",
        "tomcat.sessions.rejected"
    ]
}

接下来,获取某个具体指标值时,访问路径如下:

http://localhost:8080/actuator/metrics/jvm.memory.max

响应如下:

{
    "name": "jvm.memory.max",
    "description": "The maximum amount of memory in bytes that can be used for memory management",
    "baseUnit": "bytes",
    "measurements": [
        {
            "statistic": "VALUE",
            "value": 5337251837.0
        }
    ],
    "availableTags": [
        {
            "tag": "area",
            "values": [
                "heap",
                "nonheap"
            ]
        },
        {
            "tag": "id",
            "values": [
                "G1 Survivor Space",
                "Compressed Class Space",
                "CodeCache",
                "G1 Old Gen",
                "Metaspace",
                "G1 Eden Space"
            ]
        }
    ]
}

支持prometheus

增加以下依赖:

 <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-registry-prometheus</artifactId>
        </dependency>

在yaml中,增加对prometheus endpoint的enabled & exported,配置如下:

management:
  endpoints:
    enabled-by-default: false
    web:
      exposure:
        include:
          - info
          - health
          - metrics
          - prometheus
  endpoint:
    info:
      enabled: true
    health:
      enabled: true
    metrics:
      enabled: true
    prometheus:
      enabled: true

支持otel

pom.xml中,增加以下依赖:

   <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-registry-otlp</artifactId>
        </dependency>

yaml中增加以下配置:

management:
  otlp:
    metrics:
      export:
        url: http://localhost:4318/v1/metrics # URI of the OLTP server.

因为,otel不像prometheus一样,有默认的endpoint可以直接访问,所以需要先在本地安装open telemetry collector。

从gitHub上下载otelcol-contrib_0.124.1_windows_amd64,新建一个config.yaml,内容如下:

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318
exporters:
  debug:
    verbosity: detailed
  file:
    path: ./metrics-otlp.json # 为了方便查看,这里我将指标信息直接 export 到文件中

service:
  pipelines:
    metrics:
      receivers: [otlp] # 使用 otlp
      exporters: [file] # 使用 file

接下来,启动open telemetry collector,命令如下:

 .\otelcol-contrib.exe --config=config.yaml

接下来,我们再启动我们的springboot项目,就能发现,metrics信息,被发送到了open telemetry collector中,我们可以在上面配置的path: ./metric文件中,看到metrics信息。

支持Tracing

pom.xml,增加以下依赖:

  <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-tracing-bridge-otel</artifactId>
        </dependency>

配置文件,增加以下配置项:

management:
  tracing:
    sampling:
      probability: 1.0

上面的配置完成后,那么就可以在日志中,打印出traceid 和 spanid了

logback的配置如下:

   <variable name="log.pattern" value="%d{HH:mm:ss.SSS} [%X{traceId:-},%X{spanId:-}] [%thread] %-5level %logger{40} - [%method,%line] - %msg%n" />

打印的日志如下:

14:00:49.084 [4b8e75a49841815b82f432325bdb5294,ef1784736da5501b] [http-nio-8080-exec-1] INFO  c.w.t.controller.HahaController - [hello,16] - 
inputed name is lisi

如果说,想要将trace的相关信息,发送到otlp中,那么还需要增加以下依赖:

io.opentelemetry:opentelemetry-exporter-otlp - reports traces to a collector that can accept OTLP.

文章作者:Administrator

文章链接:http://localhost:8090//archives/actuator-note

版权声明:本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0 许可协议,转载请注明出处!


评论