Giter Site home page Giter Site logo

slog-rs / slog Goto Github PK

View Code? Open in Web Editor NEW
1.5K 18.0 96.0 16.09 MB

Structured, contextual, extensible, composable logging for Rust

Home Page: https://slog.rs/

License: Apache License 2.0

Makefile 1.07% Rust 98.85% Vim Script 0.08%
rust logging logging-library structured-logging hierarchical-loggers ecosystem slog-rs contextual

slog's Introduction

slog-rs logo
GH Actions (Cargo Test) slog-rs on crates.io slog-rs Gitter Chat docs-rs: release versions documentation
Getting started Introduction FAQ
Crate list

slog-rs - The Logging for Rust

You might consider using tracing instead

It's been a while since slog was created and it served Rust community well all this time. It remains a stable, featureful and battle-tested library, used in many important projects.

In last few years, another ecosystem for Rust was created with similar features and a very good support for debugging async code and already larger dev team and community.

Please check tracing and see if it is more suitable for your use-case. It seems that it is already a go-to logging/tracing solution for Rust.

Reasons you might want to stick with slog anyway:

  • async support doesn't benefit you
  • you consider mature, stable code & API a plus
  • it has some features that tracing is missing
  • great performance (I have NOT done any comparison, but slog's performance is very good).

Introduction (please read)

slog is an ecosystem of reusable components for structured, extensible, composable and contextual logging for Rust.

The ambition is to be The Logging Library for Rust. slog should accommodate a variety of logging features and requirements. If there is a feature that you need and standard log crate is missing, slog should have it.

This power comes with a little steeper learning curve, so if you experience any problems, please join slog-rs gitter channel to get up to speed. If you'd like to take a quick, convenient route, consider using sloggers wrapper library.

While the code is reliable, the documentation sometimes could use an improvement. Please report all issues and ideas.

Features & technical documentation

Most of the interesting documentation is auto-generated and hosted on https://docs.rs.

Go to docs.rs/slog to read about features and APIs (examples included).

Note: slog is just a core, and the actual functionality is inside many feature crates. To name a few:

There are many more slog feature crates. Search for more slog features on crates.io. It is easy to write and publish new ones. Look through all the existing crates using slog for examples and ideas.

Terminal output example

slog-term is only one of many slog features - useful showcase, multi-platform, and featuring eg. automatic TTY detection and colors.

See following screenshot: same output in both compact and full output mode.

slog-rs terminal example output

Using & help

Please use slog-rs gitter channel to ask for help or discuss slog features.

See examples/features.rs for full quick code example overview.

Read Documentation for details and features.

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

Slog community

Slog related crates are hosted under slog github organization.

Dawid Ciężarkiewicz is the original author and current maintainer of slog and therefore self-appointed benevolent dictator over the project. When working on slog Dawid follows and expects everyone to follow his Code of Conduct.

Any particular repositories under slog ecosystem might be created, controlled, maintained by other entities with various levels of autonomy. Lets work together toward a common goal in a respectful and welcoming atmosphere!

Verification Recommendation

To help with the maintained, the ownership of this crate is potentially shared between multiple developers. It is recommended to always use cargo-crev to verify the trustworthiness of each of your dependencies, including this one.

slog's People

Contributors

alex-gulyas avatar antifuchs avatar compressed avatar david-mcgillicuddy-moixa avatar demurgos avatar dpc avatar fintelia avatar herschel avatar kixunil avatar kstrafe avatar lu-zero avatar lucretiel avatar mozgiii avatar mzabaluev avatar netvl avatar panicbit avatar pdietl avatar petrochenkov avatar pthedinger avatar rasky avatar remram44 avatar swaits avatar techcable avatar tmccombs avatar tomhoule avatar tshepang avatar ubnt-intrepid avatar valarauca avatar walfie avatar whipsch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

slog's Issues

`SwitchOnSignal` drain.

A drain handling signal by switching a drain. That would be useful for production debugging, as described in the README:

  • drains are run-time swappable - Send a signal to your program and start logging everything to a file for run-time production debugging. Send another one when you're done to return to normal operation. Build your own flexible scenarios easily.

Alterantive names for macros.

trace! would have an alternative slog_trace! alias and so on.

In case of macro name conflicts between log and slog user could just selectively import alternative names, and use this.

`CompactStreamer` / `CompactTextFormat` ?

Text logging streamer/format(?) that looks something like this:

 build: 'adfksj2kdfl'
   server-ip: 32.24.2.1 server-port: 23434
      peer-ip: 2.3.65.2
          2016-08-23 16:32:23.235 Connected
          2016-08-23 16:32:26.642 Request received
      peer-ip: 11.32.53.12
          2016-08-23 16:32:33.343 Connected
          2016-08-23 16:32:34.322 Request received
          2016-08-23 16:32:35.112 Response sent
      peer-ip: 2.3.65.2
          2016-08-23 16:32:36.231 Response sent
          2016-08-23 16:32:37.542 Disconnected
      peer-ip: 11.32.53.12
          2016-08-23 16:32:38.938 Disconnected

This is almost as compact/short as normal log, while, the structured information can be easily found be following the indention.

`trivial_casts` and `unused_qualification` warnings in `o!` macro

trivial_casts and unused_qualification warnings in o! macro.
This should be fixed or add #[allow(..)] attribute at the macro definition.

Code:

#![warn(trivial_casts)]
#![warn(unused_qualifications)]

#[macro_use]
extern crate slog;
extern crate slog_term;

use slog::RecordInfo;
use slog::drain::IntoLogger;

use std::sync::Arc;

fn main() {
    let log = slog_term::stderr().into_logger(o!{
        "module" => |rec: &RecordInfo| rec.module().to_string()
    });
    let arc = Arc::new(123);
    info!(log, "arc", "arc" => *arc);
}

Output:

<slog macros>:6:7: 7:19 warning: trivial cast: `std::sync::Arc<[closure@src/main.rs:15:21: 15:64]>` as `std::sync::Arc<slog::ser::SyncSerialize + 'static>`. Cast can be replaced by coercion, this might require type ascription or a temporary variable
<slog macros>:6 $ k , std :: sync :: Arc :: new ( $ v ) as std :: sync :: Arc < $ crate :: ser
                      ^
<slog macros>:3:11: 7:29 note: in this expansion of vec! (defined in <std macros>)
src/main.rs:14:47: 16:6 note: in this expansion of o! (defined in <slog macros>)
src/main.rs:1:9: 1:22 note: lint level defined here
src/main.rs:1 #![warn(trivial_casts)]
                      ^~~~~~~~~~~~~
<slog macros>:6:7: 6:32 warning: unnecessary qualification
<slog macros>:6 $ k , std :: sync :: Arc :: new ( $ v ) as std :: sync :: Arc < $ crate :: ser
                      ^~~~~~~~~~~~~~~~~~~~~~~~~
<slog macros>:3:11: 7:29 note: in this expansion of vec! (defined in <std macros>)
src/main.rs:14:47: 16:6 note: in this expansion of o! (defined in <slog macros>)
src/main.rs:2:9: 2:30 note: lint level defined here
src/main.rs:2 #![warn(unused_qualifications)]
                      ^~~~~~~~~~~~~~~~~~~~~
<slog macros>:6:44: 7:19 warning: unnecessary qualification
<slog macros>:6 $ k , std :: sync :: Arc :: new ( $ v ) as std :: sync :: Arc < $ crate :: ser
                                                           ^
<slog macros>:3:11: 7:29 note: in this expansion of vec! (defined in <std macros>)
src/main.rs:14:47: 16:6 note: in this expansion of o! (defined in <slog macros>)
src/main.rs:2:9: 2:30 note: lint level defined here
src/main.rs:2 #![warn(unused_qualifications)]
                      ^~~~~~~~~~~~~~~~~~~~~

Bunyan format

Would be nice to have Bunyan output format, so we can keep using the same rich filtering and analysis tools across languages.

Unable to log any trace output

No matter how I configure my Cargo.toml, I am unable to produce any trace output.

The latest attempt is below:

[dependencies.slog]
version = "1.0.0-alpha6"
default-features = false
features = ["release_max_level_trace", "max_level_trace"]

After digging around a bit I believe the culprit is Cargo not honoring the default-features = false flag.

It seems that all the features are enabled (in this case, "release_max_level_info, release_max_level_trace, max_level_debug, and max_level_trace"). Due to the if clause in lib.rs, and a normal debug build, "max_level_debug" is always hit, and trace can never be enabled.

Update
Running cargo build --verbose shows the following passed to rustc (and includes all 4 dependencies):

     Running `rustc /home/jozias/projects/slog-rs/src/lib.rs --crate-name slog --crate-type lib -g --cfg feature=\"max_level_trace\" --cfg feature=\"release_max_level_info\" --cfg feature=\"max_level_debug\" --cfg feature=\"default\" -C metadata=b5fec68b10428a12 --out-dir /home/jozias/projects/trace/target/debug/deps --emit=dep-info,link -L dependency=/home/jozias/projects/trace/target/debug/deps`

So this looks like a bug in Cargo where it isn't removing the default dependencies even when default-features = false is used.

I'm going to open an issue on the cargo project.

Easier `slog_stdlog` invocation.

#[macro_use]
extern crate log;
extern crate slog_stdlog;

 fn main() { 
   slog_stdlog::init();
    info!("should just work out of the box");
 }

Yaml/toml/json builders.

Implement a crate that reads a configuration file and creates a drain defined in it. Box<Drain> will be used all over the place, which is supported and perfectly fine.

Add AsyncStreamer

Same as Stremer, but using channel and worker thread to write message asynchronously.

Question: HowTo call logger via macro in modules

Hi. I'm kindly fresh to rust and I'm actually building a nickel-rs powered API.

I would like to implement slog-rs in the API, so I can use the logger within different modules and middlewares, to log data like: users accessing the API.

While I have a main.rs as starting point, a lib.rs as library and dozens of modules like middlewares, controllers, etc., I can't get the point, where I have to put the code to instantiate the logger, to let me call macros from these different modules, middlewares, controllers, etc.

I would be very glad, if you can point me, where I could implement this, so I can call the logging instance from different modules via a macro.

Hope you get, what I try to explain.

Final touches

  • flatten drain and logger module into root namespace
  • RecordInfo -> Record
  • Node -> List
  • move atomic switcher to separate crate, to remove crossbeam dependency
  • IntoMsg -> Message trait
    • Use write_to where possible for speedup?
  • Remove rustc_serialize dep
  • Write drain to old-style logging, so libraries can take Option<Logger> and use drain to old-style logging in case their user doesn't want to use slog.
    • Document it somewhere
  • More documentation!
  • Move decorators out of the slog create? This way they can be improved after 1.0 release, and eventually even moved back to main crate, without breaking compatibility.
  • Lazy values that can actually write to io::Write? Only then allocation can be completely avoided.

slog-atomic 0.3.0 out of date with master

I suspect the slog-atomic crate was not published with the 1.0.0 release as the code on master does not match that in 0.3.0.

0.3.0:

/// Handle to `AtomicSwitch` allowing switching it's sub-drain
pub struct AtomicSwitchCtrl<E>(Arc<ArcCell<Box<Drain<Error=E>>>>);

/// Drain allowing atomically switching a sub-drain in runtime
pub struct AtomicSwitch<E>(Arc<ArcCell<Box<Drain<Error=E>>>>);

impl<E> AtomicSwitchCtrl<E> {
    /// Create new `AtomicSwitchCtrl`
    pub fn new<D: Drain<Error=E> + 'static>(d: D) -> Self {
        let a = Arc::new(ArcCell::new(Arc::new(Box::new(d) as Box<Drain<Error=E>>)));
        AtomicSwitchCtrl(a)
    }

    /// Create new `AtomicSwitchCtrl` from an existing `Arc<...>`
    pub fn new_from_arc(d: Arc<ArcCell<Box<Drain<Error=E>>>>) -> Self {
        AtomicSwitchCtrl(d)
    }

    /// Get a `AtomicSwitch` drain controlled by this `AtomicSwitchCtrl`
    pub fn drain(&self) -> AtomicSwitch<E> {
        AtomicSwitch(self.0.clone())
    }

    /// Set the drain
    pub fn set<D: Drain<Error=E>>(&self, drain: D) {
        let _ = self.0.set(Arc::new(Box::new(drain)));
    }

    /// Swap the existing drain with a new one
    pub fn swap(&self, drain: Arc<Box<Drain<Error=E>>>) -> Arc<Box<Drain<Error=E>>> {
        self.0.set(drain)
    }
}

