在 Quarkus 应用程序中收集指标


Red Hat build of Quarkus 1.11

摘要

了解如何使用 Micrometer 和 Prometheus 在 Quarkus 中收集指标。

前言

作为应用程序开发人员,您可以使用 Micrometer 收集指标,以提高 Quarkus 应用程序的性能。

先决条件

  • 已安装 OpenJDK (JDK) 11,以及 JAVA_HOME 环境变量指定的 Java SDK 的位置。

    • 登录到红帽客户门户网站,从 Software Downloads 页面下载 Red Hat Open JDK 版本。
  • 已安装 Apache Maven 3.6.2 或更高版本。Maven 可从 Apache Maven 项目网站 获得。

对红帽文档提供反馈

我们非常感谢您对我们的技术内容提供反馈,并鼓励您告诉我们您的想法。如果您想添加评论,提供见解、纠正拼写错误甚至询问问题,您可以在文档中直接这样做。

注意

您必须有一个红帽帐户并登录到客户门户网站。

要从客户门户网站提交文档反馈,请执行以下操作:

  1. 选择 Multi-page HTML 格式。
  2. 点文档右上角的 反馈 按钮。
  3. 突出显示您要提供反馈的文本部分。
  4. 点高亮文本旁的添加反馈对话框。
  5. 在页面右侧的文本框中输入您的反馈,然后单击 Submit

每次提交反馈时,我们都会自动创建跟踪问题。打开在点 Submit 后显示的链接,并开始监视问题或添加更多注释。

感谢您的宝贵反馈。

使开源包含更多

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。我们从这四个术语开始:master、slave、黑名单和白名单。由于此项工作十分艰巨,这些更改将在即将推出的几个发行版本中逐步实施。有关更多详情,请参阅我们的首席技术官 Chris Wright 提供的消息

第 1 章 Quarkus 应用程序的指标集合

指标是应用程序的特定方面量量量,用于观察趋势和行为。单个测量会定期收集,每个观察到的数字值都由字符串键以及附加(可选)标签或标签标识。

这些键值对随后附加到时间序列中:一个数据点序列随着时间进行索引。捕获和分析指标可帮助您在升级前发现潜在的问题和异常问题,并导致更严重的问题。

注意

指标不能用于诊断或问题确定。视觉化工具聚合各个测量,以提供趋势的视觉化。您需要识别观察问题的原因的具体上下文在聚合指标数据中找不到;您需要更详细的 trace 或日志数据以确定问题或根本原因分析。

您可以使用 Micrometer 库或 SmallRye Metrics 规格来收集运行时和应用程序指标:

  • Micrometer 为已知的监控系统提供了一个简单的传真客户端。Quarkus 对 Prometheus 的 Micrometer 对,以帮助您监控和管理应用程序。
  • smallrye Metrics 是 MicroProfile Metrics 规范的实现,提供 Prometheus 兼容指标端点。

Micrometer 扩展是在 Quarkus 中收集应用程序和运行时指标的建议方法,并提供以下功能:

  • 维度指标 - 计时器、gauges、计数器、分发摘要和长期任务计时器的供应商中立接口,具有维度的监控系统,允许在其维度监控系统之间有效访问特定命名指标。
  • 预配置绑定 - 缓存开箱即用的检测、类加载程序、垃圾回收、处理器利用率、线程池和 HTTP 流量。其他扩展,如 hibernate-ormmongodb-client,在启用时自动提供额外的绑定。

第 2 章 在 Quarkus 应用程序中公开指标

使用 标题扩展在 Quarkus 1.11 中启用指标。启用后, 主题扩展收集的所有指标的实时值会使用 /q/metrics 端点来查看。默认情况下,此端点仅以纯文本方式响应。

流程

  1. 添加 quarkus-micrometer-registry-prometheus 扩展作为应用程序的依赖项:

    ./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-micrometer-registry-prometheus"

    此命令将以下依赖项添加到 pom.xml 中:

    pom.xml

    <dependency>
          <groupId>io.quarkus</groupId>
        <artifactId>quarkus-micrometer-registry-prometheus</artifactId>
    </dependency>

  2. 输入以下命令在终端显示收集的指标:

    curl http://localhost:8080/q/metrics
  3. (可选)要使用 Micrometer 扩展来启用 JSON 格式的指标集合,请将以下行添加到 src/main/resources/application.properties 文件中:

    quarkus.micrometer.export.json.enabled=true
  4. 保存对 application.properties 文件的更改。
  5. 使用以下命令以 JSON 格式查看指标:

    curl -i -H "Accept: application/json" -H "Content-Type: application/json"
    http://localhost:8080/q/metrics

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

