-
Notifications
You must be signed in to change notification settings - Fork 318
Add metrics OpenTelemetry instrumentation entry mechanism #9908
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
Open
cecile75
wants to merge
10
commits into
master
Choose a base branch
from
cecile/otelmetrics13
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+280
−0
Open
Changes from 7 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
34cb0c5
initial commit
cecile75 7960f83
trace autoinstrumentaton should still match all versions after 1.4
cecile75 29ddda6
Merge branch 'master' into cecile/otelmetrics13
cecile75 726a5f0
Add otel metrics enable config but doesn't use it
cecile75 e78078d
remove useless dependencies for now
cecile75 eab6ec2
remove unused content for now
cecile75 f15cec4
Merge branch 'master' into cecile/otelmetrics13
cecile75 b0b9e20
change HashMap to ConcurrentHashMap
cecile75 c38c75e
Merge remote-tracking branch 'origin/master' into cecile/otelmetrics13
mcculls b4d62f3
Merge remote-tracking branch 'origin/master' into cecile/otelmetrics13
mcculls File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
67 changes: 67 additions & 0 deletions
67
...gent/agent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeter.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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); | ||
| } | ||
| } |
37 changes: 37 additions & 0 deletions
37
...ent-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeterBuilder.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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); | ||
| } | ||
| } |
66 changes: 66 additions & 0 deletions
66
...nt-otel/otel-shim/src/main/java/datadog/opentelemetry/shim/metrics/OtelMeterProvider.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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); | ||
| } | ||
| } | ||
20 changes: 20 additions & 0 deletions
20
dd-java-agent/instrumentation/opentelemetry/opentelemetry-1.47/build.gradle
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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') | ||
| } |
82 changes: 82 additions & 0 deletions
82
...ain/java/datadog/trace/instrumentation/opentelemetry147/OpenTelemetryInstrumentation.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Users may call this from different threads, so the map needs to handle concurrent updates.
Also
finalfields can be assigned in the same line, avoiding the need to do that in the constructor.This can mean you can drop the constructor completely, making the code more concise.
Lastly I would call this field
scopedMetersbecause it holds meters indexed by scope.(This helps make the code clearer later on when you query
scopedMetersand store the list of meters for that scope in a variable calledmeters)