Annotations

Using instrumentation annotations with a Java agent.

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.

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-methodsEnvironment 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.includeEnvironment 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.