From 34cb0c5e82de8506a2ec5223d2803d31692cdcae Mon Sep 17 00:00:00 2001 From: cecile75 <32452337+cecile75@users.noreply.github.com> Date: Tue, 4 Nov 2025 14:13:18 +0100 Subject: [PATCH 1/6] initial commit --- .../opentelemetry/shim/metrics/OtelMeter.java | 94 +++++++++++++++++++ .../shim/metrics/OtelMeterBuilder.java | 38 ++++++++ .../shim/metrics/OtelMeterProvider.java | 66 +++++++++++++ .../opentelemetry-1.4/build.gradle | 2 +- .../opentelemetry-1.47/build.gradle | 24 +++++ .../OpenTelemetryInstrumentation.java | 81 ++++++++++++++++ .../datadog/trace/api/InstrumenterConfig.java | 12 +++ settings.gradle.kts | 1 + 8 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeter.java create mode 100644 dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeterBuilder.java create mode 100644 dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeterProvider.java create mode 100644 dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.47/build.gradle create mode 100644 dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.47/src/main/java/datadog/trace/instrumentation/opentelemetry147/OpenTelemetryInstrumentation.java diff --git a/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeter.java b/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeter.java new file mode 100644 index 00000000000..1d90c975164 --- /dev/null +++ b/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeter.java @@ -0,0 +1,94 @@ +package datadog.opentelemetry.shim.metrics; + +import io.opentelemetry.api.metrics.BatchCallback; +import io.opentelemetry.api.metrics.DoubleGaugeBuilder; +import io.opentelemetry.api.metrics.DoubleHistogramBuilder; +import io.opentelemetry.api.metrics.LongCounterBuilder; +import io.opentelemetry.api.metrics.LongUpDownCounterBuilder; +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.api.metrics.MeterProvider; +import io.opentelemetry.api.metrics.ObservableMeasurement; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +// https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/1.47.0/io/opentelemetry/api/metrics/Meter.html +public class OtelMeter implements Meter { + private static final Logger LOGGER = LoggerFactory.getLogger(OtelMeter.class); + private static final Meter NOOP_METER = MeterProvider.noop().get("noop"); + private static final String NOOP_INSTRUMENT_NAME = "noop"; + + private final String instrumentationScopeName; + private final String schemaUrl; + private final String instrumentationVersion; + + public OtelMeter( + String instrumentationScopeName, String schemaUrl, String instrumentationVersion) { + this.instrumentationScopeName = instrumentationScopeName; + this.schemaUrl = schemaUrl; + this.instrumentationVersion = instrumentationVersion; + } + + public boolean match( + String instrumentationScopeName, String instrumentationVersion, String schemaUrl) { + return instrumentationScopeName.equals(this.instrumentationScopeName) + && schemaUrl.equals(this.schemaUrl) + && instrumentationVersion.equals(this.instrumentationVersion); + } + + @Override + public LongCounterBuilder counterBuilder(String instrumentName) { + LOGGER.info("CounterBuilder is not yet supported"); + return null; + } + + @Override + public LongUpDownCounterBuilder upDownCounterBuilder(String instrumentName) { + LOGGER.info("upDownCounterBuilder is not yet supported"); + return null; + } + + @Override + public DoubleHistogramBuilder histogramBuilder(String instrumentName) { + LOGGER.info("histogramBuilder is not yet supported"); + return null; + } + + @Override + public DoubleGaugeBuilder gaugeBuilder(String instrumentName) { + LOGGER.info("gaugeBuilder is not yet supported"); + return null; + } + + @Override + public BatchCallback batchCallback( + Runnable callback, + ObservableMeasurement observableMeasurement, + ObservableMeasurement... additionalMeasurements) { + LOGGER.info("batchCallback is not yet supported"); + return Meter.super.batchCallback(callback, observableMeasurement, additionalMeasurements); + } + + private static boolean isInstrumentNameInvalid(String instrumentName) { + if ((null == instrumentName) + || instrumentName.isEmpty() + || instrumentName.length() > 255 + || !Character.isLetter(instrumentName.charAt(0)) + || HasAnyInvalidCharacter(instrumentName)) { + LOGGER.warn( + "Invalid instrument name {}. Instrument names must be ASCII, start with letter, contain only alphanumeric characters, '_', '.', '/', '-' and be max 255 characters.", + instrumentName); + return true; + } + return false; + } + + private static boolean HasAnyInvalidCharacter(String instrumentName) { + for (int i = 1; i < instrumentName.length(); i++) { + char c = instrumentName.charAt(i); + if (!Character.isLetterOrDigit(c) && c != '_' && c != '.' && c != '/' && c != '-') { + return true; + } + } + return false; + } +} diff --git a/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeterBuilder.java b/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeterBuilder.java new file mode 100644 index 00000000000..989a782954a --- /dev/null +++ b/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeterBuilder.java @@ -0,0 +1,38 @@ +package datadog.opentelemetry.shim.metrics; + +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.api.metrics.MeterBuilder; +import javax.annotation.ParametersAreNonnullByDefault; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OtelMeterBuilder implements MeterBuilder { + private static final Logger LOGGER = LoggerFactory.getLogger(OtelMeterBuilder.class); + private final String instrumentationScopeName; + private String schemaUrl; + private String instrumentationVersion; + + public OtelMeterBuilder(String instrumentationScopeName) { + this.instrumentationScopeName = instrumentationScopeName; + } + + @Override + @ParametersAreNonnullByDefault + public MeterBuilder setSchemaUrl(String schemaUrl) { + this.schemaUrl = schemaUrl; + return this; + } + + @Override + @ParametersAreNonnullByDefault + public MeterBuilder setInstrumentationVersion(String instrumentationVersion) { + this.instrumentationVersion = instrumentationVersion; + return this; + } + + @Override + public Meter build() { + LOGGER.debug("Building the OtelMeter"); + return new OtelMeter(instrumentationScopeName, instrumentationVersion, schemaUrl); + } +} diff --git a/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeterProvider.java b/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeterProvider.java new file mode 100644 index 00000000000..f8ed2fc5f6f --- /dev/null +++ b/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeterProvider.java @@ -0,0 +1,66 @@ +package datadog.opentelemetry.shim.metrics; + +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.api.metrics.MeterBuilder; +import io.opentelemetry.api.metrics.MeterProvider; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.ParametersAreNonnullByDefault; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OtelMeterProvider implements MeterProvider { + private static final Logger LOGGER = LoggerFactory.getLogger(OtelMeterProvider.class); + private static final String DEFAULT_METER_NAME = ""; + public static final MeterProvider INSTANCE = new OtelMeterProvider(); + /** Meter instances, indexed by instrumentation scope name. */ + private final Map> meters; + + public OtelMeterProvider() { + this.meters = new HashMap<>(); + } + + @Override + @ParametersAreNonnullByDefault + public Meter get(String instrumentationScopeName) { + return get(instrumentationScopeName, null); + } + + public Meter get(String instrumentationScopeName, String instrumentationVersion) { + return get(instrumentationScopeName, instrumentationVersion, null); + } + + public Meter get( + String instrumentationScopeName, String instrumentationVersion, String urlSchema) { + List meters = this.meters.get(instrumentationScopeName); + if (meters != null) { + for (Meter meter : meters) { + if ((meter instanceof OtelMeter) + && ((OtelMeter) meter) + .match(instrumentationScopeName, instrumentationVersion, urlSchema)) { + return meter; + } + } + } + Meter meter = + meterBuilder(instrumentationScopeName) + .setInstrumentationVersion(instrumentationVersion) + .setSchemaUrl(urlSchema) + .build(); + this.meters.put(instrumentationScopeName, new ArrayList<>()); + this.meters.get(instrumentationScopeName).add(meter); + + return meter; + } + + @Override + public MeterBuilder meterBuilder(String instrumentationScopeName) { + if (instrumentationScopeName.trim().isEmpty()) { + LOGGER.debug("Meter requested without instrumentation scope name."); + instrumentationScopeName = DEFAULT_METER_NAME; + } + return new OtelMeterBuilder(instrumentationScopeName); + } +} diff --git a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/build.gradle b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/build.gradle index 976cd0970f1..62a6f7fa85e 100644 --- a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/build.gradle +++ b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/build.gradle @@ -4,7 +4,7 @@ muzzle { pass { module = 'opentelemetry-api' group = 'io.opentelemetry' - versions = "[$openTelemetryVersion,)" + versions = "[$openTelemetryVersion,1.46.0)" } } diff --git a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.47/build.gradle b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.47/build.gradle new file mode 100644 index 00000000000..d1552398a33 --- /dev/null +++ b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.47/build.gradle @@ -0,0 +1,24 @@ +def openTelemetryVersion = '1.47.0' + +muzzle { + pass { + module = 'opentelemetry-api' + group = 'io.opentelemetry' + versions = "[$openTelemetryVersion,)" + } +} + +apply from: "$rootDir/gradle/java.gradle" + +addTestSuiteForDir('latestDepTest', 'test') + +dependencies { + compileOnly group: 'io.opentelemetry', name: 'opentelemetry-api', version: openTelemetryVersion + compileOnly group: 'com.google.auto.value', name: 'auto-value-annotations', version: '1.6.6' + + implementation project(':dd-java-agent:agent-otel:otel-shim') + + testImplementation group: 'io.opentelemetry', name: 'opentelemetry-api', version: openTelemetryVersion + testImplementation group: 'org.skyscreamer', name: 'jsonassert', version: '1.5.1' + latestDepTestImplementation group: 'io.opentelemetry', name: 'opentelemetry-api', version: '1+' +} diff --git a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.47/src/main/java/datadog/trace/instrumentation/opentelemetry147/OpenTelemetryInstrumentation.java b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.47/src/main/java/datadog/trace/instrumentation/opentelemetry147/OpenTelemetryInstrumentation.java new file mode 100644 index 00000000000..f3c30f86955 --- /dev/null +++ b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.47/src/main/java/datadog/trace/instrumentation/opentelemetry147/OpenTelemetryInstrumentation.java @@ -0,0 +1,81 @@ +package datadog.trace.instrumentation.opentelemetry147; + +import static datadog.trace.agent.tooling.bytebuddy.matcher.HierarchyMatchers.implementsInterface; +import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.returns; +import static net.bytebuddy.matcher.ElementMatchers.takesNoArguments; + +import com.google.auto.service.AutoService; +import datadog.opentelemetry.shim.metrics.OtelMeterProvider; +import datadog.trace.agent.tooling.Instrumenter; +import datadog.trace.agent.tooling.InstrumenterModule; +import io.opentelemetry.api.metrics.MeterProvider; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +@AutoService(InstrumenterModule.class) +public class OpenTelemetryInstrumentation extends InstrumenterModule.Tracing + implements Instrumenter.CanShortcutTypeMatching, Instrumenter.HasMethodAdvice { + + public OpenTelemetryInstrumentation() { + super("opentelemetry.metrics", "opentelemetry-147"); + } + + @Override + protected boolean defaultEnabled() { + // return InstrumenterConfig.get().isMetricsOtelEnabled(); + return false; + } + + @Override + public String hierarchyMarkerType() { + return "io.opentelemetry.api.OpenTelemetry"; + } + + @Override + public ElementMatcher hierarchyMatcher() { + return implementsInterface(named(hierarchyMarkerType())); + } + + @Override + public String[] knownMatchingTypes() { + return new String[] { + "io.opentelemetry.api.DefaultOpenTelemetry", + "io.opentelemetry.api.GlobalOpenTelemetry$ObfuscatedOpenTelemetry" + }; + } + + @Override + public boolean onlyMatchKnownTypes() { + return isShortcutMatchingEnabled(false); + } + + @Override + public String[] helperClassNames() { + return new String[] { + "datadog.opentelemetry.shim.metrics.OtelMeter", + "datadog.opentelemetry.shim.metrics.OtelMeterBuilder", + "datadog.opentelemetry.shim.metrics.OtelMeterProvider", + }; + } + + @Override + public void methodAdvice(MethodTransformer transformer) { + // MeterProvider OpenTelemetry.getMeterProvider() + transformer.applyAdvice( + isMethod() + .and(named("getMeterProvider")) + .and(takesNoArguments()) + .and(returns(named("io.opentelemetry.api.metrics.MeterProvider"))), + OpenTelemetryInstrumentation.class.getName() + "$MeterProviderAdvice"); + } + + public static class MeterProviderAdvice { + @Advice.OnMethodExit(suppress = Throwable.class) + public static void returnProvider(@Advice.Return(readOnly = false) MeterProvider result) { + result = OtelMeterProvider.INSTANCE; + } + } +} diff --git a/internal-api/src/main/java/datadog/trace/api/InstrumenterConfig.java b/internal-api/src/main/java/datadog/trace/api/InstrumenterConfig.java index f7e3fabff2a..954db5d99c0 100644 --- a/internal-api/src/main/java/datadog/trace/api/InstrumenterConfig.java +++ b/internal-api/src/main/java/datadog/trace/api/InstrumenterConfig.java @@ -89,6 +89,9 @@ import java.util.Map; import java.util.Set; +// import static datadog.trace.api.config.OtelConfig.METRICS_OTEL_ENABLED; +// import static datadog.trace.api.ConfigDefaults.DEFAULT_METRICS_OTEL_ENABLED; + /** * This config is needed before instrumentation is applied * @@ -114,6 +117,7 @@ public class InstrumenterConfig { private final boolean codeOriginEnabled; private final boolean traceEnabled; private final boolean traceOtelEnabled; + // private final boolean metricsOtelEnabled; private final ProfilingEnablement profilingEnabled; private final boolean ciVisibilityEnabled; private final ProductActivation appSecActivation; @@ -204,6 +208,8 @@ private InstrumenterConfig() { CODE_ORIGIN_FOR_SPANS_ENABLED, DEFAULT_CODE_ORIGIN_FOR_SPANS_ENABLED); traceEnabled = configProvider.getBoolean(TRACE_ENABLED, DEFAULT_TRACE_ENABLED); traceOtelEnabled = configProvider.getBoolean(TRACE_OTEL_ENABLED, DEFAULT_TRACE_OTEL_ENABLED); + // metricsOtelEnabled = configProvider.getBoolean(METRICS_OTEL_ENABLED, + // DEFAULT_METRICS_OTEL_ENABLED); profilingEnabled = ProfilingEnablement.of( @@ -365,6 +371,10 @@ public boolean isTraceOtelEnabled() { return traceOtelEnabled; } + // public boolean isMetricsOtelEnabled() { + // return metricsOtelEnabled; + // } + public boolean isProfilingEnabled() { return profilingEnabled.isActive(); } @@ -610,6 +620,8 @@ public String toString() { + traceEnabled + ", traceOtelEnabled=" + traceOtelEnabled + // + ", metricsOtelEnabled=" + // + metricsOtelEnabled + ", profilingEnabled=" + profilingEnabled + ", ciVisibilityEnabled=" diff --git a/settings.gradle.kts b/settings.gradle.kts index 92aba9c108e..66e2627986a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -484,6 +484,7 @@ include( ":dd-java-agent:instrumentation:opensearch:transport", ":dd-java-agent:instrumentation:opentelemetry:opentelemetry-0.3", ":dd-java-agent:instrumentation:opentelemetry:opentelemetry-1.4", + ":dd-java-agent:instrumentation:opentelemetry:opentelemetry-1.47", ":dd-java-agent:instrumentation:opentelemetry:opentelemetry-annotations-1.20", ":dd-java-agent:instrumentation:opentelemetry:opentelemetry-annotations-1.26", ":dd-java-agent:instrumentation:opentracing", From 7960f838e8fec09ca71410044bcd9d87112aa58b Mon Sep 17 00:00:00 2001 From: cecile75 <32452337+cecile75@users.noreply.github.com> Date: Tue, 4 Nov 2025 15:52:33 +0100 Subject: [PATCH 2/6] trace autoinstrumentaton should still match all versions after 1.4 --- .../opentelemetry/opentelemetry-1.4/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/build.gradle b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/build.gradle index 62a6f7fa85e..976cd0970f1 100644 --- a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/build.gradle +++ b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/build.gradle @@ -4,7 +4,7 @@ muzzle { pass { module = 'opentelemetry-api' group = 'io.opentelemetry' - versions = "[$openTelemetryVersion,1.46.0)" + versions = "[$openTelemetryVersion,)" } } From 726a5f0459415219f1393f85683dabf82b5c24cc Mon Sep 17 00:00:00 2001 From: cecile75 <32452337+cecile75@users.noreply.github.com> Date: Thu, 6 Nov 2025 15:19:36 +0100 Subject: [PATCH 3/6] Add otel metrics enable config but doesn't use it --- .../OpenTelemetryInstrumentation.java | 1 + .../datadog/trace/api/InstrumenterConfig.java | 21 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.47/src/main/java/datadog/trace/instrumentation/opentelemetry147/OpenTelemetryInstrumentation.java b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.47/src/main/java/datadog/trace/instrumentation/opentelemetry147/OpenTelemetryInstrumentation.java index f3c30f86955..2f6c4b71960 100644 --- a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.47/src/main/java/datadog/trace/instrumentation/opentelemetry147/OpenTelemetryInstrumentation.java +++ b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.47/src/main/java/datadog/trace/instrumentation/opentelemetry147/OpenTelemetryInstrumentation.java @@ -25,6 +25,7 @@ public OpenTelemetryInstrumentation() { @Override protected boolean defaultEnabled() { + // Not activated yet to prevent NPE // return InstrumenterConfig.get().isMetricsOtelEnabled(); return false; } diff --git a/internal-api/src/main/java/datadog/trace/api/InstrumenterConfig.java b/internal-api/src/main/java/datadog/trace/api/InstrumenterConfig.java index e9eee3872a6..ec965cb499e 100644 --- a/internal-api/src/main/java/datadog/trace/api/InstrumenterConfig.java +++ b/internal-api/src/main/java/datadog/trace/api/InstrumenterConfig.java @@ -7,6 +7,7 @@ import static datadog.trace.api.ConfigDefaults.DEFAULT_INTEGRATIONS_ENABLED; import static datadog.trace.api.ConfigDefaults.DEFAULT_LLM_OBS_ENABLED; import static datadog.trace.api.ConfigDefaults.DEFAULT_MEASURE_METHODS; +import static datadog.trace.api.ConfigDefaults.DEFAULT_METRICS_OTEL_ENABLED; import static datadog.trace.api.ConfigDefaults.DEFAULT_RESOLVER_RESET_INTERVAL; import static datadog.trace.api.ConfigDefaults.DEFAULT_RUM_ENABLED; import static datadog.trace.api.ConfigDefaults.DEFAULT_RUNTIME_CONTEXT_FIELD_INJECTION; @@ -29,6 +30,7 @@ import static datadog.trace.api.config.GeneralConfig.TRIAGE_REPORT_TRIGGER; import static datadog.trace.api.config.IastConfig.IAST_ENABLED; import static datadog.trace.api.config.LlmObsConfig.LLMOBS_ENABLED; +import static datadog.trace.api.config.OtlpConfig.METRICS_OTEL_ENABLED; import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED; import static datadog.trace.api.config.ProfilingConfig.PROFILING_DIRECT_ALLOCATION_ENABLED_DEFAULT; import static datadog.trace.api.config.ProfilingConfig.PROFILING_ENABLED; @@ -91,9 +93,6 @@ import java.util.Map; import java.util.Set; -// import static datadog.trace.api.config.OtelConfig.METRICS_OTEL_ENABLED; -// import static datadog.trace.api.ConfigDefaults.DEFAULT_METRICS_OTEL_ENABLED; - /** * This config is needed before instrumentation is applied * @@ -119,7 +118,7 @@ public class InstrumenterConfig { private final boolean codeOriginEnabled; private final boolean traceEnabled; private final boolean traceOtelEnabled; - // private final boolean metricsOtelEnabled; + private final boolean metricsOtelEnabled; private final ProfilingEnablement profilingEnabled; private final boolean ciVisibilityEnabled; private final ProductActivation appSecActivation; @@ -213,8 +212,8 @@ private InstrumenterConfig() { CODE_ORIGIN_FOR_SPANS_ENABLED, DEFAULT_CODE_ORIGIN_FOR_SPANS_ENABLED); traceEnabled = configProvider.getBoolean(TRACE_ENABLED, DEFAULT_TRACE_ENABLED); traceOtelEnabled = configProvider.getBoolean(TRACE_OTEL_ENABLED, DEFAULT_TRACE_OTEL_ENABLED); - // metricsOtelEnabled = configProvider.getBoolean(METRICS_OTEL_ENABLED, - // DEFAULT_METRICS_OTEL_ENABLED); + metricsOtelEnabled = + configProvider.getBoolean(METRICS_OTEL_ENABLED, DEFAULT_METRICS_OTEL_ENABLED); profilingEnabled = ProfilingEnablement.of( @@ -379,9 +378,9 @@ public boolean isTraceOtelEnabled() { return traceOtelEnabled; } - // public boolean isMetricsOtelEnabled() { - // return metricsOtelEnabled; - // } + public boolean isMetricsOtelEnabled() { + return metricsOtelEnabled; + } public boolean isProfilingEnabled() { return profilingEnabled.isActive(); @@ -636,8 +635,8 @@ public String toString() { + traceEnabled + ", traceOtelEnabled=" + traceOtelEnabled - // + ", metricsOtelEnabled=" - // + metricsOtelEnabled + + ", metricsOtelEnabled=" + + metricsOtelEnabled + ", profilingEnabled=" + profilingEnabled + ", ciVisibilityEnabled=" From e78078dbbed470f9bf26466d98b6676e18969e2c Mon Sep 17 00:00:00 2001 From: cecile75 <32452337+cecile75@users.noreply.github.com> Date: Sun, 9 Nov 2025 15:07:05 +0100 Subject: [PATCH 4/6] remove useless dependencies for now --- .../opentelemetry/opentelemetry-1.47/build.gradle | 4 ---- 1 file changed, 4 deletions(-) diff --git a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.47/build.gradle b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.47/build.gradle index d1552398a33..22add70e45c 100644 --- a/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.47/build.gradle +++ b/dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.47/build.gradle @@ -17,8 +17,4 @@ dependencies { compileOnly group: 'com.google.auto.value', name: 'auto-value-annotations', version: '1.6.6' implementation project(':dd-java-agent:agent-otel:otel-shim') - - testImplementation group: 'io.opentelemetry', name: 'opentelemetry-api', version: openTelemetryVersion - testImplementation group: 'org.skyscreamer', name: 'jsonassert', version: '1.5.1' - latestDepTestImplementation group: 'io.opentelemetry', name: 'opentelemetry-api', version: '1+' } From eab6ec2b26d62829d8bfb03b4392b2b1c28f610e Mon Sep 17 00:00:00 2001 From: cecile75 <32452337+cecile75@users.noreply.github.com> Date: Tue, 11 Nov 2025 17:36:45 +0100 Subject: [PATCH 5/6] remove unused content for now --- .../opentelemetry/shim/metrics/OtelMeter.java | 27 ------------------- .../shim/metrics/OtelMeterBuilder.java | 1 - 2 files changed, 28 deletions(-) diff --git a/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeter.java b/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeter.java index 1d90c975164..994ceb10ab4 100644 --- a/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeter.java +++ b/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeter.java @@ -6,7 +6,6 @@ import io.opentelemetry.api.metrics.LongCounterBuilder; import io.opentelemetry.api.metrics.LongUpDownCounterBuilder; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.api.metrics.MeterProvider; import io.opentelemetry.api.metrics.ObservableMeasurement; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,8 +13,6 @@ // https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/1.47.0/io/opentelemetry/api/metrics/Meter.html public class OtelMeter implements Meter { private static final Logger LOGGER = LoggerFactory.getLogger(OtelMeter.class); - private static final Meter NOOP_METER = MeterProvider.noop().get("noop"); - private static final String NOOP_INSTRUMENT_NAME = "noop"; private final String instrumentationScopeName; private final String schemaUrl; @@ -67,28 +64,4 @@ public BatchCallback batchCallback( LOGGER.info("batchCallback is not yet supported"); return Meter.super.batchCallback(callback, observableMeasurement, additionalMeasurements); } - - private static boolean isInstrumentNameInvalid(String instrumentName) { - if ((null == instrumentName) - || instrumentName.isEmpty() - || instrumentName.length() > 255 - || !Character.isLetter(instrumentName.charAt(0)) - || HasAnyInvalidCharacter(instrumentName)) { - LOGGER.warn( - "Invalid instrument name {}. Instrument names must be ASCII, start with letter, contain only alphanumeric characters, '_', '.', '/', '-' and be max 255 characters.", - instrumentName); - return true; - } - return false; - } - - private static boolean HasAnyInvalidCharacter(String instrumentName) { - for (int i = 1; i < instrumentName.length(); i++) { - char c = instrumentName.charAt(i); - if (!Character.isLetterOrDigit(c) && c != '_' && c != '.' && c != '/' && c != '-') { - return true; - } - } - return false; - } } diff --git a/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeterBuilder.java b/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeterBuilder.java index 989a782954a..a489b034495 100644 --- a/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeterBuilder.java +++ b/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeterBuilder.java @@ -32,7 +32,6 @@ public MeterBuilder setInstrumentationVersion(String instrumentationVersion) { @Override public Meter build() { - LOGGER.debug("Building the OtelMeter"); return new OtelMeter(instrumentationScopeName, instrumentationVersion, schemaUrl); } } From b0b9e2009b1bac951f277123b3fca09851be8dd6 Mon Sep 17 00:00:00 2001 From: cecile75 <32452337+cecile75@users.noreply.github.com> Date: Thu, 13 Nov 2025 16:19:46 +0100 Subject: [PATCH 6/6] change HashMap to ConcurrentHashMap --- .../shim/metrics/OtelMeterProvider.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeterProvider.java b/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeterProvider.java index f8ed2fc5f6f..578c98f6130 100644 --- a/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeterProvider.java +++ b/dd-java-agent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeterProvider.java @@ -4,9 +4,9 @@ import io.opentelemetry.api.metrics.MeterBuilder; import io.opentelemetry.api.metrics.MeterProvider; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import javax.annotation.ParametersAreNonnullByDefault; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -16,11 +16,7 @@ public class OtelMeterProvider implements MeterProvider { private static final String DEFAULT_METER_NAME = ""; public static final MeterProvider INSTANCE = new OtelMeterProvider(); /** Meter instances, indexed by instrumentation scope name. */ - private final Map> meters; - - public OtelMeterProvider() { - this.meters = new HashMap<>(); - } + private final Map> scopedMeters = new ConcurrentHashMap<>(); @Override @ParametersAreNonnullByDefault @@ -34,7 +30,7 @@ public Meter get(String instrumentationScopeName, String instrumentationVersion) public Meter get( String instrumentationScopeName, String instrumentationVersion, String urlSchema) { - List meters = this.meters.get(instrumentationScopeName); + List meters = this.scopedMeters.get(instrumentationScopeName); if (meters != null) { for (Meter meter : meters) { if ((meter instanceof OtelMeter) @@ -49,8 +45,8 @@ public Meter get( .setInstrumentationVersion(instrumentationVersion) .setSchemaUrl(urlSchema) .build(); - this.meters.put(instrumentationScopeName, new ArrayList<>()); - this.meters.get(instrumentationScopeName).add(meter); + this.scopedMeters.put(instrumentationScopeName, new ArrayList<>()); + this.scopedMeters.get(instrumentationScopeName).add(meter); return meter; }