Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .chloggen/ottl-silent-error-mode.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: 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 `silent` ErrorMode to allow disabling logging of errors that are ignored.

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [29710]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

# If your change doesn't affect end users or the exported elements of any package,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: []
2 changes: 1 addition & 1 deletion connector/routingconnector/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ The following settings are available:
- `table.statement (required)`: the routing condition provided as the [OTTL] statement.
- `table.pipelines (required)`: the list of pipelines to use when the routing condition is met.
- `default_pipelines (optional)`: contains the list of pipelines to use when a record does not meet any of specified conditions.
- `error_mode (optional)`: determines how errors returned from OTTL statements are handled. Valid values are `ignore` and `propagate`. If `ignored` is used and a statement's condition has an error then the payload will be routed to the default pipelines. If not supplied, `propagate` is used.
- `error_mode (optional)`: determines how errors returned from OTTL statements are handled. Valid values are `propagate`, `ignore` and `silent`. If `ignored` or `silent` is used and a statement's condition has an error then the payload will be routed to the default pipelines. When `silent` is used the error is not logged. If not supplied, `propagate` is used.

Example:

Expand Down
3 changes: 2 additions & 1 deletion pkg/ottl/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ type ErrorMode string
const (
IgnoreError ErrorMode = "ignore"
PropagateError ErrorMode = "propagate"
SilentError ErrorMode = "silent"
)

