Plack::Middleware::ExceptionNotifierというのを書いた


2011/10/12 追記
あまりにもやりっぱなしなのでこっちで考え直したものを晒してます。←突っ込みはこちらで

enable 'Plack::Middleware::ExceptionNotifier',
          from => 'from@example.com',
          to => 'to@example.com';

みたいにして使ってみます。

package Plack::Middleware::ExceptionNotifier;
use strict;
use warnings;
use parent qw/Plack::Middleware/;
use Devel::StackTrace;
use Try::Tiny;
use Email::MIME;
use Email::Send;
use Plack::Util::Accessor qw( from to );

our $StackTraceClass = "Devel::StackTrace";

sub call {
    my($self, $env) = @_;

    my $res = try {
        $self->app->($env);
    } catch {
        my $caught = $_;
        my $cut = sprintf ' at \Q%s\E line %s\.\n', (caller)[1, 2];
        $caught =~ s/$cut//;
        my $trace = $StackTraceClass->new(
            indent => 1, message => $caught,
            ignore_package => __PACKAGE__,
        );
        local $SIG{__DIE__} = 'DEFAULT';
        $self->notice($trace->as_string);
        die $_;
    };

    return $res;
}

sub notice {
	my ($self, $e) = @_;

    my ($subject) = $e =~ /([^\n]+)/;
    my $email = Email::MIME->create(
        header      => [
            From    => $self->from,
            To      => $self->to,
            Subject => $subject,
        ],
        attributes => {
            content_type => "text/plain",
            charset      => "utf-8",
            encoding     => '8bit',
        },
        body_str => $e,
    );

    my $sender = Email::Send->new({mailer => 'Sendmail'});
    $sender->send($email) or die;
}

1;