AnyEvent
view release on metacpan or search on metacpan
lib/AnyEvent/Log.pm view on Meta::CPAN
$_[0][0] = $_[1] if @_ > 1;
$_[0][0]
}
=back
=head3 LOGGING LEVELS
The following methods deal with the logging level set associated with the
log context.
The most common method to use is probably C<< $ctx->level ($level) >>,
which configures the specified and any higher priority levels.
All functions which accept a list of levels also accept the special string
C<all> which expands to all logging levels.
=over 4
=item $ctx->levels ($level[, $level...)
Enables logging for the given levels and disables it for all others.
=item $ctx->level ($level)
Enables logging for the given level and all lower level (higher priority)
ones. In addition to normal logging levels, specifying a level of C<0> or
C<off> disables all logging for this level.
Example: log warnings, errors and higher priority messages.
$ctx->level ("warn");
$ctx->level (5); # same thing, just numeric
=item $ctx->enable ($level[, $level...])
Enables logging for the given levels, leaving all others unchanged.
=item $ctx->disable ($level[, $level...])
Disables logging for the given levels, leaving all others unchanged.
=item $ctx->cap ($level)
Caps the maximum priority to the given level, for all messages logged
to, or passing through, this context. That is, while this doesn't affect
whether a message is logged or passed on, the maximum priority of messages
will be limited to the specified level - messages with a higher priority
will be set to the specified priority.
Another way to view this is that C<< ->level >> filters out messages with
a too low priority, while C<< ->cap >> modifies messages with a too high
priority.
This is useful when different log targets have different interpretations
of priority. For example, for a specific command line program, a wrong
command line switch might well result in a C<fatal> log message, while the
same message, logged to syslog, is likely I<not> fatal to the system or
syslog facility as a whole, but more likely a mere C<error>.
This can be modeled by having a stderr logger that logs messages "as-is"
and a syslog logger that logs messages with a level cap of, say, C<error>,
or, for truly system-critical components, actually C<critical>.
=cut
sub _lvl_lst {
map {
$_ > 0 && $_ <= 9 ? $_+0
: $_ eq "all" ? (1 .. 9)
: $STR2LEVEL{$_} || Carp::croak "$_: not a valid logging level, caught"
} @_
}
sub _lvl {
$_[0] =~ /^(?:0|off|none)$/ ? 0 : (_lvl_lst $_[0])[-1]
}
our $NOP_CB = sub { 0 };
sub levels {
my $ctx = shift;
$ctx->[1] = 0;
$ctx->[1] |= 1 << $_
for &_lvl_lst;
AnyEvent::Log::_reassess;
}
sub level {
my $ctx = shift;
$ctx->[1] = ((1 << &_lvl) - 1) << 1;
AnyEvent::Log::_reassess;
}
sub enable {
my $ctx = shift;
$ctx->[1] |= 1 << $_
for &_lvl_lst;
AnyEvent::Log::_reassess;
}
sub disable {
my $ctx = shift;
$ctx->[1] &= ~(1 << $_)
for &_lvl_lst;
AnyEvent::Log::_reassess;
}
sub cap {
my $ctx = shift;
$ctx->[5] = &_lvl;
}
=back
=head3 SLAVE CONTEXTS
The following methods attach and detach another logging context to a
logging context.
Log messages are propagated to all slave contexts, unless the logging
lib/AnyEvent/Log.pm view on Meta::CPAN
});
$facility ||= "user";
$ctx->log_cb (sub {
my $lvl = $_[0][0] < 9 ? $_[0][0] : 8;
Sys::Syslog::syslog ("$facility|" . ($lvl - 1), $_)
for split /\n/, $_[0][1];
0
});
}
=back
=head3 MESSAGE LOGGING
These methods allow you to log messages directly to a context, without
going via your package context.
=over 4
=item $ctx->log ($level, $msg[, @params])
Same as C<AnyEvent::Log::log>, but uses the given context as log context.
Example: log a message in the context of another package.
(AnyEvent::Log::ctx "Other::Package")->log (warn => "heely bo");
=item $logger = $ctx->logger ($level[, \$enabled])
Same as C<AnyEvent::Log::logger>, but uses the given context as log
context.
=cut
*log = \&AnyEvent::Log::_log;
*logger = \&AnyEvent::Log::_logger;
=back
=cut
package AnyEvent::Log;
=head1 CONFIGURATION VIA $ENV{PERL_ANYEVENT_LOG}
Logging can also be configured by setting the environment variable
C<PERL_ANYEVENT_LOG> (or C<AE_LOG>).
The value consists of one or more logging context specifications separated
by C<:> or whitespace. Each logging specification in turn starts with a
context name, followed by C<=>, followed by zero or more comma-separated
configuration directives, here are some examples:
# set default logging level
filter=warn
# log to file instead of to stderr
log=file=/tmp/mylog
# log to file in addition to stderr
log=+%file:%file=file=/tmp/mylog
# enable debug log messages, log warnings and above to syslog
filter=debug:log=+%warnings:%warnings=warn,syslog=LOG_LOCAL0
# log trace messages (only) from AnyEvent::Debug to file
AnyEvent::Debug=+%trace:%trace=only,trace,file=/tmp/tracelog
A context name in the log specification can be any of the following:
=over 4
=item C<collect>, C<filter>, C<log>
Correspond to the three predefined C<$AnyEvent::Log::COLLECT>,
C<AnyEvent::Log::FILTER> and C<$AnyEvent::Log::LOG> contexts.
=item C<%name>
Context names starting with a C<%> are anonymous contexts created when the
name is first mentioned. The difference to package contexts is that by
default they have no attached slaves.
This makes it possible to create new log contexts that can be refered to
multiple times by name within the same log specification.
=item a perl package name
Any other string references the logging context associated with the given
Perl C<package>. In the unlikely case where you want to specify a package
context that matches on of the other context name forms, you can add a
C<::> to the package name to force interpretation as a package.
=back
The configuration specifications can be any number of the following:
=over 4
=item C<stderr>
Configures the context to use Perl's C<warn> function (which typically
logs to C<STDERR>). Works like C<log_to_warn>.
=item C<file=>I<path>
Configures the context to log to a file with the given path. Works like
C<log_to_file>.
=item C<path=>I<path>
Configures the context to log to a file with the given path. Works like
C<log_to_path>.
=item C<syslog> or C<syslog=>I<expr>
Configures the context to log to syslog. If I<expr> is given, then it is
evaluated in the L<Sys::Syslog> package, so you could use:
log=syslog=LOG_LOCAL0
=item C<nolog>
Configures the context to not log anything by itself, which is the
default. Same as C<< $ctx->log_cb (undef) >>.
=item C<cap=>I<level>
Caps logging messages entering this context at the given level, i.e.
reduces the priority of messages with higher priority than this level. The
default is C<0> (or C<off>), meaning the priority will not be touched.
=item C<0> or C<off>
Sets the logging level of the context to C<0>, i.e. all messages will be
filtered out.
=item C<all>
Enables all logging levels, i.e. filtering will effectively be switched
off (the default).
=item C<only>
Disables all logging levels, and changes the interpretation of following
level specifications to enable the specified level only.
Example: only enable debug messages for a context.
context=only,debug
=item C<except>
Enables all logging levels, and changes the interpretation of following
level specifications to disable that level. Rarely used.
Example: enable all logging levels except fatal and trace (this is rather
nonsensical).
filter=exept,fatal,trace
lib/AnyEvent/Log.pm view on Meta::CPAN
=item C<+>I<context>
Attaches the named context as slave to the context.
=item C<+>
A lone C<+> detaches all contexts, i.e. clears the slave list from the
context. Anonymous (C<%name>) contexts have no attached slaves by default,
but package contexts have the parent context as slave by default.
Example: log messages from My::Module to a file, do not send them to the
default log collector.
My::Module=+,file=/tmp/mymodulelog
=back
Any character can be escaped by prefixing it with a C<\> (backslash), as
usual, so to log to a file containing a comma, colon, backslash and some
spaces in the filename, you would do this:
PERL_ANYEVENT_LOG='log=file=/some\ \:file\ with\,\ \\-escapes'
Since whitespace (which includes newlines) is allowed, it is fine to
specify multiple lines in C<PERL_ANYEVENT_LOG>, e.g.:
PERL_ANYEVENT_LOG="
filter=warn
AnyEvent::Debug=+%trace
%trace=only,trace,+log
" myprog
Also, in the unlikely case when you want to concatenate specifications,
use whitespace as separator, as C<::> will be interpreted as part of a
module name, an empty spec with two separators:
PERL_ANYEVENT_LOG="$PERL_ANYEVENT_LOG MyMod=debug"
=cut
for (my $spec = $ENV{PERL_ANYEVENT_LOG}) {
my %anon;
my $pkg = sub {
$_[0] eq "log" ? $LOG
: $_[0] eq "filter" ? $FILTER
: $_[0] eq "collect" ? $COLLECT
: $_[0] =~ /^%(.+)$/ ? ($anon{$1} ||= do { my $ctx = ctx undef; $ctx->[0] = $_[0]; $ctx })
: $_[0] =~ /^(.*?)(?:::)?$/ ? ctx "$1" # egad :/
: die # never reached?
};
/\G[[:space:]]+/gc; # skip initial whitespace
while (/\G((?:[^:=[:space:]]+|::|\\.)+)=/gc) {
my $ctx = $pkg->($1);
my $level = "level";
while (/\G((?:[^,:[:space:]]+|::|\\.)+)/gc) {
for ("$1") {
if ($_ eq "stderr" ) { $ctx->log_to_warn;
} elsif (/^file=(.+)/ ) { $ctx->log_to_file ("$1");
} elsif (/^path=(.+)/ ) { $ctx->log_to_path ("$1");
} elsif (/^syslog(?:=(.*))?/ ) { require Sys::Syslog; $ctx->log_to_syslog ("$1");
} elsif ($_ eq "nolog" ) { $ctx->log_cb (undef);
} elsif (/^cap=(.+)/ ) { $ctx->cap ("$1");
} elsif (/^\+(.+)$/ ) { $ctx->attach ($pkg->("$1"));
} elsif ($_ eq "+" ) { $ctx->slaves;
} elsif ($_ eq "off" or $_ eq "0") { $ctx->level (0);
} elsif ($_ eq "all" ) { $ctx->level ("all");
} elsif ($_ eq "level" ) { $ctx->level ("all"); $level = "level";
} elsif ($_ eq "only" ) { $ctx->level ("off"); $level = "enable";
} elsif ($_ eq "except" ) { $ctx->level ("all"); $level = "disable";
} elsif (/^\d$/ ) { $ctx->$level ($_);
} elsif (exists $STR2LEVEL{$_} ) { $ctx->$level ($_);
} else { die "PERL_ANYEVENT_LOG ($spec): parse error at '$_'\n";
}
}
/\G,/gc or last;
}
/\G[:[:space:]]+/gc or last;
}
/\G[[:space:]]+/gc; # skip trailing whitespace
if (/\G(.+)/g) {
die "PERL_ANYEVENT_LOG ($spec): parse error at '$1'\n";
}
}
=head1 EXAMPLES
This section shows some common configurations, both as code, and as
C<PERL_ANYEVENT_LOG> string.
=over 4
=item Setting the global logging level.
Either put C<PERL_ANYEVENT_VERBOSE=><number> into your environment before
running your program, use C<PERL_ANYEVENT_LOG> or modify the log level of
the root context at runtime:
PERL_ANYEVENT_VERBOSE=5 ./myprog
PERL_ANYEVENT_LOG=log=warn
$AnyEvent::Log::FILTER->level ("warn");
=item Append all messages to a file instead of sending them to STDERR.
This is affected by the global logging level.
$AnyEvent::Log::LOG->log_to_file ($path);
PERL_ANYEVENT_LOG=log=file=/some/path
=item Write all messages with priority C<error> and higher to a file.
( run in 2.347 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )