1#[cfg(feature = "log")]
2use tracing::level_filters::LevelFilter;
3#[cfg(feature = "log")]
4use tracing_appender::rolling::{RollingFileAppender, Rotation};
5#[cfg(feature = "log")]
6use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
7
8#[cfg(feature = "log")]
9pub enum CLogLevel {
10 Trace,
11 Debug,
12 Info,
13 Warn,
14 Error,
15}
16
17#[cfg(feature = "log")]
18pub use tracing::{debug, error, info, trace, warn};
19
20#[cfg(feature = "log")]
21fn from_cloglevel(level: &CLogLevel) -> LevelFilter {
22 match level {
23 CLogLevel::Trace => LevelFilter::TRACE,
24 CLogLevel::Debug => LevelFilter::DEBUG,
25 CLogLevel::Info => LevelFilter::INFO,
26 CLogLevel::Warn => LevelFilter::WARN,
27 CLogLevel::Error => LevelFilter::ERROR,
28 }
29}
30
31#[cfg(feature = "log")]
33pub fn default_console_log(log_level: CLogLevel) {
34 let timer = tracing_subscriber::fmt::time::ChronoLocal::new("%Y-%m-%d %H:%M:%S".to_owned());
35 let console_layer = tracing_subscriber::fmt::layer()
36 .with_timer(timer.clone())
37 .with_target(true)
38 .with_line_number(true)
39 .with_writer(std::io::stdout)
40 .with_ansi(true)
41 .with_filter(from_cloglevel(&log_level));
42 tracing_subscriber::registry().with(console_layer).init();
43}
44
45#[cfg(feature = "log")]
47pub fn default_file_log(
48 log_level: CLogLevel,
49 log_path: &str,
50 log_file_name: &str,
51 max_log_files: Option<usize>,
52) {
53 let timer = tracing_subscriber::fmt::time::ChronoLocal::new("%Y-%m-%d %H:%M:%S".to_owned());
54
55 let mut file_appender = RollingFileAppender::builder()
56 .rotation(Rotation::DAILY)
57 .filename_prefix(log_file_name)
58 .filename_suffix("log");
59
60 if let Some(max_log_files) = max_log_files {
61 file_appender = file_appender.max_log_files(max_log_files);
62 };
63 let file_appender = file_appender.build(log_path).unwrap();
64
65 let file_layer = tracing_subscriber::fmt::layer()
66 .with_timer(timer)
67 .with_target(true)
68 .with_line_number(true)
69 .with_ansi(false)
70 .with_writer(file_appender)
71 .with_filter(from_cloglevel(&log_level));
72 tracing_subscriber::registry().with(file_layer).init();
73}
74
75#[cfg(feature = "log")]
77pub fn default_log(
78 log_level: CLogLevel,
79 log_path: &str,
80 log_file_name: &str,
81 max_log_files: Option<usize>,
82) {
83 let timer = tracing_subscriber::fmt::time::ChronoLocal::new("%Y-%m-%d %H:%M:%S".to_owned());
84 let console_layer = tracing_subscriber::fmt::layer()
85 .with_timer(timer.clone())
86 .with_target(true)
87 .with_line_number(true)
88 .with_writer(std::io::stdout)
89 .with_ansi(true)
90 .with_filter(from_cloglevel(&log_level));
91
92 let mut file_appender = RollingFileAppender::builder()
93 .rotation(Rotation::DAILY)
94 .filename_prefix(log_file_name)
95 .filename_suffix("log");
96
97 if let Some(max_log_files) = max_log_files {
98 file_appender = file_appender.max_log_files(max_log_files);
99 };
100 let file_appender = file_appender.build(log_path).unwrap();
101
102 let file_layer = tracing_subscriber::fmt::layer()
103 .with_timer(timer)
104 .with_target(true)
105 .with_line_number(true)
106 .with_ansi(false)
107 .with_writer(file_appender)
108 .with_filter(from_cloglevel(&log_level));
109 tracing_subscriber::registry()
110 .with(file_layer)
111 .with(console_layer)
112 .init();
113}
114
115#[test]
116#[cfg(feature = "log")]
117fn test_console_log() {
118 default_console_log(CLogLevel::Trace);
119 tracing::trace!("trace");
120 tracing::debug!("debug");
121 tracing::info!("info");
122 tracing::warn!("warn");
123 tracing::error!("error");
124}
125
126#[test]
127#[cfg(feature = "log")]
128fn test_file_log() {
129 default_file_log(CLogLevel::Trace, "./", "test", None);
130 tracing::trace!("trace");
131 tracing::debug!("debug");
132 tracing::info!("info");
133 tracing::warn!("warn");
134 tracing::error!("error");
135}
136
137#[test]
138#[cfg(feature = "log")]
139fn test_log() {
140 default_log(CLogLevel::Trace, "./", "test", None);
141 tracing::trace!("trace");
142 tracing::debug!("debug");
143 tracing::info!("info");
144 tracing::warn!("warn");
145 tracing::error!("error");
146}