summaryrefslogtreecommitdiffstats
path: root/Bugzilla/Error.pm
diff options
context:
space:
mode:
Diffstat (limited to 'Bugzilla/Error.pm')
-rw-r--r--Bugzilla/Error.pm111
1 files changed, 50 insertions, 61 deletions
diff --git a/Bugzilla/Error.pm b/Bugzilla/Error.pm
index d67571848..9fcd16386 100644
--- a/Bugzilla/Error.pm
+++ b/Bugzilla/Error.pm
@@ -13,9 +13,10 @@ use warnings;
use base qw(Exporter);
-@Bugzilla::Error::EXPORT = qw(ThrowCodeError ThrowTemplateError ThrowUserError ThrowErrorPage);
+## no critic (Modules::ProhibitAutomaticExportation)
+our @EXPORT = qw( ThrowCodeError ThrowTemplateError ThrowUserError ThrowErrorPage);
+## use critic
-use Bugzilla::Sentry;
use Bugzilla::Constants;
use Bugzilla::WebService::Constants;
use Bugzilla::Util;
@@ -37,7 +38,7 @@ sub _in_eval {
}
sub _throw_error {
- my ($name, $error, $vars) = @_;
+ my ($name, $error, $vars, $logfunc) = @_;
$vars ||= {};
$vars->{error} = $error;
@@ -47,38 +48,6 @@ sub _throw_error {
my $dbh = eval { Bugzilla->dbh };
$dbh->bz_rollback_transaction() if ($dbh && $dbh->bz_in_transaction() && !_in_eval());
- my $datadir = bz_locations()->{'datadir'};
- # If a writable $datadir/errorlog exists, log error details there.
- if (-w "$datadir/errorlog") {
- require Data::Dumper;
- my $mesg = "";
- for (1..75) { $mesg .= "-"; };
- $mesg .= "\n[$$] " . time2str("%D %H:%M:%S ", time());
- $mesg .= "$name $error ";
- $mesg .= remote_ip();
- $mesg .= Bugzilla->user->login;
- $mesg .= (' actually ' . Bugzilla->sudoer->login) if Bugzilla->sudoer;
- $mesg .= "\n";
- my %params = Bugzilla->cgi->Vars;
- $Data::Dumper::Useqq = 1;
- for my $param (sort keys %params) {
- my $val = $params{$param};
- # obscure passwords
- $val = "*****" if $param =~ /password/i;
- # limit line length
- $val =~ s/^(.{512}).*$/$1\[CHOP\]/;
- $mesg .= "[$$] " . Data::Dumper->Dump([$val],["param($param)"]);
- }
- for my $var (sort keys %ENV) {
- my $val = $ENV{$var};
- $val = "*****" if $val =~ /password|http_pass/i;
- $mesg .= "[$$] " . Data::Dumper->Dump([$val],["env($var)"]);
- }
- open(ERRORLOGFID, ">>", "$datadir/errorlog");
- print ERRORLOGFID "$mesg\n";
- close ERRORLOGFID;
- }
-
my $template = Bugzilla->template;
my $message;
@@ -97,34 +66,24 @@ sub _throw_error {
message => \$message });
if ($Bugzilla::Template::is_processing) {
- $name =~ /^global\/(user|code)-error/;
- my $type = $1 // 'unknown';
+ my ($type) = $name =~ /^global\/(user|code)-error/;
+ $type //= 'unknown';
die Template::Exception->new("bugzilla.$type.$error", $vars);
}
if (Bugzilla->error_mode == ERROR_MODE_WEBPAGE) {
- if (sentry_should_notify($vars->{error})) {
- $vars->{maintainers_notified} = 1;
- $vars->{processed} = {};
- } else {
- $vars->{maintainers_notified} = 0;
- }
-
my $cgi = Bugzilla->cgi;
$cgi->close_standby_message('text/html', 'inline', 'error', 'html');
$template->process($name, $vars)
|| ThrowTemplateError($template->error());
print $cgi->multipart_final() if $cgi->{_multipart_in_progress};
-
- if ($vars->{maintainers_notified}) {
- sentry_handle_error($vars->{error}, $vars->{processed}->{error_message});
- }
+ $logfunc->("webpage error: $error");
}
elsif (Bugzilla->error_mode == ERROR_MODE_TEST) {
die Dumper($vars);
}
elsif (Bugzilla->error_mode == ERROR_MODE_DIE) {
- die("$message\n");
+ die "$message\n";
}
elsif (Bugzilla->error_mode == ERROR_MODE_DIE_SOAP_FAULT
|| Bugzilla->error_mode == ERROR_MODE_JSON_RPC
@@ -141,6 +100,7 @@ sub _throw_error {
}
if (Bugzilla->error_mode == ERROR_MODE_DIE_SOAP_FAULT) {
+ $logfunc->("XMLRPC error: $error ($code)");
die SOAP::Fault->faultcode($code)->faultstring($message);
}
else {
@@ -150,6 +110,11 @@ sub _throw_error {
if (Bugzilla->error_mode == ERROR_MODE_REST) {
my %status_code_map = %{ REST_STATUS_CODE_MAP() };
$status_code = $status_code_map{$code} || $status_code_map{'_default'};
+ $logfunc->("REST error: $error (HTTP $status_code, internal code $code)");
+ }
+ else {
+ my $fake_code = 100000 + $code;
+ $logfunc->("JSONRPC error: $error ($fake_code)");
}
# Technically JSON-RPC isn't allowed to have error numbers
# higher than 999, but we do this to avoid conflicts with
@@ -170,22 +135,44 @@ sub _throw_error {
exit;
}
+
+sub _add_vars_to_logging_fields {
+ my ($vars) = @_;
+
+ foreach my $key (keys %$vars) {
+ Bugzilla::Logging->fields->{"var_$key"} = $vars->{$key};
+ }
+}
+
+sub _make_logfunc {
+ my ($type) = @_;
+ my $logger = Log::Log4perl->get_logger("Bugzilla.Error.$type");
+ return sub {
+ local $Log::Log4perl::caller_depth = $Log::Log4perl::caller_depth + 3;
+ if ($type eq 'User') {
+ $logger->warn(@_);
+ }
+ else {
+ $logger->error(@_);
+ }
+ };
+}
+
+
sub ThrowUserError {
- _throw_error("global/user-error.html.tmpl", @_);
+ my ($error, $vars) = @_;
+ my $logfunc = _make_logfunc('User');
+ _add_vars_to_logging_fields($vars);
+
+ _throw_error( 'global/user-error.html.tmpl', $error, $vars, $logfunc);
}
sub ThrowCodeError {
- my (undef, $vars) = @_;
-
- # Don't show function arguments, in case they contain
- # confidential data.
- local $Carp::MaxArgNums = -1;
- # Don't show the error as coming from Bugzilla::Error, show it
- # as coming from the caller.
- local $Carp::CarpInternal{'Bugzilla::Error'} = 1;
- $vars->{traceback} //= Carp::longmess();
+ my ($error, $vars) = @_;
+ my $logfunc = _make_logfunc('Code');
+ _add_vars_to_logging_fields($vars);
- _throw_error("global/code-error.html.tmpl", @_);
+ _throw_error( 'global/code-error.html.tmpl', $error, $vars, $logfunc );
}
sub ThrowTemplateError {
@@ -211,10 +198,12 @@ sub ThrowTemplateError {
# we never want to display this to the user
exit if $template_err =~ /\bModPerl::Util::exit\b/;
+ state $logger = Log::Log4perl->get_logger('Bugzilla.Error.Template');
+ $logger->error($template_err);
+
$vars->{'template_error_msg'} = $template_err;
$vars->{'error'} = "template_error";
- sentry_handle_error('error', $template_err);
$vars->{'template_error_msg'} =~ s/ at \S+ line \d+\.\s*$//;
my $template = Bugzilla->template;