第 3 章 Quarkus 应用程序的自定义指标


Micrometer 提供了一个 API,供您自行构建自定义指标。监控系统支持的最常见量表类型是量表、计数器和摘要。以下小节构建示例端点,并使用这些基本计量类型观察端点行为。

要注册计量,您需要对 MeterRegistry 的引用,该 registry 由 Micrometer 扩展进行配置和维护。MeterRegistry 可以注入应用程序,如下所示:

package org.acme.micrometer;

import io.micrometer.core.instrument.MeterRegistry;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

@Path("/")
@Produces("text/plain")
public class ExampleResource {

    private final MeterRegistry registry;

    ExampleResource(MeterRegistry registry) {
        this.registry = registry;
    }
}
Copy to Clipboard Toggle word wrap

Micrometer 有惯例,必须创建计量,并使用点来分隔网段(如 a.name. like. this )。然后 Micrometer 会将该名称转换为所选 registry 首选格式。Prometheus 使用下划线,这意味着前面的名称将显示为 a_name_like_ this,在 Prometheus 格式的指标输出中。

Micrometer 在唯一标识符和标记组合和特定计量实例之间维护内部映射。使用 注册计数器 或其他方法来递增计数器或记录值不会创建新的计量实例,除非之前未看到标识符和标签值的组合。

量表

测量值可以随时间增加或减少,如回车的速度。在监控缓存或集合的统计信息时,量表很有用。请考虑以下一个简单的示例,它可观察列表的大小:

    LinkedList<Long> list = new LinkedList<>();

    // Update the constructor to create the gauge
    ExampleResource(MeterRegistry registry) {
        this.registry = registry;
        registry.gaugeCollectionSize("example.list.size", Tags.empty(), list);
    }

    @GET
    @Path("gauge/{number}")
    public Long checkListSize(@PathParam("number") long number) {
        if (number == 2 || number % 2 == 0) {
            // add even numbers to the list
            list.add(number);
        } else {
            // remove items from the list for odd numbers
            try {
                number = list.removeFirst();
            } catch (NoSuchElementException nse) {
                number = 0;
            }
        }
        return number;
    }
Copy to Clipboard Toggle word wrap

使用 Prometheus 时,当访问 Prometheus 端点时,观察创建量表的值以及列表的大小。务必要注意,量表会被抽样,而不是设置 ; 与量表关联的值在测量之间可能会如何改变。

Micrometer 为创建量表提供了一些额外的机制。请注意,Micrometer 不会创建对它默认观察对象的强大引用。根据 registry,Micrometer 会省略量表,可观察已垃圾回收的对象或者将 NaN (而非数字)用作观察到的值。

永不计算可以计算的内容。量表的直接使用方式可能比计数器小。如果您测量什么值可以被计算(因为值始终递增),则改为使用计数器。

计数器

计数器用于测量仅增加的值。在以下示例中,您将计算测试次数以确定其是否为 prime 的次数:

    @GET
    @Path("prime/{number}")
    public String checkIfPrime(@PathParam("number") long number) {
        if (number < 1) {
            return "Only natural numbers can be prime numbers.";
        }
        if (number == 1 || number == 2 || number % 2 == 0) {
            return number + " is not prime.";
        }

        if ( testPrimeNumber(number) ) {
            return number + " is prime.";
        } else {
            return number + " is not prime.";
        }
    }

    protected boolean testPrimeNumber(long number) {
        // Count the number of times we test for a prime number
        registry.counter("example.prime.number").increment();
        for (int i = 3; i < Math.floor(Math.sqrt(number)) + 1; i = i + 2) {
            if (number % i == 0) {
                return false;
            }
        }
        return true;
    }
Copy to Clipboard Toggle word wrap

可能会在指示检查值的计数器中添加标签或标签到计数器中。请记住,每个指标名称(testPrimeNumber)和标签值组合都会生成唯一的时间序列。使用未绑定的一组数据作为标签值可导致"通配符性增长",在新时间序列创建时呈指数增加。

