GithubHelp home page GithubHelp logo

log's Introduction

log

A Rust library providing a lightweight logging facade.

Build status Latest version Documentation License

A logging facade provides a single logging API that abstracts over the actual logging implementation. Libraries can use the logging API provided by this crate, and the consumer of those libraries can choose the logging implementation that is most suitable for its use case.

Minimum supported rustc

1.60.0+

This version is explicitly tested in CI and may be bumped in any release as needed. Maintaining compatibility with older compilers is a priority though, so the bar for bumping the minimum supported version is set very high. Any changes to the supported minimum version will be called out in the release notes.

Usage

In libraries

Libraries should link only to the log crate, and use the provided macros to log whatever information will be useful to downstream consumers:

[dependencies]
log = "0.4"
use log::{info, trace, warn};

pub fn shave_the_yak(yak: &mut Yak) {
    trace!("Commencing yak shaving");

    loop {
        match find_a_razor() {
            Ok(razor) => {
                info!("Razor located: {razor}");
                yak.shave(razor);
                break;
            }
            Err(err) => {
                warn!("Unable to locate a razor: {err}, retrying");
            }
        }
    }
}

In executables

In order to produce log output, executables have to use a logger implementation compatible with the facade. There are many available implementations to choose from, here are some options:

Executables should choose a logger implementation and initialize it early in the runtime of the program. Logger implementations will typically include a function to do this. Any log messages generated before the logger is initialized will be ignored.

The executable itself may use the log crate to log as well.

Structured logging

If you enable the kv feature, you can associate structured data with your log records:

use log::{info, trace, warn};

pub fn shave_the_yak(yak: &mut Yak) {
    // `yak:serde` will capture `yak` using its `serde::Serialize` impl
    //
    // You could also use `:?` for `Debug`, or `:%` for `Display`. For a
    // full list, see the `log` crate documentation
    trace!(target = "yak_events", yak:serde; "Commencing yak shaving");

    loop {
        match find_a_razor() {
            Ok(razor) => {
                info!(razor; "Razor located");
                yak.shave(razor);
                break;
            }
            Err(e) => {
                // `e:err` will capture `e` using its `std::error::Error` impl
                warn!(e:err; "Unable to locate a razor, retrying");
            }
        }
    }
}

log's People

Contributors

alexcrichton avatar alistair23 avatar andygauge avatar brson avatar budziq avatar carols10cents avatar diondokter avatar divkov575 avatar dtolnay avatar efanzh avatar frewsxcv avatar guillaumegomez avatar hellow554 avatar huonw avatar jehiggs avatar johntitor avatar jonas-schievink avatar kodraus avatar mbrubeck avatar morrme avatar nivkner avatar nyurik avatar ottaviohartman avatar ptosi avatar sfackler avatar tethyssvensson avatar thomasdezeeuw avatar tmccombs avatar wadelma avatar yoshuawuyts 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

log's Issues

should we use rust log instead?

I need the ability to use the debug!() logging macros with a separate logger implementation per thread.

I see the default rust liblog module has this feature - and after building a logger implementation built on spdlog with both modules I prefer the default rust liblog module.

However, the default rust liblog module is marked as unstable/private - and recommends this github log library.

Am I wasting my time with the liblog module provided with Rust? (will it go away and be replaced by this github repo?) (which would be sad because I'm not seeing how to support per-thread loggers with this github log module)

Thanks!

Document where the logger outputs to by default

I started writing my own logger to output to stderr because I assumed the module output to stdout by default. I was corrected on IRC which lead me to read the source and figure out that folks on IRC were correct.

env_logger fails to compile with latest rust nightly

Compiling env_logger v0.2.2
<std macros>:2:20: 2:66 error: type `&mut std::old_io::buffered::LineBufferedWriter<std::old_io::stdio::StdWriter>` does not implement any method in scope named `write_fmt`
<std macros>:2 ( & mut * $ dst ) . write_fmt ( format_args ! ( $ ( $ arg ) * ) ) )
                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<std macros>:2:66: 2:66 help: methods from traits can only be called if the trait is in scope; the following trait is implemented but not in scope, perhaps add a `use` for it:
<std macros>:2:66: 2:66 help: candidate #1: use `std::old_io::Writer`
error: aborting due to previous error
Build failed, waiting for other jobs to finish...
Could not compile `env_logger`.

`LogLocation` lifetimes.

Could LogLocation::module_path() and LogLocation::file return 'static str, since they own them as &'static str? I am actually hitting this, and I need to use hidden variables directly instead.

I stole some code. Should I add attribution somewhere?

In slog-rs I decided to mimic compile time log level to be just like in log.

The commit is:

slog-rs/slog@6e3d6ea

slog-rs is MPL2 licensed, but I'm not sure if I should do anything else to be fair here, so I'm just letting you know.

If it's fine with you please just close the issue. If I should do anything, please let me know. Thanks!

Transform liblog into a logging facade