impl<E> Drain for AtomicSwitch<E> {
    type Error = E;
    fn log(&self, info: &Record, logger_values: &OwnedKeyValueList) -> std::result::Result<(), E> {
        self.0.get().log(info, logger_values)
    }
}

master:

/// Handle to `AtomicSwitch` that controls it.
pub struct AtomicSwitchCtrl<E>(Arc<ArcCell<Box<Drain<Error=E>>>>);

/// Drain wrapping another drain, allowing atomic substitution in runtime
pub struct AtomicSwitch<E>(Arc<ArcCell<Box<Drain<Error=E>>>>);

impl<E> AtomicSwitch<E> {
    /// Wrap `drain` in `AtomicSwitch` to allow swapping it later
    ///
    /// Use `AtomicSwitch::ctrl()` to get a handle to it
    pub fn new<D: Drain<Error=E> + 'static>(drain: D) -> Self {
        AtomicSwitch::new_from_arc(Arc::new(ArcCell::new(Arc::new(Box::new(drain) as Box<Drain<Error=E>>))))
    }

    /// Create new `AtomicSwitch` from an existing `Arc<...>`
    ///
    /// See `AtomicSwitch::new()`
    pub fn new_from_arc(d: Arc<ArcCell<Box<Drain<Error=E>>>>) -> Self {
        AtomicSwitch(d)
    }

    /// Get a `AtomicSwitchCtrl` handle to control this `AtomicSwitch` drain
    pub fn ctrl(&self) -> AtomicSwitchCtrl<E> {
        AtomicSwitchCtrl(self.0.clone())
    }
}

