编辑此页面

Micrometer 指标

Micrometer 为指标收集提供了一个抽象层。它为基本指标类型(如计数器、计量器、计时器和分布摘要)定义了一个 API,以及一个 MeterRegistry API,它概括了不同后端监控系统的指标收集和传播。

本文档是 Quarkus 可观察性参考指南的一部分,该指南介绍了此组件和其他可观察性相关组件。

Micrometer 是 Quarkus 推荐的指标方法。
默认情况下,指标在主 HTTP 服务器上公开。如果您想从单独的管理端口公开指标,请参阅托管接口部分。

Micrometer 和监控系统扩展

Quarkus Micrometer 扩展的结构与 Micrometer 项目相同。quarkus-micrometer 扩展提供了核心 Micrometer 支持和运行时集成。其他 Quarkus 和 Quarkiverse 扩展使用 Quarkus Micrometer 扩展来提供对其他监控系统的支持。

Quarkus 扩展

  • micrometer

  • micrometer-registry-prometheus

Quarkiverse 扩展(可能不完整)

  • micrometer-registry-azure-monitor

  • micrometer-registry-datadog

  • micrometer-registry-graphite

  • micrometer-registry-influx

  • micrometer-registry-jmx

  • micrometer-registry-newrelic-telemetry

  • micrometer-registry-otlp

  • micrometer-registry-signalfx

  • micrometer-registry-stackdriver

  • micrometer-registry-statsd

例如,要为您的应用程序添加 Prometheus 指标支持,请使用 micrometer-registry-prometheus 扩展。它会将 Quarkus Micrometer 扩展和 Micrometer 核心库作为依赖项引入。

使用以下命令将扩展添加到您的项目(从您的项目目录)

CLI
quarkus extension add micrometer-registry-prometheus
Maven
./mvnw quarkus:add-extension -Dextensions='micrometer-registry-prometheus'
Gradle
./gradlew addExtension --extensions='micrometer-registry-prometheus'

这会将以下内容添加到您的构建文件中

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-micrometer-registry-prometheus</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-micrometer-registry-prometheus")

一切就绪!

类似的过程适用于其他指标注册表扩展。例如,要使用 Micrometer StackDriver MeterRegistry,您可以使用 Quarkiverse 中的 quarkus-micrometer-registry-stackdriver 扩展

CLI
quarkus extension add io.quarkiverse.micrometer.registry:quarkus-micrometer-registry-stackdriver
Maven
./mvnw quarkus:add-extension -Dextensions='io.quarkiverse.micrometer.registry:quarkus-micrometer-registry-stackdriver'
Gradle
./gradlew addExtension --extensions='io.quarkiverse.micrometer.registry:quarkus-micrometer-registry-stackdriver'
pom.xml
<dependency>
    <groupId>io.quarkiverse.micrometer.registry</groupId>
    <artifactId>quarkus-micrometer-registry-stackdriver</artifactId>
</dependency>
build.gradle
implementation("io.quarkiverse.micrometer.registry:quarkus-micrometer-registry-stackdriver")

其他注册表实现

如果想要使用的 Micrometer 注册表还没有关联的扩展,请使用 quarkus-micrometer 扩展并直接引入 Micrometer 指标注册表依赖项

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-micrometer</artifactId>
</dependency>
<dependency>
    <groupId>com.acme</groupId>
    <artifactId>custom-micrometer-registry</artifactId>
    <version>...</version>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-micrometer")
implementation("com.acme:custom-micrometer-registry")

然后,您需要指定自己的提供程序来配置和初始化 MeterRegistry,如下一节所述。

创建自定义 MeterRegistry

如果需要,请使用自定义 @Produces 方法来创建和配置您自己的 MeterRegistry

以下示例自定义了 StatsD 使用的行格式

@Produces
@Singleton (1)
public StatsdMeterRegistry createStatsdMeterRegistry(StatsdConfig statsdConfig, Clock clock) { (2)
    // define what to do with lines
    Consumer<String> lineLogger = line -> logger.info(line);

    // inject a configuration object, and then customize the line builder
    return StatsdMeterRegistry.builder(statsdConfig)
          .clock(clock)
          .lineSink(lineLogger)
          .build();
}
1 该方法返回 @Singleton
2 该方法返回 MeterRegistry 的特定类型

此示例对应于 Micrometer 文档中的以下说明:Micrometer StatsD:自定义指标接收器

使用 MicroProfile Config 注入配置注册表所需的任何配置属性。大多数 Micrometer 注册表扩展,如 quarkus-micrometer-registry-statsd,都提供与 Quarkus 配置模型集成的注册表特定的配置对象。Quarkiverse GitHub 存储库可以作为有用的实现参考。

创建您自己的指标

指标数据在聚合中用于观察数据随时间的变化。此数据用于趋势分析、异常检测和警报。数据由后端监控系统存储在时间序列数据库中,新值附加到序列的末尾。

指标是延迟构建的。在您执行将创建指标的操作(如访问端点)之前,您可能看不到您正在寻找的指标的任何数据。

命名约定

指标名称应使用点分隔段,a.name.like.this。Micrometer 应用命名约定来转换注册的指标名称,以匹配后端监控系统的期望。

给定计时器的以下声明:registry.timer("http.server.requests"),应用的命名约定将为不同的监控系统发出以下指标

  • Prometheus:http_server_requests_duration_seconds

  • Atlas:httpServerRequests

  • Graphite:http.server.requests

  • InfluxDB:http_server_requests

定义聚合维度

指标,即单个数值测量值,通常会捕获其他数据。此辅助数据用于对指标进行分组或聚合以进行分析。Micrometer API 将此维度数据称为标签,但在其他文档来源中,您可能会看到它被称为“labels”或“attributes”。

Micrometer 主要为支持维度数据的后端监控系统构建(指标名称通过键/值对丰富)。对于仅支持平面指标名称的分层系统,Micrometer 将展平键/值对集(按键排序)并将其添加到名称中。

可以在将指标注册到 MeterRegistry 时或使用 Meter Filter 指定标签。

有关其他建议,请参阅 Micrometer 文档中的 标签命名

指标名称和维度的每个唯一组合都会生成一个唯一的时间序列。使用无界维度数据集可能会导致“基数爆炸”,即创建新时间序列的指数级增长。

获取 MeterRegistry 的引用

要注册指标,您需要引用 MeterRegistry,它由 Micrometer 扩展配置和维护。

使用以下方法之一获取 MeterRegistry 的引用

  1. 使用 CDI 构造函数注入

    package org.acme.micrometer;
    
    import io.micrometer.core.instrument.MeterRegistry;
    
    import jakarta.ws.rs.GET;
    import jakarta.ws.rs.Path;
    import jakarta.ws.rs.Produces;
    
    @Path("/example")
    @Produces("text/plain")
    public class ExampleResource {
    
        private final MeterRegistry registry;
    
        ExampleResource(MeterRegistry registry) {
            this.registry = registry;
        }
    }
  2. 使用 MeterRegistry 成员变量并使用 @Inject

        @Inject
        MeterRegistry registry;
  3. 使用全局 MeterRegistry

        MeterRegistry registry = Metrics.globalRegistry;

计量器

计量器测量随时间可能增加或减少的值,例如汽车上的速度计。计量器在监视缓存或集合的统计信息时非常有用。

计量器值是采样的而不是设置的;没有与计量器关联的值在测量之间可能如何变化的记录。

Micrometer 提供了几种创建计量器的机制

  1. 包装集合的构造以监视其大小

    List<String> list = registry.gaugeCollectionSize("fantastic.list", (1)
            Tags.of("key", "value") // optional (2)
            new ArrayList<>());  (3)
    1 使用点分隔约定创建新计量器 list.size
    2 标签 与计量器关联。计量器标签值是常量,必须在构造时分配。
    3 构造应观察其大小的数组列表。
  2. 使用构建器创建一个将调用函数的计量器

    Gauge.builder("jvm.threads.peak", threadBean, ThreadMXBean::getPeakThreadCount) (1)
        .baseUnit(BaseUnits.THREADS) // optional (2)
        .description("The peak live thread count...") // optional (3)
        .tags("key", "value") // optional (4)
        .register(registry); (5)
    1 创建一个名为 jvm.threads.peak 的新计量器,它将调用 getPeakThreadCountthreadBean 上,threadBeanThreadMXBean 的实例
    2 定义基本单位,有关预定义值,请参见 BaseUnits.java
    3 提供计量器的描述
    4 标签 与计量器关联
    5 将计量器注册到 MeterRegistry

有关更多信息和示例,请参阅 Micrometer 文档中的 计量器。值得注意的是两个特殊情况:用于测量时间的 TimeGauge 和用于一起报告多个标准的 MultiGauge

默认情况下,Micrometer 不会创建对其观察的对象的强引用。根据注册表的不同,Micrometer 要么省略完全观察到已进行垃圾回收的对象的计量器,要么使用 NaN(非数字)作为观察值。

何时应使用计量器?仅在不能使用其他计量器时才使用计量器。与其他计量器相比,计量器的使用可能不太直接。如果您正在测量的值可以计数(因为该值始终递增),请改用计数器。

计数器

计数器测量仅增加的值。使用以下方法之一创建计数器。

  1. MeterRegistry 上使用便利方法

    registry.counter("example.prime.number", "type", "prime"); (1) (2)
    1 example.prime.number 是计数器名称。
    2 type 是一个维度标签,值为 prime
  2. 使用 Counter.builder 提供描述和单位

    Counter.builder("count.me") (1)
        .baseUnit("beans")            // optional (2)
        .description("a description") // optional (3)
        .tags("region", "test")       // optional (4)
        .register(registry);
    1 创建一个名为 count.me 的新计数器
    2 定义一个自定义基本单位。有关预定义值,请参见 BaseUnits.java
    3 为计数器提供描述
    4 标签 与计数器关联
  3. 注释 方法

    @Counted(value = "counted.method", extraTags = { "extra", "annotated" }) (1) (2)
    void countThisMethod(){
        ...
    }
    1 CDI 拦截器将创建和注册一个名为 counted.method 的计数器
    2 拦截器创建的计数器将具有维度标签 "extra",其值为 "annotated"

有关更多信息和示例,请参阅 Micrometer 文档中的 计数器,其中包括较不常见的 FunctionCounter,该计数器可用于测量始终递增的函数返回的结果。

何时应使用计数器?如果您正在执行无法定时或汇总的操作,请使用计数器。如果您想更多地了解值的变化方式,则计时器(当基本测量单位为时间时)或分布摘要可能更合适。

