Skip to content

Commit

Permalink
Library instrumentation should read its version from a file (#5692)
Browse files Browse the repository at this point in the history
* Library instrumentation should read its version from a file

* errorprone

* animalsniffer

* code review comments

* add name as task input too

* code review comments
  • Loading branch information
Mateusz Rzeszutek authored Apr 4, 2022
1 parent d908821 commit 8e722cc
Show file tree
Hide file tree
Showing 23 changed files with 188 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,33 @@ if (testLatestDeps) {
}
}
}

tasks {
val generateInstrumentationVersionFile by registering {
val name = computeInstrumentationName()
val version = project.version as String
inputs.property("instrumentation.name", name)
inputs.property("instrumentation.version", version)

val propertiesDir = File(project.buildDir, "generated/instrumentationVersion/META-INF/io/opentelemetry/instrumentation/")
outputs.dir(propertiesDir)

doLast {
File(propertiesDir, "$name.properties").writeText("version=$version")
}
}
}

fun computeInstrumentationName(): String {
val name = when (projectDir.name) {
"javaagent", "library", "library-autoconfigure" -> projectDir.parentFile.name
else -> project.name
}
return "io.opentelemetry.$name"
}

sourceSets {
main {
output.dir("build/generated/instrumentationVersion", "builtBy" to "generateInstrumentationVersionFile")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@

package io.opentelemetry.instrumentation.api;

/**
* This class will be removed.
*
* @deprecated This class will be removed.
*/
@Deprecated
public final class InstrumentationVersion {
public static final String VERSION =
InstrumentationVersion.class.getPackage().getImplementationVersion();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.InstrumentationVersion;
import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties;
import io.opentelemetry.instrumentation.api.internal.SupportabilityMetrics;
import java.time.Instant;
import java.util.ArrayList;
Expand Down Expand Up @@ -60,7 +60,10 @@ public static <REQUEST, RESPONSE> InstrumenterBuilder<REQUEST, RESPONSE> builder
String instrumentationName,
SpanNameExtractor<? super REQUEST> spanNameExtractor) {
return new InstrumenterBuilder<>(
openTelemetry, instrumentationName, InstrumentationVersion.VERSION, spanNameExtractor);
openTelemetry,
instrumentationName,
EmbeddedInstrumentationProperties.findVersion(instrumentationName),
spanNameExtractor);
}

/**
Expand All @@ -80,6 +83,7 @@ public static <REQUEST, RESPONSE> InstrumenterBuilder<REQUEST, RESPONSE> builder
* different library versions it's easy to find out which instrumentations produced the telemetry
* data.
*/
// TODO: add a setInstrumentationVersion method to the builder instead
public static <REQUEST, RESPONSE> InstrumenterBuilder<REQUEST, RESPONSE> builder(
OpenTelemetry openTelemetry,
String instrumentationName,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.api.internal;

import static java.util.logging.Level.FINE;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import javax.annotation.Nullable;

/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
public final class EmbeddedInstrumentationProperties {

private static final Logger logger =
Logger.getLogger(EmbeddedInstrumentationProperties.class.getName());

private static final ClassLoader DEFAULT_LOADER;

static {
ClassLoader defaultLoader = EmbeddedInstrumentationProperties.class.getClassLoader();
if (defaultLoader == null) {
defaultLoader = new BootstrapProxy();
}
DEFAULT_LOADER = defaultLoader;
}

private static volatile ClassLoader loader = DEFAULT_LOADER;
private static final Map<String, String> versions = new ConcurrentHashMap<>();

public static void setPropertiesLoader(ClassLoader propertiesLoader) {
if (loader != DEFAULT_LOADER) {
logger.warning(
"Embedded properties loader has already been set up, further setPropertiesLoader() calls are ignored");
return;
}
loader = propertiesLoader;
}

@Nullable
public static String findVersion(String instrumentationName) {
return versions.computeIfAbsent(
instrumentationName, EmbeddedInstrumentationProperties::loadVersion);
}

@Nullable
private static String loadVersion(String instrumentationName) {
String path =
"META-INF/io/opentelemetry/instrumentation/" + instrumentationName + ".properties";
try (InputStream in = loader.getResourceAsStream(path)) {
if (in == null) {
logger.log(FINE, "Did not find embedded instrumentation properties file {0}", path);
return null;
}
Properties parsed = new Properties();
parsed.load(in);
return parsed.getProperty("version");
} catch (IOException e) {
logger.log(FINE, "Failed to load embedded instrumentation properties file " + path, e);
return null;
}
}

private static final class BootstrapProxy extends ClassLoader {
BootstrapProxy() {
super(null);
}
}

private EmbeddedInstrumentationProperties() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
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.internal.SpanKey;
import io.opentelemetry.instrumentation.api.internal.SpanKeyProvider;
import io.opentelemetry.sdk.common.InstrumentationLibraryInfo;
Expand Down Expand Up @@ -714,7 +713,8 @@ void instrumentationTypeDetected_generic() {
@Test
void instrumentationVersion_default() {
InstrumenterBuilder<Map<String, String>, Map<String, String>> builder =
Instrumenter.builder(otelTesting.getOpenTelemetry(), "test", name -> "span");
Instrumenter.builder(
otelTesting.getOpenTelemetry(), "test-instrumentation", name -> "span");

Instrumenter<Map<String, String>, Map<String, String>> instrumenter = builder.newInstrumenter();

Expand All @@ -723,16 +723,17 @@ void instrumentationVersion_default() {

instrumenter.end(context, Collections.emptyMap(), Collections.emptyMap(), null);

// see the test-instrumentation.properties file
InstrumentationLibraryInfo expectedLibraryInfo =
InstrumentationLibraryInfo.create("test-instrumentation", "1.2.3");

otelTesting
.assertTraces()
.hasTracesSatisfyingExactly(
trace ->
trace.hasSpansSatisfyingExactly(
span ->
span.hasName("span")
.hasInstrumentationLibraryInfo(
InstrumentationLibraryInfo.create(
"test", InstrumentationVersion.VERSION))));
span.hasName("span").hasInstrumentationLibraryInfo(expectedLibraryInfo)));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# This file is used by the InstrumenterTest#instrumentationVersion_default() test method
version=1.2.3
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public static AwsLambdaFunctionInstrumenter createInstrumenter(OpenTelemetry ope
openTelemetry,
Instrumenter.builder(
openTelemetry,
"io.opentelemetry.aws-lambda-1.0",
"io.opentelemetry.aws-lambda-events-2.2",
AwsLambdaEventsInstrumenterFactory::spanName)
.addAttributesExtractors(
new AwsLambdaFunctionAttributesExtractor(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class AwsLambdaSqsInstrumenterFactory {
public static Instrumenter<SQSEvent, Void> forEvent(OpenTelemetry openTelemetry) {
return Instrumenter.<SQSEvent, Void>builder(
openTelemetry,
"io.opentelemetry.aws-lambda-1.0",
"io.opentelemetry.aws-lambda-events-2.2",
AwsLambdaSqsInstrumenterFactory::spanName)
.addAttributesExtractors(new SqsEventAttributesExtractor())
.addSpanLinksExtractor(new SqsEventSpanLinksExtractor())
Expand All @@ -30,7 +30,7 @@ public static Instrumenter<SQSEvent, Void> forEvent(OpenTelemetry openTelemetry)
public static Instrumenter<SQSMessage, Void> forMessage(OpenTelemetry openTelemetry) {
return Instrumenter.<SQSMessage, Void>builder(
openTelemetry,
"io.opentelemetry.aws-lambda-1.0",
"io.opentelemetry.aws-lambda-events-2.2",
message -> message.getEventSource() + " process")
.addAttributesExtractors(new SqsMessageAttributesExtractor())
.addSpanLinksExtractor(new SqsMessageSpanLinksExtractor())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public final class JaxrsSingletons {
public static final String ABORT_HANDLED =
"io.opentelemetry.javaagent.instrumentation.jaxrs2.filter.abort.handled";

private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jaxrs-1.0-common";
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jaxrs-1.0";

private static final Instrumenter<HandlerData, Void> INSTRUMENTER;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@

package io.opentelemetry.instrumentation.jdbc;

import io.opentelemetry.instrumentation.api.InstrumentationVersion;
import static io.opentelemetry.instrumentation.jdbc.internal.JdbcSingletons.INSTRUMENTATION_NAME;

import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties;
import io.opentelemetry.instrumentation.jdbc.internal.DbInfo;
import io.opentelemetry.instrumentation.jdbc.internal.JdbcConnectionUrlParser;
import io.opentelemetry.instrumentation.jdbc.internal.OpenTelemetryConnection;
Expand Down Expand Up @@ -122,7 +124,12 @@ private static String extractRealUrl(String url) {
}

private static int[] parseInstrumentationVersion() {
String[] parts = InstrumentationVersion.VERSION.split("\\.");
String version = EmbeddedInstrumentationProperties.findVersion(INSTRUMENTATION_NAME);
if (version == null) {
// return 0.0 as a fallback
return new int[] {0, 0};
}
String[] parts = version.split("\\.");
if (parts.length >= 2) {
try {
int majorVersion = Integer.parseInt(parts[0]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* any time.
*/
public final class JdbcSingletons {
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jdbc";
public static final String INSTRUMENTATION_NAME = "io.opentelemetry.jdbc";

private static final Instrumenter<DbRequest, Void> INSTRUMENTER;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

package io.opentelemetry.instrumentation.jdbc

import io.opentelemetry.instrumentation.api.InstrumentationVersion
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter
import io.opentelemetry.instrumentation.jdbc.internal.OpenTelemetryConnection
import spock.lang.Specification

Expand Down Expand Up @@ -37,7 +37,7 @@ class OpenTelemetryDriverTest extends Specification {
expect:
!OpenTelemetryDriver.INSTANCE.jdbcCompliant()

String[] parts = InstrumentationVersion.getPackage().getImplementationVersion().split("\\.")
String[] parts = Instrumenter.getPackage().getImplementationVersion().split("\\.")

OpenTelemetryDriver.INSTANCE.majorVersion == Integer.parseInt(parts[0])
OpenTelemetryDriver.INSTANCE.minorVersion == Integer.parseInt(parts[1])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import io.opentelemetry.instrumentation.api.instrumenter.net.NetClientAttributesExtractor;

public final class JedisSingletons {
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jedis-3.0";
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jedis-4.0";

private static final Instrumenter<JedisRequest, Void> INSTRUMENTER;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import io.opentelemetry.javaagent.instrumentation.jsf.JsfRequest;

public class MojarraSingletons {
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.mojarra-1.2";
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jsf-mojarra-1.2";

private static final Instrumenter<JsfRequest, Void> INSTRUMENTER;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import io.opentelemetry.javaagent.instrumentation.jsf.JsfRequest;

public class MyFacesSingletons {
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.myfaces-1.2";
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jsf-myfaces-1.2";

private static final Instrumenter<JsfRequest, Void> INSTRUMENTER;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import org.apache.kafka.clients.producer.ProducerRecord;

public final class KafkaTelemetryBuilder {
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.kafka-clients-0.11";
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.kafka-clients-2.6";

private final OpenTelemetry openTelemetry;
private final List<AttributesExtractor<ProducerRecord<?, ?>, Void>> producerAttributesExtractors =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@
import io.lettuce.core.tracing.Tracing;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.api.trace.TracerBuilder;
import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties;

/** Entrypoint for instrumenting Lettuce or clients. */
public final class LettuceTelemetry {

public static final String INSTRUMENTATION_NAME = "io.opentelemetry.lettuce-5.1";

/** Returns a new {@link LettuceTelemetry} configured with the given {@link OpenTelemetry}. */
public static LettuceTelemetry create(OpenTelemetry openTelemetry) {
return new LettuceTelemetry(openTelemetry);
Expand All @@ -20,7 +24,12 @@ public static LettuceTelemetry create(OpenTelemetry openTelemetry) {
private final Tracer tracer;

private LettuceTelemetry(OpenTelemetry openTelemetry) {
tracer = openTelemetry.getTracer("io.opentelemetry.lettuce-5.1");
TracerBuilder tracerBuilder = openTelemetry.tracerBuilder(INSTRUMENTATION_NAME);
String version = EmbeddedInstrumentationProperties.findVersion(INSTRUMENTATION_NAME);
if (version != null) {
tracerBuilder.setInstrumentationVersion(version);
}
tracer = tracerBuilder.build();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
/** A builder for {@link RatpackTelemetry}. */
public final class RatpackTelemetryBuilder {

private static final String INSTRUMENTATION_NAME = "io.opentelemetry.ratpack-1.4";
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.ratpack-1.7";

private final OpenTelemetry openTelemetry;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
import static java.util.logging.Level.FINE;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;

import io.opentelemetry.instrumentation.api.InstrumentationVersion;
import io.opentelemetry.javaagent.bootstrap.InstrumentationHolder;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
Expand Down Expand Up @@ -57,9 +57,9 @@ public void transform(TypeTransformer transformer) {
transformer.applyTransformer(
(builder, typeDescription, classLoader, module) -> {
if (module != null && module.isNamed()) {
// using InstrumentationVersion because it's in the unnamed module in the bootstrap
// using Java8BytecodeBridge because it's in the unnamed module in the bootstrap
// loader, and that's where the rmi instrumentation helper classes will end up
JavaModule helperModule = JavaModule.ofType(InstrumentationVersion.class);
JavaModule helperModule = JavaModule.ofType(Java8BytecodeBridge.class);
// expose sun.rmi.server package to unnamed module
ClassInjector.UsingInstrumentation.redefineModule(
InstrumentationHolder.getInstrumentation(),
Expand Down
Loading

0 comments on commit 8e722cc

Please sign in to comment.