Exception-Reporter
view release on metacpan - search on metacpan
view release on metacpan or search on metacpan
lib/Exception/Reporter.pm view on Meta::CPAN
#pod summarizers - an arrayref of summarizer objects; required
#pod senders - an arrayref of sender objects; required
#pod dumper - a Exception::Reporter::Dumper used for dumping data
#pod always_dump - a hashref of coderefs used to generate extra dumpables
#pod caller_level - if given, the reporter will look n frames up; see below
#pod
#pod The C<always_dump> hashref bears a bit more explanation. When
#pod C<L</report_exception>> is called, each entry in C<always_dump> will be
#pod evaluated and appended to the list of given dumpables. This lets you make your
#pod reporter always include some more useful information.
#pod
#pod I<...but remember!> The reporter is probably doing its job in a C<catch>
#pod block, which means that anything that might have been changed C<local>-ly in
#pod your C<try> block will I<not> be the same when evaluated as part of the
#pod C<always_dump> code. This might not matter often, but keep it in mind when
#pod setting up your reporter.
#pod
#pod In real code, you're likely to create one Exception::Reporter object and make
#pod it globally accessible through some method. That method adds a call frame, and
#pod Exception::Reporter sometimes looks at C<caller> to get a default. If you want
#pod to skip those intermedite call frames, pass C<caller_level>. It will be used
#pod as the number of frames up the stack to look. It defaults to zero.
#pod
#pod =cut
sub new {
my ($class, $arg) = @_;
my $self = {
summarizers => $arg->{summarizers},
senders => $arg->{senders},
dumper => $arg->{dumper},
always_dump => $arg->{always_dump},
caller_level => $arg->{caller_level} || 0,
};
if ($self->{always_dump}) {
for my $key (keys %{ $self->{always_dump} }) {
Carp::confess("non-coderef entry in always_dump: $key")
unless ref($self->{always_dump}{$key}) eq 'CODE';
}
}
$self->{dumper} ||= do {
require Exception::Reporter::Dumper::YAML;
Exception::Reporter::Dumper::YAML->new;
};
Carp::confess("entry in dumper is not an Exception::Reporter::Dumper")
unless $self->{dumper}->isa('Exception::Reporter::Dumper');
for my $test (qw(Summarizer Sender)) {
my $class = "Exception::Reporter::$test";
my $key = "\L${test}s";
Carp::confess("no $key given") unless $arg->{$key} and @{ $arg->{$key} };
Carp::confess("entry in $key is not an $class")
if grep { ! $_->isa($class) } @{ $arg->{$key} };
}
bless $self => $class;
$_->register_reporter($self) for $self->_summarizers;
return $self;
}
sub _summarizers { return @{ $_[0]->{summarizers} }; }
sub _senders { return @{ $_[0]->{senders} }; }
sub dumper { return $_[0]->{dumper} }
#pod =method report_exception
#pod
#pod $reporter->report_exception(\@dumpables, \%arg);
#pod
#pod This method makes the reporter do its job: summarize dumpables and send a
#pod report.
#pod
#pod Useful options in C<%arg> are:
#pod
#pod reporter - the program or authority doing the reporting; defaults to
#pod the calling package
#pod
#pod handled - this indicates that this exception has been handled and that
#pod the user has not seen a terrible crash; senders might use
#pod this to decide who needs to get woken up
#pod
#pod extra_rcpts - this can be an arrayref of email addresses to be used as
#pod extra envelope recipients by the Email sender
#pod
#pod Each entry in C<@dumpables> is expected to look like this:
#pod
#pod [ $short_name, $value, \%arg ]
#pod
#pod The short name is used for a few things, including identifying the dumps inside
#pod the report produced. It's okay to have duplicated short names.
#pod
#pod The value can, in theory, be I<anything>. It can be C<undef>, any kind of
#pod object, or whatever you want to stick in a scalar. It's possible that
#pod extremely exotic values could confuse the "fallback" summarizer of last resort,
#pod but for the most part, anything goes.
#pod
#pod The C<%arg> entry isn't used for anything by the core libraries that ship with
#pod Exception::Reporter, but you might want to use it for your own purposes. Feel
#pod free.
#pod
#pod The reporter will try to summarize each dumpable by asking each summarizer, in
#pod order, whether it C<can_summarize> the dumpable. If it can, it will be asked
#pod to C<summarize> the dumpable. The summaries are collected into a structure
#pod that looks like this:
#pod
#pod [
#pod [ dumpable_short_name => \@summaries ],
#pod ...
#pod ]
#pod
#pod If a given dumpable can't be dumped by any summarizer, a not-very-useful
#pod placeholder is put in its place.
#pod
#pod The arrayref constructed is passed to the C<send_report> method of each sender,
view all matches for this distributionview release on metacpan - search on metacpan
( run in 0.514 second using v1.00-cache-2.02-grep-82fe00e-cpan-1925d2aa809 )