Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions doc-snippets/prometheus-migration/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
plugins {
id("java")
}

val moduleName by extra { "io.opentelemetry.examples.docs.prometheus.migration" }

dependencies {
implementation(platform("io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom:2.22.0"))

implementation("io.opentelemetry:opentelemetry-api")
implementation("io.opentelemetry:opentelemetry-sdk")
implementation("io.opentelemetry:opentelemetry-exporter-prometheus")
implementation("io.opentelemetry:opentelemetry-exporter-otlp")

implementation("io.prometheus:prometheus-metrics-core:1.3.1")
implementation("io.prometheus:prometheus-metrics-exporter-httpserver:1.3.1")
implementation("io.prometheus:prometheus-metrics-exporter-opentelemetry:1.3.1")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package otel;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.DoubleCounter;
import io.opentelemetry.api.metrics.Meter;

public class OtelCounter {
// Preallocate attribute keys and, when values are static, entire Attributes objects.
private static final AttributeKey<String> ZONE = AttributeKey.stringKey("zone");
private static final Attributes UPSTAIRS = Attributes.of(ZONE, "upstairs");
private static final Attributes DOWNSTAIRS = Attributes.of(ZONE, "downstairs");

public static void counterUsage(OpenTelemetry openTelemetry) {
Meter meter = openTelemetry.getMeter("smart.home");
// HVAC on-time is fractional — use ofDoubles() to get a DoubleCounter.
// No upfront label declaration: attributes are provided at record time.
DoubleCounter hvacOnTime =
meter
.counterBuilder("hvac.on")
.setDescription("Total time the HVAC system has been running")
.setUnit("s")
.ofDoubles()
.build();

hvacOnTime.add(127.5, UPSTAIRS);
hvacOnTime.add(3600.0, DOWNSTAIRS);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package otel;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.metrics.Meter;

public class OtelCounterCallback {
public static void counterCallbackUsage(OpenTelemetry openTelemetry) {
Meter meter = openTelemetry.getMeter("smart.home");
// The smart energy meter maintains its own cumulative joule total in firmware.
// Use an asynchronous counter to report that value when a MetricReader
// collects metrics, without maintaining a separate counter in application code.
meter
.counterBuilder("energy.consumed")
.setDescription("Total energy consumed")
.setUnit("J")
.ofDoubles()
.buildWithCallback(measurement -> measurement.record(SmartHomeDevices.totalEnergyJoules()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package otel;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.DoubleGauge;
import io.opentelemetry.api.metrics.Meter;

public class OtelGauge {
// Preallocate attribute keys and, when values are static, entire Attributes objects.
private static final AttributeKey<String> ZONE = AttributeKey.stringKey("zone");
private static final Attributes UPSTAIRS = Attributes.of(ZONE, "upstairs");
private static final Attributes DOWNSTAIRS = Attributes.of(ZONE, "downstairs");

public static void gaugeUsage(OpenTelemetry openTelemetry) {
Meter meter = openTelemetry.getMeter("smart.home");
DoubleGauge thermostatSetpoint =
meter
.gaugeBuilder("thermostat.setpoint")
.setDescription("Target temperature set on the thermostat")
.setUnit("Cel")
.build();

thermostatSetpoint.set(22.5, UPSTAIRS);
thermostatSetpoint.set(20.0, DOWNSTAIRS);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package otel;

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

public class OtelGaugeCallback {
private static final AttributeKey<String> ROOM = AttributeKey.stringKey("room");
private static final Attributes LIVING_ROOM = Attributes.of(ROOM, "living_room");
private static final Attributes BEDROOM = Attributes.of(ROOM, "bedroom");

public static void gaugeCallbackUsage(OpenTelemetry openTelemetry) {
Meter meter = openTelemetry.getMeter("smart.home");
// Temperature sensors maintain their own readings in firmware.
// Use an asynchronous gauge to report those values when a MetricReader
// collects metrics, without maintaining separate gauges in application code.
meter
.gaugeBuilder("room.temperature")
.setDescription("Current temperature in the room")
.setUnit("Cel")
.buildWithCallback(
measurement -> {
measurement.record(SmartHomeDevices.livingRoomTemperatureCelsius(), LIVING_ROOM);
measurement.record(SmartHomeDevices.bedroomTemperatureCelsius(), BEDROOM);
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package otel;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.DoubleHistogram;
import io.opentelemetry.api.metrics.Meter;
import java.util.List;

public class OtelHistogram {
// Preallocate attribute keys and, when values are static, entire Attributes objects.
private static final AttributeKey<String> DEVICE_TYPE = AttributeKey.stringKey("device_type");
private static final Attributes THERMOSTAT = Attributes.of(DEVICE_TYPE, "thermostat");
private static final Attributes LOCK = Attributes.of(DEVICE_TYPE, "lock");

public static void histogramUsage(OpenTelemetry openTelemetry) {
Meter meter = openTelemetry.getMeter("smart.home");
// setExplicitBucketBoundariesAdvice() sets default boundaries as a hint to the SDK.
// Views configured at the SDK level take precedence over this advice.
DoubleHistogram deviceCommandDuration =
meter
.histogramBuilder("device.command.duration")
.setDescription("Time to receive acknowledgment from a smart home device")
.setUnit("s")
.setExplicitBucketBoundariesAdvice(List.of(0.1, 0.25, 0.5, 1.0, 2.5, 5.0))
.build();

deviceCommandDuration.record(0.35, THERMOSTAT);
deviceCommandDuration.record(0.85, LOCK);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package otel;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.DoubleHistogram;
import io.opentelemetry.api.metrics.Meter;
import java.util.List;

public class OtelHistogramAsSummary {
private static final AttributeKey<String> DEVICE_TYPE = AttributeKey.stringKey("device_type");
private static final Attributes THERMOSTAT = Attributes.of(DEVICE_TYPE, "thermostat");
private static final Attributes LOCK = Attributes.of(DEVICE_TYPE, "lock");

public static void summaryReplacement(OpenTelemetry openTelemetry) {
Meter meter = openTelemetry.getMeter("smart.home");
// No explicit bucket boundaries: captures count and sum, a good stand-in for most
// Summary use cases. For quantile estimation, add boundaries that bracket your thresholds.
DoubleHistogram deviceCommandDuration =
meter
.histogramBuilder("device.command.duration")
.setDescription("Time to receive acknowledgment from a smart home device")
.setUnit("s")
.setExplicitBucketBoundariesAdvice(List.of())
.build();

deviceCommandDuration.record(0.35, THERMOSTAT);
deviceCommandDuration.record(0.85, LOCK);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package otel;

import io.opentelemetry.sdk.metrics.Aggregation;
import io.opentelemetry.sdk.metrics.InstrumentSelector;
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
import io.opentelemetry.sdk.metrics.View;
import java.util.List;

public class OtelHistogramExplicitBucketView {
static SdkMeterProvider createMeterProvider() {
// Override the bucket boundaries advised on the instrument for a specific histogram.
return SdkMeterProvider.builder()
.registerView(
InstrumentSelector.builder().setName("device.command.duration").build(),
View.builder()
.setAggregation(
Aggregation.explicitBucketHistogram(List.of(0.1, 0.25, 0.5, 1.0, 2.5, 5.0)))
.build())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package otel;

import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter;
import io.opentelemetry.sdk.metrics.Aggregation;
import io.opentelemetry.sdk.metrics.InstrumentType;
import io.opentelemetry.sdk.metrics.export.DefaultAggregationSelector;

public class OtelHistogramExponentialExporter {
static OtlpHttpMetricExporter createExporter() {
// Configure the exporter to use exponential histograms for all histogram instruments.
// This is the preferred approach — it applies globally without modifying instrumentation code.
return OtlpHttpMetricExporter.builder()
.setEndpoint("http://localhost:4318")
.setDefaultAggregationSelector(
DefaultAggregationSelector.getDefault()
.with(InstrumentType.HISTOGRAM, Aggregation.base2ExponentialBucketHistogram()))
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package otel;

import io.opentelemetry.sdk.metrics.Aggregation;
import io.opentelemetry.sdk.metrics.InstrumentSelector;
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
import io.opentelemetry.sdk.metrics.View;

public class OtelHistogramExponentialView {
static SdkMeterProvider createMeterProvider() {
// Use a view for per-instrument control — select a specific instrument by name
// to use exponential histograms while keeping explicit buckets for others.
return SdkMeterProvider.builder()
.registerView(
InstrumentSelector.builder().setName("device.command.duration").build(),
View.builder().setAggregation(Aggregation.base2ExponentialBucketHistogram()).build())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package otel;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.metrics.LongCounter;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader;
import java.time.Duration;

public class OtelOtlpInit {
public static void main(String[] args) throws InterruptedException {
// Configure the SDK: export metrics over OTLP/HTTP on a fixed interval.
OpenTelemetrySdk sdk =
OpenTelemetrySdk.builder()
.setMeterProvider(
SdkMeterProvider.builder()
.registerMetricReader(
PeriodicMetricReader.builder(
OtlpHttpMetricExporter.builder()
.setEndpoint("http://localhost:4318")
.build())
.setInterval(Duration.ofSeconds(60))
.build())
.build())
.build();
Runtime.getRuntime().addShutdownHook(new Thread(sdk::close));

// Instrumentation code uses the OpenTelemetry API type, not the SDK type directly.
OpenTelemetry openTelemetry = sdk;

Meter meter = openTelemetry.getMeter("smart.home");
LongCounter doorOpens =
meter
.counterBuilder("door.opens")
.setDescription("Total number of times a door has been opened")
.build();

doorOpens.add(1);

Thread.currentThread().join(); // sleep forever
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package otel;

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.exporter.prometheus.PrometheusHttpServer;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.metrics.SdkMeterProvider;

public class OtelScrapeInit {
// Preallocate attribute keys and, when values are static, entire Attributes objects.
private static final AttributeKey<String> DOOR = AttributeKey.stringKey("door");
private static final Attributes FRONT_DOOR = Attributes.of(DOOR, "front");

public static void main(String[] args) throws InterruptedException {
// Configure the SDK: register a Prometheus reader that serves /metrics.
OpenTelemetrySdk sdk =
OpenTelemetrySdk.builder()
.setMeterProvider(
SdkMeterProvider.builder()
.registerMetricReader(PrometheusHttpServer.builder().setPort(9464).build())
.build())
.build();
Runtime.getRuntime().addShutdownHook(new Thread(sdk::close));

// Instrumentation code uses the OpenTelemetry API type, not the SDK type directly.
OpenTelemetry openTelemetry = sdk;

// Metrics are served at http://localhost:9464/metrics.
Meter meter = openTelemetry.getMeter("smart.home");
LongCounter doorOpens =
meter
.counterBuilder("door.opens")
.setDescription("Total number of times a door has been opened")
.build();

doorOpens.add(1, FRONT_DOOR);

Thread.currentThread().join(); // sleep forever
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package otel;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.LongUpDownCounter;
import io.opentelemetry.api.metrics.Meter;

public class OtelUpDownCounter {
// Preallocate attribute keys and, when values are static, entire Attributes objects.
private static final AttributeKey<String> DEVICE_TYPE = AttributeKey.stringKey("device_type");
private static final Attributes THERMOSTAT = Attributes.of(DEVICE_TYPE, "thermostat");
private static final Attributes LOCK = Attributes.of(DEVICE_TYPE, "lock");

public static void upDownCounterUsage(OpenTelemetry openTelemetry) {
Meter meter = openTelemetry.getMeter("smart.home");
LongUpDownCounter devicesConnected =
meter
.upDownCounterBuilder("devices.connected")
.setDescription("Number of smart home devices currently connected")
.build();

// add() accepts positive and negative values.
devicesConnected.add(1, THERMOSTAT);
devicesConnected.add(1, THERMOSTAT);
devicesConnected.add(1, LOCK);
devicesConnected.add(-1, LOCK);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package otel;

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

public class OtelUpDownCounterCallback {
private static final AttributeKey<String> DEVICE_TYPE = AttributeKey.stringKey("device_type");
private static final Attributes THERMOSTAT = Attributes.of(DEVICE_TYPE, "thermostat");
private static final Attributes LOCK = Attributes.of(DEVICE_TYPE, "lock");

public static void upDownCounterCallbackUsage(OpenTelemetry openTelemetry) {
Meter meter = openTelemetry.getMeter("smart.home");
// The device manager maintains the count of connected devices.
// Use an asynchronous up-down counter to report that value when a MetricReader
// collects metrics.
meter
.upDownCounterBuilder("devices.connected")
.setDescription("Number of smart home devices currently connected")
.buildWithCallback(
measurement -> {
measurement.record(SmartHomeDevices.connectedDeviceCount("thermostat"), THERMOSTAT);
measurement.record(SmartHomeDevices.connectedDeviceCount("lock"), LOCK);
});
}
}
Loading
Loading