[][src]Crate slog

Slog - Structured, extensible, composable logging for Rust

slog-rs is an ecosystem of reusable components for structured, extensible, composable logging for Rust.

slog is slog-rs's main crate providing core components shared between all other parts of slog-rs ecosystem.

This is auto-generated technical documentation of slog. For information about project organization, development, help, etc. please see slog github page

Core advantages over log crate

  • extensible - slog crate provides core functionality: very basic and portable standard feature-set based on open traits. This allows implementing new features that can be independently published.
  • composable - traits that slog exposes to provide extensibility are designed to be easy to efficiently reuse and combine. By combining different functionalities every application can specify when, where and how exactly process logging data from the application and it's dependencies.
  • flexible - slog does not constrain logging to just one globally registered backend. Parts of your application can handle logging in a customized way, or completely independently.
  • structured and both human and machine readable - By keeping the key-value data format and retaining its type information, meaning of logging data is preserved. Data can be serialized to machine readable formats like JSON and send it to data-mining system for further analysis etc. On the other hand, when presenting on screen, logging information can be presented in aesthetically pleasing and easy to understand way.
  • contextual - slog's Logger objects carry set of key-value data pairs that contains the context of logging - information that otherwise would have to be repeated in every logging statement.

slog features

  • performance oriented; read what makes slog fast and see: slog bench log
    • lazily evaluation through closure values
    • async IO support included: see slog-async crate
  • #![no_std] support (with opt-out std cargo feature flag)
  • support for named format arguments (eg. info!(logger, "printed {line_count} lines", line_count = 2);) for easy bridging the human readable and machine-readable output
  • tree-structured loggers
  • modular, lightweight and very extensible
    • tiny core crate that does not pull any dependencies
    • feature-crates for specific functionality
    • using slog in library does not force users of the library to use slog (but provides additional functionality); see example how to use slog in library
  • backward and forward compatibility with log crate: see slog-stdlog crate
  • convenience crates:
  • many existing core&community provided features:
    • multiple outputs
    • filtering control
      • compile-time log level filter using cargo features (same as in log crate)
      • by level, msg, and any other meta-data
      • slog-envlogger - port of env_logger
      • terminal output, with color support: see slog-term crate
  • json
  • syslog and journald support
  • run-time configuration:

Notable details

Note: At compile time slog by default removes trace and debug level statements in release builds, and trace level records in debug builds. This makes trace and debug level logging records practically free, which should encourage using them freely. If you want to enable trace/debug messages or raise the compile time logging level limit, use the following in your Cargo.toml:

slog = { version = ... ,
         features = ["max_level_trace", "release_max_level_warn"] }

Root drain (passed to Logger::root) must be one that does not ever return errors. This forces user to pick error handing strategy. Drain::fuse() or Drain::ignore_res().

Where to start

Drain, Logger and log macro are the most important elements of slog. Make sure to read their respective documentation

Typically the biggest problem is creating a Drain

Logging to the terminal

This example is not tested
#[macro_use]
extern crate slog;
extern crate slog_term;
extern crate slog_async;

use slog::Drain;

fn main() {
    let decorator = slog_term::TermDecorator::new().build();
    let drain = slog_term::FullFormat::new(decorator).build().fuse();
    let drain = slog_async::Async::new(drain).build().fuse();

    let _log = slog::Logger::root(drain, o!());
}

Logging to a file

This example is not tested
#[macro_use]
extern crate slog;
extern crate slog_term;
extern crate slog_async;

use std::fs::OpenOptions;
use slog::Drain;

fn main() {
   let log_path = "target/your_log_file_path.log";
   let file = OpenOptions::new()
      .create(true)
      .write(true)
      .truncate(true)
      .open(log_path)
      .unwrap();

    let decorator = slog_term::PlainDecorator::new(file);
    let drain = slog_term::FullFormat::new(decorator).build().fuse();
    let drain = slog_async::Async::new(drain).build().fuse();

    let _log = slog::Logger::root(drain, o!());
}

You can consider using slog-json instead of slog-term. slog-term only coincidently fits the role of a file output format. A proper slog-file crate with suitable format, log file rotation and other file-logging related features would be awesome. Contributions are welcome!

Change logging level at runtime

This example is not tested
#[macro_use]
extern crate slog;
extern crate slog_term;
extern crate slog_async;

use slog::Drain;

use std::sync::{Arc, atomic};
use std::sync::atomic::Ordering;
use std::result;

/// Custom Drain logic
struct RuntimeLevelFilter<D>{
   drain: D,
   on: Arc<atomic::AtomicBool>,
}

impl<D> Drain for RuntimeLevelFilter<D>
    where D : Drain {
    type Ok = Option<D::Ok>;
    type Err = Option<D::Err>;

    fn log(&self,
          record: &slog::Record,
          values: &slog::OwnedKVList)
          -> result::Result<Self::Ok, Self::Err> {
          let current_level = if self.on.load(Ordering::Relaxed) {
              slog::Level::Trace
          } else {
              slog::Level::Info
          };

          if record.level().is_at_least(current_level) {
              self.drain.log(
                  record,
                  values
              )
              .map(Some)
              .map_err(Some)
          } else {
              Ok(None)
          }
      }
  }

