Initial Commit

This commit is contained in:
Riley Schneider
2025-12-03 16:38:10 +01:00
parent c5e26bf594
commit b732d8d4b5
17680 changed files with 5977495 additions and 2 deletions

View File

@@ -0,0 +1,40 @@
# Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>].
# For other contributors see ChangeLog.
# See the manual pages for details on the licensing terms.
# Pod stripped from pm file by OODoc 2.02.
# This code is part of distribution Log-Report. Meta-POD processed with
# OODoc into POD and HTML manual-pages. See README.md
# Copyright Mark Overmeer. Licensed under the same terms as Perl itself.
package Log::Report::Dispatcher::Callback;
use vars '$VERSION';
$VERSION = '1.31';
use base 'Log::Report::Dispatcher';
use warnings;
use strict;
use Log::Report 'log-report';
sub init($)
{ my ($self, $args) = @_;
$self->SUPER::init($args);
$self->{callback} = $args->{callback}
or error __x"dispatcher {name} needs a 'callback'", name => $self->name;
$self;
}
sub callback() {shift->{callback}}
sub log($$$$)
{ my $self = shift;
$self->{callback}->($self, @_);
}
1;

View File

@@ -0,0 +1,187 @@
=encoding utf8
=head1 NAME
Log::Report::Dispatcher::Callback - call a code-ref for each log-line
=head1 INHERITANCE
Log::Report::Dispatcher::Callback
is a Log::Report::Dispatcher
=head1 SYNOPSIS
sub cb($$$)
{ my ($disp, $options, $reason, $message) = @_;
...
}
dispatcher Log::Report::Dispatcher::Callback => 'cb'
, callback => \&cb;
dispatcher CALLBACK => 'cb' # same
, callback => \&cb;
=head1 DESCRIPTION
This basic file logger accepts a callback, which is called for each
message which is to be logged. When you need complex things, you
may best make your own extension to L<Log::Report::Dispatcher|Log::Report::Dispatcher>, but
for simple things this will do.
Extends L<"DESCRIPTION" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DESCRIPTION">.
B<. Example>
sub send_mail($$$)
{ my ($disp, $options, $reason, $message) = @_;
my $msg = Mail::Send->new(Subject => $reason
, To => 'admin@localhost');
my $fh = $msg->open('sendmail');
print $fh $disp->translate($reason, $message);
close $fh;
}
dispatcher CALLBACK => 'mail', callback => \&send_mail;
=head1 METHODS
Extends L<"METHODS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"METHODS">.
=head2 Constructors
Extends L<"Constructors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Constructors">.
=over 4
=item $obj-E<gt>B<close>()
Inherited, see L<Log::Report::Dispatcher/"Constructors">
=item Log::Report::Dispatcher::Callback-E<gt>B<new>($type, $name, %options)
-Option --Defined in --Default
accept Log::Report::Dispatcher depend on mode
callback <required>
charset Log::Report::Dispatcher <undef>
format_reason Log::Report::Dispatcher 'LOWERCASE'
locale Log::Report::Dispatcher <system locale>
mode Log::Report::Dispatcher 'NORMAL'
=over 2
=item accept => REASONS
=item callback => CODE
Your C<callback> is called with five parameters: this dispatcher object,
the options, a reason and a message. The C<options> are the first
parameter of L<Log::Report::report()|Log::Report/"Report Production and Configuration"> (read over there). The C<reason>
is a capitized string like C<ERROR>. Then, the C<message> (is a
L<Log::Report::Message|Log::Report::Message>). Finally the text-domain of the message.
=item charset => CHARSET
=item format_reason => 'UPPERCASE'|'LOWERCASE'|'UCFIRST'|'IGNORE'|CODE
=item locale => LOCALE
=item mode => 'NORMAL'|'VERBOSE'|'ASSERT'|'DEBUG'|0..3
=back
=back
=head2 Accessors
Extends L<"Accessors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Accessors">.
=over 4
=item $obj-E<gt>B<callback>()
Returns the code reference which will handle each logged message.
=item $obj-E<gt>B<isDisabled>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<mode>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<name>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<needs>( [$reason] )
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<type>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=back
=head2 Logging
Extends L<"Logging" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Logging">.
=over 4
=item $obj-E<gt>B<addSkipStack>(@CODE)
=item Log::Report::Dispatcher::Callback-E<gt>B<addSkipStack>(@CODE)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<collectLocation>()
=item Log::Report::Dispatcher::Callback-E<gt>B<collectLocation>()
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<collectStack>( [$maxdepth] )
=item Log::Report::Dispatcher::Callback-E<gt>B<collectStack>( [$maxdepth] )
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<log>(HASH-$of-%options, $reason, $message, $domain)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<skipStack>()
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<stackTraceLine>(%options)
=item Log::Report::Dispatcher::Callback-E<gt>B<stackTraceLine>(%options)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<translate>(HASH-$of-%options, $reason, $message)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=back
=head1 DETAILS
Extends L<"DETAILS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DETAILS">.
=head1 SEE ALSO
This module is part of Log-Report distribution version 1.31,
built on January 15, 2021. Website: F<http://perl.overmeer.net/CPAN/>
=head1 LICENSE
Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
See F<http://dev.perl.org/licenses/>

View File

@@ -0,0 +1,165 @@
# Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>].
# For other contributors see ChangeLog.
# See the manual pages for details on the licensing terms.
# Pod stripped from pm file by OODoc 2.02.
# This code is part of distribution Log-Report. Meta-POD processed with
# OODoc into POD and HTML manual-pages. See README.md
# Copyright Mark Overmeer. Licensed under the same terms as Perl itself.
package Log::Report::Dispatcher::File;
use vars '$VERSION';
$VERSION = '1.31';
use base 'Log::Report::Dispatcher';
use warnings;
use strict;
use Log::Report 'log-report';
use IO::File ();
use POSIX qw/strftime/;
use Encode qw/find_encoding/;
use Fcntl qw/:flock/;
sub init($)
{ my ($self, $args) = @_;
if(!$args->{charset})
{ my $lc = $ENV{LC_CTYPE} || $ENV{LC_ALL} || $ENV{LANG} || '';
my $cs = $lc =~ m/\.([\w-]+)/ ? $1 : '';
$args->{charset} = length $cs && find_encoding $cs ? $cs : undef;
}
$self->SUPER::init($args);
my $name = $self->name;
$self->{to} = $args->{to}
or error __x"dispatcher {name} needs parameter 'to'", name => $name;
$self->{replace} = $args->{replace} || 0;
my $format = $args->{format} || sub { '['.localtime()."] $_[0]" };
$self->{LRDF_format}
= ref $format eq 'CODE' ? $format
: $format eq 'LONG'
? sub { my $msg = shift;
my $domain = shift || '-';
my $stamp = strftime "%Y-%m-%dT%H:%M:%S", gmtime;
"[$stamp $$] $domain $msg"
}
: error __x"unknown format parameter `{what}'"
, what => ref $format || $format;
$self;
}
sub close()
{ my $self = shift;
$self->SUPER::close
or return;
my $to = $self->{to};
my @close
= ref $to eq 'CODE' ? values %{$self->{LRDF_out}}
: $self->{LRDF_filename} ? $self->{LRDF_output}
: ();
$_ && $_->close for @close;
$self;
}
#-----------
sub filename() {shift->{LRDF_filename}}
sub format() {shift->{LRDF_format}}
sub output($)
{ # fast simple case
return $_[0]->{LRDF_output} if $_[0]->{LRDF_output};
my ($self, $msg) = @_;
my $name = $self->name;
my $to = $self->{to};
if(!ref $to)
{ # constant file name
$self->{LRDF_filename} = $to;
my $binmode = $self->{replace} ? '>' : '>>';
my $f = $self->{LRDF_output} = IO::File->new($to, $binmode);
unless($f)
{ # avoid logging error to myself (issue #4)
my $msg = __x"cannot write log into {file} with mode '{binmode}'"
, binmode => $binmode, file => $to;
if(my @disp = grep $_->name ne $name, Log::Report::dispatcher('list'))
{ $msg->to($disp[0]->name);
error $msg;
}
else
{ die $msg;
}
}
$f->autoflush;
return $self->{LRDF_output} = $f;
}
if(ref $to eq 'CODE')
{ # variable filename
my $fn = $self->{LRDF_filename} = $to->($self, $msg);
return $self->{LRDF_output} = $self->{LRDF_out}{$fn};
}
# probably file-handle
$self->{LRDF_output} = $to;
}
#-----------
sub rotate($)
{ my ($self, $old) = @_;
my $to = $self->{to};
my $logs = ref $to eq 'CODE' ? $self->{LRDF_out}
: +{ $self->{to} => $self->{LRDF_output} };
while(my ($log, $fh) = each %$logs)
{ !ref $log
or error __x"cannot rotate log file which was opened as file-handle";
my $oldfn = ref $old eq 'CODE' ? $old->($log) : $old;
trace "rotating $log to $oldfn";
rename $log, $oldfn
or fault __x"unable to rotate logfile {fn} to {oldfn}"
, fn => $log, oldfn => $oldfn;
$fh->close; # close after move not possible on Windows?
my $f = $self->{LRDF_output} = $logs->{$log} = IO::File->new($log, '>>')
or fault __x"cannot write log into {file}", file => $log;
$f->autoflush;
}
$self;
}
#-----------
sub log($$$$)
{ my ($self, $opts, $reason, $msg, $domain) = @_;
my $trans = $self->translate($opts, $reason, $msg);
my $text = $self->format->($trans, $domain, $msg, %$opts);
my $out = $self->output($msg);
flock $out, LOCK_EX;
$out->print($text);
flock $out, LOCK_UN;
}
1;

View File

@@ -0,0 +1,272 @@
=encoding utf8
=head1 NAME
Log::Report::Dispatcher::File - send messages to a file or file-handle
=head1 INHERITANCE
Log::Report::Dispatcher::File
is a Log::Report::Dispatcher
=head1 SYNOPSIS
dispatcher Log::Report::Dispatcher::File => 'stderr'
, to => \*STDERR, accept => 'NOTICE-';
# close a dispatcher
dispatcher close => 'stderr';
# let dispatcher open and close the file
dispatcher FILE => 'mylog', to => '/var/log/mylog'
, charset => 'utf-8';
...
dispatcher close => 'mylog'; # will close file
# open yourself, then also close yourself
open OUT, ">:encoding('iso-8859-1')", '/var/log/mylog'
or fault "...";
dispatcher FILE => 'mylog', to => \*OUT;
...
dispatcher close => 'mylog';
close OUT;
# dispatch into a scalar
my $output = '';
open $outfile, '>', \$output;
dispatcher FILE => 'into-scalar', to => \$outfile;
...
dispatcher close => 'into-scalar';
print $output;
=head1 DESCRIPTION
This basic file logger accepts an file-handle or filename as destination.
[1.00] writing to the file protected by a lock, so multiple processes
can write to the same file.
Extends L<"DESCRIPTION" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DESCRIPTION">.
=head1 METHODS
Extends L<"METHODS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"METHODS">.
=head2 Constructors
Extends L<"Constructors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Constructors">.
=over 4
=item $obj-E<gt>B<close>()
Only when initiated with a FILENAME, the file will be closed. In any
other case, nothing will be done.
=item Log::Report::Dispatcher::File-E<gt>B<new>($type, $name, %options)
-Option --Defined in --Default
accept Log::Report::Dispatcher depend on mode
charset Log::Report::Dispatcher LOCALE
format <adds timestamp>
format_reason Log::Report::Dispatcher 'LOWERCASE'
locale Log::Report::Dispatcher <system locale>
mode Log::Report::Dispatcher 'NORMAL'
replace false
to <required>
=over 2
=item accept => REASONS
=item charset => CHARSET
=item format => CODE|'LONG'
[1.00] process each printed line. By default, this adds a timestamp,
but you may want to add hostname, process number, or more.
format => sub { '['.localtime().'] '.$_[0] }
format => sub { shift } # no timestamp
format => 'LONG'
The first parameter to format is the string to print; it is already
translated and trailed by a newline. The second parameter is the
text-domain (if known).
[1.10] As third parameter, you get the $msg raw object as well (maybe
you want to use the message context?)
[1.19] After the three positional parameters, there may be a list
of pairs providing additional facts about the exception. It may
contain C<location> information.
The "LONG" format is equivalent to:
my $t = strftime "%FT%T", gmtime;
"[$t $$] $_[1] $_[0]"
Use of context:
format => sub { my ($msgstr, $domain, $msg, %more) = @_;
my $host = $msg->context->{host};
"$host $msgstr";
}
=item format_reason => 'UPPERCASE'|'LOWERCASE'|'UCFIRST'|'IGNORE'|CODE
=item locale => LOCALE
=item mode => 'NORMAL'|'VERBOSE'|'ASSERT'|'DEBUG'|0..3
=item replace => BOOLEAN
Only used in combination with a FILENAME: throw away the old file
if it exists. Probably you wish to append to existing information.
Use the LOCALE setting by default, which is LC_CTYPE or LC_ALL or LANG
(in that order). If these contain a character-set which Perl understands,
then that is used, otherwise silently ignored.
=item to => FILENAME|FILEHANDLE|OBJECT|CODE
You can either specify a FILENAME, which is opened in append mode with
autoflush on. Or pass any kind of FILE-HANDLE or some OBJECT which
implements a C<print()> method. You probably want to have autoflush
enabled on your FILE-HANDLES.
When cleaning-up the dispatcher, the file will only be closed in case
of a FILENAME.
[1.10] When you pass a CODE, then for each log message the function is
called with two arguments: this dispatcher object and the message object.
In some way (maybe via the message context) you have to determine the
log filename. This means that probably many log-files are open at the
same time.
# configuration time
dispatcher FILE => 'logfile', to =>
sub { my ($disp, $msg) = @_; $msg->context->{logfile} };
# whenever you want to change the logfile
textdomain->updateContext(logfile => '/var/log/app');
(textdomain 'mydomain')->setContext(logfile => '/var/log/app');
# or
error __x"help", _context => {logfile => '/dev/tty'};
error __x"help", _context => "logfile=/dev/tty";
=back
=back
=head2 Accessors
Extends L<"Accessors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Accessors">.
=over 4
=item $obj-E<gt>B<filename>()
Returns the name of the opened file, or C<undef> in case this dispatcher
was started from a file-handle or file-object.
=item $obj-E<gt>B<format>()
=item $obj-E<gt>B<isDisabled>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<mode>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<name>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<needs>( [$reason] )
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<output>($msg)
Returns the file-handle to write the log lines to. [1.10] This may
depend on the $msg (especially message context)
=item $obj-E<gt>B<type>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=back
=head2 File maintenance
=over 4
=item $obj-E<gt>B<rotate>($filename|CODE)
[1.00] Move the current file to $filename, and start a new file.
=back
=head2 Logging
Extends L<"Logging" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Logging">.
=over 4
=item $obj-E<gt>B<addSkipStack>(@CODE)
=item Log::Report::Dispatcher::File-E<gt>B<addSkipStack>(@CODE)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<collectLocation>()
=item Log::Report::Dispatcher::File-E<gt>B<collectLocation>()
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<collectStack>( [$maxdepth] )
=item Log::Report::Dispatcher::File-E<gt>B<collectStack>( [$maxdepth] )
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<log>(HASH-$of-%options, $reason, $message, $domain)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<skipStack>()
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<stackTraceLine>(%options)
=item Log::Report::Dispatcher::File-E<gt>B<stackTraceLine>(%options)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<translate>(HASH-$of-%options, $reason, $message)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=back
=head1 DETAILS
Extends L<"DETAILS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DETAILS">.
=head1 SEE ALSO
This module is part of Log-Report distribution version 1.31,
built on January 15, 2021. Website: F<http://perl.overmeer.net/CPAN/>
=head1 LICENSE
Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
See F<http://dev.perl.org/licenses/>

