AxKit2
view release on metacpan or search on metacpan
plugins/error_xml view on Meta::CPAN
sub init {
$SIG{__DIE__} = sub { die AxKit2::StructuredError->new($_[0]) };
}
sub hook_error {
my $self = shift;
my $error = shift;
$self->log(LOGDEBUG, "Turning error into XML");
if ($self->config('StackTraceLog')) {
$self->log(LOGERROR, $error->to_string(1));
}
my $with_trace = $self->config('StackTrace');
my $xml = $error->to_xml($with_trace);
my $stylesheet = $self->config('ErrorStylesheet');
if (!$stylesheet) {
$self->log(LOGERROR, "Need an ErrorStylesheet to transform the XML");
$self->log(LOGERROR, $xml);
return DECLINED;
}
my $input = AxKit2::Processor->new($self->client, $self->client->headers_in->filename);
$input->dom($xml);
my $out = $input->transform(XSLT($stylesheet));
$out->output();
return OK;
}
package AxKit2::StructuredError;
use AxKit2::Utils qw(xml_escape);
use overload
'""' => \&to_string,
'bool' => sub { 1 };
sub new {
my $class = shift;
my $err = shift;
return bless { error => $err, stacktrace => _stack_trace() }, $class;
}
sub to_string {
my $self = shift;
my $with_stack = shift;
return $self->{error} unless $with_stack;
return join("\n", $self->{error}, map { " from $_->[1]:$_->[2]" } @{$self->{stacktrace}});
}
sub _stack_trace {
my @stack;
my $pos = 2;
while (1) {
# $package, $filename, $line, $subroutine, $hasargs,
# $wantarray, $evaltext, $is_require, $hints, $bitmask
my @caller = caller($pos++);
last unless @caller;
push @stack, \@caller;
}
return \@stack;
}
# <error>
# <file>filename</file>
# <msg>error message</msg>
# <stack_trace>
# <bt level="0">
# <file>filename</file>
# <line>line number</line>
# </bt>
# <bt level="2">
# <!--etc-->
# </bt>
# </stack_trace>
# </error>
sub to_xml {
my $self = shift;
my $with_stack = shift;
my $stack = $self->{stacktrace};
my $msg = $self->{error};
my $xml = "<error>\n<file>" . xml_escape($stack->[0]->[1]) . "</file>\n";
$xml .= "<msg>" . xml_escape($msg) . "</msg>\n";
if ($with_stack) {
$xml .= "<stack_trace>\n";
my $level = 0;
for my $stack_data (@$stack) {
$xml .= "<bt level='$level'>\n";
$xml .= " <package>" . xml_escape($stack_data->[0]) . "</package>\n";
$xml .= " <file>" . xml_escape($stack_data->[1]) . "</file>\n";
$xml .= " <line>" . xml_escape($stack_data->[2]) . "</line>\n";
$xml .= " <subroutine>" . xml_escape($stack_data->[3]) . "(...)</subroutine>\n";
$xml .= "</bt>\n";
$level++;
}
$xml .= "</stack_trace>\n";
}
$xml .= "</error>\n";
return $xml;
}
( run in 0.782 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )