Log::Localized
surf the logflow...
Erwan Lemonnier, November 2005
About logging mechanisms
- A logging api is usually of the form:
log_function(level,message)
Levels are usually either
- numeric: 1, 2, 3, 4...
- or keywords: INFO, WARN, CRIT, ERROR...
Most logging APIs focus on ‘where’ the message should land and ‘how’ it should be formatted:
Problematic 1/2
- Imagine a very large application... (no kidding)
- The application crashes in production...
- You know which part of the application is guilty but have no clue why.
- You turn logging on with full verbosity...
- ...and get crushed to death by an avalanche of logs!
Problematic 2/2
- What you need is a mechanism to filter log messages based on where in the code they come from.
- Ideally, this mechanism should:
- understand some form of code geography
- respect your current logging mechanism (transparent layer)
- has a simple api
The answer: Log::Localized
Perl code geography
- We need a way to localize code areas
- Easy: use namespaces
- Packages:
- main::
- Test::Harness::Straps
- Functions/Methods:
- Test::Harness::Straps::new
- We can now define logging verbosity levels per code location!
Verbosity rules
- A logging verbosity rule says ‘at this place in the code, we may log messages with levels up to X’
- 3 rules syntax:
- Match everything under a given namespace at whatever depth
Main:: = X
Foo::Bar:: = X (match even Foo::Bar::Blob::Oof)
Match everything under a given namespace with depth 1
Foo::Bar::* = X
Match a function/method
Main::usage = X
No matching rule = no logging
Example of rule file
main::* = 1
Log::Localized:: = 0
Log::Localized::llog = 4
Default file name is ‘verbosity.conf’, in local dir
Rules are stored in a Config::Tiny file, where blocks are program names
Log::Localized
- Defines a standard logging function:
Use Log::Localized;
llog(2,"a log message");
Uses an underlying logging api (currently only Log::Dispatch via Log::Dispatch::Config file)
By default log to stdout with formatting:
# [main::main() l.30] [LEVEL 0]: I am doing this
# [main::main() l.31] [LEVEL 1]: now doing that
Synopsis
# create file ‘verbosity.conf’ in local dir
package Foo;
use Log::Localized;
sub bar {
# this message will be logged
# if method bar's verbosity is >= 1
llog(1,"running bar()");
}
# this message will be logged
# if package Foo's verbosity is >= 3
llog(3,"loaded package Foo");
Use cases
- Debug large live applications
- Understand unknown code by running it and checking its logs selectively (black box analysis)
- Modify logging policy afterwards, without having to edit all code and change hardcoded verbosity levels
- Ideas?
Customization 1/2
- Log::Localized comes with defaults that make it usable out of the box
- But almost everything can be reconfigured:
- name of the exported logging function (llog)
- name and location of the verbosity rule file
- Log::Dispatch configuration
Customization 2/2
- Via special rules:
- Log::Localized::rename = $name
- Log::Localized::dispatchers = $file
- Log::Localized::format = $format
- Log::Localized::global_verbosity = $name
- Log::Localized::use_rules = $name
- Log::Localized::search_path = $PATH
- Via import parameters
Alternatives to rule files
- You can switch logging on and set verbosity globally
- Via environment variable LOG_LOCALIZED_VERBOSITY
- Verbosity level can be set from inside the code
- local $Log::Localized::VERBOSITY = 2
Incoming features
- Log4perl compatibility
- Support for changes in the verbosity rule file during runtime
- Implement as a transparent log function hijacker
Questions?