Skip to main content

Spanpruning Processor

Status Available in: contrib Maintainers: @portertech, @csmarchbanks Source: opentelemetry-collector-contrib

Supported Telemetry

Traces

Overview

Overview

The Span Pruning Processor identifies duplicate or similar leaf spans within a single trace, groups them, and replaces each group with a single aggregated summary span. When leaf spans are aggregated, the processor also recursively aggregates their parent spans if all children of those parents are being aggregated. Leaf spans are spans that are not referenced as a parent by any other span in the trace. They typically represent the last actions in an execution call stack (e.g., individual database queries, HTTP calls to external services). Spans are grouped by:
  1. Span name - spans must have the same name
  2. Span kind - spans must have the same kind (Internal, Server, Client, Producer, Consumer)
  3. Status code - spans must have the same status (OK, Error, or Unset)
  4. TraceState - spans must have identical TraceState values (for Consistent Probability Sampling compatibility)
  5. Configured attributes - spans must have matching values for attributes specified in group_by_attributes
  6. Parent span name - leaf spans must share the same parent span name to be grouped together
Parent spans are eligible for aggregation when all of their children are aggregated, they share the same name, kind, and status code, and they are not root spans. The processor can also apply selective pruning with OTTL conditions so only traces that match your criteria are pruned. Optionally, the processor can detect duration outliers using statistical methods (IQR or MAD) and either annotate summary spans with outlier correlations or preserve outlier subtrees for debugging while still aggregating normal spans. Detection runs at every aggregation level, so a slow interior span (for example one slow handler among many) is caught and its whole subtree is kept intact. This processor is useful for reducing trace data volume while preserving meaningful information about repeated operations.

Use Cases

  • Database query optimization: When an application makes many similar database queries (e.g., N+1 queries), aggregate them into a single summary span
  • Batch operations: Consolidate many similar leaf operations into a single representative span
  • Cost reduction: Reduce trace storage costs by eliminating redundant span data

Configuration

Note: This processor was renamed from spanpruning to span_pruning to match the snake_case naming convention. The deprecated component type spanpruning is still accepted as an alias and will log a deprecation warning.

Configuration Options

Glob Pattern Support

The group_by_attributes field supports glob patterns for matching attribute keys: When multiple attributes match a pattern, they are all included in the grouping key (sorted alphabetically for consistency).

Summary Span

When spans are aggregated, the summary span includes:

Properties

  • Name: Original span name (e.g., SELECT)
  • TraceID: Same as original spans
  • SpanID: Newly generated unique ID
  • ParentSpanID: Same as original spans (common parent)
  • Kind: Same as template span (inherited from slowest span)
  • StartTimestamp: Earliest start time of all spans in the group
  • EndTimestamp: Latest end time of all spans in the group
  • Status: Same as original spans (spans are grouped by status code)
  • TraceState: Inherited from the template span (preserved for Consistent Probability Sampling compatibility)
  • Attributes: Inherited from the slowest span in the group
Note: The summary span’s duration (EndTimestamp - StartTimestamp) represents the total time window covered by all aggregated spans, which may exceed duration_max_ns. For example, if spans overlap or are staggered, the time range can be larger than any individual span’s duration. Use duration_max_ns to find the slowest individual operation.

What Gets Aggregated Away

When spans are aggregated into a summary span, the following data from non-template spans is lost:

Aggregation Attributes

The following attributes are added to the summary span (shown with default aggregation_attribute_prefix: "aggregation."):

Optional Attribute Loss Analysis

When enable_attribute_loss_analysis: true, the processor analyzes how attributes vary across aggregated spans and records two loss types:
  • Diversity loss: Attribute exists on all spans in the group, but values differ across spans.
  • Missing loss: Attribute is absent from some spans in the group.
These are added to the summary span as string attributes (with your configured aggregation_attribute_prefix): The processor also records leaf and parent histogram metrics for both loss types:
  • processor_spanpruning_leaf_attribute_diversity_loss
  • processor_spanpruning_leaf_attribute_loss
  • processor_spanpruning_parent_attribute_diversity_loss
  • processor_spanpruning_parent_attribute_loss
Use attribute_loss_exemplar_sample_rate to control how often those metric points include exemplars for trace correlation.

Optional Outlier Analysis Attributes

When enable_outlier_analysis: true, the following additional attributes are added:

Summary Span Attributes (When Preserving Outliers)

When outlier_analysis.preserve_outliers: true, the summary span also includes:

