Instrument Java applications with OpenTelemetry Metrics
This guide shows how to instrument your Java application with OpenTelemetry and export the metrics to Dynatrace.
- To learn more about how Dynatrace works with OpenTelemetry, see Send data to Dynatrace with OpenTelemetry.
- To learn how to export traces to Dynatrace with OpenTelemetry, see Manually instrument Java applications with OpenTelemetry.
Overview
To monitor your Java application with OpenTelemetry
Instrument your application
Send the data to Dynatrace
Restart your application and verify the data in Dynatrace
Instrument your application
To instrument manually, add the following dependencies to your project, and add the code snippet below to your code.
- Set names for the meter and the instrument.
- Add a description and attributes to the instrument as you see fit.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-bom</artifactId>
<version>1.18.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk</artifactId>
</dependency>
</dependencies>
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.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader;
import io.opentelemetry.sdk.resources.Resource;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Optional;
import java.util.Properties;
private static LongCounter counter;
Resource serviceName = Optional.ofNullable(System.getenv("OTEL_SERVICE_NAME"))
.map(n -> Attributes.of(AttributeKey.stringKey("service.name"), n))
.map(Resource::create)
.orElseGet(Resource::empty);
Resource dtMetadata = Resource.empty();
for (String name : new String[] {"dt_metadata_e617c525669e072eebe3d0f08212e8f2.properties", "/var/lib/dynatrace/enrichment/dt_metadata.properties"}) {
try {
Properties props = new Properties();
props.load(name.startsWith("/var") ? new FileInputStream(name) : new FileInputStream(Files.readAllLines(Paths.get(name)).get(0)));
dtMetadata = dtMetadata.merge(Resource.create(props.entrySet().stream()
.collect(Attributes::builder, (b, e) -> b.put(e.getKey().toString(), e.getValue().toString()), (b1, b2) -> b1.putAll(b2.build()))
.build())
);
} catch (IOException e) {}
}
SdkMeterProvider meterProvider = SdkMeterProvider.builder()
.setResource(serviceName).setResource(dtMetadata)
.registerMetricReader(PeriodicMetricReader.builder(metricExporter).build()) //The metricExporter setup is explained in Step 2.
.build();
OpenTelemetry openTelemetry = OpenTelemetrySdk
.builder()
.setMeterProvider(meterProvider)
.buildAndRegisterGlobal();
Meter meter = openTelemetry
.meterBuilder("my-meter") //TODO Replace with the name of your meter
.setInstrumentationVersion("1.0.0")
.build();
counter = meter
.counterBuilder("my-counter") //TODO Replace with the name of your instrument
.setDescription("This is my counter.") //TODO Replace with a description of your instrument
.build();
Add the code below to any call you want to monitor. You can add attributes to each measurement as well. In this case, we used the counter instrument, which only supports non-negative increments. To find the instrument that fits your needs, see the official documentation.
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import java.util.Random;
Attributes attributes = Attributes
.of(AttributeKey.stringKey("my-key-1"), "my-value-1", //TODO Replace with your attributes
AttributeKey.stringKey("my-key-2"), Long.valueOf(new Random().nextInt(3)).toString());
counter.add(1, attributes);
Send data to Dynatrace
To send data to Dynatrace, you need to add the dependencies and add and configure the code snippet below in your Java application code.
Dynatrace version 1.254+
<dependencies>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>
</dependencies>
OtlpHttpMetricExporter metricExporter = OtlpHttpMetricExporter.builder()
.setEndpoint("<URL>") //TODO Replace <URL> to your SaaS/Managed-URL as mentioned in the next step
.addHeader("Authorization", "Api-Token <TOKEN>") //TODO Replace <TOKEN> with your API Token as mentioned in the next step
.setAggregationTemporalitySelector(AggregationTemporalitySelector.deltaPreferred())
.build();
To make sure your data arrives where it should be, you need to define the correct endpoint and token.
- To set the endpoint
- Use your Environment ID to set the endpoint to which your app will send traces as follows:
- Dynatrace SaaS
https://{your-environment-id}.live.dynatrace.com/api/v2/otlp/v1/metrics
- Dynatrace Managed
https://{your-domain}/e/{your-environment-id}/api/v2/otlp/v1/metrics
- Dynatrace ActiveGate
https://{your-activegate-endpoint}/e/{your-environment-id}/api/v2/otlp/v1/metrics
- You may need to include the port to your ActiveGate endpoint. For example:
https://{your-activegate-endpoint}:9999/e/{your-environment-id}/api/v2/otlp/v1/metrics
- If you are running a containerized ActiveGate, you need to use the FQDN of it. For example:
https://{your-activegate-service-name}.dynatrace.svc.cluster.local/e/{your-environment-id}/api/v2/otlp/v1/metrics
- You may need to include the port to your ActiveGate endpoint. For example:
- Dynatrace SaaS
- Replace
<URL>
in the code snippet above with your endpoint.
- Use your Environment ID to set the endpoint to which your app will send traces as follows:
- To create an authentication token
- In the Dynatrace menu, go to Access tokens and select Generate new token.
- Provide a Token name.
- In the Search scopes box, search for
Ingest metrics
(underAPI v2 scopes
), and select the checkbox. - Select Generate token.
- Select Copy to copy the token to your clipboard.
- Save the token in a safe place; you can't display it again.
- Replace
<TOKEN>
in the code snippet above with your token.
Dynatrace version 1.222+
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.github.Dynatrace-oss</groupId>
<artifactId>opentelemetry-metric-java</artifactId>
<version>v1.0.0</version>
</dependency>
<dependency>
<groupId>com.dynatrace.metric.util</groupId>
<artifactId>dynatrace-metric-utils-java</artifactId>
<version>1.6.0</version>
</dependency>
</dependencies>
import com.dynatrace.opentelemetry.metric.DynatraceMetricExporter;
DynatraceMetricExporter metricExporter = DynatraceMetricExporter.builder()
.setUrl("<URL>") //TODO Replace <URL> to your SaaS/Managed-URL as mentioned in the next step
.setApiToken("<TOKEN>") //TODO Replace <TOKEN> with your API Token as mentioned in the next step
.build();
If no OneAgent is available locally, you need to define the correct endpoint and token to make sure your data arrives where it should be.
- To set the endpoint
- Use your Environment ID to set the endpoint to which your app will send traces as follows:
- Dynatrace SaaS
https://{your-environment-id}.live.dynatrace.com/api/v2/metrics/ingest
- Dynatrace Managed
https://{your-domain}/e/{your-environment-id}/api/v2/metrics/ingest
- Dynatrace ActiveGate
https://{your-activegate-endpoint}/e/{your-environment-id}/api/v2/metrics/ingest
- You may need to include the port to your ActiveGate endpoint. For example:
https://{your-activegate-endpoint}:9999/e/{your-environment-id}/api/v2/metrics/ingest
- If you are running a containerized ActiveGate, you need to use the FQDN of it. For example:
https://{your-activegate-service-name}.dynatrace.svc.cluster.local/e/{your-environment-id}/api/v2/metrics/ingest
- You may need to include the port to your ActiveGate endpoint. For example:
- Dynatrace SaaS
- Replace
<URL>
in the code snippet above with your endpoint.
- Use your Environment ID to set the endpoint to which your app will send traces as follows:
- To create an authentication token
- In the Dynatrace menu, go to Access tokens and select Generate new token.
- Provide a Token name.
- In the Search scopes box, search for
Ingest metrics
(underAPI v2 scopes
), and select the checkbox. - Select Generate token.
- Select Copy to copy the token to your clipboard.
- Save the token in a safe place; you can't display it again.
- Replace
<TOKEN>
in the code snippet above with your token.
Verify that the metrics are ingested into Dynatrace
A few minutes after restarting your app, look for your metrics:
- In the Dynatrace menu, go to Metrics and filter for your metrics (by the names you have given them).
- To get more detailed information, or to filter for different criteria, expand Details for a metric and select Create chart.
If your application does not receive any traffic, there will be no metrics.