NAME
Log::Any::Adapter::Daemontools - Logging adapter suitable for use in a Daemontools-style logging chain
VERSION
version 0.090000_001
SYNOPSIS
# No "bonus features" are enabled by default, but this gets you the most
# common Unixy behavior.
use Log::Any::Adapter 'Daemontools',
config => { argv => 1, env => 1, handle_signals => ['USR1','USR2'] };
# Above is equivalent to:
use Log::Any::Adapter 'Daemontools',
config => {
log_level => 'info',
argv => {
verbose => [ '-v', '--verbose' ], quiet => [ '-q', '--quiet' ],
bundle => 1, stop => '--'
},
env => { debug => 'DEBUG' },
handle_signals => { verbose => 'USR1', quiet => 'USR2' }
};
# Above is equivalent to:
use Log::Any::Adapter::Daemontools 'global_log_level', 'global_debug_level', 'parse_log_level_opts';
use Log::Any::Adapter;
if ($ENV{DEBUG}) { global_debug_level($ENV{DEBUG}); }
if (@ARGV) {
global_log_level(
parse_log_level_opts(
array => \@ARGV,
verbose => [ '-v', '--verbose' ],
quiet => [ '-q', '--quiet' ],
bundle => 1,
stop => '--'
)
);
}
$SIG{USR1}= sub { global_log_level('+= 1'); };
$SIG{USR2}= sub { global_log_level('-= 1'); };
Log::Any::Adapter->set('Daemontools');
# Example of a differing point of view:
#
# (Beware: 'argv', 'env', and 'handle_signals' are a special once-only
# startup behavior, so this code must be the *first* created
# Log::Any::Adapter::Daemontools instance.)
#
use Log::Any::Adapter 'Daemontools',
argv => {
bundle => 1,
verbose => '-v', # none of that silly long-option stuff for us!
quiet => '-q',
stop => qr/^[^-]/, # Stop at the first non-option argument
};
# Now use our own signal handler to reload a config file that specifies
# a log level:
$SIG{HUP}= sub {
MyApp->load_my_config_file();
Log::Any::Adapter::Daemontools->global_log_level( MyApp->config->{log_level} );
};
DESCRIPTION
In the daemontools way of thinking, a daemon writes all its logging output to STDOUT/STDERR, which is a pipe to a logger process. Doing this instead of other logging alternatives keeps your program simple and allows you to capture errors generated by deeper libraries (like libc) which write debugging info to STDOUT/STDERR.
When logging to a pipe, you lose the log level information. An elegantly simple way to preserve this information is to prefix each line with "error:" or etc. prefixes, which can be re-parsed later.
Another frequent desire is to request that a long-lived daemon change its logging level on the fly. One way this is handled is by sending SIGUSR1/SIGUSR2 to tell the daemon to raise/lower the logging level. Likewise people often want to use "-v" or "-q" command line options to the same effect when running it from the command line.
This module provides a convenient way for you to configure all of that from a single "use" line.
VERSION NOTICE
NOTE: Version 0.1 lost some of the features of version 0.002 when the internals of Log::Any changed in a way that made them impossible. I don't know if anyone was using them anyway, but pay close attention if you are upgrading. This new version adheres more closely to the specification for a logging adapter.
ATTRIBUTES
config
This package can only be configured once. If 'config' is passed as an argument to the adapter constuctor it will only be processed when the first adapter is created. The purpose is to allow you to say
use Log::Any::Adapter 'Daemontools', config => { initial_options... };
and not have to call a bunch of package methods.
- env
-
env => $name_or_args
Convenient passthrough to process_env package method.
If env is a hashref, it is passed directly. If it is a scalar, it is interpreted as a pre-defined "profile" of arguments.
Profiles:
-
{ debug => 'DEBUG' }
-
- argv
-
argv => $name_or_args
Convenient passthrough to process_argv package method.
If argv is a hashref, it is passed directly. If it is a scalar, it is interpreted as a pre-defined "profile" of arguments.
Profiles:
-
{ bundle => 1, verbose => qr/^(--verbose|-v)$/, quiet => qr/^(--quiet|-q)$/, stop => '--' }
-
- signals
-
signals => [ $v, $q ], signals => { verbose => $v, quiet => $q },
Convenient passthrough to handle_signals package method.
If handle_signals is an arrayref of length 2, they are used as the verbose and quiet parameters, respectively. If it is a hashref, it is passed directly. No other type of value is supported, currently.
- level
-
global_log_level => $name global_log_level => $number
Sets the initial value of the global log level, which can be altered later and apply to all adapters that don't have log_level overridden. See global_log_level
- level_min
-
Initial value for global_log_level_min
- level_max
-
Initial value for global_log_level_max
- category_level
-
Hashref of category names to the initial log level for each. Note that categories with a specified log level will no longer be controlled by changing the global log level.
See category_log_level package method.
- category_min
-
Sets the category_log_level_min initial value. This could be used to prevent important logging streams from getting silenced even on the most extreme 'quiet' level.
- category_max
-
Sets the category_log_level_max initial value. This could be used to prevent certain modules form getting too noisy at a level of 'trace'.
PACKAGE METHODS
process_env
$class->process_env( debug => $ENV_VAR_NAME );
# and/or
$class->process_env( log_level => $ENV_VAR_NAME );
Request that this package check for the named variable, and if it exists, interpret it either as a debug level or a log level, and then set the global log level used by this adapter.
A "debug level" refers to the typical Unix practice of a environment variable named DEBUG where increasing integer values results in more debugging output. This results in the following mapping: 2=trace, 1=debug 0=info -1=notice and so on. Larger numbers are clamped to 'trace'.
The other "log level" interpretation of numbers is that they represent the numeric Log::Any level (identical to numeric syslog levels) which you want to see. So the mapping for a LOG_LEVEL variable would be 8=trace, 7=debug, 6=info, etc.
Either type of variable can also be a named log level or alias, in which case it doesn't matter which type of variable it is. These are according to "numeric_level" in Log::Any::Adapter::Util.
process_argv
$class->process_argv( bundle => ..., verbose => ..., quiet => ..., stop => ..., remove => ... )
Scans (and optionally modifies) @ARGV using method parse_log_level_opts, with the supplied options, and updates the global log level accordingly.
parse_log_level_opts
$level_offset= $class->parse_log_level_opts(
array => $arrayref, # required
verbose => $strings_or_regexes,
quiet => $strings_or_regexes,
stop => $strings_or_regexes,
bundle => $bool, # defaults to false
remove => $bool, # defaults to false
);
Scans the elements of 'array' looking for patterns listed in 'verbose', 'quiet', or 'stop'. Each match of a pattern in 'quiet' subtracts one from the return value, and each match of a pattern in 'verbose' adds one. Stops iterating the array if any pattern in 'stop' matches.
If 'bundle' is true, then this routine will also split apart "bundled options", so for example
--foo -wbmvrcd --bar
is processed as if it were
--foo -w -b -m -v -r -c -d --bar
If 'remove' is true, then this routine will alter the array to remove matching elements for 'quiet' and 'verbose' patterns. It can also remove the bundled arguments if bundling is enabled:
@array= ( '--foo', '-qvvqlkj', '--verbose' );
my $n= parse_log_level_opts(
array => \@array,
quiet => [ '-q', '--quiet' ],
verbose => [ '-v', '--verbose' ],
bundle => 1,
remove => 1
);
# $n = -1
# @array = ( '--foo', '-lkj' );
handle_signals
$class->handle_signals( verbose => $signal_name, quiet => $signal_name );
Install signal handlers (probably USR1, USR2) which increase or decrease the log level.
Basically:
$SIG{ $verbose_name }= sub { Log::Any::Adapter::Daemontools->global_log_level('+= 1'); }
if $verbose_name;
$SIG{ $quiet_name }= sub { Log::Any::Adapter::Daemontools->global_log_level('-= 1'); }
if $quiet_name;
global_log_level
$class->global_log_level # returns level number
$class->global_log_level( 'info' ); # 6
$class->global_log_level( 3 ); # 3
$class->global_log_level( 99 ); # 8 (clamped to max)
$class->global_log_level( '+= 1' ); # 4
$class->global_log_level( '-= 9' ); # -1 (clamped to min)
$class->global_log_level( -1 ); # disable all logging
Log::Any::Adapter::Daemontools has a global variable that determines the logging level. This method gets or sets the default level. Level names are converted to numbers by "numeric_level" in Log::Any::Adapter::Util. If the level has a + or - prefix it will be added to the current level.
global_log_level_min
# Our app should never have 'fatal' squelched no matter how many '-q' the user gives us
use Log::Any::Adapter 'Daemontools' log_level_min => 'fatal';
# or
Log::Any::Adapter::Daemontools->global_log_level_min(2);
This accessor lets you get/set the minimum log level used to clamp the values of global_log_level.
global_log_level_max
# We've hacked around on our logging infrastructure and actually have trace2..trace5
Log::Any::Adapter::Daemontools->global_log_level_max(12);
Get/Sets the value used for clamping global_log_level.
category_log_level
$class->category_log_level($name); # returns level number
$class->category_log_level($name => 1) # 1
$class->category_log_level($name => 'info'); # 6
$class->category_log_level($name => undef); # back to global default
$class->category_log_level($name =>
# And the API wouldn't be complete if you couldn't set your own
# upper/lower bounds on the logging level...
$class->category_log_level_min($name => $min)
$class->category_log_level_max($name => $max)
Log::Any::Adapter::Daemontools can override the global logging level on a per-category basis. Once set to a value, this category will no longer see changes to the default global level. You can restore it to the default by setting the category level to undef.
category_log_level_min
See category_log_level
category_log_level_max
See category_log_level
METHODS
Adapter instances support all the standard logging methods of Log::Any::Adapter
AUTHOR
Michael Conrad <mike@nrdvana.net>
COPYRIGHT AND LICENSE
This software is copyright (c) 2016 by Michael Conrad.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.