Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
34cb0c5
initial commit
cecile75 Nov 4, 2025
7960f83
trace autoinstrumentaton should still match all versions after 1.4
cecile75 Nov 4, 2025
29ddda6
Merge branch 'master' into cecile/otelmetrics13
cecile75 Nov 6, 2025
726a5f0
Add otel metrics enable config but doesn't use it
cecile75 Nov 6, 2025
e78078d
remove useless dependencies for now
cecile75 Nov 9, 2025
eab6ec2
remove unused content for now
cecile75 Nov 11, 2025
f15cec4
Merge branch 'master' into cecile/otelmetrics13
cecile75 Nov 12, 2025
b0b9e20
change HashMap to ConcurrentHashMap
cecile75 Nov 13, 2025
c38c75e
Merge remote-tracking branch 'origin/master' into cecile/otelmetrics13
mcculls Nov 24, 2025
b4d62f3
Merge remote-tracking branch 'origin/master' into cecile/otelmetrics13
mcculls Nov 24, 2025
9a690cc
Merge remote-tracking branch 'origin/master' into cecile/otelmetrics13
mcculls Nov 25, 2025
e8d0db1
Cleanup comment
mcculls Nov 25, 2025
6e318a3
Introduce instrumentation scope abstraction
mcculls Nov 26, 2025
8ba28de
Cache Otel meters by instrumentation scope (mandatory name, optional …
mcculls Nov 26, 2025
9195ad3
Align OtelTracerProvider with meter approach
mcculls Nov 26, 2025
14d8bba
Add activation test for OpenTelemetry 1.47 instrumentation (metrics s…
mcculls Nov 26, 2025
6b7803f
Merge remote-tracking branch 'origin/master' into cecile/otelmetrics13
mcculls Nov 26, 2025
1759ffb
Merge remote-tracking branch 'origin/master' into cecile/otelmetrics13
mcculls Dec 1, 2025
3cdc027
Merge remote-tracking branch 'origin/master' into cecile/otelmetrics13
mcculls Dec 2, 2025
bb4c4e1
Cleanup
mcculls Dec 2, 2025
b2ee792
Update dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.47…
mcculls Dec 3, 2025
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
@@ -0,0 +1,67 @@
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.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 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);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
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() {
return new OtelMeter(instrumentationScopeName, instrumentationVersion, schemaUrl);
}
}
Original file line number Diff line number Diff line change
@@ -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<String, List<Meter>> 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<Meter> 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);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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')
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
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() {
// Not activated yet to prevent NPE
// return InstrumenterConfig.get().isMetricsOtelEnabled();
return false;
}

@Override
public String hierarchyMarkerType() {
return "io.opentelemetry.api.OpenTelemetry";
}

@Override
public ElementMatcher<TypeDescription> 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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -116,6 +118,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;
Expand Down Expand Up @@ -209,6 +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);

profilingEnabled =
ProfilingEnablement.of(
Expand Down Expand Up @@ -373,6 +378,10 @@ public boolean isTraceOtelEnabled() {
return traceOtelEnabled;
}

public boolean isMetricsOtelEnabled() {
return metricsOtelEnabled;
}

public boolean isProfilingEnabled() {
return profilingEnabled.isActive();
}
Expand Down Expand Up @@ -626,6 +635,8 @@ public String toString() {
+ traceEnabled
+ ", traceOtelEnabled="
+ traceOtelEnabled
+ ", metricsOtelEnabled="
+ metricsOtelEnabled
+ ", profilingEnabled="
+ profilingEnabled
+ ", ciVisibilityEnabled="
Expand Down
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down