Skip to content

Commit 34cb0c5

Browse files
committed
initial commit
1 parent 4a1b258 commit 34cb0c5

File tree

8 files changed

+317
-1
lines changed

8 files changed

+317
-1
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package datadog.opentelemetry.shim.metrics;
2+
3+
import io.opentelemetry.api.metrics.BatchCallback;
4+
import io.opentelemetry.api.metrics.DoubleGaugeBuilder;
5+
import io.opentelemetry.api.metrics.DoubleHistogramBuilder;
6+
import io.opentelemetry.api.metrics.LongCounterBuilder;
7+
import io.opentelemetry.api.metrics.LongUpDownCounterBuilder;
8+
import io.opentelemetry.api.metrics.Meter;
9+
import io.opentelemetry.api.metrics.MeterProvider;
10+
import io.opentelemetry.api.metrics.ObservableMeasurement;
11+
import org.slf4j.Logger;
12+
import org.slf4j.LoggerFactory;
13+
14+
// https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api/1.47.0/io/opentelemetry/api/metrics/Meter.html
15+
public class OtelMeter implements Meter {
16+
private static final Logger LOGGER = LoggerFactory.getLogger(OtelMeter.class);
17+
private static final Meter NOOP_METER = MeterProvider.noop().get("noop");
18+
private static final String NOOP_INSTRUMENT_NAME = "noop";
19+
20+
private final String instrumentationScopeName;
21+
private final String schemaUrl;
22+
private final String instrumentationVersion;
23+
24+
public OtelMeter(
25+
String instrumentationScopeName, String schemaUrl, String instrumentationVersion) {
26+
this.instrumentationScopeName = instrumentationScopeName;
27+
this.schemaUrl = schemaUrl;
28+
this.instrumentationVersion = instrumentationVersion;
29+
}
30+
31+
public boolean match(
32+
String instrumentationScopeName, String instrumentationVersion, String schemaUrl) {
33+
return instrumentationScopeName.equals(this.instrumentationScopeName)
34+
&& schemaUrl.equals(this.schemaUrl)
35+
&& instrumentationVersion.equals(this.instrumentationVersion);
36+
}
37+
38+
@Override
39+
public LongCounterBuilder counterBuilder(String instrumentName) {
40+
LOGGER.info("CounterBuilder is not yet supported");
41+
return null;
42+
}
43+
44+
@Override
45+
public LongUpDownCounterBuilder upDownCounterBuilder(String instrumentName) {
46+
LOGGER.info("upDownCounterBuilder is not yet supported");
47+
return null;
48+
}
49+
50+
@Override
51+
public DoubleHistogramBuilder histogramBuilder(String instrumentName) {
52+
LOGGER.info("histogramBuilder is not yet supported");
53+
return null;
54+
}
55+
56+
@Override
57+
public DoubleGaugeBuilder gaugeBuilder(String instrumentName) {
58+
LOGGER.info("gaugeBuilder is not yet supported");
59+
return null;
60+
}
61+
62+
@Override
63+
public BatchCallback batchCallback(
64+
Runnable callback,
65+
ObservableMeasurement observableMeasurement,
66+
ObservableMeasurement... additionalMeasurements) {
67+
LOGGER.info("batchCallback is not yet supported");
68+
return Meter.super.batchCallback(callback, observableMeasurement, additionalMeasurements);
69+
}
70+
71+
private static boolean isInstrumentNameInvalid(String instrumentName) {
72+
if ((null == instrumentName)
73+
|| instrumentName.isEmpty()
74+
|| instrumentName.length() > 255
75+
|| !Character.isLetter(instrumentName.charAt(0))
76+
|| HasAnyInvalidCharacter(instrumentName)) {
77+
LOGGER.warn(
78+
"Invalid instrument name {}. Instrument names must be ASCII, start with letter, contain only alphanumeric characters, '_', '.', '/', '-' and be max 255 characters.",
79+
instrumentName);
80+
return true;
81+
}
82+
return false;
83+
}
84+
85+
private static boolean HasAnyInvalidCharacter(String instrumentName) {
86+
for (int i = 1; i < instrumentName.length(); i++) {
87+
char c = instrumentName.charAt(i);
88+
if (!Character.isLetterOrDigit(c) && c != '_' && c != '.' && c != '/' && c != '-') {
89+
return true;
90+
}
91+
}
92+
return false;
93+
}
94+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package datadog.opentelemetry.shim.metrics;
2+
3+
import io.opentelemetry.api.metrics.Meter;
4+
import io.opentelemetry.api.metrics.MeterBuilder;
5+
import javax.annotation.ParametersAreNonnullByDefault;
6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
8+
9+
public class OtelMeterBuilder implements MeterBuilder {
10+
private static final Logger LOGGER = LoggerFactory.getLogger(OtelMeterBuilder.class);
11+
private final String instrumentationScopeName;
12+
private String schemaUrl;
13+
private String instrumentationVersion;
14+
15+
public OtelMeterBuilder(String instrumentationScopeName) {
16+
this.instrumentationScopeName = instrumentationScopeName;
17+
}
18+
19+
@Override
20+
@ParametersAreNonnullByDefault
21+
public MeterBuilder setSchemaUrl(String schemaUrl) {
22+
this.schemaUrl = schemaUrl;
23+
return this;
24+
}
25+
26+
@Override
27+
@ParametersAreNonnullByDefault
28+
public MeterBuilder setInstrumentationVersion(String instrumentationVersion) {
29+
this.instrumentationVersion = instrumentationVersion;
30+
return this;
31+
}
32+
33+
@Override
34+
public Meter build() {
35+
LOGGER.debug("Building the OtelMeter");
36+
return new OtelMeter(instrumentationScopeName, instrumentationVersion, schemaUrl);
37+
}
38+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package datadog.opentelemetry.shim.metrics;
2+
3+
import io.opentelemetry.api.metrics.Meter;
4+
import io.opentelemetry.api.metrics.MeterBuilder;
5+
import io.opentelemetry.api.metrics.MeterProvider;
6+
import java.util.ArrayList;
7+
import java.util.HashMap;
8+
import java.util.List;
9+
import java.util.Map;
10+
import javax.annotation.ParametersAreNonnullByDefault;
11+
import org.slf4j.Logger;
12+
import org.slf4j.LoggerFactory;
13+
14+
public class OtelMeterProvider implements MeterProvider {
15+
private static final Logger LOGGER = LoggerFactory.getLogger(OtelMeterProvider.class);
16+
private static final String DEFAULT_METER_NAME = "";
17+
public static final MeterProvider INSTANCE = new OtelMeterProvider();
18+
/** Meter instances, indexed by instrumentation scope name. */
19+
private final Map<String, List<Meter>> meters;
20+
21+
public OtelMeterProvider() {
22+
this.meters = new HashMap<>();
23+
}
24+
25+
@Override
26+
@ParametersAreNonnullByDefault
27+
public Meter get(String instrumentationScopeName) {
28+
return get(instrumentationScopeName, null);
29+
}
30+
31+
public Meter get(String instrumentationScopeName, String instrumentationVersion) {
32+
return get(instrumentationScopeName, instrumentationVersion, null);
33+
}
34+
35+
public Meter get(
36+
String instrumentationScopeName, String instrumentationVersion, String urlSchema) {
37+
List<Meter> meters = this.meters.get(instrumentationScopeName);
38+
if (meters != null) {
39+
for (Meter meter : meters) {
40+
if ((meter instanceof OtelMeter)
41+
&& ((OtelMeter) meter)
42+
.match(instrumentationScopeName, instrumentationVersion, urlSchema)) {
43+
return meter;
44+
}
45+
}
46+
}
47+
Meter meter =
48+
meterBuilder(instrumentationScopeName)
49+
.setInstrumentationVersion(instrumentationVersion)
50+
.setSchemaUrl(urlSchema)
51+
.build();
52+
this.meters.put(instrumentationScopeName, new ArrayList<>());
53+
this.meters.get(instrumentationScopeName).add(meter);
54+
55+
return meter;
56+
}
57+
58+
@Override
59+
public MeterBuilder meterBuilder(String instrumentationScopeName) {
60+
if (instrumentationScopeName.trim().isEmpty()) {
61+
LOGGER.debug("Meter requested without instrumentation scope name.");
62+
instrumentationScopeName = DEFAULT_METER_NAME;
63+
}
64+
return new OtelMeterBuilder(instrumentationScopeName);
65+
}
66+
}

dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.4/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ muzzle {
44
pass {
55
module = 'opentelemetry-api'
66
group = 'io.opentelemetry'
7-
versions = "[$openTelemetryVersion,)"
7+
versions = "[$openTelemetryVersion,1.46.0)"
88
}
99
}
1010

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
def openTelemetryVersion = '1.47.0'
2+
3+
muzzle {
4+
pass {
5+
module = 'opentelemetry-api'
6+
group = 'io.opentelemetry'
7+
versions = "[$openTelemetryVersion,)"
8+
}
9+
}
10+
11+
apply from: "$rootDir/gradle/java.gradle"
12+
13+
addTestSuiteForDir('latestDepTest', 'test')
14+
15+
dependencies {
16+
compileOnly group: 'io.opentelemetry', name: 'opentelemetry-api', version: openTelemetryVersion
17+
compileOnly group: 'com.google.auto.value', name: 'auto-value-annotations', version: '1.6.6'
18+
19+
implementation project(':dd-java-agent:agent-otel:otel-shim')
20+
21+
testImplementation group: 'io.opentelemetry', name: 'opentelemetry-api', version: openTelemetryVersion
22+
testImplementation group: 'org.skyscreamer', name: 'jsonassert', version: '1.5.1'
23+
latestDepTestImplementation group: 'io.opentelemetry', name: 'opentelemetry-api', version: '1+'
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package datadog.trace.instrumentation.opentelemetry147;
2+
3+
import static datadog.trace.agent.tooling.bytebuddy.matcher.HierarchyMatchers.implementsInterface;
4+
import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named;
5+
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
6+
import static net.bytebuddy.matcher.ElementMatchers.returns;
7+
import static net.bytebuddy.matcher.ElementMatchers.takesNoArguments;
8+
9+
import com.google.auto.service.AutoService;
10+
import datadog.opentelemetry.shim.metrics.OtelMeterProvider;
11+
import datadog.trace.agent.tooling.Instrumenter;
12+
import datadog.trace.agent.tooling.InstrumenterModule;
13+
import io.opentelemetry.api.metrics.MeterProvider;
14+
import net.bytebuddy.asm.Advice;
15+
import net.bytebuddy.description.type.TypeDescription;
16+
import net.bytebuddy.matcher.ElementMatcher;
17+
18+
@AutoService(InstrumenterModule.class)
19+
public class OpenTelemetryInstrumentation extends InstrumenterModule.Tracing
20+
implements Instrumenter.CanShortcutTypeMatching, Instrumenter.HasMethodAdvice {
21+
22+
public OpenTelemetryInstrumentation() {
23+
super("opentelemetry.metrics", "opentelemetry-147");
24+
}
25+
26+
@Override
27+
protected boolean defaultEnabled() {
28+
// return InstrumenterConfig.get().isMetricsOtelEnabled();
29+
return false;
30+
}
31+
32+
@Override
33+
public String hierarchyMarkerType() {
34+
return "io.opentelemetry.api.OpenTelemetry";
35+
}
36+
37+
@Override
38+
public ElementMatcher<TypeDescription> hierarchyMatcher() {
39+
return implementsInterface(named(hierarchyMarkerType()));
40+
}
41+
42+
@Override
43+
public String[] knownMatchingTypes() {
44+
return new String[] {
45+
"io.opentelemetry.api.DefaultOpenTelemetry",
46+
"io.opentelemetry.api.GlobalOpenTelemetry$ObfuscatedOpenTelemetry"
47+
};
48+
}
49+
50+
@Override
51+
public boolean onlyMatchKnownTypes() {
52+
return isShortcutMatchingEnabled(false);
53+
}
54+
55+
@Override
56+
public String[] helperClassNames() {
57+
return new String[] {
58+
"datadog.opentelemetry.shim.metrics.OtelMeter",
59+
"datadog.opentelemetry.shim.metrics.OtelMeterBuilder",
60+
"datadog.opentelemetry.shim.metrics.OtelMeterProvider",
61+
};
62+
}
63+
64+
@Override
65+
public void methodAdvice(MethodTransformer transformer) {
66+
// MeterProvider OpenTelemetry.getMeterProvider()
67+
transformer.applyAdvice(
68+
isMethod()
69+
.and(named("getMeterProvider"))
70+
.and(takesNoArguments())
71+
.and(returns(named("io.opentelemetry.api.metrics.MeterProvider"))),
72+
OpenTelemetryInstrumentation.class.getName() + "$MeterProviderAdvice");
73+
}
74+
75+
public static class MeterProviderAdvice {
76+
@Advice.OnMethodExit(suppress = Throwable.class)
77+
public static void returnProvider(@Advice.Return(readOnly = false) MeterProvider result) {
78+
result = OtelMeterProvider.INSTANCE;
79+
}
80+
}
81+
}

internal-api/src/main/java/datadog/trace/api/InstrumenterConfig.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@
8989
import java.util.Map;
9090
import java.util.Set;
9191

92+
// import static datadog.trace.api.config.OtelConfig.METRICS_OTEL_ENABLED;
93+
// import static datadog.trace.api.ConfigDefaults.DEFAULT_METRICS_OTEL_ENABLED;
94+
9295
/**
9396
* This config is needed before instrumentation is applied
9497
*
@@ -114,6 +117,7 @@ public class InstrumenterConfig {
114117
private final boolean codeOriginEnabled;
115118
private final boolean traceEnabled;
116119
private final boolean traceOtelEnabled;
120+
// private final boolean metricsOtelEnabled;
117121
private final ProfilingEnablement profilingEnabled;
118122
private final boolean ciVisibilityEnabled;
119123
private final ProductActivation appSecActivation;
@@ -204,6 +208,8 @@ private InstrumenterConfig() {
204208
CODE_ORIGIN_FOR_SPANS_ENABLED, DEFAULT_CODE_ORIGIN_FOR_SPANS_ENABLED);
205209
traceEnabled = configProvider.getBoolean(TRACE_ENABLED, DEFAULT_TRACE_ENABLED);
206210
traceOtelEnabled = configProvider.getBoolean(TRACE_OTEL_ENABLED, DEFAULT_TRACE_OTEL_ENABLED);
211+
// metricsOtelEnabled = configProvider.getBoolean(METRICS_OTEL_ENABLED,
212+
// DEFAULT_METRICS_OTEL_ENABLED);
207213

208214
profilingEnabled =
209215
ProfilingEnablement.of(
@@ -365,6 +371,10 @@ public boolean isTraceOtelEnabled() {
365371
return traceOtelEnabled;
366372
}
367373

374+
// public boolean isMetricsOtelEnabled() {
375+
// return metricsOtelEnabled;
376+
// }
377+
368378
public boolean isProfilingEnabled() {
369379
return profilingEnabled.isActive();
370380
}
@@ -610,6 +620,8 @@ public String toString() {
610620
+ traceEnabled
611621
+ ", traceOtelEnabled="
612622
+ traceOtelEnabled
623+
// + ", metricsOtelEnabled="
624+
// + metricsOtelEnabled
613625
+ ", profilingEnabled="
614626
+ profilingEnabled
615627
+ ", ciVisibilityEnabled="

settings.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,7 @@ include(
484484
":dd-java-agent:instrumentation:opensearch:transport",
485485
":dd-java-agent:instrumentation:opentelemetry:opentelemetry-0.3",
486486
":dd-java-agent:instrumentation:opentelemetry:opentelemetry-1.4",
487+
":dd-java-agent:instrumentation:opentelemetry:opentelemetry-1.47",
487488
":dd-java-agent:instrumentation:opentelemetry:opentelemetry-annotations-1.20",
488489
":dd-java-agent:instrumentation:opentelemetry:opentelemetry-annotations-1.26",
489490
":dd-java-agent:instrumentation:opentracing",

0 commit comments

Comments
 (0)