摘要和计时器

Micrometer 中的计时器和分布摘要非常相似。两种指标都会记录数据,并且可以捕获其他直方图或百分位数数据。虽然分布摘要可以用于任意类型的数据,但计时器针对测量时间和持续时间进行了优化。

计时器和分布摘要在内部至少存储三个值

  • 所有记录值的聚合,即总和

  • 已记录的值的数量(计数器)

  • 在衰减时间窗口内看到的最高值(计量器)。

创建分布摘要

使用分布摘要记录值,而不是时间。使用以下方法之一创建分布摘要。

  1. MeterRegistry 上使用便利方法

    registry.summary("bytes.written", "protocol", "http"); (1) (2)
    1 bytes.written 是摘要名称
    2 protocol 是维度标签,值为 http
  2. 使用 DistributionSummary.builder 提供描述和单位

    DistributionSummary.builder("response.size") (1)
        .baseUnit("bytes")            // optional (2)
        .description("a description") // optional (3)
        .tags("protocol", "http")     // optional (4)
        .register(registry);
    1 创建一个名为 response.size 的新分布摘要
    2 使用 bytes 作为基本单位。有关预定义值,请参见 BaseUnits.java
    3 为分布摘要提供描述
    4 标签 与分布摘要关联

创建计时器

计时器测量短时延迟及其发生的频率。不支持负值,较长的持续时间可能会导致总时间溢出(Long.MAX_VALUE 纳秒(292.3 年))。

使用以下方法之一构造计时器。

  1. MeterRegistry 上使用便利方法

    registry.timer("fabric.selection", "primary", "blue"); (1) (2)
    1 fabric.selection 是摘要名称
    2 primary 是维度标签,值为 blue
  2. 使用 Timer.builder 提供描述和单位

    Timer.builder("my.timer")        (1) (2)
        .description("description ") // optional (3)
        .tags("region", "test")      // optional (4)
        .register(registry);
    1 创建一个名为 my.timer 的新计时器
    2 计时器测量时间,并将其转换为监控后端所需的单位
    3 为分布摘要提供描述
    4 标签 与计时器关联
  3. 注释 方法

    @Timed(value = "call", extraTags = {"region", "test"}) (1) (2)
    1 CDI 拦截器将创建和注册一个名为 call 的计时器
    2 拦截器创建的计时器将具有维度标签 "region",其值为 "test"

使用计时器测量持续时间

Micrometer 提供了以下便利机制来记录持续时间。

  1. 包装 Runnable 的调用

    timer.record(() -> noReturnValue());
  2. 包装 Callable 的调用

    timer.recordCallable(() -> returnValue());
  3. 创建一个用于重复调用的包装 Runnable

    Runnable r = timer.wrap(() -> noReturnValue());
  4. 创建一个用于重复调用的包装 Callable

    Callable c = timer.wrap(() -> returnValue());
  5. 对更复杂的代码路径使用 Sample

    Sample sample = Timer.start(registry); (1)
    
    doStuff; (2)
    
    sample.stop(registry.timer("my.timer", "response", response.status())); (3)
    1 我们创建一个示例,该示例记录计时器的开始时间。
    2 该示例可以作为上下文传递
    3 我们可以在停止示例时选择计时器。此示例使用响应状态作为标识计时器的标签,直到处理完成时才知道该标签。

直方图和百分位数

可以将计时器和分布摘要配置为发出其他统计信息,如直方图数据、预先计算的百分位数或服务级别目标 (SLO) 边界。有关更多信息和示例,请参阅 Micrometer 文档中的 计时器分布摘要,其中包括两种类型的内存占用量估算。

与计时器和分布摘要关联的计数、总和和直方图数据可以在维度之间(或在一系列实例之间)重新聚合。

预先计算的百分位数值不能重新聚合。百分位数对于每个数据集都是唯一的(此测量集合的第 90 个百分位数)。

自动生成的指标

HTTP 服务器

Micrometer 扩展自动计时 HTTP 服务器请求。按照 Prometheus 计时器的命名约定,查找 http_server_requests_seconds_counthttp_server_requests_seconds_sumhttp_server_requests_seconds_max。已为请求的 URI、HTTP 方法(GET、POST 等)、状态代码(200、302、404 等)以及更一般的 outcome 字段添加了维度标签。

忽略端点

您可以使用 quarkus.micrometer.binder.http-server.ignore-patterns 属性禁用 HTTP 端点的测量。此属性接受以逗号分隔的简单正则表达式匹配模式列表,用于标识应忽略的 URI 路径。例如,设置 quarkus.micrometer.binder.http-server.ignore-patterns=/example/prime/[0-9]+ 将忽略对 https://:8080/example/prime/7919 的请求。对 https://:8080/example/gauge/7919 的请求仍将被测量。

URI 模板

micrometer 扩展将尽最大努力以模板形式表示包含路径参数的 URI。使用上面的示例,对 https://:8080/example/prime/7919 的请求应显示为 http_server_requests_seconds_* 指标的属性,其值为 uri=/example/prime/{number}

如果无法确定正确的 URL,请使用 quarkus.micrometer.binder.http-server.match-patterns 属性。此属性接受以逗号分隔的列表,该列表定义简单正则表达式匹配模式与替换字符串之间的关联。例如,设置 quarkus.micrometer.binder.http-server.match-patterns=/example/prime/[0-9]+=/example/{jellybeans} 将使用值 /example/{jellybeans} 作为 uri 属性,只要请求的 uri 匹配 /example/prime/[0-9]+

