问题最初来自 Spring Cloud Gateway 的指标配置问题,因为 Micrometer、Spring Cloud 和 Spring 方面都没有文档。当我启用
spring.cloud.gateway.metrics.enabled=true
时,似乎没有简单的方法可以为公开的指标添加直方图或百分位数。
我必须添加 0.95 和 0.99 百分位数以及 slo 桶:50、100、200、300、400 和 500 毫秒。
一旦我了解了 Spring Boot 中指标的排列方式,我就意识到这个问题可以应用于您在应用程序中使用的所有指标,例如 Timer 或 DistributionSummary。
如果您需要 slo 存储桶,请将以下属性添加到您的应用程序属性文件中
management.metrics.distribution.slo.spring.cloud.gateway.requests=50ms,100ms,200ms,300ms,400ms,500ms
如果您需要百分位数,请添加
management.metrics.distribution.percentiles.spring.cloud.gateway.requests=0.95,0.99
还要确保您启用了
spring.cloud.gateway.metrics.enabled
和 spring.cloud.gateway.metrics.tags.path.enabled
。
此解决方案还可以与您拥有的每个 Timer 或 DistributionSummary 指标一起使用,您只需将 id-prefix 更改为您的指标 ID。
management.metrics.distribution.slo.{id-prefix}={your desired slo values}
Spring Cloud Gateway 的指标通过 GatewayMetricsFilter 类注册。正如您所看到的,这是一个简单的类,它只是创建一个 Timer,然后将其传递给 MeterRegistry。
神奇之处在于MeterRegistry和MeterFilter。一旦您通过meterRegistry创建了一个指标,它就会经历MeterFilter接口的一系列实现。
if (config != null) {
for (MeterFilter filter : filters) {
DistributionStatisticConfig filteredConfig = filter.configure(mappedId, config);
if (filteredConfig != null) {
config = filteredConfig;
}
}
}
他们的任务是过滤和配置属于他们的指标。如果你想知道它们是如何排列的,你可以阅读文章。
我们对 PropertiesMeterFilter 感兴趣,它是在应用程序自动配置阶段创建的。多亏了它,我们可以通过 applicaiton.property 文件配置所有指标。我们对它如何配置 DistributionStatisticConfig 感兴趣:
@Override
public DistributionStatisticConfig configure(Meter.Id id, DistributionStatisticConfig config) {
Distribution distribution = this.properties.getDistribution();
return DistributionStatisticConfig.builder()
.percentilesHistogram(lookupWithFallbackToAll(distribution.getPercentilesHistogram(), id, null))
.percentiles(lookupWithFallbackToAll(distribution.getPercentiles(), id, null))
.serviceLevelObjectives(
convertServiceLevelObjectives(id.getType(), lookup(distribution.getSlo(), id, null)))
.minimumExpectedValue(
convertMeterValue(id.getType(), lookup(distribution.getMinimumExpectedValue(), id, null)))
.maximumExpectedValue(
convertMeterValue(id.getType(), lookup(distribution.getMaximumExpectedValue(), id, null)))
.expiry(lookupWithFallbackToAll(distribution.getExpiry(), id, null))
.bufferLength(lookupWithFallbackToAll(distribution.getBufferLength(), id, null))
.build()
.merge(config);
}
正如我们所看到的,它会查找您在 applicaiton.property 中指定的所有 slo 值:
lookup(distribution.getSlo(), id, null))
如果指标的 ID 匹配,则会发布您的存储桶列表。