Skip to main content

log_full/
init.rs

1//! 日志初始化模块
2//! 
3//! 提供各种日志初始化函数
4
5use crate::error::{LogError, LogResult};
6use crate::logger::{CustomFilter, LogData, LogPlus};
7use crate::utils::{AsyncLogType, debug_check_init, parse_level, parse_size};
8use crate::quickwit::{QuickwitConfig, QuickwitClient};
9use std::io::LineWriter;
10use std::path::Path;
11use std::sync::{mpsc, OnceLock};
12
13/// 全局日志器实例
14static LOGGER_PLUS: OnceLock<LogPlus> = OnceLock::new();
15
16/// 简单初始化日志
17#[inline]
18pub fn init_log_simple(
19    level: &str,
20    log_file: String,
21    log_file_max: &str,
22    use_console: bool,
23    use_async: bool,
24) -> LogResult<()> {
25    init_log_inner(
26        parse_level(level)?,
27        log_file,
28        parse_size(log_file_max)?,
29        use_console,
30        use_async,
31        None,
32        None,
33    )
34}
35
36/// 标准初始化日志
37#[inline]
38pub fn init_log(
39    level: log::LevelFilter,
40    log_file: String,
41    log_file_max: u32,
42    use_console: bool,
43    use_async: bool,
44) -> LogResult<()> {
45    init_log_inner(level, log_file, log_file_max, use_console, use_async, None, None)
46}
47
48/// 带插件的初始化日志
49#[inline]
50pub fn init_log_with_plugin<P>(
51    level: log::LevelFilter,
52    log_file: String,
53    log_file_max: u32,
54    use_console: bool,
55    use_async: bool,
56    plugin: P,
57) -> LogResult<()>
58where
59    P: std::io::Write + Send + Sync + 'static,
60{
61    init_log_inner(
62        level,
63        log_file,
64        log_file_max,
65        use_console,
66        use_async,
67        Some(Box::new(plugin)),
68        None,
69    )
70}
71
72/// 带过滤器的初始化日志
73#[inline]
74pub fn init_log_with_filter(
75    level: log::LevelFilter,
76    log_file: String,
77    log_file_max: u32,
78    use_console: bool,
79    use_async: bool,
80    filter: impl CustomFilter,
81) -> LogResult<()> {
82    init_log_inner(
83        level,
84        log_file,
85        log_file_max,
86        use_console,
87        use_async,
88        None,
89        Some(Box::new(filter)),
90    )
91}
92
93/// 带插件和过滤器的初始化日志
94pub fn init_log_with_all<P>(
95    level: log::LevelFilter,
96    log_file: String,
97    log_file_max: u32,
98    use_console: bool,
99    use_async: bool,
100    plugin: P,
101    filter: impl CustomFilter,
102) -> LogResult<()>
103where
104    P: std::io::Write + Send + Sync + 'static,
105{
106    init_log_inner(
107        level,
108        log_file,
109        log_file_max,
110        use_console,
111        use_async,
112        Some(Box::new(plugin)),
113        Some(Box::new(filter)),
114    )
115}
116
117/// 设置特定目标的日志级别
118pub fn set_level(target: String, level: log::LevelFilter) {
119    if let Ok(mut f) = get_logger_plus().level_filter.write() {
120        f.insert(target, level);
121    }
122}
123
124/// 内部初始化函数
125fn init_log_inner(
126    level: log::LevelFilter,
127    log_file: String,
128    log_file_max: u32,
129    use_console: bool,
130    use_async: bool,
131    plugin: Option<Box<dyn std::io::Write + Send + Sync + 'static>>,
132    filter: Option<Box<dyn CustomFilter>>,
133) -> LogResult<()> {
134    init_log_inner_with_config(
135        level,
136        log_file,
137        log_file_max,
138        use_console,
139        use_async,
140        plugin,
141        filter,
142        true,
143        true,
144        true,
145        Vec::new(),
146        None,
147    )
148}
149
150/// 带完整配置的内部初始化函数
151pub fn init_log_inner_with_config(
152    level: log::LevelFilter,
153    log_file: String,
154    log_file_max: u32,
155    use_console: bool,
156    use_async: bool,
157    plugin: Option<Box<dyn std::io::Write + Send + Sync + 'static>>,
158    filter: Option<Box<dyn CustomFilter>>,
159    show_process_id: bool,
160    show_thread_info: bool,
161    show_module_path: bool,
162    highlight_keywords: Vec<String>,
163    quickwit_config: Option<QuickwitConfig>,
164) -> LogResult<()> {
165    // 验证配置
166    if log_file_max == 0 {
167        return Err(LogError::config("Max file size cannot be zero"));
168    }
169
170    if !log_file.is_empty() {
171        if let Some(parent) = Path::new(&log_file).parent() {
172            if !parent.exists() {
173                return Err(LogError::file_operation(
174                    log_file.clone(),
175                    "Parent directory does not exist",
176                ));
177            }
178        }
179    }
180
181    debug_check_init();
182
183    log::set_max_level(level);
184
185    // 如果启用控制台输出,创建一个控制台共享句柄
186    let console = if use_console {
187        Some(LineWriter::new(std::io::stdout()))
188    } else {
189        None
190    };
191
192    // 如果启用文件输出,打开日志文件
193    let (fileout, log_size) = if !log_file.is_empty() {
194        match crate::utils::open_log_file_sync(&log_file) {
195            Ok((writer, size)) => (Some(writer), size),
196            Err(e) => {
197                eprintln!("Failed to open log file {}: {}", log_file, e);
198                (None, 0)
199            }
200        }
201    } else {
202        (None, 0)
203    };
204
205    // 如果启用异步日志,开启一个线程不停读取channel中的数据进行日志写入,属于多生产者单消费者模式
206    let sender = if use_async {
207        let (sender, receiver) = mpsc::channel::<AsyncLogType>();
208        
209        // 克隆 Quickwit 客户端配置,用于异步线程
210        let quickwit_config_clone = quickwit_config.clone();
211        
212        std::thread::spawn(move || {
213            // 在异步线程中创建 Quickwit 客户端
214            let quickwit_client = if let Some(config) = quickwit_config_clone {
215                match crate::quickwit::QuickwitClient::new(config) {
216                    Ok(client) => {
217                        if std::env::var("QUICKWIT_DEBUG").is_ok() {
218                            eprintln!("✓ 异步线程中 Quickwit 客户端创建成功");
219                        }
220                        Some(client)
221                    },
222                    Err(e) => {
223                        eprintln!("✗ 异步线程中 Quickwit 客户端创建失败: {}", e);
224                        None
225                    }
226                }
227            } else {
228                None
229            };
230            
231            loop {
232                match receiver.recv() {
233                    Ok(data) => match data {
234                        AsyncLogType::Message(msg) => {
235                            get_logger_plus().write(&msg);
236                            crate::utils::put_msg_to_cache(msg);
237                        }
238                        AsyncLogType::Flush => get_logger_plus().flush_inner(),
239                        AsyncLogType::QuickwitLog(log_entry) => {
240                            if let Some(ref client) = quickwit_client {
241                                match client.send_log(&log_entry) {
242                                    Ok(()) => {
243                                        if std::env::var("QUICKWIT_DEBUG").is_ok() {
244                                            eprintln!("✓ 异步模式:日志已发送到 Quickwit: {}", log_entry.message);
245                                        }
246                                    },
247                                    Err(e) => {
248                                        eprintln!("✗ 异步模式:发送日志到 Quickwit 失败: {}", e);
249                                        eprintln!("  日志内容: {}", log_entry.message);
250                                        eprintln!("  错误详情: {:?}", e);
251                                    }
252                                }
253                            }
254                        }
255                    },
256                    Err(e) => eprintln!("logger channel recv error: {}", e),
257                }
258            }
259        });
260        Some(sender)
261    } else {
262        None
263    };
264
265    let logger_data = LogData {
266        log_size,
267        console,
268        fileout,
269        sender,
270        plugin,
271    };
272
273    // 创建 Quickwit 客户端(如果配置了)
274    let quickwit_client = match quickwit_config {
275        Some(config) => {
276            if std::env::var("QUICKWIT_DEBUG").is_ok() {
277                eprintln!("正在创建 Quickwit 客户端,配置: {:?}", config);
278            }
279            match QuickwitClient::new(config) {
280                Ok(client) => {
281                    if std::env::var("QUICKWIT_DEBUG").is_ok() {
282                        eprintln!("✓ Quickwit 客户端创建成功");
283                    }
284                    Some(client)
285                },
286                Err(e) => {
287                    eprintln!("✗ Quickwit 客户端创建失败: {}", e);
288                    return Err(e);
289                }
290            }
291        },
292        None => {
293            if std::env::var("QUICKWIT_DEBUG").is_ok() {
294                eprintln!("未配置 Quickwit,跳过客户端创建");
295            }
296            None
297        },
298    };
299
300    let logger = LogPlus::new(
301        level,
302        log_file,
303        log_file_max,
304        filter,
305        logger_data,
306        show_process_id,
307        show_thread_info,
308        show_module_path,
309        highlight_keywords,
310        quickwit_client,
311    );
312
313    LOGGER_PLUS
314        .set(logger)
315        .map_err(|_| LogError::initialization_error("Logger already initialized"))?;
316
317    log::set_logger(get_logger_plus())
318        .map_err(|e| LogError::initialization_error(format!("Failed to set logger: {}", e)))?;
319
320    Ok(())
321}
322
323/// 获取全局日志器实例
324pub fn get_logger_plus() -> &'static LogPlus {
325    LOGGER_PLUS.get().expect("Logger not initialized")
326}
327
328/// 检查日志器是否已初始化
329pub fn is_initialized() -> bool {
330    LOGGER_PLUS.get().is_some()
331}
332
333/// 获取当前日志级别
334pub fn current_log_level() -> Option<log::LevelFilter> {
335    LOGGER_PLUS.get().map(|logger| logger.level)
336}