Crates.io | logs-wheel |
lib.rs | logs-wheel |
version | 0.3.1 |
source | src |
created_at | 2023-11-11 21:54:52.884904 |
updated_at | 2023-11-20 22:13:41.025405 |
description | Rolling log files with compression |
homepage | |
repository | https://codeberg.org/mo8it/logs-wheel |
max_upload_size | |
id | 1032451 |
size | 63,626 |
Rolling log files with compression
This library offers the struct LogFileInitializer
to get a log file inside a logs directory.
It uses a rolling strategy that works like the wheel image above 🎡
The initializer has the fields directory
, filename
, max_n_old_files
and preferred_max_file_size_mib
.
Rolling will be applied to the file directory/file
if all the following conditions are true:
preferred_max_file_size_mib
(in MiB).In the case of rolling, the file will be compressed with GZIP to directory/filename-YYYYMMDD.gz
with today's date (in UTC).
If rolling was applied and the number of old files exceeds max_n_old_files
, the oldest file will be deleted.
It is important to know that rolling happens only on initialization.
The init
method returns a normal File
.
It will not apply rolling if your program runs for multiple days without being restarted.
This has the following advantages:
Your program should restart anyway every couple of days when restart the host after a system update.
But if you really want rolling every fixed amount of days while your program is running,
you can use your own type that calls the init
method under the hood when rolling should happen and then swap the file.
For more details, read the documentation of the LogFileInitializer
struct
and its init
method.
We will see what happens when calling the init
method
with the following field values for the initializer:
use logs_wheel::LogFileInitializer;
let log_file = LogFileInitializer {
directory: "logs",
filename: "test",
max_n_old_files: 2,
preferred_max_file_size_mib: 1,
}.init()?;
Ok::<(), std::io::Error>(())
This method call will always return the file logs/test
at the end.
But we will discuss its side effects.
The first call will create the directory logs/
in the current directory (because we specified a relative path) with the file test
inside it.
Content of logs/
:
test
If we call the same function again on the date 2023-11-12 (in UTC) and the size of the file logs/test
is bigger than 1 MiB,
the file will be compressed to logs/test-20231112.gz
.
The file logs/test
will be returned after truncation (empty file).
Content of logs/
:
test
test-20231112.gz
If we call the same function again on the same day, nothing will change,
even when the size of logs/test
is bigger than 1 MiB.
The file logs/test
will be open in append mode.
Content of logs/
:
test
test-20231112.gz
If we call the same function again on the next day and the size of the file logs/test
is bigger than 1 MiB,
the file will be compressed to logs/test-20231113.gz
.
The file logs/test
will be returned after truncation.
Content of logs/
:
test
test-20231113.gz
test-20231112.gz
Now, we already have 2 old files which means that we reached the limit max_n_old_files
.
If we call the same function again on the next day and the size of the file logs/test
is bigger than 1 MiB,
the file will be compressed to logs/test-20231114.gz
.
The oldest file test-20231112.gz
will be deleted.
The file logs/test
will be returned after truncation.
Content of logs/
:
test
test-20231114.gz
test-20231113.gz
You can use this library with the tracing ecosystem!
Here is an example of how to use the returned file as a tracing subscriber:
use logs_wheel::LogFileInitializer;
use std::sync::Mutex;
let log_file = LogFileInitializer {
directory: "logs",
filename: "test",
max_n_old_files: 2,
preferred_max_file_size_mib: 1,
}.init()?;
let writer = Mutex::new(log_file);
let subscriber = tracing_subscriber::fmt()
.with_writer(writer)
// … (other `SubscriberBuilder` methods)
.finish();
# Ok::<(), std::io::Error>(())
logs-wheel
can be used as an alternative. It can also be used in combination with NonBlocking for non blocking writes.