Skip to content

Commit 751bbe8

Browse files
authored
fix: properly handle DecoderError to avoid pipeline failures (#932)
* add failing test to verify the bug * treat DecoderError as warning; use proper warning handler * refactor method to fix misleading parameter naming * add CHANGELOG entry * apply changes to ng * fix outdated pydoc; improve CHANGELOG * refine CHANGELOG
1 parent b3d1ddb commit 751bbe8

File tree

6 files changed

+27
-12
lines changed

6 files changed

+27
-12
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
* simplify Dockerfile and remove docker build support for `LOGPREP_VERSION`
1010

1111
### Bugfix
12-
* generic resolver now follows yaml standard and accepts a list instead of relying on the ordering of a dict
12+
* generic_resolver now follows yaml standard and accepts a list instead of relying on the ordering of a dict
13+
* decoder errors are handled properly as warnings instead of causing pipeline failures
1314

1415
## 18.0.1
1516
### Breaking

logprep/ng/processor/decoder/processor.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
from logprep.processor.decoder.decoders import DECODERS, DecoderError
4747
from logprep.processor.decoder.rule import DecoderRule
4848
from logprep.processor.field_manager.rule import FieldManagerRule
49-
from logprep.util.helper import FieldValue, add_fields_to
49+
from logprep.util.helper import FieldValue
5050
from logprep.util.typing import is_list_of
5151

5252

@@ -78,6 +78,5 @@ def _decode(
7878
return [decoder(value) for value in source_field_values]
7979
raise DecoderError("can only decode string values")
8080
except DecoderError as error:
81-
add_fields_to(event, {"tags": rule.failure_tags}, merge_with_target=True)
82-
self._event.errors.append(error)
81+
self._handle_warning_error(event, rule, error)
8382
return []

logprep/processor/decoder/processor.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
from logprep.processor.decoder.rule import DecoderRule
4747
from logprep.processor.field_manager.processor import FieldManager
4848
from logprep.processor.field_manager.rule import FieldManagerRule
49-
from logprep.util.helper import FieldValue, add_fields_to
49+
from logprep.util.helper import FieldValue
5050
from logprep.util.typing import is_list_of
5151

5252

@@ -78,6 +78,5 @@ def _decode(
7878
return [decoder(value) for value in source_field_values]
7979
raise DecoderError("can only decode string values")
8080
except DecoderError as error:
81-
add_fields_to(event, {"tags": rule.failure_tags}, merge_with_target=True)
82-
self.result.errors.append(error)
81+
self._handle_warning_error(event, rule, error)
8382
return []

logprep/util/typing.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@
88
T = TypeVar("T")
99

1010

11-
def is_list_of(val: list[Any], class_or_tuple: type[T]) -> TypeGuard[list[T]]:
11+
def is_list_of(val: list[Any], class_type: type[T]) -> TypeGuard[list[T]]:
1212
"""Checks and statically asserts that a list has a specific element type
1313
1414
Parameters
1515
----------
1616
val : list[Any]
1717
The list to be checked
18-
class_or_tuple : type[T]
18+
class_type : type[T]
1919
The element type to be checked against
2020
2121
Returns
2222
-------
2323
TypeGuard[list[T]]
2424
The type information that `val` is of this list type
2525
"""
26-
return all(isinstance(obj, class_or_tuple) for obj in val)
26+
return all(isinstance(obj, class_type) for obj in val)

tests/unit/ng/processor/decoder/test_decoder.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import pytest
77

88
from logprep.ng.event.log_event import LogEvent
9+
from logprep.processor.base.exceptions import ProcessingError, ProcessingWarning
10+
from logprep.util.typing import is_list_of
911
from tests.unit.ng.processor.base import BaseProcessorTestCase
1012

1113

@@ -689,7 +691,13 @@ def test_testcases_failure_handling(self, rule, event, expected):
689691
self._load_rule(rule)
690692
event = LogEvent(event, original=b"")
691693
result = self.object.process(event)
692-
assert result.errors or result.warnings
694+
assert len(result.errors) > 0 or len(result.warnings) > 0
695+
assert is_list_of(
696+
result.errors, ProcessingError
697+
), f"ProcessingError expected: {result.errors}"
698+
assert is_list_of(
699+
result.warnings, ProcessingWarning
700+
), f"ProcessingWarning expected: {result.warnings}"
693701
assert event.data == expected
694702

695703
def test_decodes_different_source_json_escaping(self):

tests/unit/processor/decoder/test_decoder.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
import pytest
77

8+
from logprep.processor.base.exceptions import ProcessingError, ProcessingWarning
9+
from logprep.util.typing import is_list_of
810
from tests.unit.processor.base import BaseProcessorTestCase
911

1012

@@ -686,7 +688,13 @@ def test_testcases(self, rule, event, expected):
686688
def test_testcases_failure_handling(self, rule, event, expected):
687689
self._load_rule(rule)
688690
result = self.object.process(event)
689-
assert result.errors or result.warnings
691+
assert len(result.errors) > 0 or len(result.warnings) > 0
692+
assert is_list_of(
693+
result.errors, ProcessingError
694+
), f"ProcessingError expected: {result.errors}"
695+
assert is_list_of(
696+
result.warnings, ProcessingWarning
697+
), f"ProcessingWarning expected: {result.warnings}"
690698
assert event == expected
691699

692700
def test_decodes_different_source_json_escaping(self):

0 commit comments

Comments
 (0)