diagnostics_data/
logs_legacy.rs1use crate::{Data, Logs};
6use fidl_fuchsia_logger::LogMessage;
7
8use std::collections::HashSet;
9use std::fmt::Write;
10
11impl From<&Data<Logs>> for LogMessage {
13 fn from(data: &Data<Logs>) -> LogMessage {
14 let mut msg = data.msg().unwrap_or("").to_string();
15
16 if let Some(payload) = data.payload_keys() {
17 for property in payload.properties.iter() {
18 write!(&mut msg, " {property}").expect("allocations have to fail for this to fail");
19 }
20 }
21 let file = data.metadata.file.as_ref();
22 let line = data.metadata.line.as_ref();
23 if let (Some(file), Some(line)) = (file, line) {
24 msg = format!("[{file}({line})] {msg}");
25 }
26
27 let tags = match &data.metadata.tags {
28 None => vec![data.component_name().to_string()],
29 Some(tags) if tags.is_empty() => vec![data.component_name().to_string()],
30 Some(tags) => tags.clone(),
31 };
32
33 LogMessage {
34 pid: data.pid().unwrap_or(zx::sys::ZX_KOID_INVALID),
35 tid: data.tid().unwrap_or(zx::sys::ZX_KOID_INVALID),
36 time: data.metadata.timestamp,
37 severity: data.metadata.raw_severity() as i32,
38 dropped_logs: data.dropped_logs().unwrap_or(0) as _,
39 tags,
40 msg,
41 }
42 }
43}
44
45pub fn format_log_message(data: &Data<Logs>) -> String {
49 let mut msg = data.msg().unwrap_or("").to_string();
50
51 if let Some(payload) = data.payload_keys() {
52 for property in payload.properties.iter() {
53 write!(&mut msg, " {property}").expect("allocations have to fail for this to fail");
54 }
55 }
56 let file = data.metadata.file.as_ref();
57 let line = data.metadata.line.as_ref();
58 if let (Some(file), Some(line)) = (file, line) {
59 msg = format!("[{file}({line})] {msg}");
60 }
61 msg
62}
63
64fn include_tag_prefix(tag: &str, tags: &HashSet<String>) -> bool {
67 if tag.contains("::") {
68 tags.iter().any(|t| {
69 tag.strip_prefix(t.as_str())
70 .map(|rest| rest.starts_with("::") && rest.len() > 2)
71 .unwrap_or(false)
72 })
73 } else {
74 false
75 }
76}
77
78pub fn filter_by_tags(log_message: &Data<Logs>, include_tags: &HashSet<String>) -> bool {
81 if include_tags.is_empty() {
82 false
83 } else if log_message.tags().map(|t| t.is_empty()).unwrap_or(true) {
84 !include_tags.contains(log_message.component_name().as_ref())
85 } else {
86 !log_message
87 .tags()
88 .map(|tags| {
89 tags.iter()
90 .any(|tag| include_tags.contains(tag) || include_tag_prefix(tag, include_tags))
91 })
92 .unwrap_or(false)
93 }
94}
95
96impl From<Data<Logs>> for LogMessage {
98 fn from(data: Data<Logs>) -> LogMessage {
99 LogMessage {
100 pid: data.pid().unwrap_or(zx::sys::ZX_KOID_INVALID),
101 tid: data.tid().unwrap_or(zx::sys::ZX_KOID_INVALID),
102 time: data.metadata.timestamp,
103 severity: data.metadata.raw_severity() as i32,
104 dropped_logs: data.dropped_logs().unwrap_or(0) as _,
105 msg: format_log_message(&data),
106 tags: match data.metadata.tags {
107 Some(tags) => tags,
108 None => vec![data.component_name().to_string()],
109 },
110 }
111 }
112}
113
114#[cfg(test)]
115mod test {
116 use super::*;
117 use crate::{BuilderArgs, LogsDataBuilder, Severity, Timestamp};
118 use fidl_fuchsia_diagnostics_types as fdiagnostics_types;
119
120 const TEST_URL: &str = "fuchsia-pkg://test";
121 const TEST_MONIKER: &str = "fake-test/moniker";
122
123 macro_rules! severity_roundtrip_test {
124 ($raw:expr, $expected:expr) => {
125 let severity = Severity::from(u8::from($raw));
126 let msg = LogsDataBuilder::new(BuilderArgs {
127 timestamp: Timestamp::from_nanos(0),
128 component_url: Some(TEST_URL.into()),
129 moniker: moniker::ExtendedMoniker::parse_str(TEST_MONIKER).unwrap(),
130 severity,
131 })
132 .build();
133
134 let legacy_msg: LogMessage = (&msg).into();
135 assert_eq!(
136 legacy_msg.severity,
137 i32::from($expected),
138 "failed to round trip severity for {:?} (raw {}), intermediates: {:#?}\n{:#?}",
139 severity,
140 $raw,
141 msg,
142 legacy_msg
143 );
144 };
145 }
146
147 #[fuchsia::test]
148 fn raw_severity_roundtrip_trace() {
149 severity_roundtrip_test!(
150 fdiagnostics_types::Severity::Trace.into_primitive() - 1,
151 fdiagnostics_types::Severity::Trace.into_primitive()
152 );
153 severity_roundtrip_test!(
154 fdiagnostics_types::Severity::Trace.into_primitive(),
155 fdiagnostics_types::Severity::Trace.into_primitive()
156 );
157 severity_roundtrip_test!(
158 fdiagnostics_types::Severity::Trace.into_primitive() + 1,
159 fdiagnostics_types::Severity::Debug.into_primitive()
160 );
161 }
162
163 #[fuchsia::test]
164 fn severity_roundtrip_debug() {
165 severity_roundtrip_test!(
166 fdiagnostics_types::Severity::Debug.into_primitive() - 1,
167 fdiagnostics_types::Severity::Debug.into_primitive()
168 );
169 severity_roundtrip_test!(
170 fdiagnostics_types::Severity::Debug.into_primitive(),
171 fdiagnostics_types::Severity::Debug.into_primitive()
172 );
173 severity_roundtrip_test!(
174 fdiagnostics_types::Severity::Debug.into_primitive() + 1,
175 fdiagnostics_types::Severity::Info.into_primitive()
176 );
177 }
178
179 #[fuchsia::test]
180 fn severity_roundtrip_info() {
181 severity_roundtrip_test!(
182 fdiagnostics_types::Severity::Info.into_primitive() - 1,
183 fdiagnostics_types::Severity::Info.into_primitive()
184 );
185 severity_roundtrip_test!(
186 fdiagnostics_types::Severity::Info.into_primitive(),
187 fdiagnostics_types::Severity::Info.into_primitive()
188 );
189 severity_roundtrip_test!(
190 fdiagnostics_types::Severity::Info.into_primitive() + 1,
191 fdiagnostics_types::Severity::Warn.into_primitive()
192 );
193 }
194
195 #[fuchsia::test]
196 fn severity_roundtrip_warn() {
197 severity_roundtrip_test!(
198 fdiagnostics_types::Severity::Warn.into_primitive() - 1,
199 fdiagnostics_types::Severity::Warn.into_primitive()
200 );
201 severity_roundtrip_test!(
202 fdiagnostics_types::Severity::Warn.into_primitive(),
203 fdiagnostics_types::Severity::Warn.into_primitive()
204 );
205 severity_roundtrip_test!(
206 fdiagnostics_types::Severity::Warn.into_primitive() + 1,
207 fdiagnostics_types::Severity::Error.into_primitive()
208 );
209 }
210
211 #[fuchsia::test]
212 fn severity_roundtrip_error() {
213 severity_roundtrip_test!(
214 fdiagnostics_types::Severity::Error.into_primitive() - 1,
215 fdiagnostics_types::Severity::Error.into_primitive()
216 );
217 severity_roundtrip_test!(
218 fdiagnostics_types::Severity::Error.into_primitive(),
219 fdiagnostics_types::Severity::Error.into_primitive()
220 );
221 severity_roundtrip_test!(
222 fdiagnostics_types::Severity::Error.into_primitive() + 1,
223 fdiagnostics_types::Severity::Fatal.into_primitive()
224 );
225 }
226
227 #[fuchsia::test]
228 fn severity_roundtrip_fatal() {
229 severity_roundtrip_test!(
230 fdiagnostics_types::Severity::Fatal.into_primitive() - 1,
231 fdiagnostics_types::Severity::Fatal.into_primitive()
232 );
233 severity_roundtrip_test!(
234 fdiagnostics_types::Severity::Fatal.into_primitive(),
235 fdiagnostics_types::Severity::Fatal.into_primitive()
236 );
237 severity_roundtrip_test!(
238 fdiagnostics_types::Severity::Fatal.into_primitive() + 1,
239 fdiagnostics_types::Severity::Fatal.into_primitive()
240 );
241 }
242
243 #[fuchsia::test]
244 fn test_include_tag_prefix_unicode() {
245 let mut tags = HashSet::new();
246 tags.insert("foo".to_string());
247 tags.insert("🦀".to_string());
248
249 assert!(!include_tag_prefix("🦀::bar", &["foo".to_string()].into_iter().collect()));
250 assert!(include_tag_prefix("🦀::bar", &tags));
251 assert!(!include_tag_prefix("🦀::", &tags));
252 assert!(include_tag_prefix("foo::bar", &tags));
253 }
254}