Skip to content

feat: implement FilteringSpanProcessor for span filtering based on na… - #22

Open
imranq2 wants to merge 5 commits into
mainfrom
add-filtering-span-processor
Open

feat: implement FilteringSpanProcessor for span filtering based on na…#22
imranq2 wants to merge 5 commits into
mainfrom
add-filtering-span-processor

Conversation

@imranq2

@imranq2 imranq2 commented Jan 13, 2026

Copy link
Copy Markdown
Contributor

This PR implements a FilteringSpanProcessor for OpenTelemetry that allows filtering spans based on exact name matches, name prefixes, and duration thresholds. The implementation provides a flexible way to reduce telemetry noise by excluding low-value spans (like MongoDB SASL authentication spans) from being exported.

Changes:

Adds FilteringSpanProcessor class that wraps existing span processors to filter spans based on configurable criteria
Adds utility functions to apply span filtering from environment variables (OTEL_EXCLUDED_SPAN_NAMES, OTEL_MIN_SPAN_DURATION_MS, OTEL_EXCLUDE_ROOT_SPANS_FROM_DURATION_FILTER)
Adds OPEN_TELEMETRY log level to the project's logging configuration

Copilot AI review requested due to automatic review settings January 13, 2026 02:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements a FilteringSpanProcessor for OpenTelemetry that allows filtering spans based on exact name matches, name prefixes, and duration thresholds. The implementation provides a flexible way to reduce telemetry noise by excluding low-value spans (like MongoDB SASL authentication spans) from being exported.

Changes:

  • Adds FilteringSpanProcessor class that wraps existing span processors to filter spans based on configurable criteria
  • Adds utility functions to apply span filtering from environment variables (OTEL_EXCLUDED_SPAN_NAMES, OTEL_MIN_SPAN_DURATION_MS, OTEL_EXCLUDE_ROOT_SPANS_FROM_DURATION_FILTER)
  • Adds OPEN_TELEMETRY log level to the project's logging configuration

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
oidcauthlib/utilities/logger/log_levels.py Adds "OPEN_TELEMETRY" to the list of log sources for configurable logging
oidcauthlib/open_telemetry/filtering_span_processor.py Implements FilteringSpanProcessor class with name, prefix, and duration-based filtering logic
oidcauthlib/open_telemetry/otel_setup.py Provides setup utilities and environment variable parsing for applying span filtering to the tracer provider

Comment thread oidcauthlib/open_telemetry/otel_setup.py
Comment thread oidcauthlib/open_telemetry/filtering_span_processor.py
Comment thread oidcauthlib/open_telemetry/otel_setup.py
@gecko-security

Copy link
Copy Markdown

Gecko Security Banner

Gecko PR Summary

Summary

Three new files introduce OpenTelemetry span filtering capabilities to the authentication library. A FilteringSpanProcessor wrapper is implemented to suppress noisy or short-duration spans (e.g., MongoDB SASL handshakes, ping/health checks) from telemetry exports, preventing trace saturation. The otel_setup.py module integrates this processor into the instrumentation stack, while log_levels.py centralizes logging configuration for telemetry components. This reduces observability noise by allowing selective span exclusion based on name, prefix, and duration thresholds while preserving root spans for trace visibility.

Important Files Changed

Changed files
File Path Reason
oidcauthlib/open_telemetry/filtering_span_processor.py Implements custom SpanProcessor to filter spans by name, prefix, and duration before export
oidcauthlib/open_telemetry/otel_setup.py Configures OpenTelemetry instrumentation pipeline and integrates the filtering processor
oidcauthlib/utilities/logger/log_levels.py Defines logging levels for OpenTelemetry components to control debug output

Sequence Diagram

sequenceDiagram
    participant App as Application Code
    participant OTel as otel_setup.py
    participant Filter as FilteringSpanProcessor
    participant Wrapped as Underlying SpanProcessor
    participant Export as Trace Exporter

    App->>OTel: Initialize instrumentation
    OTel->>Filter: Create FilteringSpanProcessor
    OTel->>Filter: Configure excluded names/prefixes/duration
    Filter->>Wrapped: Wrap target SpanProcessor
    
    App->>Filter: on_start(span, context)
    Filter->>Wrapped: on_start(span, context)
    
    App->>Filter: on_end(span)
    Filter->>Filter: Check excluded_span_names
    Filter->>Filter: Check excluded_span_prefixes
    Filter->>Filter: Calculate span duration
    Filter->>Filter: Check min_duration_ms threshold
    Filter->>Filter: Check if root span exception applies
    
    alt Span passes filters
        Filter->>Wrapped: on_end(span)
        Wrapped->>Export: Export span
    else Span filtered
        Filter->>Filter: Drop span (no export)
    end
Loading

Important

  • You can view the full scan details here

Edit PR Scan Bot Settings | Gecko Security

return

# Filter 3: Check duration (if configured)
if self.min_duration_ms is not None:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on_end has nested duration-check logic; use early returns/guards for root-exemption and short-duration cases to flatten control flow and clarify the forward path.

Details

✨ AI Reasoning
​on_end contains a multi-level nested duration-filter branch guarded by if self.min_duration_ms is not None. The root-exemption check and the duration comparison are nested inside that block, which buries the main forward logic and increases indentation. Using early returns (e.g., return when root is exempt or when short-duration filter triggers) would flatten on_end and make the success path (forwarding the span) clearer.

🔧 How do I fix it?
Place parameter validation and guard clauses at the function start. Use early returns to reduce nesting levels and improve readability.

Reply @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info

return False

# Use provided values or get from environment
if excluded_span_names is None:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apply_sampler_filtering reassigns parameter 'excluded_span_names' inside the function; avoid reassigning parameters to preserve the original argument's value.

Details

✨ AI Reasoning
​The function apply_sampler_filtering takes excluded_span_names as a parameter and then reassigns it inside the function when it's None. Reassigning a parameter makes it unclear what value was passed in and conflates the caller-provided value with function-local defaults, which can confuse readers and impede debugging.

🔧 How do I fix it?
Create new local variables instead of reassigning parameters. Use different variable names to clearly distinguish between input and modified values.

Reply @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info


try:
# Load configuration
config = config or SpanFilterConfig.from_environment()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reassigning parameter 'config' in initialize. Use a new local variable (e.g., resolved_config) instead of overwriting the parameter.

Details

✨ AI Reasoning
​The initialize(...) classmethod accepts an optional parameter named config and then reassigns that same parameter with a default when None. Reassigning a parameter can confuse readers about the original argument and hinder debugging. Using a new local variable for the resolved configuration would preserve the original argument value and improve clarity while producing the same behavior.

🔧 How do I fix it?
Create new local variables instead of reassigning parameters. Use different variable names to clearly distinguish between input and modified values.

Reply @AikidoSec feedback: [FEEDBACK] to get better review comments in the future.
Reply @AikidoSec ignore: [REASON] to ignore this issue.
More info

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants