mirror of
https://github.com/hanzoai/traces.git
synced 2026-10-30 18:20:41 +00:00
* added spanfilter to filter out spans * return the error if the filters are not correctly formatted * add filters to the userconfigurable overrides * add core logic for drop items cache * wired up everything * some tweaks * refactor * fmt and manifest * tighten names * rename metric * drop already buffered counterparts when a span is filter out * add a new test and documentation * Update docs/sources/tempo/operations/manage-advanced-systems/user-configurable-overrides.md Co-authored-by: Suraj Nath <[email protected]> * Update docs/sources/tempo/configuration/_index.md Co-authored-by: Suraj Nath <[email protected]> * Update docs/sources/tempo/configuration/_index.md Co-authored-by: Suraj Nath <[email protected]> * bail early when the span kind is not client or server * Update docs/sources/tempo/operations/manage-advanced-systems/user-configurable-overrides.md Co-authored-by: Suraj Nath <[email protected]> --------- Co-authored-by: Suraj Nath <[email protected]>
283 lines
8.5 KiB
Go
283 lines
8.5 KiB
Go
package generator
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/grafana/tempo/modules/generator/processor/servicegraphs"
|
|
"github.com/grafana/tempo/modules/generator/processor/spanmetrics"
|
|
"github.com/grafana/tempo/pkg/sharedconfig"
|
|
"github.com/grafana/tempo/pkg/spanfilter/config"
|
|
)
|
|
|
|
func TestProcessorConfig_copyWithOverrides(t *testing.T) {
|
|
original := &ProcessorConfig{
|
|
ServiceGraphs: servicegraphs.Config{
|
|
HistogramBuckets: []float64{1},
|
|
Dimensions: []string{},
|
|
},
|
|
SpanMetrics: spanmetrics.Config{
|
|
HistogramBuckets: []float64{1, 2},
|
|
Dimensions: []string{"namespace"},
|
|
IntrinsicDimensions: spanmetrics.IntrinsicDimensions{Service: true},
|
|
Subprocessors: map[spanmetrics.Subprocessor]bool{},
|
|
},
|
|
}
|
|
|
|
t.Run("test enable service graph flags", func(t *testing.T) {
|
|
o := &mockOverrides{
|
|
serviceGraphsEnableClientServerPrefix: true,
|
|
serviceGraphsEnableVirtualNodeLabel: boolPtr(true),
|
|
serviceGraphsEnableMessagingSystemLatencyHistogram: boolPtr(true),
|
|
}
|
|
|
|
copied, err := original.copyWithOverrides(o, "tenant")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, true, copied.ServiceGraphs.EnableClientServerPrefix)
|
|
assert.Equal(t, true, copied.ServiceGraphs.EnableVirtualNodeLabel)
|
|
assert.Equal(t, true, copied.ServiceGraphs.EnableMessagingSystemLatencyHistogram)
|
|
})
|
|
t.Run("overrides buckets and dimension", func(t *testing.T) {
|
|
o := &mockOverrides{
|
|
serviceGraphsHistogramBuckets: []float64{1, 2},
|
|
serviceGraphsDimensions: []string{"namespace"},
|
|
spanMetricsHistogramBuckets: []float64{1, 2, 3},
|
|
spanMetricsDimensions: []string{"cluster", "namespace"},
|
|
spanMetricsIntrinsicDimensions: map[string]bool{"status_code": true},
|
|
}
|
|
|
|
copied, err := original.copyWithOverrides(o, "tenant")
|
|
require.NoError(t, err)
|
|
|
|
assert.NotEqual(t, *original, copied)
|
|
|
|
// assert nothing changed
|
|
assert.Equal(t, []float64{1}, original.ServiceGraphs.HistogramBuckets)
|
|
assert.Equal(t, []string{}, original.ServiceGraphs.Dimensions)
|
|
assert.Equal(t, []float64{1, 2}, original.SpanMetrics.HistogramBuckets)
|
|
assert.Equal(t, []string{"namespace"}, original.SpanMetrics.Dimensions)
|
|
assert.Equal(t, spanmetrics.IntrinsicDimensions{Service: true}, original.SpanMetrics.IntrinsicDimensions)
|
|
|
|
// assert overrides were applied
|
|
assert.Equal(t, []float64{1, 2}, copied.ServiceGraphs.HistogramBuckets)
|
|
assert.Equal(t, []string{"namespace"}, copied.ServiceGraphs.Dimensions)
|
|
assert.Equal(t, []float64{1, 2, 3}, copied.SpanMetrics.HistogramBuckets)
|
|
assert.Equal(t, []string{"cluster", "namespace"}, copied.SpanMetrics.Dimensions)
|
|
assert.Equal(t, spanmetrics.IntrinsicDimensions{Service: true, StatusCode: true}, copied.SpanMetrics.IntrinsicDimensions)
|
|
})
|
|
|
|
t.Run("empty overrides", func(t *testing.T) {
|
|
o := &mockOverrides{}
|
|
|
|
copied, err := original.copyWithOverrides(o, "tenant")
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, *original, copied)
|
|
})
|
|
|
|
t.Run("invalid overrides", func(t *testing.T) {
|
|
o := &mockOverrides{
|
|
spanMetricsIntrinsicDimensions: map[string]bool{"invalid": true},
|
|
}
|
|
|
|
_, err := original.copyWithOverrides(o, "tenant")
|
|
require.Error(t, err)
|
|
})
|
|
|
|
t.Run("nil policy overrides", func(t *testing.T) {
|
|
o := &mockOverrides{
|
|
spanMetricsFilterPolicies: nil,
|
|
}
|
|
|
|
copied, err := original.copyWithOverrides(o, "tenant")
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, *original, copied)
|
|
})
|
|
|
|
t.Run("empty policy overrides", func(t *testing.T) {
|
|
o := &mockOverrides{
|
|
spanMetricsFilterPolicies: []config.FilterPolicy{},
|
|
}
|
|
|
|
copied, err := original.copyWithOverrides(o, "tenant")
|
|
require.NoError(t, err)
|
|
|
|
assert.NotEqual(t, *original, copied)
|
|
|
|
assert.Equal(t, []config.FilterPolicy{}, copied.SpanMetrics.FilterPolicies)
|
|
})
|
|
|
|
t.Run("policy overrides", func(t *testing.T) {
|
|
o := &mockOverrides{
|
|
spanMetricsFilterPolicies: []config.FilterPolicy{
|
|
{
|
|
Include: &config.PolicyMatch{
|
|
MatchType: config.Strict,
|
|
Attributes: []config.MatchPolicyAttribute{
|
|
{
|
|
Key: "key",
|
|
Value: "value",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
copied, err := original.copyWithOverrides(o, "tenant")
|
|
require.NoError(t, err)
|
|
|
|
assert.NotEqual(t, *original, copied)
|
|
|
|
assert.Equal(t, []config.FilterPolicy{
|
|
{
|
|
Include: &config.PolicyMatch{
|
|
MatchType: config.Strict,
|
|
Attributes: []config.MatchPolicyAttribute{
|
|
{
|
|
Key: "key",
|
|
Value: "value",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}, copied.SpanMetrics.FilterPolicies)
|
|
})
|
|
|
|
t.Run("servicegraphs nil policy overrides", func(t *testing.T) {
|
|
o := &mockOverrides{
|
|
serviceGraphsFilterPolicies: nil,
|
|
}
|
|
|
|
copied, err := original.copyWithOverrides(o, "tenant")
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, *original, copied)
|
|
})
|
|
|
|
t.Run("servicegraphs empty policy overrides", func(t *testing.T) {
|
|
o := &mockOverrides{
|
|
serviceGraphsFilterPolicies: []config.FilterPolicy{},
|
|
}
|
|
|
|
copied, err := original.copyWithOverrides(o, "tenant")
|
|
require.NoError(t, err)
|
|
|
|
assert.NotEqual(t, *original, copied)
|
|
assert.Equal(t, []config.FilterPolicy{}, copied.ServiceGraphs.FilterPolicies)
|
|
})
|
|
|
|
t.Run("servicegraphs policy overrides", func(t *testing.T) {
|
|
o := &mockOverrides{
|
|
serviceGraphsFilterPolicies: []config.FilterPolicy{
|
|
{
|
|
Exclude: &config.PolicyMatch{
|
|
MatchType: config.Strict,
|
|
Attributes: []config.MatchPolicyAttribute{
|
|
{
|
|
Key: "resource.service.name",
|
|
Value: "mythical-requester",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
copied, err := original.copyWithOverrides(o, "tenant")
|
|
require.NoError(t, err)
|
|
|
|
assert.NotEqual(t, *original, copied)
|
|
assert.Equal(t, []config.FilterPolicy{
|
|
{
|
|
Exclude: &config.PolicyMatch{
|
|
MatchType: config.Strict,
|
|
Attributes: []config.MatchPolicyAttribute{
|
|
{
|
|
Key: "resource.service.name",
|
|
Value: "mythical-requester",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}, copied.ServiceGraphs.FilterPolicies)
|
|
})
|
|
|
|
t.Run("span multiplier key overrides", func(t *testing.T) {
|
|
o := &mockOverrides{
|
|
serviceGraphsSpanMultiplierKey: "custom_key",
|
|
spanMetricsSpanMultiplierKey: "custom_key",
|
|
}
|
|
|
|
copied, err := original.copyWithOverrides(o, "tenant")
|
|
require.NoError(t, err)
|
|
|
|
assert.NotEqual(t, *original, copied)
|
|
assert.Equal(t, "custom_key", copied.ServiceGraphs.SpanMultiplierKey)
|
|
assert.Equal(t, "custom_key", copied.SpanMetrics.SpanMultiplierKey)
|
|
})
|
|
|
|
t.Run("dimension_mappings preserved when no override", func(t *testing.T) {
|
|
// Create original config with dimension_mappings set
|
|
originalWithMappings := &ProcessorConfig{
|
|
SpanMetrics: spanmetrics.Config{
|
|
DimensionMappings: []sharedconfig.DimensionMappings{
|
|
{Name: "env", SourceLabel: []string{"deployment.environment"}},
|
|
},
|
|
TargetInfoExcludedDimensions: []string{"telemetry.sdk.version"},
|
|
},
|
|
}
|
|
|
|
// Empty overrides should preserve base config values
|
|
o := &mockOverrides{}
|
|
|
|
copied, err := originalWithMappings.copyWithOverrides(o, "tenant")
|
|
require.NoError(t, err)
|
|
|
|
// Verify dimension_mappings from base config is preserved
|
|
assert.Equal(t, []sharedconfig.DimensionMappings{
|
|
{Name: "env", SourceLabel: []string{"deployment.environment"}},
|
|
}, copied.SpanMetrics.DimensionMappings)
|
|
|
|
// Verify target_info_excluded_dimensions from base config is preserved
|
|
assert.Equal(t, []string{"telemetry.sdk.version"}, copied.SpanMetrics.TargetInfoExcludedDimensions)
|
|
})
|
|
|
|
t.Run("dimension_mappings overridden when override is set", func(t *testing.T) {
|
|
// Create original config with dimension_mappings set
|
|
originalWithMappings := &ProcessorConfig{
|
|
SpanMetrics: spanmetrics.Config{
|
|
DimensionMappings: []sharedconfig.DimensionMappings{
|
|
{Name: "env", SourceLabel: []string{"deployment.environment"}},
|
|
},
|
|
TargetInfoExcludedDimensions: []string{"telemetry.sdk.version"},
|
|
},
|
|
}
|
|
|
|
// Override should replace base config values
|
|
o := &mockOverrides{
|
|
spanMetricsDimensionMappings: []sharedconfig.DimensionMappings{
|
|
{Name: "cluster", SourceLabel: []string{"k8s.cluster.name"}},
|
|
},
|
|
spanMetricsTargetInfoExcludedDimensions: []string{"process.runtime.version"},
|
|
}
|
|
|
|
copied, err := originalWithMappings.copyWithOverrides(o, "tenant")
|
|
require.NoError(t, err)
|
|
|
|
// Verify override replaced base config
|
|
assert.Equal(t, []sharedconfig.DimensionMappings{
|
|
{Name: "cluster", SourceLabel: []string{"k8s.cluster.name"}},
|
|
}, copied.SpanMetrics.DimensionMappings)
|
|
|
|
assert.Equal(t, []string{"process.runtime.version"}, copied.SpanMetrics.TargetInfoExcludedDimensions)
|
|
})
|
|
}
|
|
|
|
func boolPtr(b bool) *bool {
|
|
return &b
|
|
}
|