4 releases

0.1.3 Oct 16, 2024
0.1.2 Sep 2, 2024
0.1.1 Aug 24, 2024
0.1.0 Aug 23, 2024

#409 in Debugging

33 downloads per month

MIT license

43KB
820 lines

winston

Crates.io Rust

A customizable, multithreaded logging library for Rust, inspired by the flexibility of Winston.js. This logger supports custom log levels, multiple transports, real-time filtering, and format customization.

Features

  • Custom Log Levels: Define your own log levels or use the default ones.
  • Multiple Transports: Log to multiple destinations (e.g., files, console, etc.).
  • Real-Time Filtering: Filter logs based on log levels and conditions.
  • Custom Formats: Define how log entries are formatted.(implemented in logform)
  • Multithreading: Logs are processed in a separate thread to avoid blocking your application.

Installation

Add the following to your Cargo.toml:

[dependencies]
winston = "0.1"

or with

cargo add winston

Usage

1. Basic Setup

Start by configuring the default logger:

use winston::{LoggerOptions, Logger, log_info, log_warn, log_error, configure};

fn main() {
    let new_options = LoggerOptions::new()
        .level("debug").add_transport(Console::new(None));

    configure(Some(new_options));

    log_info!("This is an info message.");
    log_warn!("This is a warning.");
    log_error!("This is an error.");

    Logger::shutdown();
}

2. Custom Logger Configuration

You can configure the logger with custom log levels, transports, and formats:

use winston::{transports::Console, Logger, LoggerOptions, log_warn, format::json};

fn main() {
    let options = LoggerOptions::new()
        .level("info")
        .format(json())
        .add_transport(Console::new(None));

    let logger = Logger::new(Some(options)); // or with Logger::builder().level("info").format(json()).add_transport(Console::new(None)).build();

    logger.warn("Custom logger warning!");
}

3. Querying Logs

You can query the logs that are in queryable transports like files:

use winston::{Logger, LogQuery, format};

fn main() {
    let logger = Logger::builder()
        .add_transport(
            transports::File::builder()
                .filename(temp_path.clone())
                .build(),
        )
        .format(format::combine(vec![format::timestamp(), format::json()]))
        .build();

    // Log some messages
    logger.info("Test message 1");
    logger.error("Test error message");
    logger.warn("Test warning");

    // For testing purpose, Sleep for a short duration to ensure logs are flushed to the file so the query will retrieve them
    std::thread::sleep(std::time::Duration::from_secs(1));

    let query = LogQuery::new()
        .levels(vec!["error"]);

    let results = logger.query(&query).unwrap();

    for entry in results {
        println!("{:?}", entry);
    }
}

4. Shutting Down the Logger

Ensure all log entries are processed before your application exits(this is only necessary for the default logger since statics do not call drop):

use winston::Logger;

fn main() {
    // Your code here

    // Gracefully shut down the logger
    Logger::shutdown();
}

5. Global Logger

A global logger is provided for convenience. You can log messages using macros:

use winston::{log_info, log_warn, log_error};

fn main() {
    log_info!("Global info log");
    log_warn!("Global warning log");
    log_error!("Global error log");
}

6. Changing Configuration at Runtime

You can reconfigure the logger during runtime:

use winston::{Logger, LoggerOptions};

fn main() {
    let logger = Logger::new(None);

    let new_options = LoggerOptions::new()
        .level("debug").add_transport(Console::new(None));

    logger.configure(Some(new_options));

    logger.debug("This is a debug message after reconfiguration.");
}

Contributing

Feel free to contribute to this project by submitting issues or pull requests.

License

This project is licensed under the MIT License.

Dependencies

~4–14MB
~165K SLoC