View File

@@ -0,0 +1,111 @@
# Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>].
# For other contributors see ChangeLog.
# See the manual pages for details on the licensing terms.
# Pod stripped from pm file by OODoc 2.02.
# This code is part of distribution Log-Report. Meta-POD processed with
# OODoc into POD and HTML manual-pages. See README.md
# Copyright Mark Overmeer. Licensed under the same terms as Perl itself.
package Log::Report::Dispatcher::Log4perl;
use vars '$VERSION';
$VERSION = '1.31';
use base 'Log::Report::Dispatcher';
use warnings;
use strict;
use Log::Report 'log-report';
use Log::Report::Util qw/@reasons expand_reasons/;
use Log::Log4perl qw/:levels/;
my %default_reasonToLevel =
( TRACE => $DEBUG
, ASSERT => $DEBUG
, INFO => $INFO
, NOTICE => $INFO
, WARNING => $WARN
, MISTAKE => $WARN
, ERROR => $ERROR
, FAULT => $ERROR
, ALERT => $FATAL
, FAILURE => $FATAL
, PANIC => $FATAL
);
@reasons==keys %default_reasonToLevel
or panic __"Not all reasons have a default translation";
# Do not show these as source of the error: one or more caller frames up
Log::Log4perl->wrapper_register($_) for qw/
Log::Report
Log::Report::Dispatcher
Log::Report::Dispatcher::Try
/;
sub init($)
{ my ($self, $args) = @_;
$args->{accept} ||= 'ALL';
$self->SUPER::init($args);
my $name = $self->name;
$self->{LRDL_levels} = { %default_reasonToLevel };
if(my $to_level = delete $args->{to_level})
{ my @to = @$to_level;
while(@to)
{ my ($reasons, $level) = splice @to, 0, 2;
my @reasons = expand_reasons $reasons;
$level =~ m/^[0-5]$/
or error __x "Log4perl level '{level}' must be in 0-5"
, level => $level;
$self->{LRDL_levels}{$_} = $level for @reasons;
}
}
if(my $config = delete $args->{config}) {
Log::Log4perl->init($config) or return;
}
$self;
}
#sub close()
#{ my $self = shift;
# $self->SUPER::close or return;
# $self;
#}
sub logger(;$)
{ my ($self, $domain) = @_;
defined $domain
or return Log::Log4perl->get_logger($self->name);
# get_logger() creates a logger if that does not exist. But we
# want to route it to default
$Log::Log4perl::LOGGERS_BY_NAME->{$domain}
||= Log::Log4perl->get_logger($self->name);
}
sub log($$$$)
{ my ($self, $opts, $reason, $msg, $domain) = @_;
my $text = $self->translate($opts, $reason, $msg) or return;
my $level = $self->reasonToLevel($reason);
local $Log::Log4perl::caller_depth = $Log::Log4perl::caller_depth + 3;
$text =~ s/\s+$//s; # log4perl adds own \n
$self->logger($domain)->log($level, $text);
$self;
}
sub reasonToLevel($) { $_[0]->{LRDL_levels}{$_[1]} }
1;

View File