导出的指标格式

默认情况下,指标使用 Prometheus 格式 application/openmetrics-text 导出,您可以通过将 Accept 请求标头指定为 text/plain 来恢复为以前的格式 (curl -H "Accept: text/plain" localhost:8080/q/metrics/)。

Netty 内存管理指标

Netty 内存管理指标非常重要,因为 Quarkus 构建在 Eclipse Vert.x 之上,这是一个构建在 Netty 之上的框架,用于在 Java 中创建响应式应用程序。即使您在 Quarkus 中使用命令式编程风格,在表面之下,Vert.x 也会以响应式方式方便地处理它。

简而言之,Netty 为异步应用程序提供了一种高效的内存管理系统。它提供了不同类型的内存分配策略,包括(存储在 JVM 堆中)和直接内存(在 JVM 内存之外分配),以及一个缓冲区池机制,用于优化分配并减少垃圾回收 (GC) 开销。

Netty 中的内存类别

Netty 使用两个主要的内存类别

  1. 堆内存

    • 从 JVM 堆中分配 (byte[])。

    • 由垃圾回收器管理。

    • 对于 I/O 操作速度较慢,因为它需要在通过套接字发送之前将数据复制到/从直接内存。

  2. 直接内存

    • 使用 ByteBuffer.allocateDirect() 在 JVM 堆之外分配。

    • 不由垃圾回收器管理,从而减少 GC 压力。

    • 对于 I/O 操作速度更快,因为它避免了不必要的复制。

对于 Quarkus 应用程序,不建议对 -XX:MaxRAMPercentage 使用非常高的值(将大部分可用 RAM 分配给 Java 堆),因为保留 Netty 的本机内存分配空间非常重要。

这些 Netty 指标有助于评估需要多少空间。

池化机制

Netty 使用 PooledByteBufAllocator 来减少内存分配开销和碎片。它基于 jemalloc 风格的 Arena 系统(参见 jemalloc/jemalloc),其中包括

  • Arena:管理分配的大型内存块。

  • Chunk:Arena 中的内存段(通常大小为 16MB)。

  • Page:Chunk 的固定大小部分(通常为 8KB)。

  • Subpage:Page 中用于微小对象的较小分配。

  • 线程本地缓存:用于频繁使用的小缓冲区的每个线程缓存,减少争用。

Netty 内存管理指标

Micrometer 指标报告 Netty 分配器的关键指标,有助于监控内存使用情况、固定内存、池化效率和缓存行为。

1. 内存使用情况指标(每个分配器)

这些指标跟踪 Netty 分配器当前的内存使用情况(以字节为单位)

指标名称 描述 类型 标签

allocator.memory.used

分配器当前使用的内存量

计量器

memory_type=[heap, direct]name=allocator-name

2. 池化分配器 - 固定内存指标

固定内存是指由于活动引用而无法回收的缓冲区,从而阻止分配器重复使用。 数字可能表示某种泄漏(因为未释放引用)。

指标名称 描述 类型 标签

allocator.memory.pinned

无法重复使用的固定内存量

计量器

memory_type=[heap, direct]name=allocator-name

3. 池化分配器 - Arena 指标

Arena(内存的大尺寸)通过对内存 Chunk 进行分组来有效地管理内存分配。因此,此指标是为给定分配器分配的 Arena 的数量。

指标名称 描述 类型 标签

allocator.pooled.arenas

处理内存分配的 Arena 数量

计量器

memory_type=[heap, direct]

4. 缓存大小指标

Netty 在给定线程中缓存小缓冲区,以避免频繁的内存分配并提高性能。如果同一线程需要内存,它将首先在其自己的缓存中检查。由于事件循环线程模型(线程数较少),这尤其有效。请注意,微小缓存现在已合并到小缓存中。

指标名称 描述 类型 标签

allocator.pooled.cache.size

缓冲区缓存的大小

计量器

cache_type=[small, normal]

5. 线程本地缓存指标

这些指标指示用于内存池的活动线程本地缓存的数量。它补充了缓存大小指标(缓存是大小,而这是缓存的数量)

指标名称 描述 类型 标签

allocator.pooled.threadlocal.caches

缓冲区的线程本地缓存的数量

计量器

6. Chunk 大小指标

Chunk 是 Netty Arena 中内存分配的主要单位。

指标名称 描述 类型 标签

allocator.pooled.chunk.size

池化分配器中内存 Chunk 的大小

计量器

自定义 Micrometer

Quarkus 提供了多种自定义 Micrometer 的方法。

使用 MeterFilter 自定义发出的标签和指标

Micrometer 使用 MeterFilter 实例来自定义 MeterRegistry 实例发出的指标。Micrometer 扩展将检测 MeterFilter CDI bean 并在初始化 MeterRegistry 实例时使用它们。

@Singleton
public class CustomConfiguration {

    @ConfigProperty(name = "deployment.env")
    String deploymentEnv;

    /** Define common tags that apply only to a Prometheus Registry */
    @Produces
    @Singleton
    @MeterFilterConstraint(applyTo = PrometheusMeterRegistry.class)
    public MeterFilter configurePrometheusRegistries() {
        return MeterFilter.commonTags(Arrays.asList(
                Tag.of("registry", "prometheus")));
    }

