Return fields in a smart order based on the log message type.
(log: &LogLine)
| 331 | |
| 332 | /// Return fields in a smart order based on the log message type. |
| 333 | pub fn ordered_fields(log: &LogLine) -> Vec<(&str, &str)> { |
| 334 | // Matches both "CONNECT" (L4-only decision) and "CONNECT_L7" (tunnel lifecycle for L7 endpoints) |
| 335 | let order: Option<&[&str]> = if log.message.starts_with("CONNECT") { |
| 336 | Some(CONNECT_FIELD_ORDER) |
| 337 | } else if log.message.starts_with("L7_REQUEST") { |
| 338 | Some(L7_FIELD_ORDER) |
| 339 | } else { |
| 340 | None |
| 341 | }; |
| 342 | |
| 343 | order.map_or_else( |
| 344 | || { |
| 345 | // Default: alphabetical. |
| 346 | let mut pairs: Vec<(&str, &str)> = log |
| 347 | .fields |
| 348 | .iter() |
| 349 | .map(|(k, v)| (k.as_str(), v.as_str())) |
| 350 | .collect(); |
| 351 | pairs.sort_by_key(|(k, _)| *k); |
| 352 | pairs |
| 353 | }, |
| 354 | |priority| { |
| 355 | let mut result: Vec<(&str, &str)> = Vec::with_capacity(log.fields.len()); |
| 356 | // Add priority fields first (in order). |
| 357 | for &key in priority { |
| 358 | if let Some(val) = log.fields.get(key) { |
| 359 | result.push((key, val.as_str())); |
| 360 | } |
| 361 | } |
| 362 | // Add remaining fields alphabetically. |
| 363 | let mut remaining: Vec<(&str, &str)> = log |
| 364 | .fields |
| 365 | .iter() |
| 366 | .filter(|(k, _)| !priority.contains(&k.as_str())) |
| 367 | .map(|(k, v)| (k.as_str(), v.as_str())) |
| 368 | .collect(); |
| 369 | remaining.sort_by_key(|(k, _)| *k); |
| 370 | result.extend(remaining); |
| 371 | result |
| 372 | }, |
| 373 | ) |
| 374 | } |
| 375 | |
| 376 | // --------------------------------------------------------------------------- |
| 377 | // Helpers |
no test coverage detected