Annotations
For most users, the out-of-the-box instrumentation is completely sufficient and nothing more has to be done. Sometimes, however, users wish to create spans for their own custom code without doing too much code change.
Dependencies
You’ll need to add a dependency on the
opentelemetry-instrumentation-annotations
library to use the @WithSpan
annotation.
Maven
<dependencies>
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-instrumentation-annotations</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
Gradle
dependencies {
implementation('io.opentelemetry.instrumentation:opentelemetry-instrumentation-annotations:2.2.0')
}
Creating spans around methods with @WithSpan
To create a span corresponding to one of
your method, annotate the method with @WithSpan
.
import io.opentelemetry.instrumentation.annotations.WithSpan;
public class MyClass {
@WithSpan
public void myMethod() {
<...>
}
}
Each time the application invokes the annotated method, it creates a span that
denotes its duration and provides any thrown exceptions. By default, the span
name will be <className>.<methodName>
, unless a name is provided as an
argument to the annotation.
If the return type of the method annotated by @WithSpan
is one of the
future- or promise-like
types listed below, then the span will not be ended until the future completes.
- java.util.concurrent.CompletableFuture
- java.util.concurrent.CompletionStage
- com.google.common.util.concurrent.ListenableFuture
- org.reactivestreams.Publisher
- reactor.core.publisher.Mono
- reactor.core.publisher.Flux
- io.reactivex.Completable
- io.reactivex.Maybe
- io.reactivex.Single
- io.reactivex.Observable
- io.reactivex.Flowable
- io.reactivex.parallel.ParallelFlowable
Adding attributes to the span with @SpanAttribute
When a span is created for an annotated
method the values of the arguments to the method invocation can be automatically
added as attributes to the created
span by annotating the method parameters with the @SpanAttribute
annotation.
import io.opentelemetry.instrumentation.annotations.SpanAttribute;
import io.opentelemetry.instrumentation.annotations.WithSpan;
public class MyClass {
@WithSpan
public void myMethod(@SpanAttribute("parameter1") String parameter1,
@SpanAttribute("parameter2") long parameter2) {
<...>
}
}
Unless specified as an argument to the annotation, the attribute name will be
derived from the formal parameter names if they are compiled into the .class
files by passing the -parameters
option to the javac
compiler.
Suppressing @WithSpan
instrumentation
Suppressing @WithSpan
is useful if you have code that is over-instrumented
using @WithSpan
and you want to suppress some of them without modifying the
code.
System property:
otel.instrumentation.opentelemetry-instrumentation-annotations.exclude-methods
Environment variable:
OTEL_INSTRUMENTATION_OPENTELEMETRY_INSTRUMENTATION_ANNOTATIONS_EXCLUDE_METHODS
Description:
Suppress @WithSpan
instrumentation for specific methods. Format is my.package.MyClass1[method1,method2];my.package.MyClass2[method3]
.
Creating spans around methods with otel.instrumentation.methods.include
In cases where you are unable to modify the code, you can still configure the Java agent to capture spans around specific methods.
System property:
otel.instrumentation.methods.include
Environment variable:
OTEL_INSTRUMENTATION_METHODS_INCLUDE
Description:
Add
instrumentation for specific methods in lieu of @WithSpan
. Format is
my.package.MyClass1[method1,method2];my.package.MyClass2[method3]
.
If a method is overloaded (appears more than once on the same class with the same name but different parameters), all versions of the method will be instrumented.
Next steps
Beyond the use of annotations, the OpenTelemetry API allows you to obtain a tracer that can be used for Manual Instrumentation and execute code within the scope of that span.