Log levels
The cost of logging
Logs are useful, but they come at a cost.
Formatting, serializing, and writing log messages to a file or a socket takes time. It is
not uncommon to hear about applications that spend more time writing logs than doing actual
work.
As a rule of thumb, we want each log record emitted by our application to be useful.
How do you define "useful"?
Easier said than done.
The usefulness of a log record can be situational: redundant under normal circumstances but vital when trying to troubleshoot a particularly vicious bug.
Usefulness is also subjective: depending on your intent, you might or might not care about a particular log record. This is a challenge for library authors: their software will be used in a variety of contexts, and it's hard to predict what information will be useful to the final application.
How do we reconcile these needs?
Log filtering
The common solution is to use log filters.
A log filter is a predicate that determines whether a log record should be emitted or not.
The filters are defined by the final binary, the application, therefore they are tuned based
on the application's needs.
Library authors can instrument their code ~freely, knowing that the application owner will be
in charge of deciding what they want or don't want to see.
Filters rely primarily on two pieces of information:
- the log level of the record, a measure of its importance
- the module that emitted the record, also known as the target.
Filters are evaluated at runtime for each log record, therefore they aren't entirely zero-cost, but they let us skip the most expensive parts of the logging process (formatting, serializing, emitting), therefore amortizing the cost of "unnecessary" log records.
Compile-time filtering
There is an exception though: you can filter out log records based on their level at compile
time, using some of the cargo
features exposed by the log
crate.
The filtered log statements disappear entirely: they don't exist in the compiled binary,
therefore they don't incur any runtime cost.
It is a great option to remove the noisiest log statements (e.g. TRACE
-level), although
it's not a silver bullet: you can't use it to filter out log records based on their source.
Exercise
The exercise for this section is located in 01_structured_logging/02_log_levels