From 99aee3b37327f2f3150de9e493d7697626c29f6d Mon Sep 17 00:00:00 2001
From: Tyler Helmuth <12352919+TylerHelmuth@users.noreply.github.com>
Date: Wed, 1 Feb 2023 15:44:39 -0700
Subject: [PATCH 01/11] experiment with ottl.Statements

---
 internal/filter/expr/matcher.go               |  5 ++
 pkg/ottl/parser.go                            | 73 ++++++++++++-------
 pkg/ottl/parser_test.go                       |  2 +-
 .../filterprocessor/internal/common/parser.go | 37 +++-------
 processor/routingprocessor/router.go          |  9 +--
 .../internal/common/logs.go                   | 18 ++---
 .../internal/common/metrics.go                | 44 +++++------
 .../internal/common/processor.go              | 66 ++++++++---------
 .../internal/common/traces.go                 | 34 ++++-----
 9 files changed, 139 insertions(+), 149 deletions(-)

diff --git a/internal/filter/expr/matcher.go b/internal/filter/expr/matcher.go
index 560f3542e4a6..531f6a0d9791 100644
--- a/internal/filter/expr/matcher.go
+++ b/internal/filter/expr/matcher.go
@@ -16,6 +16,7 @@ package expr // import "github.com/open-telemetry/opentelemetry-collector-contri
 
 import (
 	"context"
+	"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl"
 )
 
 // BoolExpr is an interface that allows matching a context K against a configuration of a match.
@@ -23,6 +24,10 @@ type BoolExpr[K any] interface {
 	Eval(ctx context.Context, tCtx K) (bool, error)
 }
 
+type matcher[K any] struct {
+	ottl.BoolExpr[K]
+}
+
 type notMatcher[K any] struct {
 	matcher BoolExpr[K]
 }
diff --git a/pkg/ottl/parser.go b/pkg/ottl/parser.go
index 2dcefb199126..86e93ace1254 100644
--- a/pkg/ottl/parser.go
+++ b/pkg/ottl/parser.go
@@ -20,7 +20,6 @@ import (
 
 	"github.com/alecthomas/participle/v2"
 	"go.opentelemetry.io/collector/component"
-	"go.uber.org/multierr"
 	"go.uber.org/zap"
 )
 
@@ -92,36 +91,39 @@ func WithEnumParser[K any](parser EnumParser) Option[K] {
 	}
 }
 