    /** Define common tags that apply globally */
    @Produces
    @Singleton
    public MeterFilter configureAllRegistries() {
        return MeterFilter.commonTags(Arrays.asList(
                Tag.of("env", deploymentEnv)));
    }

    /** Enable histogram buckets for a specific timer */
    @Produces
    @Singleton
    public MeterFilter enableHistogram() {
        return new MeterFilter() {
            @Override
            public DistributionStatisticConfig configure(Meter.Id id, DistributionStatisticConfig config) {
                if(id.getName().startsWith("myservice")) {
                    return DistributionStatisticConfig.builder()
                        .percentiles(0.5, 0.95)     // median and 95th percentile, not aggregable
                        .percentilesHistogram(true) // histogram buckets (e.g. prometheus histogram_quantile)
                        .build()
                        .merge(config);
                }
                return config;
            }
        };
    }
}

在此示例中,单例 CDI bean 将生成两个不同的 MeterFilter bean。一个将仅应用于 Prometheus MeterRegistry 实例(使用 @MeterFilterConstraint 限定符),另一个将应用于所有 MeterRegistry 实例。应用程序配置属性也被注入并用作标签值。有关 MeterFilter 的更多示例,请参见官方文档

对服务器 HTTP 请求使用 HttpServerMetricsTagsContributor

通过提供实现 io.quarkus.micrometer.runtime.HttpServerMetricsTagsContributor 的 CDI bean,用户代码可以根据 HTTP 请求和响应的详细信息贡献任意标签。

使用此接口创建标签时,务必限制值的基数,否则有严重降低指标系统容量的风险。

对客户端 HTTP 请求使用 HttpClientMetricsTagsContributor

通过提供实现 io.quarkus.micrometer.runtime.HttpClientMetricsTagsContributor 的 CDI bean,用户代码可以根据 HTTP 请求的详细信息贡献任意标签

对指标注册表进行任意自定义,请使用 MeterRegistryCustomizer

通过提供实现 io.quarkus.micrometer.runtime.MeterRegistryCustomizer 用户代码的 CDI bean,可以更改任何已激活的 MeterRegistry 的配置。除非使用 @io.quarkus.micrometer.runtime.MeterRegistryCustomizerConstraint 注释实现,否则自定义将应用于所有 MeterRegistry 实例。

Micrometer 是否支持注释?

Micrometer 确实定义了两个注释,@Counted@Timed,可以添加到方法中。@Timed 注释将包装方法的执行,除了在注释本身上定义的任何标签之外,还将发出以下标签:类、方法和异常(“none”或检测到的异常的简单类名)。

可以使用 @MeterTag 注释 @Counted@Timed 的参数,以动态分配有意义的标签值。

可以通过创建实现 io.micrometer.common.annotation.ValueResolver 的 bean 并引用此类来使用 MeterTag.resolver 从方法参数中提取标签:@MeterTag(resolver=CustomResolver.class)

也支持 MeterTag.expression,但是您必须通过创建实现 io.micrometer.common.annotation.ValueExpressionResolver 的 bean 来实现表达式的评估,该 bean 可以评估表达式。

enum Currency { USD, EUR }

@Singleton
class EnumOrdinalResolver implements ValueResolver {
    @Override
    public String resolve(Object parameter) {
        if(parameter instanceof Enum) {
            return String.valueOf(((Enum<?>) parameter).ordinal());
        }
        return null;
    }
}

@Singleton
public class MyExpressionResolver implements ValueExpressionResolver {
    @Override
    public String resolve(String expression, Object parameter) {
        return someParser.parse(expression).evaluate(parameter);
    }
}

// tags = type=with_enum, currency=${currency.toString()}
@Timed(value="time_something", extraTags = {"type", "with_enum"})
public Something calculateSomething(@MeterTag Currency currency) { ... }

// tags = type=with_enum, the_currency=${currency.toString()}
@Timed(value="time_something", extraTags = {"type", "with_enum"})
public Something calculateSomething(@MeterTag(key="the_currency") Currency currency) { ... }

// tags = type=with_enum, currency=${currency.ordinal()}
@Timed(value="time_something", extraTags = {"type", "with_enum"})
public Something calculateSomething(@MeterTag(resolver=EnumOrdinalResolver.class) Currency currency) { ... }

// tags = type=with_enum, currency=${currency.ordinal()}
@Timed(value="time_something", extraTags = {"type", "with_enum"})
public Something calculateSomething(@MeterTag(expression="currency.ordinal()") Currency currency) { ... }
提供的标签值必须是低基数的。高基数值可能会导致指标后端中的性能和存储问题(“基数爆炸”)。标签值不应使用最终用户数据,因为这些数据可能是高基数的。

许多方法,例如 REST 端点方法或 Vert.x 路由,都由 micrometer 扩展开箱即用地进行计数和计时。

对 MicroProfile Metrics API 的支持

如果您在应用程序中使用 MicroProfile Metrics API,Micrometer 扩展将创建一个自适应层,以将这些指标映射到 Micrometer 注册表中。请注意,两个系统之间的命名约定不同,因此在使用带有 Micrometer 的 MP Metrics 时发出的指标将会更改。

使用 MeterFilter 根据您的约定重新映射名称或标签。

