Skip to content

Commit 96de949

Browse files
transform updates for json format logs
1 parent 9d2615c commit 96de949

File tree

2 files changed

+44
-8
lines changed

2 files changed

+44
-8
lines changed

content/en/ninja-workshops/10-advanced-otel/70-transform-data/1-test-transform.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ In this exercise, we will **remove the** `com.splunk/source` and `os.type` **met
5353
{{% /tab %}}
5454
{{% /tabs %}}
5555

56-
- **Check the debug output** of both the `Agent` and `Gateway` to confirm that the `SeverityText` in the `LogRecord` is now defined with the matching severity from the log body
56+
- **Check the debug output** of both the `Agent` and `Gateway` to confirm that the `SeverityText` in the `LogRecord` is now defined with the severity from the log body, along with the matching severity number.
57+
58+
Confirm that the JSON fields from the body can be accessed as top-level log attributes.
5759

5860
{{% tabs %}}
5961
{{% tab title="New Debug Output" %}}
@@ -63,10 +65,13 @@ In this exercise, we will **remove the** `com.splunk/source` and `os.type` **met
6365
ObservedTimestamp: 2025-01-31 21:49:29.924017 +0000 UTC
6466
Timestamp: 1970-01-01 00:00:00 +0000 UTC
6567
SeverityText: WARN
66-
SeverityNumber: Unspecified(0)
68+
SeverityNumber: Warn(13)
6769
Body: Str(2025-01-31 15:49:29 [WARN] - Do or do not, there is no try.)
6870
Attributes:
6971
-> log.file.path: Str(quotes.log)
72+
-> timestamp: Str(2025-01-31 15:49:29)
73+
-> level: Str(WARN)
74+
-> message: Str(Do or do not, there is no try.)
7075
Trace ID:
7176
Span ID:
7277
Flags: 0
@@ -138,6 +143,24 @@ In this exercise, we will **remove the** `com.splunk/source` and `os.type` **met
138143
"value": {
139144
"stringValue": "quotes.log"
140145
}
146+
},
147+
{
148+
"key": "timestamp",
149+
"value": {
150+
"stringValue": "2025-01-31 15:49:29"
151+
}
152+
},
153+
{
154+
"key": "level",
155+
"value": {
156+
"stringValue": "WARN"
157+
}
158+
},
159+
{
160+
"key": "message",
161+
"value": {
162+
"stringValue": "Do or do not, there is no try."
163+
}
141164
}
142165
],
143166
"traceId": "",

content/en/ninja-workshops/10-advanced-otel/70-transform-data/_index.md

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ WORKSHOP
3434

3535
In this section, we will update the `agent.yaml` file to include a **transform** processor. This processor will help filter log resource attributes and set the log severity text based on the message body.
3636

37-
Previously, you may have noticed that the `SeverityText` and `SeverityNumber` values are undefined in the log record, but are included in the log message body
37+
Previously, you may have noticed that the `SeverityText` and `SeverityNumber` values are undefined in the log record, but the severity is included in the `level` field of the log body
3838

3939
```text
4040
<snip>
@@ -71,16 +71,29 @@ In this case, we will be filtering the resource attributes and keeping only rele
7171
7272
Notice that the `keep_keys` statement is only applicable to the log resource context.
7373

74-
- **Add another context block for the log along with set statements to set the severity_text of the log record based on the matching severity level from the unstructured log.
74+
Logs often contain structured data encoded as JSON within the log body. Extracting these fields into attributes allows for better indexing, filtering, and querying. Instead of manually parsing JSON in downstream systems, OTTL enables automatic transformation at the telemetry pipeline level.
75+
76+
- **Add another context block** for the log along with set statements to set the severity_text and severity_number of the log record based on the matching severity level from the log body.
7577

7678
```yaml
7779
- context: log
7880
statements:
79-
- set(severity_text, "INFO") where IsMatch(body, "\\[INFO\\]")
80-
- set(severity_text, "WARN") where IsMatch(body, "\\[WARN\\]")
81-
- set(severity_text, "DEBUG") where IsMatch(body, "\\[DEBUG\\]")
82-
- set(severity_text, "ERROR") where IsMatch(body, "\\[ERROR\\]")
81+
- context: log
82+
statements:
83+
- set(cache, ParseJSON(body)) where IsMatch(body, "^\\{")
84+
- flatten(cache, "")
85+
- merge_maps(attributes, cache, "upsert")
86+
- set(severity_text, attributes["level"])
87+
- set(severity_number, 1) where severity_text == "TRACE"
88+
- set(severity_number, 5) where severity_text == "DEBUG"
89+
- set(severity_number, 9) where severity_text == "INFO"
90+
- set(severity_number, 13) where severity_text == "WARN"
91+
- set(severity_number, 17) where severity_text == "ERROR"
92+
- set(severity_number, 21) where severity_text == "FATAL"
8393
```
94+
This transformation checks if the log body contains a JSON object, then extracts its fields into log attributes while preserving nested structures. The flatten(cache) step ensures that deeply nested JSON fields can be accessed as top-level attributes.
95+
96+
8497

8598
- **Update the `logs` pipeline**: Add the `transform` processor into the `logs:` pipeline:
8699

0 commit comments

Comments
 (0)