impl<E> AtomicSwitchCtrl<E> {
    /// Get Arc to the currently wrapped drain 
    pub fn get(&self) -> Arc<Box<Drain<Error=E>>> {
        self.0.get()
    }

    /// Set the current wrapped drain
    pub fn set<D: Drain<Error=E>>(&self, drain: D) {
        let _ = self.0.set(Arc::new(Box::new(drain)));
    }

    /// Swap the existing drain with a new one
    pub fn swap(&self, drain: Arc<Box<Drain<Error=E>>>) -> Arc<Box<Drain<Error=E>>> {
        self.0.set(drain)
    }

    /// Get a `AtomicSwitch` drain controlled by this `AtomicSwitchCtrl`
    pub fn drain(&self) -> AtomicSwitch<E> {
        AtomicSwitch(self.0.clone())
    }
}

impl<E> Drain for AtomicSwitch<E> {
    type Error = E;
    fn log(&self, info: &Record, logger_values: &OwnedKeyValueList) -> std::result::Result<(), E> {
        self.0.get().log(info, logger_values)
    }
}

Thread local loggers

I was wondering if we could have some sort of thread local logger (possibly adaptors for coroutine local as well), this way you wouldn't have to pass the logger around in most cases, making the crate much more ergonomic.

It wouldn't work for all occasions, granted, but I can see it being very useful in a lot of cases.