func (e *ErrorMode) UnmarshalText(text []byte) error {
str := ErrorMode(strings.ToLower(string(text)))
switch str {
case IgnoreError, PropagateError:
case IgnoreError, PropagateError, SilentError:
*e = str
return nil
default:
Expand Down
12 changes: 9 additions & 3 deletions pkg/ottl/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ func NewStatementSequence[K any](statements []*Statement[K], telemetrySettings c
// Execute is a function that will execute all the statements in the StatementSequence list.
// When the ErrorMode of the StatementSequence is `propagate`, errors cause the execution to halt and the error is returned.
// When the ErrorMode of the StatementSequence is `ignore`, errors are logged and execution continues to the next statement.
// When the ErrorMode of the StatementSequence is `silent`, errors are not logged and execution continues to the next statement.
func (s *StatementSequence[K]) Execute(ctx context.Context, tCtx K) error {
for _, statement := range s.statements {
_, _, err := statement.Execute(ctx, tCtx)
Expand All @@ -268,7 +269,9 @@ func (s *StatementSequence[K]) Execute(ctx context.Context, tCtx K) error {
err = fmt.Errorf("failed to execute statement: %v, %w", statement.origText, err)
return err
}
s.telemetrySettings.Logger.Warn("failed to execute statement", zap.Error(err), zap.String("statement", statement.origText))
if s.errorMode == IgnoreError {
s.telemetrySettings.Logger.Warn("failed to execute statement", zap.Error(err), zap.String("statement", statement.origText))
}
}
}
return nil
Expand Down Expand Up @@ -323,7 +326,8 @@ func NewConditionSequence[K any](conditions []*Condition[K], telemetrySettings c
// If using the default OR LogicOperation, if any Condition evaluates to true, then true is returned and if all Conditions evaluate to false, then false is returned.
// 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 the ErrorMode of the ConditionSequence is `ignore`, errors are logged and cause the evaluation to continue to the next condition.
// When the ErrorMode of the ConditionSequence is `silent`, errors are not logged and 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
Expand All @@ -334,7 +338,9 @@ func (c *ConditionSequence[K]) Eval(ctx context.Context, tCtx K) (bool, error) {
err = fmt.Errorf("failed to eval condition: %v, %w", condition.origText, err)
return false, err
}
c.telemetrySettings.Logger.Warn("failed to eval condition", zap.Error(err), zap.String("condition", condition.origText))
if c.errorMode == IgnoreError {
c.telemetrySettings.Logger.Warn("failed to eval condition", zap.Error(err), zap.String("condition", condition.origText))
}
continue
}
if match {
Expand Down
46 changes: 44 additions & 2 deletions pkg/ottl/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2091,6 +2091,26 @@ func Test_Statements_Execute_Error(t *testing.T) {
},
errorMode: PropagateError,
},
{
name: "SilentError error from condition",
condition: func(context.Context, any) (bool, error) {
return true, fmt.Errorf("test")
},
function: func(ctx context.Context, tCtx any) (any, error) {
return 1, nil
},
errorMode: SilentError,
},
{
name: "SilentError error from function",
condition: func(context.Context, any) (bool, error) {
return true, nil
},
function: func(ctx context.Context, tCtx any) (any, error) {
return 1, fmt.Errorf("test")
},
errorMode: SilentError,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down Expand Up @@ -2262,14 +2282,32 @@ func Test_ConditionSequence_Eval_Error(t *testing.T) {
errorMode ErrorMode
}{
{
name: "Propagate Error from function",
name: "Propagate Error from condition",
conditions: []boolExpressionEvaluator[any]{
func(context.Context, any) (bool, error) {
return true, fmt.Errorf("test")
},
},
errorMode: PropagateError,
},
{
name: "Ignore Error from function with IgnoreError",
conditions: []boolExpressionEvaluator[any]{
func(context.Context, any) (bool, error) {
return true, fmt.Errorf("test")
},
},
errorMode: IgnoreError,
},
{
name: "Ignore Error from function with SilentError",
conditions: []boolExpressionEvaluator[any]{
func(context.Context, any) (bool, error) {
return true, fmt.Errorf("test")
},
},
errorMode: SilentError,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -2287,8 +2325,12 @@ func Test_ConditionSequence_Eval_Error(t *testing.T) {
}

result, err := conditions.Eval(context.Background(), nil)
assert.Error(t, err)
assert.False(t, result)
if tt.errorMode == PropagateError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
9 changes: 5 additions & 4 deletions processor/filterprocessor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,11 @@ If all datapoints for a metric are dropped, the metric will also be dropped.

The filter processor also allows configuring an optional field, `error_mode`, which will determine how the processor reacts to errors that occur while processing an OTTL condition.

| error_mode | description |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------|
| ignore | The processor ignores errors returned by conditions and continues on to the next condition. This is the recommended mode. |
| propagate | The processor returns the error up the pipeline. This will result in the payload being dropped from the collector. |
| error_mode | description |
|------------|----------------------------------------------------------------------------------------------------------------------------------------|
| ignore | The processor ignores errors returned by conditions, logs them, and continues on to the next condition. This is the recommended mode. |
| silent | The processor ignores errors returned by conditions, does not log them, and continues on to the next condition. |
| propagate | The processor returns the error up the pipeline. This will result in the payload being dropped from the collector. |

If not specified, `propagate` will be used.

Expand Down
2 changes: 1 addition & 1 deletion processor/routingprocessor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ To configure the routing processor with [OTTL] routing conditions use the follow
- `table.statement (required)`: the routing condition provided as the [OTTL] statement.
- `table.exporters (required)`: the list of exporters to use when the routing condition is met.
- `default_exporters (optional)`: contains the list of exporters to use when a record does not meet any of specified conditions.
- `error_mode (optional)`: determines how errors returned from OTTL statements are handled. Valid values are `ignore` and `propagate`. If `ignored` is used and a statement's condition has an error then the payload will be routed to the default exporter. If not supplied, `propagate` is used.
- `error_mode (optional)`: determines how errors returned from OTTL statements are handled. Valid values are `ignore` and `propagate`. If `ignored` or `silent` is used and a statement's condition has an error then the payload will be routed to the default exporter. When `silent` is used the error is not logged. If not supplied, `propagate` is used.


```yaml
Expand Down
9 changes: 5 additions & 4 deletions processor/transformprocessor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ Each context will be processed in the order specified and each statement for a c

The transform processor also allows configuring an optional field, `error_mode`, which will determine how the processor reacts to errors that occur while processing a statement.

| error_mode | description |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------|
| ignore | The processor ignores errors returned by statements and continues on to the next statement. This is the recommended mode. |
| propagate | The processor returns the error up the pipeline. This will result in the payload being dropped from the collector. |
| error_mode | description |
|------------|---------------------------------------------------------------------------------------------------------------------------------------------|
| ignore | The processor ignores errors returned by statements, logs the error, and continues on to the next statement. This is the recommended mode. |
| silent | The processor ignores errors returned by statements, does not log the error, and continues on to the next statement. |
| propagate | The processor returns the error up the pipeline. This will result in the payload being dropped from the collector. |

If not specified, `propagate` will be used.

Expand Down