@Produces
@Singleton
public MeterFilter renameApplicationMeters() {
    final String targetMetric = MPResourceClass.class.getName() + ".mpAnnotatedMethodName";

    return MeterFilter() {
        @Override
        public Meter.Id map(Meter.Id id) {
            if (id.getName().equals(targetMetric)) {
                // Drop the scope tag (MP Registry type: application, vendor, base)
                List<Tag> tags = id.getTags().stream().filter(x -> !"scope".equals(x.getKey()))
                        .collect(Collectors.toList());
                // rename the metric
                return id.withName("my.metric.name").replaceTags(tags);
            }
            return id;
        }
    };
}

如果需要 MicroProfile Metrics API,请确保存在以下依赖项

pom.xml
<dependency>
    <groupId>org.eclipse.microprofile.metrics</groupId>
    <artifactId>microprofile-metrics-api</artifactId>
</dependency>
build.gradle
implementation("org.eclipse.microprofile.metrics:microprofile-metrics-api")
MP Metrics API 兼容性层将来可能会移动到其他扩展中。

管理接口

默认情况下,指标在主 HTTP 服务器上公开。

您可以通过在应用程序配置中设置 quarkus.management.enabled=true,在单独的网络接口和端口上公开它们。请注意,此属性是一个构建时属性。该值无法在运行时覆盖。

如果您在不自定义管理网络接口和端口的情况下启用管理接口,则指标将在以下位置公开:http://0.0.0.0:9000/q/metrics

您可以使用以下命令配置每种公开格式的路径

quarkus.micrometer.export.json.enabled=true (1)
quarkus.micrometer.export.json.path=metrics/json
quarkus.micrometer.export.prometheus.path=metrics/prometheus
1 启用 JSON 指标

使用此配置,JSON 指标将从 http://0.0.0.0:9000/q/metrics/json 获得。Prometheus 指标将从 http://0.0.0.0:9000/q/metrics/prometheus 获得。

有关更多信息,请参阅管理界面参考

配置参考

构建时固定的配置属性 - 所有其他配置属性都可以在运行时覆盖

配置属性

类型

默认

Micrometer 指标支持。

默认情况下启用 Micrometer 指标支持。

环境变量:QUARKUS_MICROMETER_ENABLED

显示更多

布尔值

true

Micrometer MeterRegistry 发现。

默认情况下将自动启用在类路径上发现的 Micrometer MeterRegistry 实现。

环境变量:QUARKUS_MICROMETER_REGISTRY_ENABLED_DEFAULT

显示更多

布尔值

true

Micrometer MeterBinder 发现。

默认情况下将自动启用在类路径上发现的 Micrometer MeterBinder 实现。

环境变量:QUARKUS_MICROMETER_BINDER_ENABLED_DEFAULT

显示更多

布尔值

true

出站 HTTP 请求指标支持。

如果启用了 Micrometer 支持,启用了 REST 客户端功能,并且此值为 true,或者此值未设置且 quarkus.micrometer.binder-enabled-default 为 true,则将启用对 HTTP 客户端指标的支持。

环境变量:QUARKUS_MICROMETER_BINDER_HTTP_CLIENT_ENABLED

显示更多

布尔值

入站 HTTP 指标支持。

如果启用了 Micrometer 支持,启用了提供 HTTP 流量的扩展,并且此值为 true,或者此值未设置且 quarkus.micrometer.binder-enabled-default 为 true,则将启用对 HTTP 服务器指标的支持。

环境变量:QUARKUS_MICROMETER_BINDER_HTTP_SERVER_ENABLED

显示更多

布尔值

Micrometer JVM 指标支持。

如果启用了 Micrometer 支持,并且此值为 true,或者此值未设置且 quarkus.micrometer.binder-enabled-default 为 true,则将启用对 JVM 指标的支持。

环境变量:QUARKUS_MICROMETER_BINDER_JVM

显示更多

布尔值

Kafka 指标支持。

如果启用了 Micrometer 支持,Kafka Consumer 或 Producer 接口位于类路径上,并且此值为 true,或者此值未设置且 quarkus.micrometer.binder-enabled-default 为 true,则将启用对 Kafka 指标的支持。

环境变量:QUARKUS_MICROMETER_BINDER_KAFKA_ENABLED

显示更多

布尔值

Redis 客户端指标支持。

如果启用了 Micrometer 支持,Quarkus Redis 客户端扩展位于类路径上,并且此值为 true,或者此值未设置且 quarkus.micrometer.binder-enabled-default 为 true,则将启用对 Redis 指标的支持。

环境变量:QUARKUS_MICROMETER_BINDER_REDIS_ENABLED

显示更多

布尔值

Stork 指标支持。

如果启用了 Micrometer 支持,并且类路径中存在 Quarkus Stork 扩展,并且此值为 true,或者此值未设置且 quarkus.micrometer.binder-enabled-default 为 true,则将启用 Stork 指标支持。

环境变量:QUARKUS_MICROMETER_BINDER_STORK_ENABLED

显示更多

布尔值

gRPC 服务器指标支持。

如果启用了 Micrometer 支持,并且类路径中存在 gRPC 服务器接口,并且此值为 true,或者此值未设置且 quarkus.micrometer.binder-enabled-default 为 true,则将启用 gRPC 服务器指标支持。

