Skip to content

Commit 00ff976

Browse files
flatten json log messages inside log record body into individual fields
if a log event is json, with otel-collector, log records's body will contain the entire log event in order to make it usable and queryable, we flatten the json into individual columns original body field is also pertained for backward compatibility if log event is unstructured (not a json), it remains as-is in body field
1 parent f9082fa commit 00ff976

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

src/otel/logs.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use super::otel_utils::collect_json_from_values;
1919
use super::otel_utils::convert_epoch_nano_to_timestamp;
2020
use super::otel_utils::insert_attributes;
2121
use crate::metrics::increment_logs_collected_by_date;
22+
use crate::utils::json::flatten::generic_flattening;
2223
use opentelemetry_proto::tonic::collector::logs::v1::ExportLogsServiceRequest;
2324
use opentelemetry_proto::tonic::logs::v1::LogRecord;
2425
use opentelemetry_proto::tonic::logs::v1::LogsData;
@@ -92,8 +93,24 @@ pub fn flatten_log_record(log_record: &LogRecord) -> Map<String, Value> {
9293
if log_record.body.is_some() {
9394
let body = &log_record.body;
9495
let body_json = collect_json_from_values(body, &"body".to_string());
95-
for key in body_json.keys() {
96-
log_record_json.insert(key.to_owned(), body_json[key].to_owned());
96+
for (key, value) in &body_json {
97+
// Always insert the original body field as is
98+
log_record_json.insert(key.clone(), value.clone());
99+
100+
// If value is a string that can be parsed as JSON object, extract its fields
101+
if let Value::String(s) = value
102+
&& let Ok(parsed) = serde_json::from_str::<Value>(s)
103+
&& let Ok(flattened_values) = generic_flattening(&parsed)
104+
{
105+
for flattened_value in flattened_values {
106+
if let Value::Object(flattened_obj) = flattened_value {
107+
for (inner_key, inner_value) in flattened_obj {
108+
let prefixed_key = format!("{key}_{inner_key}");
109+
log_record_json.insert(prefixed_key, inner_value);
110+
}
111+
}
112+
}
113+
}
97114
}
98115
}
99116
insert_attributes(&mut log_record_json, &log_record.attributes);

0 commit comments

Comments
 (0)