@@ -0,0 +1,243 @@
=encoding utf8
=head1 NAME
Log::Report::Dispatcher::Log4perl - send messages to Log::Log4perl back-end
=head1 INHERITANCE
Log::Report::Dispatcher::Log4perl
is a Log::Report::Dispatcher
=head1 SYNOPSIS
# start using log4perl via a config file
# The name of the dispatcher is the name of the default category.
dispatcher LOG4PERL => 'logger'
, accept => 'NOTICE-'
, config => "$ENV{HOME}/.log.conf";
# disable default dispatcher
dispatcher close => 'logger';
# configuration inline, not in file: adapted from the Log4perl manpage
my $name = 'logger';
my $outfile = '/tmp/a.log';
my $config = <<__CONFIG;
log4perl.category.$name = INFO, Logfile
log4perl.logger.Logfile = Log::Log4perl::Appender::File
log4perl.logger.Logfile.filename = $outfn
log4perl.logger.Logfile.layout = Log::Log4perl::Layout::PatternLayout
log4perl.logger.Logfile.layout.ConversionPattern = %d %F{1} %L> %m
__CONFIG
dispatcher LOG4PERL => $name, config => \$config;
=head1 DESCRIPTION
This dispatchers produces output tot syslog, based on the C<Sys::Log4perl>
module (which will not be automatically installed for you).
Extends L<"DESCRIPTION" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DESCRIPTION">.
=head2 Reasons <--> Levels
The REASONs for a message in L<Log::Report|Log::Report> are names quite similar to
the log levels used by Log::Log4perl. The default mapping is list
below. You can change the mapping using L<new(to_level)|Log::Report::Dispatcher::Log4perl/"Constructors">.
TRACE => $DEBUG ERROR => $ERROR
ASSERT => $DEBUG FAULT => $ERROR
INFO => $INFO ALERT => $FATAL
NOTICE => $INFO FAILURE => $FATAL
WARNING => $WARN PANIC => $FATAL
MISTAKE => $WARN
=head2 Categories
C<Log::Report> uses text-domains for translation tables. These are
also used as categories for the Log4perl infrastructure. So, typically
every module start with:
use Log::Report 'my-text-domain', %more_options;
Now, if there is a logger inside the log4perl configuration which is
named 'my-text-domain', that will be used. Otherwise, the name of the
dispatcher is used to select the logger.
=head3 Limitiations
The global C<$caller_depth> concept of Log::Log4perl is broken.
That variable is used to find the filename and line number of the logged
messages. But these messages may have been caught, rerouted, eval'ed, and
otherwise followed a unpredictable multi-leveled path before it reached
the Log::Log4perl dispatcher. This means that layout patterns C<%F>
and C<%L> are not useful in the generic case, maybe in your specific case.
=head1 METHODS
Extends L<"METHODS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"METHODS">.
=head2 Constructors
Extends L<"Constructors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Constructors">.
=over 4
=item $obj-E<gt>B<close>()
Inherited, see L<Log::Report::Dispatcher/"Constructors">
=item Log::Report::Dispatcher::Log4perl-E<gt>B<new>($type, $name, %options)
The Log::Log4perl infrastructure has all settings in a configuration
file. In that file, you should find a category with the $name.
-Option --Defined in --Default
accept Log::Report::Dispatcher 'ALL'
charset Log::Report::Dispatcher <undef>
config <undef>
format_reason Log::Report::Dispatcher 'LOWERCASE'
locale Log::Report::Dispatcher <system locale>
mode Log::Report::Dispatcher 'NORMAL'
to_level []
=over 2
=item accept => REASONS
=item charset => CHARSET
=item config => FILENAME|SCALAR
When a SCALAR reference is passed in, that must refer to a string which
contains the configuration text. Otherwise, specify an existing FILENAME.
By default, it is expected that Log::Log4perl has been initialized
externally. That module uses global variables to communicate, which
should be present before any logging is attempted.
=item format_reason => 'UPPERCASE'|'LOWERCASE'|'UCFIRST'|'IGNORE'|CODE
=item locale => LOCALE
=item mode => 'NORMAL'|'VERBOSE'|'ASSERT'|'DEBUG'|0..3
=item to_level => ARRAY-of-PAIRS
See L<reasonToLevel()|Log::Report::Dispatcher::Log4perl/"Logging">.
=back
=back
=head2 Accessors
Extends L<"Accessors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Accessors">.
=over 4
=item $obj-E<gt>B<isDisabled>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<logger>( [$domain] )
Returns the Log::Log4perl::Logger object which is used for logging.
When there is no specific logger for this $domain (logger with the exact
name of the $domain) the default logger is being used, with the name of
this dispatcher.
=item $obj-E<gt>B<mode>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<name>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<needs>( [$reason] )
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<type>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=back
=head2 Logging
Extends L<"Logging" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Logging">.
=over 4
=item $obj-E<gt>B<addSkipStack>(@CODE)
=item Log::Report::Dispatcher::Log4perl-E<gt>B<addSkipStack>(@CODE)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<collectLocation>()
=item Log::Report::Dispatcher::Log4perl-E<gt>B<collectLocation>()
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<collectStack>( [$maxdepth] )
=item Log::Report::Dispatcher::Log4perl-E<gt>B<collectStack>( [$maxdepth] )
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<log>(HASH-$of-%options, $reason, $message, $domain)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<reasonToLevel>($reason)
Returns a level which is understood by Log::Dispatch, based on
a translation table. This can be changed with L<new(to_level)|Log::Report::Dispatcher::Log4perl/"Constructors">.
example:
use Log::Log4perl qw/:levels/;
# by default, ALERTs are output as $FATAL
dispatcher Log::Log4perl => 'logger'
, to_level => [ ALERT => $ERROR, ]
, ...;
=item $obj-E<gt>B<skipStack>()
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<stackTraceLine>(%options)
=item Log::Report::Dispatcher::Log4perl-E<gt>B<stackTraceLine>(%options)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<translate>(HASH-$of-%options, $reason, $message)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=back
=head1 DETAILS
Extends L<"DETAILS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DETAILS">.
=head1 SEE ALSO
This module is part of Log-Report distribution version 1.31,
built on January 15, 2021. Website: F<http://perl.overmeer.net/CPAN/>
=head1 LICENSE
Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
See F<http://dev.perl.org/licenses/>

View File

@@ -0,0 +1,90 @@
# Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>].
# For other contributors see ChangeLog.
# See the manual pages for details on the licensing terms.
# Pod stripped from pm file by OODoc 2.02.
# This code is part of distribution Log-Report. Meta-POD processed with
# OODoc into POD and HTML manual-pages. See README.md
# Copyright Mark Overmeer. Licensed under the same terms as Perl itself.
package Log::Report::Dispatcher::LogDispatch;
use vars '$VERSION';
$VERSION = '1.31';
use base 'Log::Report::Dispatcher';
use warnings;
use strict;
use Log::Report 'log-report', syntax => 'SHORT';
use Log::Report::Util qw/@reasons expand_reasons/;
use Log::Dispatch 2.00;
my %default_reasonToLevel =
( TRACE => 'debug'
, ASSERT => 'debug'
, INFO => 'info'
, NOTICE => 'notice'
, WARNING => 'warning'
, MISTAKE => 'warning'
, ERROR => 'error'
, FAULT => 'error'
, ALERT => 'alert'
, FAILURE => 'emergency'
, PANIC => 'critical'
);
@reasons != keys %default_reasonToLevel
and panic __"Not all reasons have a default translation";
sub init($)
{ my ($self, $args) = @_;
$self->SUPER::init($args);
$args->{name} = $self->name;
$args->{min_level} ||= 'debug';
$self->{level} = { %default_reasonToLevel };
if(my $to_level = delete $args->{to_level})
{ my @to = @$to_level;
while(@to)
{ my ($reasons, $level) = splice @to, 0, 2;
my @reasons = expand_reasons $reasons;
Log::Dispatch->level_is_valid($level)
or error __x"Log::Dispatch level '{level}' not understood"
, level => $level;
$self->{level}{$_} = $level for @reasons;
}
}
$self->{backend} = $self->type->new(%$args);
$self;
}
sub close()
{ my $self = shift;
$self->SUPER::close or return;
delete $self->{backend};
$self;
}
sub backend() {shift->{backend}}
sub log($$$$$)
{ my $self = shift;
my $text = $self->translate(@_) or return;
my $level = $self->reasonToLevel($_[1]);
$self->backend->log(level => $level, message => $text);
$self;
}
sub reasonToLevel($) { $_[0]->{level}{$_[1]} }
1;

View File