环境变量:QUARKUS_MICROMETER_BINDER_GRPC_SERVER_ENABLED

显示更多

布尔值

gRPC 客户端指标支持。

如果启用了 Micrometer 支持,并且类路径中存在 gRPC 客户端接口,并且此值为 true,或者此值未设置且 quarkus.micrometer.binder-enabled-default 为 true,则将启用 gRPC 客户端指标支持。

环境变量:QUARKUS_MICROMETER_BINDER_GRPC_CLIENT_ENABLED

显示更多

布尔值

Kafka 指标支持。

如果启用了 Micrometer 支持,并且类路径中存在 MessageObservationCollector 接口,并且此值为 true,或者此值未设置且 quarkus.micrometer.binder-enabled-default 为 true,则将启用响应式消息传递指标支持。

环境变量:QUARKUS_MICROMETER_BINDER_MESSAGING_ENABLED

显示更多

布尔值

Eclipse MicroProfile Metrics 支持。

如果启用了 Micrometer 支持并且存在 MicroProfile Metrics 依赖项,则将启用 MicroProfile Metrics 支持

<dependency>
  <groupId>org.eclipse.microprofile.metrics</groupId>
  <artifactId>microprofile-metrics-api</artifactId>
</dependency>

Micrometer 扩展目前提供了一个兼容层,支持 MP Metrics API,但指标名称和记录的值将有所不同。请注意,MP Metrics 兼容层将在未来迁移到另一个扩展。

环境变量:QUARKUS_MICROMETER_BINDER_MP_METRICS_ENABLED

显示更多

布尔值

虚拟线程指标支持。

如果启用了 Micrometer 支持,并且此值设置为 true(默认值),并且 JVM 支持虚拟线程(Java 21+),并且 quarkus.micrometer.binder-enabled-default 属性为 true,则将启用虚拟线程指标支持。

环境变量:QUARKUS_MICROMETER_BINDER_VIRTUAL_THREADS_ENABLED

显示更多

布尔值

要添加到指标的标签。默认为空。设置后,标签将作为以下形式传递:key1=value1,key2=value2

环境变量:QUARKUS_MICROMETER_BINDER_VIRTUAL_THREADS_TAGS

显示更多

字符串列表

Micrometer 系统指标支持。

如果启用了 Micrometer 支持,并且此值为 true,或者此值未设置且 quarkus.micrometer.binder-enabled-default 为 true,则将启用系统指标支持。

环境变量:QUARKUS_MICROMETER_BINDER_SYSTEM

显示更多

布尔值

Vert.x 指标支持。

如果启用了 Micrometer 支持,并且类路径中存在 Vert.x MetricsOptions,并且此值为 true,或者此值未设置且 quarkus.micrometer.binder-enabled-default 为 true,则将启用 Vert.x 指标支持。

环境变量:QUARKUS_MICROMETER_BINDER_VERTX_ENABLED

显示更多

布尔值

Netty 指标支持。

如果启用了 Micrometer 支持,并且类路径中存在 Netty 分配器类,并且此值为 true,或者此值未设置且 quarkus.micrometer.binder-enabled-default 为 true,则将启用 Netty 指标支持。

环境变量:QUARKUS_MICROMETER_BINDER_NETTY_ENABLED

显示更多

布尔值

支持导出为 JSON 格式。默认关闭。

环境变量:QUARKUS_MICROMETER_EXPORT_JSON_ENABLED

显示更多

布尔值

false

JSON 指标端点的路径。默认值为 metrics。默认情况下,此值将解析为相对于 ${quarkus.http.non-application-root-path} 的路径。如果启用了管理界面,则该值将被解析为相对于 ${quarkus.management.root-path} 的路径。

环境变量:QUARKUS_MICROMETER_EXPORT_JSON_PATH

显示更多

字符串

metrics

诸如最大值、百分位数和直方图计数之类的统计数据会随着时间的推移而衰减,以便更多地权衡最近的样本。样本被累积到这些统计数据中,存储在环形缓冲区中,这些环形缓冲区在过期后会旋转,而这个缓冲区长度就是在这里设置的。

环境变量:QUARKUS_MICROMETER_EXPORT_JSON_BUFFER_LENGTH

显示更多

整数

3

诸如最大值、百分位数和直方图计数之类的统计数据会随着时间的推移而衰减,以便更多地权衡最近的样本。样本被累积到这些统计数据中,存储在环形缓冲区中,这些环形缓冲区在过期后会旋转,而过期时间就是在这里设置的。

环境变量:QUARKUS_MICROMETER_EXPORT_JSON_EXPIRY

显示更多

Duration 

P3D

支持导出到 Prometheus。

如果启用了 Micrometer 支持,并且类路径中存在 PrometheusMeterRegistry,并且此值为 true,或者此值未设置且 quarkus.micrometer.registry-enabled-default 为 true,则将启用 Prometheus 支持。

环境变量:QUARKUS_MICROMETER_EXPORT_PROMETHEUS_ENABLED

显示更多

布尔值

prometheus 指标端点的路径(生成 text/plain)。默认值为 metrics,并解析为相对于非应用程序端点 (q) 的路径,例如 ${quarkus.http.root-path}/${quarkus.http.non-application-root-path}/metrics。如果指定了绝对路径 (/metrics),则 prometheus 端点将从配置的路径提供服务。

