1use chrono::{Local, Offset};
2use serde::{Deserialize, Serialize};
3use std::str::FromStr;
4use time::{UtcOffset, format_description::well_known};
5use tracing_subscriber::{EnvFilter, fmt::format, fmt::time::OffsetTime, prelude::*};
6
7use super::error::RCSSLResult;
8
9pub use tracing::*;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
12#[serde(default)]
13pub struct LogConfig {
14 pub max_level: String,
15 pub filter: String,
16 pub rolling_file_path: Option<String>,
17}
18
19impl Default for LogConfig {
20 fn default() -> Self {
21 Self {
22 max_level: "debug".to_owned(),
23 filter: "traefik-ctl=debug".to_owned(),
24 rolling_file_path: Default::default(),
25 }
26 }
27}
28
29pub fn init_tracing(name: &str, log_config: &LogConfig) -> RCSSLResult<()> {
30 let mut logfile = None;
32 let mut stdout = None;
33 if let Some(rolling_file_path) = &log_config.rolling_file_path {
34 logfile = Some(tracing_appender::rolling::daily(rolling_file_path, name));
36 } else {
37 stdout = Some(
39 std::io::stdout
40 .with_max_level(tracing::Level::from_str(&log_config.max_level).unwrap()),
41 );
42 }
43
44 let local_offset_sec = Local::now().offset().fix().local_minus_utc();
46 let utc_offset = UtcOffset::from_whole_seconds(local_offset_sec)
47 .unwrap_or(UtcOffset::from_hms(8, 0, 0).unwrap());
48 let timer = OffsetTime::new(utc_offset, well_known::Rfc3339);
49
50 if let Some(stdout) = stdout {
51 tracing_subscriber::registry()
52 .with(EnvFilter::new(&log_config.filter))
53 .with(
54 tracing_subscriber::fmt::layer()
55 .event_format(format().compact())
56 .with_ansi(false)
57 .with_timer(timer)
58 .with_writer(stdout),
59 )
60 .try_init()?;
61 } else {
62 tracing_subscriber::registry()
63 .with(EnvFilter::new(&log_config.filter))
64 .with(
65 tracing_subscriber::fmt::layer()
66 .event_format(format().compact())
67 .with_ansi(false)
68 .with_timer(timer)
69 .with_writer(logfile.unwrap()),
70 )
71 .try_init()?;
72 }
73
74 Ok(())
75}