MT#4229 custom Internal server error page

Move error_page to notfound_page. error_page is now for internal server errors.
Introduce logging option log_crash_state, enabled by default. Crash states are
written out compressed and encoded log-file-friendly, these are useful for
debugging but take a couple dozen kilobytes of disk space each.
apogrebennyk/3_1_force_outbound
Lars Dieckow 12 years ago
parent be3439da01
commit a37b165caf

@ -32,9 +32,12 @@ my $builder = Local::Module::Build->new(
'Catalyst::View::JSON' => 0, 'Catalyst::View::JSON' => 0,
'Catalyst::View::TT' => 0, 'Catalyst::View::TT' => 0,
'Config::General' => 0, 'Config::General' => 0,
'Convert::Ascii85' => 0,
'Data::Dumper' => 0,
'Data::Validate::IP' => 0, 'Data::Validate::IP' => 0,
'DateTime' => 0, 'DateTime' => 0,
'DateTime::Format::ISO8601' => 0, 'DateTime::Format::ISO8601' => 0,
'DateTime::Format::RFC3339' => 0,
'DBIx::Class::ResultSet::RecursiveUpdate' => '0.30', 'DBIx::Class::ResultSet::RecursiveUpdate' => '0.30',
'Email::Valid' => 0, 'Email::Valid' => 0,
'File::ShareDir' => 0, 'File::ShareDir' => 0,
@ -49,6 +52,7 @@ my $builder = Local::Module::Build->new(
'HTML::FormHandler::Moose' => 0, 'HTML::FormHandler::Moose' => 0,
'HTML::FormHandler::Widget::Block::Bootstrap' => 0, 'HTML::FormHandler::Widget::Block::Bootstrap' => 0,
'HTTP::Status' => 0, 'HTTP::Status' => 0,
'IO::Compress::Xz' => 0,
'IPC::System::Simple' => 0, 'IPC::System::Simple' => 0,
'Log::Log4perl::Catalyst' => 0, 'Log::Log4perl::Catalyst' => 0,
'Module::Runtime' => 0, 'Module::Runtime' => 0,
@ -65,6 +69,7 @@ my $builder = Local::Module::Build->new(
'strict' => 0, 'strict' => 0,
'Template' => 0, 'Template' => 0,
'Text::CSV_XS' => 0, 'Text::CSV_XS' => 0,
'Time::HiRes' => 0,
'URI::Encode' => 0, 'URI::Encode' => 0,
'URI::Escape' => 0, 'URI::Escape' => 0,
'UUID' => 0, 'UUID' => 0,
@ -95,6 +100,9 @@ my $builder = Local::Module::Build->new(
# for the testcover target # for the testcover target
'Devel::Cover' => 0, 'Devel::Cover' => 0,
'sigtrap' => 0, 'sigtrap' => 0,
# for development
'Convert::Ascii85' => 0,
'IO::Uncompress::UnXz' => 0,
}, },
add_to_cleanup => [ 'NGCP-Panel-*' ], add_to_cleanup => [ 'NGCP-Panel-*' ],
); );

6
debian/control vendored

@ -9,9 +9,11 @@ Build-Depends: debhelper (>= 8),
libcatalyst-modules-perl, libcatalyst-modules-perl,
libcatalyst-perl (>= 5.90040), libcatalyst-perl (>= 5.90040),
libcatalyst-view-tt-perl, libcatalyst-view-tt-perl,
libconvert-ascii-perl,
libdata-printer-perl, libdata-printer-perl,
libdata-validate-ip-perl, libdata-validate-ip-perl,
libdatetime-format-iso8601-perl, libdatetime-format-iso8601-perl,
libdatetime-format-rfc3339-perl,
libdatetime-format-mysql-perl, libdatetime-format-mysql-perl,
libdbix-class-resultset-recursiveupdate-perl (>= 0.30~), libdbix-class-resultset-recursiveupdate-perl (>= 0.30~),
libdevel-cover-perl, libdevel-cover-perl,
@ -22,6 +24,7 @@ Build-Depends: debhelper (>= 8),
libhtml-formhandler-model-dbic-perl, libhtml-formhandler-model-dbic-perl,
libhtml-formhandler-perl (>= 0.40026), libhtml-formhandler-perl (>= 0.40026),
libhtml-parser-perl, libhtml-parser-perl,
libio-compress-lzma-perl,
libmodule-install-perl, libmodule-install-perl,
libmoosex-fileattribute-perl, libmoosex-fileattribute-perl,
libmoosex-method-signatures-perl, libmoosex-method-signatures-perl,
@ -55,9 +58,11 @@ Depends: libcatalyst-actionrole-acl-perl,
libcatalyst-perl (>= 5.90040), libcatalyst-perl (>= 5.90040),
libcatalyst-view-tt-perl, libcatalyst-view-tt-perl,
libconfig-general-perl, libconfig-general-perl,
libconvert-ascii-perl,
libdata-printer-perl, libdata-printer-perl,
libdata-validate-ip-perl, libdata-validate-ip-perl,
libdatetime-format-iso8601-perl, libdatetime-format-iso8601-perl,
libdatetime-format-rfc3339-perl,
libdatetime-format-mysql-perl, libdatetime-format-mysql-perl,
libdatetime-perl, libdatetime-perl,
libdbix-class-resultset-recursiveupdate-perl (>= 0.30~), libdbix-class-resultset-recursiveupdate-perl (>= 0.30~),
@ -71,6 +76,7 @@ Depends: libcatalyst-actionrole-acl-perl,
libhtml-parser-perl, libhtml-parser-perl,
libhttp-message-perl, libhttp-message-perl,
libipc-system-simple-perl, libipc-system-simple-perl,
libio-compress-lzma-perl,
liblog-log4perl-perl, liblog-log4perl-perl,
libmodule-runtime-perl, libmodule-runtime-perl,
libmoose-perl, libmoose-perl,