Optimize performance

https://github.com/dpc/slog-rs/wiki/Bench-log

Ideas:

  • &'a str in RecordInfo`
  • static dispatch - 39e6b5e
  • measure perf of closure-values
  • stdlog not to allocate String
  • Arc chaining instead of copying in Logger hierarchies?
  • closure-values not to allocate anything - implement SerializeKey for Fn(&RecordInfo, mut io::Writer) ? so the value can output itself without returning?
  • use the same feature that standard log uses to remove logging statesments at compile time. Now that macros are being used, this should work smoothly.

Fails to compile on windows: error: unresolved name `lvl` [E0425]

When compiling a crate that uses slog-rs on Windows, I get the following:

<slog macros>:2:22: 2:25 error: unresolved name `lvl` [E0425]
<slog macros>:2 let lvl = $ lvl ; if lvl . as_usize (  ) <= $ crate:: __slog_static_max_level
                                     ^~~
<slog macros>:2:1: 2:48 note: in this expansion of log! (defined in <slog macros>)
src\main.rs:7:5: 7:44 note: in this expansion of trace! (defined in <slog macros>)

This happens for any log level. Potential blocker for the 1.0.0 release?

I just discovered it, so I'm still investigating the cause / fix.

I was using rustc 1.9.0 (e4e8b6668 2016-05-18)


Minimal example to reproduce (I use git bash):

