summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorfranck cuny <franck@lumberjaph.net>2010-07-05 21:57:33 +0200
committerfranck cuny <franck@lumberjaph.net>2010-07-05 21:57:33 +0200
commit71c6d42b78d5fd7a7b8a65beb36105fca938d9b1 (patch)
treebd3464590fc447dd1ce0572167e06cf75e994f35 /lib
downloadplack-middleware-errornot-master.tar.gz
initial importmaster
Diffstat (limited to 'lib')
-rw-r--r--lib/Plack/Middleware/ErrorNot.pm122
1 files changed, 122 insertions, 0 deletions
diff --git a/lib/Plack/Middleware/ErrorNot.pm b/lib/Plack/Middleware/ErrorNot.pm
new file mode 100644
index 0000000..c9d1623
--- /dev/null
+++ b/lib/Plack/Middleware/ErrorNot.pm
@@ -0,0 +1,122 @@
+package Plack::Middleware::ErrorNot;
+
+use strict;
+use warnings;
+
+use POSIX qw(strftime);
+use JSON;
+use Try::Tiny;
+use Devel::StackTrace;
+use AnyEvent::HTTP;
+
+use parent qw(Plack::Middleware);
+use Plack::Util::Accessor qw(api_key api_url);
+
+sub call {
+ my ($self, $env) = @_;
+
+ my($trace, $exception);
+ local $SIG{__DIE__} = sub {
+ $trace = Devel::StackTrace->new;
+ $exception = $_[0];
+ die @_;
+ };
+
+ my $res;
+ try { $res = $self->app->($env) };
+
+ if ($trace && (!$res or $res->[0] == 500)) {
+ $self->send_notify($trace, $exception, $env);
+ $res = [500, ['Content-Type' => 'text/html'], [ "Internal Server Error" ]];
+ }
+
+ # break $trace here since $SIG{__DIE__} holds the ref to it, and
+ # $trace has refs to Standalone.pm's args ($conn etc.) and
+ # prevents garbage collection to be happening.
+ undef $trace;
+
+ return $res;
+}
+
+sub send_notify {
+ my ($self, $trace, $exception, $env) = @_;
+
+ my $req = Plack::Request->new($env);
+ my $raised_at = strftime "%a %b %e %H:%M:%S %Y", gmtime;
+
+ my @env_infos = (
+ qw/PATH_INFO
+ SERVER_NAME
+ SERVER_PORT
+ HTTP_ACCEPT
+ HTTP_ACCEPT_CHARSER
+ HTTP_ACCEPT_ENCODING
+ HTTP_ACCEPT_LANGUAGE
+ HTTP_HOST
+ REQUEST_METHOD
+ REMOTE_ADDR/
+ );
+
+ my $hash_exception = {
+ api_key => $self->api_key,
+ error => {
+ message => $exception,
+ raised_at => $raised_at,
+ backtrace => '',
+ request => {
+ url => $req->uri->as_string,
+ action => $req->uri->path,
+ parameters => map { $_ => $req->parameters->{$_} }
+ keys %{$req->parameters},
+ session => map { $_ => $req->session->{$_} }
+ keys %{$req->session},
+ },
+ }
+ };
+
+ foreach my $env_key (@env_infos) {
+ $hash_exception->{environment}->{$env_key} = $env->{$env_key}
+ if exists $env->{$env_key};
+ }
+
+ my $cv = AE::cv;
+
+ AnyEvent::HTTP::http_post $self->api_url,
+ JSON::encode_json($hash_exception),
+ headers => {
+ 'Content-Type' => 'application/json',
+ 'Accept-Type' => 'application/json'
+ }, $cv;
+
+ $cv->recv unless $env->{'psgi.nonblocking'};
+}
+
+1;
+
+=head1 NAME
+
+Plack::Middleware::ErrorNot - Sends application errors to ErrorNot
+
+=head1 SYNOPSIS
+
+ enable "ErrorNot", api_key => "...", api_url => "...";
+
+=head1 DESCRIPTION
+
+This middleware catches exceptions (run-time errors) happening in your
+application and sends them to L<ErrorNot|http://wiki.github.com/AF83/ErrorNot/>.
+
+=head1 AUTHOR
+
+franck cuny
+
+=head1 LICENSE
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<Plack::Middleware::StackTrace>, L<Plack::Middleware::HopToad>
+
+=cut