Skip to main content

actix_cloud_extra/
logger.rs

1//! Default logger setup for Actix Cloud applications.
2//!
3//! The output is normalized for readability:
4//! - Target: only keeps the first path before `::` (e.g. `project::module1::module2` => `project`).
5//! - Filename: only keeps the path starting from the last `src` (e.g. `/a/b/src/c/d/main.rs` => `src/c/d/main.rs`).
6
7use std::path::PathBuf;
8
9use actix_cloud::{
10    logger::{LogItem, Logger, LoggerBuilder, LoggerGuard},
11    tracing::Level,
12};
13
14/// Transform a log item before printing, see [module docs](self) for the rules.
15fn transformer(mut item: LogItem) -> LogItem {
16    // Trim target path.
17    // Only keep the first path before `::`. Change several library targets to our own.
18    item.target = item
19        .target
20        .split("::")
21        .next()
22        .unwrap_or("unknown")
23        .to_owned();
24
25    // Remove useless file path.
26    // Only keep path starting from the last `src`.
27    if let Some(filename) = &item.filename {
28        let mut buf = Vec::new();
29        let s = PathBuf::from(filename);
30        for i in s.iter().rev() {
31            buf.push(i);
32            if i.eq_ignore_ascii_case("src") {
33                break;
34            }
35        }
36        let mut s = PathBuf::new();
37        for i in buf.into_iter().rev() {
38            s.push(i);
39        }
40        item.filename = Some(s.to_string_lossy().into());
41    }
42    item
43}
44
45/// Start the default logger.
46///
47/// - `enable`: when `false`, nothing is started and `(None, None)` is returned.
48/// - `json`: output JSON lines instead of plain text.
49/// - `verbose`: include file name and line number, and log at `DEBUG` level.
50/// - `filter`: extra predicate, items returning `false` are dropped.
51///
52/// Returns the logger and a guard which stops logging when dropped; both are
53/// `Some` on success and `None` when the logger is disabled.
54pub fn start_logger(
55    enable: bool,
56    json: bool,
57    verbose: bool,
58    filter: fn(item: &LogItem) -> bool,
59) -> (Option<Logger>, Option<LoggerGuard>) {
60    if enable {
61        let mut builder = LoggerBuilder::new();
62        if json {
63            builder = builder.json();
64        }
65        if verbose {
66            builder = builder.filename().line_number().level(Level::DEBUG);
67        }
68        builder = builder.transformer(transformer).filter(filter);
69        let (logger, guard) = builder.start();
70        (Some(logger), Some(guard))
71    } else {
72        (None, None)
73    }
74}