There are a couple of distinct kinds of programs, each of which has different needs from a logger:

  • Short running programs like rustc need a simple logging framework that provides some reasonable level of configurable filtering when trying to debug a problem.
  • Embedded programs or kernels may not have a stderr at all. They may, however, have the ability to log information through a serial port or network interface.
  • Long running programs like servers have more advanced logging needs than the current crate provides. In this case, dynamic reconfiguration of logging filters is very helpful, as is the ability to have multiple "sinks" that can output to the console, rolling files, the syslog, over the network, etc.
  • Programs that don't care about logging shouldn't be spammed with unwanted information from libraries that they use.

The current liblog implementation covers the first and last use cases, but misses the middle two.

There are two competing concerns here: we want a single logging interface that libraries can use - it would be crazy to expect someone to provide different versions of a single crate that only differ by their choice of logging framework! But at the same time, we want the libraries to be usable in all of the contexts mentioned above, with their logging intact.

One solution is to turn liblog into a logging "facade". It provides the infrastructure to allow libraries to send log messages, while allowing the downstream application to chose the actual logging framework that will process the log messages. One example is the slf4j library for Java, which allows libraries to log in a way that will work with any of the many logging frameworks available in Java: java.util.logging, log4j, Logback, etc.

I have a prototype conversion of liblog to a facade in the log-ng project. It consists of three crates:

  • log_ng - the core facade
  • basic - a port of liblog's current RUST_LOG based log implementation
  • log4r - a prototype of a more complex logger in the vein of log4j and Logback.

Documentation is available here: http://sfackler.github.io/log-ng/doc/log_ng/

Changes from liblog

While converting liblog, I did make some changes to the current functionality:

  • The log levels are now an enum instead of a u32, consisting of Off, Error, Warn, Info, Debug, and Trace. Note that Trace is new. I don't really see the use in having 255 distinct levels, and it simplifies parsing and pretty-printing of the level if we can restrict the level to an enum.
  • The logging macros don't call enabled before calling log. It turned out when I was experimenting with logger implementations that log can pretty trivially perform the filtering itself. If argument computation is expensive, the log_enabled! macro is still available, which will call through to enabled.
  • There is now a single global logger instead of thread-local loggers. The current liblog implementation does provide the ability to set the logger, but since it's task local, it's impossible to make sure the right logger is installed in each thread - think of threads started by TaskPool for example. Having thread-local loggers also results in a log of duplicated data and computation. The RUST_LOG environment variable has to be reparsed every time a program logs on a new thread, for example. In addition, it's not totally clear to me that anyone actually wants to have different loggers on different threads. Even if one does, it's pretty easy to make a thread local logger implementation for the logging facade.
  • The ndebug cfg is checked only in debug! and trace!, not in log! as well. I'm not sure what the right thing to do is here, but it seems like completely forbidding the use of the debug and trace levels with optimizations enabled is over-aggressive, especially since the global maximum log level check makes them pretty cheap when those levels are disabled. We may want to have debug! and trace! always enabled, and have separate debug build only versions.

Interesting notes/design decisions

  • The logger may only be initialized once, and isn't torn down when a program exits. It's possible to support logger replacement and teardown with atexit but it would require storing the logger in an Arc and adding a couple extra atomic reads and writes every time a message is logged. I'm not sure what the right answer is here. I don't really think people will want to swap their loggers out dynamically, but cleanup at exit seems like a nice thing to do to avoid spamming Valgrind.
  • Log messages generated when the logger is not initialized are ignored. Some logging facades like slf4j fall back to a simple logging implementation that dumps messages at the higher levels to the console. We could do this, but I'm a bit hesitant to do something that'll clutter the console for programs that don't want logging information as well as slow them down.
  • A logger has to be manually installed. slf4j can use some reflective classpath scanning magic to automatically set itself up to use common logging frameworks if they're present on the classpath, but we don't really have that ability. We may be able to do some dark magick with weak linkage, but I think that explicit is better than implicit here.

Remaining problems/blockers

  • Since the logger has to be manually initialized, it becomes very hard to use when running tests. You could make a Once and use that to initialize the logger in every test, but that adds a huge amount of pain to adding new tests. I think the best solution here is to augment rust's test support to add something like Go's TestMain function or junit's @BeforeClass annotation to allow for global setup before any tests run. This is useful in other contexts as well for other global resource setup.

Thoughts?

Add color support to env_logger

On Unix, we can use the ansi_term crate or roll our own. I'm not sure how it works on Windows; we can just skip colors there for now.

As for configuration: we can add a new environment variable RUST_LOG_COLOR. It will take the values never, always, or auto (default). If auto, the logger will use color only when stderr is connected to a terminal.

Add ability to log (warnings) only once

Having a function which send a warning is nice to send message to the users about potential issues in the input. But when this function is called in an inner loop, the lot of identical WARNING messages can be annoying.

Would it be possible to add a warn_once! macro, which would only send the warning once? The error_once!, info_once!, debug_once! and trace_once! can also be added, for consistency.

