From 3626ee3d18062ed2192ef95e7f1c22d03d3f5f2b Mon Sep 17 00:00:00 2001 From: Drew Relmas Date: Tue, 6 Jan 2026 00:57:31 +0000 Subject: [PATCH 1/4] Add support for schema key aliases --- .../src/bridge.rs | 89 +++++++++++++-- .../parser-abstractions/src/parser.rs | 108 +++++++++++++++++- 2 files changed, 188 insertions(+), 9 deletions(-) diff --git a/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/bridge.rs b/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/bridge.rs index ae549ec9b9..977eb4bf2f 100644 --- a/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/bridge.rs +++ b/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/bridge.rs @@ -339,15 +339,25 @@ fn build_log_record_schema( ) -> Result<(ParserMapSchema, Option), ParserError> { let mut log_record_schema = ParserMapSchema::new() .set_default_map_key("Attributes") + .with_alias("attributes", "Attributes") .with_key_definition("Timestamp", ParserMapKeySchema::DateTime) + .with_alias("timestamp", "Timestamp") .with_key_definition("ObservedTimestamp", ParserMapKeySchema::DateTime) + .with_alias("observed_timestamp", "ObservedTimestamp") .with_key_definition("SeverityNumber", ParserMapKeySchema::Integer) + .with_alias("severity_number", "SeverityNumber") .with_key_definition("SeverityText", ParserMapKeySchema::String) + .with_alias("severity_text", "SeverityText") .with_key_definition("Body", ParserMapKeySchema::Any) + .with_alias("body", "Body") .with_key_definition("TraceId", ParserMapKeySchema::Array) + .with_alias("trace_id", "TraceId") .with_key_definition("SpanId", ParserMapKeySchema::Array) + .with_alias("span_id", "SpanId") .with_key_definition("TraceFlags", ParserMapKeySchema::Integer) - .with_key_definition("EventName", ParserMapKeySchema::String); + .with_alias("trace_flags", "TraceFlags") + .with_key_definition("EventName", ParserMapKeySchema::String) + .with_alias("event_name", "EventName"); if let Some(mut attributes_schema) = attributes_schema { let schema = attributes_schema.get_schema_mut(); @@ -363,13 +373,17 @@ fn build_log_record_schema( // present in Attributes users might query with ambiguous naming. // For example: source | extend Body = 'something' will write to the // top-level field and not Attributes. - if let Some(removed) = schema.remove(top_level_key) - && &removed != top_level_key_schema - { - return Err(ParserError::SchemaError(format!( - "'{top_level_key}' key cannot be declared as '{}' type", - &removed - ))); + + // Check both the canonical key and all its aliases + for key_name in log_record_schema.get_all_key_names_for_canonical_key(top_level_key) { + if let Some(removed) = schema.remove(key_name.as_ref()) + && &removed != top_level_key_schema + { + return Err(ParserError::SchemaError(format!( + "'{key_name}' key cannot be declared as '{}' type", + &removed + ))); + } } } @@ -786,4 +800,63 @@ mod tests { assert_eq!(1, e.len()); assert!(matches!(e[0], ParserError::SchemaError(_))); } + + #[test] + fn test_parse_kql_query_with_field_aliases() { + let run_test = |query: &str| { + parse_kql_query_into_pipeline(query, None).unwrap(); + }; + + // Test PascalCase canonical names + run_test("source | where SeverityText == 'Info'"); + run_test("source | extend x = SeverityNumber"); + run_test("source | project Timestamp, Body"); + + // Test snake_case aliases + run_test("source | where severity_text == 'Info'"); + run_test("source | extend x = severity_number"); + run_test("source | project timestamp, body"); + + // Test mixing aliases and canonical names + run_test("source | where severity_text == 'Info' and SeverityNumber > 0"); + run_test("source | extend ts = timestamp, sev = SeverityText"); + + // Test default map key alias + run_test("source | where attributes.custom_field == 'value'"); + run_test("source | where Attributes.custom_field == 'value'"); + } + + #[test] + fn test_attributes_schema_removes_top_level_aliases() { + // Test that when user provides an attributes schema with aliases + // of top-level fields, they get removed properly + let result = parse_kql_query_into_pipeline( + "source | extend severity_text = 'Debug'", + Some( + BridgeOptions::new().with_attributes_schema( + ParserMapSchema::new() + // This should be removed because severity_text is an alias for SeverityText + .with_key_definition("severity_text", ParserMapKeySchema::String) + .with_key_definition("custom_field", ParserMapKeySchema::Integer), + ), + ), + ); + + // Should succeed - severity_text should write to top-level field + assert!(result.is_ok()); + + // Test with canonical name too + let result = parse_kql_query_into_pipeline( + "source | extend SeverityText = 'Debug'", + Some( + BridgeOptions::new().with_attributes_schema( + ParserMapSchema::new() + .with_key_definition("SeverityText", ParserMapKeySchema::String) + .with_key_definition("custom_field", ParserMapKeySchema::Integer), + ), + ), + ); + + assert!(result.is_ok()); + } } diff --git a/rust/experimental/query_engine/parser-abstractions/src/parser.rs b/rust/experimental/query_engine/parser-abstractions/src/parser.rs index 6fa0240279..41f01a5fc3 100644 --- a/rust/experimental/query_engine/parser-abstractions/src/parser.rs +++ b/rust/experimental/query_engine/parser-abstractions/src/parser.rs @@ -101,6 +101,7 @@ impl Default for ParserOptions { #[derive(Debug, Clone, PartialEq)] pub struct ParserMapSchema { keys: HashMap, ParserMapKeySchema>, + aliases: HashMap, Box>, default_map_key: Option>, allow_undefined_keys: bool, } @@ -109,6 +110,7 @@ impl ParserMapSchema { pub fn new() -> ParserMapSchema { Self { keys: HashMap::new(), + aliases: HashMap::new(), default_map_key: None, allow_undefined_keys: false, } @@ -123,6 +125,11 @@ impl ParserMapSchema { self } + pub fn with_alias(mut self, alias: &str, canonical_key: &str) -> ParserMapSchema { + self.aliases.insert(alias.into(), canonical_key.into()); + self + } + pub fn set_default_map_key(mut self, name: &str) -> ParserMapSchema { if self.allow_undefined_keys { panic!("Default map cannot be specified when undefined keys is enabled"); @@ -155,7 +162,38 @@ impl ParserMapSchema { } pub fn get_schema_for_key(&self, name: &str) -> Option<&ParserMapKeySchema> { - self.keys.get(name) + // First check if this is an alias, if so resolve to canonical key + let key = self.aliases.get(name).map(|v| v.as_ref()).unwrap_or(name); + self.keys.get(key) + } + + pub fn get_aliases_for_key(&self, canonical_key: &str) -> Vec<&str> { + self.aliases + .iter() + .filter_map(|(alias, key)| { + if key.as_ref() == canonical_key { + Some(alias.as_ref()) + } else { + None + } + }) + .collect() + } + + pub fn get_all_key_names_for_canonical_key(&self, canonical_key: &str) -> Vec> { + let mut names = vec![canonical_key.into()]; + names.extend( + self.aliases + .iter() + .filter_map(|(alias, key)| { + if key.as_ref() == canonical_key { + Some(alias.clone()) + } else { + None + } + }), + ); + names } pub fn get_default_map(&self) -> Option<(&str, Option<&ParserMapSchema>)> { @@ -343,3 +381,71 @@ impl ParserResult { Self { pipeline } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parser_map_schema_aliases() { + let schema = ParserMapSchema::new() + .with_key_definition("SeverityText", ParserMapKeySchema::String) + .with_alias("severity_text", "SeverityText") + .with_key_definition("SeverityNumber", ParserMapKeySchema::Integer) + .with_alias("severity_number", "SeverityNumber"); + + // Test canonical key lookup + assert_eq!( + schema.get_schema_for_key("SeverityText"), + Some(&ParserMapKeySchema::String) + ); + assert_eq!( + schema.get_schema_for_key("SeverityNumber"), + Some(&ParserMapKeySchema::Integer) + ); + + // Test alias lookup - should resolve to the same schema as canonical key + assert_eq!( + schema.get_schema_for_key("severity_text"), + Some(&ParserMapKeySchema::String) + ); + assert_eq!( + schema.get_schema_for_key("severity_number"), + Some(&ParserMapKeySchema::Integer) + ); + + // Test non-existent key + assert_eq!(schema.get_schema_for_key("NonExistent"), None); + } + + #[test] + fn test_parser_map_schema_get_aliases() { + let schema = ParserMapSchema::new() + .with_key_definition("SeverityText", ParserMapKeySchema::String) + .with_alias("severity_text", "SeverityText") + .with_alias("sev_text", "SeverityText"); + + // Test getting aliases for a canonical key + let mut aliases = schema.get_aliases_for_key("SeverityText"); + aliases.sort(); + assert_eq!(aliases, vec!["sev_text", "severity_text"]); + + // Test getting all key names (canonical + aliases) + let mut all_names: Vec = schema + .get_all_key_names_for_canonical_key("SeverityText") + .into_iter() + .map(|s| s.to_string()) + .collect(); + all_names.sort(); + assert_eq!(all_names, vec!["SeverityText", "sev_text", "severity_text"]); + + // Test for key with no aliases + assert_eq!(schema.get_aliases_for_key("NonExistent"), Vec::<&str>::new()); + let non_existent: Vec = schema + .get_all_key_names_for_canonical_key("NonExistent") + .into_iter() + .map(|s| s.to_string()) + .collect(); + assert_eq!(non_existent, vec!["NonExistent"]); + } +} From f566c4b423fd41cb30c77daf2d2e754a54db4ed3 Mon Sep 17 00:00:00 2001 From: Drew Relmas Date: Tue, 6 Jan 2026 01:17:41 +0000 Subject: [PATCH 2/4] Fmt --- .../src/bridge.rs | 4 ++-- .../parser-abstractions/src/parser.rs | 23 +++++++++---------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/bridge.rs b/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/bridge.rs index 977eb4bf2f..286f62541b 100644 --- a/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/bridge.rs +++ b/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/bridge.rs @@ -373,7 +373,7 @@ fn build_log_record_schema( // present in Attributes users might query with ambiguous naming. // For example: source | extend Body = 'something' will write to the // top-level field and not Attributes. - + // Check both the canonical key and all its aliases for key_name in log_record_schema.get_all_key_names_for_canonical_key(top_level_key) { if let Some(removed) = schema.remove(key_name.as_ref()) @@ -820,7 +820,7 @@ mod tests { // Test mixing aliases and canonical names run_test("source | where severity_text == 'Info' and SeverityNumber > 0"); run_test("source | extend ts = timestamp, sev = SeverityText"); - + // Test default map key alias run_test("source | where attributes.custom_field == 'value'"); run_test("source | where Attributes.custom_field == 'value'"); diff --git a/rust/experimental/query_engine/parser-abstractions/src/parser.rs b/rust/experimental/query_engine/parser-abstractions/src/parser.rs index 41f01a5fc3..10d97ee317 100644 --- a/rust/experimental/query_engine/parser-abstractions/src/parser.rs +++ b/rust/experimental/query_engine/parser-abstractions/src/parser.rs @@ -182,17 +182,13 @@ impl ParserMapSchema { pub fn get_all_key_names_for_canonical_key(&self, canonical_key: &str) -> Vec> { let mut names = vec![canonical_key.into()]; - names.extend( - self.aliases - .iter() - .filter_map(|(alias, key)| { - if key.as_ref() == canonical_key { - Some(alias.clone()) - } else { - None - } - }), - ); + names.extend(self.aliases.iter().filter_map(|(alias, key)| { + if key.as_ref() == canonical_key { + Some(alias.clone()) + } else { + None + } + })); names } @@ -440,7 +436,10 @@ mod tests { assert_eq!(all_names, vec!["SeverityText", "sev_text", "severity_text"]); // Test for key with no aliases - assert_eq!(schema.get_aliases_for_key("NonExistent"), Vec::<&str>::new()); + assert_eq!( + schema.get_aliases_for_key("NonExistent"), + Vec::<&str>::new() + ); let non_existent: Vec = schema .get_all_key_names_for_canonical_key("NonExistent") .into_iter() From 28e44580d0fdbc560972033c6e92e7b7d1559736 Mon Sep 17 00:00:00 2001 From: Drew Relmas Date: Tue, 6 Jan 2026 15:40:25 +0000 Subject: [PATCH 3/4] Match proto --- .../engine-recordset-otlp-bridge/src/bridge.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/bridge.rs b/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/bridge.rs index 286f62541b..d6fd6583a9 100644 --- a/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/bridge.rs +++ b/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/bridge.rs @@ -341,9 +341,9 @@ fn build_log_record_schema( .set_default_map_key("Attributes") .with_alias("attributes", "Attributes") .with_key_definition("Timestamp", ParserMapKeySchema::DateTime) - .with_alias("timestamp", "Timestamp") + .with_alias("time_unix_nano", "Timestamp") .with_key_definition("ObservedTimestamp", ParserMapKeySchema::DateTime) - .with_alias("observed_timestamp", "ObservedTimestamp") + .with_alias("observed_time_unix_nano", "ObservedTimestamp") .with_key_definition("SeverityNumber", ParserMapKeySchema::Integer) .with_alias("severity_number", "SeverityNumber") .with_key_definition("SeverityText", ParserMapKeySchema::String) @@ -355,7 +355,7 @@ fn build_log_record_schema( .with_key_definition("SpanId", ParserMapKeySchema::Array) .with_alias("span_id", "SpanId") .with_key_definition("TraceFlags", ParserMapKeySchema::Integer) - .with_alias("trace_flags", "TraceFlags") + .with_alias("flags", "TraceFlags") .with_key_definition("EventName", ParserMapKeySchema::String) .with_alias("event_name", "EventName"); @@ -815,11 +815,11 @@ mod tests { // Test snake_case aliases run_test("source | where severity_text == 'Info'"); run_test("source | extend x = severity_number"); - run_test("source | project timestamp, body"); + run_test("source | project time_unix_nano, body"); // Test mixing aliases and canonical names run_test("source | where severity_text == 'Info' and SeverityNumber > 0"); - run_test("source | extend ts = timestamp, sev = SeverityText"); + run_test("source | extend ts = time_unix_nano, sev = SeverityText"); // Test default map key alias run_test("source | where attributes.custom_field == 'value'"); From ce021cc5e182401bc4c9b633ee78c168c25ad8bf Mon Sep 17 00:00:00 2001 From: Drew Relmas Date: Tue, 6 Jan 2026 15:55:00 +0000 Subject: [PATCH 4/4] Add bridge runtime aliases --- .../src/bridge.rs | 64 +++++++++++ .../engine-recordset-otlp-bridge/src/logs.rs | 105 +++++++++--------- 2 files changed, 119 insertions(+), 50 deletions(-) diff --git a/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/bridge.rs b/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/bridge.rs index d6fd6583a9..c30ede3051 100644 --- a/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/bridge.rs +++ b/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/bridge.rs @@ -859,4 +859,68 @@ mod tests { assert!(result.is_ok()); } + + #[test] + fn test_field_aliases_in_log_record_processing() { + let create_request = || { + ExportLogsServiceRequest::new().with_resource_logs(ResourceLogs::new().with_scope_logs( + ScopeLogs::new().with_log_records(vec![ + LogRecord::new() + .with_severity_text("Info".into()) + .with_severity_number(9), + LogRecord::new() + .with_severity_text("Warning".into()) + .with_severity_number(13), + ]), + )) + }; + + let pipeline_alias = parse_kql_query_into_pipeline( + "source | where severity_text == 'Info' and severity_number == 9", + None, + ) + .unwrap(); + let (result_alias, _) = process_export_logs_service_request_using_pipeline( + None, + &pipeline_alias, + RecordSetEngineDiagnosticLevel::Error, + create_request(), + ) + .unwrap(); + + let pipeline_canonical = parse_kql_query_into_pipeline( + "source | where SeverityText == 'Info' and SeverityNumber == 9", + None, + ) + .unwrap(); + let (result_canonical, _) = process_export_logs_service_request_using_pipeline( + None, + &pipeline_canonical, + RecordSetEngineDiagnosticLevel::Error, + create_request(), + ) + .unwrap(); + + let alias_logs = &result_alias.unwrap().resource_logs[0].scope_logs[0].log_records; + let canonical_logs = &result_canonical.unwrap().resource_logs[0].scope_logs[0].log_records; + + assert_eq!(alias_logs.len(), 1); + assert_eq!(canonical_logs.len(), 1); + assert_eq!( + alias_logs[0].severity_text.as_ref().unwrap().get_value(), + canonical_logs[0] + .severity_text + .as_ref() + .unwrap() + .get_value() + ); + assert_eq!( + alias_logs[0].severity_number.as_ref().unwrap().get_value(), + canonical_logs[0] + .severity_number + .as_ref() + .unwrap() + .get_value() + ); + } } diff --git a/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/logs.rs b/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/logs.rs index 077edf6103..1843231bb4 100644 --- a/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/logs.rs +++ b/rust/experimental/query_engine/engine-recordset-otlp-bridge/src/logs.rs @@ -65,16 +65,16 @@ impl MapValue for LogRecord { fn contains_key(&self, key: &str) -> bool { match key { - "Attributes" => true, - "Timestamp" => self.timestamp.is_some(), - "ObservedTimestamp" => self.observed_timestamp.is_some(), - "SeverityNumber" => self.severity_number.is_some(), - "SeverityText" => self.severity_text.is_some(), - "Body" => self.body.is_some(), - "TraceId" => self.trace_id.is_some(), - "SpanId" => self.span_id.is_some(), - "TraceFlags" => self.flags.is_some(), - "EventName" => self.event_name.is_some(), + "Attributes" | "attributes" => true, + "Timestamp" | "time_unix_nano" => self.timestamp.is_some(), + "ObservedTimestamp" | "observed_time_unix_nano" => self.observed_timestamp.is_some(), + "SeverityNumber" | "severity_number" => self.severity_number.is_some(), + "SeverityText" | "severity_text" => self.severity_text.is_some(), + "Body" | "body" => self.body.is_some(), + "TraceId" | "trace_id" => self.trace_id.is_some(), + "SpanId" | "span_id" => self.span_id.is_some(), + "TraceFlags" | "flags" => self.flags.is_some(), + "EventName" | "event_name" => self.event_name.is_some(), _ => false, } } @@ -85,22 +85,26 @@ impl MapValue for LogRecord { fn get_static(&self, key: &str) -> Result, String> { Ok(match key { - "Attributes" => Some(&self.attributes), - "Timestamp" => self.timestamp.as_ref().map(|v| v as &dyn AsStaticValue), - "ObservedTimestamp" => self + "Attributes" | "attributes" => Some(&self.attributes), + "Timestamp" | "time_unix_nano" => { + self.timestamp.as_ref().map(|v| v as &dyn AsStaticValue) + } + "ObservedTimestamp" | "observed_time_unix_nano" => self .observed_timestamp .as_ref() .map(|v| v as &dyn AsStaticValue), - "SeverityNumber" => self + "SeverityNumber" | "severity_number" => self .severity_number .as_ref() .map(|v| v as &dyn AsStaticValue), - "SeverityText" => self.severity_text.as_ref().map(|v| v as &dyn AsStaticValue), - "Body" => self.body.as_ref().map(|v| v as &dyn AsStaticValue), - "TraceId" => self.trace_id.as_ref().map(|v| v as &dyn AsStaticValue), - "SpanId" => self.span_id.as_ref().map(|v| v as &dyn AsStaticValue), - "TraceFlags" => self.flags.as_ref().map(|v| v as &dyn AsStaticValue), - "EventName" => self.event_name.as_ref().map(|v| v as &dyn AsStaticValue), + "SeverityText" | "severity_text" => { + self.severity_text.as_ref().map(|v| v as &dyn AsStaticValue) + } + "Body" | "body" => self.body.as_ref().map(|v| v as &dyn AsStaticValue), + "TraceId" | "trace_id" => self.trace_id.as_ref().map(|v| v as &dyn AsStaticValue), + "SpanId" | "span_id" => self.span_id.as_ref().map(|v| v as &dyn AsStaticValue), + "TraceFlags" | "flags" => self.flags.as_ref().map(|v| v as &dyn AsStaticValue), + "EventName" | "event_name" => self.event_name.as_ref().map(|v| v as &dyn AsStaticValue), _ => None, }) } @@ -168,36 +172,36 @@ impl AsStaticValueMut for LogRecord { impl MapValueMut for LogRecord { fn get_mut(&mut self, key: &str) -> ValueMutGetResult<'_> { match key { - "Attributes" => ValueMutGetResult::Found(&mut self.attributes), - "Timestamp" => ValueMutGetResult::NotSupported( + "Attributes" | "attributes" => ValueMutGetResult::Found(&mut self.attributes), + "Timestamp" | "time_unix_nano" => ValueMutGetResult::NotSupported( "Timestamp cannot be modified in place on LogRecord".into(), ), - "ObservedTimestamp" => ValueMutGetResult::NotSupported( + "ObservedTimestamp" | "observed_time_unix_nano" => ValueMutGetResult::NotSupported( "ObservedTimestamp cannot be modified in place on LogRecord".into(), ), - "SeverityNumber" => ValueMutGetResult::NotSupported( + "SeverityNumber" | "severity_number" => ValueMutGetResult::NotSupported( "SeverityNumber cannot be modified in place on LogRecord".into(), ), - "SeverityText" => match &mut self.severity_text { + "SeverityText" | "severity_text" => match &mut self.severity_text { Some(s) => ValueMutGetResult::Found(s), None => ValueMutGetResult::NotFound, }, - "Body" => match &mut self.body { + "Body" | "body" => match &mut self.body { Some(b) => ValueMutGetResult::Found(b), None => ValueMutGetResult::NotFound, }, - "TraceId" => match &mut self.trace_id { + "TraceId" | "trace_id" => match &mut self.trace_id { Some(t) => ValueMutGetResult::Found(t), None => ValueMutGetResult::NotFound, }, - "SpanId" => match &mut self.span_id { + "SpanId" | "span_id" => match &mut self.span_id { Some(s) => ValueMutGetResult::Found(s), None => ValueMutGetResult::NotFound, }, - "TraceFlags" => ValueMutGetResult::NotSupported( + "TraceFlags" | "flags" => ValueMutGetResult::NotSupported( "TraceFlags cannot be modified in place on LogRecord".into(), ), - "EventName" => match &mut self.event_name { + "EventName" | "event_name" => match &mut self.event_name { Some(e) => ValueMutGetResult::Found(e), None => ValueMutGetResult::NotFound, }, @@ -211,7 +215,7 @@ impl MapValueMut for LogRecord { let any_value = Into::::into(value).into(); match key { - "Attributes" => { + "Attributes" | "attributes" => { if let AnyValue::Native(OtlpAnyValue::KvlistValue(k)) = any_value { let old = mem::replace(&mut self.attributes, k); return ValueMutWriteResult::Updated(OwnedValue::Map(old.into())); @@ -221,7 +225,7 @@ impl MapValueMut for LogRecord { "Attributes cannot be set to type '{value_type:?}' on LogRecord" )) } - "Timestamp" => { + "Timestamp" | "time_unix_nano" => { if let AnyValue::Extended(ExtendedValue::DateTime(d)) = any_value { return match self.timestamp.replace(d) { Some(old) => ValueMutWriteResult::Updated(OwnedValue::DateTime(old)), @@ -233,7 +237,7 @@ impl MapValueMut for LogRecord { "Timestamp cannot be set to type '{value_type:?}' on LogRecord" )) } - "ObservedTimestamp" => { + "ObservedTimestamp" | "observed_time_unix_nano" => { if let AnyValue::Extended(ExtendedValue::DateTime(d)) = any_value { return match self.observed_timestamp.replace(d) { Some(old) => ValueMutWriteResult::Updated(OwnedValue::DateTime(old)), @@ -245,7 +249,7 @@ impl MapValueMut for LogRecord { "ObservedTimestamp cannot be set to type '{value_type:?}' on LogRecord" )) } - "SeverityNumber" => { + "SeverityNumber" | "severity_number" => { if let AnyValue::Native(OtlpAnyValue::IntValue(i)) = any_value { let value = i.get_value(); if value >= i32::MIN as i64 && value <= i32::MAX as i64 { @@ -265,7 +269,7 @@ impl MapValueMut for LogRecord { "SeverityNumber cannot be set to type '{value_type:?}' on LogRecord" )) } - "SeverityText" => { + "SeverityText" | "severity_text" => { if let AnyValue::Native(OtlpAnyValue::StringValue(s)) = any_value { return match self.severity_text.replace(s) { Some(old) => ValueMutWriteResult::Updated(OwnedValue::String(old)), @@ -277,11 +281,11 @@ impl MapValueMut for LogRecord { "SeverityText cannot be set to type '{value_type:?}' on LogRecord" )) } - "Body" => match self.body.replace(any_value) { + "Body" | "body" => match self.body.replace(any_value) { Some(old) => ValueMutWriteResult::Updated(old.into()), None => ValueMutWriteResult::Created, }, - "TraceId" => { + "TraceId" | "trace_id" => { if let AnyValue::Native(OtlpAnyValue::BytesValue(b)) = any_value { return match self.trace_id.replace(b) { Some(old) => ValueMutWriteResult::Updated( @@ -295,7 +299,7 @@ impl MapValueMut for LogRecord { "TraceId cannot be set to type '{value_type:?}' on LogRecord" )) } - "SpanId" => { + "SpanId" | "span_id" => { if let AnyValue::Native(OtlpAnyValue::BytesValue(b)) = any_value { return match self.span_id.replace(b) { Some(old) => ValueMutWriteResult::Updated( @@ -309,7 +313,7 @@ impl MapValueMut for LogRecord { "SpanId cannot be set to type '{value_type:?}' on LogRecord" )) } - "TraceFlags" => { + "TraceFlags" | "flags" => { if let AnyValue::Native(OtlpAnyValue::IntValue(i)) = any_value { let value = i.get_value(); if value >= u32::MIN as i64 && value <= u32::MAX as i64 { @@ -326,7 +330,7 @@ impl MapValueMut for LogRecord { "TraceFlags cannot be set to type '{value_type:?}' on LogRecord" )) } - "EventName" => { + "EventName" | "event_name" => { if let AnyValue::Native(OtlpAnyValue::StringValue(s)) = any_value { return match self.event_name.replace(s) { Some(old) => ValueMutWriteResult::Updated(OwnedValue::String(old)), @@ -348,51 +352,52 @@ impl MapValueMut for LogRecord { fn remove(&mut self, key: &str) -> ValueMutRemoveResult { match key { - "Attributes" => { + "Attributes" | "attributes" => { let old = mem::replace(&mut self.attributes, MapValueStorage::new(HashMap::new())); ValueMutRemoveResult::Removed(OwnedValue::Map(old.into())) } - "Timestamp" => match self.timestamp.take() { + "Timestamp" | "time_unix_nano" => match self.timestamp.take() { Some(old) => ValueMutRemoveResult::Removed(OwnedValue::DateTime(old)), None => ValueMutRemoveResult::NotFound, }, - "ObservedTimestamp" => match self.observed_timestamp.take() { + "ObservedTimestamp" | "observed_time_unix_nano" => match self.observed_timestamp.take() + { Some(old) => ValueMutRemoveResult::Removed(OwnedValue::DateTime(old)), None => ValueMutRemoveResult::NotFound, }, - "SeverityNumber" => match self.severity_number.take() { + "SeverityNumber" | "severity_number" => match self.severity_number.take() { Some(old) => ValueMutRemoveResult::Removed(OwnedValue::Integer( IntegerValueStorage::new(old.get_value()), )), None => ValueMutRemoveResult::NotFound, }, - "SeverityText" => match self.severity_text.take() { + "SeverityText" | "severity_text" => match self.severity_text.take() { Some(old) => ValueMutRemoveResult::Removed(OwnedValue::String(old)), None => ValueMutRemoveResult::NotFound, }, - "Body" => match self.body.take() { + "Body" | "body" => match self.body.take() { Some(old) => ValueMutRemoveResult::Removed(old.into()), None => ValueMutRemoveResult::NotFound, }, - "TraceId" => match self.trace_id.take() { + "TraceId" | "trace_id" => match self.trace_id.take() { Some(old) => ValueMutRemoveResult::Removed( AnyValue::Native(OtlpAnyValue::BytesValue(old)).into(), ), None => ValueMutRemoveResult::NotFound, }, - "SpanId" => match self.span_id.take() { + "SpanId" | "span_id" => match self.span_id.take() { Some(old) => ValueMutRemoveResult::Removed( AnyValue::Native(OtlpAnyValue::BytesValue(old)).into(), ), None => ValueMutRemoveResult::NotFound, }, - "TraceFlags" => match self.flags.take() { + "TraceFlags" | "flags" => match self.flags.take() { Some(old) => ValueMutRemoveResult::Removed(OwnedValue::Integer( IntegerValueStorage::new(old.get_value()), )), None => ValueMutRemoveResult::NotFound, }, - "EventName" => match self.event_name.take() { + "EventName" | "event_name" => match self.event_name.take() { Some(old) => ValueMutRemoveResult::Removed(OwnedValue::String(old)), None => ValueMutRemoveResult::NotFound, },