Crates.io | logroller |
lib.rs | logroller |
version | 0.1.10 |
created_at | 2024-10-31 15:30:23.815062+00 |
updated_at | 2025-07-05 08:28:06.472497+00 |
description | A feature-rich log rotation library with timezone support, flexible rotation strategies, and compression, integrating seamlessly with the tracing ecosystem. |
homepage | |
repository | https://github.com/trayvonpan/logroller/ |
max_upload_size | |
id | 1430251 |
size | 88,464 |
LogRoller is a Rust library for efficient log writing and file rotation. It provides a simple API for writing logs to files and automatically rotating them based on size or time. It works seamlessly with the tracing-appender
crate for use with the tracing
framework.
xz
feature)Add logroller
to your Cargo.toml
:
# For basic logging or with tracing framework
[dependencies]
logroller = "0.1"
# Enable XZ compression support (optional)
logroller = { version = "0.1", features = ["xz"] }
logroller
as a simple loggerCreate a new LogRoller
instance and write logs to it:
use logroller::{LogRollerBuilder, Rotation, RotationSize};
use std::io::Write;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut logger = LogRollerBuilder::new("./logs", "logger.log")
.rotation(Rotation::SizeBased(RotationSize::MB(100))) // Rotate at 100MB
.max_keep_files(3) // Keep only last 3 files
.build()?;
writeln!(logger, "This is an info message")?;
writeln!(logger, "This is a warning message")?;
writeln!(logger, "This is an error message")?;
Ok(())
}
logroller
with tracing
and tracing-appender
Integrate with the tracing framework for structured logging:
use logroller::{Compression, LogRollerBuilder, Rotation, RotationAge, TimeZone};
use tracing_subscriber::util::SubscriberInitExt;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let appender = LogRollerBuilder::new("./logs", "tracing.log")
.rotation(Rotation::AgeBased(RotationAge::Daily)) // Rotate daily
.max_keep_files(7) // Keep a week's worth of logs
.time_zone(TimeZone::Local) // Use local timezone
.compression(Compression::Gzip) // Compress old logs
.build()?;
let (non_blocking, _guard) = tracing_appender::non_blocking(appender);
tracing_subscriber::fmt()
.with_writer(non_blocking)
.with_ansi(false)
.with_target(false)
.with_file(true)
.with_line_number(true)
.finish()
.try_init()?;
tracing::info!("This is an info message");
tracing::warn!("This is a warning message");
tracing::error!("This is an error message");
Ok(())
}
// Size-based rotation
Rotation::SizeBased(RotationSize::Bytes(1_000_000)) // 1MB in bytes
Rotation::SizeBased(RotationSize::KB(1_000)) // 1MB in KB
Rotation::SizeBased(RotationSize::MB(1)) // 1MB
Rotation::SizeBased(RotationSize::GB(1)) // 1GB
// Time-based rotation
Rotation::AgeBased(RotationAge::Minutely) // Rotate every minute
Rotation::AgeBased(RotationAge::Hourly) // Rotate every hour
Rotation::AgeBased(RotationAge::Daily) // Rotate at midnight
use chrono::FixedOffset;
// UTC time zone
.time_zone(TimeZone::UTC)
// Local system time zone
.time_zone(TimeZone::Local)
// Custom time zone (e.g., UTC+8)
.time_zone(TimeZone::Fix(FixedOffset::east_opt(8 * 3600).unwrap()))
// Limit number of kept files
.max_keep_files(7) // Keep only last 7 files
// Add custom suffix to log files
.suffix("error".to_string()) // Results in: app.log.2025-04-01.error
// Set file permissions (Unix systems only)
.file_mode(0o644) // rw-r--r-- permissions
use logroller::{Compression, LogRollerBuilder, Rotation, RotationAge, TimeZone};
let logger = LogRollerBuilder::new("./logs", "high_freq.log")
.rotation(Rotation::AgeBased(RotationAge::Hourly))
.max_keep_files(24) // Keep one day of hourly logs
.compression(Compression::Gzip)
.time_zone(TimeZone::UTC) // Use UTC for consistent timing
.build()?;
let logger = LogRollerBuilder::new("./logs", "large_app.log")
.rotation(Rotation::SizeBased(RotationSize::GB(1)))
.max_keep_files(5) // Keep only last 5 files
.compression(Compression::Gzip)
.build()?;
XZ compression provides the highest compression ratios but requires enabling the xz
feature:
// Cargo.toml
// logroller = { version = "0.1", features = ["xz"] }
use logroller::{Compression, LogRollerBuilder, Rotation, RotationAge};
let logger = LogRollerBuilder::new("./logs", "compressed.log")
.rotation(Rotation::AgeBased(RotationAge::Daily))
.compression(Compression::XZ(6)) // Compression level 0-9
.build()?;
let mut logger = LogRollerBuilder::new("./logs", "graceful.log")
.rotation(Rotation::AgeBased(RotationAge::Daily))
.graceful_shutdown(true) // Enable graceful shutdown
.build()?;
LogRoller provides graceful shutdown functionality to ensure proper cleanup of background operations: (default is false
)
When graceful_shutdown
is true
, flush()
waits for background compression threads to complete
When graceful_shutdown
is false
(default), flush()
returns immediately without waiting
Setting to false
prevents potential hangs during shutdown but may cause compression corruption
tracing-appender::non_blocking
for non-blocking log writesxz
feature)max_keep_files
to prevent excessive disk usageCommon issues and solutions:
File Permissions:
.file_mode()
to set appropriate permissions on Unix systemsDisk Space:
max_keep_files
settingsTime Zone Issues:
TimeZone::UTC
for consistent timing across different environmentsContributions are welcome! Here's how you can help:
Please ensure your code:
This project is licensed under the MIT License - see the LICENSE file for details.