Error! logging on Windows x64 Rust prints nothing without env variable

The example tells me:

Log levels are controlled on a per-module basis, and by default all logging is disabled except for error!

However, when I copy the example...

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

fn main() {
    env_logger::init().unwrap();
    error!("this is printed by default\n");
}

.. and cargo build it (successfully) and then cargo run it, the console prints nothing. However, once I type this in the cmd window:

@set RUST_LOG=ERROR

everything works fine. I'm not sure if this is intended to be this way, but if I read the example description I'd assume this is a bug.

Environment:
Windows 8.1 64-bit
Rustc 1.0.0-beta.4 (850151a75 2015-04-30) (built 2015-05-01)
Cargo 0.2.0-nightly (efb482d 2015-04-30) (built 2015-04-30)

Cargo dependencies:
[dependencies] log = "0.3.1" env_logger = "0.3.0"

Allow env_logger to be initialised from user supplied spec

In some situations it may be required / desirable to obtain the logging spec from some place other than an environment variable but still make use of the rest of env_logger's functionality.

My current workaround manually sets the environment variable and then initialises env_logger:

fn init_logging(spec: &str) {
    ::std::env::set_var("RUST_LOG", spec);
    ::env_logger::init().unwrap();
}

I think it would be much nicer (and trivial to support) if this could be written like this instead:

fn init_logging(spec: &str) {
    ::env_logger::init_with_spec(spec);
}

Use core not std

I believe everything in the logging interface just requires core, not std. (The Box<Log> could become a Unique<Log> as it is never deallocated.) This is important for allowing the interface to reach its full potential, e.g. serial port debugging before allocation is set up. https://github.com/rust-lang/bitflags was similarly changed to use core for the same reason.

If this sounds good, I would be happy to do the implementation work.

build problems due to 0cdde6e5e015ee6f6d9381ab624a312af7c9b069

Hi,

Trying to build this package today gives me:

