I totally dont understand how to use log crate. This documentation does not explain clearly for me how to implement logging for an executable (not library)? Should I implement another crate which implements logger? I’ve broke my mind with this. Can someone please explain where from should I start with some examples? If you have a projects which are using this crate please give me a link probably it will show me usage of it better.
log crate provides only an API for logging. The idea is that all crates use the same API for issuing logging calls, and then the final executable plugs in the concrete logging implementation.
The simplest logging implementation is env_logger. See the first example in the linked docs, it should be pretty nice.
Fern seems to be a more enterprisy implementation of the
log API, but I have not used it myself.
Thanks much for the clarification.
fern is what I decided to use now. I also wonder, is there any benefit from providing the log API by the language itself? What does it make better to have an api in the language? I can only think of benefit for end-users who may only change the logger but remain API calls untouched after that. Did I miss something?
Yeah, the benefit is pretty substantial. I’ll explain in a moment, but let me first clarify that the log API is provided by the library, and not by the language. You should not equate the language and it’s stdlib, especially in the case of Rust, which has several implementations of “standard libraries” (std lib, core lib, lrs). And the
log crate is not even in a standard library.
Suppose you are writing a library and you know that if you add some logging to it, than the users of you library can debug it more easily. Perhaps your library does some HTTP requests and you want to log them. What choices do you have?
First of all, you can omit the logging altogether. Your library will be harder to debug and monitor, but it will be easy to configure. Not a bad solution after all
Then, you can just dump all debug info to the stderr unconditionally. It’s also very easy to configure and does help with debugging, but otherwise it’s very unfriendly: just imagine three libraries simultaneously writing debug info to stderr. What a mess!
Another choice is to provide some hook to the user of your library, so that she can setup the verbosity level, the destination of logging and toggle the logging itself. This is a bit harder to implement, and a bit harder for the user to configure, but it does allow to log info when it’s necessary.
However even this solution is not ideal. Suppose the user uses five libraries. Now she has to write the same logging config five time, which is plainly boring. Another problem is that your library can depend on another library, which has it’s own logging callbacks. Then you’ll have to either expose your dependency to the user of your library, or to somehow combine the configuration of two libraries. Meh.
So in Rust, there is this blessed
log crate which allows to use the same logging config for all libraries and their dependencies. The benefit is not that you can swap loggers, the benefit is that you can add dependencies without changes to your logging config.
I think the same approach with blessed logging facade is used by Python. And in Java there seems to be several competing facades which causes a bit of a trouble (I may be terribly wrong about Python, or Java, or logging in general, please do correct me if it is the case )
The Java world has standardized on SLF4J in my experience, which provides bridges for old stuff that still talks to java.util.logging or directly to log4j.
Okay, few more questions:
- How to tell the logger to split output files if they reach some size? For example - see Xorg logging where most recent is
Xorg.0.log, next is
- Is it possible to tell/filter where from logging comes from? I use library which uses logging too and I want to have logger working at
Tracelevel but the library floods too much (1 second - 700 KB). Can I disable it somehow for anything that is not in my project?
This depends on the logging implementation you are using. I have not used anything more complicated that env logger, so I can’t really help here. Quick skimming through fern docs didn’t bring anything useful.