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 时填入的参数。
该配置需探针4.5.0及以上版本方可生效,且无需重启应用。完成配置后,单击保存。
步骤3:查看指标并配置告警
-
在ARMS控制台的页面顶部菜单栏选择应用接入的地域。搜索 以
metricstore-apm-metrics-custom关键字开头的 Prometheus 存储实例,随后点击共享版前往 grafana。 -
进入 grafana 页面后,点击 explore,在数据源处选择上一步骤拿到的 prometheus 存储实例
进入对应的 Grafana 文件夹页面后,若该文件夹下尚无仪表盘,页面会提示
This folder doesn't have any dashboards yet,可单击 + Create Dashboard 创建仪表盘,或通过 Manage dashboards 将已有仪表盘移入该文件夹。 -
您可以通过 PromQL 简单查询在代码中定义的指标,如下图所示,也可以在 Grafana 中自定义展示大盘。

自此通过 OpenTelemetry SDK 定义的指标就已经成功上报并存储到 ARMS 服务端 Prometheus 存储实例中了,后续您可以对 Prometheus 存储实例中的指标创建告警规则。
注意事项
-
目前 ARMS 指标上报间隔为 15 秒一次。
-
对于 Counter 类指标,ARMS 目前上报的不是累计值,而是一个上报周期内的增加值,即每 15 秒该指标的增加值。