@@ -0,0 +1,207 @@
=encoding utf8
=head1 NAME
Log::Report::Dispatcher::LogDispatch - send messages to Log::Dispatch back-end
=head1 INHERITANCE
Log::Report::Dispatcher::LogDispatch
is a Log::Report::Dispatcher
=head1 SYNOPSIS
use Log::Dispatch::File;
dispatcher Log::Dispatch::File => 'logger', accept => 'NOTICE-'
, filename => 'logfile', to_level => [ 'ALERT-' => 'err' ];
# disable default dispatcher
dispatcher close => 'logger';
=head1 DESCRIPTION
This dispatchers produces output to and C<Log::Dispatch> back-end.
(which will NOT be automatically installed for you).
The REASON for a message often uses names which are quite similar to the
log-levels used by Log::Dispatch. However: they have a different
approach. The REASON of Log::Report limits the responsibility of the
programmer to indicate the cause of the message: whether it was able to
handle a certain situation. The Log::Dispatch levels are there for the
user's of the program. However: the programmer does not known anything
about the application (in the general case). This is cause of much of
the trickery in Perl programs.
The default translation table is list below. You can change the mapping
using L<new(to_level)|Log::Report::Dispatcher::LogDispatch/"Constructors">. See example in SYNOPSIS.
Extends L<"DESCRIPTION" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DESCRIPTION">.
=head1 METHODS
Extends L<"METHODS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"METHODS">.
=head2 Constructors
Extends L<"Constructors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Constructors">.
=over 4
=item $obj-E<gt>B<close>()
Inherited, see L<Log::Report::Dispatcher/"Constructors">
=item Log::Report::Dispatcher::LogDispatch-E<gt>B<new>($type, $name, %options)
The Log::Dispatch infrastructure has quite a large number of output
TYPEs, each extending the Log::Dispatch::Output base-class. You
do not create these objects yourself: Log::Report is doing it for you.
The Log::Dispatch back-ends are very careful with validating their
parameters, so you will need to restrict the options to what is supported
for the specific back-end. See their respective manual-pages. The errors
produced by the back-ends quite horrible and untranslated, sorry.
-Option --Defined in --Default
accept Log::Report::Dispatcher depend on mode
callbacks []
charset Log::Report::Dispatcher <undef>
format_reason Log::Report::Dispatcher 'LOWERCASE'
locale Log::Report::Dispatcher <system locale>
max_level undef
min_level debug
mode Log::Report::Dispatcher 'NORMAL'
to_level []
=over 2
=item accept => REASONS
=item callbacks => CODE|ARRAY-of-CODE
See Log::Dispatch::Output.
=item charset => CHARSET
=item format_reason => 'UPPERCASE'|'LOWERCASE'|'UCFIRST'|'IGNORE'|CODE
=item locale => LOCALE
=item max_level => LEVEL
Like C<min_level>.
=item min_level => LEVEL
Restrict the messages which are passed through based on the LEVEL,
so after the reason got translated into a Log::Dispatch compatible
LEVEL. The default will use Log::Report restrictions only.
=item mode => 'NORMAL'|'VERBOSE'|'ASSERT'|'DEBUG'|0..3
=item to_level => ARRAY-of-PAIRS
See L<reasonToLevel()|Log::Report::Dispatcher::LogDispatch/"Logging">.
=back
=back
=head2 Accessors
Extends L<"Accessors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Accessors">.
=over 4
=item $obj-E<gt>B<backend>()
Returns the Log::Dispatch::Output object which is used for logging.
=item $obj-E<gt>B<isDisabled>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<mode>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<name>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<needs>( [$reason] )
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<type>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=back
=head2 Logging
Extends L<"Logging" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Logging">.
=over 4
=item $obj-E<gt>B<addSkipStack>(@CODE)
=item Log::Report::Dispatcher::LogDispatch-E<gt>B<addSkipStack>(@CODE)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<collectLocation>()
=item Log::Report::Dispatcher::LogDispatch-E<gt>B<collectLocation>()
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<collectStack>( [$maxdepth] )
=item Log::Report::Dispatcher::LogDispatch-E<gt>B<collectStack>( [$maxdepth] )
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<log>(HASH-$of-%options, $reason, $message, $domain)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<reasonToLevel>($reason)
Returns a level which is understood by Log::Dispatch, based on
a translation table. This can be changed with L<new(to_level)|Log::Report::Dispatcher::LogDispatch/"Constructors">.
=item $obj-E<gt>B<skipStack>()
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<stackTraceLine>(%options)
=item Log::Report::Dispatcher::LogDispatch-E<gt>B<stackTraceLine>(%options)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<translate>(HASH-$of-%options, $reason, $message)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=back
=head1 DETAILS
Extends L<"DETAILS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DETAILS">.
=head1 SEE ALSO
This module is part of Log-Report distribution version 1.31,
built on January 15, 2021. Website: F<http://perl.overmeer.net/CPAN/>
=head1 LICENSE
Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
See F<http://dev.perl.org/licenses/>

View File

@@ -0,0 +1,29 @@
# Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>].
# For other contributors see ChangeLog.
# See the manual pages for details on the licensing terms.
# Pod stripped from pm file by OODoc 2.02.
# This code is part of distribution Log-Report. Meta-POD processed with
# OODoc into POD and HTML manual-pages. See README.md
# Copyright Mark Overmeer. Licensed under the same terms as Perl itself.
package Log::Report::Dispatcher::Perl;
use vars '$VERSION';
$VERSION = '1.31';
use base 'Log::Report::Dispatcher';
use warnings;
use strict;
use Log::Report 'log-report';
use IO::File;
my $singleton = 0; # can be only one (per thread)
sub log($$$$)
{ my ($self, $opts, $reason, $message, $domain) = @_;
print STDERR $self->translate($opts, $reason, $message);
}
1;

View File

@@ -0,0 +1,52 @@
=encoding utf8
=head1 NAME
Log::Report::Dispatcher::Perl - send messages to die and warn
=head1 INHERITANCE
Log::Report::Dispatcher::Perl
is a Log::Report::Dispatcher
=head1 SYNOPSIS
dispatcher Log::Report::Dispatcher::Perl => 'default'
, accept => 'NOTICE-';
# close the default dispatcher
dispatcher close => 'default';
=head1 DESCRIPTION
Ventilate the problem reports via the standard Perl error mechanisms:
C<die()>, C<warn()>, and C<print()>. There can be only one such dispatcher
(per thread), because once C<die()> is called, we are not able to return.
Therefore, this dispatcher will always be called last.
In the early releases of Log::Report, it tried to simulate the behavior
of warn and die using STDERR and exit; however: that is not possible.
Extends L<"DESCRIPTION" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DESCRIPTION">.
=head1 METHODS
Extends L<"METHODS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"METHODS">.
=head1 DETAILS
Extends L<"DETAILS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DETAILS">.
=head1 SEE ALSO
This module is part of Log-Report distribution version 1.31,
built on January 15, 2021. Website: F<http://perl.overmeer.net/CPAN/>
=head1 LICENSE
Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
See F<http://dev.perl.org/licenses/>

View File

