Observability - OpenTelemetry Java
Intro to OpenTelemetry Java
- OpenTelemetry Java is the set of OpenTelemetry observability tools for the Java ecosystem.
- At a high level, it consists of the API, the SDK, and instrumentation.
Overview
The API is a set of classes and interfaces for recording telemetry across key observability signals.
It supports multiple implementations, with a low-overhead minimalist Noop and SDK reference implementation provided out of the box.
It is designed to be taken as a direct dependency by libraries, frameworks, and application owners looking to add instrumentation.
It comes with strong backwards compatibility guarantees, zero transitive dependencies, and supports Java 8+.
The SDK is the built-in reference implementation of the API, processing and exporting telemetry produced by instrumentation API calls.
Configuring the SDK to process and export appropriately is an essential step to integrating OpenTelemetry into an application.
The SDK has autoconfiguration and programmatic configuration options.
Instrumentation records telemetry using the API.
- There are a variety of categories of instrumentation
- including: zero-code Java agent, zero-code Spring Boot starter, library, native, manual, and shims.
Navigating the docs
The OpenTelemetry Java documentation is organized as follows
- Getting Started by Example
- A quick example to get off the ground running with OpenTelemetry Java
- demonstrating integration of the OpenTelemetry Java agent into a simple web application.
- Instrumentation ecosystem
- A guide to the OpenTelemetry Java instrumentation ecosystem.
- This is a key resource for application authors looking to integrate OpenTelemetry Java into applications.
- Learn about the different categories of instrumentation, and decide which is right for you.
- zero-code Java agent, zero-code Spring Boot starter, library, native, manual, and shims.
- Record Telemetry with API
- A technical reference for the OpenTelemetry API, exploring all key aspects of the API with working code examples.
- Most users will use this page like an encyclopedia, consulting the index of sections as needed, rather than reading front to back.
- Manage Telemetry with SDK
- A technical reference for the OpenTelemetry SDK
- exploring all SDK plugin extension points and the programmatic configuration API with working code examples.
- Most users will use this page like an encyclopedia, consulting the index of sections as needed, rather than reading front to back.
- A technical reference for the OpenTelemetry SDK
- Configure the SDK
- A technical reference for configuring the SDK, focussing on zero-code autoconfiguration.
- Includes a reference of all supported environment variables and system properties for configuring the SDK.
- Explores all programmatic customization points with working code examples.
- Most users will use this page like an encyclopedia, consulting the index of sections as needed, rather than reading front to back.
Repositories
Repository | Description |
---|---|
opentelemetry-java | Core API and SDK components |
opentelemetry-java-instrumentation | Instrumentation maintained by OpenTelemetry, including OpenTelemetry Java agent |
opentelemetry-java-contrib | Community maintained components that don’t fit the express scope of other repositories |
semantic-conventions-java | Generated code for semantic conventions |
opentelemetry-proto-java | Generated bindings for OTLP |
opentelemetry-java-examples | End-to-end code examples demonstrating a variety of patterns using the API, SDK, and instrumentation |
- opentelemetry-java, opentelemetry-java-instrumentation, and opentelemetry-java-contrib each publish large catalogs of artifacts.
- Please consult repositories for details
- or see the “Managed Dependencies” column in the Bill of Materials table to see a full list of managed dependencies.
- As a general rule, artifacts published from the same repository have the same version.
- The exception to this is opentelemetry-java-contrib
- which can be thought of as a group of independent projects that are co-located in the same repository to take advantage of shared tooling.
- For now, the artifacts of opentelemetry-java-contrib are aligned but this is a coincidence and will change in the future.
- The exception to this is opentelemetry-java-contrib
- The repositories have a release cadence which mirrors their high level dependency structure
- opentelemetry-java is the core and releases first each month.
- opentelemetry-java-instrumentation depends on opentelemetry-java and is next to publish.
- opentelemetry-java-contrib depends on opentelemetry-java-instrumentation and opentelemetry-java and is last to publish.
- Although semantic-conventions-java is a dependency of opentelemetry-java-instrumentation
- it is an independent artifact with an independent release schedule.
Dependencies and BOMs
- A bill of materials, or BOM for short, is an artifact that helps keep the versions of related dependencies aligned.
- OpenTelemetry Java publishes several BOMs catering to different use cases, listed below in order of increasing scope.
- We highly recommend using a BOM.
Because the BOMs are hierarchical, adding dependencies on multiple BOMs is not recommended
as it is redundant and can lead unintuitive dependency version resolution.
Description | Repository | Group ID/Artifact ID |
---|---|---|
Stable core API and SDK artifacts | opentelemetry-java | io.opentelemetry opentelemetry-bom |
Experimental core API and SDK artifacts including all of opentelemetry-bom |
opentelemetry-java | io.opentelemetry opentelemetry-bom-alpha |
Stable instrumentation artifacts including all of opentelemetry-bom |
opentelemetry-java-instrumentation | io.opentelemetry.instrumentation opentelemetry-instrumentation-bom |
Experimental instrumentation artifacts including all of opentelemetry-instrumentation-bom |
opentelemetry-java-instrumentation | io.opentelemetry.instrumentation opentelemetry-instrumentation-bom-alpha |
The following code snippet demonstrates adding a BOM dependency
1 | <project> |
Getting Started by Example
Example Application
Dependencies
- To begin, set up an environment in a new directory called java-simple.
- Within that directory, create a file called build.gradle.kts with the following content:
Create and launch an HTTP Server
In that same folder, create a file called DiceApplication.java and add the following code to the file:
1 | package otel; |
Create another file called RollController.java and add the following code to the file:
1 | package otel; |
Build and run the application with the following command, then open http://localhost:8080/rolldice in your web browser to ensure it is working.
1 | $ curl -v 'http://localhost:8080/rolldice' |
Instrumentation
Next, you’ll use a Java agent to automatically instrument the application at launch time.
While you can configure the Java agent in a number of ways, the steps below use environment variables.
- Download opentelemetry-javaagent.jar from Releases of the opentelemetry-java-instrumentation repository.
- The JAR file contains the agent and all automatic instrumentation packages.
1 | curl -L -O https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar |
Set and export variables that specify the Java agent JAR and a console exporter, using a notation suitable for your shell/terminal environment
1 | $ export JAVA_TOOL_OPTIONS="-javaagent:PATH/TO/opentelemetry-javaagent.jar" \ |
Run your application once again
From another terminal, send a request using curl:
You should have seen trace & log output from the server
1 | $ curl localhost:8080/rolldice |
Stop the server process.
When stopping the server, you should see an output of all the metrics collected
Instrumentation ecosystem
- Instrumentation records telemetry using the API.
- The SDK is the built-in reference implementation of the API
- and is configured to process and export the telemetry produced by instrumentation API calls.
- This page discusses the OpenTelemetry ecosystem in OpenTelemetry Java, including resources for end users and cross-cutting instrumentation topics:
Topic | Desc |
---|---|
Instrumentation categories | addressing different use cases and installation patterns |
Context propagation | provides correlation between traces, metrics, and logs, allowing the signals to complement each other. |
Semantic conventions | define how to produce telemetry for standard operations |
Log instrumentation | which is used to get logs from an existing Java logging framework into OpenTelemetry |
Instrumentation categories
There are several categories of instrumentation
Instrumentation | Desc |
---|---|
Zero-code: Java agent | is a form of zero-code instrumentation that dynamically manipulates application bytecode. |
Zero-code: Spring Boot starter | is a form of zero-code instrumentation that leverages spring autoconfigure to install library instrumentation. |
Library instrumentation | wraps or uses extension points to instrument a library, requiring users to install and/or adapt library usage. |
Native instrumentation | is built directly into libraries and frameworks. |
Manual instrumentation | is written by application authors, and typically specific to the application domain. |
Shims | bridge data from one observability library to another, typically from some library into OpenTelemetry. |
- Zero-code instrumentation is installed automatically based on detected libraries / frameworks.
- The opentelemetry-java-instrumentation project contains the source code for Java agent, Spring Boot starter, and Library instrumentation.
Zero-code: Java agent
- The Java agent is a form of zero-code automatic instrumentation that dynamically manipulates application bytecode.
- For a list of libraries instrumented by the Java agent, see the “Auto-instrumented versions” column on supported libraries.
Zero-code: Spring Boot starter
- The Spring Boot starter is a form of zero-code automatic instrumentation that leverages spring autoconfigure to install library instrumentation.
Library instrumentation
- Library instrumentation wraps or uses extension points to instrument a library, requiring users to install and/or adapt library usage.
- https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/supported-libraries.md
Native instrumentation
- Native instrumentation is built directly into libraries or frameworks.
- OpenTelemetry encourages library authors to add native instrumentation using the API.
- In the long term, we hope the native instrumentation becomes the norm
- and view the instrumentation maintained by OpenTelemetry in opentelemetry-java-instrumentation as a temporary means of filling the gap.
- Elasticsearch Java API Client + Quarkus
Manual instrumentation
- Manual instrumentation is written by application authors, and typically specific to the application domain.
Shims
- A shim is instrumentation that bridges data from one observability library to another, typically from some library into OpenTelemetry.
- Shims maintained in the OpenTelemetry Java ecosystem:
Description | Signal(s) | Artifact |
---|---|---|
Bridge OpenTracing into OpenTelemetry | Traces | io.opentelemetry opentelemetry-opentracing-shim |
Bridge Opencensus into OpenTelemetry | Traces, Metrics | io.opentelemetry opentelemetry-opencensus-shim |
Bridge Micrometer into OpenTelemetry | Metrics | io.opentelemetry.instrumentation opentelemetry-micrometer-1.5 |
Bridge JMX into OpenTelemetry | Metrics | io.opentelemetry.instrumentation opentelemetry-jmx-metrics |
Bridge OpenTelemetry into Prometheus Java client | Metrics | io.opentelemetry.contrib opentelemetry-prometheus-client-bridge |
Bridge OpenTelemetry into Micrometer | Metrics | io.opentelemetry.contrib opentelemetry-micrometer-meter-provider |
Bridge Log4j into OpenTelemetry | Logs | io.opentelemetry.instrumentation opentelemetry-log4j-appender-2.17 |
Bridge Logback into OpenTelemetry | Logs | io.opentelemetry.instrumentation opentelemetry-logback-appender-1.0 |
Bridge OpenTelemetry context into Log4j | Context | io.opentelemetry.instrumentation opentelemetry-log4j-context-data-2.17-autoconfigure |
Bridge OpenTelemetry context into Logback | Context | io.opentelemetry.instrumentation opentelemetry-logback-mdc-1.0 |
Context propagation
- The OpenTelemetry APIs are designed to be complementary, with the whole greater than the sum of the parts.
- Each signal has its own strengths, and collectively stitch together a compelling observability story.
- Importantly, the data from the various signals are linked together through trace context:
- Spans are related to other spans through span parent and links, which each record trace context of related spans.
- Metrics are related to spans through exemplars, which record trace context of a particular measurement.
- Logs are related to spans by recording trace context on log records.
- For this correlation to work
- trace context must be propagated throughout an application (across function calls and threads), and across application boundaries.
- The context API facilitates this.
- Instrumentation needs to be written in a manner which is context aware:
- Libraries that represent the entry point to an application (i.e. HTTP servers, message consumers, etc.)
- should extract context from incoming messages.
- Libraries that represent an exit point from an application (i.e. HTTP clients, message producers, etc.)
- should inject context into outgoing messages.
- Libraries should implicitly or explicitly pass Context through the callstack and across any threads.
- Libraries that represent the entry point to an application (i.e. HTTP servers, message consumers, etc.)
Semantic conventions
- The semantic conventions define how to produce telemetry for standard operations.
- Semantic conventions specify span names, span kinds, metric instruments, metric units, metric types, and attribute key, value, and requirement levels.
- When writing instrumentation, consult the semantic conventions and conform to any which are applicable to the domain.
- OpenTelemetry Java publishes artifacts to assist in conforming to the semantic conventions
- including generated constants for attribute keys and values.
Log instrumentation
- While the LoggerProvider / Logger APIs are structurally similar to the equivalent trace and metric APIs, they serve a different use case.
- As of now, LoggerProvider / Logger and associated classes represent the Log Bridge API
- which exists to write log appenders to bridge logs recorded through other log APIs / frameworks into OpenTelemetry.
- They are not intended for end user use as a replacement for Log4j / SLF4J / Logback / etc.
- There are two typical workflows for consuming log instrumentation in OpenTelemetry catering to different application requirements:
Direct to collector
- In the direct to collector workflow, logs are emitted directly from an application to a collector using a network protocol (e.g. OTLP).
- This workflow is simple to set up as it doesn’t require any additional log forwarding components
- and allows an application to easily emit structured logs that conform to the log data model.
- However, the overhead required for applications to queue and export logs to a network location may not be suitable for all applications.
- To use this workflow:
- Install appropriate log appender.
- Configure the OpenTelemetry Log SDK to export log records to desired target destination (the collector or other)
- Log appenders are a type of shim which bridges logs from a log framework into the OpenTelemetry log SDK.
- See “Bridge Log4j into OpenTelemetry”, “Bridge Logback into OpenTelemetry” entries.
Via file or stdout
- In the file or stdout workflow, logs are written to files or standout output.
- Another component (e.g. FluentBit) is responsible for reading / tailing the logs
- parsing them to more structured format, and forwarding them a target, such as the collector.
- This workflow may be preferable in situations where application requirements do not permit additional overhead from direct to collector.
- However, it requires that all log fields required down stream are encoded into the logs
- and that the component reading the logs parse the data into the log data model.
- Log correlation with traces is available by installing a shim to bridge OpenTelemetry context into the log framework.
- See “Bridge OpenTelemetry context into Log4j”, “Bridge OpenTelemetry context into Logback” entries.
Record Telemetry with API
- The API is a set of classes and interfaces for recording telemetry across key observability signals.
- The SDK is the built-in reference implementation of the API, configured to process and export telemetry.
The API consists of the following top-level components
Components | Desc |
---|---|
Context | A standalone API for propagating context throughout an application and across application boundaries, including trace context and baggage. |
TracerProvider | The API entry point for traces |
MeterProvider | The API entry point for metrics |
LoggerProvider | The API entry point for logs |
OpenTelemetry | A holder for top-level API components (i.e. TracerProvider, MeterProvider, LoggerProvider, ContextPropagators) which is convenient to pass to instrumentation. |
The API is designed to support multiple implementations. Two implementations are provided by OpenTelemetry:
Implementations | Desc |
---|---|
SDK reference implementation | This is the right choice for most users. |
Noop implementation | A minimalist, zero-dependency implementation for instrumentations to use by default when the user doesn’t install an instance. |
- The API is designed to be taken as a direct dependency by libraries, frameworks, and application owners.
- It comes with strong backwards compatibility guarantees, zero transitive dependencies, and supports Java 8+
- Libraries and frameworks should depend only on the API and only call methods from the API
- and instruct applications / end users to add a dependency on the SDK and install a configured instance.
Context API
- The io.opentelemetry:opentelemetry-api-context:1.54.1 artifact contains standalone APIs (i.e. packaged separately from OpenTelemetry API)
- for propagating context throughout an application and across application boundaries.
- The io.opentelemetry:opentelemetry-extension-kotlint:1.54.1 is an extension with tools for propagating context into coroutines.
- It consists of:
Components | Desc |
---|---|
Context | An immutable bundle of key value pairs which is implicitly or explicitly propagated through an application. |
ContextStorage | A mechanism for storing and retrieving the current context, defaulting to thread local. |
ContextPropagators | A container of registered propagators for propagating Context across application boundaries. |
Context
- Context is an immutable bundle of key value pairs, with utilities for implicitly propagating through an application and across threads.
- Implicit propagation means that the context can be accessed without explicitly passing it as an argument.
- Context is a recurring concept in the OpenTelemetry API:
- The current active Span is stored in context, and by default a span’s parent is assigned to whatever span is currently in context.
- The measurements recorded to metric instruments accept a context argument
- used to link measurements to spans via exemplars and defaulting to whatever span is currently in context.
- LogRecords accept a context argument, used to link log record spans and defaulting to whatever span is currently in context.
The following code snippet explores Context API usage:
1 | package otel; |
- Context instances can be explicitly passed around application code
- but it’s more convenient to use implicit context, calling Context.makeCurrent() and accessing via Context.current().
- Context provides a number of utilities for implicit context propagation.
- These utilities wrap utility classes like
- Scheduler, ExecutorService, ScheduledExecutorService, Runnable, Callable, Consumer, Supplier, Function, etc
- and modify their behavior to call Context.makeCurrent() before running.
ContextStorage
- ContextStorage is a mechanism for storing and retrieving the current Context.
- The default ContextStorage implementation stores Context in thread local.
ContextPropagators
- ContextPropagators is a container of registered propagators for propagating Context across application boundaries.
- Context is injected into a carrier when leaving an application (i.e. an outbound HTTP request)
- and extracted from a carrier when entering an application (i.e. serving an HTTP request).
- See SDK TextMapPropagators for propagator implementations.
The following code snippet explores ContextPropagators API for extraction:
1 | package otel; |
The following code snippet explores ContextPropagators API for injection:
1 | package otel; |
OpenTelemetry API
- The io.opentelemetry:opentelemetry-api:1.54.1 artifact contains the OpenTelemetry API
- including traces, metrics, logs, noop implementation, baggage, key TextMapPropagator implementations, and a dependency on the context API.
Providers and Scopes
- Providers and scopes are recurring concepts in the OpenTelemetry API.
- A scope is a logical unit within the application which telemetry is associated with.
- A provider provides components for recording telemetry relative to a particular scope:
- TracerProvider provides scoped Tracers for recording spans.
- MeterProvider provides scoped Meters for recording metrics.
- LoggerProvider provides scoped Loggers for recording logs.
Log
- While the LoggerProvider / Logger APIs are structurally similar to the equivalent trace and metric APIs, they serve a different use case.
- As of now, LoggerProvider / Logger and associated classes represent the Log Bridge API
- which exists to write log appenders to bridge logs recorded through other log APIs / frameworks into OpenTelemetry.
- They are not intended for end user use as a replacement for Log4j / SLF4J / Logback / etc.
scope
- A scope is identified by the triplet (name, version, schemaUrl).
- Care must be taken to ensure the scope identity is unique.
- A typical approach is to set the scope name to the package name or fully qualified class name, and to set the scope version to the library version.
- If emitting telemetry for multiple signals (i.e. metrics and traces), the same scope should be used.
The following code snippet explores provider and scope API usage:
1 | package otel; |
Attributes
- Attributes is a bundle of key value pairs representing the standard attribute definition.
- Attributes are a recurring concept in the OpenTelemetry API:
- Spans, span events, and span links have attributes.
- The measurements recorded to metric instruments have attributes.
- LogRecords have attributes.
The following code snippet explores Attributes API usage:
1 | package otel; |
OpenTelemetry
Spring Boot Starter
- The Spring Boot starter is a special case where OpenTelemetry is available as a Spring bean.
- Simply inject OpenTelemetry into your Spring components.
- Extending the Spring Boot starter with custom manual instrumentation.
OpenTelemetry is a holder for top-level API components which is convenient to pass to instrumentation. OpenTelemetry consists of
Components | Desc |
---|---|
TracerProvider | The API entry point for traces. |
MeterProvider | The API entry point for metrics. |
LoggerProvider | The API entry point for logs. |
ContextPropagators | The API entry point for context propagation. |
The following code snippet explores OpenTelemetry API usage:
1 | package otel; |
GlobalOpenTelemetry
Java agent
- The Java agent is a special case where GlobalOpenTelemetry is set by the agent.
- Simply call GlobalOpenTelemetry.get() to access the OpenTelemetry instance.
- Extending the Java agent with custom manual instrumentation
GlobalOpenTelemetry
- GlobalOpenTelemetry holds a global singleton OpenTelemetry instance.
- Instrumentation should avoid using GlobalOpenTelemetry.
- Instead, accept OpenTelemetry as an initialization argument and default to the Noop implementation if not set.
- There is an exception to this rule: the OpenTelemetry instance installed by the Java agent is available via GlobalOpenTelemetry.
- Users with additional manual instrumentation are encouraged to access it via GlobalOpenTelemetry.get().
- GlobalOpenTelemetry.get() is guaranteed to always return the same result.
- If GlobalOpenTelemetry.get() is called before GlobalOpenTelemetry.set(..)
- GlobalOpenTelemetry is set to the noop implementation and future calls to GlobalOpenTelemetry.set(..) throw an exception.
- Therefore, it’s critical to call GlobalOpenTelemetry.set(..) as early in the application lifecycle as possible
- and before GlobalOpenTelemetry.get() is called by any instrumentation.
- This guarantee surfaces initialization ordering issues
- calling GlobalOpenTelemetry.set() too late (i.e. after instrumentation has called GlobalOpenTelemetry.get())
- triggers an exception rather than silently failing.
- If GlobalOpenTelemetry.get() is called before GlobalOpenTelemetry.set(..)
- If autoconfigure is present, GlobalOpenTelemetry can be automatically initialized by setting
- -Dotel.java.global-autoconfigure.enabled=true (or via env var export OTEL_JAVA_GLOBAL_AUTOCONFIGURE_ENABLED=true).
- When enabled, the first call to GlobalOpenTelemetry.get() triggers autoconfiguration and calls GlobalOpenTelemetry.set(..) with the resulting OpenTelemetry instance.
The following code snippet explores GlobalOpenTelemetry API context propagation:
1 | package otel; |
TracerProvider
TracerProvider is the API entry point for traces and provides Tracers
Tracer
Tracer is used to record spans for an instrumentation scope.
Span
- SpanBuilder and Span are used to construct and record data to spans.
- SpanBuilder is used to add data to a span before starting it by calling Span startSpan().
- Data can be added / updated after starting by calling various Span update methods.
- The data provided to SpanBuilder before starting is provided as an input to Samplers.
The following code snippet explores SpanBuilder / Span API usage:
1 | package otel; |
- Span parenting is an important aspect of tracing.
- Each span has an optional parent.
- By collecting all the spans in a trace and following each span’s parent, we can construct a hierarchy.
- The span APIs are built on top of context, which allows span context to be implicitly passed around an application and across threads.
- When a span is created, its parent is set to the whatever span is present in Context.current()
- unless there is no span or the context is explicitly overridden.
- Most of the context API usage guidance applies to spans.
- Span context is propagated across application boundaries with the W3CTraceContextPropagator and other TextMapPropagators.
The following code snippet explores Span API context propagation:
1 | package otel; |
MeterProvider
MeterProvider is the API entry point for metrics and provides Meters.
Meter
- Meter is used to obtain instruments for a particular instrumentation scope.
- There are a variety of instruments, each with different semantics and default behavior in the SDK.
- It’s important to choose the right instrument for each particular use case:
Instrument | Sync/Async | Description | Example | Default SDK Aggregation |
---|---|---|---|---|
Counter | sync | Record monotonic (positive) values. | Record user logins | sum (monotonic=true) |
Async Counter | async | Observe monotonic sums. | Observe number of classes loaded in the JVM | sum (monotonic=true) |
UpDownCounter | sync | Record non-monotonic (positive and negative) values. | Record when items are added to and removed from a queue | sum (monotonic=false) |
Async UpDownCounter | async | Observe non-monotonic (positive and negative) sums. | Observe JVM memory pool usage | sum (monotonic=false) |
Histogram | sync | Record monotonic (positive) values where the distribution is important. | Record duration of HTTP requests processed by server | ExplicitBucketHistogram |
Gauge | sync | Record the latest value where spatial re-aggregation does not make sense | Record temperature | LastValue |
Async Gauge | async | Observe the latest value where spatial re-aggregation does not make sense | Observe CPU utilization | LastValue |
Spatial re-aggregation is the process of merging attribute streams by dropping attributes which are not needed.
- For example, given series with attributes {“color”: “red”, “shape”: “square”}, {“color”: “blue”, “shape”: “square”}
- you can perform spatial re-aggregation by dropping the color attribute, and merging the series where the attributes are equal after dropping color.
- Most aggregations have a useful spatial aggregation merge function (i.e. sums are summed together)
- but gauges aggregated by the LastValue aggregation are the exception.
The instrument APIs have share a variety of features:
- Created using the builder pattern.
- Required instrument name
- Optional unit and description.
- Record values which are long or double, which is configured via the builder.
1 | flowchart TD |
Counter
LongCounter and DoubleCounter are used to record monotonic (positive) values.
The following code snippet explores counter API usage:
1 | package otel; |
Async Counter
ObservableLongCounter and ObservableDoubleCounter are used to observe monotonic (positive) sums.
The following code snippet explores async counter API usage:
1 | package otel; |
UpDownCounter
LongUpDownCounter and DoubleUpDownCounter are used to record non-monotonic (positive and negative) values.
The following code snippet explores updowncounter API usage:
1 | package otel; |
Async UpDownCounter
ObservableLongUpDownCounter and ObservableDoubleUpDownCounter are used to observe non-monotonic (positive and negative) sums.
The following code snippet explores async updowncounter API usage:
1 | package otel; |
Histogram
DoubleHistogram and LongHistogram are used to record monotonic (positive) values where the distribution is important.
The following code snippet explores histogram API usage:
1 | package otel; |
Gauge
DoubleGauge and LongGauge are used to record the latest value where spatial re-aggregation does not make sense.
The following code snippet explores gauge API usage:
1 | package otel; |
Async Gauge
ObservableDoubleGauge and ObservableLongGauge are used to observe the latest value where spatial re-aggregation does not make sense.
The following code snippet explores async gauge API usage:
1 | package otel; |
LoggerProvider
- LoggerProvider is the API entry point for logs and provides Loggers.
- While the LoggerProvider / Logger APIs are structurally similar to the equivalent trace and metric APIs, they serve a different use case.
- As of now, LoggerProvider / Logger and associated classes represent the Log Bridge API
- which exists to write log appenders to bridge logs recorded through other log APIs / frameworks into OpenTelemetry.
- They are not intended for end user use as a replacement for Log4j / SLF4J / Logback / etc.
Logger
Logger is used to emit log records for an instrumentation scope.
LogRecordBuilder
LogRecordBuilder is used to construct and emit log records.
The following code snippet explores LogRecordBuilder API usage:
1 | package otel; |
Noop implementation
- The OpenTelemetry#noop() method provides access to a noop implementation of OpenTelemetry. and all API components it provides access to.
- As the name suggests, the noop implementation does nothing and is designed to have no impact on performance.
- Instrumentation may see impact on performance even when the noop is used
- if it is computing / allocating attribute values and other data required to record the telemetry.
- The noop is a useful default instance of OpenTelemetry when a user has not configured and installed a concrete implementation such as the SDK.
The following code snippet explores OpenTelemetry#noop() API usage:
1 | package otel; |
Semantic attributes
- The semantic conventions describe how to collect telemetry in a standardized way for common operations.
- This includes an attribute registry, which enumerates definitions for all attributes referenced in the conventions, organized by domain.
- The semantic-conventions-java project generates constants from the semantic conventions, which can be used to help instrumentation conform:
Description | Artifact |
---|---|
Generated code for stable semantic conventions | io.opentelemetry.semconv:opentelemetry-semconv:1.37.0-alpha |
Generated code for incubating semantic conventions | io.opentelemetry.semconv:opentelemetry-semconv-incubating:1.37.0-alpha |
- While both opentelemetry-semconv and opentelemetry-semconv-incubating include the -alpha suffix and are subject to breaking changes
- the intent is to stabilize opentelemetry-semconv and leave the -alpha suffix on opentelemetry-semconv-incubating permanently.
- Libraries can use opentelemetry-semconv-incubating for testing, but should not include it as a dependency
- since attributes may come and go from version to version
- including it as a dependency may expose end users to runtime errors when transitive version conflicts occur.
- The attribute constants generated from semantic conventions are instances of
AttributeKey<T>
- and can be used anywhere the OpenTelemetry API accepts attributes.
The following code snippet explores semantic convention attribute API usage:
1 | package otel; |
Baggage
- Baggage is a bundle of application defined key-value pairs associated with a distributed request or workflow execution.
- Baggage keys and values are strings, and values have optional string metadata.
- Telemetry can be enriched with data from baggage by configuring the SDK to add entries as attributes to spans, metrics, and log records.
- The baggage API is built on top of context, which allows span context to be implicitly passed around an application and across threads.
- Most of the context API usage guidance applies to baggage.
- Baggage is propagated across application boundaries with the W3CBaggagePropagator.
The following code snippet explores Baggage API usage:
1 | package otel; |
Incubating API
- The io.opentelemetry:opentelemetry-api-incubator:1.54.1-alpha artifact contains experimental trace, metric, log, and context APIs which.
- Incubating APIs may have breaking API changes in minor releases.
- Often, these represent experimental specification features or API designs we want to vet with user feedback before committing to.
- Libraries should not depend on the incubating APIs, since users may be exposed to runtime errors when transitive version conflicts occur.
Manage Telemetry with SDK
- The SDK is the built-in reference implementation of the API, processing and exporting telemetry produced by instrumentation API calls.
- The SDK consists of the following top level components:
Components | Desc |
---|---|
SdkTracerProvider | The SDK implementation of TracerProvider, including tools for sampling, processing, and exporting spans. |
SdkMeterProvider | The SDK implementation of MeterProvider, including tools for configuring metric streams and reading / exporting metrics. |
SdkLoggerProvider | The SDK implementation of LoggerProvider, including tools for processing and exporting logs. |
TextMapPropagator | Propagates context across process boundaries. |
- These are combined into OpenTelemetrySdk
- a carrier object which makes it convenient to pass fully-configured SDK components to instrumentation.
- The SDK comes packaged with a variety of built-in components which are sufficient for many use cases
- and supports plugin interfaces for extensibility.
SDK plugin extension interfaces
When built-in components are insufficient, the SDK can be extended by implementing various plugin extension interfaces:
Plugin interfaces | Desc |
---|---|
Sampler | Configures which spans are recorded and sampled. |
SpanProcessor | Processes spans when they start and end. |
SpanExporter | Exports spans out of process. |
MetricReader | Reads aggregated metrics. |
MetricExporter | Exports metrics out of process. |
LogRecordProcessor | Processes log records when they are emitted. |
LogRecordExporter | Exports log records out of process. |
TextMapPropagator | Propagates context across process boundaries. |
SDK components
- The io.opentelemetry:opentelemetry-sdk:1.54.1 artifact contains the OpenTelemetry SDK.
- The following sections describe the core user-facing components of the SDK. Each component section includes:
- A brief description, including a link to the Javadoc type reference.
- If the component is a plugin extension interface, a table of available built-in and opentelemetry-java-contrib implementations.
- A simple demonstration of programmatic-configuration.
- If the component is a plugin extension interface, a simple demonstration of a custom implementation.
OpenTelemetrySdk
- OpenTelemetrySdk is the SDK implementation of OpenTelemetry.
- It is a holder for top-level SDK components which makes it convenient to pass fully-configured SDK components to instrumentation.
- OpenTelemetrySdk is configured by the application owner, and consists of:
Components | Desc |
---|---|
SdkTracerProvider | The SDK implementation of TracerProvider |
SdkMeterProvider | The SDK implementation of MeterProvider |
SdkLoggerProvider | The SDK implementation of LoggerProvider |
ContextPropagators | Propagates context across process boundaries |
The following code snippet demonstrates OpenTelemetrySdk programmatic configuration:
1 | package otel; |
Resource
- Resource is a set of attributes defining the telemetry source.
- An application should associate the same resource with SdkTracerProvider, SdkMeterProvider, SdkLoggerProvider.
- ResourceProviders contribute contextual information to the autoconfigured resource based on the environment.
The following code snippet demonstrates Resource programmatic configuration:
1 | package otel; |
SdkTracerProvider
- SdkTracerProvider is the SDK implementation of TracerProvider, and is responsible for handling trace telemetry produced by the API.
- SdkTracerProvider is configured by the application owner, and consists of:
Components | Desc |
---|---|
Resource | The resource spans are associated with. |
Sampler | Configures which spans are recorded and sampled. |
SpanProcessors | Processes spans when they start and end. |
SpanExporters | Exports spans out of process (in conjunction with associated with SpanProcessors). |
SpanLimits | Controls the limits of data associated with spans. |
The following code snippet demonstrates SdkTracerProvider programmatic configuration:
1 | package otel; |
Sampler
- A Sampler is a plugin extension interface responsible for determining which spans are recorded and sampled.
- By default SdkTracerProvider is configured with the ParentBased(root=AlwaysOn) sampler.
- This results in 100% of spans being sampled if unless a calling application performs sampling.
- If this is too noisy / expensive, change the sampler.
Samplers built-in to the SDK and maintained by the community in opentelemetry-java-contrib:
Class | Artifact | Description |
---|---|---|
ParentBased | io.opentelemetry:opentelemetry-sdk:1.54.1 | Samples spans based on sampling status of the span’s parent. |
AlwaysOn | io.opentelemetry:opentelemetry-sdk:1.54.1 | Samples all spans. |
AlwaysOff | io.opentelemetry:opentelemetry-sdk:1.54.1 | Drops all spans. |
TraceIdRatioBased | io.opentelemetry:opentelemetry-sdk:1.54.1 | Samples spans based on a configurable ratio. |
JaegerRemoteSampler | io.opentelemetry:opentelemetry-sdk-extension-jaeger-remote-sampler:1.54.1 | Samples spans based on configuration from a remote server. |
LinksBasedSampler | io.opentelemetry.contrib:opentelemetry-samplers:1.50.0-alpha | Samples spans based on sampling status of the span’s links. |
RuleBasedRoutingSampler | io.opentelemetry.contrib:opentelemetry-samplers:1.50.0-alpha | Samples spans based on configurable rules. |
ConsistentSamplers | io.opentelemetry.contrib:opentelemetry-consistent-sampling:1.50.0-alpha | Various consistent sampler implementations as defined by probability sampling. |
The following code snippet demonstrates Sampler programmatic configuration:
1 | package otel; |
Implement the Sampler interface to provide your own custom sampling logic. For example:
1 | package otel; |
- Callback invoked when span is started, before any SpanProcessor is called.
- If the SamplingDecision is:
- DROP: the span is dropped.
- A valid span context is created and SpanProcessor#onStart is still called
- but no data is recorded and SpanProcessor#onEnd is not called.
- RECORD_ONLY: the span is recorded but not sampled.
- Data is recorded to the span, SpanProcessor#onStart and SpanProcessor#onEnd are called
- but the span’s sampled status indicates it should not be exported out of process.
- RECORD_AND_SAMPLE: the span is recorded and sampled.
- Data is recorded to the span, SpanProcessor#onStart and SpanProcessor#onEnd are called
- and the span’s sampled status indicates it should be exported out of process.
- DROP: the span is dropped.
Sampler -> Processor
SamplingDecision | Desc | SpanProcessor#onStart | SpanProcessor#onEnd |
---|---|---|---|
DROP | not recorded + not sampled | Yes | No |
RECORD_ONLY | recorded + not sampled | Yes | Yes |
RECORD_AND_SAMPLE | recorded + sampled | Yes | Yes |
SpanProcessor
- A SpanProcessor is a plugin extension interface with callbacks invoked when a span is started and ended.
- They are often paired with SpanExporters to export spans out of process, but have other applications such as data enrichment.
Span processors built-in to the SDK and maintained by the community in opentelemetry-java-contrib:
Class | Artifact | Description |
---|---|---|
BatchSpanProcessor | io.opentelemetry:opentelemetry-sdk:1.54.1 | Batches sampled spans and exports them via a configurable SpanExporter |
SimpleSpanProcessor | io.opentelemetry:opentelemetry-sdk:1.54.1 | Exports each sampled span via a configurable SpanExporter. |
BaggageSpanProcessor | io.opentelemetry.contrib:opentelemetry-baggage-processor:1.50.0-alpha | Enriches spans with baggage. |
JfrSpanProcessor | io.opentelemetry.contrib:opentelemetry-jfr-events:1.50.0-alpha | Creates JFR events from spans. |
StackTraceSpanProcessor | io.opentelemetry.contrib:opentelemetry-span-stacktrace:1.50.0-alpha | Enriches select spans with stack trace data. |
InferredSpansProcessor | io.opentelemetry.contrib:opentelemetry-inferred-spans:1.50.0-alpha | Generates spans from async profiler instead of instrumentation. |
The following code snippet demonstrates SpanProcessor programmatic configuration:
1 | package otel; |
Implement the SpanProcessor interface to provide your own custom span processing logic. For example:
1 | package otel; |
SpanExporter
- A SpanExporter is a plugin extension interface responsible for exporting spans out of process.
- Rather than directly registering with SdkTracerProvider, they are paired with SpanProcessors (typically BatchSpanProcessor).
Span exporters built-in to the SDK and maintained by the community in opentelemetry-java-contrib:
Class | Artifact | Description |
---|---|---|
OtlpHttpSpanExporter | io.opentelemetry:opentelemetry-exporter-otlp:1.54.1 | Exports spans via OTLP http/protobuf |
OtlpGrpcSpanExporter | io.opentelemetry:opentelemetry-exporter-otlp:1.54.1 | Exports spans via OTLP grpc |
LoggingSpanExporter | io.opentelemetry:opentelemetry-exporter-logging:1.54.1 | Logs spans to JUL in a debugging format. |
OtlpJsonLoggingSpanExporter | io.opentelemetry:opentelemetry-exporter-logging-otlp:1.54.1 | Logs spans to JUL in an OTLP JSON encoding. |
OtlpStdoutSpanExporter | io.opentelemetry:opentelemetry-exporter-logging-otlp:1.54.1 | Logs spans to System.out in the OTLP JSON file encoding (experimental). |
ZipkinSpanExporter | io.opentelemetry:opentelemetry-exporter-zipkin:1.54.1 | Export spans to Zipkin. |
InterceptableSpanExporter | io.opentelemetry.contrib:opentelemetry-processors:1.50.0-alpha | Passes spans to a flexible interceptor before exporting. |
KafkaSpanExporter | io.opentelemetry.contrib:opentelemetry-kafka-exporter:1.50.0-alpha | Exports spans by writing to a Kafka topic. |
The following code snippet demonstrates SpanExporter programmatic configuration:
1 | package otel; |
Implement the SpanExporter interface to provide your own custom span export logic. For example:
1 | package otel; |
SpanLimits
SpanLimits defines constraints for the data captured by spans, including max attribute length, max number of attributes, and more.
The following code snippet demonstrates SpanLimits programmatic configuration:
1 | package otel; |
SdkMeterProvider
- SdkMeterProvider is the SDK implementation of MeterProvider, and is responsible for handling metric telemetry produced by the API.
- SdkMeterProvider is configured by the application owner, and consists of:
- Resource: The resource metrics are associated with.
- MetricReader: Reads the aggregated state of metrics.
- Optionally, with CardinalityLimitSelector for overriding cardinality limit by instrument kind.
- If unset, each instrument is limited to 2000 unique combinations of attributes per collection cycle.
- Cardinality limits are also configurable for individual instruments via views.
- MetricExporter: Exports metrics out of process (in conjunction with associated MetricReader).
- Views: Configures metric streams, including dropping unused metrics.
The following code snippet demonstrates SdkMeterProvider programmatic configuration:
1 | package otel; |
MetricReader
- A MetricReader is a plugin extension interface which is responsible for reading aggregated metrics.
- They are often paired with MetricExporters to export metrics out of process
- but may also be used to serve the metrics to external scrapers in pull-based protocols.
Metric readers built-in to the SDK and maintained by the community in opentelemetry-java-contrib:
Class | Artifact | Description |
---|---|---|
PeriodicMetricReader | io.opentelemetry:opentelemetry-sdk:1.54.1 | Reads metrics on a periodic basis and exports them via a configurable MetricExporter. |
PrometheusHttpServer | io.opentelemetry:opentelemetry-exporter-prometheus:1.54.1-alpha | Serves metrics on an HTTP server in various prometheus formats. |
The following code snippet demonstrates MetricReader programmatic configuration:
1 | package otel; |
Implement the MetricReader interface to provide your own custom metric reader logic. For example:
1 | package otel; |
MetricExporter
- A MetricExporter is a plugin extension interface responsible for exporting metrics out of process.
- Rather than directly registering with SdkMeterProvider, they are paired with PeriodicMetricReader.
Metric exporters built-in to the SDK and maintained by the community in opentelemetry-java-contrib:
Class | Artifact | Description |
---|---|---|
OtlpHttpMetricExporter | io.opentelemetry:opentelemetry-exporter-otlp:1.54.1 | Exports metrics via OTLP http/protobuf. |
OtlpGrpcMetricExporter | io.opentelemetry:opentelemetry-exporter-otlp:1.54.1 | Exports metrics via OTLP grpc. |
LoggingMetricExporter | io.opentelemetry:opentelemetry-exporter-logging:1.54.1 | Logs metrics to JUL in a debugging format. |
OtlpJsonLoggingMetricExporter | io.opentelemetry:opentelemetry-exporter-logging-otlp:1.54.1 | Logs metrics to JUL in the OTLP JSON encoding. |
OtlpStdoutMetricExporter | io.opentelemetry:opentelemetry-exporter-logging-otlp:1.54.1 | Logs metrics to System.out in the OTLP JSON file encoding (experimental). |
InterceptableMetricExporter | io.opentelemetry.contrib:opentelemetry-processors:1.50.0-alpha | Passes metrics to a flexible interceptor before exporting. |
The following code snippet demonstrates MetricExporter programmatic configuration:
1 | package otel; |
Implement the MetricExporter interface to provide your own custom metric export logic. For example:
1 | package otel; |
Views
- Views allow metric streams to be customized
- including changing metric names, metric descriptions, metric aggregations (i.e. histogram bucket boundaries)
- the set of attribute keys to retain, cardinality limit, etc.
- Views have somewhat unintuitive behavior when multiple match a particular instrument.
- If one matching view changes the metric name and another changes the metric aggregation
- you might expect the name and aggregation are changed, but this is not the case.
- Instead, two metric streams are produced
- one with the configured metric name and the default aggregation
- and another with the original metric name and the configured aggregation.
- In other words, matching views do not merge.
- For best results, configure views with narrow selection criteria (i.e. select a single specific instrument)
The following code snippet demonstrates View programmatic configuration:
1 | package otel; |
SdkLoggerProvider
- SdkLoggerProvider is the SDK implementation of LoggerProvider, and is responsible for handling log telemetry produced by the log bridge API.
- SdkLoggerProvider is configured by the application owner, and consists of:
Components | Desc |
---|---|
Resource | The resource logs are associated with. |
LogRecordProcessor | Processes logs when they are emitted. |
LogRecordExporter | Exports logs out of process (in conjunction with associated LogRecordProcessor). |
LogLimits | Controls the limits of data associated with logs. |
The following code snippet demonstrates SdkLoggerProvider programmatic configuration:
1 | package otel; |
LogRecordProcessor
- A LogRecordProcessor is a plugin extension interface with a callback invoked when a log is emitted.
- They are often paired with LogRecordExporters to export logs out of process, but have other applications such as data enrichment.
Log record processors built-in to the SDK and maintained by the community in opentelemetry-java-contrib:
Class | Artifact | Description |
---|---|---|
BatchLogRecordProcessor | io.opentelemetry:opentelemetry-sdk:1.54.1 | Batches log records and exports them via a configurable LogRecordExporter. |
SimpleLogRecordProcessor | io.opentelemetry:opentelemetry-sdk:1.54.1 | Exports each log record a via a configurable LogRecordExporter. |
EventToSpanEventBridge | io.opentelemetry.contrib:opentelemetry-processors:1.50.0-alpha | Records event log records as span events on the current span. |
The following code snippet demonstrates LogRecordProcessor programmatic configuration:
1 | package otel; |
Implement the LogRecordProcessor interface to provide your own custom log processing logic. For example:
1 | package otel; |
LogRecordExporter
- A LogRecordExporter is a plugin extension interface responsible for exporting log records out of process.
- Rather than directly registering with SdkLoggerProvider, they are paired with LogRecordProcessors (typically BatchLogRecordProcessor).
Log record exporters built-in to the SDK and maintained by the community in opentelemetry-java-contrib:
Class | Artifact | Description |
---|---|---|
OtlpHttpLogRecordExporter | io.opentelemetry:opentelemetry-exporter-otlp:1.54.1 | Exports log records via OTLP http/protobuf. |
OtlpGrpcLogRecordExporter | io.opentelemetry:opentelemetry-exporter-otlp:1.54.1 | Exports log records via OTLP grpc |
SystemOutLogRecordExporter | io.opentelemetry:opentelemetry-exporter-logging:1.54.1 | Logs log records to system out in a debugging format. |
OtlpJsonLoggingLogRecordExporter | io.opentelemetry:opentelemetry-exporter-logging-otlp:1.54.1 | Logs log records to JUL in the OTLP JSON encoding. |
OtlpStdoutLogRecordExporter | io.opentelemetry:opentelemetry-exporter-logging-otlp:1.54.1 | Logs log records to System.out in the OTLP JSON file encoding (experimental). |
InterceptableLogRecordExporter | io.opentelemetry.contrib:opentelemetry-processors:1.50.0-alpha | Passes log records to a flexible interceptor before exporting. |
- OtlpJsonLoggingLogRecordExporter logs to JUL, and may cause infinite loops
- (i.e. JUL -> SLF4J -> Logback -> OpenTelemetry Appender -> OpenTelemetry Log SDK -> JUL) if not carefully configured.
The following code snippet demonstrates LogRecordExporter programmatic configuration:
1 | package otel; |
Implement the LogRecordExporter interface to provide your own custom log record export logic. For example:
1 | package otel; |
LogLimits
LogLimits defines constraints for the data captured by log records, including max attribute length, and max number of attributes.
The following code snippet demonstrates LogLimits programmatic configuration:
1 | package otel; |
TextMapPropagator
TextMapPropagator is a plugin extension interface responsible for propagating context across process boundaries in a text format.
TextMapPropagators built-in to the SDK and maintained by the community in opentelemetry-java-contrib:
Class | Artifact | Description |
---|---|---|
W3CTraceContextPropagator | io.opentelemetry:opentelemetry-api:1.54.1 | Propagate trace context using W3C trace context propagation protocol. |
W3CBaggagePropagator | io.opentelemetry:opentelemetry-api:1.54.1 | Propagate baggage using W3C baggage propagation protocol. |
MultiTextMapPropagator | io.opentelemetry:opentelemetry-context:1.54.1 | Compose multiple propagators. |
JaegerPropagator | io.opentelemetry:opentelemetry-extension-trace-propagators:1.54.1 | Propagator trace context using the Jaeger propagation protocol. |
B3Propagator | io.opentelemetry:opentelemetry-extension-trace-propagators:1.54.1 | Propagator trace context using the B3 propagation protocol. |
OtTracePropagator | io.opentelemetry:opentelemetry-extension-trace-propagators:1.54.1 | Propagator trace context using the OpenTracing propagation protocol. |
PassThroughPropagator | io.opentelemetry:opentelemetry-api-incubator:1.54.1-alpha | Propagate a configurable set fields without participating in telemetry. |
AwsXrayPropagator | io.opentelemetry.contrib:opentelemetry-aws-xray-propagator:1.50.0-alpha | Propagate trace context using AWS X-Ray propagation protocol. |
AwsXrayLambdaPropagator | io.opentelemetry.contrib:opentelemetry-aws-xray-propagator:1.50.0-alpha | Propagate trace context using environment variables and AWS X-Ray propagation protocol. |
The following code snippet demonstrates TextMapPropagator programmatic configuration:
1 | package otel; |
Implement the TextMapPropagator interface to provide your own custom propagator logic. For example:
1 | package otel; |
Appendix
Internal logging
- SDK components log a variety of information to java.util.logging
- at different log levels and using logger names based on the fully qualified class name of the relevant component.
- By default, log messages are handled by the root handler in your application.
- If you have not installed a custom root handler for your application, logs of level INFO or higher are sent to the console by default.
- You may want to change the behavior of the logger for OpenTelemetry.
- For example, you can reduce the logging level to output additional information when debugging
- increase the level for a particular class to ignore errors coming from the class
- or install a custom handler or filter to run custom code whenever OpenTelemetry logs a particular message.
- No detailed list of logger names and log information is maintained.
- However, all OpenTelemetry API, SDK, contrib and instrumentation components share the same io.opentelemetry.* package prefix.
- It can be useful to enable finer grain logs for all io.opentelemetry.*, inspect the output, and narrow down to packages or FQCNs of interest.
For example:
1 | ## Turn off all OpenTelemetry logging |
1 | ## Turn off logging for just the BatchSpanProcessor |
1 | ## Log "FINE" messages for help in debugging |
For more fine-grained control and special case handling, custom handlers and filters can be specified with code.
1 | package otel; |
1 | ## Registering the custom filter on the BatchSpanProcessor |
OTLP exporters
- The span exporter, metric exporter, and log exporter sections describe OTLP exporters of the form:
- OtlpHttp{Signal}Exporter, which exports data via OTLP http/protobuf
- OtlpGrpc{Signal}Exporter, which exports data via OTLP grpc
- The exporters for all signals are available via io.opentelemetry:opentelemetry-exporter-otlp:1.54.1
- and have significant overlap across grpc and http/protobuf versions of the OTLP protocol, and between signals.
- The following sections elaborate on these key concepts:
Concepts | Desc |
---|---|
Senders | an abstraction for a different HTTP / gRPC client libraries. |
Authentication | options for OTLP exporters |
Senders
- The OTLP exporters depend on various client libraries to execute HTTP and gRPC requests.
- There is no single HTTP / gRPC client library which satisfies all use cases in the Java ecosystem:
- Java 11+ brings the built-in java.net.http.HttpClient
- but opentelemetry-java needs to support Java 8+ users
- and this can’t be used to export via gRPC because there is no support for trailer headers.
- OkHttp provides a powerful HTTP client with support for trailer headers, but depends on the kotlin standard library.
- grpc-java provides its own ManagedChannel abstraction with various transport implementations, but is not suitable for http/protobuf.
- Java 11+ brings the built-in java.net.http.HttpClient
- In order to accommodate various use cases
- opentelemetry-exporter-otlp uses an internal “sender” abstraction, with a variety of implementations to reflect application constraints.
- To choose another implementation
- exclude the io.opentelemetry:opentelemetry-exporter-sender-okhttp default dependency, and add a dependency on the alternative.
Artifact | Description | OTLP Protocols | Default |
---|---|---|---|
io.opentelemetry:opentelemetry-exporter-sender-okhttp:1.54.1 | OkHttp based implementation. | grpc, http/protobuf | Yes |
io.opentelemetry:opentelemetry-exporter-sender-jdk:1.54.1 | Java 11+ java.net.http.HttpClient based implementation. | http/protobuf | No |
io.opentelemetry:opentelemetry-exporter-sender-grpc-managed-channel:1.54.1 | grpc-java ManagedChannel based implementation. | grpc | No |
Authentication
- The OTLP exporters provide mechanisms for static and dynamic header-based authentication, and for mTLS.
- If using zero-code SDK autoconfigure with environment variables and system properties, see relevant system properties:
- otel.exporter.otlp.headers for static header-based authentication.
- otel.exporter.otlp.client.key, otel.exporter.otlp.client.certificate for mTLS authentication.
The following code snippet demonstrates programmatic configuration of static and dynamic header-based authentication:
1 | package otel; |
Configure the SDK
- The SDK is the built-in reference implementation of the API, processing and exporting telemetry produced by instrumentation API calls.
- Configuring the SDK to process and export appropriately is an essential step to integrating OpenTelemetry into an application.
- All SDK components have programmatic configuration APIs.
- This is the most flexible, expressive way to configure the SDK.
- However, changing configuration requires adjusting code and recompiling the application
- and there is no language interoperability since the API is written in java.
- The zero-code SDK autoconfigure module configures SDK components through system properties or environment variables
- with various extension points for instances where the properties are insufficient.
- We recommend using the zero-code SDK autoconfigure module since it reduces boilerplate code
- allows reconfiguration without rewriting code or recompiling the application, and has language interoperability.
- Java agent and Spring starter automatically configure the SDK using the zero-code SDK autoconfigure module, and install instrumentation with it.
- All autoconfigure content is applicable to Java agent and Spring starter users.
Programmatic configuration
- The programmatic configuration interface is the set of APIs for constructing SDK components.
- All SDK components have a programmatic configuration API, and all other configuration mechanisms are built on top of this API.
- For example, the autoconfigure environment variable and system property configuration interface
- interprets well-known environment variables and system properties into a series of calls to the programmatic configuration API.
- While other configuration mechanisms offer more convenience
- none offer the flexibility of writing code expressing the precise configuration required.
- When a particular capability isn’t supported by a higher order configuration mechanism
- you might have no choice but to use programmatic configuration.
Zero-code SDK autoconfigure
- The autoconfigure module (artifact io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.54.1)
- is a configuration interface built on top of the programmatic configuration interface, which configures SDK components with zero code.
- There are two distinct autoconfigure workflows:
- Environment variables and system properties
- interprets environment variables and system properties to create SDK components
- including various customization points for overlaying programmatic configuration.
- Declarative configuration (currently under development)
- interprets a configuration model to create SDK components, which is typically encoded in a YAML configuration file.
- Environment variables and system properties
Automatically configure SDK components using with autoconfigure as follows:
1 | package otel; |
- Java agent and Spring starter automatically configure the SDK using the zero-code SDK autoconfigure module, and install instrumentation with it.
- All autoconfigure content is applicable to Java agent and Spring starter users.
- The autoconfigure module registers Java shutdown hooks to shut down the SDK when appropriate.
- Because OpenTelemetry Java uses java.util.logging for internal logging, some logging might be suppressed during shutdown hooks.
- This is a bug in the JDK itself, and not something under the control of OpenTelemetry Java.
- If you require logging during shutdown hooks
- consider using System.out rather than a logging framework which might shut itself down in a shutdown hook
- thus suppressing your log messages.
Environment variables and system properties
- The autoconfigure module supports properties listed in the environment variable configuration specification
- with occasional experimental and Java-specific additions.
- The following properties are listed as system properties, but can also be set using environment variables.
- Apply the following steps to convert a system property to an environment variable:
- Convert the name to uppercase.
- Replace all
.
and-
characters with_
.
- For example, the otel.sdk.disabled system property is equivalent to the OTEL_SDK_DISABLED environment variable.
- Apply the following steps to convert a system property to an environment variable:
- If a property is defined as both a system property and environment variable, the system property takes priority.
Properties: general
Properties for disabling the SDK:
System property | Description | Default |
---|---|---|
otel.sdk.disabled | If true, disable the OpenTelemetry SDK. | false |
- If disabled, AutoConfiguredOpenTelemetrySdk#getOpenTelemetrySdk() returns a minimally configured instance
- for example, OpenTelemetrySdk.builder().build().
Properties for attribute limits (see span limits, log limits):
System property | Description | Default |
---|---|---|
otel.attribute.value.length.limit | The maximum length of attribute values. Applies to spans and logs. Overridden by otel.span.attribute.value.length.limit, otel.span.attribute.count.limit. |
No limit |
otel.attribute.count.limit | The maximum number of attributes. Applies to spans, span events, span links, and logs. |
128 |
Properties for context propagation:
System property | Description | Default |
---|---|---|
otel.propagators | Comma-separated list of propagators. Known values include tracecontext, baggage, b3, b3multi, jaeger, ottrace, xray, xray-lambda. |
tracecontext,baggage (W3C) |
- tracecontext configures W3CTraceContextPropagator.
- baggage configures W3CBaggagePropagator.
- b3, b3multi configures B3Propagator.
- jaeger configures JaegerPropagator.
- ottrace configures OtTracePropagator.
- xray configures AwsXrayPropagator.
- xray-lambda configures AwsXrayLambdaPropagator.
Properties: resource
Properties for configuring resource:
System property | Description | Default |
---|---|---|
otel.service.name | Specify logical service name. Takes precedence over service.name defined with otel.resource.attributes. |
unknown_service:java |
otel.resource.attributes | Specify resource attributes in the following format: key1=val1,key2=val2,key3=val3. | |
otel.resource.disabled.keys | Specify resource attribute keys to filter. | |
otel.java.enabled.resource.providers | Comma-separated list of ResourceProvider fully qualified class names to enable. If unset, all resource providers are enabled. |
|
otel.java.disabled.resource.providers | Comma-separated list of ResourceProvider fully qualified class names to disable. |
- For example, to disable the OS resource provider
- set -Dotel.java.disabled.resource.providers=io.opentelemetry.instrumentation.resources.OsResourceProvider.
- The otel.service.name and otel.resource.attributes system properties / environment variables
- are interpreted in the io.opentelemetry.sdk.autoconfigure.EnvironmentResourceProvider resource provider.
- If opting in to specify resource providers via otel.java.enabled.resource-providers, you’ll likely want to include it to avoid surprises.
Properties: traces
Properties for batch span processor(s) paired with exporters specified via otel.traces.exporter:
System property | Description | Default |
---|---|---|
otel.bsp.schedule.delay | The interval, in milliseconds, between two consecutive exports. | 5000 |
otel.bsp.max.queue.size | The maximum number of spans that can be queued before batching. | 2048 |
otel.bsp.max.export.batch.size | The maximum number of spans to export in a single batch. | 512 |
otel.bsp.export.timeout | The maximum allowed time, in milliseconds, to export data. | 30000 |
Properties for sampler:
System property | Description | Default |
---|---|---|
otel.traces.sampler | The sampler to use. Known values include always_on, always_off, traceidratio, parentbased_always_on, parentbased_always_off, parentbased_traceidratio, jaeger_remote. |
parentbased_always_on |
otel.traces.sampler.arg | An argument to the configured tracer if supported, for example a ratio. |
- always_on configures AlwaysOnSampler.
- always_off configures AlwaysOffSampler.
- traceidratio configures TraceIdRatioBased.
- otel.traces.sampler.arg sets the ratio.
- parentbased_always_on configures ParentBased(root=AlwaysOnSampler).
- parentbased_always_off configures ParentBased(root=AlwaysOffSampler).
- parentbased_traceidratio configures ParentBased(root=TraceIdRatioBased).
- otel.traces.sampler.arg sets the ratio.
- jaeger_remote configures JaegerRemoteSampler.
- otel.traces.sampler.arg is a comma-separated list of args as described in the specification.
Properties for span limits:
System property | Description | Default |
---|---|---|
otel.span.attribute.value.length.limit | The maximum length of span attribute values. Takes precedence over otel.attribute.value.length.limit. |
No limit |
otel.span.attribute.count.limit | The maximum number of attributes per span. Takes precedence over otel.attribute.count.limit. |
128 |
otel.span.event.count.limit | The maximum number of events per span. | 128 |
otel.span.link.count.limit | The maximum number of links per span. | 128 |
Properties: metrics
Properties for periodic metric reader:
System property | Description | Default |
---|---|---|
otel.metric.export.interval | The interval, in milliseconds, between the start of two export attempts. | 60000 |
Properties for exemplars:
System property | Description | Default |
---|---|---|
otel.metrics.exemplar.filter | The filter for exemplar sampling. Can be ALWAYS_OFF, ALWAYS_ON or TRACE_BASED. |
TRACE_BASED |
Properties for cardinality limits:
System property | Description | Default |
---|---|---|
otel.java.metrics.cardinality.limit | If set, configure cardinality limit. The value dictates the maximum number of distinct points per metric. |
2000 |
Properties: logs
Properties for log record processor(s) pared with exporters via otel.logs.exporter:
System property | Description | Default |
---|---|---|
otel.blrp.schedule.delay | The interval, in milliseconds, between two consecutive exports. | 1000 |
otel.blrp.max.queue.size | The maximum number of log records that can be queued before batching. | 2048 |
otel.blrp.max.export.batch.size | The maximum number of log records to export in a single batch. | 512 |
otel.blrp.export.timeout | The maximum allowed time, in milliseconds, to export data. | 30000 |
Properties: exporters
Properties for setting exporters:
System property | Purpose | Default |
---|---|---|
otel.traces.exporter | Comma-separated list of span exporters. Known values include otlp, zipkin, console, logging-otlp, none. |
otlp |
otel.metrics.exporter | Comma-separated list of metric exporters. Known values include otlp, prometheus, none. |
otlp |
otel.logs.exporter | Comma-separated list of log record exporters. Known values include otlp, console, logging-otlp, none. |
otlp |
otel.java.exporter.memory_mode | If reusable_data, enable reusable memory mode (on exporters which support it) to reduce allocations. Known values include reusable_data, immutable_data. |
reusable_data |
- Known exporters and artifacts
- otlp configures OtlpHttp{Signal}Exporter / OtlpGrpc{Signal}Exporter.
- zipkin configures ZipkinSpanExporter.
- console configures LoggingSpanExporter, LoggingMetricExporter, SystemOutLogRecordExporter.
- logging-otlp configures OtlpJsonLogging{Signal}Exporter.
- experimental-otlp/stdout configures OtlpStdout{Signal}Exporter (this option is experimental and subject to change or removal).
- Exporters which adhere to otel.java.exporter.memory_mode=reusable_data
- are OtlpGrpc{Signal}Exporter, OtlpHttp{Signal}Exporter, OtlpStdout{Signal}Exporter, and PrometheusHttpServer.
Properties for otlp span, metric, and log exporters:
System property | Description | Default |
---|---|---|
otel.{signal}.exporter=otlp | Select the OpenTelemetry exporter for {signal}. | |
otel.exporter.otlp.protocol | The transport protocol to use on OTLP trace, metric, and log requests. Options include grpc and http/protobuf. |
grpc |
otel.exporter.otlp.{signal}.protocol | The transport protocol to use on OTLP {signal} requests. Options include grpc and http/protobuf |
grpc |
otel.exporter.otlp.endpoint | The endpoint to send all OTLP traces, metrics, and logs to. Often the address of an OpenTelemetry Collector. Must be a URL with a scheme of either http or https based on the use of TLS. |
http://localhost:4317 when protocol is grpc http://localhost:4318 when protocol is http/protobuf |
otel.exporter.otlp.{signal}.endpoint | The endpoint to send OTLP {signal} to. Often the address of an OpenTelemetry Collector. Must be a URL with a scheme of either http or https based on the use of TLS. If protocol is http/protobuf the version and signal must be appended to the path (e.g. v1/traces, v1/metrics, or v1/logs) |
http://localhost:4317 when protocol is grpc http://localhost:4318/v1/{signal} when protocol is http/protobuf. |
otel.exporter.otlp.certificate | The path to the file containing trusted certificates to use when verifying an OTLP trace, metric, or log server’s TLS credentials. The file should contain one or more X.509 certificates in PEM format. |
The host platform’s trusted root certificates are used. |
otel.exporter.otlp.{signal}.certificate | The path to the file containing trusted certificates to use when verifying an OTLP {signal} server’s TLS credentials. The file should contain one or more X.509 certificates in PEM format. |
The host platform’s trusted root certificates are used |
otel.exporter.otlp.client.key | The path to the file containing private client key to use when verifying an OTLP trace, metric, or log client’s TLS credentials. The file should contain one private key PKCS8 PEM format. |
No client key file is used. |
otel.exporter.otlp.{signal}.client.key | The path to the file containing private client key to use when verifying an OTLP {signal} client’s TLS credentials. The file should contain one private key PKCS8 PEM format. |
No client key file is used. |
otel.exporter.otlp.client.certificate | The path to the file containing trusted certificates to use when verifying an OTLP trace, metric, or log client’s TLS credentials. The file should contain one or more X.509 certificates in PEM format. |
No chain file is used. |
otel.exporter.otlp.{signal}.client.certificate | The path to the file containing trusted certificates to use when verifying an OTLP {signal} client’s TLS credentials. The file should contain one or more X.509 certificates in PEM format. |
No chain file is used. |
otel.exporter.otlp.headers | Key-value pairs separated by commas to pass as request headers on OTLP trace, metric, and log requests. | |
otel.exporter.otlp.compression | The compression type to use on OTLP trace, metric, and log requests. Options include gzip. | No compression will be used. |
otel.exporter.otlp.{signal}.compression | The compression type to use on OTLP {signal} requests. Options include gzip. | No compression will be used. |
otel.exporter.otlp.timeout | The maximum waiting time, in milliseconds, allowed to send each OTLP trace, metric, and log batch. | 10000 |
otel.exporter.otlp.{signal}.timeout | The maximum waiting time, in milliseconds, allowed to send each OTLP {signal} batch. | 10000 |
otel.exporter.otlp.metrics.temporality.preference | The preferred output aggregation temporality. Options include DELTA, LOWMEMORY, and CUMULATIVE. If CUMULATIVE, all instruments will have cumulative temporality. If DELTA, counter (sync and async) and histograms will be delta, up down counters (sync and async) will be cumulative. If LOWMEMORY, sync counter and histograms will be delta, async counter and up down counters (sync and async) will be cumulative. |
CUMULATIVE |
otel.exporter.otlp.metrics.default.histogram.aggregation | The preferred default histogram aggregation. Options include BASE2_EXPONENTIAL_BUCKET_HISTOGRAM and EXPLICIT_BUCKET_HISTOGRAM. |
EXPLICIT_BUCKET_HISTOGRAM |
otel.java.exporter.otlp.retry.disabled | If false, retry on when transient errors occur. | false |
- The text placeholder {signal} refers to the supported OpenTelemetry Signal. Valid values include traces, metrics, and logs.
- Signal specific configurations take priority over the generic versions.
- For example, if you set both otel.exporter.otlp.endpoint and otel.exporter.otlp.traces.endpoint, the latter will take precedence.
- OpenTelemetry Java agent 2.x and the OpenTelemetry Spring Boot starter use http/protobuf by default.
- OTLP requires transient errors to be handled with a retry strategy.
- When retry is enabled, retryable gRPC status codes are retried using an exponential backoff with jitter algorithm.
- The specific options of RetryPolicy can only be customized via programmatic customization.
Properties for zipkin span exporter:
System property | Description | Default |
---|---|---|
otel.traces.exporter=zipkin | Select the Zipkin exporter | |
otel.exporter.zipkin.endpoint | The Zipkin endpoint to connect to. Only HTTP is supported. | http://localhost:9411/api/v2/spans |
Properties for prometheus metric exporter.
System property | Description | Default |
---|---|---|
otel.metrics.exporter=prometheus | Select the Prometheus exporter | |
otel.exporter.prometheus.port | The local port used to bind the prometheus metric server. | 9464 |
otel.exporter.prometheus.host | The local address used to bind the prometheus metric server. | 0.0.0.0 |
Programmatic customization
- Programmatic customization provides hooks to supplement the supported properties with programmatic configuration.
- If using the Spring starter, see also spring starter programmatic configuration.
1 | package otel; |
SPI (Service provider interface)
- SPIs (artifact io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.54.1)
- extend SDK autoconfiguration beyond the components built-in to the SDK.
- The following sections describe the available SPIs. Each SPI section includes:
- A brief description, including link to Javadoc type reference.
- A table of available built-in and opentelemetry-java-contrib implementations.
- A simple demonstration of a custom implementation.
ResourceProvider
ResourceProviders contribute to the autoconfigured resource.
ResourceProviders built-in to the SDK and maintained by the community in opentelemetry-java-contrib:
Class | Artifact | Description |
---|---|---|
io.opentelemetry.sdk.autoconfigure.internal.EnvironmentResourceProvider | io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.54.1 | Provides resource attributes based on OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES env vars. |
io.opentelemetry.instrumentation.resources.ContainerResourceProvider | io.opentelemetry.instrumentation:opentelemetry-resources:2.20.1-alpha | Provides container resource attributes. |
io.opentelemetry.instrumentation.resources.HostResourceProvider | io.opentelemetry.instrumentation:opentelemetry-resources:2.20.1-alpha | Provides host resource attributes. |
io.opentelemetry.instrumentation.resources.HostIdResourceProvider | io.opentelemetry.instrumentation:opentelemetry-resources:2.20.1-alpha | Provides host ID resource attribute. |
io.opentelemetry.instrumentation.resources.ManifestResourceProvider | io.opentelemetry.instrumentation:opentelemetry-resources:2.20.1-alpha | Provides service resource attributes based on jar manifest. |
io.opentelemetry.instrumentation.resources.OsResourceProvider | io.opentelemetry.instrumentation:opentelemetry-resources:2.20.1-alpha | Provides OS resource attributes. |
io.opentelemetry.instrumentation.resources.ProcessResourceProvider | io.opentelemetry.instrumentation:opentelemetry-resources:2.20.1-alpha | Provides process resource attributes. |
io.opentelemetry.instrumentation.resources.ProcessRuntimeResourceProvider | io.opentelemetry.instrumentation:opentelemetry-resources:2.20.1-alpha | Provides process runtime resource attributes. |
Implement the ResourceProvider interface to participate in resource autoconfiguration. For example:
1 | package otel; |
AutoConfigurationCustomizerProvider
Implement the AutoConfigurationCustomizerProvider interface to customize a variety of autoconfigured SDK components. For example:
1 | package otel; |
ConfigurableSpanExporterProvider
Implement the ConfigurableSpanExporterProvider interface to allow a custom span exporter to participate in autoconfiguration. For example:
1 | package otel; |
ConfigurableMetricExporterProvider
Implement the ConfigurableMetricExporterProvider interface to allow a custom metric exporter to participate in autoconfiguration. For example:
1 | package otel; |
ConfigurableLogRecordExporterProvider
Implement the ConfigurableLogRecordExporterProvider interface to allow a custom log record exporter to participate in autoconfiguration. For example:
1 | package otel; |
ConfigurableSamplerProvider
Implement the ConfigurableSamplerProvider interface to allow a custom sampler to participate in autoconfiguration. For example:
1 | package otel; |
ConfigurablePropagatorProvider
Implement the ConfigurablePropagatorProvider interface to allow a custom propagator to participate in autoconfiguration. For example:
1 | package otel; |
Declarative configuration
- Declarative configuration is currently under development.
- It allows for YAML file-based configuration as described in opentelemetry-configuration and declarative configuration.
- Include io.opentelemetry:opentelemetry-sdk-extension-incubator:1.54.1-alpha and specify the path to the config file as described in the table below.
System property | Purpose | Default |
---|---|---|
otel.experimental.config.file | The path to the SDK configuration file. | Unset |
- When a config file is specified, environment variables and system properties are ignored, programmatic customization and SPIs are skipped.
- The contents of the file alone dictate SDK configuration.