0.2.1 |
|
---|---|
0.2.0 |
|
0.1.2 |
|
0.1.1 |
|
0.1.0 |
|
#303 in #logger
86KB
nolog-plain 日志记录器
20行代码,无依赖。
一个用于写入文件的简单 nolog 日志记录器的非彩色版本。如果您需要彩色输出,请参考 nolog 包(有相同的20行代码,但带有彩色输出)。
- 支持命名格式参数
info!("{line_count} lines.");
。 - 显示代码位置
[src/main.rs 15:5]
。 - 易于添加时间戳
[2022-07-10 06:49:33.646361181 UTC]
。 - 在发布构建中自动禁用
cargo run --release
。您可以修改代码来禁用此功能。请参阅“如果您不需要在发布构建中禁用日志”部分。 - 与
log
包具有相同的语法。随着项目的增长,可以在不更改代码的情况下迁移到高级日志记录器(使用log
包外观)。 - 可以直接构建到项目中,而不是作为依赖项。
- 使用Rust的内置宏。
- 易于修改以重定向日志输出(到
stderr
或file
)。 - MIT 许可证。
将 nolog-plain 作为文件日志记录的依赖项
在 Cargo.toml
nolog-plain = "0.2.1"
下载下面的示例
git clone https://github.com/vglinka/nolog-plain
cd ./nolog-plain/
cargo run --example base
cargo run --example to-file
cargo run --example to-stderr
cargo run --example to-file-debug-plus-release
cargo run --example to-file-debug-plus-release --release
cd ./examples/as-dep-to-file-timestamp-chrono/
cargo run
cd ./examples/as-dep-to-file/
cargo run
logger.rs
:
/* ----------------------------------------------------------------------------
MIT License
Copyright (c) 2022 Vadim Glinka
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---------------------------------------------------------------------------- */
pub use nolog_plain::{crit, debug, error, info, trace, warn /* writelog */};
// We don't import writelog because we want to override it --- ^^^^^^^^
#[rustfmt::skip] #[macro_export] #[cfg(debug_assertions)] macro_rules!
writelog { ( $msg:expr ) => { log($msg) } }
// ^^^
// function `log` instead of `println` macro.
use std::fmt::Arguments;
use std::fs::OpenOptions;
use std::io::{BufWriter, Write};
use std::path::PathBuf;
pub struct LogFile;
impl LogFile {
pub fn path() -> PathBuf {
PathBuf::from("log.txt")
}
}
#[rustfmt::skip]
pub fn log(msg: Arguments) {
// ^^^^^^^^^ std::fmt::Arguments
let path = LogFile::path();
let open_file = |path| { OpenOptions::new()
.create(true)
.write(true)
.append(true)
.open(&path)
};
if let Ok(file) = open_file(path) {
let mut buf = BufWriter::new(file);
writeln!(buf, "{msg}").ok();
buf.flush().ok();
};
}
main.rs
:
mod logger;
use crate::logger::*;
// ^^^^^^^^^
// It must be imported in each module in which we will use logging.
use std::fs::OpenOptions;
use std::io;
use std::io::prelude::*;
fn main() -> io::Result<()> {
let path = LogFile::path();
let mut file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.truncate(true)
//^^^^^^^ truncate the file to 0 length if it already exists.
.open(&path)?;
let a = 42;
trace!("text {a},{a},{a}");
debug!("text {a},{},{}", a, 24);
info!("text {},{},{}", a, 24, "42");
warn!("text {a},{},{}", 'a', "422");
error!("text {a},{a},{}", a);
crit!("text {a},{a},{a}");
let mut contents = String::new();
file.read_to_string(&mut contents)?;
println!("-- In {path:?} --");
println!("{contents}");
/* Output:
-- In "log.txt" --
TRCE: text 42,42,42 [src/main.rs 29:5]
DEBG: text 42,42,24 [src/main.rs 30:5]
INFO: text 42,24,42 [src/main.rs 31:5]
WARN: text 42,a,422 [src/main.rs 32:5]
ERRO: text 42,42,42 [src/main.rs 33:5]
CRIT: text 42,42,42 [src/main.rs 34:5]
*/
Ok(())
}
直接使用 nolog-plain
同样的事情,只是在 Cargo.toml
中我们不添加 nolog-plain
作为依赖,在 logger.rs
中我们复制这个库的全部代码(所有20行)
/* ----------------------------------------------------------------------------
MIT License
Copyright (c) 2022 Vadim Glinka
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---------------------------------------------------------------------------- */
#[rustfmt::skip] #[macro_export] #[cfg(debug_assertions)] macro_rules!
trace { ( $($msg:expr),* ) => { writelog!(format_args!("TRCE: {} [{} {}:{}]", format_args!($($msg),*), file!(), line!(), column!())) } }
#[rustfmt::skip] #[macro_export] #[cfg(debug_assertions)] macro_rules!
debug { ( $($msg:expr),* ) => { writelog!(format_args!("DEBG: {} [{} {}:{}]", format_args!($($msg),*), file!(), line!(), column!())) } }
#[rustfmt::skip] #[macro_export] #[cfg(debug_assertions)] macro_rules!
info { ( $($msg:expr),* ) => { writelog!(format_args!("INFO: {} [{} {}:{}]", format_args!($($msg),*), file!(), line!(), column!())) } }
#[rustfmt::skip] #[macro_export] #[cfg(debug_assertions)] macro_rules!
warn { ( $($msg:expr),* ) => { writelog!(format_args!("WARN: {} [{} {}:{}]", format_args!($($msg),*), file!(), line!(), column!())) } }
#[rustfmt::skip] #[macro_export] #[cfg(debug_assertions)] macro_rules!
error { ( $($msg:expr),* ) => { writelog!(format_args!("ERRO: {} [{} {}:{}]", format_args!($($msg),*), file!(), line!(), column!())) } }
#[rustfmt::skip] #[macro_export] #[cfg(debug_assertions)] macro_rules!
crit { ( $($msg:expr),* ) => { writelog!(format_args!("CRIT: {} [{} {}:{}]", format_args!($($msg),*), file!(), line!(), column!())) } }
#[rustfmt::skip] #[macro_export] #[cfg(not(debug_assertions))] macro_rules! trace { ( $($msg:expr),* ) => () }
#[rustfmt::skip] #[macro_export] #[cfg(not(debug_assertions))] macro_rules! debug { ( $($msg:expr),* ) => () }
#[rustfmt::skip] #[macro_export] #[cfg(not(debug_assertions))] macro_rules! info { ( $($msg:expr),* ) => () }
#[rustfmt::skip] #[macro_export] #[cfg(not(debug_assertions))] macro_rules! warn { ( $($msg:expr),* ) => () }
#[rustfmt::skip] #[macro_export] #[cfg(not(debug_assertions))] macro_rules! error { ( $($msg:expr),* ) => () }
#[rustfmt::skip] #[macro_export] #[cfg(not(debug_assertions))] macro_rules! crit { ( $($msg:expr),* ) => () }
#[rustfmt::skip] #[macro_export] #[cfg(debug_assertions)] macro_rules!
writelog { ( $msg:expr ) => { log($msg) } }
// ^^^
// function `log` instead of `println` macro.
use std::fmt::Arguments;
use std::fs::OpenOptions;
use std::io::{BufWriter, Write};
use std::path::PathBuf;
pub struct LogFile;
impl LogFile {
pub fn path() -> PathBuf {
PathBuf::from("log.txt")
}
}
#[rustfmt::skip]
pub fn log(msg: Arguments) {
// ^^^^^^^^^ std::fmt::Arguments
let path = LogFile::path();
let open_file = |path| { OpenOptions::new()
.create(true)
.write(true)
.append(true)
.open(&path)
};
if let Ok(file) = open_file(path) {
let mut buf = BufWriter::new(file);
writeln!(buf, "{msg}").ok();
buf.flush().ok();
};
}
现在你有了日志记录器,没有新的依赖。
如何添加时间戳
例如,我们将使用 chrono crate。
-- In "log.txt" --
[2022-07-10 06:49:33.646361181 UTC] TRCE: text 42,42,42 [src/main.rs 22:5]
[2022-07-10 06:49:33.646393648 UTC] DEBG: text 42,42,24 [src/main.rs 23:5]
[2022-07-10 06:49:33.646405179 UTC] INFO: text 42,24,42 [src/main.rs 24:5]
[2022-07-10 06:49:33.646415125 UTC] WARN: text 42,a,422 [src/main.rs 25:5]
[2022-07-10 06:49:33.646424722 UTC] ERRO: text 42,42,42 [src/main.rs 26:5]
[2022-07-10 06:49:33.646434216 UTC] CRIT: text 42,42,42 [src/main.rs 27:5]
如果你不需要在发布构建中禁用日志记录
这将使代码更加简洁
/* ----------------------------------------------------------------------------
MIT License
Copyright (c) 2022 Vadim Glinka
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---------------------------------------------------------------------------- */
#[rustfmt::skip] #[macro_export] macro_rules!
trace { ( $($msg:expr),* ) => { writelog!(format_args!("TRCE: {} [{} {}:{}]", format_args!($($msg),*), file!(), line!(), column!())) } }
#[rustfmt::skip] #[macro_export] macro_rules!
debug { ( $($msg:expr),* ) => { writelog!(format_args!("DEBG: {} [{} {}:{}]", format_args!($($msg),*), file!(), line!(), column!())) } }
#[rustfmt::skip] #[macro_export] macro_rules!
info { ( $($msg:expr),* ) => { writelog!(format_args!("INFO: {} [{} {}:{}]", format_args!($($msg),*), file!(), line!(), column!())) } }
#[rustfmt::skip] #[macro_export] macro_rules!
warn { ( $($msg:expr),* ) => { writelog!(format_args!("WARN: {} [{} {}:{}]", format_args!($($msg),*), file!(), line!(), column!())) } }
#[rustfmt::skip] #[macro_export] macro_rules!
error { ( $($msg:expr),* ) => { writelog!(format_args!("ERRO: {} [{} {}:{}]", format_args!($($msg),*), file!(), line!(), column!())) } }
#[rustfmt::skip] #[macro_export] macro_rules!
crit { ( $($msg:expr),* ) => { writelog!(format_args!("CRIT: {} [{} {}:{}]", format_args!($($msg),*), file!(), line!(), column!())) } }
#[rustfmt::skip] #[macro_export] macro_rules!
writelog { ( $msg:expr ) => { println!("{}", $msg) } }
变更日志
- 0.2.1 – 修改了
README.md
和示例。 - 0.2.0 – 将宏调用
format!()
替换为调用format_args!()
,因为format_args!()
避免了堆分配。所有示例都已更新。使用std::fmt::Arguments
替代了String
。请参阅 示例。 - 0.1.2 – 修改了
README.md
和示例。 - 0.1.1 – 修改了
README.md
和示例。