57、指标

Spring Boot Actuator 为 Micrometer 提供了依赖管理和自动配置,Micrometer 是一个支持众多监控系统的应用程序指标门面,包括:

提示

要了解有关 Micrometer 功能的更多信息,请参阅其参考文档,特别是概念部分

57.1、入门

Spring Boot 自动配置了一个组合的 MeterRegistry,并为 classpath 中每个受支持的实现向该组合注册一个注册表。在运行时,只需要 classpath 中有 micrometer-registry-{system} 依赖即可让 Spring Boot 配置该注册表。

大部分注册表都有共同点 例如,即使 Micrometer 注册实现位于 classpath 上,你也可以禁用特定的注册表。例如,要禁用 Datadog:

  1. management.metrics.export.datadog.enabled=false

Spring Boot 还会将所有自动配置的注册表添加到 Metrics 类的全局静态复合注册表中,除非你明确禁止:

  1. management.metrics.use-global-registry=false

在注册表中注册任何指标之前,你可以注册任意数量的 MeterRegistryCustomizer bean 以进一步配置注册表,例如通用标签:

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

你可以通过指定泛型类型,自定义注册表实现:

  1. @Bean
  2. MeterRegistryCustomizer<GraphiteMeterRegistry> graphiteMetricsNamingConvention() {
  3. return registry -> registry.config().namingConvention(MY_CUSTOM_CONVENTION);
  4. }

使用该设置,你可以在组件中注入 MeterRegistry 并注册指标:

  1. @Component
  2. public class SampleBean {
  3. private final Counter counter;
  4. public SampleBean(MeterRegistry registry) {
  5. this.counter = registry.counter("received.messages");
  6. }
  7. public void handleMessage(String message) {
  8. this.counter.increment();
  9. // 处理消息实现
  10. }
  11. }

Spring Boot 还配置内置的测量工具(即 MeterBinder 实现),你可以通过配置或专用注解标记来控制。

57.2、支持的监控系统

57.2.1、AppOptics

默认情况下,AppOptics 注册表会定期将指标推送到 api.appoptics.com/v1/measurements。要将指标导出到 SaaS AppOptics,你必须提供 API 令牌:

  1. management.metrics.export.appoptics.api-token=YOUR_TOKEN

57.2.2、Atlas

默认情况下,度量标准将导出到本地的 Atlas。可以使用以下方式指定 Atlas 服务器的位置:

  1. management.metrics.export.atlas.uri=https://atlas.example.com:7101/api/v1/publish

57.2.3、Datadog

Datadog 注册表会定期将指标推送到 datadoghq。要将指标导出到 Datadog,你必须提供 API 密钥:

  1. management.metrics.export.datadog.api-key=YOUR_KEY

你还可以更改度量标准发送到 Datadog 的间隔时间:

  1. management.metrics.export.datadog.step=30s

57.2.4、Dynatrace

Dynatrace 注册表定期将指标推送到配置的 URI。要将指标导出到 Dynatrace,必须提供 API 令牌、设备 ID 和 URI:

  1. management.metrics.export.dynatrace.api-token=YOUR_TOKEN
  2. management.metrics.export.dynatrace.device-id=YOUR_DEVICE_ID
  3. management.metrics.export.dynatrace.uri=YOUR_URI

你还可以更改度量标准发送到 Dynatrace 的间隔时间:

  1. management.metrics.export.dynatrace.step=30s

57.2.5、Elastic

默认情况下,度量将导出到本地的 Elastic。可以使用以下属性提供 Elastic 服务器的位置:

  1. management.metrics.export.elastic.host=https://elastic.example.com:8086

57.2.6、Ganglia

默认情况下,度量将导出到本地的 Ganglia。可以使用以下方式提供 Ganglia 服务器主机和端口:

  1. management.metrics.export.ganglia.host=ganglia.example.com
  2. management.metrics.export.ganglia.port=9649

57.2.7、Graphite

默认情况下,度量将导出到本地的 Graphite。可以使用以下方式提供 Graphite 服务器主机和端口:

  1. management.metrics.export.graphite.host=graphite.example.com
  2. management.metrics.export.graphite.port=9004

Micrometer 提供了一个默认的 HierarchicalNameMapper,它管理维度计数器 id 如何映射到平面分层名称

提示