cd /tmp
cargo new use_slog
cd use_slog
echo 'slog = "1.0.0-alpha3"' >> Cargo.toml
echo 'slog-term = "1.0.0-alpha3"' >> Cargo.toml
rm -f src/lib.rs
cat > src/main.rs << EOF
#[macro_use]
extern crate slog;
extern crate slog_term;

fn main() {
    let log = slog::Logger::root(slog_term::streamer().full().build(), o!());
    trace!(log, "logging a trace message");
}
EOF
cargo build

Support custom timestamp, level, msg key names.

Timestamp could be really OwnedKeyValue with the value being a closure, with a possibility of an user adding it's own. The problem it's evaluation would happen a bit later (important for async drain).

Level & msg are kind of special, but maybe something similiar could be done for them.

Interoperability with standard logging facilities.

It might make sense to build log crate adapters, so calls like info!(...) would be logged as some_global_logger.info("original-info-message"). This most pobably could be done as a separate library (log-slog-logger)?

The other way around could be useful too: implement a slog::Drain that forwards logging record to log calls, formatting them before the write.

slog-stream unpublished

I’m unable to locate the slog-stream crate on crates.io. Is it possible to depend on it through some other mechanism?

Review the list of `emit_x` functions in `Serializer`.

While not tragic, every time this list changes, API breaks for serializer adapters (slog-serde).

Also, while at it, review the list of types implementing Serializable. Adding these is backward-compatible, but it's better to check now.

Derive or implement `Debug` for `Logger`

Loggers should be stored in the structs their context is associated with. Since Logger doesn't implement Debug this imposes a limitation on these structs.

How should the output of Debug look? The connected drain and a list of owned values are available in the loggers. I think printing the list of owned values is sufficient to identify the logger.

slog-scopes

Create a library that uses thread_local stack of Loggers to allow not passing Logger when not desired.

slog_stdlog::scope

slog_stdlog::scope(
    |prev_logger| { prev_logger.new(o!("more-data" => 2)) },
    || {
       /// code to be executed
        ....

      //// old logging statement to be used with a logger with `"more-data"`
      info!("check out more data");
});

info!("prev_logger will be used here");

StdLog doesn't pass key => value from inside log messages with env_logger

I'm currently trying to implement stdlog for Amethyst for optional slog support for a binary. To enable this, I'm using the

struct Foo {
    logger: logger.unwrap_or(slog::Logger::root(slog_stdlog::StdLog.fuse(), o!()))
}

method described in crates/example-lib However, when a binary doesn't use a slog drain, but env_logger, messages that should look like this with env_logger (and does with slog)

ERROR:my:library:source: error message here, errorid: 405, cause: foo

looks like

ERROR:my:library:source: error message here

skipping the information that should be delivered with error!(self.logger, "error message here"; "errorid" => error_id, "cause" => cause);

slog-syslog: Streamer3164 doesn't empty buffer after writing

The Drain::log implementation for Streamer3164 never trims TL_BUF after writing some bytes from it via syslog::Logger::send.

Note that syslog::Logger::send_raw returns the number of bytes written from the RFC3164 formatted message and not the raw message passed to it, so using the count returned by send is not suitable for trimming TL_BUF.

Streamer3164 should probably use format_3164 directly and continuously call send_raw until the message is fully written. Drain::log feels like std::io::Write::write_all to me, so I think this is semantically appropriate.

Strategies and tools for libraries to allow seamless `slog` support.

Currently most libraries can just keep using log logging statement. Applications using them can just use slog-stdlog + slog-stdlog::scope to redirect it where they want.

The more complicated ones can just accept Logger, but what if they don't want to force slog dependency on their user?

Alternatives to slog-rs

Hi!

Seems like we're both doing the same thing: https://github.com/3Hren/blacklog. Even goals are nearly the same.

I've started this project as a port of my another logging library for C++ focusing on structured logs, performance and configuration from generic source.

Since both our projects in the early alpha stage, maybe we should to calm down and reunite our forces on neutral territory?

What I suggest:

  • Create a separate repo/organization with name we both like.
  • Declare the manifest, which describes how we code, what goals we have etc.
  • Prove each PR with tests and benchmarks. Automate with Travis CI and maybe homu.

Alternatives:

  • Bog off, I want my own crate!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.