Skip to content

Commit 2d498b9

Browse files
authored
Add instrumentation type to instrumenter customizer (#15227)
1 parent 7555b7a commit 2d498b9

File tree

5 files changed

+101
-2
lines changed

5 files changed

+101
-2
lines changed

instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/instrumenter/InstrumenterCustomizer.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
1212
import io.opentelemetry.instrumentation.api.instrumenter.OperationMetrics;
1313
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
14+
import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor;
1415
import java.util.function.Function;
1516
import java.util.function.UnaryOperator;
1617

@@ -33,6 +34,16 @@ public interface InstrumenterCustomizer {
3334
*/
3435
String getInstrumentationName();
3536

37+
/**
38+
* Tests whether given instrumenter produces telemetry of specified type. Instrumentation type is
39+
* detected based on the standard {@link AttributesExtractor} implementations used by this
40+
* instrumenter e.g. instrumenters that use {@link HttpClientAttributesExtractor} have {@link
41+
* InstrumentationType#HTTP_CLIENT} type.
42+
*
43+
* @return the name of the instrumentation this customizer targets
44+
*/
45+
boolean hasType(InstrumentationType type);
46+
3647
/**
3748
* Adds a single {@link AttributesExtractor} to the instrumenter. This extractor will be used to
3849
* extract attributes from requests and responses during the request lifecycle.
@@ -94,4 +105,16 @@ default InstrumenterCustomizer setSpanNameExtractor(
94105
*/
95106
InstrumenterCustomizer setSpanNameExtractor(
96107
UnaryOperator<SpanNameExtractor<?>> spanNameExtractor);
108+
109+
/** Types of instrumentation. */
110+
enum InstrumentationType {
111+
HTTP_CLIENT,
112+
HTTP_SERVER,
113+
DB_CLIENT,
114+
RPC_CLIENT,
115+
RPC_SERVER,
116+
MESSAGING_PRODUCER,
117+
MESSAGING_CONSUMER_RECEIVE,
118+
MESSAGING_CONSUMER_PROCESS
119+
}
97120
}

instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/instrumenter/internal/InstrumenterCustomizerImpl.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
import io.opentelemetry.instrumentation.api.instrumenter.OperationMetrics;
1212
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
1313
import io.opentelemetry.instrumentation.api.internal.InternalInstrumenterCustomizer;
14+
import io.opentelemetry.instrumentation.api.internal.SpanKey;
15+
import java.util.HashMap;
16+
import java.util.Map;
1417
import java.util.function.UnaryOperator;
1518

1619
/**
@@ -19,6 +22,19 @@
1922
*/
2023
@SuppressWarnings({"unchecked", "rawtypes"})
2124
public final class InstrumenterCustomizerImpl implements InstrumenterCustomizer {
25+
private static final Map<InstrumentationType, SpanKey> typeToSpanKey = new HashMap<>();
26+
27+
static {
28+
typeToSpanKey.put(InstrumentationType.HTTP_CLIENT, SpanKey.HTTP_CLIENT);
29+
typeToSpanKey.put(InstrumentationType.HTTP_SERVER, SpanKey.HTTP_SERVER);
30+
typeToSpanKey.put(InstrumentationType.DB_CLIENT, SpanKey.DB_CLIENT);
31+
typeToSpanKey.put(InstrumentationType.RPC_CLIENT, SpanKey.RPC_CLIENT);
32+
typeToSpanKey.put(InstrumentationType.RPC_SERVER, SpanKey.RPC_SERVER);
33+
typeToSpanKey.put(InstrumentationType.MESSAGING_PRODUCER, SpanKey.PRODUCER);
34+
typeToSpanKey.put(InstrumentationType.MESSAGING_CONSUMER_RECEIVE, SpanKey.CONSUMER_RECEIVE);
35+
typeToSpanKey.put(InstrumentationType.MESSAGING_CONSUMER_PROCESS, SpanKey.CONSUMER_RECEIVE);
36+
}
37+
2238
private final InternalInstrumenterCustomizer customizer;
2339

2440
public InstrumenterCustomizerImpl(InternalInstrumenterCustomizer customizer) {
@@ -30,6 +46,15 @@ public String getInstrumentationName() {
3046
return customizer.getInstrumentationName();
3147
}
3248

49+
@Override
50+
public boolean hasType(InstrumentationType type) {
51+
SpanKey spanKey = typeToSpanKey.get(type);
52+
if (spanKey == null) {
53+
throw new IllegalArgumentException("unexpected instrumentation type: " + type);
54+
}
55+
return customizer.hasType(spanKey);
56+
}
57+
3358
@Override
3459
public InstrumenterCustomizer addAttributesExtractor(AttributesExtractor<?, ?> extractor) {
3560
customizer.addAttributesExtractor(extractor);

instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/InstrumenterBuilder.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,15 +395,26 @@ private void propagateOperationListenersToOnEnd() {
395395

396396
private static <REQUEST, RESPONSE> void applyCustomizers(
397397
InstrumenterBuilder<REQUEST, RESPONSE> builder) {
398-
for (InternalInstrumenterCustomizerProvider provider :
399-
InternalInstrumenterCustomizerUtil.getInstrumenterCustomizerProviders()) {
398+
List<InternalInstrumenterCustomizerProvider> customizerProviders =
399+
InternalInstrumenterCustomizerUtil.getInstrumenterCustomizerProviders();
400+
if (customizerProviders.isEmpty()) {
401+
return;
402+
}
403+
404+
Set<SpanKey> spanKeys = builder.getSpanKeysFromAttributesExtractors();
405+
for (InternalInstrumenterCustomizerProvider provider : customizerProviders) {
400406
provider.customize(
401407
new InternalInstrumenterCustomizer<REQUEST, RESPONSE>() {
402408
@Override
403409
public String getInstrumentationName() {
404410
return builder.instrumentationName;
405411
}
406412

413+
@Override
414+
public boolean hasType(SpanKey type) {
415+
return spanKeys.contains(type);
416+
}
417+
407418
@Override
408419
public void addAttributesExtractor(AttributesExtractor<REQUEST, RESPONSE> extractor) {
409420
builder.addAttributesExtractor(extractor);

instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/InternalInstrumenterCustomizer.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ public interface InternalInstrumenterCustomizer<REQUEST, RESPONSE> {
1919

2020
String getInstrumentationName();
2121

22+
boolean hasType(SpanKey type);
23+
2224
void addAttributesExtractor(AttributesExtractor<REQUEST, RESPONSE> extractor);
2325

2426
void addAttributesExtractors(

instrumentation-api/src/test/java/io/opentelemetry/instrumentation/api/internal/InstrumentationCustomizerTest.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import io.opentelemetry.api.trace.SpanId;
2323
import io.opentelemetry.api.trace.SpanKind;
2424
import io.opentelemetry.context.Context;
25+
import io.opentelemetry.instrumentation.api.incubator.instrumenter.InstrumenterCustomizer.InstrumentationType;
2526
import io.opentelemetry.instrumentation.api.incubator.instrumenter.InstrumenterCustomizerProvider;
2627
import io.opentelemetry.instrumentation.api.incubator.instrumenter.internal.InternalInstrumenterCustomizerProviderImpl;
2728
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
@@ -110,6 +111,43 @@ void testGetInstrumentationName() {
110111
assertThat(customizerCalled).isTrue();
111112
}
112113

114+
@Test
115+
void testHasType() {
116+
AtomicBoolean customizerCalled = new AtomicBoolean();
117+
setCustomizer(
118+
customizer -> {
119+
customizerCalled.set(true);
120+
assertThat(customizer.hasType(InstrumentationType.HTTP_CLIENT)).isTrue();
121+
assertThat(customizer.hasType(InstrumentationType.HTTP_SERVER)).isFalse();
122+
});
123+
124+
class TestAttributesExtractor implements AttributesExtractor<Object, Object>, SpanKeyProvider {
125+
@Override
126+
public void onStart(AttributesBuilder attributes, Context parentContext, Object request) {}
127+
128+
@Override
129+
public void onEnd(
130+
AttributesBuilder attributes,
131+
Context context,
132+
Object request,
133+
@Nullable Object response,
134+
@Nullable Throwable error) {}
135+
136+
@Nullable
137+
@Override
138+
public SpanKey internalGetSpanKey() {
139+
return SpanKey.HTTP_CLIENT;
140+
}
141+
}
142+
143+
Instrumenter.<Map<String, String>, Map<String, String>>builder(
144+
otelTesting.getOpenTelemetry(), "test", unused -> "span")
145+
.addAttributesExtractor(new TestAttributesExtractor())
146+
.buildInstrumenter();
147+
148+
assertThat(customizerCalled).isTrue();
149+
}
150+
113151
@Test
114152
void testAddAttributesExtractor() {
115153
AtomicBoolean customizerCalled = new AtomicBoolean();

0 commit comments

Comments
 (0)