然而,可以添加一个标签来传达一些的更多信息。在以下示例中,进行了调整,计数器被移动来添加一个标签。

    @GET
    @Path("prime/{number}")
    public String checkIfPrime(@PathParam("number") long number) {
        if (number < 1) {
            registry.counter("example.prime.number", "type", "not-natural").increment();
            return "Only natural numbers can be prime numbers.";
        }
        if (number == 1 ) {
            registry.counter("example.prime.number", "type", "one").increment();
            return number + " is not prime.";
        }
        if (number == 2 || number % 2 == 0) {
            registry.counter("example.prime.number", "type", "even").increment();
            return number + " is not prime.";
        }

        if ( testPrimeNumber(number) ) {
            registry.counter("example.prime.number", "type", "prime").increment();
            return number + " is prime.";
        } else {
            registry.counter("example.prime.number", "type", "not-prime").increment();
            return number + " is not prime.";
        }
    }

    protected boolean testPrimeNumber(long number) {
        for (int i = 3; i < Math.floor(Math.sqrt(number)) + 1; i = i + 2) {
            if (number % i == 0) {
                return false;
            }
        }
        return true;
    }
Copy to Clipboard Toggle word wrap

查看由此计数器生成的数据,您可以确定检查负数字的频率,或者数字一或一个数字,等等。尝试以下序列,并在纯文本输出中查找 example_prime_number_total。请注意,当 Micrometer 将 Prometheus 命名规则应用到 example.prime.number 时,会添加 _total 后缀。

# If you did not leave quarkus running in dev mode, start it again:
./mvnw compile quarkus:dev

curl http://localhost:8080/example/prime/-1
curl http://localhost:8080/example/prime/0
curl http://localhost:8080/example/prime/1
curl http://localhost:8080/example/prime/2
curl http://localhost:8080/example/prime/3
curl http://localhost:8080/example/prime/15
curl http://localhost:8080/q/metrics
Copy to Clipboard Toggle word wrap

不得计算您可以时间或总结的内容。计数器仅记录一个计数,这可能是必需的。但是,如果您更好地了解值的改变方式,一个计时器(当基本测量单位是时),或者发布摘要可能更为合适。

概述和计时器

Micrometer 中的计时器和配送摘要非常相似。两者都允许您记录观察到的值,这将与其他记录值进行聚合,并作为总和存储。Micrometer 还递增计数器,以指示已记录的测量数,并在指定的时间间隔内跟踪观察到的值。

发行版摘要是通过调用 记录 方法以记录记录值的方式进行填充,而计时器则提供特定于时间和测量持续时间的额外功能。例如,我们可以使用一个计时器来测量使用 记录 方法之一总结调用供应商功能需要花费的时间长度:

    protected boolean testPrimeNumber(long number) {
        Timer timer = registry.timer("example.prime.number.test");
        return timer.record(() -> {
            for (int i = 3; i < Math.floor(Math.sqrt(number)) + 1; i = i + 2) {
                if (number % i == 0) {
                    return false;
                }
            }
            return true;
        });
    }
Copy to Clipboard Toggle word wrap

Micrometer 将在为这个计时器发送指标时应用 Prometheus 约定。Prometheus 以秒为单位测量时间。Micrometer 将测量的时间转换为秒,并在指标名称中包含单位(按约定)。访问 prime 端点几次后,查看以下三个条目的纯文本输出: example_prime_number_seconds_count、example_ prime_number_seconds_sum、example_prime_number_test_seconds_ sum.

# If you did not leave quarkus running in dev mode, start it again:
./mvnw compile quarkus:dev

curl http://localhost:8080/example/prime/256
curl http://localhost:8080/q/metrics
curl http://localhost:8080/example/prime/7919
curl http://localhost:8080/q/metrics
Copy to Clipboard Toggle word wrap

可以将计时器和配送摘要配置为发送其他统计信息,如直方数据、预计算百分比或服务级别目标(SLO)界限。请注意,计算、校验和以及直方数据可在度量(或在一系列实例之间或一系列实例之间)重新分配,而预先计算百分比的值。

Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2026 Red Hat
返回顶部