Skip to content

Commit eb89a29

Browse files
committed
Address review comments: Implement config as per the suggested new design
Signed-off-by: Manisha Yadav <yavmanis@amazon.com>
1 parent 38de323 commit eb89a29

10 files changed

Lines changed: 627 additions & 828 deletions

File tree

data-prepper-plugins/multiline-codecs/README.md

Lines changed: 31 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,46 +12,49 @@ The multiline input codec can be configured with source plugins (e.g. S3 source,
1212
- **Python tracebacks**: `Traceback` blocks spanning multiple lines
1313
- **Timestamp-prefixed logs**: Logs where each entry starts with a timestamp and continuation lines don't
1414
- **Multi-line JSON/XML in logs**: Structured data embedded across multiple lines within log entries
15-
- **Custom log formats**: Any format where a recognizable pattern marks the start of a new event
15+
- **Custom log formats**: Any format where a recognizable pattern marks the start or end of a new event
1616

1717
## Configuration Options
1818

19+
Exactly one of the four pattern fields must be specified:
20+
1921
| Option | Required | Type | Default | Description |
2022
|---|---|---|---|---|
21-
| `match` | Yes | String (regex) | - | A regular expression pattern used to identify line boundaries |
22-
| `negate` | No | Boolean | `false` | When `false`, lines matching the pattern are continuation lines. When `true`, lines NOT matching the pattern are continuation lines |
23-
| `what` | No | String | `previous` | Whether continuation lines belong to the `previous` or `next` event |
23+
| `event_start_pattern` | One of four | String (regex) | - | A new event begins at each line matching this pattern |
24+
| `event_end_pattern` | One of four | String (regex) | - | An event ends at each line matching this pattern (inclusive) |
25+
| `continuation_line_start_pattern` | One of four | String (regex) | - | Lines matching this pattern are continuations of the previous event |
26+
| `continuation_line_end_pattern` | One of four | String (regex) | - | Lines matching this pattern are prepended to the next event |
27+
| `omit_matched_section` | No | Boolean | `false` | When true, the matched portion of the line is omitted from the output |
2428
| `max_lines` | No | Integer | `500` | Maximum number of lines that can be combined into a single event |
25-
| `max_length` | No | Integer | `10000` | Maximum character length of a combined multiline event |
26-
| `line_separator` | No | String | `\n` | Separator string used when joining lines into a single event message |
29+
| `max_length` | No | Integer | `10000` | Maximum character length of a combined multiline event. Note: a single line exceeding this limit will still be emitted as a complete event without truncation |
30+
| `line_separator` | No | String | `\n` | Separator string used when joining lines into a single event message. Note: `BufferedReader.readLine()` strips original line endings, so the codec normalizes joined lines using this separator. Set to `""` for no separator |
31+
| `encoding` | No | String | `UTF-8` | Character encoding to use when reading the input stream |
2732

2833
## How It Works
2934

30-
The codec reads lines from the input stream and uses the `match` regex to determine event boundaries:
35+
The codec reads lines from the input stream and uses the configured pattern to determine event boundaries:
3136

32-
1. **`negate=true` + `what=previous`** (most common): A new event starts when a line matches the pattern. Lines that do NOT match are appended to the preceding event.
37+
1. **`event_start_pattern`** (most common): Each line matching the pattern starts a new event. All subsequent non-matching lines are appended to it.
3338

34-
2. **`negate=false` + `what=previous`**: Lines that match the pattern are appended to the preceding event.
39+
2. **`event_end_pattern`**: Lines are accumulated until a line matches the pattern. The matching line is included in the current event, and the next line starts a new event.
3540

36-
3. **`negate=true` + `what=next`**: Lines that do NOT match the pattern are prepended to the next matching line.
41+
3. **`continuation_line_start_pattern`**: Lines matching the pattern are continuations of the previous event. Non-matching lines start new events.
3742

38-
4. **`negate=false` + `what=next`**: Lines that match the pattern are prepended to the next non-matching line.
43+
4. **`continuation_line_end_pattern`**: Lines matching the pattern are prepended to the next non-matching line's event.
3944

4045
## Examples
4146

42-
### Java Stack Traces (timestamp-based grouping)
47+
### Java Stack Traces
4348

44-
Each log entry starts with a timestamp. Lines without a timestamp are continuations of the previous entry.
49+
Each log entry starts with a timestamp. Lines without a timestamp (stack frames) are part of the previous entry.
4550

4651
```yaml
4752
pipeline:
4853
source:
4954
s3:
5055
codec:
5156
multiline:
52-
match: "^\\d{4}-\\d{2}-\\d{2}"
53-
negate: true
54-
what: previous
57+
event_start_pattern: "^\\d{4}-\\d{2}-\\d{2}"
5558
```
5659
5760
Input:
@@ -62,51 +65,46 @@ Input:
6265
2024-01-01 12:00:01 INFO Application recovered
6366
```
6467

65-
Result: 2 events
66-
- Event 1: The ERROR line with its full stack trace grouped together
67-
- Event 2: The INFO line as a single event
68+
Result: 2 events (stack trace grouped with its ERROR line)
6869

69-
### Java Stack Traces (pattern-based grouping)
70+
### Delimiter-Separated Entries
7071

71-
Lines starting with whitespace followed by `at `, `...`, or `Caused by:` are continuations.
72+
Log entries are separated by a `---` line.
7273

7374
```yaml
7475
pipeline:
7576
source:
7677
s3:
7778
codec:
7879
multiline:
79-
match: "^\\s+(at |\\.\\.\\.|Caused by:)"
80-
negate: false
81-
what: previous
80+
event_end_pattern: "^---$"
8281
```
8382
84-
### Python Tracebacks
83+
### Stack Traces (continuation pattern)
84+
85+
Lines starting with whitespace followed by `at ` or `Caused by:` are continuations.
8586

8687
```yaml
8788
pipeline:
8889
source:
8990
s3:
9091
codec:
9192
multiline:
92-
match: "^Traceback|^\\s|^\\w+Error"
93-
negate: false
94-
what: previous
93+
continuation_line_start_pattern: "^\\s+(at |\\.\\.\\.|Caused by:)"
9594
```
9695

97-
### Log Entries with Preamble (next mode)
96+
### Omitting Timestamps from Output
9897

99-
Lines starting with whitespace are prepended to the next non-indented line.
98+
Strip the timestamp from each event's first line:
10099

101100
```yaml
102101
pipeline:
103102
source:
104103
s3:
105104
codec:
106105
multiline:
107-
match: "^\\s"
108-
negate: false
109-
what: next
106+
event_start_pattern: "^\\d{4}-\\d{2}-\\d{2}\\s+\\d{2}:\\d{2}:\\d{2}\\s+"
107+
omit_matched_section: true
110108
```
111109

112110
## Developer Guide

data-prepper-plugins/multiline-codecs/build.gradle

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,9 @@
77
* compatible open source license.
88
*/
99

10-
plugins {
11-
id 'java'
12-
}
13-
1410
dependencies {
1511
implementation project(':data-prepper-api')
1612
implementation 'com.fasterxml.jackson.core:jackson-annotations'
17-
implementation libs.parquet.common
1813
testImplementation project(':data-prepper-plugins:common')
1914
testImplementation project(':data-prepper-test:test-event')
2015
}
21-
22-
test {
23-
useJUnitPlatform()
24-
}

0 commit comments

Comments
 (0)