diff --git a/appmgr/src/logs.rs b/appmgr/src/logs.rs index b4a7f922e..a76b9ef40 100644 --- a/appmgr/src/logs.rs +++ b/appmgr/src/logs.rs @@ -42,6 +42,7 @@ struct JournalctlEntry { #[serde(rename = "__REALTIME_TIMESTAMP")] timestamp: String, #[serde(rename = "MESSAGE")] + #[serde(deserialize_with = "deserialize_string_or_utf8_array")] message: String, #[serde(rename = "__CURSOR")] cursor: String, @@ -60,6 +61,43 @@ impl JournalctlEntry { } } +fn deserialize_string_or_utf8_array<'de, D: serde::de::Deserializer<'de>>( + deserializer: D, +) -> std::result::Result { + struct Visitor; + impl<'de> serde::de::Visitor<'de> for Visitor { + type Value = String; + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "a parsable string") + } + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + Ok(v.to_owned()) + } + fn visit_string(self, v: String) -> Result + where + E: serde::de::Error, + { + Ok(v) + } + fn visit_seq(self, mut seq: A) -> Result + where + A: serde::de::SeqAccess<'de>, + { + String::from_utf8( + std::iter::repeat_with(|| seq.next_element::().transpose()) + .take_while(|a| a.is_some()) + .filter_map(|a| a) + .collect::, _>>()?, + ) + .map_err(serde::de::Error::custom) + } + } + deserializer.deserialize_any(Visitor) +} + #[derive(Debug)] pub enum LogSource { Service(&'static str),