Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: rjbs/Exception-Reporter
base: 1159ffcad1
...
head fork: rjbs/Exception-Reporter
compare: 813ebc3e1c
  • 10 commits
  • 9 files changed
  • 0 commit comments
  • 1 contributor
View
19 lib/Exception/Reporter.pm
@@ -114,11 +114,23 @@ sub _senders { return @{ $_[0]->{senders} }; }
=method report_exception
- $reporter->report_exception(\@dumpables, $arg);
+ $reporter->report_exception(\@dumpables, \%arg);
This method makes the reporter do its job: summarize dumpables and send a
report.
+Useful options in C<%arg> are:
+
+ reporter - the program or authority doing the reporting; defaults to
+ the calling package
+
+ handled - this indicates that this exception has been handled and that
+ the user has not seen a terribel crash; senders might use
+ this to decide who needs to get woken up
+
+ extra_rcpts - this can be an arrayref of email addresses to be used as
+ extra envelope recipients by the Email sender
+
Each entry in C<@dumpables> is expected to look like this:
[ $short_name, $value, \%arg ]
@@ -160,6 +172,9 @@ sub report_exception {
my $guid = _guid_string;
+ my @caller = caller;
+ $arg->{reporter} ||= $caller[0];
+
my @summaries;
my @sumz = $self->_summarizers;
@@ -192,7 +207,7 @@ sub report_exception {
$arg,
{
guid => $guid,
- caller => [caller],
+ caller => \@caller,
}
);
}
View
17 lib/Exception/Reporter/Sender.pm
@@ -1,5 +1,22 @@
use strict;
use warnings;
package Exception::Reporter::Sender;
+# ABSTRACT: a thing that sends exception reports
+
+=head1 OVERVIEW
+
+This class exists almost entirely to allow C<isa>-checking. It provides a
+C<new> method that returns a blessed, empty object. Passing it any parameters
+will cause an exception to be thrown.
+
+=cut
+
+sub new {
+ my $class = shift;
+
+ Carp::confess("$class constructor does not take any parameters") if @_;
+
+ return bless {}, $class;
+}
1;
View
46 lib/Exception/Reporter/Sender/Email.pm
@@ -4,21 +4,44 @@ package Exception::Reporter::Sender::Email;
# ABSTRACT: an report sender that sends detailed dumps via email
use parent 'Exception::Reporter::Sender';
+=head1 SYNOPSIS
+
+ my $sender = Exception::Reporter::Sender::Email->new({
+ from => 'root',
+ to => 'Beloved SysAdmins <sysadmins@example.com>',
+ });
+
=head1 OVERVIEW
This is the only report sender you'll probably ever need.
It turns the report into a multipart email message and sends it via email.
+Each set of summaries is turned into a MIME message part. If a dumpable has
+become more than one summary, its summaries will be children of a
+C<multipart/related> part. Otherwise, its summary will become a part of the
+kind indicated in the summary.
+
+The C<ident> of the first summary will be used for the subject of the message.
+
+The GUID of the exception report (the thing returned by the reporter's
+C<report_exception> method) is used as the local part of the email message's
+Message-ID.
+
+Every reported message has a In-Reply-To header formed by combining a
+slightly-munged version of the C<ident> and the C<reporter>. This means that
+similar exception report emails will thread together in a thread-capable email
+reader.
+
=cut
use Digest::MD5 ();
use Email::Address ();
-use Email::Date::Format qw(email_date);
use Email::MIME::Creator ();
use Email::MessageID ();
use Email::Sender::Simple ();
-use String::Truncate qw(elide);
+use String::Truncate;
+use Try::Tiny;
sub new {
my ($class, $arg) = @_;
@@ -90,10 +113,9 @@ C<%internal_arg> contains data produced by the Exception::Reporter using this
object. It includes the C<guid> of the report and the C<caller> calling the
reporter.
-The GUID is used in generating a message id.
+If the email cannot be injected, a warning will be issued.
-All similar exceptions should have identical In-Reply-To headers, which can be
-used to thread common exceptions together.
+The return value of C<send_report> is not defined.
=cut
@@ -143,7 +165,7 @@ sub send_report {
. "THIS EXCEPTION WAS CAUGHT AND EXECUTION CONTINUED\n"
. "THIS REPORT IS PROVIDED FOR INFORMATIONAL PURPOSES\n",
attributes => {
- content_type => "text/plain", # could be better
+ content_type => "text/plain",
charset => 'utf-8',
encoding => 'quoted-printable',
name => 'prelude',
@@ -167,8 +189,7 @@ sub send_report {
header_str => [
From => $self->from_header,
To => $self->to_header,
- Date => email_date,
- Subject => elide("$reporter: $ident", 65),
+ Subject => String::Truncate::elide("$reporter: $ident", 65),
'X-Mailer' => __PACKAGE__,
'Message-Id' => Email::MessageID->new(user => $internal_arg->{guid})
->in_brackets,
@@ -181,7 +202,7 @@ sub send_report {
],
);
- eval {
+ try {
Email::Sender::Simple->send(
$email,
{
@@ -189,13 +210,10 @@ sub send_report {
to => [ $self->env_to ],
}
);
+ } catch {
+ Carp::cluck "failed to send exception report: $_";
};
- if ($@) {
- Carp::cluck "failed to send exception report: $@";
- return;
- }
-
return;
}
View
21 lib/Exception/Reporter/Summarizer.pm
@@ -1,9 +1,25 @@
use strict;
use warnings;
package Exception::Reporter::Summarizer;
+# ABSTRACT: a thing that summarizes dumpables for reporting
+
+use Carp ();
+
+=head1 OVERVIEW
+
+This class exists almost entirely to allow C<isa>-checking. It provides a
+C<new> method that returns a blessed, empty object. Passing it any parameters
+will cause an exception to be thrown.
+
+A C<sanitize_filename> method is also provided, which turns a vaguely
+filename-like string into a safer filename string.
+
+=cut
sub new {
- my ($class, $arg) = @_;
+ my $class = shift;
+
+ Carp::confess("$class constructor does not take any parameters") if @_;
return bless {}, $class;
}
@@ -11,6 +27,9 @@ sub new {
sub sanitize_filename {
my ($self, $filename) = @_;
+ # These don't need to be actually secure, since we won't use this for
+ # opening any filehandles. -- rjbs, 2012-07-03
+ $filename =~ s/\.+/./g;
$filename =~ s/[^-a-zA-Z0-9]/-/g;
return $filename;
}
View
9 lib/Exception/Reporter/Summarizer/Email.pm
@@ -3,6 +3,14 @@ use warnings;
package Exception::Reporter::Summarizer::Email;
use parent 'Exception::Reporter::Summarizer';
+=head1 OVERVIEW
+
+This summarizer will only summarize Email::Simple (or subclass) objects. The
+emails will be summarized as C<message/rfc822> data containing the
+stringification of the message.
+
+=cut
+
use Try::Tiny;
sub can_summarize {
@@ -21,6 +29,7 @@ sub summarize {
mimetype => 'message/rfc822',
ident => "email message for $fn_base",
body => $value->as_string,
+ body_is_bytes => 1,
};
}
View
12 lib/Exception/Reporter/Summarizer/ExceptionClass.pm
@@ -3,6 +3,18 @@ use warnings;
package Exception::Reporter::Summarizer::ExceptionClass;
use parent 'Exception::Reporter::Summarizer';
+=head1 OVERVIEW
+
+This summarizer handles only L<Exception::Class> objects. A dumped exception
+will result in between one and four summaries:
+
+ * a text summary of the exceptions full message
+ * if available, a YAML dump of the exception's pid, time, uid, etc.
+ * if available, the stringification of the exception's stack trace
+ * if any fields are defined, a YAML dump of the exception's fields
+
+=cut
+
use YAML::XS ();
use Try::Tiny;
View
18 lib/Exception/Reporter/Summarizer/Fallback.pm
@@ -3,6 +3,18 @@ use warnings;
package Exception::Reporter::Summarizer::Fallback;
use parent 'Exception::Reporter::Summarizer';
+=head1 OVERVIEW
+
+This summarizer will accept any input and summarize it by dumping it to YAML.
+
+I recommended that this summarizer is always in your list of summarizers,
+and always last.
+
+If a YAML dump can't be produced, the exception from YAML will be attached,
+along with the stringification of the dumpable value.
+
+=cut
+
use YAML::XS ();
use Try::Tiny;
@@ -27,7 +39,7 @@ sub summarize {
$ident =~ s/\s+(?:at .+?)? ?line\s\d+\.?$//;
return {
- filename => "$fn_base.txt",
+ filename => "$fn_base.yaml",
mimetype => 'text/plain',
ident => $ident,
body => $body,
@@ -37,13 +49,13 @@ sub summarize {
{
filename => "$fn_base-error.txt",
mimetype => 'text/plain',
- ident => "value for $name couldn't be processed",
+ ident => "$name dumpable dumping error",
body => "could not summarize $name value: $_\n",
},
{
filename => "$fn_base-raw.txt",
mimetype => 'text/plain',
- ident => "stringified value for $name",
+ ident => "$name dumpable stringification",
body => do { no warnings 'uninitialized'; "$name" },
},
);
View
9 lib/Exception/Reporter/Summarizer/File.pm
@@ -3,6 +3,13 @@ use warnings;
package Exception::Reporter::Summarizer::File;
use parent 'Exception::Reporter::Summarizer';
+=head1 OVERVIEW
+
+This summarizer expects L<Exception::Reporter::Dumpable::File> objects, and
+summarizes them just as you might expect.
+
+=cut
+
use File::Basename ();
use Try::Tiny;
@@ -19,8 +26,6 @@ sub summarize {
File::Basename::basename($value->path)
);
- # fn_base = sanitize leaf name
-
return {
filename => $fn_base,
mimetype => $value->mimetype,
View
2  t/basic.t
@@ -24,7 +24,7 @@ my $reporter = Exception::Reporter->new({
senders => [
Exception::Reporter::Sender::Email->new({
from => 'root',
- to => 'IC Group Sysadmins <sysadmins@icgroup.com>',
+ to => 'Example Sysadmins <sysadmins@example.com>',
}),
],
summarizers => [

No commit comments for this range

Something went wrong with that request. Please try again.