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

以前に作りっぱなしだったやつがあまりにもやりっぱなしだったので、ちょこっと考え直してみた。

書いた理由は、plackup -E deployment app.psgi とかで起動した場合に、例外が発生したらメールで通知して欲しかったからなんだけど、そんなもの既にあるよとか、本来そんなやり方するものじゃないとかツッコミがいただけると幸いです。それ以外にもまずいところがあったら教えて下さい。

実装はこんな感じ。
Plack::Middleware::ExceptionNotice

package Plack::Middleware::ExceptionNotice;
use strict;
use warnings;
use parent qw/Plack::Middleware/;
use Plack::Util::Accessor qw( notifier );
use Class::Load;

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

    my $res = $self->app->($env);
    my $stacktrace = $env->{'plack.stacktrace.text'};
    return $res unless $stacktrace;

    Class::Load::load_class($self->notifier);
    die $self->notifier->notice($stacktrace) ||
        'Exception notifier does not return the results.';
}

1;


使い方はこんな感じ。
app.psgi

builder {
    enable "HTTPExceptions";
    enable 'ExceptionNotice',
        notifier => 'MyApp::ExceptionNotifier';
    enable "StackTrace";
    $app;
};

Plack::Middleware::StackTrace は例外が発生すると plack.stacktrace.text をセットするので、その有無で通知を行います。通知を行う方法は自由で notice というメソッドを実装したクラスを指定します。


今回作ってみた通知用のクラスはこんな感じ。
MyApp::ExceptionNotifier

package MyApp::ExceptionNotifier;
use strict;
use warnings;
use Email::MIME;
use Email::Send;

sub notice {
    my ($self, $e) = @_;
    my $email = Email::MIME->create(
        header      => [
            From    => 'from@example.com',
            To      => 'to@example.com',
            Subject => 'raise exceptions',
        ],
        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 $!;
    return 'noticed exception.';
}

1;