Skip to content

Commit

Permalink
- Added changelog
Browse files Browse the repository at this point in the history
- Added README entry for the feature flag
- Added missing mutex lock around reading trace data in `SetAttrOnScopeSpans`
- Added tests + benchmarks for `SetAttrOnScopeSpans`
  • Loading branch information
djluck committed Dec 7, 2024
1 parent 8e0239a commit b0ddd0e
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 1 deletion.
15 changes: 15 additions & 0 deletions .chloggen/tailsampling-record-policy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: processor/tailsampling

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: |
Adds support for optionally recording the policy (and any composite policy) associated with an inclusive tail processor sampling decision.
This functionality is disabled by default, you can enable it by passing the following feature flag to the collector: `+processor.tailsamplingprocessor.recordpolicy`
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [35180]
10 changes: 10 additions & 0 deletions processor/tailsamplingprocessor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,16 @@ sum (otelcol_processor_tail_sampling_count_traces_sampled) by (policy)

As a reminder, a policy voting to sample the trace does not guarantee sampling; an "inverted not" decision from another policy would still discard the trace.

### Tracking sampling policy
To better understand _which_ sampling policy made the decision to include a trace, you can enable tracking the policy responsible for sampling a trace via the `processor.tailsamplingprocessor.recordpolicy` feature gate.

When this feature gate is set, this will add additional attributes on each sampled span scope:

| Attribute | Description | Present? |
|---------------------------------|---------------------------------------------------------------------------|----------------------------|
| `tailsampling.policy` | Records the configured name of the policy that sampled a trace | Always |
| `tailsampling.composite_policy` | Records the configured name of a composite subpolicy that sampled a trace | When composite policy used |

### Policy Evaluation Errors

```
Expand Down
3 changes: 2 additions & 1 deletion processor/tailsamplingprocessor/internal/sampling/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,10 @@ func invertHasInstrumentationLibrarySpanWithCondition(ilss ptrace.ScopeSpansSlic
}

func SetAttrOnScopeSpans(data *TraceData, attrName string, attrKey string) {
data.Mutex.Lock()
defer data.Mutex.Unlock()

rs := data.ReceivedBatches.ResourceSpans()

for i := 0; i < rs.Len(); i++ {
rss := rs.At(i)
for j := 0; j < rss.ScopeSpans().Len(); j++ {
Expand Down
87 changes: 87 additions & 0 deletions processor/tailsamplingprocessor/internal/sampling/util_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package sampling

import (
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/ptrace"
"testing"
)

func TestSetAttrOnScopeSpans_Empty(t *testing.T) {
traces := ptrace.NewTraces()
traceData := &TraceData{
ReceivedBatches: traces,
}

SetAttrOnScopeSpans(traceData, "test.attr", "value")
}

func TestSetAttrOnScopeSpans_Many(t *testing.T) {

assertAttrExists := func(t *testing.T, attrs pcommon.Map, key string, value string) {
v, ok := attrs.Get(key)
assert.True(t, ok)
assert.Equal(t, value, v.AsString())
}

traces := ptrace.NewTraces()

rs1 := traces.ResourceSpans().AppendEmpty()
ss1 := rs1.ScopeSpans().AppendEmpty()
span1 := ss1.Spans().AppendEmpty()
span2 := ss1.Spans().AppendEmpty()
ss2 := rs1.ScopeSpans().AppendEmpty()
span3 := ss2.Spans().AppendEmpty()
rs2 := traces.ResourceSpans().AppendEmpty()
ss3 := rs2.ScopeSpans().AppendEmpty()
span4 := ss3.Spans().AppendEmpty()

traceData := &TraceData{
ReceivedBatches: traces,
}

SetAttrOnScopeSpans(traceData, "test.attr", "value")

assertAttrExists(t, ss1.Scope().Attributes(), "test.attr", "value")
assertAttrExists(t, ss2.Scope().Attributes(), "test.attr", "value")
assertAttrExists(t, ss3.Scope().Attributes(), "test.attr", "value")

_, ok := span1.Attributes().Get("test.attr")
assert.False(t, ok)
_, ok = span2.Attributes().Get("test.attr")
assert.False(t, ok)
_, ok = span3.Attributes().Get("test.attr")
assert.False(t, ok)
_, ok = span4.Attributes().Get("test.attr")
assert.False(t, ok)
}

func BenchmarkSetAttrOnScopeSpans(b *testing.B) {
for n := 0; n < b.N; n++ {

traces := ptrace.NewTraces()

for i := 0; i < 5; i++ {
rs := traces.ResourceSpans().AppendEmpty()
ss1 := rs.ScopeSpans().AppendEmpty()
ss1.Spans().AppendEmpty()
ss1.Spans().AppendEmpty()
ss1.Spans().AppendEmpty()

ss2 := rs.ScopeSpans().AppendEmpty()
ss2.Spans().AppendEmpty()
ss2.Spans().AppendEmpty()

ss3 := rs.ScopeSpans().AppendEmpty()
ss3.Spans().AppendEmpty()
}

traceData := &TraceData{
ReceivedBatches: traces,
}

b.StartTimer()
SetAttrOnScopeSpans(traceData, "test.attr", "value")
b.StopTimer()
}
}

0 comments on commit b0ddd0e

Please sign in to comment.