support_kit/logs/
log_file_config.rs1use 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}