diff --git a/internal/filter/filterottl/filter.go b/internal/filter/filterottl/filter.go index 0cecbb999049..6324c8a35bd9 100644 --- a/internal/filter/filterottl/filter.go +++ b/internal/filter/filterottl/filter.go @@ -28,7 +28,7 @@ func NewBoolExprForSpan(conditions []string, functions map[string]ottl.Factory[o if err != nil { return nil, err } - c := ottlspan.NewConditionSequence(statements, errorMode, set) + c := ottlspan.NewConditionSequence(statements, set, ottlspan.WithConditionSequenceErrorMode(errorMode)) return &c, nil } @@ -44,7 +44,7 @@ func NewBoolExprForSpanEvent(conditions []string, functions map[string]ottl.Fact if err != nil { return nil, err } - c := ottlspanevent.NewConditionSequence(statements, errorMode, set) + c := ottlspanevent.NewConditionSequence(statements, set, ottlspanevent.WithConditionSequenceErrorMode(errorMode)) return &c, nil } @@ -60,7 +60,7 @@ func NewBoolExprForMetric(conditions []string, functions map[string]ottl.Factory if err != nil { return nil, err } - c := ottlmetric.NewConditionSequence(statements, errorMode, set) + c := ottlmetric.NewConditionSequence(statements, set, ottlmetric.WithConditionSequenceErrorMode(errorMode)) return &c, nil } @@ -76,7 +76,7 @@ func NewBoolExprForDataPoint(conditions []string, functions map[string]ottl.Fact if err != nil { return nil, err } - c := ottldatapoint.NewConditionSequence(statements, errorMode, set) + c := ottldatapoint.NewConditionSequence(statements, set, ottldatapoint.WithConditionSequenceErrorMode(errorMode)) return &c, nil } @@ -92,7 +92,7 @@ func NewBoolExprForLog(conditions []string, functions map[string]ottl.Factory[ot if err != nil { return nil, err } - c := ottllog.NewConditionSequence(statements, errorMode, set) + c := ottllog.NewConditionSequence(statements, set, ottllog.WithConditionSequenceErrorMode(errorMode)) return &c, nil } @@ -108,6 +108,6 @@ func NewBoolExprForResource(conditions []string, functions map[string]ottl.Facto if err != nil { return nil, err } - c := ottlresource.NewConditionSequence(statements, errorMode, set) + c := ottlresource.NewConditionSequence(statements, set, ottlresource.WithConditionSequenceErrorMode(errorMode)) return &c, nil } diff --git a/pkg/ottl/contexts/ottldatapoint/datapoint.go b/pkg/ottl/contexts/ottldatapoint/datapoint.go index 87cd9b350eb5..6b95f27ea06d 100644 --- a/pkg/ottl/contexts/ottldatapoint/datapoint.go +++ b/pkg/ottl/contexts/ottldatapoint/datapoint.go @@ -98,8 +98,20 @@ func NewStatements(statements []*ottl.Statement[TransformContext], telemetrySett return s } -func NewConditionSequence(conditions []*ottl.Condition[TransformContext], errorMode ottl.ErrorMode, telemetrySettings component.TelemetrySettings, options ...ottl.ConditionSequenceOption[TransformContext]) ottl.ConditionSequence[TransformContext] { - return ottl.NewConditionSequence(conditions, errorMode, telemetrySettings, options...) +type ConditionSequenceOption func(*ottl.ConditionSequence[TransformContext]) + +func WithConditionSequenceErrorMode(errorMode ottl.ErrorMode) ConditionSequenceOption { + return func(c *ottl.ConditionSequence[TransformContext]) { + ottl.WithConditionSequenceErrorMode[TransformContext](errorMode)(c) + } +} + +func NewConditionSequence(conditions []*ottl.Condition[TransformContext], telemetrySettings component.TelemetrySettings, options ...ConditionSequenceOption) ottl.ConditionSequence[TransformContext] { + c := ottl.NewConditionSequence(conditions, telemetrySettings) + for _, op := range options { + op(&c) + } + return c } var symbolTable = map[ottl.EnumSymbol]ottl.Enum{ diff --git a/pkg/ottl/contexts/ottllog/log.go b/pkg/ottl/contexts/ottllog/log.go index 8b0dc3b98fcf..24e1a80e02d7 100644 --- a/pkg/ottl/contexts/ottllog/log.go +++ b/pkg/ottl/contexts/ottllog/log.go @@ -88,8 +88,20 @@ func NewStatements(statements []*ottl.Statement[TransformContext], telemetrySett return s } -func NewConditionSequence(conditions []*ottl.Condition[TransformContext], errorMode ottl.ErrorMode, telemetrySettings component.TelemetrySettings, options ...ottl.ConditionSequenceOption[TransformContext]) ottl.ConditionSequence[TransformContext] { - return ottl.NewConditionSequence(conditions, errorMode, telemetrySettings, options...) +type ConditionSequenceOption func(*ottl.ConditionSequence[TransformContext]) + +func WithConditionSequenceErrorMode(errorMode ottl.ErrorMode) ConditionSequenceOption { + return func(c *ottl.ConditionSequence[TransformContext]) { + ottl.WithConditionSequenceErrorMode[TransformContext](errorMode)(c) + } +} + +func NewConditionSequence(conditions []*ottl.Condition[TransformContext], telemetrySettings component.TelemetrySettings, options ...ConditionSequenceOption) ottl.ConditionSequence[TransformContext] { + c := ottl.NewConditionSequence(conditions, telemetrySettings) + for _, op := range options { + op(&c) + } + return c } var symbolTable = map[ottl.EnumSymbol]ottl.Enum{ diff --git a/pkg/ottl/contexts/ottlmetric/metrics.go b/pkg/ottl/contexts/ottlmetric/metrics.go index 257285f9e711..8b97f04be700 100644 --- a/pkg/ottl/contexts/ottlmetric/metrics.go +++ b/pkg/ottl/contexts/ottlmetric/metrics.go @@ -92,8 +92,20 @@ func NewStatements(statements []*ottl.Statement[TransformContext], telemetrySett return s } -func NewConditionSequence(conditions []*ottl.Condition[TransformContext], errorMode ottl.ErrorMode, telemetrySettings component.TelemetrySettings, options ...ottl.ConditionSequenceOption[TransformContext]) ottl.ConditionSequence[TransformContext] { - return ottl.NewConditionSequence(conditions, errorMode, telemetrySettings, options...) +type ConditionSequenceOption func(*ottl.ConditionSequence[TransformContext]) + +func WithConditionSequenceErrorMode(errorMode ottl.ErrorMode) ConditionSequenceOption { + return func(c *ottl.ConditionSequence[TransformContext]) { + ottl.WithConditionSequenceErrorMode[TransformContext](errorMode)(c) + } +} + +func NewConditionSequence(conditions []*ottl.Condition[TransformContext], telemetrySettings component.TelemetrySettings, options ...ConditionSequenceOption) ottl.ConditionSequence[TransformContext] { + c := ottl.NewConditionSequence(conditions, telemetrySettings) + for _, op := range options { + op(&c) + } + return c } var symbolTable = internal.MetricSymbolTable diff --git a/pkg/ottl/contexts/ottlresource/resource.go b/pkg/ottl/contexts/ottlresource/resource.go index 548752b38d02..a908d57085dc 100644 --- a/pkg/ottl/contexts/ottlresource/resource.go +++ b/pkg/ottl/contexts/ottlresource/resource.go @@ -71,8 +71,20 @@ func NewStatements(statements []*ottl.Statement[TransformContext], telemetrySett return s } -func NewConditionSequence(conditions []*ottl.Condition[TransformContext], errorMode ottl.ErrorMode, telemetrySettings component.TelemetrySettings, options ...ottl.ConditionSequenceOption[TransformContext]) ottl.ConditionSequence[TransformContext] { - return ottl.NewConditionSequence(conditions, errorMode, telemetrySettings, options...) +type ConditionSequenceOption func(*ottl.ConditionSequence[TransformContext]) + +func WithConditionSequenceErrorMode(errorMode ottl.ErrorMode) ConditionSequenceOption { + return func(c *ottl.ConditionSequence[TransformContext]) { + ottl.WithConditionSequenceErrorMode[TransformContext](errorMode)(c) + } +} + +func NewConditionSequence(conditions []*ottl.Condition[TransformContext], telemetrySettings component.TelemetrySettings, options ...ConditionSequenceOption) ottl.ConditionSequence[TransformContext] { + c := ottl.NewConditionSequence(conditions, telemetrySettings) + for _, op := range options { + op(&c) + } + return c } func parseEnum(_ *ottl.EnumSymbol) (*ottl.Enum, error) { diff --git a/pkg/ottl/contexts/ottlscope/scope.go b/pkg/ottl/contexts/ottlscope/scope.go index 508dca447ca8..67e88b8a175b 100644 --- a/pkg/ottl/contexts/ottlscope/scope.go +++ b/pkg/ottl/contexts/ottlscope/scope.go @@ -78,8 +78,20 @@ func NewStatements(statements []*ottl.Statement[TransformContext], telemetrySett return s } -func NewConditionSequence(conditions []*ottl.Condition[TransformContext], errorMode ottl.ErrorMode, telemetrySettings component.TelemetrySettings, options ...ottl.ConditionSequenceOption[TransformContext]) ottl.ConditionSequence[TransformContext] { - return ottl.NewConditionSequence(conditions, errorMode, telemetrySettings, options...) +type ConditionSequenceOption func(*ottl.ConditionSequence[TransformContext]) + +func WithConditionSequenceErrorMode(errorMode ottl.ErrorMode) ConditionSequenceOption { + return func(c *ottl.ConditionSequence[TransformContext]) { + ottl.WithConditionSequenceErrorMode[TransformContext](errorMode)(c) + } +} + +func NewConditionSequence(conditions []*ottl.Condition[TransformContext], telemetrySettings component.TelemetrySettings, options ...ConditionSequenceOption) ottl.ConditionSequence[TransformContext] { + c := ottl.NewConditionSequence(conditions, telemetrySettings) + for _, op := range options { + op(&c) + } + return c } func parseEnum(_ *ottl.EnumSymbol) (*ottl.Enum, error) { diff --git a/pkg/ottl/contexts/ottlspan/span.go b/pkg/ottl/contexts/ottlspan/span.go index 77442d238746..f1585b550e44 100644 --- a/pkg/ottl/contexts/ottlspan/span.go +++ b/pkg/ottl/contexts/ottlspan/span.go @@ -85,8 +85,20 @@ func NewStatements(statements []*ottl.Statement[TransformContext], telemetrySett return s } -func NewConditionSequence(conditions []*ottl.Condition[TransformContext], errorMode ottl.ErrorMode, telemetrySettings component.TelemetrySettings, options ...ottl.ConditionSequenceOption[TransformContext]) ottl.ConditionSequence[TransformContext] { - return ottl.NewConditionSequence(conditions, errorMode, telemetrySettings, options...) +type ConditionSequenceOption func(*ottl.ConditionSequence[TransformContext]) + +func WithConditionSequenceErrorMode(errorMode ottl.ErrorMode) ConditionSequenceOption { + return func(c *ottl.ConditionSequence[TransformContext]) { + ottl.WithConditionSequenceErrorMode[TransformContext](errorMode)(c) + } +} + +func NewConditionSequence(conditions []*ottl.Condition[TransformContext], telemetrySettings component.TelemetrySettings, options ...ConditionSequenceOption) ottl.ConditionSequence[TransformContext] { + c := ottl.NewConditionSequence(conditions, telemetrySettings) + for _, op := range options { + op(&c) + } + return c } 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 29be0a000137..00fcf82597d0 100644 --- a/pkg/ottl/contexts/ottlspanevent/span_events.go +++ b/pkg/ottl/contexts/ottlspanevent/span_events.go @@ -93,8 +93,20 @@ func NewStatements(statements []*ottl.Statement[TransformContext], telemetrySett return s } -func NewConditionSequence(conditions []*ottl.Condition[TransformContext], errorMode ottl.ErrorMode, telemetrySettings component.TelemetrySettings, options ...ottl.ConditionSequenceOption[TransformContext]) ottl.ConditionSequence[TransformContext] { - return ottl.NewConditionSequence(conditions, errorMode, telemetrySettings, options...) +type ConditionSequenceOption func(*ottl.ConditionSequence[TransformContext]) + +func WithConditionSequenceErrorMode(errorMode ottl.ErrorMode) ConditionSequenceOption { + return func(c *ottl.ConditionSequence[TransformContext]) { + ottl.WithConditionSequenceErrorMode[TransformContext](errorMode)(c) + } +} + +func NewConditionSequence(conditions []*ottl.Condition[TransformContext], telemetrySettings component.TelemetrySettings, options ...ConditionSequenceOption) ottl.ConditionSequence[TransformContext] { + c := ottl.NewConditionSequence(conditions, telemetrySettings) + for _, op := range options { + op(&c) + } + return c } func parseEnum(val *ottl.EnumSymbol) (*ottl.Enum, error) { diff --git a/pkg/ottl/parser.go b/pkg/ottl/parser.go index 7a9cc40a237e..e432d457a6ed 100644 --- a/pkg/ottl/parser.go +++ b/pkg/ottl/parser.go @@ -32,6 +32,7 @@ func (e *ErrorMode) UnmarshalText(text []byte) error { } } +// TODO: move this and ErrorMode to a config.go file type LogicOperation string const ( @@ -337,6 +338,13 @@ type ConditionSequence[K any] struct { type ConditionSequenceOption[K any] func(*ConditionSequence[K]) +// WithConditionSequenceErrorMode sets the ErrorMode of a ConditionSequence +func WithConditionSequenceErrorMode[K any](errorMode ErrorMode) ConditionSequenceOption[K] { + return func(c *ConditionSequence[K]) { + c.errorMode = errorMode + } +} + // WithLogicOperation sets the LogicOperation of a ConditionSequence // When setting AND the conditions will be ANDed together. // When setting OR the conditions will be ORed together. @@ -348,17 +356,17 @@ func WithLogicOperation[K any](logicOp LogicOperation) ConditionSequenceOption[K // NewConditionSequence creates a new ConditionSequence with the provided Condition slice, ErrorMode, and component.TelemetrySettings. // You may also augment the ConditionSequence with a slice of ConditionSequenceOption. -func NewConditionSequence[K any](conditions []*Condition[K], errorMode ErrorMode, telemetrySettings component.TelemetrySettings, options ...ConditionSequenceOption[K]) ConditionSequence[K] { - s := ConditionSequence[K]{ +func NewConditionSequence[K any](conditions []*Condition[K], telemetrySettings component.TelemetrySettings, options ...ConditionSequenceOption[K]) ConditionSequence[K] { + c := ConditionSequence[K]{ conditions: conditions, - errorMode: errorMode, + errorMode: IgnoreError, telemetrySettings: telemetrySettings, logicOp: Or, } for _, op := range options { - op(&s) + op(&c) } - return s + return c } // Eval evaluates the result of each Condition in the ConditionSequence. @@ -367,6 +375,7 @@ func NewConditionSequence[K any](conditions []*Condition[K], errorMode ErrorMode // If using the AND LogicOperation, if any Condition evaluates to false, then false is returned and if all Conditions evaluate to true, then true is returned. // When the ErrorMode of the ConditionSequence is `propagate`, errors cause the evaluation to be false and an error is returned. // When the ErrorMode of the ConditionSequence is `ignore`, errors cause the evaluation to continue to the next condition. +// When using the AND LogicOperation with the `ignore` ErrorMode the sequence will evaluate to false if all conditions error. func (c *ConditionSequence[K]) Eval(ctx context.Context, tCtx K) (bool, error) { var atLeastOneMatch bool for _, condition := range c.conditions { @@ -389,5 +398,10 @@ func (c *ConditionSequence[K]) Eval(ctx context.Context, tCtx K) (bool, error) { return false, nil } } + // When ANDing it is possible to arrive here not because everything was true, but because everything errored and was ignored. + // In that situation, we don't want to return True when no conditions actually passed. In a situation when everything failed + // we are essentially left with an empty set, which is normally evaluated in mathematics as False. We will use that + // idea to return False when ANDing and everything errored. We use atLeastOneMatch here to return true if anything did match. + // It is not possible to get here if any condition during an AND explicitly failed. return c.logicOp == And && atLeastOneMatch, nil }