fn main() {
    // atomic variable controlling logging level
    let on = Arc::new(atomic::AtomicBool::new(false));

    let decorator = slog_term::TermDecorator::new().build();
    let drain = slog_term::FullFormat::new(decorator).build();
    let drain = RuntimeLevelFilter {
        drain: drain,
        on: on.clone(),
    }.fuse();
    let drain = slog_async::Async::new(drain).build().fuse();

    let _log = slog::Logger::root(drain, o!());

    // switch level in your code
    on.store(true, Ordering::Relaxed);
}

Why is this not an existing crate? Because there are multiple ways to achieve the same result, and each application might come with it's own variation. Supporting a more general solution is a maintenance effort. There is also nothing stopping anyone from publishing their own crate implementing it.

Alternative to the above approach is slog-atomic crate. It implements swapping whole parts of Drain logging hierarchy.

Examples & help

Basic examples that are kept up-to-date are typically stored in respective git repository, under examples/ subdirectory. Eg. slog-term examples.

slog-rs wiki pages contain some pages about slog-rs technical details.

Source code of other software using slog-rs can be an useful reference.

Visit slog-rs gitter channel for immediate help.

Migrating from slog v1 to slog v2

Key-value pairs come now after format string

#[macro_use]
extern crate slog;

fn main() {
    let drain = slog::Discard;
    let root = slog::Logger::root(drain, o!());
    info!(root, "formatted: {}", 1; "log-key" => true);
}

See more information about format at log.

slog-streamer is gone

Create simple terminal logger like this:

This example is not tested
#[macro_use]
extern crate slog;
extern crate slog_term;
extern crate slog_async;

use slog::Drain;

fn main() {
    let decorator = slog_term::TermDecorator::new().build();
    let drain = slog_term::FullFormat::new(decorator).build().fuse();
    let drain = slog_async::Async::new(drain).build().fuse();

    let _log = slog::Logger::root(drain, o!());
}

Logging macros now takes ownership of values.

Pass them by reference: &x.

Modules

serDeprecated

Compatibility name to ease upgrading from slog v1

Macros

b

Macro for building group of key-value pairs in BorrowedKV

crit

Log critical level record

debug

Log debug level record

error

Log error level record

info

Log info level record

kv

Macro for build KV implementing type

log

Log message a logging record

o

Macro for building group of key-value pairs: OwnedKV

record

Create Record at the given code location

record_static

Create RecordStatic at the given code location

slog_b

Alias of b

slog_crit

Log critical level record (alias)

slog_debug

Log debug level record (alias)

slog_error

Log error level record

slog_info

Log info level record (alias)

slog_kv

Alias of kv

slog_log

Log message a logging record (alias)

slog_o

Macro for building group of key-value pairs (alias)

slog_record

Create Record at the given code location (alias)

slog_record_static

Create RecordStatic at the given code location (alias)

slog_trace

Log trace level record (alias)

slog_warn

Log warning level record (alias)

trace

Log trace level record

warn

Log warning level record

Structs

BorrowedKV

Borrowed KV

Discard

Drain discarding everything

Duplicate

Drain duplicating records into two other Drains

Filter

Drain filtering records

FnValue

Explicit lazy-closure Value

Fuse

Drain panicking on error

IgnoreResult

Drain ignoring result

Key

Opaque Key is a representation of a key.

LevelFilter

Drain filtering records by Record logging level

Logger

Logging handle used to execute logging statements

MapError

Drain mapping error returned by another Drain

OwnedKV

Owned KV

OwnedKVList

Chain of SyncMultiSerialize-s of a Logger and its ancestors

PushFnValue

Lazy Value that writes to Serializer

PushFnValueSerializer

Handle passed to PushFnValue closure

Record

One logging record

RecordStatic

Information that can be static in the given record thus allowing to optimize record creation to be done mostly at compile-time.

SingleKV

Single pair Key and Value

Enums

Error

Serialization Error

FilterLevel

Logging filtering level

Level

Logging level associated with a logging Record

MutexDrainError

Error returned by Mutex<D : Drain>

Statics

LOG_LEVEL_NAMES

Official capitalized logging (and logging filtering) level names

LOG_LEVEL_SHORT_NAMES

Official capitalized logging (and logging filtering) short level names

Traits

Drain

Logging drain

FilterFn

Function that can be used in Filter drain

KV

Key-value pair(s) for log events

MapErrFn

Function that can be used in MapErr drain

SendRefUnwindSafeDrain

Drain + Send + RefUnwindSafe bound

SendSyncRefUnwindSafeDrain

Drain + Send + Sync + RefUnwindSafe bound

SendSyncRefUnwindSafeKV

This type is used to enforce KVs stored in Loggers are thread-safe.

SendSyncUnwindSafe

Send + Sync + UnwindSafe bound

SendSyncUnwindSafeDrain

Drain + Send + Sync + UnwindSafe bound

SerdeValue

A value that can be serialized via serde

Serializer

Serializer

Value

Value that can be serialized

Type Definitions

OwnedKeyValueListDeprecated

Compatibility name to ease upgrading from slog v1

PushFnSerializerDeprecated

Old name of PushFnValueSerializer

PushLazyDeprecated

Compatibility name to ease upgrading from slog v1

Result

Serialization Result

SerializeDeprecated

Compatibility name to ease upgrading from slog v1

ValueSerializerDeprecated

Compatibility name to ease upgrading from slog v1