Micrometer 提供了一个 API,允许您构建自己的自定义指标。监控系统支持的最常见的分段类型包括 Ggauges、计数器和总结。以下小节构建了一个示例端点,并使用这些基本测量类型观察端点行为。

要注册游戏,您需要对 MeterRegistry 的引用,该引用由 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;
    }
}

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

Micrometer 在唯一指标标识符和标签组合和特定分段实例之间维护内部映射。使用 寄存器计数器 或其他方法递增计数器或记录值不会创建温度的新实例,除非之前没有看到标识符和标签值的组合。

gauges

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

    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;
    }

使用 Prometheus 时,创建的 gauge 的值并在 Prometheus 端点被访问时观察到列表的大小。务必要注意,gaug 被抽样而不是设置,没有记录与 gauge 关联的值如何在测量之间有所变化。

Micrometer 为创建 gauges 提供了一些额外的机制。请注意,micrometer 不会创建对默认观察到的对象的强引用。根据 registry,micrometer 可以省略 gauges 来观察整个垃圾回收的对象,或使用 NaN (不是数字)作为观察到的值。

永远不会计算您可以计算的任何内容。gauges 可能比计数器更低。如果您要计算量(因为值始终递增),请使用计数器。

计数器

计数器用于测量仅增加的值。在以下示例中,您将计算测试数字的次数,以查看它是主数:

    @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;
    }

可能需要尝试向计数器添加标签或标签来指示要检查的值。请记住,指标名称(testPrimeNumber)和标签值的每个唯一组合都会生成唯一的时间序列。将未绑定的数据集用作标签值可能会导致"cardinality explosion",创建新时间序列的指数增加。

但是,可以添加一个标签来传递较少的信息。在以下示例中,进行了调整,计数器被移动以添加一些标签。

    @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;
    }

查看此计数器生成的数据,您可以告诉如何检查负数或数字数,或者一个数字数,等等。尝试以下序列,并在纯文本输出中查找 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

永不可以计算您可以花费时间或总结的时间。计数器仅记录一个计数,这可能是需要的。但是,如果您想要了解更多有关值变化的信息,计时器(当测量的基本单位为时间时),或者分布概述可能更为合适。

总结和时间

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;
        });
    }

Micrometer 在为这个计时器发出指标时会应用 Prometheus 约定。Prometheus 测量时间(以秒为单位)。Micrometer 将测量的持续时间转换为秒,并按惯例在指标名称中包含单元。在访问 prime 端点后,查看以下三个条目的纯文本输出: example_prime_number_test_seconds_count,example_prime_number_test_seconds_sum, 和 example_prime_number_test_seconds_max

# 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

计时器和发行版摘要都可以配置为发出其他统计信息,如直方图数据、预计算百分比或服务级别目标(SLO)边界。请注意,计数、总和直方数据可以在维度(或一系列实例内)中重新聚合,而预先计算的值则不能被重新计算。

第 4 章 HTTP 指标

Micrometer 扩展会自动扩展 HTTP 服务器请求的时间。按照计时器的 Prometheus 命名惯例,查找 http_server_requests_seconds_counthttp_server_requests_seconds_sumhttp_server_requests_seconds_max。为请求的 uri、HTTP 方法(GET、POST 等)、状态代码(200、302、404 等)和更常规的结果字段添加了维度标签。