如果启用了管理界面,则该值将被解析为相对于 ${quarkus.management.root-path}(默认为 q)的路径,例如 http://${quarkus.management.host}:${quarkus.management.port}/${quarkus.management.root-path}/metrics。如果指定了绝对路径 (/metrics),则 prometheus 端点将从配置的路径提供服务,例如 http://${quarkus.management.host}:${quarkus.management.port}/metrics

环境变量:QUARKUS_MICROMETER_EXPORT_PROMETHEUS_PATH

显示更多

字符串

metrics

默认情况下,此扩展将创建一个 Prometheus MeterRegistry 实例。

使用此属性可以否决创建默认的 Prometheus MeterRegistry。

环境变量:QUARKUS_MICROMETER_EXPORT_PROMETHEUS_DEFAULT_REGISTRY

显示更多

布尔值

true

用于指定 http 指标中 uri 标签的正则表达式的逗号分隔列表。

Vertx Instrumentation 将尝试将参数化的资源路径 /item/123 转换为通用形式 /item/{id},以减少 uri 标签值的基数。

此处指定的模式将优先于那些计算出的值。

例如,如果在此列表中指定了 /item/\\\\d+=/item/custom/item/[0-9]+=/item/custom,则对匹配路径 (/item/123) 的请求将使用指定的替换值 (/item/custom) 作为 uri 标签的值。请注意,反斜杠必须双重转义为 \\\\

环境变量:QUARKUS_MICROMETER_BINDER_HTTP_SERVER_MATCH_PATTERNS

显示更多

字符串列表

定义应忽略(不测量)的 uri 路径的正则表达式的逗号分隔列表。

环境变量:QUARKUS_MICROMETER_BINDER_HTTP_SERVER_IGNORE_PATTERNS

显示更多

字符串列表

禁止从指标收集中获取非应用程序 uri。这将禁止使用 ${quarkus.http.root-path}/${quarkus.http.non-application-root-path} 的非应用程序端点的所有指标。

默认情况下启用禁止非应用程序 uri。

环境变量:QUARKUS_MICROMETER_BINDER_HTTP_SERVER_SUPPRESS_NON_APPLICATION_URIS

显示更多

布尔值

true

禁止从指标收集中获取未匹配模板的 4xx 错误。此配置的存在是为了限制调用方侧错误的基数爆炸。不适用于 404 错误。

默认情况下禁用禁止 4xx 错误。

环境变量:QUARKUS_MICROMETER_BINDER_HTTP_SERVER_SUPPRESS4XX_ERRORS

显示更多

布尔值

false

允许的最大唯一 URI 标签值数量。达到最大标签值数量后,过滤器会拒绝带有其他标签值的指标。

环境变量:QUARKUS_MICROMETER_BINDER_HTTP_SERVER_MAX_URI_TAGS

显示更多

整数

100

Prometheus 注册表配置属性。

Prometheus MeterRegistry 配置的属性源,请参阅 https://micrometer.io/docs/registry/prometheus

环境变量:QUARKUS_MICROMETER_EXPORT_PROMETHEUS__CONFIGURATION_PROPERTY_NAME_

显示更多

Map<String,String>

用于指定 http 指标中 uri 标签的正则表达式的逗号分隔列表。

出站 HTTP 客户端 Instrumentation 将尝试将参数化的资源路径 /item/123 转换为通用形式 /item/{id},以减少 uri 标签值的基数。

此处指定的模式将优先于那些计算出的值。

例如,如果在此列表中指定了 /item/\\\\d+=/item/custom/item/[0-9]+=/item/custom,则对匹配路径 (/item/123) 的请求将使用指定的替换值 (/item/custom) 作为 uri 标签的值。请注意,反斜杠必须双重转义为 \\\\

环境变量:QUARKUS_MICROMETER_BINDER_HTTP_CLIENT_MATCH_PATTERNS

显示更多

字符串列表

定义应忽略(不测量)的 uri 路径的正则表达式的逗号分隔列表。

环境变量:QUARKUS_MICROMETER_BINDER_HTTP_CLIENT_IGNORE_PATTERNS

显示更多

字符串列表

禁止从指标收集中获取未匹配模板的 4xx 错误。此配置的存在是为了限制调用方侧错误的基数爆炸。不适用于 404 错误。

默认情况下禁用禁止 4xx 错误。

环境变量:QUARKUS_MICROMETER_BINDER_HTTP_CLIENT_SUPPRESS4XX_ERRORS

显示更多

布尔值

false

允许的最大唯一 URI 标签值数量。达到最大标签值数量后,过滤器会拒绝带有其他标签值的指标。

环境变量:QUARKUS_MICROMETER_BINDER_HTTP_CLIENT_MAX_URI_TAGS

显示更多

整数

100

关于 Duration 格式

要编写持续时间值,请使用标准的 java.time.Duration 格式。有关更多信息,请参阅 Duration#parse() Java API 文档

您还可以使用简化的格式,以数字开头

  • 如果该值仅为一个数字,则表示以秒为单位的时间。

  • 如果该值是一个数字后跟 ms,则表示以毫秒为单位的时间。

在其他情况下,简化格式将被转换为 java.time.Duration 格式以进行解析

  • 如果该值是一个数字后跟 hms,则在其前面加上 PT

  • 如果该值是一个数字后跟 d,则在其前面加上 P

相关内容