Support logging DB queries
parent
c59ff61181
commit
961e6ff825
|
@ -200,8 +200,6 @@ sub _tt_provider_load_compiled
|
|||
# Global Code
|
||||
#####################################################################
|
||||
|
||||
# $::SIG{__DIE__} = i_am_cgi() ? \&CGI::Carp::confess : \&Carp::confess;
|
||||
|
||||
# Note that this is a raw subroutine, not a method, so $class isn't available.
|
||||
sub init_page
|
||||
{
|
||||
|
@ -1083,6 +1081,7 @@ sub _cleanup
|
|||
{
|
||||
next if !$dbh;
|
||||
$dbh->bz_rollback_transaction() if $dbh->bz_in_transaction;
|
||||
$dbh->write_query_log;
|
||||
$dbh->disconnect;
|
||||
}
|
||||
undef $_request_cache;
|
||||
|
|
|
@ -95,6 +95,12 @@ use constant get_param_list => (
|
|||
default => 0,
|
||||
},
|
||||
|
||||
{
|
||||
name => 'query_log',
|
||||
type => 't',
|
||||
default => '',
|
||||
},
|
||||
|
||||
{
|
||||
name => 'docs_urlbase',
|
||||
type => 't',
|
||||
|
|
129
Bugzilla/DB.pm
129
Bugzilla/DB.pm
|
@ -44,6 +44,7 @@ use Bugzilla::Error;
|
|||
use Bugzilla::DB::Schema;
|
||||
|
||||
use List::Util qw(max);
|
||||
use POSIX qw(strftime);
|
||||
use Storable qw(dclone);
|
||||
|
||||
#####################################################################
|
||||
|
@ -1474,6 +1475,134 @@ sub _check_references {
|
|||
}
|
||||
}
|
||||
|
||||
sub interpolate_params
|
||||
{
|
||||
my $self = shift;
|
||||
my ($sql, $bind) = @_;
|
||||
my $r = '';
|
||||
# match unquoted part + any number of quoted strings/identifiers
|
||||
while ($sql =~ s!^([^"`']*)((?:`(?:[^`]+|``)*`|"(?:[^"\\]+|\\.|"")*"|'(?:[^'\\]+|\\.|'')*)*)!!so)
|
||||
{
|
||||
my ($c, $q) = ($1, $2);
|
||||
last if $c eq '' && $q eq '';
|
||||
$c =~ s/\?/$self->quote(shift @$bind)/geso;
|
||||
$r .= $c.$q;
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
sub write_query_log
|
||||
{
|
||||
my $self = shift;
|
||||
if (my $logfile = Bugzilla->params->{query_log})
|
||||
{
|
||||
# Log queries
|
||||
$logfile = bz_locations()->{datadir} . '/' . $logfile if substr($logfile, 0, 1) ne '/';
|
||||
trick_taint($logfile);
|
||||
my $fd;
|
||||
my @q = @{ tied(%$self)->{_logged_queries} || [] };
|
||||
if (@q && open $fd, ">>", $logfile)
|
||||
{
|
||||
print $fd strftime("[%Y-%m-%d %H:%M:%S] ", localtime) .
|
||||
"[pid=$$] $ENV{REQUEST_URI} DB queries:\n" . join("\n", map { $self->interpolate_params(@$_).';' } @q) . "\n\n";
|
||||
close $fd;
|
||||
}
|
||||
tied(%$self)->{_logged_queries} = [];
|
||||
}
|
||||
}
|
||||
|
||||
sub log_query
|
||||
{
|
||||
my $self = shift;
|
||||
push @{tied(%$self)->{_logged_queries}}, [ @_ ] if Bugzilla->params->{query_log};
|
||||
}
|
||||
|
||||
sub get_logged_queries
|
||||
{
|
||||
my $self = shift;
|
||||
return tied(%$self)->{_logged_queries} || [];
|
||||
}
|
||||
|
||||
sub do
|
||||
{
|
||||
my $self = shift;
|
||||
my ($sql, undef, @bind) = @_;
|
||||
$self->log_query($sql, \@bind);
|
||||
$self->SUPER::do(@_);
|
||||
}
|
||||
|
||||
sub selectrow_array
|
||||
{
|
||||
my $self = shift;
|
||||
my ($sql, undef, @bind) = @_;
|
||||
$self->log_query($sql, \@bind);
|
||||
return $self->SUPER::selectrow_array(@_);
|
||||
}
|
||||
|
||||
sub selectrow_arrayref
|
||||
{
|
||||
my $self = shift;
|
||||
my ($sql, undef, @bind) = @_;
|
||||
$self->log_query($sql, \@bind);
|
||||
return $self->SUPER::selectrow_array(@_);
|
||||
}
|
||||
|
||||
sub selectrow_hashref
|
||||
{
|
||||
my $self = shift;
|
||||
my ($sql, undef, @bind) = @_;
|
||||
$self->log_query($sql, \@bind);
|
||||
return $self->SUPER::selectrow_hashref(@_);
|
||||
}
|
||||
|
||||
sub selectall_hashref
|
||||
{
|
||||
my $self = shift;
|
||||
my ($sql, undef, @bind) = @_;
|
||||
$self->log_query($sql, \@bind);
|
||||
return $self->SUPER::selectall_hashref(@_);
|
||||
}
|
||||
|
||||
sub selectall_arrayref
|
||||
{
|
||||
my $self = shift;
|
||||
my ($sql, undef, @bind) = @_;
|
||||
$self->log_query($sql, \@bind);
|
||||
return $self->SUPER::selectall_arrayref(@_);
|
||||
}
|
||||
|
||||
sub selectcol_arrayref
|
||||
{
|
||||
my $self = shift;
|
||||
my ($sql, undef, @bind) = @_;
|
||||
$self->log_query($sql, \@bind);
|
||||
return $self->SUPER::selectcol_arrayref(@_);
|
||||
}
|
||||
|
||||
sub prepare
|
||||
{
|
||||
my $self = shift;
|
||||
return bless $self->SUPER::prepare(@_), 'Bugzilla::DB::st';
|
||||
}
|
||||
|
||||
sub prepare_cached
|
||||
{
|
||||
my $self = shift;
|
||||
return bless $self->SUPER::prepare_cached(@_), 'Bugzilla::DB::st';
|
||||
}
|
||||
|
||||
package Bugzilla::DB::st;
|
||||
|
||||
use base qw(DBI::st);
|
||||
|
||||
sub execute
|
||||
{
|
||||
my $self = shift;
|
||||
my $dbh = tied(%$self)->{Database}->{Driver}->{ChildHandles};
|
||||
$dbh->[$#$dbh]->log_query(tied(%$self)->{Statement}, [ @_ ]);
|
||||
return $self->SUPER::execute(@_);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
|
|
@ -778,7 +778,8 @@ sub bz_setup_database {
|
|||
}
|
||||
|
||||
package Bugzilla::DB::Oracle::st;
|
||||
use base qw(DBI::st);
|
||||
|
||||
use base qw(Bugzilla::DB::st);
|
||||
|
||||
sub fetchrow_arrayref
|
||||
{
|
||||
|
|
|
@ -40,6 +40,9 @@
|
|||
report_user_errors_to_maintainer =>
|
||||
"Whether to send e-mail messages about each 'user' (invalid input, non-fatal) error to Bugzilla maintainer (not recommended).",
|
||||
|
||||
query_log =>
|
||||
"<b>Use only for debug purposes!</b> Path to the file to which Bugzilla should log all database queries with all parameters.",
|
||||
|
||||
docs_urlbase =>
|
||||
"The URL that is the common initial leading part of all"
|
||||
_ " $terms.Bugzilla documentation URLs. It may be an absolute URL,"
|
||||
|
|
Loading…
Reference in New Issue