# HELP http_server_requests_seconds
# TYPE http_server_requests_seconds summary
http_server_requests_seconds_count{env="test",method="GET",outcome="SUCCESS",registry="prometheus",status="200",uri="/example/prime/{number}",} 6.0
http_server_requests_seconds_sum{env="test",method="GET",outcome="SUCCESS",registry="prometheus",status="200",uri="/example/prime/{number}",} 0.007355093
http_server_requests_seconds_count{env="test",method="GET",outcome="SUCCESS",registry="prometheus",status="200",uri="/example/gauge/{number}",} 4.0
http_server_requests_seconds_sum{env="test",method="GET",outcome="SUCCESS",registry="prometheus",status="200",uri="/example/gauge/{number}",} 0.005035393
# HELP http_server_requests_seconds_max
# TYPE http_server_requests_seconds_max gauge
http_server_requests_seconds_max{env="test",method="GET",outcome="SUCCESS",registry="prometheus",status="200",uri="/example/prime/{number}",} 0.002110405
http_server_requests_seconds_max{env="test",method="GET",outcome="SUCCESS",registry="prometheus",status="200",uri="/example/gauge/{number}",} 0.00239441

忽略端点

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

URI 模板

Micrometer 扩展将在 代表以模板形式包含路径参数的 URI 时进行最佳工作。使用以上示例,对 http://localhost:8080/example/prime/7919 的请求应该显示为 http_server_requests_seconds 指标数据的属性,标签为 uri=/example/prime/{number}

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

第 5 章 可靠性指标

可靠性指标用于使用限定措施表达软件组件的可靠性。您使用的指标取决于应用可靠性指标的系统类型以及应用域的要求。从站点可靠性工程角度来说,需要专注于 Java 应用程序的一些关键指标。

失败的时间

平均故障时间(MTTF)是两个连续故障之间的时间间隔。您用于测量 MTTF 的时间单元取决于系统,还可由事务数量定义。对于具有大型事务的系统,MTTF 通常一致。

修复的时间

补救时间(MTTR)是跟踪导致失败和修复错误所花费的平均时间。

表示故障之间的时间

当您组合 MTTF 和 MTTR 指标时,结果等于 Mean Time Failure (MTBF)。时间测量是实时的,而不是 MTTF 中包含的执行时间。

失败的速度

失败率(ROCOF)是以单元时间间隔内发生的故障次数,并专注于经常发生、意外事件的可能性。

Demand 上的故障的可能性

在 Demand (POFOD)失败的可能性是系统在发出服务请求时失败的概率。POFOD 是安全关键系统以及偶尔需要服务的安全系统保护系统的重要措施。

Availabiity

可用性测量系统可在任意给定时间使用的可能性。您必须考虑修复时间和系统的重启时间。

第 6 章 与 OpenShift 集成

您可以使 Quarkus 应用程序能够将 Micrometer 指标库用于运行时和应用程序指标。Micrometer 在应用程序和第三方(如 Prometheus)之间表现上相似,它们嵌入在 OpenShift 中。Quarkus 与 OpenShift 的集成不仅可以公开自动启用的嵌入式指标,还可以公开作为应用程序注册的自定义指标。

有关配置各种指标的更多信息,请参阅 Quarkus Micrometer 社区指南

先决条件

  • 您可以访问 OpenShift CLI、4.6 或更高版本
  • 您有一个 OpenShift 实例

流程

完成以下说明并在 OpenShift 中使用嵌入式 Prometheus 来公开 Quarkus 应用程序的指标:

6.1. 在 OpenShift 中为用户定义的项目启用监控

在 Red Hat OpenShift Container Platform 4.6 或更高版本中,您可以为用户定义的项目以及默认平台监控启用监控。

先决条件

  • 有权访问 OpenShift CLI、4.6 或更高版本
  • 有一个 OpenShift 实例

流程

  1. 前往 为用户定义的项目启用监控,并按照如何启用用户定义的项目监控的具体说明进行操作。在概述中,您将在命名空间 openshift-monitoring中创建 ConfigMap

cluster-monitoring-config.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
    name: cluster-monitoring-config
    namespace: openshift-monitoring
data:
    config.yaml: |
    enableUserWorkload: true
注意

如果使用 OpenShift 4.5 或更早版本,请使用:

apiVersion: v1
kind: ConfigMap
metadata:
    name: cluster-monitoring-config
    namespace: openshift-monitoring
data:
    config.yaml: |
    techPreviewUserWorkload:
        enabled: true

完成为用户定义的项目启用监控的步骤后,OpenShift 会自动创建一个命名空间 openshift-user-workload-monitoring,在开始将 Quarkus 应用程序部署到 OpenShift 并在 OpenShift 中创建服务监控器时,将 进行部署。

6.2. 将 Quarkus 应用程序部署到 OpenShift

设置所需的基础架构后,您必须使用 Prometheus 启用 Micrometer。

先决条件

流程

  1. 实现 REST API:

    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-resteasy</artifactId>
    </dependency>
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-micrometer-registry-prometheus</artifactId>
    </dependency>
  2. 添加 micrometer registry facade:

    import javax.inject.Inject;
    import javax.ws.rs.GET;
    import javax.ws.rs.Path;
    
    import io.micrometer.core.instrument.MeterRegistry;
    
    @Path("/hello")
    public class GreetingsResource {
    
        @Inject
        MeterRegistry registry;
    
        @GET
        public String sayHello() {
            registry.counter("greeting_counter").increment();
    
            return "Hello!";
        }
    }

    这个 Micrometer facade 创建一个计数器,每次调用服务时都会递增。registry 帮助创建自定义指标或手动使用指标。您还可以按如下方式注解方法:

    @GET
    @Counted(value = "greeting_counter")
    public String sayHello() {
        return "Hello!";
    }
  3. 运行应用程序:

    mvn compile quarkus:dev
  4. 调用您的服务:

    curl http://localhost:8080/hello

    该服务应该返回 Hello!

  5. 浏览到 http://localhost:8080/q/metrics。您应该会看到带有计数 1.0 的 greeting_counter (您刚刚完成的一个):

    # HELP greeting_counter_total
    #TYPE greeting_counter_total counter
    greeting_counter_total 1.0
  6. 通过在 pom.xml 中输入扩展 quarkus-openshift,将 Quarkus 应用程序部署到 OpenShift 中:

    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-openshift</artifactId>
    </dependency>
  7. 在 OpenShift 中将应用程序部署到名为 my-project 的新创建的项目中:

    oc new-project my-project
    
    mvn clean package -Dquarkus.kubernetes.deploy=true -Dquarkus.openshift.expose=true -Dquarkus.openshift.labels.app-with-metrics=quarkus-app

app-with-metrics 在 OpenShift 项目中创建服务监控器

注意

如果您使用没有安全 SSL 的 OpenShift,您还需要将 -Dquarkus.kubernetes-client.trust-certs=true 附加到 Maven 命令。

6.3. 在 OpenShift 项目中创建服务监控器

Prometheus 使用拉取模型从应用程序获取指标,这意味着它会提取或监视端点来拉取指标。虽然前面的步骤开始在 OpenShift 实例中公开服务,但还没有在 Prometheus 中配置任何内容来提取您的服务。这就是需要服务监控器的原因。

服务监控器是一个自定义资源,您必须在运行服务的同一项目中创建它: my-project

流程

  1. 设置 service-monitor.yaml

    apiVersion: monitoring.coreos.com/v1
    kind: ServiceMonitor
    metadata:
      labels:
        k8s-app: prometheus-app-monitor
      name: prometheus-app-monitor
      namespace: my-project
    spec:
      endpoints:
      - interval: 30s
        targetPort: 8080
        scheme: http
      selector:
        matchLabels:
          app-with-metrics: 'quarkus-app'
  2. 应用您的 service-monitor.yaml :

    oc apply -f service-monitor.yaml

    此命令创建一个名为 prometheus-app-monitor 的服务监控器,它将选择带有标签 app-with-metrics: quarkus-app 的应用程序。此标签 在将 Quarkus 应用程序部署到 OpenShift 过程中添加。OpenShift 为标记为 app-with-metrics: quarkus-app 的所有服务调用端点 /metrics

  3. 使用您的服务监控器:

    1. 调用您的问候服务: curl http://quarkus-micrometer-my-project.ocp.host/hello。这会递增您的 greeting_counter_total 计数器。
    2. 要查看指标,请浏览 OpenShift 控制台并选择 Developer > Monitoring 视图。
    3. 选择 Metrics 选项卡。
    4. Custom Query 字段中,输入 greeting_counter_total

指标显示在 Custom Query 字段的下表中。

法律通告

Copyright © 2023 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.
Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

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

让开源更具包容性

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

關於紅帽

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

Theme

© 2026 Red Hat
返回顶部