-func (p *Parser[K]) ParseStatements(statements []string) ([]*Statement[K], error) {
+func (p *Parser[K]) ParseStatements(statements []string, errorMode ErrorMode) (Statements[K], error) {
 	var parsedStatements []*Statement[K]
-	var errors error
-
 	for _, statement := range statements {
-		parsed, err := parseStatement(statement)
-		if err != nil {
-			errors = multierr.Append(errors, err)
-			continue
-		}
-		function, err := p.newFunctionCall(parsed.Invocation)
+		parsedStatement, err := p.ParseStatement(statement)
 		if err != nil {
-			errors = multierr.Append(errors, err)
-			continue
+			return Statements[K]{}, err
 		}
-		expression, err := p.newBoolExpr(parsed.WhereClause)
-		if err != nil {
-			errors = multierr.Append(errors, err)
-			continue
-		}
-		parsedStatements = append(parsedStatements, &Statement[K]{
-			function:  function,
-			condition: expression,
-		})
+		parsedStatements = append(parsedStatements, parsedStatement)
 	}
+	return Statements[K]{
+		statements:        parsedStatements,
+		errorMode:         errorMode,
+		telemetrySettings: p.telemetrySettings,
+	}, nil
+}
 
-	if errors != nil {
-		return nil, errors
+func (p *Parser[K]) ParseStatement(statement string) (*Statement[K], error) {
+	parsed, err := parseStatement(statement)
+	if err != nil {
+		return nil, err
+	}
+	function, err := p.newFunctionCall(parsed.Invocation)
+	if err != nil {
+		return nil, err
 	}
-	return parsedStatements, nil
+	expression, err := p.newBoolExpr(parsed.WhereClause)
+	if err != nil {
+		return nil, err
+	}
+	return &Statement[K]{
+		function:  function,
+		condition: expression,
+	}, nil
 }
 
 var parser = newParser[parsedStatement]()
@@ -158,13 +160,13 @@ func newParser[G any]() *participle.Parser[G] {
 
 // Statements represents a list of statements that will be executed sequentially for a TransformContext.
 type Statements[K any] struct {
-	statements        []Statement[K]
+	statements        []*Statement[K]
 	errorMode         ErrorMode
 	telemetrySettings component.TelemetrySettings
 }
 
 // Execute is a function that will execute all the statements in the Statements list.
-func (s *Statements[K]) Execute(ctx context.Context, tCtx K) error {
+func (s Statements[K]) Execute(ctx context.Context, tCtx K) error {
 	for _, statement := range s.statements {
 		_, _, err := statement.Execute(ctx, tCtx)
 		if err != nil {
@@ -177,3 +179,22 @@ func (s *Statements[K]) Execute(ctx context.Context, tCtx K) error {
 	}
 	return nil
 }
+
+// Eval returns true if any of the statements' conditions pass and false otherwise
+func (s Statements[K]) Eval(ctx context.Context, tCtx K) (bool, error) {
+	for _, statement := range s.statements {
+		ret, err := statement.condition.Eval(ctx, tCtx)
+		if err != nil {
+			if s.errorMode == PropagateError {
+				err = fmt.Errorf("failed to evaluate condition: %w", err)
+				return false, err
+			}
+			s.telemetrySettings.Logger.Error("failed to evaluate condition", zap.Error(err))
+		} else {
+			if ret {
+				return true, nil
+			}
+		}
+	}
+	return false, nil
+}
diff --git a/pkg/ottl/parser_test.go b/pkg/ottl/parser_test.go
index 406c1f759e47..6a325fca0a4a 100644
--- a/pkg/ottl/parser_test.go
+++ b/pkg/ottl/parser_test.go
@@ -1363,7 +1363,7 @@ func Test_Execute_Error(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			statements := Statements[interface{}]{
-				statements: []Statement[interface{}]{
+				statements: []*Statement[interface{}]{
 					{
 						condition: BoolExpr[any]{tt.condition},
 						function:  Expr[any]{exprFunc: tt.function},
diff --git a/processor/filterprocessor/internal/common/parser.go b/processor/filterprocessor/internal/common/parser.go
index 2a77f472473d..c71b8eb80479 100644
--- a/processor/filterprocessor/internal/common/parser.go
+++ b/processor/filterprocessor/internal/common/parser.go
@@ -32,51 +32,51 @@ import (
 func ParseSpan(conditions []string, set component.TelemetrySettings) (expr.BoolExpr[ottlspan.TransformContext], error) {
 	statmentsStr := conditionsToStatements(conditions)
 	parser := ottlspan.NewParser(functions[ottlspan.TransformContext](), set)
-	statements, err := parser.ParseStatements(statmentsStr)
+	statements, err := parser.ParseStatements(statmentsStr, ottl.PropagateError)
 	if err != nil {
 		return nil, err
 	}
-	return statementsToExpr(statements), nil
+	return statements, nil
 }
 
 func ParseSpanEvent(conditions []string, set component.TelemetrySettings) (expr.BoolExpr[ottlspanevent.TransformContext], error) {
 	statmentsStr := conditionsToStatements(conditions)
 	parser := ottlspanevent.NewParser(functions[ottlspanevent.TransformContext](), set)
-	statements, err := parser.ParseStatements(statmentsStr)
+	statements, err := parser.ParseStatements(statmentsStr, ottl.PropagateError)
 	if err != nil {
 		return nil, err
 	}
-	return statementsToExpr(statements), nil
+	return statements, nil
 }
 
 func ParseLog(conditions []string, set component.TelemetrySettings) (expr.BoolExpr[ottllog.TransformContext], error) {
 	statmentsStr := conditionsToStatements(conditions)
 	parser := ottllog.NewParser(functions[ottllog.TransformContext](), set)
-	statements, err := parser.ParseStatements(statmentsStr)
+	statements, err := parser.ParseStatements(statmentsStr, ottl.PropagateError)
 	if err != nil {
 		return nil, err
 	}
-	return statementsToExpr(statements), nil
+	return statements, nil
 }
 
 func ParseMetric(conditions []string, set component.TelemetrySettings) (expr.BoolExpr[ottlmetric.TransformContext], error) {
 	statmentsStr := conditionsToStatements(conditions)
 	parser := ottlmetric.NewParser(functions[ottlmetric.TransformContext](), set)
-	statements, err := parser.ParseStatements(statmentsStr)
+	statements, err := parser.ParseStatements(statmentsStr, ottl.PropagateError)
 	if err != nil {
 		return nil, err
 	}
-	return statementsToExpr(statements), nil
+	return statements, nil
 }
 
 func ParseDataPoint(conditions []string, set component.TelemetrySettings) (expr.BoolExpr[ottldatapoint.TransformContext], error) {
 	statmentsStr := conditionsToStatements(conditions)
 	parser := ottldatapoint.NewParser(functions[ottldatapoint.TransformContext](), set)
-	statements, err := parser.ParseStatements(statmentsStr)
+	statements, err := parser.ParseStatements(statmentsStr, ottl.PropagateError)
 	if err != nil {
 		return nil, err
 	}
-	return statementsToExpr(statements), nil
+	return statements, nil
 }
 
 func conditionsToStatements(conditions []string) []string {
@@ -87,23 +87,6 @@ func conditionsToStatements(conditions []string) []string {
 	return statements
 }
 
-type statementExpr[K any] struct {
-	statement *ottl.Statement[K]
-}
-
-func (se statementExpr[K]) Eval(ctx context.Context, tCtx K) (bool, error) {
-	_, ret, err := se.statement.Execute(ctx, tCtx)
-	return ret, err
-}
-
-func statementsToExpr[K any](statements []*ottl.Statement[K]) expr.BoolExpr[K] {
-	var rets []expr.BoolExpr[K]
-	for _, statement := range statements {
-		rets = append(rets, statementExpr[K]{statement: statement})
-	}
-	return expr.Or(rets...)
-}
-
 func functions[K any]() map[string]interface{} {
 	return map[string]interface{}{
 		"TraceID":     ottlfuncs.TraceID[K],
diff --git a/processor/routingprocessor/router.go b/processor/routingprocessor/router.go
index 46f5a3a3654a..d5d6544d430d 100644
--- a/processor/routingprocessor/router.go
+++ b/processor/routingprocessor/router.go
@@ -132,14 +132,11 @@ func (r *router[E, K]) registerRouteExporters(available map[component.ID]compone
 func (r *router[E, K]) getStatementFrom(item RoutingTableItem) (*ottl.Statement[K], error) {
 	var statement *ottl.Statement[K]
 	if item.Statement != "" {
-		statements, err := r.parser.ParseStatements([]string{item.Statement})
+		var err error
+		statement, err = r.parser.ParseStatement(item.Statement)
 		if err != nil {
-			return statement, err
+			return nil, err
 		}
-		if len(statements) != 1 {
-			return statement, errors.New("more than one statement specified")
-		}
-		statement = statements[0]
 	}
 	return statement, nil
 }
diff --git a/processor/transformprocessor/internal/common/logs.go b/processor/transformprocessor/internal/common/logs.go
index 8267b2dcbe4d..0085155be122 100644
--- a/processor/transformprocessor/internal/common/logs.go
+++ b/processor/transformprocessor/internal/common/logs.go
@@ -29,7 +29,9 @@ import (
 
 var _ consumer.Logs = &logStatements{}
 
-type logStatements []*ottl.Statement[ottllog.TransformContext]
+type logStatements struct {
+	ottl.Statements[ottllog.TransformContext]
+}
 
 func (l logStatements) Capabilities() consumer.Capabilities {
 	return consumer.Capabilities{
@@ -45,11 +47,9 @@ func (l logStatements) ConsumeLogs(ctx context.Context, ld plog.Logs) error {
 			logs := slogs.LogRecords()
 			for k := 0; k < logs.Len(); k++ {
 				tCtx := ottllog.NewTransformContext(logs.At(k), slogs.Scope(), rlogs.Resource())
-				for _, statement := range l {
-					_, _, err := statement.Execute(ctx, tCtx)
-					if err != nil {
-						return err
-					}
+				err := l.Execute(ctx, tCtx)
+				if err != nil {
+					return err
 				}
 			}
 		}
@@ -93,13 +93,13 @@ func NewLogParserCollection(settings component.TelemetrySettings, options ...Log
 func (pc LogParserCollection) ParseContextStatements(contextStatements ContextStatements) (consumer.Logs, error) {
 	switch contextStatements.Context {
 	case Log:
-		lStatements, err := pc.logParser.ParseStatements(contextStatements.Statements)
+		lStatements, err := pc.logParser.ParseStatements(contextStatements.Statements, ottl.PropagateError)
 		if err != nil {
 			return nil, err
 		}
-		return logStatements(lStatements), nil
+		return logStatements{lStatements}, nil
 	default:
-		statements, err := pc.parseCommonContextStatements(contextStatements)
+		statements, err := pc.parseCommonContextStatements(contextStatements, ottl.PropagateError)
 		if err != nil {
 			return nil, err
 		}
diff --git a/processor/transformprocessor/internal/common/metrics.go b/processor/transformprocessor/internal/common/metrics.go
index 097818dffb51..91a1fcc12ff3 100644
--- a/processor/transformprocessor/internal/common/metrics.go
+++ b/processor/transformprocessor/internal/common/metrics.go
@@ -31,7 +31,9 @@ import (
 
 var _ consumer.Metrics = &metricStatements{}
 
-type metricStatements []*ottl.Statement[ottlmetric.TransformContext]
+type metricStatements struct {
+	ottl.Statements[ottlmetric.TransformContext]
+}
 
 func (m metricStatements) Capabilities() consumer.Capabilities {
 	return consumer.Capabilities{
@@ -47,11 +49,9 @@ func (m metricStatements) ConsumeMetrics(ctx context.Context, md pmetric.Metrics
 			metrics := smetrics.Metrics()
 			for k := 0; k < metrics.Len(); k++ {
 				tCtx := ottlmetric.NewTransformContext(metrics.At(k), smetrics.Scope(), rmetrics.Resource())
-				for _, statement := range m {
-					_, _, err := statement.Execute(ctx, tCtx)
-					if err != nil {
-						return err
-					}
+				err := m.Execute(ctx, tCtx)
+				if err != nil {
+					return err
 				}
 			}
 		}
@@ -61,7 +61,9 @@ func (m metricStatements) ConsumeMetrics(ctx context.Context, md pmetric.Metrics
 
 var _ consumer.Metrics = &dataPointStatements{}
 
-type dataPointStatements []*ottl.Statement[ottldatapoint.TransformContext]
+type dataPointStatements struct {
+	ottl.Statements[ottldatapoint.TransformContext]
+}
 
 func (d dataPointStatements) Capabilities() consumer.Capabilities {
 	return consumer.Capabilities{
@@ -102,7 +104,7 @@ func (d dataPointStatements) ConsumeMetrics(ctx context.Context, md pmetric.Metr
 func (d dataPointStatements) handleNumberDataPoints(ctx context.Context, dps pmetric.NumberDataPointSlice, metric pmetric.Metric, metrics pmetric.MetricSlice, is pcommon.InstrumentationScope, resource pcommon.Resource) error {
 	for i := 0; i < dps.Len(); i++ {
 		tCtx := ottldatapoint.NewTransformContext(dps.At(i), metric, metrics, is, resource)
-		err := d.callFunctions(ctx, tCtx)
+		err := d.Execute(ctx, tCtx)
 		if err != nil {
 			return err
 		}
@@ -113,7 +115,7 @@ func (d dataPointStatements) handleNumberDataPoints(ctx context.Context, dps pme
 func (d dataPointStatements) handleHistogramDataPoints(ctx context.Context, dps pmetric.HistogramDataPointSlice, metric pmetric.Metric, metrics pmetric.MetricSlice, is pcommon.InstrumentationScope, resource pcommon.Resource) error {
 	for i := 0; i < dps.Len(); i++ {
 		tCtx := ottldatapoint.NewTransformContext(dps.At(i), metric, metrics, is, resource)
-		err := d.callFunctions(ctx, tCtx)
+		err := d.Execute(ctx, tCtx)
 		if err != nil {
 			return err
 		}
@@ -124,7 +126,7 @@ func (d dataPointStatements) handleHistogramDataPoints(ctx context.Context, dps
 func (d dataPointStatements) handleExponetialHistogramDataPoints(ctx context.Context, dps pmetric.ExponentialHistogramDataPointSlice, metric pmetric.Metric, metrics pmetric.MetricSlice, is pcommon.InstrumentationScope, resource pcommon.Resource) error {
 	for i := 0; i < dps.Len(); i++ {
 		tCtx := ottldatapoint.NewTransformContext(dps.At(i), metric, metrics, is, resource)
-		err := d.callFunctions(ctx, tCtx)
+		err := d.Execute(ctx, tCtx)
 		if err != nil {
 			return err
 		}
@@ -135,17 +137,7 @@ func (d dataPointStatements) handleExponetialHistogramDataPoints(ctx context.Con
 func (d dataPointStatements) handleSummaryDataPoints(ctx context.Context, dps pmetric.SummaryDataPointSlice, metric pmetric.Metric, metrics pmetric.MetricSlice, is pcommon.InstrumentationScope, resource pcommon.Resource) error {
 	for i := 0; i < dps.Len(); i++ {
 		tCtx := ottldatapoint.NewTransformContext(dps.At(i), metric, metrics, is, resource)
-		err := d.callFunctions(ctx, tCtx)
-		if err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-func (d dataPointStatements) callFunctions(ctx context.Context, tCtx ottldatapoint.TransformContext) error {
-	for _, statement := range d {
-		_, _, err := statement.Execute(ctx, tCtx)
+		err := d.Execute(ctx, tCtx)
 		if err != nil {
 			return err
 		}
@@ -197,19 +189,19 @@ func NewMetricParserCollection(settings component.TelemetrySettings, options ...
 func (pc MetricParserCollection) ParseContextStatements(contextStatements ContextStatements) (consumer.Metrics, error) {
 	switch contextStatements.Context {
 	case Metric:
-		mStatements, err := pc.metricParser.ParseStatements(contextStatements.Statements)
+		mStatements, err := pc.metricParser.ParseStatements(contextStatements.Statements, ottl.PropagateError)
 		if err != nil {
 			return nil, err
 		}
-		return metricStatements(mStatements), nil
+		return metricStatements{mStatements}, nil
 	case DataPoint:
-		dpStatements, err := pc.dataPointParser.ParseStatements(contextStatements.Statements)
+		dpStatements, err := pc.dataPointParser.ParseStatements(contextStatements.Statements, ottl.PropagateError)
 		if err != nil {
 			return nil, err
 		}
-		return dataPointStatements(dpStatements), nil
+		return dataPointStatements{dpStatements}, nil
 	default:
-		statements, err := pc.parseCommonContextStatements(contextStatements)
+		statements, err := pc.parseCommonContextStatements(contextStatements, ottl.PropagateError)
 		if err != nil {
 			return nil, err
 		}
diff --git a/processor/transformprocessor/internal/common/processor.go b/processor/transformprocessor/internal/common/processor.go
index 9d49fb45ddb4..d600a89bf16a 100644
--- a/processor/transformprocessor/internal/common/processor.go
+++ b/processor/transformprocessor/internal/common/processor.go
@@ -34,7 +34,9 @@ var _ consumer.Metrics = &resourceStatements{}
 var _ consumer.Logs = &resourceStatements{}
 var _ baseContext = &resourceStatements{}
 
-type resourceStatements []*ottl.Statement[ottlresource.TransformContext]
+type resourceStatements struct {
+	ottl.Statements[ottlresource.TransformContext]
+}
 
 func (r resourceStatements) Capabilities() consumer.Capabilities {
 	return consumer.Capabilities{
@@ -46,11 +48,9 @@ func (r resourceStatements) ConsumeTraces(ctx context.Context, td ptrace.Traces)
 	for i := 0; i < td.ResourceSpans().Len(); i++ {
 		rspans := td.ResourceSpans().At(i)
 		tCtx := ottlresource.NewTransformContext(rspans.Resource())
-		for _, statement := range r {
-			_, _, err := statement.Execute(ctx, tCtx)
-			if err != nil {
-				return err
-			}
+		err := r.Execute(ctx, tCtx)
+		if err != nil {
+			return err
 		}
 	}
 	return nil
@@ -60,11 +60,9 @@ func (r resourceStatements) ConsumeMetrics(ctx context.Context, md pmetric.Metri
 	for i := 0; i < md.ResourceMetrics().Len(); i++ {
 		rmetrics := md.ResourceMetrics().At(i)
 		tCtx := ottlresource.NewTransformContext(rmetrics.Resource())
-		for _, statement := range r {
-			_, _, err := statement.Execute(ctx, tCtx)
-			if err != nil {
-				return err
-			}
+		err := r.Execute(ctx, tCtx)
+		if err != nil {
+			return err
 		}
 	}
 	return nil
@@ -74,11 +72,9 @@ func (r resourceStatements) ConsumeLogs(ctx context.Context, ld plog.Logs) error
 	for i := 0; i < ld.ResourceLogs().Len(); i++ {
 		rlogs := ld.ResourceLogs().At(i)
 		tCtx := ottlresource.NewTransformContext(rlogs.Resource())
-		for _, statement := range r {
-			_, _, err := statement.Execute(ctx, tCtx)
-			if err != nil {
-				return err
-			}
+		err := r.Execute(ctx, tCtx)
+		if err != nil {
+			return err
 		}
 	}
 	return nil
@@ -89,7 +85,9 @@ var _ consumer.Metrics = &scopeStatements{}
 var _ consumer.Logs = &scopeStatements{}
 var _ baseContext = &scopeStatements{}
 
-type scopeStatements []*ottl.Statement[ottlscope.TransformContext]
+type scopeStatements struct {
+	ottl.Statements[ottlscope.TransformContext]
+}
 
 func (s scopeStatements) Capabilities() consumer.Capabilities {
 	return consumer.Capabilities{
@@ -103,11 +101,9 @@ func (s scopeStatements) ConsumeTraces(ctx context.Context, td ptrace.Traces) er
 		for j := 0; j < rspans.ScopeSpans().Len(); j++ {
 			sspans := rspans.ScopeSpans().At(j)
 			tCtx := ottlscope.NewTransformContext(sspans.Scope(), rspans.Resource())
-			for _, statement := range s {
-				_, _, err := statement.Execute(ctx, tCtx)
-				if err != nil {
-					return err
-				}
+			err := s.Execute(ctx, tCtx)
+			if err != nil {
+				return err
 			}
 		}
 	}
@@ -120,11 +116,9 @@ func (s scopeStatements) ConsumeMetrics(ctx context.Context, md pmetric.Metrics)
 		for j := 0; j < rmetrics.ScopeMetrics().Len(); j++ {
 			smetrics := rmetrics.ScopeMetrics().At(j)
 			tCtx := ottlscope.NewTransformContext(smetrics.Scope(), rmetrics.Resource())
-			for _, statement := range s {
-				_, _, err := statement.Execute(ctx, tCtx)
-				if err != nil {
-					return err
-				}
+			err := s.Execute(ctx, tCtx)
+			if err != nil {
+				return err
 			}
 		}
 	}
@@ -137,11 +131,9 @@ func (s scopeStatements) ConsumeLogs(ctx context.Context, ld plog.Logs) error {
 		for j := 0; j < rlogs.ScopeLogs().Len(); j++ {
 			slogs := rlogs.ScopeLogs().At(j)
 			tCtx := ottlscope.NewTransformContext(slogs.Scope(), rlogs.Resource())
-			for _, statement := range s {
-				_, _, err := statement.Execute(ctx, tCtx)
-				if err != nil {
-					return err
-				}
+			err := s.Execute(ctx, tCtx)
+			if err != nil {
+				return err
 			}
 		}
 	}
@@ -160,20 +152,20 @@ type baseContext interface {
 	consumer.Logs
 }
 
-func (pc parserCollection) parseCommonContextStatements(contextStatement ContextStatements) (baseContext, error) {
+func (pc parserCollection) parseCommonContextStatements(contextStatement ContextStatements, errorMode ottl.ErrorMode) (baseContext, error) {
 	switch contextStatement.Context {
 	case Resource:
-		statements, err := pc.resourceParser.ParseStatements(contextStatement.Statements)
+		statements, err := pc.resourceParser.ParseStatements(contextStatement.Statements, errorMode)
 		if err != nil {
 			return nil, err
 		}
-		return resourceStatements(statements), nil
+		return resourceStatements{statements}, nil
 	case Scope:
-		statements, err := pc.scopeParser.ParseStatements(contextStatement.Statements)
+		statements, err := pc.scopeParser.ParseStatements(contextStatement.Statements, errorMode)
 		if err != nil {
 			return nil, err
 		}
-		return scopeStatements(statements), nil
+		return scopeStatements{statements}, nil
 	default:
 		return nil, fmt.Errorf("unknown context %v", contextStatement.Context)
 	}
diff --git a/processor/transformprocessor/internal/common/traces.go b/processor/transformprocessor/internal/common/traces.go
index 8377cc8a7efc..8eacc908ec21 100644
--- a/processor/transformprocessor/internal/common/traces.go
+++ b/processor/transformprocessor/internal/common/traces.go
@@ -30,7 +30,9 @@ import (
 
 var _ consumer.Traces = &traceStatements{}
 
-type traceStatements []*ottl.Statement[ottlspan.TransformContext]
+type traceStatements struct {
+	ottl.Statements[ottlspan.TransformContext]
+}
 
 func (t traceStatements) Capabilities() consumer.Capabilities {
 	return consumer.Capabilities{
@@ -46,11 +48,9 @@ func (t traceStatements) ConsumeTraces(ctx context.Context, td ptrace.Traces) er
 			spans := sspans.Spans()
 			for k := 0; k < spans.Len(); k++ {
 				tCtx := ottlspan.NewTransformContext(spans.At(k), sspans.Scope(), rspans.Resource())
-				for _, statement := range t {
-					_, _, err := statement.Execute(ctx, tCtx)
-					if err != nil {
-						return err
-					}
+				err := t.Execute(ctx, tCtx)
+				if err != nil {
+					return err
 				}
 			}
 		}
@@ -60,7 +60,9 @@ func (t traceStatements) ConsumeTraces(ctx context.Context, td ptrace.Traces) er
 
 var _ consumer.Traces = &spanEventStatements{}
 
-type spanEventStatements []*ottl.Statement[ottlspanevent.TransformContext]
+type spanEventStatements struct {
+	ottl.Statements[ottlspanevent.TransformContext]
+}
 
 func (s spanEventStatements) Capabilities() consumer.Capabilities {
 	return consumer.Capabilities{
@@ -79,11 +81,9 @@ func (s spanEventStatements) ConsumeTraces(ctx context.Context, td ptrace.Traces
 				spanEvents := span.Events()
 				for n := 0; n < spanEvents.Len(); n++ {
 					tCtx := ottlspanevent.NewTransformContext(spanEvents.At(n), span, sspans.Scope(), rspans.Resource())
-					for _, statement := range s {
-						_, _, err := statement.Execute(ctx, tCtx)
-						if err != nil {
-							return err
-						}
+					err := s.Execute(ctx, tCtx)
+					if err != nil {
+						return err
 					}
 				}
 			}
@@ -136,18 +136,18 @@ func NewTraceParserCollection(settings component.TelemetrySettings, options ...T
 func (pc TraceParserCollection) ParseContextStatements(contextStatements ContextStatements) (consumer.Traces, error) {
 	switch contextStatements.Context {
 	case Span:
-		tStatements, err := pc.spanParser.ParseStatements(contextStatements.Statements)
+		tStatements, err := pc.spanParser.ParseStatements(contextStatements.Statements, ottl.PropagateError)
 		if err != nil {
 			return nil, err
 		}
-		return traceStatements(tStatements), nil
+		return traceStatements{tStatements}, nil
 	case SpanEvent:
-		seStatements, err := pc.spanEventParser.ParseStatements(contextStatements.Statements)
+		seStatements, err := pc.spanEventParser.ParseStatements(contextStatements.Statements, ottl.PropagateError)
 		if err != nil {
 			return nil, err
 		}
-		return spanEventStatements(seStatements), nil
+		return spanEventStatements{seStatements}, nil
 	default:
-		return pc.parseCommonContextStatements(contextStatements)
+		return pc.parseCommonContextStatements(contextStatements, ottl.PropagateError)
 	}
 }

From a3f0874ecb6e8e7d9659f53eea78a395af4d821d Mon Sep 17 00:00:00 2001
From: Tyler Helmuth <12352919+TylerHelmuth@users.noreply.github.com>
Date: Fri, 3 Feb 2023 15:36:59 -0700
Subject: [PATCH 02/11] Keep experimenting

---
 pkg/ottl/contexts/ottllog/log.go              | 16 ++++++++++
 pkg/ottl/parser.go                            | 29 ++++++++++++++-----
 .../internal/common/logs.go                   |  3 +-
 3 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/pkg/ottl/contexts/ottllog/log.go b/pkg/ottl/contexts/ottllog/log.go
index 4987414d9d80..c166cb25af23 100644
--- a/pkg/ottl/contexts/ottllog/log.go
+++ b/pkg/ottl/contexts/ottllog/log.go
@@ -78,6 +78,22 @@ func NewParser(functions map[string]interface{}, telemetrySettings component.Tel
 	return p
 }
 
+type StatementsOption func(*ottl.Statements[TransformContext])
+
+func WithErrorMode(errorMode ottl.ErrorMode) StatementsOption {
+	return func(s *ottl.Statements[TransformContext]) {
+		ottl.WithErrorMode[TransformContext](errorMode)(s)
+	}
+}
+
+func NewStatements(statements []*ottl.Statement[TransformContext], telemetrySettings component.TelemetrySettings, options ...StatementsOption) ottl.Statements[TransformContext] {
+	s := ottl.NewStatements(statements, telemetrySettings)
+	for _, op := range options {
+		op(&s)
+	}
+	return s
+}
+
 var symbolTable = map[ottl.EnumSymbol]ottl.Enum{
 	"SEVERITY_NUMBER_UNSPECIFIED": ottl.Enum(plog.SeverityNumberUnspecified),
 	"SEVERITY_NUMBER_TRACE":       ottl.Enum(plog.SeverityNumberTrace),
diff --git a/pkg/ottl/parser.go b/pkg/ottl/parser.go
index 86e93ace1254..c0498d0bad78 100644
--- a/pkg/ottl/parser.go
+++ b/pkg/ottl/parser.go
@@ -91,20 +91,16 @@ func WithEnumParser[K any](parser EnumParser) Option[K] {
 	}
 }
 
-func (p *Parser[K]) ParseStatements(statements []string, errorMode ErrorMode) (Statements[K], error) {
+func (p *Parser[K]) ParseStatements(statements []string) ([]*Statement[K], error) {
 	var parsedStatements []*Statement[K]
 	for _, statement := range statements {
 		parsedStatement, err := p.ParseStatement(statement)
 		if err != nil {
-			return Statements[K]{}, err
+			return nil, err
 		}
 		parsedStatements = append(parsedStatements, parsedStatement)
 	}
-	return Statements[K]{
-		statements:        parsedStatements,
-		errorMode:         errorMode,
-		telemetrySettings: p.telemetrySettings,
-	}, nil
+	return parsedStatements, nil
 }
 
 func (p *Parser[K]) ParseStatement(statement string) (*Statement[K], error) {
@@ -165,6 +161,25 @@ type Statements[K any] struct {
 	telemetrySettings component.TelemetrySettings
 }
 
+type StatementsOption[K any] func(*Statements[K])
+
+func WithErrorMode[K any](errorMode ErrorMode) StatementsOption[K] {
+	return func(s *Statements[K]) {
+		s.errorMode = errorMode
+	}
+}
+
+func NewStatements[K any](statements []*Statement[K], telemetrySettings component.TelemetrySettings, options ...StatementsOption[K]) Statements[K] {
+	s := Statements[K]{
+		statements:        statements,
+		telemetrySettings: telemetrySettings,
+	}
+	for _, op := range options {
+		op(&s)
+	}
+	return s
+}
+
 // Execute is a function that will execute all the statements in the Statements list.
 func (s Statements[K]) Execute(ctx context.Context, tCtx K) error {
 	for _, statement := range s.statements {
diff --git a/processor/transformprocessor/internal/common/logs.go b/processor/transformprocessor/internal/common/logs.go
index 0085155be122..cd0302107416 100644
--- a/processor/transformprocessor/internal/common/logs.go
+++ b/processor/transformprocessor/internal/common/logs.go
@@ -93,10 +93,11 @@ func NewLogParserCollection(settings component.TelemetrySettings, options ...Log
 func (pc LogParserCollection) ParseContextStatements(contextStatements ContextStatements) (consumer.Logs, error) {
 	switch contextStatements.Context {
 	case Log:
-		lStatements, err := pc.logParser.ParseStatements(contextStatements.Statements, ottl.PropagateError)
+		parseStatements, err := pc.logParser.ParseStatements(contextStatements.Statements)
 		if err != nil {
 			return nil, err
 		}
+		lStatements := ottllog.NewStatements(parseStatements, pc.settings, ottllog.WithErrorMode(ottl.PropagateError))
 		return logStatements{lStatements}, nil
 	default:
 		statements, err := pc.parseCommonContextStatements(contextStatements, ottl.PropagateError)

From 50ca4e3d7aff966dffd31ef160c90fb70b3121d1 Mon Sep 17 00:00:00 2001
From: Tyler Helmuth <12352919+TylerHelmuth@users.noreply.github.com>
Date: Mon, 6 Feb 2023 11:41:08 -0800
Subject: [PATCH 03/11] Add NewStatements to all contexts

---
 pkg/ottl/contexts/ottldatapoint/datapoint.go  | 16 +++++++++++++
 pkg/ottl/contexts/ottlmetric/metrics.go       | 16 +++++++++++++
 pkg/ottl/contexts/ottlresource/resource.go    | 16 +++++++++++++
 pkg/ottl/contexts/ottlscope/scope.go          | 16 +++++++++++++
 pkg/ottl/contexts/ottlspan/span.go            | 16 +++++++++++++
 .../contexts/ottlspanevent/span_events.go     | 16 +++++++++++++
 pkg/ottl/parser.go                            | 23 ++-----------------
 .../internal/common/metrics.go                |  7 +++---
 .../internal/common/processor.go              | 11 +++++----
 .../internal/common/traces.go                 |  9 ++++----
 10 files changed, 113 insertions(+), 33 deletions(-)

diff --git a/pkg/ottl/contexts/ottldatapoint/datapoint.go b/pkg/ottl/contexts/ottldatapoint/datapoint.go
index 0c489fecc6d1..8a427c1b87e3 100644
--- a/pkg/ottl/contexts/ottldatapoint/datapoint.go
+++ b/pkg/ottl/contexts/ottldatapoint/datapoint.go
@@ -89,6 +89,22 @@ func NewParser(functions map[string]interface{}, telemetrySettings component.Tel
 	return p
 }
 
+type StatementsOption func(*ottl.Statements[TransformContext])
+
+func WithErrorMode(errorMode ottl.ErrorMode) StatementsOption {
+	return func(s *ottl.Statements[TransformContext]) {
+		ottl.WithErrorMode[TransformContext](errorMode)(s)
+	}
+}
+
+func NewStatements(statements []*ottl.Statement[TransformContext], telemetrySettings component.TelemetrySettings, options ...StatementsOption) ottl.Statements[TransformContext] {
+	s := ottl.NewStatements(statements, telemetrySettings)
+	for _, op := range options {
+		op(&s)
+	}
+	return s
+}
+
 var symbolTable = map[ottl.EnumSymbol]ottl.Enum{
 	"FLAG_NONE":              0,
 	"FLAG_NO_RECORDED_VALUE": 1,
diff --git a/pkg/ottl/contexts/ottlmetric/metrics.go b/pkg/ottl/contexts/ottlmetric/metrics.go
index 5eecbea6ae86..0ffb64c56c07 100644
--- a/pkg/ottl/contexts/ottlmetric/metrics.go
+++ b/pkg/ottl/contexts/ottlmetric/metrics.go
@@ -77,6 +77,22 @@ func NewParser(functions map[string]interface{}, telemetrySettings component.Tel
 	return p
 }
 
+type StatementsOption func(*ottl.Statements[TransformContext])
+
+func WithErrorMode(errorMode ottl.ErrorMode) StatementsOption {
+	return func(s *ottl.Statements[TransformContext]) {
+		ottl.WithErrorMode[TransformContext](errorMode)(s)
+	}
+}
+
+func NewStatements(statements []*ottl.Statement[TransformContext], telemetrySettings component.TelemetrySettings, options ...StatementsOption) ottl.Statements[TransformContext] {
+	s := ottl.NewStatements(statements, telemetrySettings)
+	for _, op := range options {
+		op(&s)
+	}
+	return s
+}
+
 var symbolTable = ottlcommon.MetricSymbolTable
 
 func parseEnum(val *ottl.EnumSymbol) (*ottl.Enum, error) {
diff --git a/pkg/ottl/contexts/ottlresource/resource.go b/pkg/ottl/contexts/ottlresource/resource.go
index 91f872f20574..8d89f12e0a55 100644
--- a/pkg/ottl/contexts/ottlresource/resource.go
+++ b/pkg/ottl/contexts/ottlresource/resource.go
@@ -62,6 +62,22 @@ func NewParser(functions map[string]interface{}, telemetrySettings component.Tel
 	return p
 }
 
+type StatementsOption func(*ottl.Statements[TransformContext])
+
+func WithErrorMode(errorMode ottl.ErrorMode) StatementsOption {
+	return func(s *ottl.Statements[TransformContext]) {
+		ottl.WithErrorMode[TransformContext](errorMode)(s)
+	}
+}
+
+func NewStatements(statements []*ottl.Statement[TransformContext], telemetrySettings component.TelemetrySettings, options ...StatementsOption) ottl.Statements[TransformContext] {
+	s := ottl.NewStatements(statements, telemetrySettings)
+	for _, op := range options {
+		op(&s)
+	}
+	return s
+}
+
 func parseEnum(_ *ottl.EnumSymbol) (*ottl.Enum, error) {
 	return nil, fmt.Errorf("resource context does not provide Enum support")
 }
diff --git a/pkg/ottl/contexts/ottlscope/scope.go b/pkg/ottl/contexts/ottlscope/scope.go
index 0bcb9c621192..82bea0cce928 100644
--- a/pkg/ottl/contexts/ottlscope/scope.go
+++ b/pkg/ottl/contexts/ottlscope/scope.go
@@ -69,6 +69,22 @@ func NewParser(functions map[string]interface{}, telemetrySettings component.Tel
 	return p
 }
 
+type StatementsOption func(*ottl.Statements[TransformContext])
+
+func WithErrorMode(errorMode ottl.ErrorMode) StatementsOption {
+	return func(s *ottl.Statements[TransformContext]) {
+		ottl.WithErrorMode[TransformContext](errorMode)(s)
+	}
+}
+
+func NewStatements(statements []*ottl.Statement[TransformContext], telemetrySettings component.TelemetrySettings, options ...StatementsOption) ottl.Statements[TransformContext] {
+	s := ottl.NewStatements(statements, telemetrySettings)
+	for _, op := range options {
+		op(&s)
+	}
+	return s
+}
+
 func parseEnum(val *ottl.EnumSymbol) (*ottl.Enum, error) {
 	return nil, fmt.Errorf("instrumentation scope context does not provide Enum support")
 }
diff --git a/pkg/ottl/contexts/ottlspan/span.go b/pkg/ottl/contexts/ottlspan/span.go
index 8a03f08222dd..b5e8a118f0f4 100644
--- a/pkg/ottl/contexts/ottlspan/span.go
+++ b/pkg/ottl/contexts/ottlspan/span.go
@@ -76,6 +76,22 @@ func NewParser(functions map[string]interface{}, telemetrySettings component.Tel
 	return p
 }
 
+type StatementsOption func(*ottl.Statements[TransformContext])
+
+func WithErrorMode(errorMode ottl.ErrorMode) StatementsOption {
+	return func(s *ottl.Statements[TransformContext]) {
+		ottl.WithErrorMode[TransformContext](errorMode)(s)
+	}
+}
+
+func NewStatements(statements []*ottl.Statement[TransformContext], telemetrySettings component.TelemetrySettings, options ...StatementsOption) ottl.Statements[TransformContext] {
+	s := ottl.NewStatements(statements, telemetrySettings)
+	for _, op := range options {
+		op(&s)
+	}
+	return s
+}
+
 func parseEnum(val *ottl.EnumSymbol) (*ottl.Enum, error) {
 	if val != nil {
 		if enum, ok := ottlcommon.SpanSymbolTable[*val]; ok {
diff --git a/pkg/ottl/contexts/ottlspanevent/span_events.go b/pkg/ottl/contexts/ottlspanevent/span_events.go
index 85363f117e87..d6277ab7ec34 100644
--- a/pkg/ottl/contexts/ottlspanevent/span_events.go
+++ b/pkg/ottl/contexts/ottlspanevent/span_events.go
@@ -84,6 +84,22 @@ func NewParser(functions map[string]interface{}, telemetrySettings component.Tel
 	return p
 }
 
+type StatementsOption func(*ottl.Statements[TransformContext])
+
+func WithErrorMode(errorMode ottl.ErrorMode) StatementsOption {
+	return func(s *ottl.Statements[TransformContext]) {
+		ottl.WithErrorMode[TransformContext](errorMode)(s)
+	}
+}
+
+func NewStatements(statements []*ottl.Statement[TransformContext], telemetrySettings component.TelemetrySettings, options ...StatementsOption) ottl.Statements[TransformContext] {
+	s := ottl.NewStatements(statements, telemetrySettings)
+	for _, op := range options {
+		op(&s)
+	}
+	return s
+}
+
 func parseEnum(val *ottl.EnumSymbol) (*ottl.Enum, error) {
 	if val != nil {
 		if enum, ok := ottlcommon.SpanSymbolTable[*val]; ok {
diff --git a/pkg/ottl/parser.go b/pkg/ottl/parser.go
index c0498d0bad78..3c4a7b3b6248 100644
--- a/pkg/ottl/parser.go
+++ b/pkg/ottl/parser.go
@@ -94,11 +94,11 @@ func WithEnumParser[K any](parser EnumParser) Option[K] {
 func (p *Parser[K]) ParseStatements(statements []string) ([]*Statement[K], error) {
 	var parsedStatements []*Statement[K]
 	for _, statement := range statements {
-		parsedStatement, err := p.ParseStatement(statement)
+		ps, err := p.ParseStatement(statement)
 		if err != nil {
 			return nil, err
 		}
-		parsedStatements = append(parsedStatements, parsedStatement)
+		parsedStatements = append(parsedStatements, ps)
 	}
 	return parsedStatements, nil
 }
@@ -194,22 +194,3 @@ func (s Statements[K]) Execute(ctx context.Context, tCtx K) error {
 	}
 	return nil
 }
-
-// Eval returns true if any of the statements' conditions pass and false otherwise
-func (s Statements[K]) Eval(ctx context.Context, tCtx K) (bool, error) {
-	for _, statement := range s.statements {
-		ret, err := statement.condition.Eval(ctx, tCtx)
-		if err != nil {
-			if s.errorMode == PropagateError {
-				err = fmt.Errorf("failed to evaluate condition: %w", err)
-				return false, err
-			}
-			s.telemetrySettings.Logger.Error("failed to evaluate condition", zap.Error(err))
-		} else {
-			if ret {
-				return true, nil
-			}
-		}
-	}
-	return false, nil
-}
diff --git a/processor/transformprocessor/internal/common/metrics.go b/processor/transformprocessor/internal/common/metrics.go
index 91a1fcc12ff3..5c629aae49ae 100644
--- a/processor/transformprocessor/internal/common/metrics.go
+++ b/processor/transformprocessor/internal/common/metrics.go
@@ -16,7 +16,6 @@ package common // import "github.com/open-telemetry/opentelemetry-collector-cont
 
 import (
 	"context"
-
 	"go.opentelemetry.io/collector/component"
 	"go.opentelemetry.io/collector/consumer"
 	"go.opentelemetry.io/collector/pdata/pcommon"
@@ -189,16 +188,18 @@ func NewMetricParserCollection(settings component.TelemetrySettings, options ...
 func (pc MetricParserCollection) ParseContextStatements(contextStatements ContextStatements) (consumer.Metrics, error) {
 	switch contextStatements.Context {
 	case Metric:
-		mStatements, err := pc.metricParser.ParseStatements(contextStatements.Statements, ottl.PropagateError)
+		parseStatements, err := pc.metricParser.ParseStatements(contextStatements.Statements)
 		if err != nil {
 			return nil, err
 		}
+		mStatements := ottlmetric.NewStatements(parseStatements, pc.settings, ottlmetric.WithErrorMode(ottl.PropagateError))
 		return metricStatements{mStatements}, nil
 	case DataPoint:
-		dpStatements, err := pc.dataPointParser.ParseStatements(contextStatements.Statements, ottl.PropagateError)
+		parseStatements, err := pc.dataPointParser.ParseStatements(contextStatements.Statements)
 		if err != nil {
 			return nil, err
 		}
+		dpStatements := ottldatapoint.NewStatements(parseStatements, pc.settings, ottldatapoint.WithErrorMode(ottl.PropagateError))
 		return dataPointStatements{dpStatements}, nil
 	default:
 		statements, err := pc.parseCommonContextStatements(contextStatements, ottl.PropagateError)
diff --git a/processor/transformprocessor/internal/common/processor.go b/processor/transformprocessor/internal/common/processor.go
index d600a89bf16a..4eb3c8a37bcf 100644
--- a/processor/transformprocessor/internal/common/processor.go
+++ b/processor/transformprocessor/internal/common/processor.go
@@ -17,7 +17,6 @@ package common // import "github.com/open-telemetry/opentelemetry-collector-cont
 import (
 	"context"
 	"fmt"
-
 	"go.opentelemetry.io/collector/component"
 	"go.opentelemetry.io/collector/consumer"
 	"go.opentelemetry.io/collector/pdata/plog"
@@ -155,17 +154,19 @@ type baseContext interface {
 func (pc parserCollection) parseCommonContextStatements(contextStatement ContextStatements, errorMode ottl.ErrorMode) (baseContext, error) {
 	switch contextStatement.Context {
 	case Resource:
-		statements, err := pc.resourceParser.ParseStatements(contextStatement.Statements, errorMode)
+		parseStatements, err := pc.resourceParser.ParseStatements(contextStatement.Statements)
 		if err != nil {
 			return nil, err
 		}
-		return resourceStatements{statements}, nil
+		rStatements := ottlresource.NewStatements(parseStatements, pc.settings, ottlresource.WithErrorMode(errorMode))
+		return resourceStatements{rStatements}, nil
 	case Scope:
-		statements, err := pc.scopeParser.ParseStatements(contextStatement.Statements, errorMode)
+		parseStatements, err := pc.scopeParser.ParseStatements(contextStatement.Statements)
 		if err != nil {
 			return nil, err
 		}
-		return scopeStatements{statements}, nil
+		sStatements := ottlscope.NewStatements(parseStatements, pc.settings, ottlscope.WithErrorMode(errorMode))
+		return scopeStatements{sStatements}, nil
 	default:
 		return nil, fmt.Errorf("unknown context %v", contextStatement.Context)
 	}
diff --git a/processor/transformprocessor/internal/common/traces.go b/processor/transformprocessor/internal/common/traces.go
index 8eacc908ec21..24583eff6c7a 100644
--- a/processor/transformprocessor/internal/common/traces.go
+++ b/processor/transformprocessor/internal/common/traces.go
@@ -16,7 +16,6 @@ package common // import "github.com/open-telemetry/opentelemetry-collector-cont
 
 import (
 	"context"
-
 	"go.opentelemetry.io/collector/component"
 	"go.opentelemetry.io/collector/consumer"
 	"go.opentelemetry.io/collector/pdata/ptrace"
@@ -136,16 +135,18 @@ func NewTraceParserCollection(settings component.TelemetrySettings, options ...T
 func (pc TraceParserCollection) ParseContextStatements(contextStatements ContextStatements) (consumer.Traces, error) {
 	switch contextStatements.Context {
 	case Span:
-		tStatements, err := pc.spanParser.ParseStatements(contextStatements.Statements, ottl.PropagateError)
+		parseStatements, err := pc.spanParser.ParseStatements(contextStatements.Statements)
 		if err != nil {
 			return nil, err
 		}
-		return traceStatements{tStatements}, nil
+		sStatements := ottlspan.NewStatements(parseStatements, pc.settings, ottlspan.WithErrorMode(ottl.PropagateError))
+		return traceStatements{sStatements}, nil
 	case SpanEvent:
-		seStatements, err := pc.spanEventParser.ParseStatements(contextStatements.Statements, ottl.PropagateError)
+		parseStatements, err := pc.spanEventParser.ParseStatements(contextStatements.Statements)
 		if err != nil {
 			return nil, err
 		}
+		seStatements := ottlspanevent.NewStatements(parseStatements, pc.settings, ottlspanevent.WithErrorMode(ottl.PropagateError))
 		return spanEventStatements{seStatements}, nil
 	default:
 		return pc.parseCommonContextStatements(contextStatements, ottl.PropagateError)

From c10373f9d114f0f62502de79fdfdbc5a4ea942f8 Mon Sep 17 00:00:00 2001
From: Tyler Helmuth <12352919+TylerHelmuth@users.noreply.github.com>
Date: Mon, 6 Feb 2023 11:41:21 -0800
Subject: [PATCH 04/11] Revert Eval function to add later

---
 internal/filter/expr/matcher.go               |  5 ---
 pkg/ottl/parser.go                            |  2 +-
 .../filterprocessor/internal/common/parser.go | 37 ++++++++++++++-----
 3 files changed, 28 insertions(+), 16 deletions(-)

diff --git a/internal/filter/expr/matcher.go b/internal/filter/expr/matcher.go
index 531f6a0d9791..560f3542e4a6 100644
--- a/internal/filter/expr/matcher.go
+++ b/internal/filter/expr/matcher.go
@@ -16,7 +16,6 @@ package expr // import "github.com/open-telemetry/opentelemetry-collector-contri
 
 import (
 	"context"
-	"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl"
 )
 
 // BoolExpr is an interface that allows matching a context K against a configuration of a match.
@@ -24,10 +23,6 @@ type BoolExpr[K any] interface {
 	Eval(ctx context.Context, tCtx K) (bool, error)
 }
 
-type matcher[K any] struct {
-	ottl.BoolExpr[K]
-}
-
 type notMatcher[K any] struct {
 	matcher BoolExpr[K]
 }
diff --git a/pkg/ottl/parser.go b/pkg/ottl/parser.go
index 3c4a7b3b6248..73779f9f637c 100644
--- a/pkg/ottl/parser.go
+++ b/pkg/ottl/parser.go
@@ -181,7 +181,7 @@ func NewStatements[K any](statements []*Statement[K], telemetrySettings componen
 }
 
 // Execute is a function that will execute all the statements in the Statements list.
-func (s Statements[K]) Execute(ctx context.Context, tCtx K) error {
+func (s *Statements[K]) Execute(ctx context.Context, tCtx K) error {
 	for _, statement := range s.statements {
 		_, _, err := statement.Execute(ctx, tCtx)
 		if err != nil {
diff --git a/processor/filterprocessor/internal/common/parser.go b/processor/filterprocessor/internal/common/parser.go
index c71b8eb80479..2a77f472473d 100644
--- a/processor/filterprocessor/internal/common/parser.go
+++ b/processor/filterprocessor/internal/common/parser.go
@@ -32,51 +32,51 @@ import (
 func ParseSpan(conditions []string, set component.TelemetrySettings) (expr.BoolExpr[ottlspan.TransformContext], error) {
 	statmentsStr := conditionsToStatements(conditions)
 	parser := ottlspan.NewParser(functions[ottlspan.TransformContext](), set)
-	statements, err := parser.ParseStatements(statmentsStr, ottl.PropagateError)
+	statements, err := parser.ParseStatements(statmentsStr)
 	if err != nil {
 		return nil, err
 	}
-	return statements, nil
+	return statementsToExpr(statements), nil
 }
 
 func ParseSpanEvent(conditions []string, set component.TelemetrySettings) (expr.BoolExpr[ottlspanevent.TransformContext], error) {
 	statmentsStr := conditionsToStatements(conditions)
 	parser := ottlspanevent.NewParser(functions[ottlspanevent.TransformContext](), set)
-	statements, err := parser.ParseStatements(statmentsStr, ottl.PropagateError)
+	statements, err := parser.ParseStatements(statmentsStr)
 	if err != nil {
 		return nil, err
 	}
-	return statements, nil
+	return statementsToExpr(statements), nil
 }
 
 func ParseLog(conditions []string, set component.TelemetrySettings) (expr.BoolExpr[ottllog.TransformContext], error) {
 	statmentsStr := conditionsToStatements(conditions)
 	parser := ottllog.NewParser(functions[ottllog.TransformContext](), set)
-	statements, err := parser.ParseStatements(statmentsStr, ottl.PropagateError)
+	statements, err := parser.ParseStatements(statmentsStr)
 	if err != nil {
 		return nil, err
 	}
-	return statements, nil
+	return statementsToExpr(statements), nil
 }
 
 func ParseMetric(conditions []string, set component.TelemetrySettings) (expr.BoolExpr[ottlmetric.TransformContext], error) {
 	statmentsStr := conditionsToStatements(conditions)
 	parser := ottlmetric.NewParser(functions[ottlmetric.TransformContext](), set)
-	statements, err := parser.ParseStatements(statmentsStr, ottl.PropagateError)
+	statements, err := parser.ParseStatements(statmentsStr)
 	if err != nil {
 		return nil, err
 	}
-	return statements, nil
+	return statementsToExpr(statements), nil
 }
 
 func ParseDataPoint(conditions []string, set component.TelemetrySettings) (expr.BoolExpr[ottldatapoint.TransformContext], error) {
 	statmentsStr := conditionsToStatements(conditions)
 	parser := ottldatapoint.NewParser(functions[ottldatapoint.TransformContext](), set)
-	statements, err := parser.ParseStatements(statmentsStr, ottl.PropagateError)
+	statements, err := parser.ParseStatements(statmentsStr)
 	if err != nil {
 		return nil, err
 	}
-	return statements, nil
+	return statementsToExpr(statements), nil
 }
 
 func conditionsToStatements(conditions []string) []string {
@@ -87,6 +87,23 @@ func conditionsToStatements(conditions []string) []string {
 	return statements
 }
 
+type statementExpr[K any] struct {
+	statement *ottl.Statement[K]
+}
+
+func (se statementExpr[K]) Eval(ctx context.Context, tCtx K) (bool, error) {
+	_, ret, err := se.statement.Execute(ctx, tCtx)
+	return ret, err
+}
+
+func statementsToExpr[K any](statements []*ottl.Statement[K]) expr.BoolExpr[K] {
+	var rets []expr.BoolExpr[K]
+	for _, statement := range statements {
+		rets = append(rets, statementExpr[K]{statement: statement})
+	}
+	return expr.Or(rets...)
+}
+
 func functions[K any]() map[string]interface{} {
 	return map[string]interface{}{
 		"TraceID":     ottlfuncs.TraceID[K],

From 5a53bb30a0008e3c30a460ca454d58006f4167c4 Mon Sep 17 00:00:00 2001
From: Tyler Helmuth <12352919+TylerHelmuth@users.noreply.github.com>
Date: Mon, 6 Feb 2023 11:55:54 -0800
Subject: [PATCH 05/11] Add changelog

---
 .chloggen/ottl-update-parsestatements.yaml | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
 create mode 100755 .chloggen/ottl-update-parsestatements.yaml

diff --git a/.chloggen/ottl-update-parsestatements.yaml b/.chloggen/ottl-update-parsestatements.yaml
new file mode 100755
index 000000000000..b29aa2a4268d
--- /dev/null
+++ b/.chloggen/ottl-update-parsestatements.yaml
@@ -0,0 +1,16 @@
+# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
+change_type: enhancement
+
+# 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: Add `NewStatements` func to enable creation of Statements structs.
+
+# One or more tracking issues related to the change
+issues: [18385]
+
+# (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:

From 817054534933af86f38257b4ffa9b781e0d4e04a Mon Sep 17 00:00:00 2001
From: Tyler Helmuth <12352919+TylerHelmuth@users.noreply.github.com>
Date: Mon, 6 Feb 2023 12:26:33 -0800
Subject: [PATCH 06/11] Fix lint

---
 processor/transformprocessor/internal/common/metrics.go   | 1 +
 processor/transformprocessor/internal/common/processor.go | 1 +
 processor/transformprocessor/internal/common/traces.go    | 1 +
 3 files changed, 3 insertions(+)

diff --git a/processor/transformprocessor/internal/common/metrics.go b/processor/transformprocessor/internal/common/metrics.go
index 5c629aae49ae..0235859b0e74 100644
--- a/processor/transformprocessor/internal/common/metrics.go
+++ b/processor/transformprocessor/internal/common/metrics.go
@@ -16,6 +16,7 @@ package common // import "github.com/open-telemetry/opentelemetry-collector-cont
 
 import (
 	"context"
+
 	"go.opentelemetry.io/collector/component"
 	"go.opentelemetry.io/collector/consumer"
 	"go.opentelemetry.io/collector/pdata/pcommon"
diff --git a/processor/transformprocessor/internal/common/processor.go b/processor/transformprocessor/internal/common/processor.go
index 4eb3c8a37bcf..c9f1802eb9da 100644
--- a/processor/transformprocessor/internal/common/processor.go
+++ b/processor/transformprocessor/internal/common/processor.go
@@ -17,6 +17,7 @@ package common // import "github.com/open-telemetry/opentelemetry-collector-cont
 import (
 	"context"
 	"fmt"
+
 	"go.opentelemetry.io/collector/component"
 	"go.opentelemetry.io/collector/consumer"
 	"go.opentelemetry.io/collector/pdata/plog"
diff --git a/processor/transformprocessor/internal/common/traces.go b/processor/transformprocessor/internal/common/traces.go
index 24583eff6c7a..de6cab1156c3 100644
--- a/processor/transformprocessor/internal/common/traces.go
+++ b/processor/transformprocessor/internal/common/traces.go
@@ -16,6 +16,7 @@ package common // import "github.com/open-telemetry/opentelemetry-collector-cont
 
 import (
 	"context"
+
 	"go.opentelemetry.io/collector/component"
 	"go.opentelemetry.io/collector/consumer"
 	"go.opentelemetry.io/collector/pdata/ptrace"

From 7b4567e46e14abd629e5dd9e657d92717535ecfc Mon Sep 17 00:00:00 2001
From: Tyler Helmuth <12352919+TylerHelmuth@users.noreply.github.com>
Date: Mon, 6 Feb 2023 14:07:15 -0800
Subject: [PATCH 07/11] run make gotidy

---
 pkg/ottl/go.mod | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pkg/ottl/go.mod b/pkg/ottl/go.mod
index ab483d7c9344..4f0ee3619d14 100644
--- a/pkg/ottl/go.mod
+++ b/pkg/ottl/go.mod
@@ -11,7 +11,6 @@ require (
 	go.opentelemetry.io/collector/component v0.70.1-0.20230130215412-26bd7b2bf678
 	go.opentelemetry.io/collector/pdata v1.0.0-rc4.0.20230130215412-26bd7b2bf678
 	go.opentelemetry.io/otel/trace v1.12.0
-	go.uber.org/multierr v1.9.0
 	go.uber.org/zap v1.24.0
 	golang.org/x/exp v0.0.0-20221205204356-47842c84f3db
 )
@@ -36,6 +35,7 @@ require (
 	go.opentelemetry.io/otel v1.12.0 // indirect
 	go.opentelemetry.io/otel/metric v0.35.0 // indirect
 	go.uber.org/atomic v1.10.0 // indirect
+	go.uber.org/multierr v1.9.0 // indirect
 	golang.org/x/net v0.5.0 // indirect
 	golang.org/x/sys v0.4.0 // indirect
 	golang.org/x/text v0.6.0 // indirect

From 911f0fa8dc15ef406f51441a4edce46ce80eec9f Mon Sep 17 00:00:00 2001
From: Tyler Helmuth <12352919+TylerHelmuth@users.noreply.github.com>
Date: Mon, 13 Feb 2023 12:20:54 -0700
Subject: [PATCH 08/11] Keep original logic

---
 processor/routingprocessor/router.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/processor/routingprocessor/router.go b/processor/routingprocessor/router.go
index d5d6544d430d..92462b17da05 100644
--- a/processor/routingprocessor/router.go
+++ b/processor/routingprocessor/router.go
@@ -135,7 +135,7 @@ func (r *router[E, K]) getStatementFrom(item RoutingTableItem) (*ottl.Statement[
 		var err error
 		statement, err = r.parser.ParseStatement(item.Statement)
 		if err != nil {
-			return nil, err
+			return statement, err
 		}
 	}
 	return statement, nil

From 56b65e500596a9c0eec781956032311656173c0a Mon Sep 17 00:00:00 2001
From: Tyler Helmuth <12352919+TylerHelmuth@users.noreply.github.com>
Date: Mon, 13 Feb 2023 12:21:49 -0700
Subject: [PATCH 09/11] Keep original logic

---
 processor/routingprocessor/router.go | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/processor/routingprocessor/router.go b/processor/routingprocessor/router.go
index 92462b17da05..4ee24e7ae09e 100644
--- a/processor/routingprocessor/router.go
+++ b/processor/routingprocessor/router.go
@@ -132,8 +132,7 @@ func (r *router[E, K]) registerRouteExporters(available map[component.ID]compone
 func (r *router[E, K]) getStatementFrom(item RoutingTableItem) (*ottl.Statement[K], error) {
 	var statement *ottl.Statement[K]
 	if item.Statement != "" {
-		var err error
-		statement, err = r.parser.ParseStatement(item.Statement)
+		statement, err := r.parser.ParseStatement(item.Statement)
 		if err != nil {
 			return statement, err
 		}

From c9ea8072e186c584305725f81fa7d501f1a68e13 Mon Sep 17 00:00:00 2001
From: Tyler Helmuth <12352919+TylerHelmuth@users.noreply.github.com>
Date: Mon, 13 Feb 2023 12:23:57 -0700
Subject: [PATCH 10/11] Revert "Keep original logic"

This reverts commit 56b65e500596a9c0eec781956032311656173c0a.
---
 processor/routingprocessor/router.go | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/processor/routingprocessor/router.go b/processor/routingprocessor/router.go
index 4ee24e7ae09e..92462b17da05 100644
--- a/processor/routingprocessor/router.go
+++ b/processor/routingprocessor/router.go
@@ -132,7 +132,8 @@ func (r *router[E, K]) registerRouteExporters(available map[component.ID]compone
 func (r *router[E, K]) getStatementFrom(item RoutingTableItem) (*ottl.Statement[K], error) {
 	var statement *ottl.Statement[K]
 	if item.Statement != "" {
-		statement, err := r.parser.ParseStatement(item.Statement)
+		var err error
+		statement, err = r.parser.ParseStatement(item.Statement)
 		if err != nil {
 			return statement, err
 		}

From 5cd18886bb19109bad9a9c79c4b93741161b9eef Mon Sep 17 00:00:00 2001
From: Tyler Helmuth <12352919+TylerHelmuth@users.noreply.github.com>
Date: Tue, 14 Feb 2023 09:48:38 -0700
Subject: [PATCH 11/11] Apply feedback

---
 processor/transformprocessor/internal/common/logs.go      | 4 ++--
 processor/transformprocessor/internal/common/metrics.go   | 4 ++--
 processor/transformprocessor/internal/common/processor.go | 8 ++++----
 processor/transformprocessor/internal/common/traces.go    | 8 ++++----
 4 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/processor/transformprocessor/internal/common/logs.go b/processor/transformprocessor/internal/common/logs.go
index cd0302107416..b8b16bf631b7 100644
--- a/processor/transformprocessor/internal/common/logs.go
+++ b/processor/transformprocessor/internal/common/logs.go
@@ -93,11 +93,11 @@ func NewLogParserCollection(settings component.TelemetrySettings, options ...Log
 func (pc LogParserCollection) ParseContextStatements(contextStatements ContextStatements) (consumer.Logs, error) {
 	switch contextStatements.Context {
 	case Log:
-		parseStatements, err := pc.logParser.ParseStatements(contextStatements.Statements)
+		parsedStatements, err := pc.logParser.ParseStatements(contextStatements.Statements)
 		if err != nil {
 			return nil, err
 		}
-		lStatements := ottllog.NewStatements(parseStatements, pc.settings, ottllog.WithErrorMode(ottl.PropagateError))
+		lStatements := ottllog.NewStatements(parsedStatements, pc.settings, ottllog.WithErrorMode(ottl.PropagateError))
 		return logStatements{lStatements}, nil
 	default:
 		statements, err := pc.parseCommonContextStatements(contextStatements, ottl.PropagateError)
diff --git a/processor/transformprocessor/internal/common/metrics.go b/processor/transformprocessor/internal/common/metrics.go
index 0235859b0e74..fd58391ed65e 100644
--- a/processor/transformprocessor/internal/common/metrics.go
+++ b/processor/transformprocessor/internal/common/metrics.go
@@ -196,11 +196,11 @@ func (pc MetricParserCollection) ParseContextStatements(contextStatements Contex
 		mStatements := ottlmetric.NewStatements(parseStatements, pc.settings, ottlmetric.WithErrorMode(ottl.PropagateError))
 		return metricStatements{mStatements}, nil
 	case DataPoint:
-		parseStatements, err := pc.dataPointParser.ParseStatements(contextStatements.Statements)
+		parsedStatements, err := pc.dataPointParser.ParseStatements(contextStatements.Statements)
 		if err != nil {
 			return nil, err
 		}
-		dpStatements := ottldatapoint.NewStatements(parseStatements, pc.settings, ottldatapoint.WithErrorMode(ottl.PropagateError))
+		dpStatements := ottldatapoint.NewStatements(parsedStatements, pc.settings, ottldatapoint.WithErrorMode(ottl.PropagateError))
 		return dataPointStatements{dpStatements}, nil
 	default:
 		statements, err := pc.parseCommonContextStatements(contextStatements, ottl.PropagateError)
diff --git a/processor/transformprocessor/internal/common/processor.go b/processor/transformprocessor/internal/common/processor.go
index c9f1802eb9da..73b0eeee6dab 100644
--- a/processor/transformprocessor/internal/common/processor.go
+++ b/processor/transformprocessor/internal/common/processor.go
@@ -155,18 +155,18 @@ type baseContext interface {
 func (pc parserCollection) parseCommonContextStatements(contextStatement ContextStatements, errorMode ottl.ErrorMode) (baseContext, error) {
 	switch contextStatement.Context {
 	case Resource:
-		parseStatements, err := pc.resourceParser.ParseStatements(contextStatement.Statements)
+		parsedStatements, err := pc.resourceParser.ParseStatements(contextStatement.Statements)
 		if err != nil {
 			return nil, err
 		}
-		rStatements := ottlresource.NewStatements(parseStatements, pc.settings, ottlresource.WithErrorMode(errorMode))
+		rStatements := ottlresource.NewStatements(parsedStatements, pc.settings, ottlresource.WithErrorMode(errorMode))
 		return resourceStatements{rStatements}, nil
 	case Scope:
-		parseStatements, err := pc.scopeParser.ParseStatements(contextStatement.Statements)
+		parsedStatements, err := pc.scopeParser.ParseStatements(contextStatement.Statements)
 		if err != nil {
 			return nil, err
 		}
-		sStatements := ottlscope.NewStatements(parseStatements, pc.settings, ottlscope.WithErrorMode(errorMode))
+		sStatements := ottlscope.NewStatements(parsedStatements, pc.settings, ottlscope.WithErrorMode(errorMode))
 		return scopeStatements{sStatements}, nil
 	default:
 		return nil, fmt.Errorf("unknown context %v", contextStatement.Context)
diff --git a/processor/transformprocessor/internal/common/traces.go b/processor/transformprocessor/internal/common/traces.go
index de6cab1156c3..4ff5dc2245bf 100644
--- a/processor/transformprocessor/internal/common/traces.go
+++ b/processor/transformprocessor/internal/common/traces.go
@@ -136,18 +136,18 @@ func NewTraceParserCollection(settings component.TelemetrySettings, options ...T
 func (pc TraceParserCollection) ParseContextStatements(contextStatements ContextStatements) (consumer.Traces, error) {
 	switch contextStatements.Context {
 	case Span:
-		parseStatements, err := pc.spanParser.ParseStatements(contextStatements.Statements)
+		parsedStatements, err := pc.spanParser.ParseStatements(contextStatements.Statements)
 		if err != nil {
 			return nil, err
 		}
-		sStatements := ottlspan.NewStatements(parseStatements, pc.settings, ottlspan.WithErrorMode(ottl.PropagateError))
+		sStatements := ottlspan.NewStatements(parsedStatements, pc.settings, ottlspan.WithErrorMode(ottl.PropagateError))
 		return traceStatements{sStatements}, nil
 	case SpanEvent:
-		parseStatements, err := pc.spanEventParser.ParseStatements(contextStatements.Statements)
+		parsedStatements, err := pc.spanEventParser.ParseStatements(contextStatements.Statements)
 		if err != nil {
 			return nil, err
 		}
-		seStatements := ottlspanevent.NewStatements(parseStatements, pc.settings, ottlspanevent.WithErrorMode(ottl.PropagateError))
+		seStatements := ottlspanevent.NewStatements(parsedStatements, pc.settings, ottlspanevent.WithErrorMode(ottl.PropagateError))
 		return spanEventStatements{seStatements}, nil
 	default:
 		return pc.parseCommonContextStatements(contextStatements, ottl.PropagateError)