% cargo build
   Compiling log v0.2.1 (file:///private/tmp/log)
src/lib.rs:260:5: 267:6 error: method `from_str` has an incompatible type for trait: expected enum `core::result::Result`, found enum `core::option::Option` [E0053]
src/lib.rs:260     fn from_str(level: &str) -> Option<LogLevel> {
src/lib.rs:261         LOG_LEVEL_NAMES.iter()
src/lib.rs:262             .position(|&name| name.eq_ignore_ascii_case(level))
src/lib.rs:263             .into_iter()
src/lib.rs:264             .filter(|&idx| idx != 0)
src/lib.rs:265             .map(|idx| LogLevel::from_usize(idx).unwrap())
               ...
src/lib.rs:259:1: 268:2 error: not all trait items implemented, missing: `Err` [E0046]
src/lib.rs:259 impl FromStr for LogLevel {
src/lib.rs:260     fn from_str(level: &str) -> Option<LogLevel> {
src/lib.rs:261         LOG_LEVEL_NAMES.iter()
src/lib.rs:262             .position(|&name| name.eq_ignore_ascii_case(level))
src/lib.rs:263             .into_iter()
src/lib.rs:264             .filter(|&idx| idx != 0)
               ...
src/lib.rs:367:5: 371:6 error: method `from_str` has an incompatible type for trait: expected enum `core::result::Result`, found enum `core::option::Option` [E0053]
src/lib.rs:367     fn from_str(level: &str) -> Option<LogLevelFilter> {
src/lib.rs:368         LOG_LEVEL_NAMES.iter()
src/lib.rs:369             .position(|&name| name.eq_ignore_ascii_case(level))
src/lib.rs:370             .map(|p| LogLevelFilter::from_usize(p).unwrap())
src/lib.rs:371     }
src/lib.rs:366:1: 372:2 error: not all trait items implemented, missing: `Err` [E0046]
src/lib.rs:366 impl FromStr for LogLevelFilter {
src/lib.rs:367     fn from_str(level: &str) -> Option<LogLevelFilter> {
src/lib.rs:368         LOG_LEVEL_NAMES.iter()
src/lib.rs:369             .position(|&name| name.eq_ignore_ascii_case(level))
src/lib.rs:370             .map(|p| LogLevelFilter::from_usize(p).unwrap())
src/lib.rs:371     }
               ...

This appears to have been broken by 0cdde6e5e015ee6f6d9381ab624a312af7c9b069 (to rust). I would submit a PR but I have no clue how to fix.

docs: add example of initializing the logger from a unit test

Since I do not expect rust-lang/rfcs#1664 to be addressed in the short term, it would be a good idea to update the docs for env_logger to include an example usage on a few #[test] functions in addition to the current fn main.

(That is, I think the current docs leave a lot up to the intutition of the reader in terms of understanding how to generalize that one use of env_logger to other contexts.)

Are these `#[inline]` helping?

I've noticed that log crate goes out of it's way to add #[inline] in a lot of places. I'd like to ask - is it worth it with a current rust compiler? Any experiences and measurements?

Corresponding slog-rs issue: slog-rs/slog#25

Use logger in a dynamically loaded shared library

Since a dynamically loaded shared library is compiled separately from the executable. The linker would need to resolve the logger in the library to the instance in the executable at run-time when we invoke "dlopen".
Having a way to ask dynamic library not allocate but to look for in run-time would make log usable in dynamically loaded library.

Stabilize and document `__log`.

Sometimes needs arise where one wants to deliver a custom logging statement to log crate. __log is exactly that function, but then anyone using it is risking breaking changes.

It seems to me once log API is considered stable, __log should be documented and stabilized as well.

log! macro fails when cross compiling with no_std

I'm using a nightly rustc (1.8.0-nightly, ba356ffbc 2016-01-24) on an x86_64 linux system, and trying to cross compile liblog to i686. I'm able to compile libcore and liblog just fine, but when I try to use the log! macro, rust chokes.

Compiled with rustc -L $LIB_I686_DIR --target i686-unknown-linux-gnu temp.rs

temp.rs

Output:

<log macros>:1:37: 1:50 error: unresolved name `log::INFO` [E0425]
<log macros>:1 ( $ ( $ arg : tt ) * ) => ( log ! ( :: log:: INFO , $ ( $ arg ) * ) )
                                                   ^~~~~~~~~~~~~
<log macros>:1:29: 1:68 note: in this expansion of log! (defined in <log macros>)
temp.rs:36:5: 36:27 note: in this expansion of info! (defined in <log macros>)
<log macros>:1:37: 1:50 help: run `rustc --explain E0425` to see a detailed explanation
<log macros>:3:28: 3:42 error: unresolved name `log::DEBUG` [E0425]
<log macros>:3 let lvl = $ lvl ; ( lvl != :: log:: DEBUG || cfg ! ( debug_assertions ) ) &&
                                          ^~~~~~~~~~~~~~
<log macros>:5:24: 5:45 note: in this expansion of log_enabled! (defined in <log macros>)
<log macros>:1:29: 1:68 note: in this expansion of log! (defined in <log macros>)
temp.rs:36:5: 36:27 note: in this expansion of info! (defined in <log macros>)
<log macros>:3:28: 3:42 help: run `rustc --explain E0425` to see a detailed explanation
<log macros>:4:8: 4:26 error: unresolved name `log::log_level` [E0425]
<log macros>:4 lvl <= :: log:: log_level (  ) && :: log:: mod_enabled (
                      ^~~~~~~~~~~~~~~~~~
<log macros>:5:24: 5:45 note: in this expansion of log_enabled! (defined in <log macros>)
<log macros>:1:29: 1:68 note: in this expansion of log! (defined in <log macros>)
temp.rs:36:5: 36:27 note: in this expansion of info! (defined in <log macros>)
<log macros>:4:8: 4:26 help: run `rustc --explain E0425` to see a detailed explanation
<log macros>:4:35: 4:55 error: unresolved name `log::mod_enabled` [E0425]
<log macros>:4 lvl <= :: log:: log_level (  ) && :: log:: mod_enabled (
                                                 ^~~~~~~~~~~~~~~~~~~~
<log macros>:5:24: 5:45 note: in this expansion of log_enabled! (defined in <log macros>)
<log macros>:1:29: 1:68 note: in this expansion of log! (defined in <log macros>)
temp.rs:36:5: 36:27 note: in this expansion of info! (defined in <log macros>)
<log macros>:4:35: 4:55 help: run `rustc --explain E0425` to see a detailed explanation
<log macros>:6:1: 6:13 error: unresolved name `log::log` [E0425]
<log macros>:6 :: log:: log ( lvl , & LOC , format_args ! ( $ ( $ arg ) + ) ) } } )
               ^~~~~~~~~~~~
<log macros>:1:29: 1:68 note: in this expansion of log! (defined in <log macros>)
temp.rs:36:5: 36:27 note: in this expansion of info! (defined in <log macros>)
<log macros>:6:1: 6:13 help: run `rustc --explain E0425` to see a detailed explanation
<log macros>:4:1: 4:5 error: structure `log::LogLocation` has no field named `line`
<log macros>:4 line : line ! (  ) , file : file ! (  ) , module_path : module_path ! (  ) , }
               ^~~~
<log macros>:4:1: 4:5 help: did you mean `__line`?
<log macros>:4 line : line ! (  ) , file : file ! (  ) , module_path : module_path ! (  ) , }
               ^~~~
<log macros>:4:22: 4:26 error: structure `log::LogLocation` has no field named `file`
<log macros>:4 line : line ! (  ) , file : file ! (  ) , module_path : module_path ! (  ) , }
                                    ^~~~
<log macros>:4:22: 4:26 help: did you mean `__file`?
<log macros>:4 line : line ! (  ) , file : file ! (  ) , module_path : module_path ! (  ) , }
                                    ^~~~
