From 540e645d563808a29dee6bc13110708c6e65190c Mon Sep 17 00:00:00 2001 From: Alon Gubkin Date: Mon, 24 Aug 2026 02:35:38 -0700 Subject: [PATCH 1/2] fix(cli): render structured log messages --- crates/alien-cli/src/commands/logs.rs | 46 ++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/crates/alien-cli/src/commands/logs.rs b/crates/alien-cli/src/commands/logs.rs index dc22e6382..78b25a3ba 100644 --- a/crates/alien-cli/src/commands/logs.rs +++ b/crates/alien-cli/src/commands/logs.rs @@ -896,7 +896,7 @@ fn extract_message(hit: &Value) -> String { .and_then(|body| body.get("message")) .and_then(Value::as_str) { - return message.to_string(); + return tracing_json_message(message).unwrap_or_else(|| message.to_string()); } if let Some(body) = hit.get("body").and_then(Value::as_str) { return body.to_string(); @@ -907,6 +907,19 @@ fn extract_message(hit: &Value) -> String { hit.to_string() } +fn tracing_json_message(input: &str) -> Option { + let record = serde_json::from_str::(input).ok()?; + let record = record.as_object()?; + record.get("timestamp")?.as_str()?; + record.get("level")?.as_str()?; + record + .get("fields")? + .as_object()? + .get("message")? + .as_str() + .map(str::to_string) +} + fn timestamp_from_nanos(timestamp_nanos: i64) -> Option> { let secs = timestamp_nanos.div_euclid(1_000_000_000); let nanos = timestamp_nanos.rem_euclid(1_000_000_000) as u32; @@ -1278,4 +1291,35 @@ mod tests { "2023-11-14T22:13:20.123+00:00" ); } + + #[test] + fn extracts_message_from_pre_normalization_tracing_record() { + let original = serde_json::json!({ + "timestamp": "2026-08-24T09:12:53.647763Z", + "level": "DEBUG", + "fields": { + "message": "Processed pending jobs", + "job_count": 2 + }, + "target": "example_service::worker" + }) + .to_string(); + let hit = serde_json::json!({ "body": { "message": original } }); + + let entry = log_entry_from_hit(hit.clone()); + + assert_eq!(entry.message, "Processed pending jobs"); + assert_eq!(entry.raw, hit); + } + + #[test] + fn does_not_guess_a_message_from_generic_json() { + let original = r#"{"level":"INFO","message":"ready"}"#; + let hit = serde_json::json!({ "body": { "message": original } }); + + let entry = log_entry_from_hit(hit.clone()); + + assert_eq!(entry.message, original); + assert_eq!(entry.raw, hit); + } } From 797633cd28e81b9c39d59c6998369d5b6cd59602 Mon Sep 17 00:00:00 2001 From: Alon Gubkin Date: Mon, 24 Aug 2026 02:41:13 -0700 Subject: [PATCH 2/2] fix(cli): require tracing record target --- crates/alien-cli/src/commands/logs.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/alien-cli/src/commands/logs.rs b/crates/alien-cli/src/commands/logs.rs index 78b25a3ba..c1450f22d 100644 --- a/crates/alien-cli/src/commands/logs.rs +++ b/crates/alien-cli/src/commands/logs.rs @@ -912,6 +912,7 @@ fn tracing_json_message(input: &str) -> Option { let record = record.as_object()?; record.get("timestamp")?.as_str()?; record.get("level")?.as_str()?; + record.get("target")?.as_str()?; record .get("fields")? .as_object()? @@ -1314,7 +1315,8 @@ mod tests { #[test] fn does_not_guess_a_message_from_generic_json() { - let original = r#"{"level":"INFO","message":"ready"}"#; + let original = + r#"{"timestamp":"2026-08-24T09:12:53Z","level":"INFO","fields":{"message":"ready"}}"#; let hit = serde_json::json!({ "body": { "message": original } }); let entry = log_entry_from_hit(hit.clone());