quantum_log/lib.rs
1//! QuantumLog - 高性能异步日志库
2//!
3//! QuantumLog 是一个专为高性能计算环境设计的异步日志库,
4//! 支持多种输出格式和目标,包括文件、数据库和标准输出。
5//!
6//! # 快速开始
7//!
8//! ```rust
9//! use quantum_log::{init, shutdown};
10//! use tracing::{info, warn, error};
11//!
12//! #[tokio::main]
13//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
14//! // 初始化 QuantumLog
15//! init().await?;
16//!
17//! // 使用标准的 tracing 宏
18//! info!("Application started");
19//! warn!("This is a warning");
20//! error!("This is an error");
21//!
22//! // 优雅关闭
23//! shutdown().await?;
24//! Ok(())
25//! }
26//! ```
27//!
28//! # 自定义配置
29//!
30//! ```rust
31//! use quantum_log::{QuantumLogConfig, init_with_config};
32//!
33//! #[tokio::main]
34//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
35//! let config = QuantumLogConfig {
36//! global_level: "DEBUG".to_string(),
37//! ..Default::default()
38//! };
39//!
40//! quantum_log::init_with_config(config).await?;
41//!
42//! // 你的应用代码...
43//!
44//! quantum_log::shutdown().await?;
45//! Ok(())
46//! }
47//! ```
48
49pub mod config;
50pub mod core;
51pub mod diagnostics;
52pub mod error;
53pub mod mpi;
54pub mod shutdown;
55pub mod sinks;
56pub mod utils;
57
58#[cfg(feature = "database")]
59pub mod database {
60 pub use crate::sinks::database::*;
61}
62
63pub use config::{
64 load_config_from_file, BackpressureStrategy, OutputFormat, QuantumLogConfig,
65 QuantumLoggerConfig, StdoutConfig,
66};
67pub use diagnostics::{get_diagnostics, DiagnosticsSnapshot};
68pub use error::{QuantumLogError, Result};
69pub use shutdown::{
70 ShutdownCoordinator, ShutdownHandle as QuantumShutdownHandle, ShutdownListener, ShutdownSignal,
71 ShutdownState,
72};
73
74pub use core::event::QuantumLogEvent;
75pub use core::subscriber::{BufferStats, QuantumLogSubscriber, QuantumLogSubscriberBuilder};
76
77use once_cell::sync::Lazy;
78use std::sync::{
79 atomic::{AtomicBool, Ordering},
80 Arc, Mutex,
81};
82// Initialize diagnostics
83use crate::diagnostics::init_diagnostics;
84
85/// 库版本
86pub const VERSION: &str = env!("CARGO_PKG_VERSION");
87
88/// 全局订阅器实例
89static GLOBAL_SUBSCRIBER: Lazy<Arc<Mutex<Option<QuantumLogSubscriber>>>> =
90 Lazy::new(|| Arc::new(Mutex::new(None)));
91
92/// QuantumLog 初始化标记
93/// 用于确保日志系统只被初始化一次
94pub static IS_QUANTUM_LOG_INITIALIZED: AtomicBool = AtomicBool::new(false);
95
96/// 使用默认配置初始化 QuantumLog
97///
98/// 这是一个便捷函数,使用默认配置初始化 QuantumLog。
99/// 默认配置包括:
100/// - 启用控制台输出
101/// - 日志级别为 INFO
102/// - 使用默认格式化器
103///
104/// # 示例
105///
106/// ```rust
107/// use quantum_log::init;
108///
109/// #[tokio::main]
110/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
111/// init().await?;
112/// tracing::info!("Hello, QuantumLog!");
113/// Ok(())
114/// }
115/// ```
116pub async fn init() -> Result<()> {
117 // Ensure diagnostics subsystem is initialized early
118 let _ = init_diagnostics();
119
120 let config = QuantumLogConfig {
121 pre_init_stdout_enabled: true,
122 stdout: Some(crate::config::StdoutConfig {
123 enabled: true,
124 ..Default::default()
125 }),
126 ..Default::default()
127 };
128
129 let mut subscriber = QuantumLogSubscriber::with_config(config)?;
130
131 // 初始化订阅器
132 subscriber.initialize().await?;
133
134 // 存储订阅器实例以便后续关闭
135 if let Ok(mut global) = GLOBAL_SUBSCRIBER.lock() {
136 *global = Some(subscriber.clone());
137 }
138
139 // 安装为全局订阅器
140 subscriber.install_global()?;
141
142 Ok(())
143}
144
145/// 使用指定配置初始化 QuantumLog
146///
147/// # 参数
148///
149/// * `config` - QuantumLog 配置
150///
151/// # 示例
152///
153/// ```rust
154/// use quantum_log::{QuantumLogConfig, init_with_config};
155///
156/// #[tokio::main]
157/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
158/// let config = QuantumLogConfig {
159/// global_level: "DEBUG".to_string(),
160/// ..Default::default()
161/// };
162///
163/// quantum_log::init_with_config(config).await?;
164/// quantum_log::shutdown().await?;
165/// Ok(())
166/// }
167/// ```
168pub async fn init_with_config(config: QuantumLogConfig) -> Result<()> {
169 // Ensure diagnostics subsystem is initialized early
170 let _ = init_diagnostics();
171
172 let mut subscriber = QuantumLogSubscriber::with_config(config)?;
173
174 // 初始化订阅器
175 subscriber.initialize().await?;
176
177 // 存储订阅器实例以便后续关闭
178 if let Ok(mut global) = GLOBAL_SUBSCRIBER.lock() {
179 *global = Some(subscriber.clone());
180 }
181
182 // 安装为全局订阅器(这会消费 subscriber)
183 subscriber.install_global()?;
184
185 Ok(())
186}
187
188/// 使用构建器初始化 QuantumLog
189///
190/// # 参数
191///
192/// * `builder_fn` - 构建器配置函数
193///
194/// # 示例
195///
196/// ```rust
197/// use quantum_log::{init_with_builder, shutdown};
198///
199/// #[tokio::main]
200/// async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
201/// init_with_builder(|builder| {
202/// builder
203/// .max_buffer_size(5000)
204/// .custom_field("service", "my-app")
205/// .custom_field("version", "1.0.0")
206/// }).await?;
207///
208/// shutdown().await?;
209/// Ok(())
210/// }
211/// ```
212pub async fn init_with_builder<F>(
213 builder_fn: F,
214) -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>>
215where
216 F: FnOnce(QuantumLogSubscriberBuilder) -> QuantumLogSubscriberBuilder,
217{
218 // Ensure diagnostics subsystem is initialized early
219 let _ = init_diagnostics();
220
221 let builder = QuantumLogSubscriber::builder();
222 let mut subscriber = builder_fn(builder).build()?;
223
224 // 初始化订阅器
225 subscriber.initialize().await?;
226
227 // 存储订阅器实例以便后续关闭
228 if let Ok(mut global) = GLOBAL_SUBSCRIBER.lock() {
229 *global = Some(subscriber.clone());
230 }
231
232 // 安装为全局订阅器(这会消费 subscriber)
233 subscriber.install_global()?;
234
235 Ok(())
236}
237
238/// 优雅关闭 QuantumLog
239///
240/// 这会关闭所有 sink 并等待它们完成处理所有待处理的事件。
241/// 建议在应用程序退出前调用此函数。
242///
243/// # 示例
244///
245/// ```rust
246/// use quantum_log::{init, shutdown};
247///
248/// #[tokio::main]
249/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
250/// init().await?;
251///
252/// // 你的应用代码...
253///
254/// shutdown().await?;
255/// Ok(())
256/// }
257/// ```
258pub async fn shutdown() -> Result<()> {
259 let subscriber = if let Ok(mut global) = GLOBAL_SUBSCRIBER.lock() {
260 global.take()
261 } else {
262 None
263 };
264
265 if let Some(subscriber) = subscriber {
266 subscriber.shutdown().await?;
267 }
268 Ok(())
269}
270
271/// 获取缓冲区统计信息
272///
273/// 返回当前预初始化缓冲区的统计信息,包括当前大小、丢弃的事件数量等。
274///
275/// # 示例
276///
277/// ```rust
278/// use quantum_log::{init, get_buffer_stats, shutdown};
279///
280/// #[tokio::main]
281/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
282/// init().await?;
283///
284/// let stats = get_buffer_stats();
285/// if let Some(stats) = stats {
286/// println!("Buffer size: {}, Dropped: {}", stats.current_size, stats.dropped_count);
287/// }
288///
289/// shutdown().await?;
290/// Ok(())
291/// }
292/// ```
293pub fn get_buffer_stats() -> Option<BufferStats> {
294 if let Ok(global) = GLOBAL_SUBSCRIBER.lock() {
295 global
296 .as_ref()
297 .map(|subscriber| subscriber.get_buffer_stats())
298 } else {
299 None
300 }
301}
302
303/// 检查 QuantumLog 是否已初始化
304///
305/// # 示例
306///
307/// ```rust
308/// use quantum_log::{init, is_initialized, shutdown};
309///
310/// #[tokio::main]
311/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
312/// assert!(!is_initialized());
313///
314/// init().await?;
315/// assert!(is_initialized());
316///
317/// shutdown().await?;
318/// Ok(())
319/// }
320/// ```
321pub fn is_initialized() -> bool {
322 if let Ok(global) = GLOBAL_SUBSCRIBER.lock() {
323 global
324 .as_ref()
325 .is_some_and(|subscriber| subscriber.is_initialized())
326 } else {
327 false
328 }
329}
330
331/// 获取当前配置的引用
332///
333/// 返回当前 QuantumLog 实例使用的配置。如果 QuantumLog 未初始化,返回 None。
334pub fn get_config() -> Option<QuantumLogConfig> {
335 if let Ok(global) = GLOBAL_SUBSCRIBER.lock() {
336 global
337 .as_ref()
338 .map(|subscriber| subscriber.config().clone())
339 } else {
340 None
341 }
342}
343
344// 外部依赖
345use tokio::sync::oneshot;
346
347/// 关闭句柄,用于优雅关闭日志系统
348#[derive(Debug)]
349pub struct ShutdownHandle {
350 sender: Option<oneshot::Sender<()>>,
351}
352
353impl ShutdownHandle {
354 /// 创建新的关闭句柄
355 pub fn new(sender: oneshot::Sender<()>) -> Self {
356 Self {
357 sender: Some(sender),
358 }
359 }
360
361 /// 触发优雅关闭
362 pub async fn shutdown(mut self) -> Result<()> {
363 if let Some(sender) = self.sender.take() {
364 sender.send(()).map_err(|_| {
365 QuantumLogError::ShutdownError("Failed to send shutdown signal".to_string())
366 })?;
367 }
368 Ok(())
369 }
370}
371
372/// 初始化 QuantumLog 日志系统
373///
374/// 这是设计文档中指定的主要初始化函数,它会:
375/// 1. 检查是否已经初始化,确保只初始化一次
376/// 2. 使用默认配置创建并初始化 QuantumLogSubscriber
377/// 3. 返回 ShutdownHandle 用于优雅关闭
378///
379/// # 返回值
380///
381/// 返回 `ShutdownHandle`,可用于优雅关闭日志系统
382///
383/// # 错误
384///
385/// 如果日志系统已经初始化,将返回错误
386///
387/// # 示例
388///
389/// ```rust
390/// use quantum_log::init_quantum_logger;
391///
392/// #[tokio::main]
393/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
394/// let shutdown_handle = init_quantum_logger().await?;
395///
396/// // 你的应用代码...
397///
398/// shutdown_handle.shutdown().await?;
399/// Ok(())
400/// }
401/// ```
402pub async fn init_quantum_logger() -> Result<ShutdownHandle> {
403 // Ensure diagnostics subsystem is initialized early
404 let _ = init_diagnostics();
405
406 // 检查是否已经初始化
407 if IS_QUANTUM_LOG_INITIALIZED
408 .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
409 .is_err()
410 {
411 return Err(QuantumLogError::InitializationError(
412 "QuantumLog has already been initialized".to_string(),
413 ));
414 }
415
416 // 创建默认配置的订阅器
417 let mut subscriber = QuantumLogSubscriber::new().map_err(|e| {
418 QuantumLogError::InitializationError(format!("Failed to create subscriber: {}", e))
419 })?;
420
421 // 初始化订阅器
422 subscriber.initialize().await.map_err(|e| {
423 QuantumLogError::InitializationError(format!("Failed to initialize subscriber: {}", e))
424 })?;
425
426 // 创建关闭通道
427 let (shutdown_sender, shutdown_receiver) = oneshot::channel();
428
429 // 克隆订阅器用于关闭任务
430 let subscriber_for_shutdown = subscriber.clone();
431
432 // 保存订阅器到全局状态
433 if let Ok(mut global) = GLOBAL_SUBSCRIBER.lock() {
434 *global = Some(subscriber.clone());
435 } else {
436 // 如果获取锁失败,重置初始化标记
437 IS_QUANTUM_LOG_INITIALIZED.store(false, Ordering::SeqCst);
438 return Err(QuantumLogError::InitializationError(
439 "Failed to acquire global subscriber lock".to_string(),
440 ));
441 }
442
443 // 安装为全局订阅器
444 if let Err(e) = subscriber.install_global() {
445 // 如果安装失败,清理状态
446 IS_QUANTUM_LOG_INITIALIZED.store(false, Ordering::SeqCst);
447 if let Ok(mut global) = GLOBAL_SUBSCRIBER.lock() {
448 *global = None;
449 }
450 return Err(QuantumLogError::InitializationError(format!(
451 "Failed to install global subscriber: {}",
452 e
453 )));
454 }
455
456 // 启动关闭监听任务
457 tokio::spawn(async move {
458 if shutdown_receiver.await.is_ok() {
459 // 执行优雅关闭
460 if let Err(e) = subscriber_for_shutdown.shutdown().await {
461 eprintln!("Error during shutdown: {}", e);
462 }
463 // 重置初始化标记
464 IS_QUANTUM_LOG_INITIALIZED.store(false, Ordering::SeqCst);
465 // 清理全局订阅器
466 if let Ok(mut global) = GLOBAL_SUBSCRIBER.lock() {
467 *global = None;
468 }
469 }
470 });
471
472 Ok(ShutdownHandle::new(shutdown_sender))
473}