Preserved Outlier Span Attributes

Preserved outlier spans are annotated with: A preserved outlier (the root of its subtree) becomes a sibling of its summary span, and its whole subtree moves with it. The outlier keeps everything beneath it, but its aggregated ancestors are replaced by the summary it now hangs from (linked via summary_span_id).

Histogram Buckets

When aggregation_histogram_buckets is configured, summary spans include latency distribution data as cumulative histogram buckets. Cumulative means each bucket count includes all spans with duration less than or equal to that bucket boundary. Worked example with buckets [10ms, 50ms, 100ms] and span durations [5ms, 15ms, 25ms, 75ms, 150ms]:
  • histogram_bucket_bounds_s: [0.01, 0.05, 0.1]
  • histogram_bucket_counts: [1, 3, 4, 5]
    • Bucket 0 (<=10ms): 1 span (5ms)
    • Bucket 1 (<=50ms): 3 spans (5ms, 15ms, 25ms)
    • Bucket 2 (<=100ms): 4 spans (5ms, 15ms, 25ms, 75ms)
    • Bucket 3 (+Inf): 5 spans (all spans)

Outlier Analysis (Optional)

When enable_outlier_analysis: true, the processor detects duration outliers and identifies attributes that correlate with slow spans.

Detection Methods

The processor supports two statistical methods for outlier detection: When to use each:
  • IQR: Best for typical distributions with moderate outliers. Standard choice for most use cases.
  • MAD: Better when you have extreme outliers that would skew IQR calculations, or when you need more stable detection thresholds.

How It Works

IQR (Interquartile Range) Method:
  1. Sort spans by duration
  2. Calculate Q1 (25th percentile) and Q3 (75th percentile)
  3. Calculate IQR = Q3 - Q1
  4. Flag spans with duration > Q3 + (iqr_multiplier × IQR) as outliers
MAD (Median Absolute Deviation) Method:
  1. Sort spans by duration and find the median
  2. Calculate |duration - median| for each span
  3. MAD = median of those deviations
  4. Flag spans with duration > median + (mad_multiplier × MAD × 1.4826) as outliers
Note: The 1.4826 scale factor makes MAD comparable to standard deviation for normal distributions. Attribute Correlation (same for both methods):
  • Compare attribute values between outliers and normal spans
  • Find attribute values that appear frequently in outliers but rarely in normal spans
  • Report the strongest correlations based on the configured thresholds

Configuration Example

Example Output

Interpretation:
  • Median vs Avg: Large difference (8ms vs 45ms) indicates outliers are skewing the average
  • Primary correlation: All outliers (100%) had cache_hit=false, while 0% of normal spans did
  • Secondary correlation: 80% of outliers hit shard 7, but only 10% of normal spans did
This helps identify root causes of latency issues:
  • Cache misses
  • Specific database shards
  • Failed retries
  • Timeout scenarios

When to Use

  • Enable when you need to understand why some operations are slow
  • Disable (default) to minimize overhead when outlier analysis isn’t needed
  • Works best with groups of 10+ spans for statistical reliability

Performance Impact

  • Computational overhead: Sorts durations, calculates quartiles, counts attribute occurrences
  • Minimal when disabled: Zero overhead (no sorting or calculations)
  • Recommended: Use min_group_size: 7 or higher to skip analysis on small groups

Preserving Outlier Subtrees (Optional)

When outlier_analysis.preserve_outliers: true, each detected outlier is kept along with its whole subtree instead of being aggregated. A leaf outlier (e.g. a slow query) is the degenerate single-span case; an interior outlier (e.g. a slow handler) keeps every span beneath it. This provides:
  • Full visibility into slow operations for debugging, including everything the slow span did
  • Preserved context: original attributes, events, links, and tree structure remain intact
  • Selective aggregation: only prune repetitive normal spans
Preservation keeps everything beneath an outlier, not above it: the outlier’s subtree is kept, but its ancestors still aggregate normally. The preserved subtree is reparented as a sibling of its summary span (the whole subtree moves with its root), so a slow leaf ends up under the same summary its normal siblings collapsed into, and a slow interior span hangs off the summary that replaced its peers.

Configuration

Configuration Options

Example Output

Before (10 similar SELECT spans, 2 are outliers):
After (with preserve_outliers: true, max_preserved_outliers: 2):

