Skip to content

Commit 159e53d

Browse files
committed
Refactor extension to be consistent with existence.
1 parent 7109962 commit 159e53d

File tree

7 files changed

+263
-187
lines changed

7 files changed

+263
-187
lines changed
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
Comparing source compatibility of opentelemetry-instrumentation-api-2.17.0-SNAPSHOT.jar against opentelemetry-instrumentation-api-2.16.0.jar
2-
No changes.
2+
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder (not serializable)
3+
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
4+
GENERIC TEMPLATES: === REQUEST:java.lang.Object, === RESPONSE:java.lang.Object
5+
*** MODIFIED FIELD: PUBLIC (<- PACKAGE_PROTECTED) NON_FINAL (<- FINAL) io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor<? super REQUEST><? super REQUEST> spanNameExtractor

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

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121
import io.opentelemetry.context.propagation.TextMapSetter;
2222
import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
2323
import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties;
24-
import io.opentelemetry.instrumentation.api.internal.InstrumentationCustomizer;
2524
import io.opentelemetry.instrumentation.api.internal.InstrumenterBuilderAccess;
25+
import io.opentelemetry.instrumentation.api.internal.InstrumenterCustomizer;
26+
import io.opentelemetry.instrumentation.api.internal.InstrumenterCustomizerImpl;
27+
import io.opentelemetry.instrumentation.api.internal.InstrumenterCustomizerProvider;
2628
import io.opentelemetry.instrumentation.api.internal.InstrumenterUtil;
2729
import io.opentelemetry.instrumentation.api.internal.SchemaUrlProvider;
2830
import io.opentelemetry.instrumentation.api.internal.ServiceLoaderUtil;
@@ -33,7 +35,6 @@
3335
import java.util.List;
3436
import java.util.Map;
3537
import java.util.Set;
36-
import java.util.function.Predicate;
3738
import java.util.logging.Logger;
3839
import java.util.stream.Collectors;
3940
import java.util.stream.Stream;
@@ -56,7 +57,7 @@ public final class InstrumenterBuilder<REQUEST, RESPONSE> {
5657

5758
final OpenTelemetry openTelemetry;
5859
final String instrumentationName;
59-
SpanNameExtractor<? super REQUEST> spanNameExtractor;
60+
public SpanNameExtractor<? super REQUEST> spanNameExtractor;
6061

6162
final List<SpanLinksExtractor<? super REQUEST>> spanLinksExtractors = new ArrayList<>();
6263
final List<AttributesExtractor<? super REQUEST, ? super RESPONSE>> attributesExtractors =
@@ -74,16 +75,19 @@ public final class InstrumenterBuilder<REQUEST, RESPONSE> {
7475
boolean propagateOperationListenersToOnEnd = false;
7576
boolean enabled = true;
7677

77-
private static final Map<Predicate<String>, List<InstrumentationCustomizer>>
78+
private static final Map<String, List<InstrumenterCustomizerProvider>>
7879
INSTRUMENTATION_CUSTOMIZER_MAP = new HashMap<>();
7980

8081
static {
81-
List<InstrumentationCustomizer> customizers =
82-
ServiceLoaderUtil.load(InstrumentationCustomizer.class);
83-
for (InstrumentationCustomizer customizer : customizers) {
84-
INSTRUMENTATION_CUSTOMIZER_MAP
85-
.computeIfAbsent(customizer.instrumentationNamePredicate(), k -> new ArrayList<>())
86-
.add(customizer);
82+
List<InstrumenterCustomizerProvider> providers =
83+
ServiceLoaderUtil.load(InstrumenterCustomizerProvider.class);
84+
for (InstrumenterCustomizerProvider provider : providers) {
85+
String instrumentationName = provider.getInstrumentationName();
86+
if (instrumentationName != null) {
87+
INSTRUMENTATION_CUSTOMIZER_MAP
88+
.computeIfAbsent(instrumentationName, k -> new ArrayList<>())
89+
.add(provider);
90+
}
8791
}
8892
}
8993

@@ -299,30 +303,24 @@ public Instrumenter<REQUEST, RESPONSE> buildInstrumenter(
299303
private Instrumenter<REQUEST, RESPONSE> buildInstrumenter(
300304
InstrumenterConstructor<REQUEST, RESPONSE> constructor,
301305
SpanKindExtractor<? super REQUEST> spanKindExtractor) {
302-
List<InstrumentationCustomizer> customizers =
303-
INSTRUMENTATION_CUSTOMIZER_MAP.entrySet().stream()
304-
.filter(entry -> entry.getKey().test(instrumentationName))
305-
.flatMap(entry -> entry.getValue().stream())
306-
.collect(Collectors.toList());
307-
if (customizers != null) {
308-
for (InstrumentationCustomizer customizer : customizers) {
309-
if (customizer.getContextCustomizer() != null) {
310-
addContextCustomizer(customizer.getContextCustomizer());
311-
}
312-
if (customizer.getAttributesExtractor() != null) {
313-
addAttributesExtractor(customizer.getAttributesExtractor());
314-
}
315-
if (customizer.getAttributesExtractors() != null) {
316-
addAttributesExtractors(customizer.getAttributesExtractors());
317-
}
318-
if (customizer.getOperationMetrics() != null) {
319-
addOperationMetrics(customizer.getOperationMetrics());
320-
}
321-
if (customizer.getSpanNameExtractor() != null) {
322-
this.spanNameExtractor = customizer.getSpanNameExtractor();
323-
}
306+
307+
List<InstrumenterCustomizerProvider> providers =
308+
INSTRUMENTATION_CUSTOMIZER_MAP.get(instrumentationName);
309+
310+
if (providers != null && !providers.isEmpty()) {
311+
InstrumenterCustomizer customizer =
312+
new InstrumenterCustomizerImpl(this) {
313+
@Override
314+
public String getInstrumentationName() {
315+
return instrumentationName;
316+
}
317+
};
318+
319+
for (InstrumenterCustomizerProvider provider : providers) {
320+
provider.customize(customizer);
324321
}
325322
}
323+
326324
this.spanKindExtractor = spanKindExtractor;
327325
return constructor.create(this);
328326
}

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

Lines changed: 0 additions & 98 deletions
This file was deleted.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.api.internal;
7+
8+
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
9+
import io.opentelemetry.instrumentation.api.instrumenter.ContextCustomizer;
10+
import io.opentelemetry.instrumentation.api.instrumenter.OperationMetrics;
11+
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
12+
import java.util.function.Function;
13+
14+
/**
15+
* A service provider interface (SPI) for providing customizations for instrumentation, including
16+
* operation metrics, attributes extraction, and context customization.
17+
*
18+
* <p>This allows external modules or plugins to contribute custom logic for specific instrumented
19+
* libraries, without modifying core instrumentation code. This class is internal and is hence not
20+
* for public use. Its APIs are unstable and can change at any time.
21+
*/
22+
public interface InstrumenterCustomizer {
23+
24+
/**
25+
* Returns the name of the instrumentation that this customizer applies to. This allows for
26+
* efficient mapping of customizers to specific instrumentations rather than using predicates for
27+
* matching.
28+
*
29+
* @return the name of the instrumentation this customizer targets
30+
*/
31+
String getInstrumentationName();
32+
33+
/**
34+
* Adds a single AttributesExtractor to the instrumenter. This extractor will be used to extract
35+
* attributes from requests and responses during span creation and enrichment.
36+
*
37+
* @param extractor the attributes extractor to add
38+
* @return this InstrumenterCustomizer for method chaining
39+
*/
40+
InstrumenterCustomizer addAttributesExtractor(AttributesExtractor<?, ?> extractor);
41+
42+
/**
43+
* Adds multiple AttributesExtractors to the instrumenter. These extractors will be used to
44+
* extract attributes from requests and responses during span creation and enrichment.
45+
*
46+
* @param extractors the collection of attributes extractors to add
47+
* @return this InstrumenterCustomizer for method chaining
48+
*/
49+
InstrumenterCustomizer addAttributesExtractors(
50+
Iterable<? extends AttributesExtractor<?, ?>> extractors);
51+
52+
/**
53+
* Adds an OperationMetrics implementation to the instrumenter. This will be used to create
54+
* metrics capturing the request processing metrics for the instrumented operations.
55+
*
56+
* @param operationMetrics the metrics factory to add
57+
* @return this InstrumenterCustomizer for method chaining
58+
*/
59+
InstrumenterCustomizer addOperationMetrics(OperationMetrics operationMetrics);
60+
61+
/**
62+
* Sets a ContextCustomizer for the instrumenter. The customizer will modify the context during
63+
* the Instrumenter.start() operation, allowing custom context propagation or enrichment.
64+
*
65+
* @param customizer the context customizer to set
66+
* @return this InstrumenterCustomizer for method chaining
67+
*/
68+
InstrumenterCustomizer addContextCustomizer(ContextCustomizer<?> customizer);
69+
70+
/**
71+
* Sets a transformer function that will modify the SpanNameExtractor. This allows customizing how
72+
* span names are generated for the instrumented operations.
73+
*
74+
* @param spanNameExtractorTransformer function that transforms the original span name extractor
75+
* @return this InstrumenterCustomizer for method chaining
76+
*/
77+
InstrumenterCustomizer setSpanNameExtractor(
78+
Function<SpanNameExtractor<?>, SpanNameExtractor<?>> spanNameExtractorTransformer);
79+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.api.internal;
7+
8+
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
9+
import io.opentelemetry.instrumentation.api.instrumenter.ContextCustomizer;
10+
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
11+
import io.opentelemetry.instrumentation.api.instrumenter.OperationMetrics;
12+
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
13+
import java.util.function.Function;
14+
15+
/**
16+
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
17+
* any time.
18+
*/
19+
public abstract class InstrumenterCustomizerImpl implements InstrumenterCustomizer {
20+
21+
private final InstrumenterBuilder<?, ?> builder;
22+
23+
public InstrumenterCustomizerImpl(InstrumenterBuilder<?, ?> builder) {
24+
this.builder = builder;
25+
}
26+
27+
@Override
28+
@SuppressWarnings("unchecked")
29+
public InstrumenterCustomizer addAttributesExtractor(AttributesExtractor<?, ?> extractor) {
30+
builder.addAttributesExtractor((AttributesExtractor<Object, Object>) extractor);
31+
return this;
32+
}
33+
34+
@Override
35+
@SuppressWarnings("unchecked")
36+
public InstrumenterCustomizer addAttributesExtractors(
37+
Iterable<? extends AttributesExtractor<?, ?>> extractors) {
38+
builder.addAttributesExtractors((Iterable<AttributesExtractor<Object, Object>>) extractors);
39+
return this;
40+
}
41+
42+
@Override
43+
public InstrumenterCustomizer addOperationMetrics(OperationMetrics operationMetrics) {
44+
builder.addOperationMetrics(operationMetrics);
45+
return this;
46+
}
47+
48+
@Override
49+
@SuppressWarnings("unchecked")
50+
public InstrumenterCustomizer addContextCustomizer(ContextCustomizer<?> customizer) {
51+
builder.addContextCustomizer((ContextCustomizer<Object>) customizer);
52+
return this;
53+
}
54+
55+
@Override
56+
@SuppressWarnings("unchecked")
57+
public InstrumenterCustomizer setSpanNameExtractor(
58+
Function<SpanNameExtractor<?>, SpanNameExtractor<?>> spanNameExtractorTransformer) {
59+
builder.spanNameExtractor =
60+
(SpanNameExtractor<? super Object>)
61+
spanNameExtractorTransformer.apply(builder.spanNameExtractor);
62+
return this;
63+
}
64+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.api.internal;
7+
8+
/**
9+
* A service provider interface (SPI) for customizing instrumentation behavior.
10+
*
11+
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
12+
* at any time.
13+
*/
14+
public interface InstrumenterCustomizerProvider {
15+
16+
/**
17+
* Returns a predicate that matches the instrumentation name for which this provider is
18+
* applicable.
19+
*
20+
* @return a predicate that matches the instrumentation name for which this provider is applicable
21+
*/
22+
String getInstrumentationName();
23+
24+
/**
25+
* Customizes the given instrumenter.
26+
*
27+
* <p>This method is called for each instrumenter being built. Implementations can use the
28+
* provided customizer to add or modify behavior of the instrumenter.
29+
*
30+
* @param customizer the customizer for the instrumenter being built
31+
*/
32+
void customize(InstrumenterCustomizer customizer);
33+
}

0 commit comments

Comments
 (0)