-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[processor/tailsampling] support trace_state policy (#10852)
- Loading branch information
Showing
11 changed files
with
225 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 69 additions & 0 deletions
69
processor/tailsamplingprocessor/internal/sampling/trace_state_filter.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package sampling // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/tailsamplingprocessor/internal/sampling" | ||
|
||
import ( | ||
"go.opentelemetry.io/collector/pdata/pcommon" | ||
"go.opentelemetry.io/collector/pdata/ptrace" | ||
tracesdk "go.opentelemetry.io/otel/trace" | ||
"go.uber.org/zap" | ||
) | ||
|
||
type traceStateFilter struct { | ||
key string | ||
logger *zap.Logger | ||
matcher func(string) bool | ||
} | ||
|
||
var _ PolicyEvaluator = (*traceStateFilter)(nil) | ||
|
||
// NewTraceStateFilter creates a policy evaluator that samples all traces with | ||
// the given value by the specific key in the trace_state. | ||
func NewTraceStateFilter(logger *zap.Logger, key string, values []string) PolicyEvaluator { | ||
// initialize the exact value map | ||
valuesMap := make(map[string]struct{}) | ||
for _, value := range values { | ||
// the key-value pair("=" will take one character) in trace_state can't exceed 256 characters | ||
if value != "" && len(key)+len(value) < 256 { | ||
valuesMap[value] = struct{}{} | ||
} | ||
} | ||
return &traceStateFilter{ | ||
key: key, | ||
logger: logger, | ||
matcher: func(toMatch string) bool { | ||
_, matched := valuesMap[toMatch] | ||
return matched | ||
}, | ||
} | ||
} | ||
|
||
// Evaluate looks at the trace data and returns a corresponding SamplingDecision. | ||
func (tsf *traceStateFilter) Evaluate(_ pcommon.TraceID, trace *TraceData) (Decision, error) { | ||
trace.Lock() | ||
batches := trace.ReceivedBatches | ||
trace.Unlock() | ||
|
||
return hasSpanWithCondition(batches, func(span ptrace.Span) bool { | ||
traceState, err := tracesdk.ParseTraceState(string(span.TraceState())) | ||
if err != nil { | ||
return false | ||
} | ||
if ok := tsf.matcher(traceState.Get(tsf.key)); ok { | ||
return true | ||
} | ||
return false | ||
}), nil | ||
} |
113 changes: 113 additions & 0 deletions
113
processor/tailsamplingprocessor/internal/sampling/trace_state_filter_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package sampling | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"go.opentelemetry.io/collector/pdata/pcommon" | ||
"go.opentelemetry.io/collector/pdata/ptrace" | ||
"go.uber.org/zap" | ||
) | ||
|
||
// TestTraceStateCfg is replicated with StringAttributeCfg | ||
type TestTraceStateCfg struct { | ||
Key string | ||
Values []string | ||
} | ||
|
||
func TestTraceStateFilter(t *testing.T) { | ||
|
||
cases := []struct { | ||
Desc string | ||
Trace *TraceData | ||
filterCfg *TestTraceStateCfg | ||
Decision Decision | ||
}{ | ||
{ | ||
Desc: "nonmatching trace_state key", | ||
Trace: newTraceState("non_matching=value"), | ||
filterCfg: &TestTraceStateCfg{Key: "example", Values: []string{"value"}}, | ||
Decision: NotSampled, | ||
}, | ||
{ | ||
Desc: "nonmatching trace_state value", | ||
Trace: newTraceState("example=non_matching"), | ||
filterCfg: &TestTraceStateCfg{Key: "example", Values: []string{"value"}}, | ||
Decision: NotSampled, | ||
}, | ||
{ | ||
Desc: "matching trace_state", | ||
Trace: newTraceState("example=value"), | ||
filterCfg: &TestTraceStateCfg{Key: "example", Values: []string{"value"}}, | ||
Decision: Sampled, | ||
}, | ||
{ | ||
Desc: "nonmatching trace_state on empty filter list", | ||
Trace: newTraceState("example=value"), | ||
filterCfg: &TestTraceStateCfg{Key: "example", Values: []string{}}, | ||
Decision: NotSampled, | ||
}, | ||
{ | ||
Desc: "nonmatching trace_state on multiple key-values", | ||
Trace: newTraceState("example=non_matching,non_matching=value"), | ||
filterCfg: &TestTraceStateCfg{Key: "example", Values: []string{"value"}}, | ||
Decision: NotSampled, | ||
}, | ||
{ | ||
Desc: "matching trace_state on multiple key-values", | ||
Trace: newTraceState("example=value,non_matching=value"), | ||
filterCfg: &TestTraceStateCfg{Key: "example", Values: []string{"value"}}, | ||
Decision: Sampled, | ||
}, | ||
{ | ||
Desc: "nonmatching trace_state on multiple filter list", | ||
Trace: newTraceState("example=non_matching"), | ||
filterCfg: &TestTraceStateCfg{Key: "example", Values: []string{"value1", "value2"}}, | ||
Decision: NotSampled, | ||
}, | ||
{ | ||
Desc: "matching trace_state on multiple filter list", | ||
Trace: newTraceState("example=value1"), | ||
filterCfg: &TestTraceStateCfg{Key: "example", Values: []string{"value1", "value2"}}, | ||
Decision: Sampled, | ||
}, | ||
} | ||
|
||
for _, c := range cases { | ||
t.Run(c.Desc, func(t *testing.T) { | ||
filter := NewTraceStateFilter(zap.NewNop(), c.filterCfg.Key, c.filterCfg.Values) | ||
decision, err := filter.Evaluate(pcommon.NewTraceID([16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}), c.Trace) | ||
assert.NoError(t, err) | ||
assert.Equal(t, decision, c.Decision) | ||
}) | ||
} | ||
} | ||
|
||
func newTraceState(traceState string) *TraceData { | ||
var traceBatches []ptrace.Traces | ||
traces := ptrace.NewTraces() | ||
rs := traces.ResourceSpans().AppendEmpty() | ||
ils := rs.ScopeSpans().AppendEmpty() | ||
span := ils.Spans().AppendEmpty() | ||
span.SetTraceID(pcommon.NewTraceID([16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16})) | ||
span.SetSpanID(pcommon.NewSpanID([8]byte{1, 2, 3, 4, 5, 6, 7, 8})) | ||
span.SetTraceState(ptrace.TraceState(traceState)) | ||
traceBatches = append(traceBatches, traces) | ||
return &TraceData{ | ||
ReceivedBatches: traceBatches, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters