elfo_logger/config.rs
1//! Configuration for the logger.
2//!
3//! Note: all types here are exported only for documentation purposes
4//! and are not subject to stable guarantees. However, the config
5//! structure (usually encoded in TOML) follows stable guarantees.
6
7use std::path::PathBuf;
8
9use fxhash::FxHashMap;
10use serde::{Deserialize, Deserializer};
11use tracing::metadata::LevelFilter;
12
13use bytesize::ByteSize;
14
15/// Logger configuration.
16///
17/// It's exported only for documentation purposes and cannot be created or
18/// received outside the dumper.
19#[derive(Debug, Deserialize)]
20pub struct Config {
21 /// Sink for the log output.
22 /// By default logs are written to stdout.
23 #[serde(default)]
24 pub sink: Sink,
25 /// Path to the log file, applicable only for `Sink::File`.
26 pub path: Option<PathBuf>,
27 /// Log format.
28 #[serde(default)]
29 pub format: Format,
30
31 /// Size limit for each written log-line, in bytes.
32 /// If size exceeds the limit, it will be truncated in the following order:
33 ///
34 /// 1. Message with custom fields
35 /// 2. Meta-info (level, timestamp, ...)
36 /// 3. Meta-fields (location, module)
37 #[serde(default = "default_max_line_size")]
38 pub max_line_size: ByteSize,
39
40 /// Override log levels for specific targets.
41 /// Useful to suppress noisy logs from dependencies.
42 #[serde(default)]
43 pub targets: FxHashMap<String, LoggingTargetConfig>,
44}
45
46/// Configuration for a specific logging target.
47#[derive(Debug, Deserialize)]
48pub struct LoggingTargetConfig {
49 /// Maximum log level for the target.
50 #[serde(deserialize_with = "deserialize_level_filter")]
51 pub max_level: LevelFilter,
52}
53
54/// Sink for the log output.
55/// By default logs are written to stdout.
56#[derive(Debug, Default, PartialEq, Deserialize)]
57pub enum Sink {
58 /// Write logs to a file, specified by `path`.
59 File,
60 /// Write logs to stdout.
61 #[default]
62 Stdout,
63 // TODO: stdout + stderr
64}
65
66/// Log format.
67#[derive(Debug, Deserialize, Default)]
68pub struct Format {
69 /// Include location info in the log output.
70 #[serde(default)]
71 pub with_location: bool,
72 /// Include module info in the log output.
73 #[serde(default)]
74 pub with_module: bool,
75 /// Specify when to use colored output.
76 /// By default, colors are enabled only for interactive terminals.
77 #[serde(default)]
78 pub colorization: Colorization,
79}
80
81/// When to use colored output.
82#[derive(Debug, Deserialize, Default)]
83pub enum Colorization {
84 /// Use colors only if the output is a terminal.
85 #[default]
86 Auto,
87 /// Never use colors.
88 Never,
89 /// Use colors unconditionally.
90 Always,
91}
92
93fn default_max_line_size() -> ByteSize {
94 ByteSize(u64::MAX)
95}
96
97// TODO: deduplicate with core
98fn deserialize_level_filter<'de, D>(deserializer: D) -> Result<LevelFilter, D::Error>
99where
100 D: Deserializer<'de>,
101{
102 use PrettyLevelFilter::*;
103
104 #[derive(Deserialize)]
105 pub(crate) enum PrettyLevelFilter {
106 Trace,
107 Debug,
108 Info,
109 Warn,
110 Error,
111 Off,
112 }
113
114 let pretty = PrettyLevelFilter::deserialize(deserializer)?;
115
116 Ok(match pretty {
117 Trace => LevelFilter::TRACE,
118 Debug => LevelFilter::DEBUG,
119 Info => LevelFilter::INFO,
120 Warn => LevelFilter::WARN,
121 Error => LevelFilter::ERROR,
122 Off => LevelFilter::OFF,
123 })
124}