如何使用 SLA 和标签注册 Micrometer Timer?

Posted

技术标签:

【中文标题】如何使用 SLA 和标签注册 Micrometer Timer?【英文标题】:How to register Micrometer Timer with SLA and tags? 【发布时间】:2018-10-26 06:32:17 【问题描述】:

我正在尝试将我的 Prometheus 指标迁移到千分尺,但现在我遇到了一件事情......

目前我的 Prometheus 直方图配置如下:

private static final Histogram REQUEST_DURATION = Histogram
        .build("http_request_duration_milliseconds", "Duration in milliseconds for processing a request.")
        .labelNames("http_method", "http_status", "java_class", "java_method")
        .buckets(10, 25, 50, 100, 500, 1000)
        .register();

所以为了切换到千分尺,我将其替换如下:

Timer.builder("http.request.duration")
            .description("Duration in seconds for processing a request.")
            .sla(Duration.ofMillis(10), Duration.ofMillis(25), Duration.ofMillis(50), Duration.ofMillis(100), Duration.ofMillis(500), Duration.ofMillis(1000), Duration.ofMillis(5000))
            .register(registry);

好的。让我们看看我想如何使用它......目前我只是调用

REQUEST_DURATION.labels(httpMethod, httpStatus, javaClass, javaMethod).observe(milliseconds);

所以我把它换成了

Metrics.timer("http.request.duration",
            "http.method", httpMethod,
            "http.status", httpStatus,
            "java.class", javaClass,
            "java.method", javaMethod)
            .record(Duration.ofNanos(nanoseconds));

但现在的问题是,Micrometer 抱怨我之前配置的指标没有这些标签。当然我做到了,因为我不知道那个时候的价值观。这里是例外:

java.lang.IllegalArgumentException: Prometheus requires that all meters with the same name have the same set of tag keys. There is already an existing meter containing tag keys []. The meter you are attempting to register has keys [http.method, http.status, java.class, java.method].

好的。所以我想,那么让我们用Metrics.timer 调用来指定存储桶。但这不起作用,因为没有传递这些值的方法。

那么...如何为我的指标设置sla 存储桶 tags

【问题讨论】:

好的.. 刚刚意识到在这种情况下我应该使用Timer 而不是DistributionSummary。我会更新问题。 【参考方案1】:

我在Micrometer slack channel 上得到了答案。解决此问题的 Micrometer 方法不是注册指标本身,而是注册一个过滤器,如下所示:

registry.config().meterFilter(new MeterFilter() 
    @Override
    public DistributionStatisticConfig configure(Meter.Id id, DistributionStatisticConfig config) 
        if (id.getName().equals("http.request.duration")) 
            return DistributionStatisticConfig.builder()
                    .sla(Duration.ofMillis(10).toNanos(),
                         Duration.ofMillis(25).toNanos(),
                         Duration.ofMillis(50).toNanos(), 
                         Duration.ofMillis(100).toNanos(),
                         Duration.ofMillis(500).toNanos(),
                         Duration.ofMillis(1000).toNanos(), 
                         Duration.ofMillis(5000).toNanos())
                    .build()
                    .merge(config);
        
        return config;
    
);

当使用Metrics.timer(...) 推送度量值时,Micrometer 将调用此过滤器并应用此处指定的所有配置。此过滤器仅在仪表初始化时调用,即当 Metrics.timer(...) 第一次使用此特定 nametags 调用时。所以我们不必担心这里的性能。

【讨论】:

【参考方案2】:

首先,最好在名称部分之间使用点分隔符。这使度量标准与供应商保持中立,因此如果您决定将其运送到 Prometheus 以外的其他地方,它可以工作!也就是说,最好记为http.request.duration。应用 Prometheus 命名约定后,它将显示为 http_request_duration_seconds

如果这是一个 Spring Boot 应用程序,您可以在 property-based meter filter 中声明 SLA:

management.metrics.distribution.sla.http.request.duration=10ns,25ns,50ns,100ns,500ns,1000ns,5000ns

如果您使用的是 Spring Boot 1.x,则必须按照文档中的 here 转义名称。

顺便说一句,Spring 已经 automatically records 使用名为 http_server_requests 的指标请求持续时间。它上面没有 Java 类和 Java 方法,但有方法和状态,以及其他一些你在这里没有的东西。您有机会覆盖WebMvcTagsProvider 以提供额外的标签(包括Java 类和方法):

@Bean
WebMvcTagsProvider requestTags() 
   return customProvider; // can be extended from DefaultWebMvcTagsProvider

WebMvcTagsProvider#httpRequestTags 有一个 handler 参数,您可以从中推断类型和方法。

【讨论】:

太酷了!这些属性在 Spring Boot 1 中是否已经可用?因为就我而言,我还不能升级到第 2 版。 您可以在 Spring Boot 1 应用程序中包含 micrometer-spring-legacymicrometer-registry-prometheus 作为依赖项,然后您就可以开始使用了。无需手动检测您的 MVC 端点/控制器。此外,您还可以免费获得一大堆自动配置的 JVM 指标。 感谢带点的提示。我的代码中已经有这个,但忘了在这里更新它。我现在更新了我的代码。 关于http_server_requests...我知道Spring已经记录了。但它不记录java类和方法名,只记录路径。此外,它没有配置这些存储桶,...但我想现在我可以使用配置参数设置存储桶。 @Ethan 更新了答案,向您展示了如何将 Java 类/方法添加到 Spring 的默认工具中。一般来说,默认情况下我们不会将 SLAs/percentiles/etc 添加到计时器中,而是允许您通过这样的属性在您认为合适的时候添加它们。

以上是关于如何使用 SLA 和标签注册 Micrometer Timer?的主要内容,如果未能解决你的问题,请参考以下文章

如何根据标签更新 MicroMeter 量规

以 Micrometer 为单位的 Counter 指标的动态标签值

MicroMeter:删除/禁用某个标签

如何使用 Java prometheus sdk 创建带有标签的 Gauge 度量?

有没有办法将 Micrometer @Timed 注释捕获到 Prometheus 指标存储/注册表中? [复制]

如何为某些 Spring Boot Micrometer 指标提供标签,但不为其他指标提供标签?