emabee / flexi_logger Goto Github PK
View Code? Open in Web Editor NEWA flexible logger for rust programs that can write to stderr, stdout, and/or to log files
License: Apache License 2.0
A flexible logger for rust programs that can write to stderr, stdout, and/or to log files
License: Apache License 2.0
My application uses slog
and would like to replace with flexi_logger
so log-rotation can be supported without using external utility.
_rCURRENT
? In my current implementation, log files are rotated (using Logrotate linux util) as kdb.log, kdb-1.log, kdb-2.logPrepare empty /non-empty log files etc before logger is initialized and verify correct behavior afterwards.
One feature that could get added is Criterion::AgeOrSize(age, u64)
where log rotation would happen when either the file has become older than the specified age, or it has exceeded the size specified in bytes.
Hi,
I've been turning this one around from one side to another and seem not to be able to get it right...
The objective was to customize formatting such as to get the with_thread
formatting version minus the timestamp being logged to stderr. This because it is being logged through systemd (by capture of stdout/stderr), which already keeps track of the date and time, prepending it already... so if I go for the build-in with_thread
formatter, the timestamp ends up being printed twice in each line.
My attempt; (copy&paste with_thread
and modify...)
pub fn formatter(w: &mut Write, record: &LogRecord) -> Result<(), IoError>
{
write!(
w,
"T[{:?}] {} [{}:{}] {}",
thread::current().name().unwrap_or("<unnamed>"),
record.level(),
record.file().unwrap_or("<unnamed>"),
record.line().unwrap_or(0),
&record.args()
)
}
...and the venerable main...
fn main()
{
Logger::with_env_or_str("info")
.format(formatter)
.start()
.unwrap_or_else(|e| panic!("Logger initialization failed with {}", e));
}
But to no avail. What am I doing wrong?
Any help would be much appreciated.
Best regards,
lwk
I switch from slog_async to flexi_logger and lost ~20% throughput. The log level is set to info and less than 10 lines are logged per second. Any reason for this performance drop?
I suspect few things but please help me here.
slog = { version = "2.5.2", features = ["max_level_trace", "release_max_level_info"] }
but this is not supported by flexi_logger. I did use log level features as below.
log = { version = "0.4.11", features = ["max_level_trace", "release_max_level_info"] }
I seem to be running into a strange issue. When I first start up my program, with an empty logs folder, it creates babblebot_rCURRENT.log
and logs to the file. If I stop my program, and start it again, I now see babblebot_r00000.log
and babblebot_rCURRENT.log
in my logs folder, but both are completely blank and no new output is appended. I still see log output in stdout.
Hi,
It looks like the Crates.io version is 15.5, but this repo's version is still 15.4 :)
I'm trying to log things to a file, stderr, and stdout at the same time.
To do that I must create a new writer for Stdout which I've done this way:
struct StdoutWriter {
format: FormatFunction,
log_level: log::LevelFilter
}
impl StdoutWriter {
fn new(format: FormatFunction, log_level: LevelFilter) -> Self {
StdoutWriter { format, log_level}
}
}
impl LogWriter for StdoutWriter {
#[inline]
fn write(&self, now: &mut DeferredNow, record: &Record) -> std::io::Result<()> {
(self.format)(&mut std::io::stdout(), now, record)
}
fn flush(&self) -> std::io::Result<()> {
std::io::stdout().flush()
}
fn max_log_level(&self) -> log::LevelFilter {
self.log_level
}
}
However, I was wondering if flexi_logger couldn't expose the StdoutWriter
that it already uses internally (as a Primary Writer), to make that easier.
Or maybe I'm missing something :)
Thanks!
Please add compatibility with multi_log:
https://docs.rs/multi_log/0.1.2/multi_log
That would allow me to use flexi_logger with winlog (Windows Event Logger).
Right now start() calls log::set_boxed_logger() itself. It would be great if there was a function that returned the set_boxed_logger() parameter instead of calling the function, so that the users could call set_boxed_logger() themselves, allowing multi_log to work.
Hi,
Thanks for creating 'flexi_logger'!
For some reason, I don't get any colored output with the default settings (or any other settings I tried).
When I run cargo run --example colors
, however, I get colored output (the output of Cargo is colored, as well).
Do you have any idea what the problem could be?
I'm using flexi_logger = "0.15.12"
in Cargo.toml (so the "colors" feature is activated), and besides the defaults I have tested the following:
let logger_config = "warn, main=trace, devtools_protocol_client=trace";
flexi_logger::Logger::with_str(logger_config)
.check_parser_error()
.expect("Logger config string formatted incorrectly")
.log_target(flexi_logger::LogTarget::StdOut)
.format_for_stdout(flexi_logger::colored_detailed_format)
.format_for_stderr(flexi_logger::colored_detailed_format)
.start()
.expect("Failed to start logger");
It would be nice if it somehow would be possible to activate colored output, because 'flexi_logger' looks really nice :)
LogConfig defaults timestamp to true and the Logger api only allows to set timestamp to true.
Hi,
it would be nice to be able to opt-in colored output.
If you need suggestions, ping me!
For a custom LogWriter
I am currently writing it would be easier to have a &mut self
for write
. What is the rational behind making it immutable?
Hi,
My program uses flexi_logger with a specfile. But, if I launch 2 instances in parallel, the second one does not enable logging and fails with: "Filesystem notifications for the specfile could not be set up".
I think it should be possible to run 2 instances with the same configuration without specfile filesystem notifications. Perhaps add an option to disable the "automatic reloading at runtime" feature?
Thanks!
When initializing flexi_logger with an initial logspec like "info", and configuring it to use an already existing specfile that uses more trace levels (e.g. including "debug" and "trace2), then the additional trace levels do not become effective (in the example only "error", "warn" and "info" will be printed.
I was using env_logger
and doing something like this:
let mut builder = env_logger::Builder::new();
builder.parse_filters("my-target=trace");
builder.try_init().unwrap();
trace!(target: "my-target", "this gets logged!");
As you can see, I setting a specific loglevel for a specific target. Quite handy for debugging!
I've been trying a way to do that with flexi_logger, but I haven't managed to succeed.
let spec = LogSpecification::parse("my-target=trace").unwrap();
Logger::with(spec).start().unwrap();
trace!(target: "my-target", "this doesn't get logged!");
As you can see there are two problems:
LogSpecification::parse("my-target=trace").unwrap()
will panic because hyphens are not allowed (but they are allowed as target by log
)my_target=trace
and trace!(target: "my_target", ...)
, nothing gets logged.I think there's a way around using a new writer
as described in the docs.
However this solution is cumbersome: imagine the use case where you want users to pass different targets via a CLI interface (--log 'my_target=trace, my_other_target=info
).
I'm not sure however whether or not this feature could get easily implemented in flexi_logger. :)
This method expects a path, so it makes sense to use PathBuf
and not String
Line 356 in 2757e79
Follow-up on #47 .
Currently, one can write this:
.log_target(LogTarget::File)
.duplicate_to_stderr(Duplicate::All)
.duplicate_to_stdout(Duplicate::Info)
However, stderr and stdout use the same format. If stderr is pointing to a file, this means that either stdout will be colorless, or that your file will contain colors.
A good thing to do would be to allow users to specify two different formats for stdout and stderr.
See [this comment] :)
Title says it all :) I can use tail -f
, but it'd be nice if I needn't too. There's functionality for duplicated logs to stdout, but that won't work for my use-case, because stdout needs to be valid JSON.
Oh, and thanks for writing the library, it's really awesome!
I implemented a simple change for default appending to a log file instead of default overwriting: max-b@d3c3804
I don't know if you would want to add this optionally with some configuration instead.
Not a bug report but an end-user question:
Sometimes my program or my test seems to have ended already before all has been logged. The symptom is that sometimes the last few logging records are missing.
What should I do? Somehow get the logging thread then wait for it to end?
I tried thread::yield_now()
, thread::sleep()
, io::stderr().lock().flush()
, etc., but sometimes records are still missing. Often an additional strategic dummy info!()
somewhere helps.
When quit the application by std::process::exit(0),flexi_logger will be crashed with core dump as bellow.
[2019-08-21 07:07:38.330857 +08:00] INFO [ns_nice/src/web_server.rs:87] Start web server.
^Cthread '' panicked at 'cannot access stderr during shutdown', src/libcore/option.rs:1034:5
stack backtrace:
0: 0x55878d11bc8b - backtrace::backtrace::libunwind::trace::hfe5db90796807973
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.29/src/backtrace/libunwind.rs:88
1: 0x55878d11bc8b - backtrace::backtrace::trace_unsynchronized::h34b865a835594335
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.29/src/backtrace/mod.rs:66
2: 0x55878d11bc8b - std::sys_common::backtrace::_print::h527254ae44989167
at src/libstd/sys_common/backtrace.rs:47
3: 0x55878d11bc8b - std::sys_common::backtrace::print::he85dd5ddddf46503
at src/libstd/sys_common/backtrace.rs:36
4: 0x55878d11bc8b - std::panicking::default_hook::{{closure}}::h847a2eb38b396f14
at src/libstd/panicking.rs:200
5: 0x55878d11b967 - std::panicking::default_hook::h2ca0f9a30a0e206b
at src/libstd/panicking.rs:214
6: 0x55878d11c400 - std::panicking::rust_panic_with_hook::hffcefc09751839d1
at src/libstd/panicking.rs:477
7: 0x55878d11bf82 - std::panicking::continue_panic_fmt::hc0f142c930c846fc
at src/libstd/panicking.rs:384
8: 0x55878d11be66 - rust_begin_unwind
at src/libstd/panicking.rs:311
9: 0x55878d13961d - core::panicking::panic_fmt::h2daf88b2616ca2b2
at src/libcore/panicking.rs:85
10: 0x55878d139687 - core::option::expect_failed::h4b77ebe6e62ec3a1
at src/libcore/option.rs:1034
11: 0x55878d111fe5 - core::option::Option::expect::h5a6ae296007c8783
at /rustc/eae3437dfe991621e8afdc82734f4a172d7ddf9b/src/libcore/option.rs:314
12: 0x55878d111fe5 - std::io::stdio::stderr::h4547669837e9df0d
at src/libstd/io/stdio.rs:629
13: 0x55878ce5293a - flexi_logger::primary_writer::StdErrWriter::write::h4c538220bc2b5d9a
at /home/gary/.cargo/registry/src/github.com-1ecc6299db9ec823/flexi_logger-0.14.1/src/primary_writer.rs:82
14: 0x55878ce52778 - flexi_logger::primary_writer::PrimaryWriter::write::haa0c9f6ce84cc295
at /home/gary/.cargo/registry/src/github.com-1ecc6299db9ec823/flexi_logger-0.14.1/src/primary_writer.rs:47
Hi,
I'm a little at loss on why this might be...
This works perfectly fine:
Logger::with_env_or_str("mymod1=info, mymod2=error")
.start()
.unwrap_or_else(|e| panic!("Logger initialization failed with {}", e));
Expected and get; mymod1 logs at level info and mymod2 at level error unless I override the string default with the RUST_LOG="info, ..." which in turn also does work perfectly as expected.
However:
Logger::with_env_or_str("mymod1=info, mymod2=error")
.format(opt_format)
.start()
.unwrap_or_else(|e| panic!("Logger initialization failed with {}", e));
Expected same as above but with changed formatting (tried with detailed_format and opt_format).
What I get instead is no output at all. Unless I specify "info, mymod1=info, mymod2=error" in which case I get the intended behaviour parsed from the string (everything: info, mymod1: info, mymod2: error). Also works if I specify via RUST_LOG. But on not passing the leading "info, " string does not get parsed as expected.
Any ideas why this might be happening?
Best regards,
lwk
Hey!
Thanks for writing this library and making it available!
I've run into a problem. I run a project on a raspberry pi, which has a bunch of threads that e.g. poll some attached hardware for changes. For debugging, I log the raw values they get, among other things. All my logs are written to files and everything above warnings is copied to stderr.
The problem is this: I set up log rotation, keeping 5 plain-text files and 30 zipped ones. They fill up quite quickly with debug logging on, but that's not surprising. Now, whenever the logs are rotated and an old one is zipped, nothing can log anymore for as long as that takes.
Let me illustrate with a bunch of logs :) This is a fresh start, with no log files, so five plain text files are produced (this doesn't take long), and then later one file is zipped (this takes a while):
Log is written to logs/raspitest_rCURRENT.log
Server is listening on: http://[::1]:3000
[2020-01-29 14:05:40.745225 +00:00] WARN [raspitest::pca9685_sync] src\pca9685_sync.rs:87: took too long, lagging 2918µs behind
[2020-01-29 14:05:40.752097 +00:00] WARN [raspitest::pca9685_sync] src\pca9685_sync.rs:87: took too long, lagging 1558µs behind
[2020-01-29 14:05:40.760958 +00:00] WARN [raspitest::pca9685_sync] src\pca9685_sync.rs:87: took too long, lagging 3750µs behind
[2020-01-29 14:05:40.777664 +00:00] WARN [raspitest::pca9685_sync] src\pca9685_sync.rs:87: took too long, lagging 1387µs behind
[2020-01-29 14:05:40.792007 +00:00] WARN [raspitest::pca9685_sync] src\pca9685_sync.rs:87: took too long, lagging 2462µs behind
[2020-01-29 14:05:40.894974 +00:00] WARN [raspitest::dht22] src\dht22.rs:96: unable to read from pin 26: Checksum
Log is written to logs/raspitest_rCURRENT.log
[2020-01-29 14:05:41.895071 +00:00] WARN [raspitest::pca9685_sync] src\pca9685_sync.rs:87: took too long, lagging 101µs behind
[2020-01-29 14:05:42.988239 +00:00] WARN [raspitest::pca9685_sync] src\pca9685_sync.rs:87: took too long, lagging 7554µs behind
[2020-01-29 14:05:44.185762 +00:00] WARN [raspitest::pca9685_sync] src\pca9685_sync.rs:87: took too long, lagging 406µs behind
[2020-01-29 14:05:44.421706 +00:00] WARN [raspitest::pca9685_sync] src\pca9685_sync.rs:87: took too long, lagging 1663µs behind
Log is written to logs/raspitest_rCURRENT.log
[2020-01-29 14:05:47.943784 +00:00] WARN [raspitest::pca9685_sync] src\pca9685_sync.rs:87: took too long, lagging 215µs behind
Log is written to logs/raspitest_rCURRENT.log
[2020-01-29 14:05:49.726632 +00:00] WARN [raspitest::pca9685_sync] src\pca9685_sync.rs:87: took too long, lagging 259µs behind
[2020-01-29 14:05:49.740501 +00:00] WARN [raspitest::pca9685_sync] src\pca9685_sync.rs:87: took too long, lagging 22µs behind
[2020-01-29 14:05:49.756751 +00:00] WARN [raspitest::pca9685_sync] src\pca9685_sync.rs:87: took too long, lagging 1068µs behind
[2020-01-29 14:05:50.273502 +00:00] WARN [raspitest::mcp23017_input] src\mcp23017_input.rs:131: took too long, lagging 4147µs behind
[2020-01-29 14:05:50.274273 +00:00] WARN [raspitest::pca9685_sync] src\pca9685_sync.rs:87: took too long, lagging 2994µs behind
Log is written to logs/raspitest_rCURRENT.log
[2020-01-29 14:05:52.989480 +00:00] WARN [raspitest::pca9685_sync] src\pca9685_sync.rs:87: took too long, lagging 1677µs behind
[2020-01-29 14:05:55.467321 +00:00] WARN [raspitest::pca9685_sync] src\pca9685_sync.rs:87: took too long, lagging 294µs behind
Log is written to logs/raspitest_rCURRENT.log
[2020-01-29 14:05:57.984365 +00:00] WARN [raspitest::pca9685_sync] src\pca9685_sync.rs:87: took too long, lagging 4783µs behind
Log is written to logs/raspitest_rCURRENT.log
[2020-01-29 14:06:04.791070 +00:00] WARN [raspitest::mcp23017_input] src\mcp23017_input.rs:131: took too long, lagging 4856814µs behind
[2020-01-29 14:06:04.792825 +00:00] WARN [raspitest::pca9685_sync] src\pca9685_sync.rs:87: took too long, lagging 4864683µs behind
I run these things pretty close to their limit, so they're always lagging a bit behind. But note how, after the last rotation, they lag behind a lot. I suspect this is because they tried to debug-log something, but got blocked.
Do you think I got the problem about right?
The obvious solution for me, for now, is to not debug-log (at least in production 😄 ). Long-term: Can we maybe move the zipping to another thread?
Best,
Logger::start_with_specfile() returns before the specfile is read and evaluated.
Currently when using a file target flexi_logger creates the log file on initialization. My app doesn't print a lot of logs by default so that means an empty file is created for every run. Would it be possible to at least add an option to create the file only when needed? (i.e. the first time a log line is printed)
Is it possible to rotate logs based on time rather than size? (ex. rotate daily instead of rotating once it reaches a certain size). This is a pretty common logging practice and I only see size in the docs.
Since I upgraded from 0.6.14 to 0.7.0, I'm getting a file created although I only want logging to stdout. The file is however empty. It's named like this:
wong_2018-03-06_19-09-44.log
I've double checked, and downgrading to 0.6.14 works, the file is not created anymore.
This is my init:
let log_level = match matches.occurrences_of("verbosity") {
0 => flexi_logger::Level::Info,
1 => flexi_logger::Level::Debug,
_ => flexi_logger::Level::Trace,
};
let log_spec = flexi_logger::LogSpecBuilder::new()
.default(flexi_logger::Level::Info.to_level_filter())
.module("wong", log_level.to_level_filter())
.build();
flexi_logger::Logger::with(log_spec)
.format(log_format)
.start()
.unwrap();
It's a bit of a pain that these just silently fall back to some default log spec. If I start a long-running process (months long), I want it to die immediately if no log spec was found (or it failed to parse the spec). At the moment, this just prints a message, which could easily be missed. Now when I come back in a couple of months, my logs are all out of whack, because I didn't see the message.
If you'd be willing to allow it, may I submit a PR to change these methods to return a Result, so that:
env()
doesn't find a RUST_LOG
environment variable, it returns an Err
parse()
fails to parse the spec, it returns an Err
Alternatively, to maintain backwards compatibility, I could add new methods e.g. env_result()
or something like that.
I might be missing something but it seems like the add_writer
requires calling all the logging macros with a target. I can't see any way to add an additional writer that always get's used.
Would adding some way to add writers that always get logged to be accepted?
My use case is I want to write a custom writer for the windows event viewer but also use the file log writer to keep text logs for my application.
Thanks!
fn main() {
let exe_path = format!("{}", std::env::current_exe().unwrap().parent().unwrap().display());
let criterion = flexi_logger::Criterion::Age(flexi_logger::Age::Day);
flexi_logger::Logger::with_env_or_str("info")
.log_target(LogTarget::StdOut)
.log_to_file()
.directory(exe_path)
.format(flexi_logger::detailed_format)
.print_message()
.rotate(criterion, flexi_logger::Naming::Timestamps, flexi_logger::Cleanup::Never)
.start()
.unwrap();
info!("Started application!");
}
Only logs to the file for me. How do I log to both CLI and a file?
Hi,
I noticed that formatting the message with format!
before logging is much faster than letting the logger do it. I would expect the performance to be similar or the logger to be slightly faster. Is this an expected behavior?
info!("{}", s); // 1700-2600us
info!("{}", format!("{}", s)); // 200-700us
Here is a simple test program:
[dependencies]
log = "0.4.6"
flexi_logger = "0.11.1"
use std::fmt;
use std::time::Instant;
struct Struct {
data: [u8; 32],
}
impl fmt::Display for Struct {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.data)
}
}
fn main() {
let _log_handle = flexi_logger::Logger::with_str("info")
.start()
.unwrap();
let mut structs = Vec::new();
for i in 0..10 {
structs.push(Struct { data: [i as u8; 32] });
}
{ // With format
let start = Instant::now();
for s in &structs {
log::info!("{}", format!("{}", s));
}
eprintln!("with format: {:?}", start.elapsed()); // 2-7ms
}
{ // Plain logger
let start = Instant::now();
for s in &structs {
log::info!("{}", s);
}
eprintln!("plain: {:?}", start.elapsed()); // 17-26ms
}
}
The length of the message does not matter that much, it's more about how many segments the Display
implementation writes. Is there maybe some buffering problem?
I can reproduce on Windows 10 with PowerShell and on Ubuntu Server.
Hi
First, thanks for this great logger!
I'm using Terminator terminal on Linux with solarized dark theme. Whenever I choose any of the colored output some of the text is invisible or close to the background color. Is there a way to provide my own color choices?
On Windows textfiles commonly end in a carriage return + line feed ("\r\n"
). flexi_logger's FileLogWriter only uses the simple line feed ("\n"
) common to Unix systems. I am using this crate for logging of a Windows service. An administrator may want to inspect log files using Notepad, as they cannot rely on more sophisticated tools to be present.
I am starting to work on this as it should not be too complex to add.
Hi, and thank you for this amazing crate.
I'm currently trying to add module filters coming from different sources. I'd like for my program to have some preset module filters, then check if there are more filters defined with RUST_LOG, and then ultimately add some features passed in by an argument.
The code would look like:
fn setup_logger(filter: &str) {
let mut builder = LogSpecBuilder::new();
// Set my preset module filters
builder.module("myfirstmodule", LevelFilter::Trace);
builder.module("mysecondmodule", LevelFilter::Info);
builder.default(LevelFilter::Error);
// See if RUST_LOG defines any module filters
builder.add_env();
// Add the filter passed in as parameter
build.add_str(filter);
// Create the LogSpec
let spec = builder.build();
// Start the logger
Logger::with(spec).start().unwrap();
}
However I see the builder has no method like add_env()
or add_str()
, and LogSpecification and Logger only provide associated functions to do that, not methods.
Am I doing it wrong? Or would it be a nice feature to add some methods that allow gettings filters from env / str in the builder?
Hello again!
Was wondering if you're open to changing the way this crate rotates log files?
It'd be nicer if the logs were always written to the same file, e.g. logs/my_proj.log
, and once that file reaches the size limit, the file is renamed to logs/my_proj_r00001.log
, and then the program recreates logs/my_proj.log
and continues to write there. That way, if you want to follow the logs, you don't need to re-enter the follow command every time the file rotates.
Hi,
Right now if I run a flexi_logger-enabled application from terminal (on Linux) I get a properly colored output.
However, if I launch it from another application (without terminal) and capture its output to show it in GUI, I still get color escape sequences in the text, and the displayed text is garbled in the GUI.
I think flexi_logger should use ::atty::is(::atty::Stream::Stdout) or similar to check whether colored output is actually supported.
Thanks!
The output in stdout looks fine, but the output that is written to files seems to have some weird character escapes: ^[[1;38;5;196mERROR^[[0m [babblebot::web] ^[[1;38;5;196mmissing field 'access_token' at line 1 column 74^[[0m
. Any idea why this might be happening?
Seems it does not remove old log files after restart.
Logger::with_env_or_str("debug")
.log_to_file()
.format(opt_format)
.rotate(
Criterion::Age(Age::Day),
Naming::Timestamps,
Cleanup::KeepLogFiles(6),
)
Hi!
First of all, let me express my thanks for creating the excellent flexi_logger crate!
I noticed a crash in logger.rs, line 661:
thread 'flexi_logger-specfile-watcher' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }', /home/anders/.cargo/registry/src/github.com-1ecc6299db9ec823/flexi_logger-0.15.2/src/logger.rs:661:40
I'm using flexi_logger 0.15.2 .
The problem occurred when I removed some log files which were present in the same directory that the specfile was located in.
The problem seems to be this line:
if path.canonicalize().unwrap() == specfile {
Apparently the path that is to be canonicalized must actually exist, or the line above will panic.
Revision 5b741cb replaced print_err
with eprintln
, but there is one remaining call to print_err
in flexi_writer.rs
on line 204 (only visible when compiling on linux).
Hi. Thanks for your contribution to the Rust ecosystem.
I was reading the documentation for the compressed logging. I was puzzled to find all this discussion of "zip" files. It would be highly unusual for a program to write logs in actual zip format (the format expected by unzip
). Traditional log management programs like logrotate
and savelog
make gzip files ending in .gz
. Tools like zgrep
which are usually used for inspecting logs expect gzip files.
I looked at the code, and indeed flexi_logger does make gzipped logfiles. But it calls them .zip
, and the documentation is wrong too. Unfortunately I don't think this can fixed without at least some kind of breaking change: currently the file contents and file extension do not match.
I suggest that the right complete fix is to change (i) the file extension, from .zip
to .gz
(ii) the documentation, to refer to gzip rather than zip, (iii) all the in-Rust names, changing Zip
to Gzip
everywhere, (iv) all the corresponding names in the configuration (env, specfile, etc.). [Option 1]
How much do you want to worry about compatibility ? In some of these cases it would be possible to provide aliases, although that's a fair amount of work. I think we could provide aliases for the builder methods and probably for the configuration. [Option 2]
Going in the other direction, we could retain the existing programmatic names and merely change the docs and the file extension. That would avoid this being a build break, and in practice would be unlikely to break production systems, although it would leave the anomalous names in Rust source code and logger spec files. This is also quite easy, since the spec handling wouldn't need changing :-). [Option 3]
Since we'll be changing the file extension, I guess we should arrange to at least rotate away the .zip
files made by older versions of flexi_logger, to avoid a situation where ancient .zip
files , obsoleted by recent .gz
files, are retained forever.
Please let me know what you prefer. I am happy to do the work to implement what I call options 1 and 3 above. My recommendation would be to do option 3 right away and then think about whether you need to go on to option 1 or 2.
I apologise for filing what you may see as a duplicate of #42. But I felt #42's framing was wrong. I wanted to set out a coherent (but opinionated) summary of the situation as I see it, under a corresponding title. I hope you find this helpful.
Is it possible to turn logging completely off for certain modules? Something like:
with_str("warn, mymodule=off")
It's hard to know what minimum supported rust version is used for this crate! This means that I'm not sure what rust version to bump to - at the moment I'm getting the following build failure when building against Rust 1.42:
error: attributes are not yet allowed on `if` expressions
##[error] --> /home/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/flexi_logger-0.15.11/src/logger.rs:163:9
|
163 | #[cfg(feature = "colors")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
It would be really useful for folks downstream if an explicit version was pinned in the .travis.yml
- at the moment it's only tested against stable, beta, and nightly.
Does FlexiLogger support multiple log files? Not sure if I see a clear way todo it from the examples.
The use case is I have an application that hosts a basic web api and services out a few assets using actix-web. The application also does a lot of background processing.
I want the web request logs to go into their own file vs the application logs. However everything is hosted in one process.
Thanks!
The documentation states:
By default, the log file will grow indefinitely. With this option, when the log file reaches or exceeds the specified file size, the file will be closed and a new file will be opened. Also the filename pattern changes - instead of the timestamp, a serial number is included into the filename.
But after calling flexi_logger::Logger::rotate_over_size(), I get a filename with a timestamp and a serial number. This is with v0.9.0.
When I want to use buffer, I must keep the LoggerHandle
which returned by start and then call shutdown myself, like this:
fn main() -> Result<(), Box<dyn std::error::Error>> {
let logger = Logger::with_str("info")
.log_target(LogTarget::File)
.buffer_and_flush()
.start()?;
// ... do all your work ...
logger.shutdown();
Ok(())
}
I think it's very unrust to do this, and implement a drop method for LoggerHandle make it more rust, the main function will envolved to like this:
fn main() -> Result<(), Box<dyn std::error::Error>> {
let _logger_guard = Logger::with_str("info")
.log_target(LogTarget::File)
.buffer_and_flush()
.start()?;
// ... do all your work ...
Ok(())
}
When a FileLogWriterState
is created, it sometimes rotate_output_file_to_date
but does not call remove_or_zip_too_old_logfiles
. The latter is only called when an existing _rCURRENT
overflows. Therefore when a downstream program is run repeatedly, but doesn't generate enough log messages to trigger mount_next_linewriter_if_necessary
in a single run, old rCURRENT
messages can accumulate indefinitely in the log directory.
Warning: new to writing real Rust, might mess up terminology… 🐻 with me
When binary crate has a dash in its name, e.g. in Cargo.toml:
[package]
name = "thing-doer"
version = "0.1.0"
the appropriate filter string is not:
LogOptions::new()
.init(Some("thing-doer=trace"))
.unwrap_or_else(|e|{ panic!("Logger initialization failed with {}", e)} );
but rather:
LogOptions::new()
.init(Some("thing_doer=trace"))
.unwrap_or_else(|e|{ panic!("Logger initialization failed with {}", e)} );
I discovered this the hard way, by logging not working upon setup and then creating my own log format to output the record.target()
. The output of record.target()
was thing_doer
and not thing-doer
.
I think this might be a "problem" in the log
crate but this should probably be documented in flexi_logger since it uses that target for comparing the named log level configurations.
I'm setting my log config like this:
let log_level_config = format!("{name}={level}", name = crate_name!().to_string().replace("-", "_"), level = "trace");
LogOptions::new()
//…
.init(Some(log_level_config))
.unwrap_or_else(|e|{ panic!("Logger initialization failed with {}", e)} );
I've worked around it by using that replace()
method so I don't have to think about it for now. I may regret that.
Hello,
When I try to unzip file using Linux (Ubuntu) unzip app get:
Archive: core_r00000.log.zip
End-of-central-directory signature not found. Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive. In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
I seems that the logger is making corrupt zip files.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.