通过OpenTelemetry Java SDK自定义指标

ARMS提供了常见的应用监控指标,如果您需要自定义指标,可以引入OpenTelemetry Java SDK实现。本文介绍如何自定义指标并在Grafana中查询自定义指标。

前提条件

  • 已经成功接入ARMS应用监控,具体操作,请参见应用接入

  • ARMS探针版本为 4.5.0 及以上版本。

引入依赖

请先参考如下Maven代码引入OpenTelemetry Java SDK。更多信息,请参见OpenTelemetry官方文档

<dependencies>
    <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-api</artifactId>
    </dependency>
    <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-sdk-trace</artifactId>
    </dependency>
    <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-sdk</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>io.opentelemetry</groupId>
      <artifactId>opentelemetry-bom</artifactId>
      <version>1.23.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

自定义指标步骤

OpenTelemetry 当前支持的指标类型大体有以下四类,目前除了Histogram(直方图),其余类型ARMS都支持。

  • Counter(计数器) 用途:记录单调递增的累积值(只能增加,不能减少)。 示例:HTTP 请求总数、错误发生次数。

  • UpDownCounter(可增减计数器) 用途:记录可增减的非单调值(如当前活跃连接数)。 示例:并发请求数、队列中的任务数。

  • Histogram(直方图,暂不支持) 用途:记录值的分布(如延迟、响应大小),支持计算分位数。 示例:请求延迟分布(P90、P95)、文件上传大小。

  • Gauge(仪表) 用途:捕获某一时刻的瞬时值(如 CPU 使用率、内存占用)。 示例:系统温度、实时内存使用量。

步骤1:代码中增加自定义指标

下面的代码是一段抢购商品的简单示例代码,其中定义了两个指标:

  • product_seckill_count:抢购次数

  • product_current_stock:当前库存

其中在获取定义指标的工厂类 meter 时,传入了一个product_seckill参数,这个可以理解为一个分组的概念,后续通过该 meter 定义的指标都在该分组下,后续配置中会用到该分组。

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.LongCounter;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.api.metrics.ObservableLongGauge;

import javax.annotation.PreDestroy;
import java.util.concurrent.atomic.AtomicInteger;

class ProductService {

    // 静态库存计数器
    public final AtomicInteger stock = new AtomicInteger(0);

    private LongCounter seckillCounter;
    private ObservableLongGauge observableLongGauge;
    private final AttributeKey<String> seckillResult = AttributeKey.stringKey("seckill_result");

    public ProductService() {
        OpenTelemetry agentOpenTelemetry = GlobalOpenTelemetry.get();


        //定义指标工厂类,注意这里的product_seckill很重要
        Meter meter = agentOpenTelemetry.getMeter("product_seckill");
        //定义一个counter指标,用于记录商品抢购的次数
        seckillCounter = meter.counterBuilder("product_seckill_count")
                .setUnit("1")
                .setDescription("seckill product count")
                .build();

        //定义一个gauge指标,代表当前库存的商品数量
        observableLongGauge = meter.gaugeBuilder("product_current_stock").ofLongs().buildWithCallback((measurement -> {
            //记录当前商品数量
            measurement.record(stock.get());
        }));

    }
    
    @PreDestroy
    public void clear() {
        observableLongGauge.close(); 
    }
    
    public void setKillProductCount(int count) {
        stock.set(count);
    }

    public String seckillProduct() {
        int currentStock = stock.get();
        if (currentStock <= 0) {
            seckillCounter.add(1, Attributes.of(seckillResult, "failed"));
            return "抢购失败,商品已售罄";
        }
        // 尝试扣减库存
        if (stock.decrementAndGet() >= 0) {
            seckillCounter.add(1, Attributes.of(seckillResult, "success"));
            return "抢购成功,剩余库存:" + stock.get();
        } else {
            stock.incrementAndGet(); // 回滚
            seckillCounter.add(1, Attributes.of(seckillResult, "success"));
            return "抢购失败,商品已售罄";
        }
    }
}

步骤2:在控制台配置指标采集

在控制台修改自定义指标采集配置,新增上一步创建 meter 时填入的参数。

image.png

步骤3:查看指标并配置告警

  1. ARMS控制台Prometheus监控 > 实例列表页面顶部菜单栏选择应用接入的地域。

    实例类型为Prometheus for 应用监控的实例即为默认集成的应用监控实例。

    2024-10-29_11-56-55

  2. 单击右侧共享版进入 Grafana 页面,然后单击 Explore,选择数据源为上一步对应的 Prometheus 实例名称。

    2025-07-31_16-26-27

  3. 您可以通过 PromQL 简单查询在代码中定义的指标,如下图所示,也可以在 Grafana 中自定义展示大盘

    image

自此通过 OpenTelemetry SDK 定义的指标就已经成功上报并存储到 ARMS 服务端 Prometheus 存储实例中了,后续您可以对 Prometheus 存储实例中的指标创建告警规则

注意事项

  • 目前 ARMS 指标上报间隔为 15 秒一次。

  • 对于 Counter 类指标,ARMS 目前上报的不是累计值,而是一个上报周期内的增加值,即每 15 秒该指标的增加值。