<log macros>:4:43: 4:54 error: structure `log::LogLocation` has no field named `module_path`
<log macros>:4 line : line ! (  ) , file : file ! (  ) , module_path : module_path ! (  ) , }
                                                         ^~~~~~~~~~~
<log macros>:4:43: 4:54 help: did you mean `__module_path`?
<log macros>:4 line : line ! (  ) , file : file ! (  ) , module_path : module_path ! (  ) , }
                                                         ^~~~~~~~~~~
error: aborting due to 8 previous errors

When I do a pretty expansion, the info!() turns into this:

{
    static LOC: ::log::LogLocation =
        ::log::LogLocation{line: 36u32,
        file: "temp.rs",
        module_path: "temp",};
    let lvl = ::log::INFO;
    if {
        let lvl = lvl;
        (lvl != ::log::DEBUG || true) && lvl <= ::log::log_level() &&
            ::log::mod_enabled(lvl, "temp")
    } {
        ::log::log(lvl, &LOC,
                   ::core::fmt::Arguments::new_v1({
                       static __STATIC_FMTSTR:
                       &'static [&'static str]
                       =
                       &["Hello World!"];
                   __STATIC_FMTSTR
                   },
                   &match () {
                       () => [],
                   }))
    }
};

It looks like rust is stripping leading underscores within the log!() macro, and converting LogLevels into all caps.

Log libz-blitz evaluation tracker

log evaluation for 2017-05-16

For more information see the internals libz blitz thread.

This post is a wiki. Feel free to edit it.

Links

Pre-review checklist

Do these before the libs team review.

  • Create evaluation thread based on this template
  • Work with author and issue tracker to identify known blockers
  • Compare crate to guidelines by filling in checklist
  • Record other questions and notes about crate
  • Draft several use case statements to serve as cookbook examples
  • Record recommendations for updated guidelines
  • Publish evaluation to coordination thread for review and notify reviewers

Post-review checklist

Do these after the libs team review.

  • Publish libs team meeting video
  • Create new issues and tracking issue on crate's issue tracker
  • Solicit use cases for cookbook examples related to the crate
  • File bugs to implement cookbook examples
  • File bugs to update guidelines
  • Post all approachable issues to twir call for participation thread
  • Update links in coordination thread

