52. Metrics
Spring Boot Actuator 包含具有“量规”和“计数器”支持的 Metrics 服务。 “量规”记录单个值; “计数器”记录增量(增量或减量)。 Spring Boot Actuator 还提供了一个PublicMetrics接口,您可以实施该接口以公开无法通过这两种机制之一记录的 Metrics。以SystemPublicMetrics为例。
所有 HTTP 请求的 Metrics 都会自动记录,因此,如果您点击metrics
端点,您应该会看到类似以下的响应:
{
"counter.status.200.root": 20,
"counter.status.200.metrics": 3,
"counter.status.200.star-star": 5,
"counter.status.401.root": 4,
"gauge.response.star-star": 6,
"gauge.response.root": 2,
"gauge.response.metrics": 3,
"classes": 5808,
"classes.loaded": 5808,
"classes.unloaded": 0,
"heap": 3728384,
"heap.committed": 986624,
"heap.init": 262144,
"heap.used": 52765,
"nonheap": 0,
"nonheap.committed": 77568,
"nonheap.init": 2496,
"nonheap.used": 75826,
"mem": 986624,
"mem.free": 933858,
"processors": 8,
"threads": 15,
"threads.daemon": 11,
"threads.peak": 15,
"threads.totalStarted": 42,
"uptime": 494836,
"instance.uptime": 489782,
"datasource.primary.active": 5,
"datasource.primary.usage": 0.25
}
在这里,我们可以看到基本的memory
,heap
,class loading
,processor
和thread pool
信息以及一些 HTTPMetrics。在这种情况下,root
('/')和/metrics
URL 已分别返回HTTP 200
响应20
和3
次。似乎root
URL 返回HTTP 401
(未授权)4
次。双星号(star-star
)来自 Spring MVC 匹配为/**
(通常是静态资源)的请求。
gauge
显示请求的最后响应时间。因此,对root
的最后一个请求花了2ms
进行响应,而对/metrics
的最后一个请求花了3ms
。
Note
在此示例中,我们实际上是使用/metrics
URL 通过 HTTP 访问端点,这解释了为什么metrics
出现在响应中。
52.1 系统 Metrics
Spring Boot 公开了以下系统 Metrics:
-
系统总内存,以 KB 为单位(
mem
) -
可用内存量,以 KB 为单位(
mem.free
) -
处理器数量(
processors
) -
系统正常运行时间,以毫秒为单位(
uptime
) -
应用程序上下文的正常运行时间,以毫秒为单位(
instance.uptime
) -
平均系统负载(
systemload.average
) -
堆信息,以 KB(
heap
,heap.committed
,heap.init
,heap.used
)为单位 -
线程信息(
threads
,thread.peak
,thread.daemon
) -
类加载信息(
classes
,classes.loaded
,classes.unloaded
) -
垃圾收集信息(
gc.xxx.count
,gc.xxx.time
)
52.2 数据源 Metrics
针对应用程序中定义的每个受支持的DataSource
公开以下 Metrics:
-
Active 连接数(
datasource.xxx.active
) -
连接池的当前使用情况(
datasource.xxx.usage
)。
所有数据源 Metrics 共享datasource.
前缀。对于每个数据源,该前缀进一步符合条件:
-
如果数据源是主要数据源(即唯一的可用数据源或现有数据源中标记为
@Primary
的数据源),则前缀为datasource.primary
。 -
如果数据源 Bean 名称以
DataSource
结尾,则前缀是不包含DataSource
的 Bean 名称(即datasource.batch
表示batchDataSource
)。 -
在所有其他情况下,都使用 Bean 的名称。
通过使用自定义版本DataSourcePublicMetrics
注册 bean,可以覆盖部分或全部默认值。默认情况下,Spring Boot 为所有支持的数据源提供元数据。如果不支持立即使用您喜欢的数据源,则可以添加其他DataSourcePoolMetadataProvider
bean。有关示例,请参见DataSourcePoolMetadataProvidersConfiguration
。
52.3 缓存 Metrics
针对应用程序中定义的每个受支持的缓存公开以下 Metrics:
-
当前缓存的大小(
cache.xxx.size
) -
命中率(
cache.xxx.hit.ratio
) -
错过率(
cache.xxx.miss.ratio
)
Note
缓存提供程序不会以一致的方式公开命中率/未命中率。尽管有些暴露了“汇总”值(即自上次清除统计信息以来的命中率),而另一些暴露了“时间”值(即最后一秒的命中率)。检查您的缓存提供程序文档以获取更多详细信息。
如果两个不同的高速缓存 Management 器碰巧定义了相同的高速缓存,则高速缓存的名称将以CacheManager
bean 的名称为前缀。
通过使用自定义版本CachePublicMetrics
注册 bean,可以覆盖部分或全部默认值。默认情况下,Spring Boot 为 EhCache,Hazelcast,Infinispan,JCache 和 Guava 提供缓存统计信息。如果不支持立即使用您喜欢的缓存库,则可以添加其他CacheStatisticsProvider
bean。有关示例,请参见CacheStatisticsAutoConfiguration
。
52.4 Tomcat 会话 Metrics
如果您将 Tomcat 用作嵌入式 Servlet 容器,则会话 Metrics 将自动公开。 httpsessions.active
和httpsessions.max
键提供 Active 会话数和最大会话数。
52.5 记录自己的 Metrics
要记录自己的 Metrics,请向您的 bean 中注入CounterService和/或GaugeService。 CounterService
公开increment
,decrement
和reset
方法; GaugeService
提供了submit
方法。
这是一个简单的示例,该示例计算方法被调用的次数:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.metrics.CounterService;
import org.springframework.stereotype.Service;
@Service
public class MyService {
private final CounterService counterService;
@Autowired
public MyService(CounterService counterService) {
this.counterService = counterService;
}
public void exampleMethod() {
this.counterService.increment("services.system.myservice.invoked");
}
}
Tip
您可以将任何字符串用作度量标准名称,但应遵循所选 Store/制图技术的准则。 Matt Aimonetti 的博客提供了一些适用于 Graphite 的良好准则。
52.6 添加自己的公开 Metrics
要添加每次调用度量端点时计算的其他度量,只需注册其他PublicMetrics
实现 bean。默认情况下,所有此类 bean 均由端点收集。您可以通过定义自己的MetricsEndpoint
轻松更改它。
52.7 Java 8 的特殊功能
Spring Boot 提供的GaugeService
和CounterService
的默认实现取决于您所使用的 Java 版本。使用 Java 8(或更高版本)时,该实现将切换到针对快速写入进行优化的高性能版本,并由原子内存缓冲区支持,而不是由不变但相对昂贵的Metric<?>
类型支持(计数器的速度快大约 5 倍,而测量的速度大约是两倍)与基于存储库的实现一样快)。即使对于 Java 7(它们具有某些 Java 8 并发库的反向移植),Dropwizard 度量标准服务(请参阅下文)也非常有效,但是它们不记录度量标准值的时间戳。如果需要考虑度量收集的性能,则始终建议使用高性能选项之一,并且不经常读取度量,以便在本地缓冲写入操作,仅在需要时才读取。
Note
如果您使用的是 Java 8 或使用 DropwizardMetrics,则默认情况下不会使用旧的MetricRepository
及其InMemoryMetricRepository
实现。
52.8Metrics 编写器,导出器和聚合
Spring Boot 提供了一种称为Exporter
的标记接口的实现,可用于将 Metrics 读数从内存中的缓冲区复制到可以分析和显示它们的位置。确实,如果您提供实现MetricWriter
接口(对于简单用例为GaugeWriter
)并将其标记为@ExportMetricWriter
的@Bean
,则它将自动连接至Exporter
,并每 5 秒提供一次 Metrics 更新(通过spring.metrics.export.delay-millis
配置)。此外,您定义并标记为@ExportMetricReader
的任何MetricReader
的值都将由默认导出器导出。
Note
此功能使您可以在应用程序(@EnableScheduling
)中启用计划,如果您运行集成测试,这将是一个问题,因为您自己的计划任务将开始。您可以通过将spring.metrics.export.enabled
设置为false
来禁用此行为。
默认的导出器是MetricCopyExporter
,它试图通过不复制自上次调用以来从未更改过的值来优化自身(可以使用标志spring.metrics.export.send-latest
来关闭优化)。另请注意,Dropwizard MetricRegistry
不支持时间戳,因此,如果您使用 Dropwizard 度量标准,则优化不可用(所有度量标准都会在每个刻度上复制)。
导出触发器的默认值(delay-millis
,includes
,excludes
和send-latest
)可以设置为spring.metrics.export.*
。可以将特定MetricWriters
的各个值设置为spring.metrics.export.triggers.<name>.*
,其中<name>
是 Bean 名称(或用于匹配 Bean 名称的模式)。
Warning
如果您关闭默认的MetricRepository
(例如,使用 DropwizardMetrics),则会禁用 Metrics 的自动导出。您可以pass 语句自己的MetricReader
类型的 bean 并将其声明为@ExportMetricReader
来获得相同的功能。
52.8.1 示例:导出到 Redis
如果您提供类型为RedisMetricRepository
的@Bean
并将其标记为@ExportMetricWriter
,则 Metrics 将导出到 Redis 缓存以进行聚合。为此,RedisMetricRepository
有两个重要的参数来配置它:prefix
和key
(传递到其构造函数中)。最好使用应用程序实例唯一的前缀(例如,使用随机值以及应用程序的逻辑名称,以使其可以与同一应用程序的其他实例相关联)。 “键”用于保留所有度量标准名称的全局索引,因此对于系统而言,它应该是“全局”唯一的(例如,对于您的系统而言,这是唯一的(例如,如果同一系统的两个实例具有不同的键,则它们可以共享 Redis 缓存)) 。
Example:
@Bean
@ExportMetricWriter
MetricWriter metricWriter(MetricExportProperties export) {
return new RedisMetricRepository(connectionFactory,
export.getRedis().getPrefix(), export.getRedis().getKey());
}
application.properties.
spring.metrics.export.redis.prefix: metrics.mysystem.${spring.application.name:application}.${random.value:0000}
spring.metrics.export.redis.key: keys.metrics.mysystem
该前缀的末尾是应用程序名称和 ID,因此以后可以轻松地使用它来标识具有相同逻辑名称的一组进程。
Note
同时设置key
和prefix
非常重要。该密钥用于所有存储库操作,并且可以由多个存储库共享。如果多个存储库共享一个密钥(例如,您需要在它们之间进行聚合),那么通常您会有一个只读的“主”存储库,该存储库具有一个简短但可识别的前缀(例如“ metrics.mysystem”),以及许多带有以主前缀开头的前缀的只写存储库(如上例中的metrics.mysystem.*
)。像这样从“主”存储库中读取所有密钥是有效的,但是读取具有较长前缀的子集是无效的(例如,使用其中一个写入存储库)。
Tip
上面的示例使用MetricExportProperties
来注入和提取密钥和前缀。为了方便起见,Spring Boot 为您提供了合理的默认配置。只要遵循建议,您就无法阻止您使用自己的价值观。
52.8.2 示例:导出到 Open TSDB
如果您提供类型为OpenTsdbGaugeWriter
的@Bean
并将其标记为@ExportMetricWriter
,则 Metrics 将导出到Open TSDB以进行汇总。 OpenTsdbGaugeWriter
具有url
属性,您需要将其设置为 Open TSDB“/put”端点,例如localhost:4242/api/put
)。它还具有namingStrategy
,您可以自定义或配置namingStrategy
以使度量标准与服务器上所需的数据结构相匹配。默认情况下,它仅通过度量标准名称作为 Open TSDB 度量标准名称传递,并添加标签“ domain”(值为“ org.springframework.metrics”)和“ process”(其值等于命名的对象哈希)战略)。因此,在运行应用程序并生成一些 Metrics 之后,您可以在 TSD UI(默认为localhost:4242)中检查 Metrics。
Example:
curl localhost:4242/api/query?start=1h-ago&m=max:counter.status.200.root
[
{
"metric": "counter.status.200.root",
"tags": {
"domain": "org.springframework.metrics",
"process": "b968a76"
},
"aggregateTags": [],
"dps": {
"1430492872": 2,
"1430492875": 6
}
}
]
52.8.3 示例:导出到 Statsd
要将度量导出到 Statsd,请首先确保已添加com.timgroup:java-statsd-client
作为项目的依赖项(Spring Boot 为此提供了依赖项 Management)。然后将spring.metrics.export.statsd.host
值添加到application.properties
文件中。除非提供spring.metrics.export.statsd.port
覆盖,否则将打开到端口8125
的连接。如果需要自定义前缀,可以使用spring.metrics.export.statsd.prefix
。
或者,您可以提供StatsdMetricWriter
类型的@Bean
并将其标记为@ExportMetricWriter
:
@Value("${spring.application.name:application}.${random.value:0000}")
private String prefix = "metrics";
@Bean
@ExportMetricWriter
MetricWriter metricWriter() {
return new StatsdMetricWriter(prefix, "localhost", 8125);
}
52.8.4 示例:导出到 JMX
如果您提供类型JmxMetricWriter
标记为@ExportMetricWriter
的@Bean
,那么度量标准将作为 MBeans 导出到本地服务器(MBeanExporter
是由 Spring Boot JMX 自动配置提供的,只要它已打开)。然后可以使用任何了解 JMX 的工具(例如 JConsole 或 JVisualVM)对 Metrics 进行检查,绘制图形,发出警报等。
Example:
@Bean
@ExportMetricWriter
MetricWriter metricWriter(MBeanExporter exporter) {
return new JmxMetricWriter(exporter);
}
每个度量标准都作为单独的 MBean 导出。 ObjectNames
的格式由ObjectNamingStrategy
给出,该ObjectNamingStrategy
可以注入JmxMetricWriter
(默认值将 break 度量标准名称并标记前两个句点分隔的部分,其方式应能使 JVisualVM 或 JConsole 中的度量标准组很好地组合)。
52.9 汇总来自多个来源的 Metrics
您可以使用AggregateMetricReader
合并来自不同物理来源的 Metrics。相同逻辑度量标准的源只需要使用句点分隔的前缀发布它们,阅读器就会进行汇总(通过截断度量标准名称并删除前缀)。对计数器求和,其他所有值(即仪表)取其最新值。
如果多个应用程序实例正在馈送到中央(例如 Redis)存储库,并且您想显示结果,这将非常有用。特别推荐与MetricReaderPublicMetrics
结合使用,以将结果连接到“/metrics”端点。
Example:
@Autowired
private MetricExportProperties export;
@Bean
public PublicMetrics metricsAggregate() {
return new MetricReaderPublicMetrics(aggregatesMetricReader());
}
private MetricReader globalMetricsForAggregation() {
return new RedisMetricRepository(this.connectionFactory,
this.export.getRedis().getAggregatePrefix(), this.export.getRedis().getKey());
}
private MetricReader aggregatesMetricReader() {
AggregateMetricReader repository = new AggregateMetricReader(
globalMetricsForAggregation());
return repository;
}
Note
上面的示例使用MetricExportProperties
来注入和提取密钥和前缀。 Spring Boot 为方便起见向您提供了此设置,默认设置是合理的。它们在MetricExportAutoConfiguration
中设置。
Note
上面的MetricReaders
不是@Beans
,也没有标记为@ExportMetricReader
,因为它们只是从其他存储库收集和分析数据,并且不希望导出其值。
52.10 DropwizardMetrics
当您声明对io.dropwizard.metrics:metrics-core
库的依赖关系时,将创建默认的MetricRegistry
Spring bean。如果需要自定义,还可以注册自己的@Bean
实例。 Dropwizard“Metrics”库的用户将发现 Spring BootMetrics 自动发布到com.codahale.metrics.MetricRegistry
。 MetricRegistry
中的 Metrics 也会通过/metrics
端点自动公开
使用 DropwizardMetrics 时,默认的CounterService
和GaugeService
替换为DropwizardMetricServices
,它是MetricRegistry
的包装器(因此您可以@Autowired
这些服务之一并可以正常使用它)。您还可以通过为 Metrics 名称添加适当的类型(即timer.*
,histogram.*
(用于仪表)和meter.*
)来创建“特殊” DropwizardMetrics。
52.11 消息通道集成
如果存在一个名为metricsChannel
的MessageChannel
bean,那么将创建一个MetricWriter
并将度量写入该通道。发送到该通道的每个消息将包含Delta或Metric有效负载,并具有metricName
头。编写器自动连接到导出器(对于所有编写器),因此所有度量标准值都将显示在通道上,并且订阅者可以执行其他分析或操作(由您提供 Channels 和所需的任何订阅者) )。