要控制此行为,请定义 GraphiteMeterRegistry 并提供自己的 HierarchicalNameMapper。除非你自己定义,否则使用自动配置的 GraphiteConfigClock bean:

  1. @Bean
  2. public GraphiteMeterRegistry graphiteMeterRegistry(GraphiteConfig config, Clock clock) {
  3. return new GraphiteMeterRegistry(config, clock, MY_HIERARCHICAL_MAPPER);
  4. }

57.2.8、Humio

默认情况下,Humio 注册表会定期将指标推送到 cloud.humio.com。要将指标导出到 SaaS Humio,你必须提供 API 令牌:

  1. management.metrics.export.humio.api-token=YOUR_TOKEN

你还应配置一个或多个标记,以标识要推送指标的数据源:

  1. management.metrics.export.humio.tags.alpha=a
  2. management.metrics.export.humio.tags.bravo=b

57.2.9、Influx

默认情况下,度量将导出到本地的 Influx。要指定 Influx 服务器的位置,可以使用:

  1. management.metrics.export.influx.uri=https://influx.example.com:8086

57.2.10、JMX

Micrometer 提供了与 JMX 的分层映射,主要为了方便在本地查看指标且可移植。默认情况下,度量将导出到 metrics JMX 域。可以使用以下方式提供要使用的域:

  1. management.metrics.export.jmx.domain=com.example.app.metrics

Micrometer 提供了一个默认的 HierarchicalNameMapper,它管理维度计数器 id 如何映射到平面分层名称

提示

要控制此行为,请定义 JmxMeterRegistry 并提供自己的 HierarchicalNameMapper。除非你自己定义,否则使用自动配置的 JmxConfigClock bean:

  1. @Bean
  2. public JmxMeterRegistry jmxMeterRegistry(JmxConfig config, Clock clock) {
  3. return new JmxMeterRegistry(config, clock, MY_HIERARCHICAL_MAPPER);
  4. }

57.2.11、KairosDB

默认情况下,度量将导出到本地的 KairosDB。可以使用以下方式提供 KairosDB 服务器的位置:

  1. management.metrics.export.kairos.uri=https://kairosdb.example.com:8080/api/v1/datapoints

57.2.12、New Relic

New Relic 注册表定期将指标推送到 New Relic。要将指标导出到 New Relic,你必须提供 API 密钥和帐户 ID:

  1. management.metrics.export.newrelic.api-key=YOUR_KEY
  2. management.metrics.export.newrelic.account-id=YOUR_ACCOUNT_ID

你还可以更改将度量发送到 New Relic 的间隔时间:

  1. management.metrics.export.newrelic.step=30s

57.2.13、Prometheus

Prometheus 希望抓取或轮询各个应用实例以获取指标数据。Spring Boot 在 /actuator/prometheus 上提供 actuator 端点,以适当的格式呈现 Prometheus scrape

提示

默认情况下端点不可用,必须暴露,请参阅暴露端点以获取更多详细信息。

以下是要添加到 prometheus.yml 的示例 scrape_config

  1. scrape_configs:
  2. - job_name: 'spring'
  3. metrics_path: '/actuator/prometheus'
  4. static_configs:
  5. - targets: ['HOST:PORT']

57.2.14、SignalFx

SignalFx 注册表定期将指标推送到 SignalFx。要将指标导出到 SignalFx,你必须提供访问令牌:

  1. management.metrics.export.signalfx.access-token=YOUR_ACCESS_TOKEN

你还可以更改将指标发送到 SignalFx 的间隔时间:

  1. management.metrics.export.signalfx.step=30s

57.2.15、Simple

Micrometer 附带一个简单的内存后端,如果没有配置其他注册表,它将自动用作后备。这使你可以查看指标端点中收集的指标信息。

只要你使用了任何其他可用的后端,内存后端就会自动禁用。你也可以显式禁用它:

  1. management.metrics.export.simple.enabled=false

57.2.16、StatsD

StatsD 注册表将 UDP 上的指标推送到 StatsD 代理。 默认情况下,度量将导出到本地的 StatsD 代理,可以使用以下方式提供 StatsD 代理主机和端口:

  1. management.metrics.export.statsd.host=statsd.example.com
  2. management.metrics.export.statsd.port=9125

你还可以更改要使用的 StatsD 线路协议(默认为 Datadog):

  1. management.metrics.export.statsd.flavor=etsy

57.2.17、Wavefront

Wavefront 注册表定期将指标推送到 Wavefront。如果要将指标直接导出到 Wavefront,则你必须提供 API 令牌:

  1. management.metrics.export.wavefront.api-token=YOUR_API_TOKEN

