From 72fdae8a0db9236eb0229888608aee0e5a8212cc Mon Sep 17 00:00:00 2001 From: Sean Porter Date: Thu, 1 May 2025 15:56:25 -0700 Subject: [PATCH 1/6] cleaned up SpanWithCondition invert Signed-off-by: Sean Porter --- .../internal/sampling/util.go | 29 +++++-------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/processor/tailsamplingprocessor/internal/sampling/util.go b/processor/tailsamplingprocessor/internal/sampling/util.go index ee55981dd51f3..34682d1d8e01d 100644 --- a/processor/tailsamplingprocessor/internal/sampling/util.go +++ b/processor/tailsamplingprocessor/internal/sampling/util.go @@ -23,7 +23,7 @@ func hasResourceOrSpanWithCondition( return Sampled } - if hasInstrumentationLibrarySpanWithCondition(rs.ScopeSpans(), shouldSampleSpan) { + if hasInstrumentationLibrarySpanWithCondition(rs.ScopeSpans(), shouldSampleSpan, false) { return Sampled } } @@ -45,7 +45,7 @@ func invertHasResourceOrSpanWithCondition( return InvertNotSampled } - if !invertHasInstrumentationLibrarySpanWithCondition(rs.ScopeSpans(), shouldSampleSpan) { + if !hasInstrumentationLibrarySpanWithCondition(rs.ScopeSpans(), shouldSampleSpan, true) { return InvertNotSampled } } @@ -57,41 +57,26 @@ func hasSpanWithCondition(td ptrace.Traces, shouldSample func(span ptrace.Span) for i := 0; i < td.ResourceSpans().Len(); i++ { rs := td.ResourceSpans().At(i) - if hasInstrumentationLibrarySpanWithCondition(rs.ScopeSpans(), shouldSample) { + if hasInstrumentationLibrarySpanWithCondition(rs.ScopeSpans(), shouldSample, false) { return Sampled } } return NotSampled } -func hasInstrumentationLibrarySpanWithCondition(ilss ptrace.ScopeSpansSlice, check func(span ptrace.Span) bool) bool { +func hasInstrumentationLibrarySpanWithCondition(ilss ptrace.ScopeSpansSlice, check func(span ptrace.Span) bool, invert bool) bool { for i := 0; i < ilss.Len(); i++ { ils := ilss.At(i) for j := 0; j < ils.Spans().Len(); j++ { span := ils.Spans().At(j) - if check(span) { - return true + if r := check(span); r != invert { + return r } } } - return false -} - -func invertHasInstrumentationLibrarySpanWithCondition(ilss ptrace.ScopeSpansSlice, check func(span ptrace.Span) bool) bool { - for i := 0; i < ilss.Len(); i++ { - ils := ilss.At(i) - - for j := 0; j < ils.Spans().Len(); j++ { - span := ils.Spans().At(j) - - if !check(span) { - return false - } - } - } - return true + return invert } func SetAttrOnScopeSpans(data *TraceData, attrName string, attrKey string) { From b293ef915a30769ba13a84382dacb160a5d60816 Mon Sep 17 00:00:00 2001 From: Sean Porter Date: Fri, 2 May 2025 13:54:30 -0700 Subject: [PATCH 2/6] feature gate to disable invert sample Signed-off-by: Sean Porter --- .../sampling/boolean_tag_filter_test.go | 24 ++++++++++++++-- .../internal/sampling/featureflag.go | 16 +++++++++++ .../sampling/numeric_tag_filter_test.go | 24 ++++++++++++++-- .../sampling/string_tag_filter_test.go | 28 ++++++++++++++++--- .../internal/sampling/util.go | 12 ++++++++ 5 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 processor/tailsamplingprocessor/internal/sampling/featureflag.go diff --git a/processor/tailsamplingprocessor/internal/sampling/boolean_tag_filter_test.go b/processor/tailsamplingprocessor/internal/sampling/boolean_tag_filter_test.go index 25a1643759e92..32a6b020f11d9 100644 --- a/processor/tailsamplingprocessor/internal/sampling/boolean_tag_filter_test.go +++ b/processor/tailsamplingprocessor/internal/sampling/boolean_tag_filter_test.go @@ -10,6 +10,7 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/featuregate" "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/ptrace" ) @@ -61,9 +62,10 @@ func TestBooleanTagFilterInverted(t *testing.T) { resAttr["example"] = 8 cases := []struct { - Desc string - Trace *TraceData - Decision Decision + Desc string + Trace *TraceData + Decision Decision + DisableInvertSample bool }{ { Desc: "non-matching span attribute", @@ -80,10 +82,26 @@ func TestBooleanTagFilterInverted(t *testing.T) { Trace: newTraceBoolAttrs(empty, "example", true), Decision: InvertNotSampled, }, + { + Desc: "span attribute with non matching boolean value with DisableInvertSample", + Trace: newTraceBoolAttrs(empty, "example", false), + Decision: Sampled, + DisableInvertSample: true, + }, + { + Desc: "span attribute with matching boolean value with DisableInvertSample", + Trace: newTraceBoolAttrs(empty, "example", true), + Decision: NotSampled, + DisableInvertSample: true, + }, } for _, c := range cases { t.Run(c.Desc, func(t *testing.T) { + if c.DisableInvertSample { + featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", true) + defer featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", false) + } u, _ := uuid.NewRandom() decision, err := filter.Evaluate(context.Background(), pcommon.TraceID(u), c.Trace) assert.NoError(t, err) diff --git a/processor/tailsamplingprocessor/internal/sampling/featureflag.go b/processor/tailsamplingprocessor/internal/sampling/featureflag.go new file mode 100644 index 0000000000000..06f307598bc38 --- /dev/null +++ b/processor/tailsamplingprocessor/internal/sampling/featureflag.go @@ -0,0 +1,16 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package sampling // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/tailsamplingprocessor/internal/sampling" + +import "go.opentelemetry.io/collector/featuregate" + +var disableInvertSample = featuregate.GlobalRegistry().MustRegister( + "processor.tailsamplingprocessor.disableinvertsample", + featuregate.StageAlpha, + featuregate.WithRegisterDescription("When enabled, sampling policy 'invert_match' will result in a SAMPLED or NOT SAMPLED decision instead of INVERT SAMPLED or INVERT NOT SAMPLED."), +) + +func IsInvertSampleDisabled() bool { + return disableInvertSample.IsEnabled() +} diff --git a/processor/tailsamplingprocessor/internal/sampling/numeric_tag_filter_test.go b/processor/tailsamplingprocessor/internal/sampling/numeric_tag_filter_test.go index ffb551eb80aa3..a4a6da4499631 100644 --- a/processor/tailsamplingprocessor/internal/sampling/numeric_tag_filter_test.go +++ b/processor/tailsamplingprocessor/internal/sampling/numeric_tag_filter_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/featuregate" "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/ptrace" ) @@ -97,9 +98,10 @@ func TestNumericTagFilterInverted(t *testing.T) { resAttr["example"] = 8 cases := []struct { - Desc string - Trace *TraceData - Decision Decision + Desc string + Trace *TraceData + Decision Decision + DisableInvertSample bool }{ { Desc: "nonmatching span attribute", @@ -146,10 +148,26 @@ func TestNumericTagFilterInverted(t *testing.T) { Trace: newTraceIntAttrs(map[string]any{"example": math.MaxInt32 + 1}, "non_matching", math.MaxInt32+1), Decision: InvertSampled, }, + { + Desc: "nonmatching span attribute with DisableInvertSample", + Trace: newTraceIntAttrs(empty, "non_matching", math.MinInt32), + Decision: Sampled, + DisableInvertSample: true, + }, + { + Desc: "span attribute at the lower limit with DisableInvertSample", + Trace: newTraceIntAttrs(empty, "example", math.MinInt32), + Decision: NotSampled, + DisableInvertSample: true, + }, } for _, c := range cases { t.Run(c.Desc, func(t *testing.T) { + if c.DisableInvertSample { + featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", true) + defer featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", false) + } u, _ := uuid.NewRandom() decision, err := filter.Evaluate(context.Background(), pcommon.TraceID(u), c.Trace) assert.NoError(t, err) diff --git a/processor/tailsamplingprocessor/internal/sampling/string_tag_filter_test.go b/processor/tailsamplingprocessor/internal/sampling/string_tag_filter_test.go index e9ee3da867737..965544372e9e2 100644 --- a/processor/tailsamplingprocessor/internal/sampling/string_tag_filter_test.go +++ b/processor/tailsamplingprocessor/internal/sampling/string_tag_filter_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "go.opentelemetry.io/collector/component/componenttest" + "go.opentelemetry.io/collector/featuregate" "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/ptrace" ) @@ -24,10 +25,11 @@ type TestStringAttributeCfg struct { func TestStringTagFilter(t *testing.T) { cases := []struct { - Desc string - Trace *TraceData - filterCfg *TestStringAttributeCfg - Decision Decision + Desc string + Trace *TraceData + filterCfg *TestStringAttributeCfg + Decision Decision + DisableInvertSample bool }{ { Desc: "nonmatching node attribute key", @@ -197,10 +199,28 @@ func TestStringTagFilter(t *testing.T) { filterCfg: &TestStringAttributeCfg{Key: "example", Values: []string{}, EnabledRegexMatching: true, InvertMatch: true}, Decision: InvertSampled, }, + { + Desc: "invert matching node attribute key with DisableInvertSample", + Trace: newTraceStringAttrs(map[string]any{"example": "value"}, "", ""), + filterCfg: &TestStringAttributeCfg{Key: "example", Values: []string{"value"}, EnabledRegexMatching: false, CacheMaxSize: defaultCacheSize, InvertMatch: true}, + Decision: NotSampled, + DisableInvertSample: true, + }, + { + Desc: "invert nonmatching node attribute key with DisableInvertSample", + Trace: newTraceStringAttrs(map[string]any{"non_matching": "value"}, "", ""), + filterCfg: &TestStringAttributeCfg{Key: "example", Values: []string{"value"}, EnabledRegexMatching: false, CacheMaxSize: defaultCacheSize, InvertMatch: true}, + Decision: Sampled, + DisableInvertSample: true, + }, } for _, c := range cases { t.Run(c.Desc, func(t *testing.T) { + if c.DisableInvertSample { + featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", true) + defer featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", false) + } filter := NewStringAttributeFilter(componenttest.NewNopTelemetrySettings(), c.filterCfg.Key, c.filterCfg.Values, c.filterCfg.EnabledRegexMatching, c.filterCfg.CacheMaxSize, c.filterCfg.InvertMatch) decision, err := filter.Evaluate(context.Background(), pcommon.TraceID([16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}), c.Trace) assert.NoError(t, err) diff --git a/processor/tailsamplingprocessor/internal/sampling/util.go b/processor/tailsamplingprocessor/internal/sampling/util.go index 34682d1d8e01d..af387661b7f88 100644 --- a/processor/tailsamplingprocessor/internal/sampling/util.go +++ b/processor/tailsamplingprocessor/internal/sampling/util.go @@ -37,18 +37,30 @@ func invertHasResourceOrSpanWithCondition( shouldSampleResource func(resource pcommon.Resource) bool, shouldSampleSpan func(span ptrace.Span) bool, ) Decision { + isd := IsInvertSampleDisabled() + for i := 0; i < td.ResourceSpans().Len(); i++ { rs := td.ResourceSpans().At(i) resource := rs.Resource() if !shouldSampleResource(resource) { + if isd { + return NotSampled + } return InvertNotSampled } if !hasInstrumentationLibrarySpanWithCondition(rs.ScopeSpans(), shouldSampleSpan, true) { + if isd { + return NotSampled + } return InvertNotSampled } } + + if isd { + return Sampled + } return InvertSampled } From f04d533e51939a097860acb109ebc826d655f374 Mon Sep 17 00:00:00 2001 From: Sean Porter Date: Tue, 6 May 2025 08:50:18 -0700 Subject: [PATCH 3/6] err check test feature gate usage Signed-off-by: Sean Porter --- .../internal/sampling/boolean_tag_filter_test.go | 8 ++++++-- .../internal/sampling/numeric_tag_filter_test.go | 8 ++++++-- .../internal/sampling/string_tag_filter_test.go | 8 ++++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/processor/tailsamplingprocessor/internal/sampling/boolean_tag_filter_test.go b/processor/tailsamplingprocessor/internal/sampling/boolean_tag_filter_test.go index 32a6b020f11d9..61d0518185d87 100644 --- a/processor/tailsamplingprocessor/internal/sampling/boolean_tag_filter_test.go +++ b/processor/tailsamplingprocessor/internal/sampling/boolean_tag_filter_test.go @@ -99,8 +99,12 @@ func TestBooleanTagFilterInverted(t *testing.T) { for _, c := range cases { t.Run(c.Desc, func(t *testing.T) { if c.DisableInvertSample { - featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", true) - defer featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", false) + err := featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", true) + assert.NoError(t, err) + defer func() { + err := featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", false) + assert.NoError(t, err) + }() } u, _ := uuid.NewRandom() decision, err := filter.Evaluate(context.Background(), pcommon.TraceID(u), c.Trace) diff --git a/processor/tailsamplingprocessor/internal/sampling/numeric_tag_filter_test.go b/processor/tailsamplingprocessor/internal/sampling/numeric_tag_filter_test.go index a4a6da4499631..2034d2e8c83f6 100644 --- a/processor/tailsamplingprocessor/internal/sampling/numeric_tag_filter_test.go +++ b/processor/tailsamplingprocessor/internal/sampling/numeric_tag_filter_test.go @@ -165,8 +165,12 @@ func TestNumericTagFilterInverted(t *testing.T) { for _, c := range cases { t.Run(c.Desc, func(t *testing.T) { if c.DisableInvertSample { - featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", true) - defer featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", false) + err := featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", true) + assert.NoError(t, err) + defer func() { + err := featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", false) + assert.NoError(t, err) + }() } u, _ := uuid.NewRandom() decision, err := filter.Evaluate(context.Background(), pcommon.TraceID(u), c.Trace) diff --git a/processor/tailsamplingprocessor/internal/sampling/string_tag_filter_test.go b/processor/tailsamplingprocessor/internal/sampling/string_tag_filter_test.go index 965544372e9e2..46893b1ffffc4 100644 --- a/processor/tailsamplingprocessor/internal/sampling/string_tag_filter_test.go +++ b/processor/tailsamplingprocessor/internal/sampling/string_tag_filter_test.go @@ -218,8 +218,12 @@ func TestStringTagFilter(t *testing.T) { for _, c := range cases { t.Run(c.Desc, func(t *testing.T) { if c.DisableInvertSample { - featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", true) - defer featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", false) + err := featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", true) + assert.NoError(t, err) + defer func() { + err := featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", false) + assert.NoError(t, err) + }() } filter := NewStringAttributeFilter(componenttest.NewNopTelemetrySettings(), c.filterCfg.Key, c.filterCfg.Values, c.filterCfg.EnabledRegexMatching, c.filterCfg.CacheMaxSize, c.filterCfg.InvertMatch) decision, err := filter.Evaluate(context.Background(), pcommon.TraceID([16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}), c.Trace) From bbb5dfc20f704038859ca604b066a7a2c9f201c4 Mon Sep 17 00:00:00 2001 From: Sean Porter Date: Fri, 9 May 2025 10:27:40 -0700 Subject: [PATCH 4/6] first pass at readme inverted deprecation Signed-off-by: Sean Porter --- processor/tailsamplingprocessor/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/processor/tailsamplingprocessor/README.md b/processor/tailsamplingprocessor/README.md index f9ae20425bbe4..54450925faeb1 100644 --- a/processor/tailsamplingprocessor/README.md +++ b/processor/tailsamplingprocessor/README.md @@ -65,12 +65,12 @@ The following configuration options can also be modified: Each policy will result in a decision, and the processor will evaluate them to make a final decision: - When there's a "drop" decision, the trace is not sampled; -- When there's an "inverted not sample" decision, the trace is not sampled; +- When there's an "inverted not sample" decision, the trace is not sampled; *Deprecated* - When there's a "sample" decision, the trace is sampled; -- When there's a "inverted sample" decision and no "not sample" decisions, the trace is sampled; +- When there's a "inverted sample" decision and no "not sample" decisions, the trace is sampled; *Deprecated* - In all other cases, the trace is NOT sampled -An "inverted" decision is the one made based on the "invert_match" attribute, such as the one from the string, numeric or boolean tag policy. +An "inverted" decision is the one made based on the "invert_match" attribute, such as the one from the string, numeric or boolean tag policy. There is an exception to this if the policy is within an and or composite policy, the resulting decision will be either sampled or not sampled. The "inverted" decision has been deprecated, please make use of drop policy to explicitly not sample select traces. Examples: From 8ba0080c24a0c74addc5eb8c4700e2eaf2e3b179 Mon Sep 17 00:00:00 2001 From: Sean Porter Date: Fri, 9 May 2025 10:30:05 -0700 Subject: [PATCH 5/6] bold and italic deprecated Signed-off-by: Sean Porter --- processor/tailsamplingprocessor/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/processor/tailsamplingprocessor/README.md b/processor/tailsamplingprocessor/README.md index 54450925faeb1..7146aaf4f990a 100644 --- a/processor/tailsamplingprocessor/README.md +++ b/processor/tailsamplingprocessor/README.md @@ -65,9 +65,9 @@ The following configuration options can also be modified: Each policy will result in a decision, and the processor will evaluate them to make a final decision: - When there's a "drop" decision, the trace is not sampled; -- When there's an "inverted not sample" decision, the trace is not sampled; *Deprecated* +- When there's an "inverted not sample" decision, the trace is not sampled; ***Deprecated*** - When there's a "sample" decision, the trace is sampled; -- When there's a "inverted sample" decision and no "not sample" decisions, the trace is sampled; *Deprecated* +- When there's a "inverted sample" decision and no "not sample" decisions, the trace is sampled; ***Deprecated*** - In all other cases, the trace is NOT sampled An "inverted" decision is the one made based on the "invert_match" attribute, such as the one from the string, numeric or boolean tag policy. There is an exception to this if the policy is within an and or composite policy, the resulting decision will be either sampled or not sampled. The "inverted" decision has been deprecated, please make use of drop policy to explicitly not sample select traces. From 3b939c07b4b1bfdc691b411a48bd9f5e03462d8b Mon Sep 17 00:00:00 2001 From: Sean Porter Date: Fri, 9 May 2025 12:27:39 -0700 Subject: [PATCH 6/6] improved feature gate name and docs Signed-off-by: Sean Porter --- ...gprocessor-deprecate-invert-decisions.yaml | 27 ++++++++++++++ processor/tailsamplingprocessor/README.md | 8 ++++- .../sampling/boolean_tag_filter_test.go | 30 ++++++++-------- .../internal/sampling/featureflag.go | 8 ++--- .../sampling/numeric_tag_filter_test.go | 30 ++++++++-------- .../sampling/string_tag_filter_test.go | 36 +++++++++---------- .../internal/sampling/util.go | 2 +- 7 files changed, 87 insertions(+), 54 deletions(-) create mode 100644 .chloggen/tailsamplingprocessor-deprecate-invert-decisions.yaml diff --git a/.chloggen/tailsamplingprocessor-deprecate-invert-decisions.yaml b/.chloggen/tailsamplingprocessor-deprecate-invert-decisions.yaml new file mode 100644 index 0000000000000..0d439f06ee790 --- /dev/null +++ b/.chloggen/tailsamplingprocessor-deprecate-invert-decisions.yaml @@ -0,0 +1,27 @@ +# Use this changelog template to create an entry for release notes. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: deprecation + +# 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: The invert decisions (InvertSampled and InvertNotSampled) have been deprecated, please make use of drop policy to explicitly not sample select traces. + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [39833] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: + +# If your change doesn't affect end users or the exported elements of any package, +# you should instead start your pull request title with [chore] or use the "Skip Changelog" label. +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [] diff --git a/processor/tailsamplingprocessor/README.md b/processor/tailsamplingprocessor/README.md index 7146aaf4f990a..e20d4447544ff 100644 --- a/processor/tailsamplingprocessor/README.md +++ b/processor/tailsamplingprocessor/README.md @@ -70,7 +70,7 @@ Each policy will result in a decision, and the processor will evaluate them to m - When there's a "inverted sample" decision and no "not sample" decisions, the trace is sampled; ***Deprecated*** - In all other cases, the trace is NOT sampled -An "inverted" decision is the one made based on the "invert_match" attribute, such as the one from the string, numeric or boolean tag policy. There is an exception to this if the policy is within an and or composite policy, the resulting decision will be either sampled or not sampled. The "inverted" decision has been deprecated, please make use of drop policy to explicitly not sample select traces. +An "inverted" decision is the one made based on the "invert_match" attribute, such as the one from the string, numeric or boolean tag policy. There is an exception to this if the policy is within an and or composite policy, the resulting decision will be either sampled or not sampled. The "inverted" decisions have been deprecated, please make use of drop policy to explicitly not sample select traces. Examples: @@ -560,6 +560,12 @@ When this feature gate is set, this will add additional attributes on each sampl | `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 | +### Disable invert decisions + +The invert sampling decisions (`InvertSampled` and `InvertNotSampled`) have been deprecated, however, they are still available. To disable them before their complete removal, you can use the `processor.tailsamplingprocessor.disableinvertdecisions` feature gate. When this feature gate is set, sampling policy `invert_match` will result in a `Sampled` or `NotSampled` decision instead of `InvertSampled` or `InvertNotSampled`. This applies to the string, numeric, and boolean tag policy. + +If you disable invert decisions, you can make use of drop policy to explicitly not sample select traces. + ### Policy Evaluation Errors ``` diff --git a/processor/tailsamplingprocessor/internal/sampling/boolean_tag_filter_test.go b/processor/tailsamplingprocessor/internal/sampling/boolean_tag_filter_test.go index 61d0518185d87..1a13bbca8487f 100644 --- a/processor/tailsamplingprocessor/internal/sampling/boolean_tag_filter_test.go +++ b/processor/tailsamplingprocessor/internal/sampling/boolean_tag_filter_test.go @@ -62,10 +62,10 @@ func TestBooleanTagFilterInverted(t *testing.T) { resAttr["example"] = 8 cases := []struct { - Desc string - Trace *TraceData - Decision Decision - DisableInvertSample bool + Desc string + Trace *TraceData + Decision Decision + DisableInvertDecision bool }{ { Desc: "non-matching span attribute", @@ -83,26 +83,26 @@ func TestBooleanTagFilterInverted(t *testing.T) { Decision: InvertNotSampled, }, { - Desc: "span attribute with non matching boolean value with DisableInvertSample", - Trace: newTraceBoolAttrs(empty, "example", false), - Decision: Sampled, - DisableInvertSample: true, + Desc: "span attribute with non matching boolean value with DisableInvertDecision", + Trace: newTraceBoolAttrs(empty, "example", false), + Decision: Sampled, + DisableInvertDecision: true, }, { - Desc: "span attribute with matching boolean value with DisableInvertSample", - Trace: newTraceBoolAttrs(empty, "example", true), - Decision: NotSampled, - DisableInvertSample: true, + Desc: "span attribute with matching boolean value with DisableInvertDecision", + Trace: newTraceBoolAttrs(empty, "example", true), + Decision: NotSampled, + DisableInvertDecision: true, }, } for _, c := range cases { t.Run(c.Desc, func(t *testing.T) { - if c.DisableInvertSample { - err := featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", true) + if c.DisableInvertDecision { + err := featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertdecisions", true) assert.NoError(t, err) defer func() { - err := featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", false) + err := featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertdecisions", false) assert.NoError(t, err) }() } diff --git a/processor/tailsamplingprocessor/internal/sampling/featureflag.go b/processor/tailsamplingprocessor/internal/sampling/featureflag.go index 06f307598bc38..c42b0c1de9ed1 100644 --- a/processor/tailsamplingprocessor/internal/sampling/featureflag.go +++ b/processor/tailsamplingprocessor/internal/sampling/featureflag.go @@ -5,12 +5,12 @@ package sampling // import "github.com/open-telemetry/opentelemetry-collector-co import "go.opentelemetry.io/collector/featuregate" -var disableInvertSample = featuregate.GlobalRegistry().MustRegister( - "processor.tailsamplingprocessor.disableinvertsample", +var disableInvertDecisions = featuregate.GlobalRegistry().MustRegister( + "processor.tailsamplingprocessor.disableinvertdecisions", featuregate.StageAlpha, featuregate.WithRegisterDescription("When enabled, sampling policy 'invert_match' will result in a SAMPLED or NOT SAMPLED decision instead of INVERT SAMPLED or INVERT NOT SAMPLED."), ) -func IsInvertSampleDisabled() bool { - return disableInvertSample.IsEnabled() +func IsInvertDecisionsDisabled() bool { + return disableInvertDecisions.IsEnabled() } diff --git a/processor/tailsamplingprocessor/internal/sampling/numeric_tag_filter_test.go b/processor/tailsamplingprocessor/internal/sampling/numeric_tag_filter_test.go index 2034d2e8c83f6..f83d8b6e5061c 100644 --- a/processor/tailsamplingprocessor/internal/sampling/numeric_tag_filter_test.go +++ b/processor/tailsamplingprocessor/internal/sampling/numeric_tag_filter_test.go @@ -98,10 +98,10 @@ func TestNumericTagFilterInverted(t *testing.T) { resAttr["example"] = 8 cases := []struct { - Desc string - Trace *TraceData - Decision Decision - DisableInvertSample bool + Desc string + Trace *TraceData + Decision Decision + DisableInvertDecision bool }{ { Desc: "nonmatching span attribute", @@ -149,26 +149,26 @@ func TestNumericTagFilterInverted(t *testing.T) { Decision: InvertSampled, }, { - Desc: "nonmatching span attribute with DisableInvertSample", - Trace: newTraceIntAttrs(empty, "non_matching", math.MinInt32), - Decision: Sampled, - DisableInvertSample: true, + Desc: "nonmatching span attribute with DisableInvertDecision", + Trace: newTraceIntAttrs(empty, "non_matching", math.MinInt32), + Decision: Sampled, + DisableInvertDecision: true, }, { - Desc: "span attribute at the lower limit with DisableInvertSample", - Trace: newTraceIntAttrs(empty, "example", math.MinInt32), - Decision: NotSampled, - DisableInvertSample: true, + Desc: "span attribute at the lower limit with DisableInvertDecision", + Trace: newTraceIntAttrs(empty, "example", math.MinInt32), + Decision: NotSampled, + DisableInvertDecision: true, }, } for _, c := range cases { t.Run(c.Desc, func(t *testing.T) { - if c.DisableInvertSample { - err := featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", true) + if c.DisableInvertDecision { + err := featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertdecisions", true) assert.NoError(t, err) defer func() { - err := featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", false) + err := featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertdecisions", false) assert.NoError(t, err) }() } diff --git a/processor/tailsamplingprocessor/internal/sampling/string_tag_filter_test.go b/processor/tailsamplingprocessor/internal/sampling/string_tag_filter_test.go index 46893b1ffffc4..62f0899e8c7e7 100644 --- a/processor/tailsamplingprocessor/internal/sampling/string_tag_filter_test.go +++ b/processor/tailsamplingprocessor/internal/sampling/string_tag_filter_test.go @@ -25,11 +25,11 @@ type TestStringAttributeCfg struct { func TestStringTagFilter(t *testing.T) { cases := []struct { - Desc string - Trace *TraceData - filterCfg *TestStringAttributeCfg - Decision Decision - DisableInvertSample bool + Desc string + Trace *TraceData + filterCfg *TestStringAttributeCfg + Decision Decision + DisableInvertDecision bool }{ { Desc: "nonmatching node attribute key", @@ -200,28 +200,28 @@ func TestStringTagFilter(t *testing.T) { Decision: InvertSampled, }, { - Desc: "invert matching node attribute key with DisableInvertSample", - Trace: newTraceStringAttrs(map[string]any{"example": "value"}, "", ""), - filterCfg: &TestStringAttributeCfg{Key: "example", Values: []string{"value"}, EnabledRegexMatching: false, CacheMaxSize: defaultCacheSize, InvertMatch: true}, - Decision: NotSampled, - DisableInvertSample: true, + Desc: "invert matching node attribute key with DisableInvertDecision", + Trace: newTraceStringAttrs(map[string]any{"example": "value"}, "", ""), + filterCfg: &TestStringAttributeCfg{Key: "example", Values: []string{"value"}, EnabledRegexMatching: false, CacheMaxSize: defaultCacheSize, InvertMatch: true}, + Decision: NotSampled, + DisableInvertDecision: true, }, { - Desc: "invert nonmatching node attribute key with DisableInvertSample", - Trace: newTraceStringAttrs(map[string]any{"non_matching": "value"}, "", ""), - filterCfg: &TestStringAttributeCfg{Key: "example", Values: []string{"value"}, EnabledRegexMatching: false, CacheMaxSize: defaultCacheSize, InvertMatch: true}, - Decision: Sampled, - DisableInvertSample: true, + Desc: "invert nonmatching node attribute key with DisableInvertDecision", + Trace: newTraceStringAttrs(map[string]any{"non_matching": "value"}, "", ""), + filterCfg: &TestStringAttributeCfg{Key: "example", Values: []string{"value"}, EnabledRegexMatching: false, CacheMaxSize: defaultCacheSize, InvertMatch: true}, + Decision: Sampled, + DisableInvertDecision: true, }, } for _, c := range cases { t.Run(c.Desc, func(t *testing.T) { - if c.DisableInvertSample { - err := featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", true) + if c.DisableInvertDecision { + err := featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertdecisions", true) assert.NoError(t, err) defer func() { - err := featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertsample", false) + err := featuregate.GlobalRegistry().Set("processor.tailsamplingprocessor.disableinvertdecisions", false) assert.NoError(t, err) }() } diff --git a/processor/tailsamplingprocessor/internal/sampling/util.go b/processor/tailsamplingprocessor/internal/sampling/util.go index af387661b7f88..eb23e55acfef3 100644 --- a/processor/tailsamplingprocessor/internal/sampling/util.go +++ b/processor/tailsamplingprocessor/internal/sampling/util.go @@ -37,7 +37,7 @@ func invertHasResourceOrSpanWithCondition( shouldSampleResource func(resource pcommon.Resource) bool, shouldSampleSpan func(span ptrace.Span) bool, ) Decision { - isd := IsInvertSampleDisabled() + isd := IsInvertDecisionsDisabled() for i := 0; i < td.ResourceSpans().Len(); i++ { rs := td.ResourceSpans().At(i)