support_kit/logs/
log_file_config.rs

1use serde::{Deserialize, Serialize};
2use tracing_appender::non_blocking::WorkerGuard;
3
4use crate::TracingTarget;
5
6use super::{LogRotation, LoggerConfig};
7
8#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, bon::Builder)]
9pub struct LogFileConfig {
10    #[builder(into)]
11    pub directory: std::path::PathBuf,
12    #[builder(into)]
13    pub name: String,
14    #[builder(into)]
15    pub rotation: Option<LogRotation>,
16}
17
18impl LogFileConfig {
19    pub fn init_log_appender(&self, logger_config: &LoggerConfig) -> (TracingTarget, WorkerGuard) {
20        use tracing_appender::rolling::{daily, hourly, minutely, never};
21        use tracing_subscriber::{
22            fmt::{time::ChronoLocal, writer::MakeWriterExt},
23            Layer,
24        };
25
26        let directory = self.directory.clone();
27        let file_name_prefix = format!("{}.log", &self.name);
28
29        let (non_blocking, guard) =
30            tracing_appender::non_blocking(match self.rotation.clone().unwrap_or_default() {
31                LogRotation::Daily => daily(directory, file_name_prefix),
32                LogRotation::Hourly => hourly(directory, file_name_prefix),
33                LogRotation::PerMinute => minutely(directory, file_name_prefix),
34                LogRotation::Never => never(directory, file_name_prefix),
35            });
36
37        let logger = tracing_subscriber::fmt::layer()
38            .json()
39            .with_writer(
40                non_blocking
41                    .with_min_level(logger_config.min_tracing_level())
42                    .with_max_level(logger_config.max_tracing_level()),
43            )
44            .with_timer(ChronoLocal::default())
45            .boxed();
46
47        (logger, guard)
48    }
49}
50
51impl<GivenPath, GivenName> From<(GivenPath, GivenName)> for LogFileConfig
52where
53    GivenPath: Into<std::path::PathBuf>,
54    GivenName: Into<String>,
55{
56    fn from((directory, name): (GivenPath, GivenName)) -> Self {
57        Self::builder().directory(directory).name(name).build()
58    }
59}
60
61impl<GivenPath, GivenName, GivenRotation> From<(GivenPath, GivenName, GivenRotation)>
62    for LogFileConfig
63where
64    GivenPath: Into<std::path::PathBuf>,
65    GivenName: Into<String>,
66    GivenRotation: Into<LogRotation>,
67{
68    fn from((directory, name, rotation): (GivenPath, GivenName, GivenRotation)) -> Self {
69        Self::builder()
70            .directory(directory)
71            .name(name)
72            .rotation(rotation)
73            .build()
74    }
75}