slog-rs - Structured, composable logging for Rust

Travis CI Build Status crates.io Gitter Chat
Documentation FAQ

Status & news

slog-rs is near final 1.0.0 release (see milestone 1.0).

Testing, feedback, PRs, etc. are very welcome. I'd be also very happy to share the ownership of the project with other people to make it more community-driven.

Long term goal is to make it a go-to logging crate for Rust.

Features

Advantages over log crate

Terminal output example

slog-rs terminal output

Using & help

Code snippet

``rust fn main() { // Create a new drain hierarchy, for the need of your program. // Choose from collection of existing drains, or write your own //struct-s implementingDrain` trait. let drain = slogterm::asyncstderr();

// `AtomicSwitch` is a drain that wraps other drain and allows to change
// it atomically in runtime.
let ctrl = AtomicSwitchCtrl::new(drain);
let drain = ctrl.drain();

// Turn a drain into new group of loggers, sharing that drain.
//
// Note `o!` macro for more natural `OwnedKeyValue` sequence building.
let root = Logger::root(drain, o!("version" => VERSION, "build-id" => "8dfljdf"));

// Build logging context as data becomes available.
//
// Create child loggers from existing ones. Children clone `key: value`
// pairs from their parents.
let log = root.new(o!("child" => 1));

// Closures can be used for values that change at runtime.
// Data captured by the closure needs to be `Send+Sync`.
let counter = Arc::new(AtomicUsize::new(0));
let log = log.new(o!("counter" => {
    let counter = counter.clone();
    // Note the `move` to capture `counter`,
    // and unfortunate `|_ : &_|` that helps
    // current `rustc` limitations. In the future,
    // a `|_|` could work.
    move |_ : &Record| { counter.load(SeqCst)}
}));

// Loggers  can be cloned, passed between threads and stored without hassle.
let join = thread::spawn({
    let log = log.clone();
    move || {

        info!(log, "before-fetch-add"); // counter == 0
        counter.fetch_add(1, SeqCst);
        info!(log, "after-fetch-add"); // counter == 1

        // `AtomicSwitch` drain can swap it's interior atomically (race-free).
        ctrl.set(
            // drains are composable and reusable
            level_filter(
                Level::Info,
                async_stream(
                    std::io::stderr(),
                    // multiple outputs formats are supported
                    slog_json::new(),
                ),
            ),
        );

        // Closures can be used for lazy evaluation:
        // This `slow_fib` won't be evaluated, as the current drain discards
        // "trace" level logging records.
        debug!(log, "debug", "lazy-closure" => |_ : &Record| slow_fib(40));

        info!(log, "subthread", "stage" => "start");
        thread::sleep(Duration::new(1, 0));
        info!(log, "subthread", "stage" => "end");
    }
});

join.join().unwrap();

} ```

See examples/features.rs for full code.

Read Documentation for details and features.

See [faq] for answers to common questions. If you want to say hi, or need help use #slog-rs gitter.im.

To report a bug or ask for features use github issues.

Building & running

If you need to install Rust (come on, you should have done that long time ago!), use rustup.

In your project

In Cargo.toml:

[dependencies] slog = "*"

In your main.rs:

```

[macro_use]

extern crate slog; ```

Alternatives

Please fill an issue if slog does not fill your needs. I will appreciate any feedback. You might look into issue discussing slog-rs alternatives too.