captains_log/lib.rs
1//! # captains-log
2//!
3//! A light-weight logger for rust, implementation base on the crate `log`.
4//!
5//! ## Features
6//!
7//! * Allow customize log format and time format.
8//!
9//! * Supports signal listening for log-rotate.
10//!
11//! * Supports multiple log files, each with its own log level.
12//!
13//! * Supports hook on panic.
14//!
15//! * On default supports multi-process/thread/coroutine log into the same file.
16//! Atomic line appending can be done on Linux
17//!
18//! * Provides `LogFilter` for fine-grain control to log level.
19//!
20//! * Provides `LogFilterKV` for API logging with additional key.
21//! For example, you can set req_id in LogFilterKV, and track the
22//! complete request handling procedure from log.
23//!
24//! * For test suits usage:
25//!
26//! Allow dynamic reconfigure logger setting in different test function.
27//!(NOTE: currently signal_listener does not support reconfigure).
28//!
29//! Provides an attribute macro #\[logfn\] to wrap test function.
30//! Logging test-start and test-end.
31
32//!
33//! ## Dependency
34//!
35//! ``` toml
36//! [dependencies]
37//! log = { version = "0.4", features = ["std", "kv_unstable"] }
38//! captains_log = "0.2"
39//! ```
40//!
41//! ## Fast setup example:
42//!
43//! <font color=Blue>Refer to recipe in `recipe` module, including console & file output. </font>
44//!
45//! ```rust
46//! // #[macro_use]
47//! // extern crate captains_log;
48//! // #[macro_use]
49//! // extern crate log;
50//! use log::{debug, info, error};
51//! use captains_log::recipe::split_error_file_logger;
52//!
53//! let log_builder = split_error_file_logger("/tmp", "test", log::Level::Debug);
54//! log_builder.build();
55//!
56//! // non-error msg will only appear in /tmp/test.log
57//! debug!("Set a course to Sol system");
58//! info!("Engage");
59//!
60//! // will appear in both /tmp/test.log and /tmp/test.log.wf
61//! error!("Engine over heat!");
62//!
63//! ```
64//!
65//! ## Customize format example
66//!
67//! ``` rust
68//! extern crate signal_hook;
69//! extern crate chrono;
70//! use captains_log::*;
71
72//! fn format_f(r: FormatRecord) -> String {
73//! let time = r.time();
74//! let level = r.level();
75//! let file = r.file();
76//! let line = r.line();
77//! let msg = r.msg();
78//! format!("{time}|{level}|{file}:{line}|{msg}\n").to_string()
79//! }
80//! let debug_format = LogFormat::new(
81//! "%Y%m%d %H:%M:%S%.6f",
82//! format_f,
83//! );
84//! let debug_file = LogFile::new(
85//! "/tmp", "test.log", log::Level::Trace, debug_format);
86//! let config = Builder::default()
87//! .signal(signal_hook::consts::SIGINT)
88//! .file(debug_file);
89//!
90//! config.build();
91//! ```
92//!
93//! ## Fine-grain module-level log control
94//!
95//! Place LogFilter in Arc and share among coroutines.
96//! Log level can be changed on-the-fly.
97//!
98//! ``` rust
99//! use std::sync::Arc;
100//! use captains_log::*;
101//! log::set_max_level(log::LevelFilter::Debug);
102//! let logger_io = Arc::new(LogFilter::new());
103//! let logger_req = Arc::new(LogFilter::new());
104//! logger_io.set_level(log::Level::Error);
105//! logger_req.set_level(log::Level::Debug);
106//! logger_debug!(logger_req, "Begin handle req ...");
107//! logger_debug!(logger_io, "Issue io to disk ...");
108//! logger_error!(logger_req, "Req invalid ...");
109//!
110//! ```
111//!
112//! ## API-level log handling
113//!
114//! Request log can be track by custom key `req_id`, which kept in LogFilterKV.
115//!
116//! ``` rust
117//! use captains_log::*;
118//! fn debug_format_req_id_f(r: FormatRecord) -> String {
119//! let time = r.time();
120//! let level = r.level();
121//! let file = r.file();
122//! let line = r.line();
123//! let msg = r.msg();
124//! let req_id = r.key("req_id");
125//! format!("[{time}][{level}][{file}:{line}] {msg}{req_id}\n").to_string()
126//! }
127//! let builder = recipe::file_logger_custom("/tmp", "log_filter", log::Level::Debug,
128//! recipe::DEFAULT_TIME, debug_format_req_id_f);
129//! builder.build().expect("setup_log");
130//! let logger = LogFilterKV::new("req_id", format!("{:016x}", 123).to_string());
131//! logger_debug!(logger, "Req / received");
132//! logger_debug!(logger, "header xxx");
133//! logger_info!(logger, "Req / 200 complete");
134//!
135//! ```
136
137extern crate captains_log_helper;
138extern crate log;
139extern crate signal_hook;
140
141#[macro_use]
142extern crate enum_dispatch;
143
144mod config;
145mod console_impl;
146mod file_impl;
147mod formatter;
148mod log_impl;
149mod time;
150
151pub mod macros;
152pub mod recipe;
153
154mod log_filter;
155
156pub use self::{config::*, formatter::FormatRecord, log_filter::*, log_impl::setup_log};
157pub use captains_log_helper::logfn;
158
159#[cfg(test)]
160mod tests;