Guidelines checklist

  • Organization (crate is structured in an intelligible way)
    • Crate root re-exports common functionality ([C-REEXPORT])
    • Modules provide a sensible API hierarchy ([C-HIERARCHY])
  • Naming (crate aligns with Rust naming conventions)
    • Casing conforms to RFC 430 ([C-CASE])
    • Ad-hoc conversions follow as_, to_, into_ conventions ([C-CONV])
    • Methods on collections that produce iterators follow iter, iter_mut, into_iter ([C-ITER])
    • Iterator type names match the methods that produce them ([C-ITER-TY])
    • Ownership suffixes use _mut and _ref ([C-OWN-SUFFIX])
    • Single-element containers implement appropriate getters ([C-GETTERS])
  • Interoperability (crate interacts nicely with other library functionality)
    • Types eagerly implement common traits ([C-COMMON-TRAITS])
      • Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash Debug,
        Display, Default
    • Conversions use the standard traits From, AsRef, AsMut ([C-CONV-TRAITS])
    • Collections implement FromIterator and Extend ([C-COLLECT])
    • Data structures implement Serde's Serialize, Deserialize ([C-SERDE])
    • Crate has a "serde" cfg option that enables Serde ([C-SERDE-CFG])
    • Types are Send and Sync where possible ([C-SEND-SYNC])
    • Error types are Send and Sync ([C-SEND-SYNC-ERR])
    • Error types are meaningful, not () ([C-MEANINGFUL-ERR])
    • Binary number types provide Hex, Octal, Binary formatting ([C-NUM-FMT])
  • Macros (crate presents well-behaved macros)
    • Input syntax is evocative of the output ([C-EVOCATIVE])
    • Macros compose well with attributes ([C-MACRO-ATTR])
    • Item macros work anywhere that items are allowed ([C-ANYWHERE])
    • Item macros support visibility specifiers ([C-MACRO-VIS])
    • Type fragments are flexible ([C-MACRO-TY])
  • Documentation (crate is abundantly documented)
    • Crate level docs are thorough and include examples ([C-CRATE-DOC])
    • All items have a rustdoc example ([C-EXAMPLE])
    • Examples use ?, not try!, not unwrap ([C-QUESTION-MARK])
    • Function docs include error conditions in "Errors" section ([C-ERROR-DOC])
    • Function docs include panic conditions in "Panics" section ([C-PANIC-DOC])
    • Prose contains hyperlinks to relevant things ([C-LINK])
    • Cargo.toml publishes CI badges for tier 1 platforms ([C-CI])
    • Cargo.toml includes all common metadata ([C-METADATA])
      • authors, description, license, homepage, documentation, repository,
        readme, keywords, categories
    • Crate sets html_root_url attribute "https://docs.rs/$crate/$version" ([C-HTML-ROOT])
    • Cargo.toml documentation key points to "https://docs.rs/$crate" ([C-DOCS-RS])
  • Predictability (crate enables legible code that acts how it looks)
    • Smart pointers do not add inherent methods ([C-SMART-PTR])
    • Conversions live on the most specific type involved ([C-CONV-SPECIFIC])
    • Functions with a clear receiver are methods ([C-METHOD])
    • Functions do not take out-parameters ([C-NO-OUT])
    • Operator overloads are unsurprising ([C-OVERLOAD])
    • Only smart pointers implement Deref and DerefMut ([C-DEREF])
    • Deref and DerefMut never fail ([C-DEREF-FAIL])
    • Constructors are static, inherent methods ([C-CTOR])
  • Flexibility (crate supports diverse real-world use cases)
    • Functions expose intermediate results to avoid duplicate work ([C-INTERMEDIATE])
    • Caller decides where to copy and place data ([C-CALLER-CONTROL])
    • Functions minimize assumptions about parameters by using generics ([C-GENERIC])
    • Traits are object-safe if they may be useful as a trait object ([C-OBJECT])
  • Type safety (crate leverages the type system effectively)
    • Newtypes provide static distinctions ([C-NEWTYPE])
    • Arguments convey meaning through types, not bool or Option ([C-CUSTOM-TYPE])
    • Types for a set of flags are bitflags, not enums ([C-BITFLAG])
    • Builders enable construction of complex values ([C-BUILDER])
  • Dependability (crate is unlikely to do the wrong thing)
    • Functions validate their arguments ([C-VALIDATE])
    • Destructors never fail ([C-DTOR-FAIL])
    • Destructors that may block have alternatives ([C-DTOR-BLOCK])
  • Debuggability (crate is conducive to easy debugging)
    • All public types implement Debug ([C-DEBUG])
    • Debug representation is never empty ([C-DEBUG-NONEMPTY])
  • Future proofing (crate is free to improve without breaking users' code)
    • Structs have private fields ([C-STRUCT-PRIVATE])
    • Newtypes encapsulate implementation details ([C-NEWTYPE-HIDE])
  • Necessities (to whom they matter, they really matter)
    • Public dependencies of a stable crate are stable ([C-STABLE])
    • Crate and its dependencies have a permissive license ([C-PERMISSIVE])

Cookbook use case statements

  • Debug messages
  • Logging info/error messages
  • Logging levels per module
  • Linux syslog logging

Crate issues

(List potential issues here)

Style guide updates

(List potential updates to the style guide)

Discussion topics

(List new questions that arose from this evaluation)

Cannot import LogMetadata

I am trying to write a customized logger, but I got some issue like this:

xxxxx.rs:17:30: 17:41 error: unresolved import `log::LogMetadata`. There is no `LogMetadata` in `log`
xxxxx.rs:17 use log::{LogRecord,LogLevel,LogMetadata,LogLocation,set_logger};

It's strange that only LogMetadata not imported properly.

BTW, I specified log version to exactly 0.3.1 in Cargo.toml.

[dev-dependencies]
log = "0.3.1"

env_logger performance, eliminating overhead of unused logging calls

Quoted from here: google/tarpc#139

an interesting observation: we get ~10-20% higher throughput by removing all the debug logging calls in tarpc
things like trace! compiles to a memory load and a branch in the final code, which actually ends up mattering for common calls
I know slog (https://github.com/slog-rs/slog) has unused logging calls be completely compiled away
and also compose a bit more nicely

tarpc uses env_logger. Is is possible to keep the semantics of env_logger the same while optimizing the log calls so that unused logging calls are also completely optimized away?

Changing env_logger's log format

What's the recommended way to change env_logger's log format?

I have tried to override the Log trait for Logger to change the log format but can't see how to do it.

add a way to set an indentation level

Debug logs are very linear. It's often very hard to detect when a specific scope of some kind has been left. I can probably implement it without it being a breaking change. Here's my design idea:

Add set_indent and get_indent methods to the Log trait with default impls that do nothing. Add a log_indent! macro to set the log indent, increase it by one or decrease it by one depending on the args. Future work might also make it create a scope lock to decrease the scope level again at the end of the scope.

Does anything speak against doing this? Technically I could do it as a new logger impl, but it would be very tedious to repeat the entire env logger impl.
Change env_logger to indent the log message by the current level.

log + DynamicLibrary

Is it possible to use DynamicLibrary::open(Some(&path)) and then execute it functions:

unsafe {
    std::mem::transmute(lib.symbol::<u8>("test_function").unwrap())
}

that use logger within?

In dyn lib:

#[no_mangle]
pub extern fn test_function() -> Result<()> {
    warn!("MESSAGE_FROM_DYN_LIB");
    Ok(())
}

In my case, the log messages from the dynamic library is not displayed.

Change environment variable name.

For env_logger, maybe keep the default as RUST_LOG and allow the users to change it as a config option? For example, I might want people to use MC_LOG to change the log level of my Minecraft clone.

Link to logging sinks other than env_logger in the README/crate docs

A major purpose of the log crate is to be flexible wrt to the logger implementation! We should link to popular implementations of loggers in addition to other loggers than env_logger. This'll hopefully dispel the notion that env_logger is "the logger implementation" and is instead just "a logger implementation".

Use of logging prevents (threaded) SDL application from exiting

I've only tested this on Windows, and I don't have a small reproduction I can share. I'll edit this issue once I have more information.

This might be caused from the combination of rust-sdl2 and logging, or the use of threads, or the combination of both. But as soon as I started to use the log crate (along with env_logger), whenever my application tries to exit, it seems to get stuck in an infinite loop. The SDL window closes, the end of main is reached, but the program doesn't exit.

Inspiration from logxi?

Hi,
I just wanted to present to you this Golang library: https://github.com/mgutz/logxi. I'm using it in my Go projects and I find it awesome.

I considered writing something like it for rust, but since there is already logging library, I just wanted you to take a look and consider adding some features here...

Examples:

  • automatic stdout/file detection for dev/prod usage
  • dev logging with nicely formatted and colored output
  • logging to file in parseable format - JSON
  • changing logged levels by ENV variable before running the program

And maybe others?
Thank you.

Feature request: Logging only for testing

It would be good to have a macro which does a println/log during testing, but is removed when not testing.

Another alternative would be a log statement which is removed when ndebug is set.

'macro undefined' when adding log 0.3.6 to an executable

I wanted to add logging to my hello-world application, so I followed the instructions in the README, but I get the following error:

/Users/danfox/rust-hello-world/target/debug/build/rust-hello-world-35e574f972a5f97c/out/main.rs:235:5: 235:8 error: macro undefined: 'log!'
/Users/danfox/rust-hello-world/target/debug/build/rust-hello-world-35e574f972a5f97c/out/main.rs:235     log!("Starting server on localhost:3000");
                                                                                                        ^~~
error: aborting due to previous error
error: Could not compile `rust-hello-world`.

(This red build is reproducible on travis)

Is the log crate known to be incompatible with syntex or am I just making a much simpler mistake? Any suggestions on what to try next are welcome :)

Build error after updating to latest nightly

<log macros>:4:8: 4:21 error: mismatched types:
 expected `usize`,
    found `u32`
(expected usize,
    found u32) [E0308]
<log macros>:4 line : line ! (  ) , file : file ! (  ) , module_path : module_path ! (  ) , }
                      ^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
 expected `usize`,
    found `u32`
