Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Library instrumentation should read its version from a file #5692

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()
mateuszrzeszutek marked this conversation as resolved.
Show resolved Hide resolved
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)
mateuszrzeszutek marked this conversation as resolved.
Show resolved Hide resolved

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

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";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯


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";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a test now that fails when these are wrong?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, there isn't, unfortunately -- I went over all usages of Instrumenter#builder() and fixed them all manually. Currently I don't have any good idea about how to verify this in a smart way that does not require adding assertions to every test.


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