diff --git a/.chloggen/ottl-parser-signatiure-opts.yaml b/.chloggen/ottl-parser-signatiure-opts.yaml new file mode 100644 index 000000000000..d86e0927ddf4 --- /dev/null +++ b/.chloggen/ottl-parser-signatiure-opts.yaml @@ -0,0 +1,16 @@ +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: breaking + +# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) +component: pkg/ottl + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: Change signatures of ottl and all context Parsers to accept a list of Options. + +# One or more tracking issues related to the change +issues: [13759] + +# (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: diff --git a/pkg/ottl/boolean_value_test.go b/pkg/ottl/boolean_value_test.go index af914d80f8fc..9e8d869fdac3 100644 --- a/pkg/ottl/boolean_value_test.go +++ b/pkg/ottl/boolean_value_test.go @@ -81,11 +81,11 @@ func comparisonHelper(left any, right any, op string) *comparison { } func Test_newComparisonEvaluator(t *testing.T) { - p := NewParser( + p := NewParser[any]( defaultFunctionsForTests(), testParsePath, - testParseEnum, componenttest.NewNopTelemetrySettings(), + WithEnumParser[any](testParseEnum), ) var tests = []struct { @@ -132,11 +132,11 @@ func Test_newComparisonEvaluator(t *testing.T) { } func Test_newConditionEvaluator_invalid(t *testing.T) { - p := NewParser( + p := NewParser[any]( defaultFunctionsForTests(), testParsePath, - testParseEnum, component.TelemetrySettings{}, + WithEnumParser[any](testParseEnum), ) tests := []struct { @@ -165,11 +165,11 @@ func Test_newConditionEvaluator_invalid(t *testing.T) { } func Test_newBooleanExpressionEvaluator(t *testing.T) { - p := NewParser( + p := NewParser[any]( defaultFunctionsForTests(), testParsePath, - testParseEnum, component.TelemetrySettings{}, + WithEnumParser[any](testParseEnum), ) tests := []struct { diff --git a/pkg/ottl/compare_test.go b/pkg/ottl/compare_test.go index 8fe502799fd8..5fe0e5f8786a 100644 --- a/pkg/ottl/compare_test.go +++ b/pkg/ottl/compare_test.go @@ -116,7 +116,7 @@ func Test_compare(t *testing.T) { for _, tt := range tests { for _, op := range ops { t.Run(fmt.Sprintf("%s %v", tt.name, op), func(t *testing.T) { - p := NewParser[interface{}](nil, nil, nil, componenttest.NewNopTelemetrySettings()) + p := NewParser[interface{}](nil, nil, componenttest.NewNopTelemetrySettings()) if got := p.compare(tt.a, tt.b, op); got != tt.want[op] { t.Errorf("compare(%v, %v, %v) = %v, want %v", tt.a, tt.b, op, got, tt.want[op]) } @@ -130,7 +130,7 @@ func Test_compare(t *testing.T) { // The summary is that they're pretty fast; all the calls to compare are 12 ns/op or less on a 2019 intel // mac pro laptop, and none of them have any allocations. func BenchmarkCompareEQInt64(b *testing.B) { - testParser := NewParser[interface{}](nil, nil, nil, componenttest.NewNopTelemetrySettings()) + testParser := NewParser[interface{}](nil, nil, componenttest.NewNopTelemetrySettings()) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { @@ -139,7 +139,7 @@ func BenchmarkCompareEQInt64(b *testing.B) { } func BenchmarkCompareEQFloat(b *testing.B) { - testParser := NewParser[interface{}](nil, nil, nil, componenttest.NewNopTelemetrySettings()) + testParser := NewParser[interface{}](nil, nil, componenttest.NewNopTelemetrySettings()) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { @@ -148,7 +148,7 @@ func BenchmarkCompareEQFloat(b *testing.B) { } func BenchmarkCompareEQString(b *testing.B) { - testParser := NewParser[interface{}](nil, nil, nil, componenttest.NewNopTelemetrySettings()) + testParser := NewParser[interface{}](nil, nil, componenttest.NewNopTelemetrySettings()) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { @@ -157,7 +157,7 @@ func BenchmarkCompareEQString(b *testing.B) { } func BenchmarkCompareEQPString(b *testing.B) { - testParser := NewParser[interface{}](nil, nil, nil, componenttest.NewNopTelemetrySettings()) + testParser := NewParser[interface{}](nil, nil, componenttest.NewNopTelemetrySettings()) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { @@ -166,7 +166,7 @@ func BenchmarkCompareEQPString(b *testing.B) { } func BenchmarkCompareEQBytes(b *testing.B) { - testParser := NewParser[interface{}](nil, nil, nil, componenttest.NewNopTelemetrySettings()) + testParser := NewParser[interface{}](nil, nil, componenttest.NewNopTelemetrySettings()) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { @@ -175,7 +175,7 @@ func BenchmarkCompareEQBytes(b *testing.B) { } func BenchmarkCompareEQNil(b *testing.B) { - testParser := NewParser[interface{}](nil, nil, nil, componenttest.NewNopTelemetrySettings()) + testParser := NewParser[interface{}](nil, nil, componenttest.NewNopTelemetrySettings()) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { @@ -184,7 +184,7 @@ func BenchmarkCompareEQNil(b *testing.B) { } func BenchmarkCompareNEInt(b *testing.B) { - testParser := NewParser[interface{}](nil, nil, nil, componenttest.NewNopTelemetrySettings()) + testParser := NewParser[interface{}](nil, nil, componenttest.NewNopTelemetrySettings()) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { @@ -193,7 +193,7 @@ func BenchmarkCompareNEInt(b *testing.B) { } func BenchmarkCompareNEFloat(b *testing.B) { - testParser := NewParser[interface{}](nil, nil, nil, componenttest.NewNopTelemetrySettings()) + testParser := NewParser[interface{}](nil, nil, componenttest.NewNopTelemetrySettings()) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { @@ -202,7 +202,7 @@ func BenchmarkCompareNEFloat(b *testing.B) { } func BenchmarkCompareNEString(b *testing.B) { - testParser := NewParser[interface{}](nil, nil, nil, componenttest.NewNopTelemetrySettings()) + testParser := NewParser[interface{}](nil, nil, componenttest.NewNopTelemetrySettings()) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { @@ -211,7 +211,7 @@ func BenchmarkCompareNEString(b *testing.B) { } func BenchmarkCompareLTFloat(b *testing.B) { - testParser := NewParser[interface{}](nil, nil, nil, componenttest.NewNopTelemetrySettings()) + testParser := NewParser[interface{}](nil, nil, componenttest.NewNopTelemetrySettings()) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { @@ -220,7 +220,7 @@ func BenchmarkCompareLTFloat(b *testing.B) { } func BenchmarkCompareLTString(b *testing.B) { - testParser := NewParser[interface{}](nil, nil, nil, componenttest.NewNopTelemetrySettings()) + testParser := NewParser[interface{}](nil, nil, componenttest.NewNopTelemetrySettings()) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { @@ -229,7 +229,7 @@ func BenchmarkCompareLTString(b *testing.B) { } func BenchmarkCompareLTNil(b *testing.B) { - testParser := NewParser[interface{}](nil, nil, nil, componenttest.NewNopTelemetrySettings()) + testParser := NewParser[interface{}](nil, nil, componenttest.NewNopTelemetrySettings()) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { diff --git a/pkg/ottl/contexts/ottldatapoint/datapoint.go b/pkg/ottl/contexts/ottldatapoint/datapoint.go index 271a3ded18d8..0c489fecc6d1 100644 --- a/pkg/ottl/contexts/ottldatapoint/datapoint.go +++ b/pkg/ottl/contexts/ottldatapoint/datapoint.go @@ -39,6 +39,8 @@ type TransformContext struct { cache pcommon.Map } +type Option func(*ottl.Parser[TransformContext]) + func NewTransformContext(dataPoint interface{}, metric pmetric.Metric, metrics pmetric.MetricSlice, instrumentationScope pcommon.InstrumentationScope, resource pcommon.Resource) TransformContext { return TransformContext{ dataPoint: dataPoint, @@ -74,8 +76,17 @@ func (tCtx TransformContext) getCache() pcommon.Map { return tCtx.cache } -func NewParser(functions map[string]interface{}, telemetrySettings component.TelemetrySettings) ottl.Parser[TransformContext] { - return ottl.NewParser[TransformContext](functions, parsePath, parseEnum, telemetrySettings) +func NewParser(functions map[string]interface{}, telemetrySettings component.TelemetrySettings, options ...Option) ottl.Parser[TransformContext] { + p := ottl.NewParser[TransformContext]( + functions, + parsePath, + telemetrySettings, + ottl.WithEnumParser[TransformContext](parseEnum), + ) + for _, opt := range options { + opt(&p) + } + return p } var symbolTable = map[ottl.EnumSymbol]ottl.Enum{ diff --git a/pkg/ottl/contexts/ottllog/log.go b/pkg/ottl/contexts/ottllog/log.go index d8b2e5aacc23..4987414d9d80 100644 --- a/pkg/ottl/contexts/ottllog/log.go +++ b/pkg/ottl/contexts/ottllog/log.go @@ -38,6 +38,8 @@ type TransformContext struct { cache pcommon.Map } +type Option func(*ottl.Parser[TransformContext]) + func NewTransformContext(logRecord plog.LogRecord, instrumentationScope pcommon.InstrumentationScope, resource pcommon.Resource) TransformContext { return TransformContext{ logRecord: logRecord, @@ -63,8 +65,17 @@ func (tCtx TransformContext) getCache() pcommon.Map { return tCtx.cache } -func NewParser(functions map[string]interface{}, telemetrySettings component.TelemetrySettings) ottl.Parser[TransformContext] { - return ottl.NewParser[TransformContext](functions, parsePath, parseEnum, telemetrySettings) +func NewParser(functions map[string]interface{}, telemetrySettings component.TelemetrySettings, options ...Option) ottl.Parser[TransformContext] { + p := ottl.NewParser[TransformContext]( + functions, + parsePath, + telemetrySettings, + ottl.WithEnumParser[TransformContext](parseEnum), + ) + for _, opt := range options { + opt(&p) + } + return p } var symbolTable = map[ottl.EnumSymbol]ottl.Enum{ diff --git a/pkg/ottl/contexts/ottlmetric/metrics.go b/pkg/ottl/contexts/ottlmetric/metrics.go index 98238ff3830a..5eecbea6ae86 100644 --- a/pkg/ottl/contexts/ottlmetric/metrics.go +++ b/pkg/ottl/contexts/ottlmetric/metrics.go @@ -37,6 +37,8 @@ type TransformContext struct { cache pcommon.Map } +type Option func(*ottl.Parser[TransformContext]) + func NewTransformContext(metric pmetric.Metric, instrumentationScope pcommon.InstrumentationScope, resource pcommon.Resource) TransformContext { return TransformContext{ metric: metric, @@ -62,8 +64,17 @@ func (tCtx TransformContext) getCache() pcommon.Map { return tCtx.cache } -func NewParser(functions map[string]interface{}, telemetrySettings component.TelemetrySettings) ottl.Parser[TransformContext] { - return ottl.NewParser[TransformContext](functions, parsePath, parseEnum, telemetrySettings) +func NewParser(functions map[string]interface{}, telemetrySettings component.TelemetrySettings, options ...Option) ottl.Parser[TransformContext] { + p := ottl.NewParser[TransformContext]( + functions, + parsePath, + telemetrySettings, + ottl.WithEnumParser[TransformContext](parseEnum), + ) + for _, opt := range options { + opt(&p) + } + return p } var symbolTable = ottlcommon.MetricSymbolTable diff --git a/pkg/ottl/contexts/ottlresource/resource.go b/pkg/ottl/contexts/ottlresource/resource.go index 86b804b40fd9..91f872f20574 100644 --- a/pkg/ottl/contexts/ottlresource/resource.go +++ b/pkg/ottl/contexts/ottlresource/resource.go @@ -32,6 +32,8 @@ type TransformContext struct { cache pcommon.Map } +type Option func(*ottl.Parser[TransformContext]) + func NewTransformContext(resource pcommon.Resource) TransformContext { return TransformContext{ resource: resource, @@ -47,8 +49,17 @@ func (tCtx TransformContext) getCache() pcommon.Map { return tCtx.cache } -func NewParser(functions map[string]interface{}, telemetrySettings component.TelemetrySettings) ottl.Parser[TransformContext] { - return ottl.NewParser[TransformContext](functions, parsePath, parseEnum, telemetrySettings) +func NewParser(functions map[string]interface{}, telemetrySettings component.TelemetrySettings, options ...Option) ottl.Parser[TransformContext] { + p := ottl.NewParser[TransformContext]( + functions, + parsePath, + telemetrySettings, + ottl.WithEnumParser[TransformContext](parseEnum), + ) + for _, opt := range options { + opt(&p) + } + return p } func parseEnum(_ *ottl.EnumSymbol) (*ottl.Enum, error) { diff --git a/pkg/ottl/contexts/ottlscope/scope.go b/pkg/ottl/contexts/ottlscope/scope.go index 33d9c1465adf..0bcb9c621192 100644 --- a/pkg/ottl/contexts/ottlscope/scope.go +++ b/pkg/ottl/contexts/ottlscope/scope.go @@ -34,6 +34,8 @@ type TransformContext struct { cache pcommon.Map } +type Option func(*ottl.Parser[TransformContext]) + func NewTransformContext(instrumentationScope pcommon.InstrumentationScope, resource pcommon.Resource) TransformContext { return TransformContext{ instrumentationScope: instrumentationScope, @@ -54,8 +56,17 @@ func (tCtx TransformContext) getCache() pcommon.Map { return tCtx.cache } -func NewParser(functions map[string]interface{}, telemetrySettings component.TelemetrySettings) ottl.Parser[TransformContext] { - return ottl.NewParser[TransformContext](functions, parsePath, parseEnum, telemetrySettings) +func NewParser(functions map[string]interface{}, telemetrySettings component.TelemetrySettings, options ...Option) ottl.Parser[TransformContext] { + p := ottl.NewParser[TransformContext]( + functions, + parsePath, + telemetrySettings, + ottl.WithEnumParser[TransformContext](parseEnum), + ) + for _, opt := range options { + opt(&p) + } + return p } func parseEnum(val *ottl.EnumSymbol) (*ottl.Enum, error) { diff --git a/pkg/ottl/contexts/ottlspan/span.go b/pkg/ottl/contexts/ottlspan/span.go index 61ead7a1240d..8a03f08222dd 100644 --- a/pkg/ottl/contexts/ottlspan/span.go +++ b/pkg/ottl/contexts/ottlspan/span.go @@ -36,6 +36,8 @@ type TransformContext struct { cache pcommon.Map } +type Option func(*ottl.Parser[TransformContext]) + func NewTransformContext(span ptrace.Span, instrumentationScope pcommon.InstrumentationScope, resource pcommon.Resource) TransformContext { return TransformContext{ span: span, @@ -61,8 +63,17 @@ func (tCtx TransformContext) getCache() pcommon.Map { return tCtx.cache } -func NewParser(functions map[string]interface{}, telemetrySettings component.TelemetrySettings) ottl.Parser[TransformContext] { - return ottl.NewParser[TransformContext](functions, parsePath, parseEnum, telemetrySettings) +func NewParser(functions map[string]interface{}, telemetrySettings component.TelemetrySettings, options ...Option) ottl.Parser[TransformContext] { + p := ottl.NewParser[TransformContext]( + functions, + parsePath, + telemetrySettings, + ottl.WithEnumParser[TransformContext](parseEnum), + ) + for _, opt := range options { + opt(&p) + } + return p } func parseEnum(val *ottl.EnumSymbol) (*ottl.Enum, error) { diff --git a/pkg/ottl/contexts/ottlspanevent/span_events.go b/pkg/ottl/contexts/ottlspanevent/span_events.go index bce1d2a81cf7..85363f117e87 100644 --- a/pkg/ottl/contexts/ottlspanevent/span_events.go +++ b/pkg/ottl/contexts/ottlspanevent/span_events.go @@ -39,6 +39,8 @@ type TransformContext struct { cache pcommon.Map } +type Option func(*ottl.Parser[TransformContext]) + func NewTransformContext(spanEvent ptrace.SpanEvent, span ptrace.Span, instrumentationScope pcommon.InstrumentationScope, resource pcommon.Resource) TransformContext { return TransformContext{ spanEvent: spanEvent, @@ -69,8 +71,17 @@ func (tCtx TransformContext) getCache() pcommon.Map { return tCtx.cache } -func NewParser(functions map[string]interface{}, telemetrySettings component.TelemetrySettings) ottl.Parser[TransformContext] { - return ottl.NewParser[TransformContext](functions, parsePath, parseEnum, telemetrySettings) +func NewParser(functions map[string]interface{}, telemetrySettings component.TelemetrySettings, options ...Option) ottl.Parser[TransformContext] { + p := ottl.NewParser[TransformContext]( + functions, + parsePath, + telemetrySettings, + ottl.WithEnumParser[TransformContext](parseEnum), + ) + for _, opt := range options { + opt(&p) + } + return p } func parseEnum(val *ottl.EnumSymbol) (*ottl.Enum, error) { diff --git a/pkg/ottl/expression_test.go b/pkg/ottl/expression_test.go index 4851f2fb1aee..b6faff33ee2d 100644 --- a/pkg/ottl/expression_test.go +++ b/pkg/ottl/expression_test.go @@ -290,11 +290,11 @@ func Test_newGetter(t *testing.T) { functions := map[string]interface{}{"Hello": hello[interface{}]} - p := NewParser( + p := NewParser[any]( functions, testParsePath, - testParseEnum, component.TelemetrySettings{}, + WithEnumParser[any](testParseEnum), ) for _, tt := range tests { diff --git a/pkg/ottl/functions_test.go b/pkg/ottl/functions_test.go index 4d3e22a1e6fc..ba37e37cdfc9 100644 --- a/pkg/ottl/functions_test.go +++ b/pkg/ottl/functions_test.go @@ -37,11 +37,11 @@ func Test_NewFunctionCall_invalid(t *testing.T) { functions["testing_enum"] = functionWithEnum functions["testing_telemetry_settings_first"] = functionWithTelemetrySettingsFirst - p := NewParser( + p := NewParser[any]( functions, testParsePath, - testParseEnum, component.TelemetrySettings{}, + WithEnumParser[any](testParseEnum), ) tests := []struct { @@ -269,11 +269,11 @@ func Test_NewFunctionCall_invalid(t *testing.T) { } func Test_NewFunctionCall(t *testing.T) { - p := NewParser( + p := NewParser[any]( defaultFunctionsForTests(), testParsePath, - testParseEnum, component.TelemetrySettings{}, + WithEnumParser[any](testParseEnum), ) tests := []struct { diff --git a/pkg/ottl/math_test.go b/pkg/ottl/math_test.go index b6fc92bb2619..4f73f11ded30 100644 --- a/pkg/ottl/math_test.go +++ b/pkg/ottl/math_test.go @@ -215,8 +215,8 @@ func Test_evaluateMathExpression(t *testing.T) { p := NewParser[any]( functions, mathParsePath, - testParseEnum, component.TelemetrySettings{}, + WithEnumParser[any](testParseEnum), ) mathParser := newParser[value]() @@ -258,8 +258,8 @@ func Test_evaluateMathExpression_error(t *testing.T) { p := NewParser[any]( functions, mathParsePath, - testParseEnum, component.TelemetrySettings{}, + WithEnumParser[any](testParseEnum), ) mathParser := newParser[value]() diff --git a/pkg/ottl/parser.go b/pkg/ottl/parser.go index 3e4cc529f615..2f053098c8c3 100644 --- a/pkg/ottl/parser.go +++ b/pkg/ottl/parser.go @@ -56,12 +56,31 @@ func (s *Statement[K]) Execute(ctx context.Context, tCtx K) (any, bool, error) { return result, condition, nil } -func NewParser[K any](functions map[string]interface{}, pathParser PathExpressionParser[K], enumParser EnumParser, telemetrySettings component.TelemetrySettings) Parser[K] { - return Parser[K]{ - functions: functions, - pathParser: pathParser, - enumParser: enumParser, - telemetrySettings: telemetrySettings, +func NewParser[K any]( + functions map[string]interface{}, + pathParser PathExpressionParser[K], + settings component.TelemetrySettings, + options ...Option[K], +) Parser[K] { + p := Parser[K]{ + functions: functions, + pathParser: pathParser, + enumParser: func(*EnumSymbol) (*Enum, error) { + return nil, fmt.Errorf("enums aren't supported for the current context: %T", new(K)) + }, + telemetrySettings: settings, + } + for _, opt := range options { + opt(&p) + } + return p +} + +type Option[K any] func(*Parser[K]) + +func WithEnumParser[K any](parser EnumParser) Option[K] { + return func(p *Parser[K]) { + p.enumParser = parser } }