(expected usize,
    found u32) [E0308]
<log macros>:4 line : line ! (  ) , file : file ! (  ) , module_path : module_path ! (  ) , }
                      ^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
 expected `usize`,
    found `u32`
(expected usize,
    found u32) [E0308]
<log macros>:4 line : line ! (  ) , file : file ! (  ) , module_path : module_path ! (  ) , }
                      ^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
 expected `usize`,
    found `u32`
(expected usize,
    found u32) [E0308]
<log macros>:4 line : line ! (  ) , file : file ! (  ) , module_path : module_path ! (  ) , }
                      ^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
 expected `usize`,
    found `u32`
(expected usize,
    found u32) [E0308]
<log macros>:4 line : line ! (  ) , file : file ! (  ) , module_path : module_path ! (  ) , }
                      ^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
 expected `usize`,
    found `u32`
(expected usize,
    found u32) [E0308]
<log macros>:4 line : line ! (  ) , file : file ! (  ) , module_path : module_path ! (  ) , }
                      ^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
 expected `usize`,
    found `u32`
(expected usize,
    found u32) [E0308]
<log macros>:4 line : line ! (  ) , file : file ! (  ) , module_path : module_path ! (  ) , }
                      ^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
 expected `usize`,
    found `u32`
(expected usize,
    found u32) [E0308]
<log macros>:4 line : line ! (  ) , file : file ! (  ) , module_path : module_path ! (  ) , }
                      ^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
 expected `usize`,
    found `u32`
(expected usize,
    found u32) [E0308]
<log macros>:4 line : line ! (  ) , file : file ! (  ) , module_path : module_path ! (  ) , }

Using a custom logger requires set_logger in every task

Issue by seanmonstar
Wednesday Aug 27, 2014 at 16:24 GMT

For earlier discussion, see rust-lang/rust#16794

This issue was labelled with: A-libs in the Rust repository


Currently, the logger is stored in TLS. It's fine to setup a logger at the start of your program, but if you use spawn a lot, it's cumbersome to remember in each call to setup your logger again.

I think tasks should inherit the logger from the task that spawned it, perhaps with an option to turn it off (less important).

cc #3309

Very long build times (~3-4 minutes) for env_logger

When building rustfmt on stable 1.16.0 the build time is very slow (~230 seconds on a quad-core 4GHz Sandy Bridge on Windows), and it appears the majority of time is spent building env_logger.

I observed similarly long build times on a quad-core, modern macbook pro laptop.

