All Products
Search
Document Center

Application Real-Time Monitoring Service:Customize metrics using the OpenTelemetry Java SDK

Last Updated:Nov 17, 2025

ARMS provides common Application Monitoring metrics. You can import the OpenTelemetry Java SDK to customize metrics. This topic describes how to customize metrics and query them in Grafana.

Prerequisites

  • You have connected your application to ARMS Application Monitoring. For more information, see Application access.

  • The ARMS agent version is 4.5.0 or later.

Import dependencies

Import the OpenTelemetry Java SDK by adding the following Maven dependency. For more information, see the official OpenTelemetry document.

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

Steps to customize metrics

OpenTelemetry currently supports the following four types of metrics. ARMS supports all types except for Histogram.

  • CounterUsage: Records monotonically increasing cumulative values.Example: Total number of HTTP requests and number of faults.

  • UpDownCounterUsage: Records non-monotonic values that can increase or decrease, such as the number of active connections.Example: Number of concurrent requests and number of tasks in a queue.

  • Histogram (not supported)Usage: Records the distribution of values, such as latency and response size, and supports quantile calculation.Example: Request latency distribution (P90 and P95) and file upload size.

  • GaugeUsage: Captures an instantaneous value at a specific time, such as CPU utilization or memory usage.Example: System temperature and real-time memory usage.

Step 1: Add custom metrics to the code

The following code shows a simple flash sale example that defines two metrics:

  • product_seckill_count: The number of flash sale attempts.

  • product_current_stock: The current inventory.

When you retrieve the meter, which is a factory class for defining metrics, you pass in a parameter named product_seckill. This parameter acts as a group name. All metrics defined by this meter belong to this group. This group name is used in subsequent configurations.

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 {

    // Static inventory counter
    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();


        // Define the metric factory class. Note that product_seckill is important.
        Meter meter = agentOpenTelemetry.getMeter("product_seckill");
        // Define a counter metric to record the number of flash sale attempts.
        seckillCounter = meter.counterBuilder("product_seckill_count")
                .setUnit("1")
                .setDescription("seckill product count")
                .build();

        // Define a gauge metric to represent the current inventory of the product.
        observableLongGauge = meter.gaugeBuilder("product_current_stock").ofLongs().buildWithCallback((measurement -> {
            // Record the current product quantity.
            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 "Flash sale failed. The product is sold out.";
        }
        // Try to deduct the inventory.
        if (stock.decrementAndGet() >= 0) {
            seckillCounter.add(1, Attributes.of(seckillResult, "success"));
            return "Flash sale successful. Remaining inventory: " + stock.get();
        } else {
            stock.incrementAndGet(); // Rollback
            seckillCounter.add(1, Attributes.of(seckillResult, "success"));
            return "Flash sale failed. The product is sold out.";
        }
    }
}

Step 2: Configure metric collection in the console

In the console, modify the Custom Metric Collection Configuration and add the parameter that you used to create the meter in the previous step.

image.png

Step 3: View metrics and configure alerts

  1. In the top menu bar of the Managed Service for Prometheus > Instances page in the ARMS console, select the region where your application is deployed.

    The instance with the type Prometheus Instance for Application Monitoring is the default Application Monitoring instance.

    2024-10-29_11-56-55

  2. Click Shared Edition to open the Grafana page. Click Explore and select the Prometheus instance from the previous step as the data source.

    2025-07-31_16-26-27

  3. You can use Prometheus Query Language (PromQL) to query the metrics that you defined in the code, as shown in the following figure. You can also Create a custom Grafana dashboard in Grafana.

    image

At this point, the metrics that you defined using the OpenTelemetry SDK are reported to and stored in the Prometheus instance in ARMS. You can then create alert rules for these metrics.

Notes

  • ARMS reports metrics at a 15-second interval.

  • For Counter metrics, ARMS reports the increment within each reporting epoch, not the cumulative value. This means that ARMS reports the increase in the metric's value every 15 seconds.