support_kit/logs/
log_file_config.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use serde::{Deserialize, Serialize};
use tracing_appender::non_blocking::WorkerGuard;

use crate::TracingTarget;

use super::{LogRotation, LoggerConfig};

#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, bon::Builder)]
pub struct LogFileConfig {
    #[builder(into)]
    pub directory: std::path::PathBuf,
    #[builder(into)]
    pub name: String,
    #[builder(into)]
    pub rotation: Option<LogRotation>,
}

impl LogFileConfig {
    pub fn init_log_appender(&self, logger_config: &LoggerConfig) -> (TracingTarget, WorkerGuard) {
        use tracing_appender::rolling::{daily, hourly, minutely, never};
        use tracing_subscriber::{
            fmt::{time::ChronoLocal, writer::MakeWriterExt},
            Layer,
        };

        let directory = self.directory.clone();
        let file_name_prefix = format!("{}.log", &self.name);

        let (non_blocking, guard) =
            tracing_appender::non_blocking(match self.rotation.clone().unwrap_or_default() {
                LogRotation::Daily => daily(directory, file_name_prefix),
                LogRotation::Hourly => hourly(directory, file_name_prefix),
                LogRotation::PerMinute => minutely(directory, file_name_prefix),
                LogRotation::Never => never(directory, file_name_prefix),
            });

        let logger = tracing_subscriber::fmt::layer()
            .json()
            .with_writer(
                non_blocking
                    .with_min_level(logger_config.min_tracing_level())
                    .with_max_level(logger_config.max_tracing_level()),
            )
            .with_timer(ChronoLocal::default())
            .boxed();

        (logger, guard)
    }
}

impl<GivenPath, GivenName> From<(GivenPath, GivenName)> for LogFileConfig
where
    GivenPath: Into<std::path::PathBuf>,
    GivenName: Into<String>,
{
    fn from((directory, name): (GivenPath, GivenName)) -> Self {
        Self::builder().directory(directory).name(name).build()
    }
}

impl<GivenPath, GivenName, GivenRotation> From<(GivenPath, GivenName, GivenRotation)>
    for LogFileConfig
where
    GivenPath: Into<std::path::PathBuf>,
    GivenName: Into<String>,
    GivenRotation: Into<LogRotation>,
{
    fn from((directory, name, rotation): (GivenPath, GivenName, GivenRotation)) -> Self {
        Self::builder()
            .directory(directory)
            .name(name)
            .rotation(rotation)
            .build()
    }
}