Not sure if this is env_logger specific or a rustc issue but just wanted to report the issue.

Is this expected?

Mutability issues with the `Log` trait

Hi,

I would like to implement Log for the syslog crate, but I cannot do so because the log method requires an immutable self: fn log(&self, record: &LogRecord).

In the case of logging to a remote server via TCP, the logger holds an instance of TcpStream, which must stay mutable for writing.

Would it be alright to update the trait definition? Or can you suggest a way to bend my code for this?

v0.2.6 should be v0.3.0

It includes the changes from #27 which significantly change the api that logger implementations interact with.

multiple logging sinks

Issue by graydon
Monday Jul 15, 2013 at 21:02 GMT

For earlier discussion, see rust-lang/rust#7805

This issue was labelled with: A-diagnostics, A-instrumentation, A-libs, A-runtime, I-enhancement in the Rust repository


Things like https://logging.apache.org/log4cxx/ and similar logging libraries tend to be able to send logging to a number of possible sinks (syslog, files, in-memory, etc.)

Our logging should know how to do this too.

See also #6810 , sub-bug of #3309

static item is never used: `LOC` ?

Am i the only one getting warnings like this:

<log macros>:3:1: 5:8 warning: static item is never used: `LOC`, #[warn(dead_code)] on by default
<log macros>:3 static LOC : $ crate:: LogLocation = $ crate:: LogLocation {
<log macros>:4 __line : line ! (  ) , __file : file ! (  ) , __module_path : module_path ! (
<log macros>:5 ) , } ; let lvl = $ lvl ; if ! cfg ! ( log_level = "off" ) && (
<log macros>:1:1: 13:64 note: in expansion of log!
<log macros>:13:1: 13:62 note: expansion site
<log macros>:1:1: 13:64 note: in expansion of log!
<log macros>:4:1: 4:53 note: expansion site
<log macros>:1:1: 4:57 note: in expansion of debug!
src/parser.rs:8:5: 8:38 note: expansion site

I'm not aware that i did something wrong.. i have a library and lib.rs basically contains the import and the #[macro_use] statement.
The expansion sites are debug!() statements..

Make the global logger thread local

It'd be very useful to have the global logger be init'd so it is thread local. This could be a significant breaking change to library users, so I'd suggest it was done using a compile-time feature.

Why?

  1. Occasionally, logging can be quite expensive for some binaries, particularly if they are using one of the newer cloud services. In this world, one runs a second logging thread and has log requests forwarded to it (eg using thread::mpsc).
  2. For larger server projects, logging needs may also vary for different parts of the code base:-
    • The main thread is used only for startup, option parsing and shutdown, and has very little in the way of logging needs, but if it does log, should log to standard error
    • The main application threads (eg socket listeners) need to log to a monitored cloud service, so pass their logging requests to a third logging thread
    • The logging thread receives log requests and forwards them on. It itself may need a logger that talks, say, to local syslog.

What do you think?

Could log output be shown in tests?

Normally running tests mutes standard output, but using this rather obscure command cargo test -- --nocapture, output such as println!("something"); is shown in the test result.
This is great for debugging. However, it doesn't appear to work with the log macros.

I found #56 which documents how to enable output in tests specifically, but I am wondering if there is some easier way?

Provide benchmarks for env-logger

From the README and the docs, I didn't see anything about how fast the log / don't log decision is. In particular, I'm interested in whether using env-controled debug! in performance-sensitive code would be a good idea or not.

#[macro_use(info)] raise error: macro undefined: 'log!'

Code:

#[macro_use(info)]
extern crate log;

Error:

<log macros>:4:1: 4:4 error: macro undefined: 'log!'
<log macros>:4 log ! ( $ crate:: LogLevel:: Info , $ ( $ arg ) * ) ; )
               ^~~

I will use #[macro_use] for now but I thought it was interesting to limit the macro to import in the namespace

$rustc --version
rustc 1.1.0-dev

env: Allow zero-allocation LogBuilder::format?

The the "format function" passed to LogBuilder::format must implement Fn(&LogBuilder) -> String. That is, it must allocate a new string on the heap for every message logged. The string is discarded immediately after env_logger::Logger writes to stderr.

Would you consider, instead, making the signature Fn(&LogBuilder, &mut std::io::Write) -> io::Result? That way, customized env loggers could write directly to stderr without creating a String.

Add a method to set the active logging filters post-initialization.

For example, in Chrome PNaCl applications, access to host environmental vars is completely restricted. Thus all logging code in those applications are effectively dead code.

It would be great if I could enable logging by, for example, adding a DOM attribute (which turns into an argument provide to the PPP_InstanceCreated callback) of the module before it's attached to the DOM (thereby creating the instance). Also, note PPP_InstanceCreated is not where rust-ppapi initializes std, so this needs to allow users to set the desired filter value after initialization. Doesn't need to be thread-safe, but should probably include a warning label.

This represents a nice-to-have feature.

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.