@ -1,11 +1,15 @@
package NGCP::Panel::Controller::Root; package NGCP::Panel::Controller::Root;
use Sipwise::Base; use Sipwise::Base;
BEGIN { extends 'Catalyst::Controller' } BEGIN { extends 'Catalyst::Controller' }
use Carp qw(longmess);
use Convert::Ascii85 qw();
use Data::Dumper qw(Dumper);
use DateTime qw();
use DateTime::Format::RFC3339 qw();
use IO::Compress::Xz qw(xz);
use NGCP::Panel::Widget; use NGCP::Panel::Widget;
use Scalar::Util qw(blessed); use Scalar::Util qw(blessed);
use Time::HiRes qw();
# #
# Sets the actions in this controller to be registered with no prefix # Sets the actions in this controller to be registered with no prefix
@ -111,7 +115,41 @@ sub default :Path {
$c->detach( '/error_page' ); $c->detach( '/error_page' );
} }
sub end : ActionClass('RenderView') {} sub render :ActionClass('RenderView') { }
sub end :Private {
my ($self, $c) = @_;
$c->forward('render');
if (@{ $c->error }) {
my $incident = DateTime->from_epoch(epoch => Time::HiRes::time);
my $incident_id = sprintf '%X', $incident->strftime('%s%N');
my $incident_timestamp = DateTime::Format::RFC3339->new->format_datetime($incident);
my $crash_state;
if ($c->config->{log_crash_state}) {
local $Data::Dumper::Indent = 1;
local $Data::Dumper::Useqq = 1;
local $Data::Dumper::Deparse = 1;
local $Data::Dumper::Quotekeys = 0;
local $Data::Dumper::Sortkeys = 1;
my $buffer;
xz(\(join(q(), @{ $c->error }) . longmess . Dumper($c) . Dumper($c->config)), \$buffer);
$crash_state = Convert::Ascii85::encode($buffer);
$crash_state =~ s/(.{80})/$1\n/g;
}
$c->log->error(
"Exception id $incident_id at $incident_timestamp crash_state:" .
($crash_state ? ("\n" . $crash_state) : ' disabled')
);
$c->clear_errors;
$c->stash(
exception_incident => $incident_id,
exception_timestamp => $incident_timestamp,
template => 'error_page.tt'
);
$c->response->status(500);
$c->detach($c->view);
}
}
sub _prune_row { sub _prune_row {
my ($columns, %row) = @_; my ($columns, %row) = @_;
@ -129,8 +167,7 @@ sub error_page :Private {
my ($self,$c) = @_; my ($self,$c) = @_;
$c->log->error( 'Failed to find path ' . $c->request->path ); $c->log->error( 'Failed to find path ' . $c->request->path );
$c->stash(template => 'error_page.tt'); $c->stash(template => 'notfound_page.tt');
#$c->response->body( 'Page not found' );
$c->response->status(404); $c->response->status(404);
} }

@ -10,6 +10,9 @@ log4perl.appender.Default.layout=PatternLayout
log4perl.appender.Default.layout.ConversionPattern=%d{ISO8601} [%p] [%F +%L] %m{chomp}%n log4perl.appender.Default.layout.ConversionPattern=%d{ISO8601} [%p] [%F +%L] %m{chomp}%n
# perhaps also add: host=%H pid=%P # perhaps also add: host=%H pid=%P
# each crash state is <50 KiB
log_crash_state 1
<Model::DB> <Model::DB>
schema_class NGCP::Schema schema_class NGCP::Schema
</Model::DB> </Model::DB>

@ -0,0 +1,21 @@
#!/usr/bin/env perl
use Convert::Ascii85 qw();
use IO::Uncompress::UnXz qw(unxz $UnXzError);
local $/ = undef;
my $buf = Convert::Ascii85::decode(<>);
my $out;
unxz \$buf, \$out or die $UnXzError;
print $out;
__END__
=encoding UTF-8
=head1 NAME
ngcp_panel_decode_crash - decode a crash state from the Web server error log
=head1 USAGE
ngcp_panel_decode_crash < crashfile

@ -6,11 +6,16 @@
<h1>Oops!</h1> <h1>Oops!</h1>
<h2>[% c.response.status %] Not found</h2> <h2>[% c.response.status %] Internal server error </h2>
<div class="error-details"> <div class="error-details">
Sorry, an error has occured, Requested page not found! <p>Sorry, an exceptional error has occured:</p>
<ul>
<li>incident number: [% exception_incident %]</li>
<li>time of incident: [% exception_timestamp %]</li>
</ul>
<p>Details have been logged on the server. If you want to report the error,
describe what you were doing or attempting to do just before.</p>
</div> <!-- /error-details --> </div> <!-- /error-details -->
<div class="error-actions"> <div class="error-actions">

@ -0,0 +1,37 @@
<div class="row">
<div class="span12">
<div class="error-container">
<h1>Oops!</h1>
<h2>[% c.response.status %] Not found</h2>
<div class="error-details">
Sorry, an error has occured, Requested page not found!
</div> <!-- /error-details -->
<div class="error-actions">
<a href="[% c.uri_for('/back') %]" class="btn btn-large btn-primary">
<i class="icon-chevron-left"></i>
&nbsp;
Back to Dashboard
</a>
<a href="mailto:[% c.config.contact.email %]" class="btn btn-large">
<i class="icon-envelope"></i>
&nbsp;
Contact Support
</a>
</div> <!-- /error-actions -->
</div> <!-- /.error-container -->
</div> <!-- /.span12 -->
</div> <!-- /.row -->
Loading…
Cancel
Save