如何在SLA和标签上注册Micrometer Timer?

时间:2018-05-16 09:18:46

标签: java spring-boot prometheus micrometer

我正在尝试将我的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

2 个答案:

答案 0 :(得分:5)

我在Micrometer slack channel得到了答案。千分尺解决这个问题的方法不是注册度量本身,而是注册注册过滤器,如下所示:

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(...)name调用tags时。所以我们不必担心这里的表现。

答案 1 :(得分:2)

首先,最好在名称部分之间使用点分隔符。这使公制供应商保持中立,所以如果你决定运送到普罗米修斯以外的东西,它就可以了!换句话说,最好将其记录为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
}

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