@@ -0,0 +1,128 @@
# Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>].
# For other contributors see ChangeLog.
# See the manual pages for details on the licensing terms.
# Pod stripped from pm file by OODoc 2.02.
# This code is part of distribution Log-Report. Meta-POD processed with
# OODoc into POD and HTML manual-pages. See README.md
# Copyright Mark Overmeer. Licensed under the same terms as Perl itself.
package Log::Report::Dispatcher::Syslog;
use vars '$VERSION';
$VERSION = '1.31';
use base 'Log::Report::Dispatcher';
use warnings;
use strict;
use Log::Report 'log-report';
use Sys::Syslog qw/:standard :extended :macros/;
use Log::Report::Util qw/@reasons expand_reasons/;
use Encode qw/encode/;
use File::Basename qw/basename/;
my %default_reasonToPrio =
( TRACE => LOG_DEBUG
, ASSERT => LOG_DEBUG
, INFO => LOG_INFO
, NOTICE => LOG_NOTICE
, WARNING => LOG_WARNING
, MISTAKE => LOG_WARNING
, ERROR => LOG_ERR
, FAULT => LOG_ERR
, ALERT => LOG_ALERT
, FAILURE => LOG_EMERG
, PANIC => LOG_CRIT
);
@reasons==keys %default_reasonToPrio
or panic __"not all reasons have a default translation";
my $active;
sub init($)
{ my ($self, $args) = @_;
$args->{format_reason} ||= 'IGNORE';
$self->SUPER::init($args);
error __x"max one active syslog dispatcher, attempt for {new} have {old}"
, new => $self->name, old => $active
if $active;
$active = $self->name;
setlogsock(delete $args->{logsocket})
if $args->{logsocket};
my $ident = delete $args->{identity} || basename $0;
my $flags = delete $args->{flags} || 'pid,nowait';
my $fac = delete $args->{facility} || 'user';
openlog $ident, $flags, $fac; # doesn't produce error.
$self->{LRDS_incl_dom} = delete $args->{include_domain};
$self->{LRDS_charset} = delete $args->{charset} || "utf-8";
$self->{LRDS_format} = $args->{format} || sub {$_[0]};
$self->{prio} = +{ %default_reasonToPrio };
if(my $to_prio = delete $args->{to_prio})
{ my @to = @$to_prio;
while(@to)
{ my ($reasons, $level) = splice @to, 0, 2;
my @reasons = expand_reasons $reasons;
my $prio = Sys::Syslog::xlate($level);
error __x"syslog level '{level}' not understood", level => $level
if $prio eq -1;
$self->{prio}{$_} = $prio for @reasons;
}
}
$self;
}
sub close()
{ my $self = shift;
undef $active;
closelog;
$self->SUPER::close;
}
#--------------
sub format(;$)
{ my $self = shift;
@_ ? $self->{LRDS_format} = shift : $self->{LRDS_format};
}
#--------------
sub log($$$$$)
{ my ($self, $opts, $reason, $msg, $domain) = @_;
my $text = $self->translate($opts, $reason, $msg) or return;
my $format = $self->format;
# handle each line in message separately
$text =~ s/\s+$//s;
my @text = split /\n/, $format->($text, $domain, $msg, %$opts);
my $prio = $self->reasonToPrio($reason);
my $charset = $self->{LRDS_charset};
if($self->{LRDS_incl_dom} && $domain)
{ $domain =~ s/\%//g; # security
syslog $prio, "$domain %s", encode($charset, shift @text);
}
syslog $prio, "%s", encode($charset, $_)
for @text;
}
sub reasonToPrio($) { $_[0]->{prio}{$_[1]} }
1;

View File

@@ -0,0 +1,236 @@
=encoding utf8
=head1 NAME
Log::Report::Dispatcher::Syslog - send messages to syslog
=head1 INHERITANCE
Log::Report::Dispatcher::Syslog
is a Log::Report::Dispatcher
=head1 SYNOPSIS
# add syslog dispatcher
dispatcher SYSLOG => 'syslog', accept => 'NOTICE-'
, format_reason => 'IGNORE'
, to_prio => [ 'ALERT-' => 'err' ];
# disable default dispatcher, when daemon
dispatcher close => 'default';
=head1 DESCRIPTION
This dispatchers produces output to syslog, based on the Sys::Syslog
module (which will NOT be automatically installed for you, because some
systems have a problem with this dependency).
The REASON for a message often uses names which are quite similar to
the log-levels used by syslog. However: they have a different purpose.
The REASON is used by the programmer to indicate the cause of the message:
whether it was able to handle a certain situation. The syslog levels
are there for the user's of the program (with syslog usually the
system administrators). It is not unusual to see a "normal" error
or mistake as a very serious situation in a production environment. So,
you may wish to translate any message above reason MISTAKE into a LOG_CRIT.
The default translation table is list below. You can change the mapping
using L<new(to_prio)|Log::Report::Dispatcher::Syslog/"Constructors">. See example in SYNOPSIS.
TRACE => LOG_DEBUG ERROR => LOG_ERR
ASSERT => LOG_DEBUG FAULT => LOG_ERR
INFO => LOG_INFO ALERT => LOG_ALERT
NOTICE => LOG_NOTICE FAILURE => LOG_EMERG
WARNING => LOG_WARNING PANIC => LOG_CRIT
MISTAKE => LOG_WARNING
Extends L<"DESCRIPTION" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DESCRIPTION">.
=head1 METHODS
Extends L<"METHODS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"METHODS">.
=head2 Constructors
Extends L<"Constructors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Constructors">.
=over 4
=item $obj-E<gt>B<close>()
Inherited, see L<Log::Report::Dispatcher/"Constructors">
=item Log::Report::Dispatcher::Syslog-E<gt>B<new>($type, $name, %options)
With syslog, people tend not to include the REASON of the message
in the logs, because that is already used to determine the destination
of the message.
-Option --Defined in --Default
accept Log::Report::Dispatcher depend on mode
charset 'utf8'
facility 'user'
flags 'pid,nowait'
format <unchanged>
format_reason Log::Report::Dispatcher 'IGNORE'
identity <basename $0>
include_domain <false>
locale Log::Report::Dispatcher <system locale>
logsocket undef
mode Log::Report::Dispatcher 'NORMAL'
to_prio []
=over 2
=item accept => REASONS
=item charset => CHARSET
Translate the text-strings into the specified charset, otherwise the
sysadmin may get unreadable text.
=item facility => STRING
The possible values for this depend (a little) on the system. POSIX
only defines C<user>, and C<local0> up to C<local7>.
=item flags => STRING
Any combination of flags as defined by Sys::Syslog, for instance
C<pid>, C<ndelay>, and C<nowait>.
=item format => CODE
[1.10] With a CODE reference you get your hands on the text before
it gets sent to syslog. The three parameters are: the (translated) text,
the related text domain object, and the message object. You may want to
use context information from the latter.
[1.19] After the three positional parameters, there may be a list of
pairs (named parameters) with additional info. This may contain a
C<location> with an ARRAY of information produced by caller() about the
origin of the exception.
=item format_reason => 'UPPERCASE'|'LOWERCASE'|'UCFIRST'|'IGNORE'|CODE
=item identity => STRING
=item include_domain => BOOLEAN
[1.00] Include the text-domain of the message in each logged message.
=item locale => LOCALE
=item logsocket => 'unix'|'inet'|'stream'|HASH
If specified, the log socket type will be initialized to this before
C<openlog()> is called. If not specified, the system default is used.
=item mode => 'NORMAL'|'VERBOSE'|'ASSERT'|'DEBUG'|0..3
=item to_prio => ARRAY-of-PAIRS
See L<reasonToPrio()|Log::Report::Dispatcher::Syslog/"Logging">.
=back
=back
=head2 Accessors
Extends L<"Accessors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Accessors">.
=over 4
=item $obj-E<gt>B<format>( [CODE] )
Returns the CODE ref which formats the syslog line.
=item $obj-E<gt>B<isDisabled>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<mode>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<name>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<needs>( [$reason] )
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<type>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=back
=head2 Logging
Extends L<"Logging" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Logging">.
=over 4
=item $obj-E<gt>B<addSkipStack>(@CODE)
=item Log::Report::Dispatcher::Syslog-E<gt>B<addSkipStack>(@CODE)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<collectLocation>()
=item Log::Report::Dispatcher::Syslog-E<gt>B<collectLocation>()
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<collectStack>( [$maxdepth] )
=item Log::Report::Dispatcher::Syslog-E<gt>B<collectStack>( [$maxdepth] )
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<log>(HASH-$of-%options, $reason, $message, $domain)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<reasonToPrio>($reason)
Returns a level which is understood by syslog(3), based on a translation
table. This can be changed with L<new(to_prio)|Log::Report::Dispatcher::Syslog/"Constructors">.
=item $obj-E<gt>B<skipStack>()
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<stackTraceLine>(%options)
=item Log::Report::Dispatcher::Syslog-E<gt>B<stackTraceLine>(%options)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<translate>(HASH-$of-%options, $reason, $message)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=back
=head1 DETAILS
Extends L<"DETAILS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DETAILS">.
=head1 SEE ALSO
This module is part of Log-Report distribution version 1.31,
built on January 15, 2021. Website: F<http://perl.overmeer.net/CPAN/>
=head1 LICENSE
Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
See F<http://dev.perl.org/licenses/>