Behavior Notes

  • Multi-level detection: outliers are detected within each sibling group at every level (leaf groups and eligible parent groups) that meets min_group_size.
  • Subtree, not ancestors: a preserved outlier keeps everything beneath it (its whole subtree), but its ancestors still aggregate; the subtree is reparented as a sibling of its summary.
  • Nested outliers: an outlier already inside a preserved subtree is not preserved (or counted) again, since the enclosing subtree already keeps it.
  • Skip aggregation: if protection leaves a group below min_spans_to_aggregate, that group is left unchanged.
  • Selection order: outliers are preserved starting with the most extreme (longest duration) first, capped by max_preserved_outliers subtrees per group.

Pipeline Placement

This processor is designed to work best when placed after processors that ensure complete traces are available:
Or with tail sampling:

Example

Basic Example

A trace with repeated database queries (some failing): Before Processing:
After Processing (with min_spans_to_aggregate: 2):
Note: Spans with different status codes are grouped separately, preserving error information.

Recursive Parent Aggregation Example

When spans are aggregated, the processor also checks if their parent spans can be aggregated. Parent spans are eligible for aggregation when:
  1. All of their children are being aggregated
  2. They share the same name, kind, and status code with other eligible parents
  3. They are not root spans (must have a parent)
  4. At least 2 parents meet the criteria
Before Processing (with min_spans_to_aggregate: 2, group_by_attributes: ["db.op"]):
After Processing:
Why each span was handled this way:

OTTL Condition Filtering

The conditions field allows selective trace pruning using OTTL (OpenTelemetry Transformation Language) expressions. Only traces where at least one span matches any condition will be pruned.

Behavior

Syntax

Conditions use OTTL span context syntax. Each condition is a boolean expression evaluated against each span in a trace. If any span matches any condition, the entire trace is eligible for pruning.

Common Examples

Filter by service name:
Filter by span attributes:
Filter by HTTP route:
Multiple conditions (OR logic):
A trace is pruned if any span matches any condition. Filter by span name:
Filter by status:

Use Cases

  • Targeted pruning: Only prune traces from specific services known to generate repetitive spans
  • Environment filtering: Prune only production traces while preserving development traces
  • Operation-specific: Prune only database-heavy traces while keeping HTTP traces intact
  • Debugging: Temporarily disable pruning for specific services to investigate issues

Limitations

  • Requires complete traces for accurate leaf detection
  • Summary span inherits attributes from the slowest span in the group
  • Parent spans are only aggregated when ALL their children are aggregated

Consistent Probability Sampling (CPS) Compatibility

The processor is designed to be compatible with Consistent Probability Sampling (CPS). CPS uses TraceState to carry sampling metadata (ot=th:...;rv:...) where:
  • th (threshold) indicates the sampling probability threshold
  • rv (randomness value) provides consistent randomness for sampling decisions
Why TraceState matters for aggregation: Spans with different TraceState values represent different sampling populations with different “adjusted counts” (weights). Aggregating them together would produce statistically incorrect summaries and break downstream sampling decisions. The processor uses exact TraceState matching (not just the th value) because:
  • The rv value affects sampling decisions
  • Vendor-specific keys may have semantic meaning
  • Key ordering may be significant

Telemetry

The processor emits the following metrics to help monitor its operation:

Counters

Byte metrics semantics

When enable_bytes_metrics is enabled, the processor serializes trace data with ptrace.ProtoMarshaler on each batch. This adds CPU overhead because it measures:
  • Full batch bytes before pruning (bytes_received)
  • Matched subset bytes before pruning (bytes_processed_input)
  • Matched subset bytes after pruning (bytes_processed_output)
  • Full batch bytes after pruning (bytes_emitted)
When no conditions are configured, the matched subset is the full batch, so bytes_processed_input == bytes_received and bytes_processed_output == bytes_emitted. When conditions are configured, the matched subset may be smaller than the full batch, and the matched-subset metrics reflect only traces that matched. After aggregation, bytes_processed_output can exceed bytes_processed_input when summary spans are larger than the leaf spans they replace, so matched-byte savings can be negative even when pruning is functioning correctly.

Histograms

These metrics can be used to:
  • Monitor the effectiveness of span pruning (compare spans_received vs spans_pruned)
  • Track the compression ratio achieved by aggregation
  • Track condition selectivity with traces_skipped
  • Track byte changes (bytes_received/bytes_emitted for the full batch, bytes_processed_input/bytes_processed_output for the matched subset)
  • Identify processing bottlenecks via processing_duration
  • Understand aggregation patterns via aggregation_group_size

Configuration

Example Configuration


Last generated: 2026-08-24