或者,你可以在环境中使用 Wavefront sidecar 或内部代理设置,将指标数据转发到 Wavefront API 主机:

  1. management.metrics.export.wavefront.uri=proxy://localhost:2878

提示

如果将度量发布到 Wavefront 代理(如文档中所述),则主机必须采用 proxy://HOST:PORT 格式。

你还可以更改将指标发送到 Wavefront 的间隔时间:

  1. management.metrics.export.wavefront.step=30s

57.3、支持的指标

Spring Boot 在适当的环境注册以下核心指标:

  • JVM 指标,报告利用率:
    • 各种内存和缓冲池
    • 与垃圾回收有关的统计
    • 线程利用率
    • 加载/卸载 class 的数量
  • CPU 指标
  • 文件描述符指标
  • Kafka 消费者指标
  • Log4j2 指标:记录每个级别记录到 Log4j2 的事件数
  • Logback 指标:记录每个级别记录到 Logback 的事件数
  • 正常运行时间指标:报告正常运行时间和表示应用程序绝对启动时间的固定计量值
  • Tomcat 指标
  • Spring Integration 指标

57.3.1、Spring MVC 指标

自动配置启用 Spring MVC 处理的请求的指标记录。当 management.metrics.web.server.auto-time-requeststrue 时,将对所有请求进行此检测。或者,当设置为 false 时,你可以通过将 @Timed 添加到请求处理方法来启用检测:

  1. @RestController
  2. @Timed // <1>
  3. public class MyController {
  4. @GetMapping("/api/people")
  5. @Timed(extraTags = { "region", "us-east-1" }) // <2>
  6. @Timed(value = "all.people", longTask = true) // <3>
  7. public List<Person> listPeople() { ... }
  8. }
  1. 一个控制器类,为控制器中的每个请求处理程序启用计时。
  2. 启用单个端点。如果你在类上使用了它,就不需要在方法上再次声明,但可以用它来进一步自定义该特定端点的计时器。
  3. 使用 longTask = true 的方法为该方法启用长任务计时器。长任务计时器需要单独的指标名称,并且可以使用短任务计时器进行堆叠。

默认情况下,使用名称为 http.server.requests 生成度量指标。可以通过设置 management.metrics.web.server.requests-metric-name 属性来自定义名称。

默认情况下,Spring MVC 相关指标使用了以下标签标记:

标签 描述
exception 处理请求时抛出的异常的简单类名。
method 请求的方法(例如,GETPOST
outcome 根据响应状态码生成结果。1xx 是 INFORMATIONAL,2xx 是 SUCCESS,3xx 是 REDIRECTION,4xx 是 CLIENT_ERROR,5xx 是 SERVER_ERROR
status 响应的 HTTP 状态码(例如,200500
uri 如果可能,在变量替换之前请求 URI 模板(例如,/api/person/{id}

要自定义标签,请提供一个实现了 WebMvcTagsProvider@Bean

57.3.2、Spring WebFlux 指标

自动配置启用了 WebFlux 控制器和函数式处理程序处理的所有请求的指标记录功能。

默认情况下,使用名为 http.server.requests 生成度量指标。你可以通过设置 management.metrics.web.server.requests-metric-name 属性来自定义名称。

默认情况下,与 WebFlux 相关的指标使用以下标签标记:

标签 描述
exception 处理请求时抛出的异常的简单类名。
method 请求方法(例如,GETPOST
outcome 根据响应状态码生成请求结果。1xx 是 INFORMATIONAL,2xx 是 SUCCESS,3xx 是 REDIRECTION,4xx 是 CLIENT_ERROR,5xx 是 SERVER_ERROR
status 响应的 HTTP 状态码(例如,200500
uri 如果可能,在变量替换之前请求 URI 模板(例如,/api/person/{id}

要自定义标签,请提供一个实现了 WebFluxTagsProvider@Bean

57.3.3、Jersey Server 指标

自动配置启用了由 Jersey JAX-RS 实现处理的请求的指标记录功能。当 management.metrics.web.server.auto-time-requeststrue 时,将对所有请求进行该项检测。当设置为 false 时,你可以通过将 @Timed 添加到请求处理方法上来启用检测:

  1. @Component
  2. @Path("/api/people")
  3. @Timed // <1>
  4. public class Endpoint {
  5. @GET
  6. @Timed(extraTags = { "region", "us-east-1" }) // <2>
  7. @Timed(value = "all.people", longTask = true) // <3>
  8. public List<Person> listPeople() { ... }
  9. }
  1. 在资源类上,为资源中的每个请求处理程序启用计时。
  2. 在方法上则启用单个端点。如果你在类上使用了它,则不需在方法上再次声明,但可以用它来进一步自定义该特定端点的计时器。
  3. 在有 longTask = true 的方法上,为该方法启用长任务计时器。长任务计时器需要单独的度量名称,并且可以使用短任务计时器进行堆叠。

默认情况下,使用名为 http.server.requests 生成度量指标。可以通过设置 management.metrics.web.server.requests-metric-name 属性来自定义名称。

默认情况下,Jersey 服务器指标使用以下标签标记:

标签 描述
exception 处理请求时抛出的异常的简单类名。
method 请求的方法(例如,GETPOST
outcome 根据响应状态码生成的请求结果。1xx 是 INFORMATIONAL,2xx 是 SUCCESS,3xx 是 REDIRECTION,4xx 是 CLIENT_ERROR,5xx 是 SERVER_ERROR
status 响应的 HTTP 状态码(例如,200500
uri 如果可能,在变量替换之前请求 URI 模板(例如,/api/person/{id}

要自定义标签,请提供一个实现了 JerseyTagsProvider@Bean

57.3.4、HTTP Client 指标

Spring Boot Actuator 管理 RestTemplate 和 WebClient 的指标记录。为此,你必须注入一个自动配置的 builder 并使用它来创建实例:

  • RestTemplateBuilder 用于 RestTemplate
  • WebClient.Builder 用于 WebClient

也可以手动指定负责此指标记录的自定义程序,即 MetricsRestTemplateCustomizerMetricsWebClientCustomizer

默认情况下,使用名为 http.client.requests 生成度量指标。可以通过设置 management.metrics.web.client.requests-metric-name 属性来自定义名称。

默认情况下,已指标记录客户端生成的度量指标使用以下标签标记:

  • method,请求的方法(例如,GETPOST)。
  • uri,变量替换之前的请求 URI 模板(如果可能)(例如,/api/person/{id})。
  • status,响应的 HTTP 状态码(例如,200500)。
  • clientName,URI 的主机部分 。

要根据你选择的客户端自定义标签,你可以提供一个实现了 RestTemplateExchangeTagsProviderWebClientExchangeTagsProvider@BeanRestTemplateExchangeTagsWebClientExchangeTags 中有便捷的静态函数。

57.3.5、Cache 指标

在启动时,自动配置启动所有可用 Cache 的指标记录功能,指标以 cache 为前缀。缓存指标记录针对一组基本指标进行了标准化。此外,还提供了缓存特定的指标。

支持以下缓存库:

  • Caffeine
  • EhCache 2
  • Hazelcast
  • 所有兼容 JCache(JSR-107)的实现

度量指标由缓存的名称和从 bean 名称派生的 CacheManager 的名称标记。

注意

只有启动时可用的缓存才会绑定到注册表。对于在启动阶段之后即时或以编程方式创建的缓存,需要显式注册。可用 CacheMetricsRegistrar bean 简化该过程。

57.3.6、数据源指标

自动配置启用对所有可用 DataSource 对象进行指标记录功能,指标的名称为 jdbc。数据源指标记录会生成表示池中当前活动、大允许和最小允许连接的计量器(gauge)。这些计量器都有一个以 jdbc 为前缀的名称。

度量指标也由基于 bean 名称计算的 DataSource 的名称标记。

提示

默认情况下,Spring Boot 为所有支持的数据源提供了元数据。如果开箱即用不支持你喜欢的数据源,则可以添加其他 DataSourcePoolMetadataProvider bean。有关示例,请参阅 DataSourcePoolMetadataProvidersConfiguration

此外,Hikari 特定的指标用 hikaricp 前缀暴露。每个度量指标都由池名称标记(可以使用 spring.datasource.name 控制)。

57.3.7、Hibernate 指标

自动配置启用所有可用 Hibernate EntityManagerFactory 实例的指标记录功能,这些实例使用名为 hibernate 的度量指标统计信息。

度量指标也由从 bean 名称派生的 EntityManagerFactory 的名称标记。

要启用信息统计,必须将标准 JPA 属性 hibernate.generate_statistics 设置为 true。你可以在自动配置的 EntityManagerFactory 上启用它,如下所示:

  1. spring.jpa.properties.hibernate.generate_statistics=true

57.3.8、RabbitMQ 指标

自动配置将使用名为 rabbitmq 的度量指标启用对所有可用 RabbitMQ 连接工厂进行指标记录。

57.4、注册自定义指标

要注册自定义指标,请将 MeterRegistry 注入你的组件中,如下所示:

  1. class Dictionary {
  2. private final List<String> words = new CopyOnWriteArrayList<>();
  3. Dictionary(MeterRegistry registry) {
  4. registry.gaugeCollectionSize("dictionary.size", Tags.empty(), this.words);
  5. }
  6. // …
  7. }

如果你发现跨组件或应用程序重复记录一套度量指标,则可以将此套件封装在 MeterBinder 实现中。默认情况下,所有 MeterBinder bean 的指标都将自动绑定到 Spring 管理的 MeterRegistry

57.5、自定义单独指标

如果需要将自定义特定的 Meter 实例,可以使用 io.micrometer.core.instrument.config.MeterFilter 接口。默认情况下,所有 MeterFilter bean 都将自动应用于 MeterRegistry.Config

例如,如果要将 mytag.region 标记重命名为 mytag.area 以获取以 com.example 开头的所有 meter ID,则可以执行以下操作:

  1. @Bean
  2. public MeterFilter renameRegionTagMeterFilter() {
  3. return MeterFilter.renameTag("com.example", "mytag.region", "mytag.area");
  4. }

57.5.1、自定义标签

通用标签通常用于操作环境中的维度下钻,例如主机、实例、区域、堆栈等。通用标签应用于所有 meter,并且可以按照以下示例进行配置:

  1. management.metrics.tags.region=us-east-1
  2. management.metrics.tags.stack=prod

上面的示例将 regionstack 标签添加到所有 meter 中,其值分别为 us-east-1prod

注意

如果你使用 Graphite,那么标签的顺序很重要。由于使用此方法无法保证通用标签的顺序,因此建议 Graphite 用户定义自定义 MeterFilter

57.5.2、Per-meter 属性

除了 MeterFilter bean 之外,还可以使用 properties 在 per-meter 基础上自定义。Per-meter 定义适用于以给定名称开头的所有 meter ID。例如,以下将禁用任何以 example.remote 开头的 ID 的 meter:

  1. management.metrics.enable.example.remote=false

以下属性允许 per-meter 自定义:

表 57.1、Per-meter 自定义

| 属性 | 描述 || management.metrics.enable | 是否拒绝 meter 发布任何指标。 || management.metrics.distribution.percentiles-histogram | 是否发布一个适用于计算可聚合(跨维度)的百分比近似柱状图。 || management.metrics.distribution.minimum-expected-valuemanagement.metrics.distribution.maximum-expected-value| 通过限制预期值的范围来发布较少的柱状图桶。 || management.metrics.distribution.percentiles | 发布在你自己的应用程序中计算的百分比数值 || management.metrics.distribution.sla | 发一个使用 SLA 定义的存储桶发布累积柱状图。 |

有关 percentiles-histogrampercentilessla 概念的更多详细信息,请参阅「柱状图与百分位数」部分的文档。

57.6、指标端点

Spring Boot 提供了一个 metrics 端点,可以在诊断中用于检查应用程序收集的度量指标。默认情况下端点不可用,必须手动暴露,请参阅暴露端点以获取更多详细信息。

访问 /actuator/metrics 会显示可用的 meter 名称列表。你可以查看某一个 meter 的信息,方法是将其名称作为选择器,例如,/actuator/metrics/jvm.memory.max

提示

你在此处使用的名称应与代码中使用的名称相匹配,而不是在命名约定规范化后的名称 —— 为了发送到监控系统。换句话说,如果 jvm.memory.max 由于 Prometheus 命名约定而显示为 jvm_memory_max,则在审查度量指标端点中的 meter 时,应仍使用 jvm.memory.max 作为选择器。

你还可以在 URL 的末尾添加任意数量的 tag=KEY:VALUE 查询参数,以便多维度向下钻取 meter,例如 /actuator/metrics/jvm.memory.max?tag=area:nonheap

提示

报告的测量值是与 meter 名称和已应用的任何标签匹配的所有 meter 的统计数据的总和。因此,在上面的示例中,返回的 Value 统计信息是堆的 Code Cache,Compressed Class Space 和 Metaspace 区域的最大内存占用量的总和。如果你只想查看 Metaspace 的最大大小,可以添加一个额外的 tag=id:Metaspace,即 /actuator/metrics/jvm.memory.max?tag=area:nonheap&tag=id:Metaspace