View File

@@ -0,0 +1,123 @@
# Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>].
# For other contributors see ChangeLog.
# See the manual pages for details on the licensing terms.
# Pod stripped from pm file by OODoc 2.02.
# This code is part of distribution Log-Report. Meta-POD processed with
# OODoc into POD and HTML manual-pages. See README.md
# Copyright Mark Overmeer. Licensed under the same terms as Perl itself.
package Log::Report::Dispatcher::Try;
use vars '$VERSION';
$VERSION = '1.31';
use base 'Log::Report::Dispatcher';
use warnings;
use strict;
use Log::Report 'log-report', syntax => 'SHORT';
use Log::Report::Exception ();
use Log::Report::Util qw/%reason_code expand_reasons/;
use List::Util qw/first/;
use overload
bool => 'failed'
, '""' => 'showStatus'
, fallback => 1;
#-----------------
sub init($)
{ my ($self, $args) = @_;
defined $self->SUPER::init($args) or return;
$self->{exceptions} = delete $args->{exceptions} || [];
$self->{died} = delete $args->{died};
$self->hide($args->{hide} // 'NONE');
$self->{on_die} = $args->{on_die} // 'ERROR';
$self;
}
#-----------------
sub died(;$)
{ my $self = shift;
@_ ? ($self->{died} = shift) : $self->{died};
}
sub exceptions() { @{shift->{exceptions}} }
sub hides($) { $_[0]->{LRDT_hides}{$_[1]} }
sub hide(@)
{ my $self = shift;
my @reasons = expand_reasons(@_ > 1 ? \@_ : shift);
$self->{LRDT_hides} = +{ map +($_ => 1), @reasons };
}
sub die2reason() { shift->{on_die} }
#-----------------
sub log($$$$)
{ my ($self, $opts, $reason, $message, $domain) = @_;
unless($opts->{stack})
{ my $mode = $self->mode;
$opts->{stack} = $self->collectStack
if $reason eq 'PANIC'
|| ($mode==2 && $reason_code{$reason} >= $reason_code{ALERT})
|| ($mode==3 && $reason_code{$reason} >= $reason_code{ERROR});
}
$opts->{location} ||= '';
my $e = Log::Report::Exception->new
( reason => $reason
, report_opts => $opts
, message => $message
);
push @{$self->{exceptions}}, $e;
# $self->{died} ||=
# exists $opts->{is_fatal} ? $opts->{is_fatal} : $e->isFatal;
$self;
}
sub reportFatal(@) { $_->throw(@_) for shift->wasFatal }
sub reportAll(@) { $_->throw(@_) for shift->exceptions }
#-----------------
sub failed() { defined shift->{died}}
sub success() { ! defined shift->{died}}
sub wasFatal(@)
{ my ($self, %args) = @_;
defined $self->{died} or return ();
# An (hidden) eval between LR::try()s may add more messages
my $ex = first { $_->isFatal } @{$self->{exceptions}}
or return ();
(!$args{class} || $ex->inClass($args{class})) ? $ex : ();
}
sub showStatus()
{ my $self = shift;
my $fatal = $self->wasFatal or return '';
__x"try-block stopped with {reason}: {text}"
, reason => $fatal->reason
, text => $self->died;
}
1;

View File

@@ -0,0 +1,335 @@
=encoding utf8
=head1 NAME
Log::Report::Dispatcher::Try - capture all reports as exceptions
=head1 INHERITANCE
Log::Report::Dispatcher::Try
is a Log::Report::Dispatcher
=head1 SYNOPSIS
try { ... }; # mind the ';' !!
if($@) { # signals something went wrong
if(try {...}) { # block ended normally
my $x = try { read_temperature() };
my @x = try { read_lines_from_file() };
try { ... } # no comma!!
mode => 'DEBUG', accept => 'ERROR-';
try sub { ... }, # with comma
mode => 'DEBUG', accept => 'ALL';
try \&myhandler, accept => 'ERROR-';
try { ... } hide => 'TRACE';
print ref $@; # Log::Report::Dispatcher::Try
$@->reportFatal; # re-dispatch result of try block
$@->reportAll; # ... also warnings etc
if($@) {...} # if errors
if($@->failed) { # same # }
if($@->success) { # no errors # }
try { # something causes an error report, which is caught
failure 'no network';
};
$@->reportFatal(to => 'syslog'); # overrule destination
print $@->exceptions; # no re-cast, just print
=head1 DESCRIPTION
The B<try> works like Perl's build-in C<eval()>, but implements
real exception handling which Perl core lacks.
The L<Log::Report::try()|Log::Report/"Report Production and Configuration"> function creates this C<::Try> dispatcher
object with name 'try'. After the C<try()> is over, you can find
the object in C<$@>. The C<$@> as C<::Try> object behaves exactly
as the C<$@> produced by C<eval>, but has many added features.
The C<try()> function catches fatal errors happening inside the BLOCK
(CODE reference which is just following the function name) into the
C<::Try> object C<$@>. The errors are not automatically progressed to
active dispatchers. However, non-fatal exceptions (like info or notice)
are also collected (unless not accepted, see L<new(accept)|Log::Report::Dispatcher/"Constructors">, but also
immediately passed to the active dispatchers (unless the reason is hidden,
see L<new(hide)|Log::Report::Dispatcher::Try/"Constructors">)
After the C<try()> has run, you can introspect the collected exceptions.
Typically, you use L<wasFatal()|Log::Report::Dispatcher::Try/"Status"> to get the exception which terminated
the run of the BLOCK.
Extends L<"DESCRIPTION" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DESCRIPTION">.
=head1 METHODS
Extends L<"METHODS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"METHODS">.
=head2 Constructors
Extends L<"Constructors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Constructors">.
=over 4
=item $obj-E<gt>B<close>()
Inherited, see L<Log::Report::Dispatcher/"Constructors">
=item Log::Report::Dispatcher::Try-E<gt>B<new>($type, $name, %options)
-Option --Defined in --Default
accept Log::Report::Dispatcher depend on mode
charset Log::Report::Dispatcher <undef>
died undef
exceptions []
format_reason Log::Report::Dispatcher 'LOWERCASE'
hide 'NONE'
locale Log::Report::Dispatcher <system locale>
mode Log::Report::Dispatcher 'NORMAL'
on_die 'ERROR'
=over 2
=item accept => REASONS
=item charset => CHARSET
=item died => STRING
The exit string ($@) of the eval'ed block.
=item exceptions => ARRAY
ARRAY of L<Log::Report::Exception|Log::Report::Exception> objects.
=item format_reason => 'UPPERCASE'|'LOWERCASE'|'UCFIRST'|'IGNORE'|CODE
=item hide => REASONS|ARRAY|'ALL'|'NONE'
[1.09] see L<hide()|Log::Report::Dispatcher::Try/"Accessors">
=item locale => LOCALE
=item mode => 'NORMAL'|'VERBOSE'|'ASSERT'|'DEBUG'|0..3
=item on_die => 'ERROR'|'PANIC'
When code which runs in this block exits with a die(), it will get
translated into a L<Log::Report::Exception|Log::Report::Exception> using
L<Log::Report::Die::die_decode()|Log::Report::Die/"FUNCTIONS">. How serious are we about these
errors?
=back
=back
=head2 Accessors
Extends L<"Accessors" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Accessors">.
=over 4
=item $obj-E<gt>B<die2reason>()
Returns the value of L<new(on_die)|Log::Report::Dispatcher::Try/"Constructors">.
=item $obj-E<gt>B<died>( [STRING] )
The message which was reported by C<eval>, which is used internally
to catch problems in the try block.
=item $obj-E<gt>B<exceptions>()
Returns all collected C<Log::Report::Exceptions>. The last of
them may be a fatal one. The other are non-fatal.
=item $obj-E<gt>B<hide>(@reasons)
[1.09] By default, the try will only catch messages which stop the
execution of the block (errors etc, internally a 'die'). Other messages
are passed to the parent dispatchers.
This option gives the opportunity to stop, for instance, trace messages.
Those messages are still collected inside the try object (unless excluded
by L<new(accept)|Log::Report::Dispatcher/"Constructors">), so may get passed-on later via L<reportAll()|Log::Report::Dispatcher::Try/"Logging"> if
you like.
Be warned: Using this method will reset the whole 'hide' configuration:
it's a I<set> not an I<add>.
example: change the setting of the running block
my $parent_try = dispatcher 'active-try';
$parent_try->hide('ALL');
=item $obj-E<gt>B<hides>($reason)
Check whether the try stops message which were produced for C<$reason>.
=item $obj-E<gt>B<isDisabled>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<mode>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<name>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<needs>( [$reason] )
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=item $obj-E<gt>B<type>()
Inherited, see L<Log::Report::Dispatcher/"Accessors">
=back
=head2 Logging
Extends L<"Logging" in Log::Report::Dispatcher|Log::Report::Dispatcher/"Logging">.
=over 4
=item $obj-E<gt>B<addSkipStack>(@CODE)
=item Log::Report::Dispatcher::Try-E<gt>B<addSkipStack>(@CODE)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<collectLocation>()
=item Log::Report::Dispatcher::Try-E<gt>B<collectLocation>()
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<collectStack>( [$maxdepth] )
=item Log::Report::Dispatcher::Try-E<gt>B<collectStack>( [$maxdepth] )
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<log>($opts, $reason, $message)
Other dispatchers translate the message here, and make it leave the
program. However, messages in a "try" block are only captured in
an intermediate layer: they may never be presented to an end-users.
And for sure, we do not know the language yet.
The $message is either a STRING or a L<Log::Report::Message|Log::Report::Message>.
=item $obj-E<gt>B<reportAll>(%options)
Re-cast the messages in all collect exceptions into the defined
dispatchers, which were disabled during the try block. The %options
will end-up as HASH of %options to L<Log::Report::report()|Log::Report/"Report Production and Configuration">; see
L<Log::Report::Exception::throw()|Log::Report::Exception/"Processing"> which does the job.
=item $obj-E<gt>B<reportFatal>()
Re-cast only the fatal message to the defined dispatchers. If the
block was left without problems, then nothing will be done. The %options
will end-up as HASH of %options to L<Log::Report::report()|Log::Report/"Report Production and Configuration">; see
L<Log::Report::Exception::throw()|Log::Report::Exception/"Processing"> which does the job.
=item $obj-E<gt>B<skipStack>()
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<stackTraceLine>(%options)
=item Log::Report::Dispatcher::Try-E<gt>B<stackTraceLine>(%options)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=item $obj-E<gt>B<translate>(HASH-$of-%options, $reason, $message)
Inherited, see L<Log::Report::Dispatcher/"Logging">
=back
=head2 Status
=over 4
=item $obj-E<gt>B<failed>()
Returns true if the block was left with an fatal message.
=item $obj-E<gt>B<showStatus>()
If this object is kept in C<$@>, and someone uses this as string, we
want to show the fatal error message.
The message is not very informative for the good cause: we do not want
people to simply print the C<$@>, but wish for a re-cast of the message
using L<reportAll()|Log::Report::Dispatcher::Try/"Logging"> or L<reportFatal()|Log::Report::Dispatcher::Try/"Logging">.
=item $obj-E<gt>B<success>()
Returns true if the block exited normally.
=item $obj-E<gt>B<wasFatal>(%options)
Returns the L<Log::Report::Exception|Log::Report::Exception> which caused the "try" block to
die, otherwise an empty LIST (undef).
-Option--Default
class undef
=over 2
=item class => CLASS|REGEX
Only return the exception if it was fatal, and in the same time in
the specified CLASS (as string) or matches the REGEX.
See L<Log::Report::Message::inClass()|Log::Report::Message/"Processing">
=back
=back
=head1 DETAILS
Extends L<"DETAILS" in Log::Report::Dispatcher|Log::Report::Dispatcher/"DETAILS">.
=head1 OVERLOADING
=over 4
=item overload: B<boolean>
Returns true if the previous try block did produce a terminal
error. This "try" object is assigned to C<$@>, and the usual
perl syntax is C<if($@) {...error-handler...}>.
=item overload: B<stringify>
When C<$@> is used the traditional way, it is checked to have
a string content. In this case, stringify into the fatal error
or nothing.
=back
=head1 SEE ALSO
This module is part of Log-Report distribution version 1.31,
built on January 15, 2021. Website: F<http://perl.overmeer.net/CPAN/>
=head1 LICENSE
Copyrights 2007-2021 by [Mark Overmeer <markov@cpan.org>]. For other contributors see ChangeLog.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
See F<http://dev.perl.org/licenses/>