Exception-Reporter

 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 distribution
 view release on metacpan -  search on metacpan

( run in 0.514 second using v1.00-cache-2.02-grep-82fe00e-cpan-1925d2aa809 )