Add version to the InstrumenterBuilder and Instrumenter
MODIFY
instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/Instrumenter.java
instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/Instrumenter.java
@@ -58,7 +58,34 @@ public class Instrumenter<REQUEST, RESPONSE> {
OpenTelemetry openTelemetry,
String instrumentationName,
SpanNameExtractor<? super REQUEST> spanNameExtractor) {
- return new InstrumenterBuilder<>(openTelemetry, instrumentationName, spanNameExtractor);
+ return new InstrumenterBuilder<>(
+ openTelemetry, instrumentationName, InstrumentationVersion.VERSION, spanNameExtractor);
+ }
+
+ /**
+ * Returns a new {@link InstrumenterBuilder}.
+ *
+ * <p>The {@code instrumentationName} is the name of the instrumentation library, not the name of
+ * the instrument*ed* library. The value passed in this parameter should uniquely identify the
+ * instrumentation library so that during troubleshooting it's possible to pinpoint what tracer
+ * produced problematic telemetry.
+ *
+ * <p>The {@code instrumentationVersion} is the version of the instrumentation library, not the
+ * version of the instrument*ed* library.
+ *
+ * <p>In this project we use a convention to encode the minimum supported version of the
+ * instrument*ed* library into the instrumentation name, for example {@code
+ * io.opentelemetry.apache-httpclient-4.0}. This way, if there are different instrumentations for
+ * different library versions it's easy to find out which instrumentations produced the telemetry
+ * data.
+ */
+ public static <REQUEST, RESPONSE> InstrumenterBuilder<REQUEST, RESPONSE> builder(
+ OpenTelemetry openTelemetry,
+ String instrumentationName,
+ String instrumentationVersion,
+ SpanNameExtractor<? super REQUEST> spanNameExtractor) {
+ return new InstrumenterBuilder<>(
+ openTelemetry, instrumentationName, instrumentationVersion, spanNameExtractor);
}
private static final SupportabilityMetrics supportability = SupportabilityMetrics.instance();
@@ -82,7 +109,7 @@ public class Instrumenter<REQUEST, RESPONSE> {
Instrumenter(InstrumenterBuilder<REQUEST, RESPONSE> builder) {
this.instrumentationName = builder.instrumentationName;
this.tracer =
- builder.openTelemetry.getTracer(instrumentationName, InstrumentationVersion.VERSION);
+ builder.openTelemetry.getTracer(instrumentationName, builder.instrumentationVersion);
this.spanNameExtractor = builder.spanNameExtractor;
this.spanKindExtractor = builder.spanKindExtractor;
this.spanStatusExtractor = builder.spanStatusExtractor;

MODIFY
instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java
instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java
@@ -42,6 +42,7 @@ public final class InstrumenterBuilder<REQUEST, RESPONSE> {
final OpenTelemetry openTelemetry;
final Meter meter;
final String instrumentationName;
+ final String instrumentationVersion;
final SpanNameExtractor<? super REQUEST> spanNameExtractor;
final List<SpanLinksExtractor<? super REQUEST>> spanLinksExtractors = new ArrayList<>();
@@ -63,11 +64,13 @@ public final class InstrumenterBuilder<REQUEST, RESPONSE> {
InstrumenterBuilder(
OpenTelemetry openTelemetry,
String instrumentationName,
+ String instrumentationVersion,
SpanNameExtractor<? super REQUEST> spanNameExtractor) {
this.openTelemetry = openTelemetry;
// TODO(anuraaga): Retrieve from openTelemetry when not alpha anymore.
this.meter = GlobalMeterProvider.get().get(instrumentationName);
this.instrumentationName = instrumentationName;
+ this.instrumentationVersion = instrumentationVersion;
this.spanNameExtractor = spanNameExtractor;
}

MODIFY
instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterTest.java
instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterTest.java
@@ -22,6 +22,7 @@ import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.ContextKey;
import io.opentelemetry.context.propagation.TextMapGetter;
+import io.opentelemetry.instrumentation.api.InstrumentationVersion;
import io.opentelemetry.instrumentation.api.instrumenter.db.DbAttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpClientAttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpServerAttributesExtractor;
@@ -641,6 +642,53 @@ class InstrumenterTest {
assertThat(SpanKey.PRODUCER.fromContextOrNull(context)).isNull();
}
+ @Test
+ void instrumentationVersion_default() {
+ InstrumenterBuilder<Map<String, String>, Map<String, String>> builder =
+ Instrumenter.builder(otelTesting.getOpenTelemetry(), "test", name -> "span");
+
+ Instrumenter<Map<String, String>, Map<String, String>> instrumenter = builder.newInstrumenter();
+
+ Context context = instrumenter.start(Context.root(), Collections.emptyMap());
+ assertThat(Span.fromContext(context)).isNotNull();
+
+ instrumenter.end(context, Collections.emptyMap(), Collections.emptyMap(), null);
+
+ otelTesting
+ .assertTraces()
+ .hasTracesSatisfyingExactly(
+ trace ->
+ trace.hasSpansSatisfyingExactly(
+ span ->
+ span.hasName("span")
+ .hasInstrumentationLibraryInfo(
+ InstrumentationLibraryInfo.create(
+ "test", InstrumentationVersion.VERSION))));
+ }
+
+ @Test
+ void instrumentationVersion_custom() {
+ InstrumenterBuilder<Map<String, String>, Map<String, String>> builder =
+ Instrumenter.builder(otelTesting.getOpenTelemetry(), "test", "1.0", name -> "span");
+
+ Instrumenter<Map<String, String>, Map<String, String>> instrumenter = builder.newInstrumenter();
+
+ Context context = instrumenter.start(Context.root(), Collections.emptyMap());
+ assertThat(Span.fromContext(context)).isNotNull();
+
+ instrumenter.end(context, Collections.emptyMap(), Collections.emptyMap(), null);
+
+ otelTesting
+ .assertTraces()
+ .hasTracesSatisfyingExactly(
+ trace ->
+ trace.hasSpansSatisfyingExactly(
+ span ->
+ span.hasName("span")
+ .hasInstrumentationLibraryInfo(
+ InstrumentationLibraryInfo.create("test", "1.0"))));
+ }
+
private static void validateInstrumentationTypeSpanPresent(SpanKey spanKey, Context context) {
Span span = Span.fromContext(context);

Add version to the InstrumenterBuilder and Instrumenter (#4611)