- Introduction
- Architecture
- Automatic Instrumentation
- Manual Instrumentation
- Agent Instrumentation
- Access to the OpenTelemetry Tracing API
- Configuration
- Service Loader Support
- Semantic Conventions
- Tracing Enablement
- MicroProfile OpenTracing
- MicroProfile Telemetry and MicroProfile OpenTracing
license-efsl.adoc :sectnums:
In cloud-native technology stacks, distributed and polyglot architectures are the norm. Distributed architectures introduce a variety of operational challenges including how to solve availability and performance issues quickly. These challenges have led to the rise of observability.
Telemetry data is needed to power observability products. Traditionally, telemetry data has been provided by either open-source projects or commercial vendors. With a lack of standardization, the net result is the lack of data portability and the burden on the user to maintain the instrumentation.
The OpenTelemetry project solves these problems by providing a single, vendor-agnostic solution.
OpenTelemetry is a set of APIs, SDKs, tooling and integrations that are designed for the creation and management of telemetry data such as traces, metrics, and logs.
This specification defines the behaviors that allow MicroProfile applications to easily participate in an environment where distributed tracing is enabled via OpenTelemetry (a merger between OpenTracing and OpenCensus).
The OpenTelemetry specification describes the cross-language requirements and expectations for all OpenTelemetry implementations. This specification is based on the Java implementation v{otel-java-version} of OpenTelemetry. An implementation of this MicroProfile Telemetry may consume a later patch release of the Java implementation as long as the required TCKs pass successfully.
Refer to the OpenTelemetry specification repo to understand some essential terms.
Important
|
The Metrics and Logging integrations of OpenTelemetry are out of scope of this specification. Implementations are free to provide support for both Metrics and Logging if desired. |
This specification supports the following three types of instrumentation:
-
Automatic Instrumentation
-
Manual Instrumentation
-
Agent Instrumentation
Jakarta RESTful Web Services (server and client), and MicroProfile REST Clients are automatically enlisted to participate in distributed tracing without code modification as specified in the Tracing API.
These should follow the rules specified in the Semantic Conventions section.
Explicit manual instrumentation can be added into a MicroProfile application in the following ways:
Annotating a method in any Jakarta CDI aware beans with the io.opentelemetry.instrumentation.annotations.WithSpan
annotation.
This will create a new Span and establish any required relationships with the current Trace context.
Method parameters can be annotated with the io.opentelemetry.instrumentation.annotations.SpanAttribute
annotation to indicate which method parameters should be part of the Trace.
Example:
@ApplicationScoped
class SpanBean {
@WithSpan
void span() {
}
@WithSpan("name")
void spanName() {
}
@WithSpan(kind = SpanKind.SERVER)
void spanKind() {
}
@WithSpan
void spanArgs(@SpanAttribute(value = "arg") String arg) {
}
}
By obtaining a SpanBuilder
from the current Tracer
and calling io.opentelemetry.api.trace.Tracer.spanBuilder(String)
.
In this case, it is the developer’s responsibility to ensure that the Span
is properly created, closed, and propagated.
Example:
@RequestScoped
@Path("/")
public class SpanResource {
@Inject
Tracer tracer;
@GET
@Path("/span/new")
public Response spanNew() {
Span span = tracer.spanBuilder("span.new")
.setSpanKind(SpanKind.INTERNAL)
.setParent(Context.current().with(this.span))
.setAttribute("my.attribute", "value")
.startSpan();
span.end();
return Response.ok().build();
}
}
Note
|
Start and end a new |
By obtaining the current Span
to add attributes. The Span lifecycle is managed by the implementation.
Example:
@RequestScoped
@Path("/")
public class SpanResource {
@GET
@Path("/span/current")
public Response spanCurrent() {
Span span = Span.current();
span.setAttribute("my.attribute", "value");
return Response.ok().build();
}
}
Or with CDI:
@RequestScoped
@Path("/")
public class SpanResource {
@Inject
Span span;
@GET
@Path("/span/current")
public Response spanCurrent() {
span.setAttribute("my.attribute", "value");
return Response.ok().build();
}
}
Implementations are free to support the OpenTelemetry Agent Instrumentation. This provides the ability to gather telemetry data without code modifications by attaching a Java Agent JAR to the running JVM.
If an implementation of MicroProfile Telemetry Tracing provides such support, it must conform to the instructions detailed in the OpenTelemetry Java Instrumentation project, including:
Both Agent and MicroProfile Telemetry Tracing Instrumentation (if any), must coexist with each other.
An implementation of MicroProfile Telemetry Tracing must provide the following CDI beans for supporting contextual instance injection:
-
io.opentelemetry.api.OpenTelemetry
-
io.opentelemetry.api.trace.Tracer
-
io.opentelemetry.api.trace.Span
-
io.opentelemetry.api.baggage.Baggage
Calling the OpenTelemetry API directly must work in the same way and yield the same results:
-
io.opentelemetry.api.trace.Span.current()
-
io.opentelemetry.api.baggage.Baggage.current()
Implementations MAY support:
-
io.opentelemetry.api.GlobalOpenTelemetry.get()
To obtain the Tracer
with the OpenTelemetry API, the consumer must use the exact same instrumentation name and version used by the implementation.
Failure to do so, may result in a different Tracer
and incorrect handling of the OpenTelemetry data.
OpenTelemetry must be configured by MicroProfile Config following the semantics of configuration properties detailed in OpenTelemetry SDK Autoconfigure {otel-java-version}.
At minimum the following MicroProfile Config properties MUST be supported:
Property Name | Description |
---|---|
Global Configuration |
|
|
Set to Default value: |
Exporters configuration |
|
|
List of exporters to be used for tracing, separated by commas. Default value: |
|
The propagators to be used. Values other than Default value: |
Resource attributes |
|
|
Specify resource attributes in the following format: |
|
Specify logical service name. Takes precedence over Default value: application name (if applicable) |
Batch Span Processor |
|
|
The interval, in milliseconds, between two consecutive exports. Default value: |
|
The maximum queue size. Default value: |
|
The maximum batch size. Default value: |
|
The maximum allowed time, in milliseconds, to export data. Default value: |
Sampler |
|
|
The sampler to use for tracing. Supported values are:
Support for other samplers might be added with additional libraries Default value: |
|
An argument to the configured tracer if supported, for example a ratio. Consult OpenTelemetry documentation for details. |
OTLP Exporter |
|
|
The transport protocol to use on OTLP trace, metric, and log requests. Options include grpc and http/protobuf. Default value: |
|
The transport protocol to use on OTLP trace requests. Options include grpc and http/protobuf. Default value: |
|
The OTLP traces, metrics, and logs endpoint to connect to. 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 will be appended to the path (e.g. v1/traces, v1/metrics, or v1/logs) Default value: |
|
The OTLP traces endpoint to connect to. Must be a URL with a scheme of either http or https based on the use of TLS. Default value: |
|
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. By default the host platform’s trusted root certificates are used. |
|
The path to the file containing trusted certificates to use when verifying an OTLP trace server’s TLS credentials. The file should contain one or more X.509 certificates in PEM format. By default the host platform’s trusted root certificates are used. |
|
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. By default no client key is used. |
|
The path to the file containing private client key to use when verifying an OTLP trace client’s TLS credentials. The file should contain one private key PKCS8 PEM format. By default no client key file is used. |
|
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. By default no chain file is used. |
|
The path to the file containing trusted certificates to use when verifying an OTLP trace server’s TLS credentials. The file should contain one or more X.509 certificates in PEM format. By default no chain file is used. |
|
Key-value pairs separated by commas to pass as request headers on OTLP trace, metric, and log requests. |
|
Key-value pairs separated by commas to pass as request headers on OTLP trace requests. |
|
The compression type to use on OTLP trace, metric, and log requests. Options include gzip. By default no compression will be used. |
|
The compression type to use on OTLP trace requests. Options include gzip. By default no compression will be used. |
|
The maximum waiting time, in milliseconds, allowed to send each OTLP trace, metric, and log batch. Default value: |
|
The maximum waiting time, in milliseconds, allowed to send each OTLP trace batch. Default value: |
If Environment Config Source is enabled for MicroProfile Config, then the environment variables as described by the OpenTelemetry SDK Autoconfigure are also supported.
Implementation will load additional configuration related components by means of service loader. This allows the application to define its own metadata and trace handling behavior. The following components are supported
Component interface | Purpose |
---|---|
Provides implementation for a name referred in |
|
Provides implementation for a name referred in |
|
Provides implementation for a name referred in |
|
Customizes configuration properties before they are applied to the SDK |
|
Defines resource attributes describing the application |
Behavior when multiple implementations are found for a given component name is undefined. Behavior when customizer changes other properties than those listed in the spec is also undefined.
The Trace Semantic Conventions for Spans and Attributes must be followed by any compatible implementation.
All attributes marked as required
must be present in the context of the Span where they are defined.
Any other attribute is optional.
Implementations can also add their own attributes.
By default, MicroProfile Telemetry Tracing is deactivated.
In order to enable any of the tracing aspects, the configuration otel.sdk.disabled=false
must be specified in any of the configuration sources available via MicroProfile Config.
Important
|
This is a deviation from the OpenTelemetry Specification that specifies this configuration property officially, where OpenTelemetry is activated by default! But in fact, it will be activated only by adding it’s dependency to the application or platform project. To be able to add MicroProfile Telemetry Tracing to MicroProfile implementations by default without side effects, this deviating behaviour has been defined here (see also MicroProfile Telemetry and MicroProfile OpenTracing). |
This property is read once when the application is starting. Any changes afterwards will not take effect unless the application is restarted.
MicroProfile Telemetry Tracing supersedes MicroProfile OpenTracing. Even if the end goal is the same, there are some considerable differences:
-
Different API (between OpenTracing and OpenTelemetry)
-
No
@Traced
annotation -
No specific MicroProfile configuration
-
No customization of Span name through MicroProfile API
-
Differences in attribute names and mandatory ones
For these reasons, the MicroProfile Telemetry Tracing specification does not provide any migration path between both projects. While it is certainly possible to achieve a migration path at the code level and at the specification level (at the expense of not following the main OpenTelemetry specification), it is unlikely to be able to achieve the same compatibility at the data layer. Regardless, implementations are still free to provide migration paths between MicroProfile OpenTracing and MicroProfile Telemetry Tracing.
If a migration path is provided, the bridge layer provided by OpenTelemetry should be used. This bridge layer implements OpenTracing APIs using OpenTelemetry API. The bridge layer takes OpenTelemetry Tracer and exposes as OpenTracing Tracer. See the example below.
//From the global OpenTelemetry configuration
Tracer tracer1 = OpenTracingShim.createTracerShim();
//From a provided OpenTelemetry instance oTel
Tracer tracer2 = OpenTracingShim.createTracerShim(oTel);
Afterwards, you can then register the tracer as the OpenTracing Global Tracer:
GlobalTracer.registerIfAbsent(tracer);