open-telemetry / open-telemetry/opentelemetry-java-instrumentation
Add extension for flexible span filtering before span creation
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 2.6k
- Forks
- 1.2k
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 228
Description
Is your feature request related to a problem? Please describe.
Currently, opentelemetry-java-instrumentation lacks readily available extension points for filtering Spat creation actions before they are actually created.
For example, if my distro contains background threads, I don't want to create corresponding Spats for these threads, I'd like to filter Spat creation based on thread information.
Additionally, we'd like to set up some rate-limiting logic before Spat creation to control its creation.
Describe the solution you'd like
Add a ShouldStartFilter extension point that allows filtering before span creation:
@FunctionalInterface
public interface ShouldStartFilter<REQUEST> {
/**
* Determines whether a span should be started for the given operation.
*/
boolean shouldStart(Context parentContext, REQUEST request, SpanKind spanKind, String instrumentationName);
/**
* Filter priority (lower numbers = higher priority)
*/
default int getPriority() { return 0; }
/**
* Combines multiple filters
*/
static <REQUEST> ShouldStartFilter<REQUEST> allOf(List<ShouldStartFilter<REQUEST>> filters) {
// Implementation that executes filters in priority order
}
}
Integration with InstrumenterBuilder
public class InstrumenterBuilder<REQUEST, RESPONSE> {
private final List<ShouldStartFilter<REQUEST>> shouldStartFilters = new ArrayList<>();
public InstrumenterBuilder<REQUEST, RESPONSE> addShouldStartFilter(ShouldStartFilter<REQUEST> filter) {
shouldStartFilters.add(filter);
return this;
}
// Build the composite filter during instrumenter construction
private ShouldStartFilter<REQUEST> buildShouldStartFilter() {
if (shouldStartFilters.isEmpty()) {
return ShouldStartFilter.none(); // Pass-through filter
}
return ShouldStartFilter.allOf(shouldStartFilters);
}
// Modified build methods to include the filter
public Instrumenter<REQUEST, RESPONSE> buildInstrumenter() {
return new Instrumenter<>(
// ... existing parameters ...
buildShouldStartFilter() // Pass the composite filter
);
}
}
Integration with InstrumenterCustomizer
public interface InstrumenterCustomizer {
// Existing methods...
InstrumenterCustomizer addShouldStartFilter(ShouldStartFilter<?> filter);
}
Core Integration: Modified Instrumenter Class
The key integration point is in the Instrumenter.shouldStart() method:
public class Instrumenter<REQUEST, RESPONSE> {
private final ShouldStartFilter<REQUEST> shouldStartFilter;
// ... other existing fields ...
// Constructor receives the filter from InstrumenterBuilder
Instrumenter(
// ... existing parameters ...
ShouldStartFilter<REQUEST> shouldStartFilter) {
// ... existing initialization ...
this.shouldStartFilter = shouldStartFilter;
}
/**
* Modified shouldStart method that applies filters before existing logic
*/
public boolean shouldStart(Context parentContext, REQUEST request) {
// 1. Check if instrumenter is enabled (existing logic)
if (!enabled) {
return false;
}
// 2. Extract span kind (needed for both filters and suppressors)
SpanKind spanKind = spanKindExtractor.extract(request);
// 3. NEW: Apply ShouldStartFilter before any span creation logic
if (!shouldStartFilter.shouldStart(parentContext, request, spanKind, instrumentationName)) {
// Filter rejected - record metrics and return false immediately
supportability.recordFilteredSpan(spanKind, instrumentationName, "should_start_filter");
return false;
}
// 4. Apply existing SpanSuppressor logic (unchanged)
boolean suppressed = spanSuppressor.shouldSuppress(parentContext, spanKind);
if (suppressed) {
supportability.recordSuppressedSpan(spanKind, instrumentationName);
}
return !suppressed;
}
}
Describe alternatives you've considered
No response
Additional context
No response
Tip
React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read InstrumenterBuilder and InstrumenterCustomizer first, then follow Instrumenter.shouldStart(), the named integration point for applying filtering before existing suppression logic. Done means defining the ShouldStartFilter extension, composing filters by priority, wiring it through the builder and customizer, and applying it before span creation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100