From: Gilles Darold Date: Mon, 17 Jun 2019 14:42:29 +0000 (+0200) Subject: Update tools/pgbadger_tools script to be compatible with new binary file format in... X-Git-Tag: v11.0~10 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=48be6f5add613308b1aab82322fbdb1e50d26899;p=pgbadger Update tools/pgbadger_tools script to be compatible with new binary file format in pgBadger v11. --- diff --git a/tools/pgbadger_tools b/tools/pgbadger_tools index 6bc69aa..f2039b8 100755 --- a/tools/pgbadger_tools +++ b/tools/pgbadger_tools @@ -35,7 +35,7 @@ my @SQL_ACTION = ('SELECT', 'INSERT', 'UPDATE', 'DELETE', 'COPY FROM', 'COPY T my %overall_stat = (); my %pgb_overall_stat = (); my %overall_checkpoint = (); -my @top_slowest = (); +my %top_slowest = (); my %normalyzed_info = (); my %error_info = (); my %pgb_error_info = (); @@ -61,12 +61,18 @@ my %cur_info = (); my %cur_temp_info = (); my %cur_lock_info = (); my %tsung_session = (); +my %errors_code = (); my @top_locked_info = (); my @top_tempfile_info = (); my @log_files = (); my $nlines = 0; my $sample = 3; my $top = 20; +my $anonymize = 0; + +# Let's say --explode was not used to generate the binary files +# in this case all data are stored under the postgres database. +my $def_db = 'postgres'; ################################################################## # Get the command line parameters @@ -158,17 +164,17 @@ if ($psql_cmd) { ################################################################## if ($explain_slowest) { &logmsg('LOG', "Output each slowest queries within explain statement."); - &dump_slowest_queries(); + &dump_slowest_queries($def_db); } # when option --explain-time-consuming is set at command line if ($explain_time_consuming) { &logmsg('LOG', "Output each most times consuming queries within explain statement."); - &dump_times_consuming_queries(); + &dump_times_consuming_queries($def_db); } # when option --explain-normalized is set at command line if ($explain_normalized) { &logmsg('LOG', "Output each slowest normalized queries within explain statement."); - &dump_normalized_slowest_queries(); + &dump_normalized_slowest_queries($def_db); } #################################################################### @@ -184,11 +190,11 @@ if ($csv_time_consuming || $csv_slowest || $csv_normalized) { Text::CSV->import(); } if ($csv_time_consuming) { - &csv_times_consuming_queries(); + &csv_times_consuming_queries($def_db); } elsif ($csv_slowest) { - &csv_slowest_queries(); + &csv_slowest_queries($def_db); } elsif ($csv_normalized) { - &csv_normalized_queries(); + &csv_normalized_queries($def_db); } } @@ -320,31 +326,40 @@ sub logmsg } #### -# Stores top N error sample queries +# Stores top N error sample queries, taken from pgbadger script #### sub set_top_error_sample { - my ($q, $date, $real_error, $detail, $context, $statement, $hint, $db, $user, $app, $remote) = @_; + my ($curdb, $q, $date, $real_error, $detail, $context, $statement, $hint, $db, $user, $app, $remote, $sqlstate) = @_; + + $errors_code{$curdb}{$sqlstate}++ if ($sqlstate); # Stop when we have our number of samples - if (!exists $error_info{$q}{date} || ($#{$error_info{$q}{date}} < $sample)) { - if ( ($q =~ /deadlock detected/) || ($real_error && !grep(/^\Q$real_error\E$/, @{$error_info{$q}{error}})) ) { - push(@{$error_info{$q}{date}}, $date); - push(@{$error_info{$q}{detail}}, $detail); - push(@{$error_info{$q}{context}}, $context); - push(@{$error_info{$q}{statement}}, $statement); - push(@{$error_info{$q}{hint}}, $hint); - push(@{$error_info{$q}{error}}, $real_error); - push(@{$error_info{$q}{db}}, $db); - push(@{$error_info{$q}{user}}, $user); - push(@{$error_info{$q}{app}}, $app); - push(@{$error_info{$q}{remote}}, $remote); + if (!exists $error_info{$curdb}{$q}{date} || ($#{$error_info{$curdb}{$q}{date}}+1 < $sample)) { + if ( ($q =~ /deadlock detected/) || ($real_error && !grep(/^\Q$real_error\E$/, @{$error_info{$curdb}{$q}{error}})) ) { + if ($anonymize) { + $context = &anonymize_query($context); + $statement = &anonymize_query($statement); + $detail = &anonymize_query($detail); + } + + push(@{$error_info{$curdb}{$q}{date}}, $date); + push(@{$error_info{$curdb}{$q}{detail}}, $detail); + push(@{$error_info{$curdb}{$q}{context}}, $context); + push(@{$error_info{$curdb}{$q}{statement}}, $statement); + push(@{$error_info{$curdb}{$q}{hint}}, $hint); + push(@{$error_info{$curdb}{$q}{error}}, $real_error); + push(@{$error_info{$curdb}{$q}{db}}, $db); + push(@{$error_info{$curdb}{$q}{user}}, $user); + push(@{$error_info{$curdb}{$q}{app}}, $app); + push(@{$error_info{$curdb}{$q}{remote}}, $remote); + push(@{$error_info{$curdb}{$q}{sqlstate}}, $sqlstate); } } } #### -# Load statistics from binary file into memory +# Load statistics from binary file into memory, the function is copied from pgbadger script #### sub load_stats { @@ -373,50 +388,93 @@ sub load_stats my %_tempfile_info = %{$stats{tempfile_info}}; my %_cancelled_info = %{$stats{cancelled_info}}; my %_logs_type = %{$stats{logs_type}}; + my %_errors_code = %{$stats{errors_code}}; my %_lock_info = %{$stats{lock_info}}; my %_per_minute_info = %{$stats{per_minute_info}}; my %_pgb_per_minute_info = %{$stats{pgb_per_minute_info}}; - my @_top_slowest = @{$stats{top_slowest}}; + my %_top_slowest = %{$stats{top_slowest}}; my $_nlines = $stats{nlines}; my $_first_log_timestamp = $stats{first_log_timestamp}; my $_last_log_timestamp = $stats{last_log_timestamp}; my @_log_files = @{$stats{log_files}}; my %_autovacuum_info = %{$stats{autovacuum_info}}; my %_autoanalyze_info = %{$stats{autoanalyze_info}}; - my @_top_locked_info = @{$stats{top_locked_info}}; - my @_top_tempfile_info = @{$stats{top_tempfile_info}}; - my @_top_cancelled_info = @{$stats{top_cancelled_info}}; + my %_top_locked_info = %{$stats{top_locked_info}}; + my %_top_tempfile_info = %{$stats{top_tempfile_info}}; + my %_top_cancelled_info = %{$stats{top_cancelled_info}}; ### overall_stat ### - $overall_stat{queries_number} += $_overall_stat{queries_number}; - - if ($_overall_stat{'first_log_ts'}) { - $overall_stat{'first_log_ts'} = $_overall_stat{'first_log_ts'} - if (!$overall_stat{'first_log_ts'} || - ($overall_stat{'first_log_ts'} gt $_overall_stat{'first_log_ts'})); + # Those a used to update the progress bar and are not related to any database + $overall_stat{'queries_number'} += $_overall_stat{'queries_number'}; + $overall_stat{'errors_number'} += $_overall_stat{'errors_number'}; + $pgb_overall_stat{'queries_number'} += $_pgb_overall_stat{'queries_number'}; + $pgb_overall_stat{'errors_number'} += $_pgb_overall_stat{'errors_number'}; + foreach my $d (keys %{ $_overall_stat{nlines} }) + { + $overall_stat{'nlines'}{$d} += $_overall_stat{'nlines'}{$d}; } - $overall_stat{'last_log_ts'} = $_overall_stat{'last_log_ts'} - if not $overall_stat{'last_log_ts'} - or $overall_stat{'last_log_ts'} lt $_overall_stat{'last_log_ts'}; + foreach my $curdb (keys %_overall_stat) + { + next if (grep(/^$curdb$/, 'queries_number', 'errors_number', 'queries_number', 'errors_number', 'nlines')); + if ($_overall_stat{$curdb}{'first_log_ts'}) { + $overall_stat{$curdb}{'first_log_ts'} = $_overall_stat{$curdb}{'first_log_ts'} + if (!$overall_stat{$curdb}{'first_log_ts'} || + ($overall_stat{$curdb}{'first_log_ts'} gt $_overall_stat{$curdb}{'first_log_ts'})); + } - if ($_overall_stat{'first_query_ts'}) { - $overall_stat{'first_query_ts'} = $_overall_stat{'first_query_ts'} - if (!$overall_stat{'first_query_ts'} || - ($overall_stat{'first_query_ts'} gt $_overall_stat{'first_query_ts'})); - } + $overall_stat{$curdb}{'last_log_ts'} = $_overall_stat{$curdb}{'last_log_ts'} + if not $overall_stat{$curdb}{'last_log_ts'} + or $overall_stat{$curdb}{'last_log_ts'} lt $_overall_stat{$curdb}{'last_log_ts'}; - $overall_stat{'last_query_ts'} = $_overall_stat{'last_query_ts'} - if not $overall_stat{'last_query_ts'} - or $overall_stat{'last_query_ts'} lt $_overall_stat{'last_query_ts'}; + $overall_stat{$curdb}{'queries_number'} += $_overall_stat{$curdb}{'queries_number'}; + $overall_stat{$curdb}{'errors_number'} += $_overall_stat{$curdb}{'errors_number'}; + $pgb_overall_stat{$curdb}{'queries_number'} += $_pgb_overall_stat{$curdb}{'queries_number'}; + $pgb_overall_stat{$curdb}{'errors_number'} += $_pgb_overall_stat{$curdb}{'errors_number'}; + + if ($_overall_stat{$curdb}{'first_query_ts'}) { + $overall_stat{$curdb}{'first_query_ts'} = $_overall_stat{$curdb}{'first_query_ts'} + if (!$overall_stat{$curdb}{'first_query_ts'} || + ($overall_stat{$curdb}{'first_query_ts'} gt $_overall_stat{$curdb}{'first_query_ts'})); + } - $overall_stat{errors_number} += $_overall_stat{errors_number}; - $overall_stat{queries_duration} += $_overall_stat{queries_duration}; + $overall_stat{$curdb}{'last_query_ts'} = $_overall_stat{$curdb}{'last_query_ts'} + if not $overall_stat{$curdb}{'last_query_ts'} + or $overall_stat{$curdb}{'last_query_ts'} lt $_overall_stat{$curdb}{'last_query_ts'}; + + $overall_stat{$curdb}{queries_duration} += $_overall_stat{$curdb}{queries_duration}; + + foreach my $a (@SQL_ACTION) { + $overall_stat{$curdb}{$a} += $_overall_stat{$curdb}{$a} + if exists $_overall_stat{$curdb}{$a}; + } + + foreach my $k (keys %{$_overall_stat{$curdb}{peak}}) { + $overall_stat{$curdb}{peak}{$k}{query} += $_overall_stat{$curdb}{peak}{$k}{query}; + $overall_stat{$curdb}{peak}{$k}{select} += $_overall_stat{$curdb}{peak}{$k}{select}; + $overall_stat{$curdb}{peak}{$k}{write} += $_overall_stat{$curdb}{peak}{$k}{write}; + $overall_stat{$curdb}{peak}{$k}{connection} += $_overall_stat{$curdb}{peak}{$k}{connection}; + $overall_stat{$curdb}{peak}{$k}{session} += $_overall_stat{$curdb}{peak}{$k}{session}; + $overall_stat{$curdb}{peak}{$k}{tempfile_size} += $_overall_stat{$curdb}{peak}{$k}{tempfile_size}; + $overall_stat{$curdb}{peak}{$k}{tempfile_count} += $_overall_stat{$curdb}{peak}{$k}{tempfile_count}; + $overall_stat{$curdb}{peak}{$k}{cancelled_size} += $_overall_stat{$curdb}{peak}{$k}{cancelled_size}; + $overall_stat{$curdb}{peak}{$k}{cancelled_count} += $_overall_stat{$curdb}{peak}{$k}{cancelled_count}; + } + + foreach my $k (keys %{$_overall_stat{$curdb}{histogram}{query_time}}) { + $overall_stat{$curdb}{histogram}{query_time}{$k} += $_overall_stat{$curdb}{histogram}{query_time}{$k}; + } + $overall_stat{$curdb}{histogram}{query_total} += $_overall_stat{$curdb}{histogram}{total}; + $overall_stat{$curdb}{histogram}{query_total} += $_overall_stat{$curdb}{histogram}{query_total}; + foreach my $k (keys %{$_overall_stat{$curdb}{histogram}{session_time}}) { + $overall_stat{$curdb}{histogram}{session_time}{$k} += $_overall_stat{$curdb}{histogram}{session_time}{$k}; + } + $overall_stat{$curdb}{histogram}{session_total} += $_overall_stat{$curdb}{histogram}{session_total}; - foreach my $a (@SQL_ACTION) { - $overall_stat{$a} += $_overall_stat{$a} - if exists $_overall_stat{$a}; + foreach my $k ('prepare', 'bind','execute') { + $overall_stat{$curdb}{$k} += $_overall_stat{$curdb}{$k}; + } } $overall_checkpoint{checkpoint_warning} += $_overall_checkpoint{checkpoint_warning}; @@ -424,35 +482,11 @@ sub load_stats if ($_overall_checkpoint{checkpoint_write} > $overall_checkpoint{checkpoint_write}); $overall_checkpoint{checkpoint_sync} = $_overall_checkpoint{checkpoint_sync} if ($_overall_checkpoint{checkpoint_sync} > $overall_checkpoint{checkpoint_sync}); - foreach my $k (keys %{$_overall_stat{peak}}) { - $overall_stat{peak}{$k}{query} += $_overall_stat{peak}{$k}{query}; - $overall_stat{peak}{$k}{select} += $_overall_stat{peak}{$k}{select}; - $overall_stat{peak}{$k}{write} += $_overall_stat{peak}{$k}{write}; - $overall_stat{peak}{$k}{connection} += $_overall_stat{peak}{$k}{connection}; - $overall_stat{peak}{$k}{session} += $_overall_stat{peak}{$k}{session}; - $overall_stat{peak}{$k}{tempfile_size} += $_overall_stat{peak}{$k}{tempfile_size}; - $overall_stat{peak}{$k}{tempfile_count} += $_overall_stat{peak}{$k}{tempfile_count}; - $overall_stat{peak}{$k}{cancelled_size} += $_overall_stat{peak}{$k}{cancelled_size}; - $overall_stat{peak}{$k}{cancelled_count} += $_overall_stat{peak}{$k}{cancelled_count}; - } - - foreach my $k (keys %{$_overall_stat{histogram}{query_time}}) { - $overall_stat{histogram}{query_time}{$k} += $_overall_stat{histogram}{query_time}{$k}; - } - $overall_stat{histogram}{query_total} += $_overall_stat{histogram}{total}; - $overall_stat{histogram}{query_total} += $_overall_stat{histogram}{query_total}; - foreach my $k (keys %{$_overall_stat{histogram}{session_time}}) { - $overall_stat{histogram}{session_time}{$k} += $_overall_stat{histogram}{session_time}{$k}; - } - $overall_stat{histogram}{session_total} += $_overall_stat{histogram}{session_total}; - - foreach my $k ('prepare', 'bind','execute') { - $overall_stat{$k} += $_overall_stat{$k}; - } - foreach my $k (keys %{$_overall_checkpoint{peak}}) { $overall_checkpoint{peak}{$k}{checkpoint_wbuffer} += $_overall_checkpoint{peak}{$k}{checkpoint_wbuffer}; $overall_checkpoint{peak}{$k}{walfile_usage} += $_overall_checkpoint{peak}{$k}{walfile_usage}; + $overall_checkpoint{peak}{$k}{distance} += $_overall_checkpoint{peak}{$k}{distance}; + $overall_checkpoint{peak}{$k}{estimate} += $_overall_checkpoint{peak}{$k}{estimate}; } ### pgbouncer related overall stats ### @@ -470,98 +504,106 @@ sub load_stats } $pgb_overall_stat{histogram}{session_total} += $_pgb_overall_stat{histogram}{session_total}; - $pgb_overall_stat{errors_number} += $_pgb_overall_stat{errors_number}; - ### Logs level ### - foreach my $l (qw(LOG WARNING ERROR FATAL PANIC DETAIL HINT STATEMENT CONTEXT)) { - $logs_type{$l} += $_logs_type{$l} if exists $_logs_type{$l}; + foreach my $l (qw(LOG WARNING ERROR FATAL PANIC DETAIL HINT STATEMENT CONTEXT)) + { + foreach my $curdb (keys %_logs_type) + { + $logs_type{$curdb}{$l} += $_logs_type{$curdb}{$l} if exists $_logs_type{$curdb}{$l}; + } + } + + ### Errors code ### + + foreach my $curdb (keys %_errors_code) + { + foreach my $c (keys %{$_errors_code{$curdb}}) { + $errors_code{$curdb}{$c} += $_errors_code{$curdb}{$c}; + } } ### database_info ### - foreach my $db (keys %_database_info) { - foreach my $k (keys %{ $_database_info{$db} }) { - $database_info{$db}{$k} += $_database_info{$db}{$k}; + foreach my $curdb (keys %_database_info) + { + foreach my $db (keys %{$_database_info{$curdb}}) { + foreach my $k (keys %{ $_database_info{$curdb}{$db} }) { + $database_info{$curdb}{$db}{$k} += $_database_info{$curdb}{$db}{$k}; + } } } ### application_info ### - foreach my $app (keys %_application_info) { - foreach my $k (keys %{ $_application_info{$app} }) { - $application_info{$app}{$k} += $_application_info{$app}{$k}; + foreach my $curdb (keys %_application_info) + { + foreach my $app (keys %{$_application_info{$curdb}}) { + foreach my $k (keys %{ $_application_info{$curdb}{$app} }) { + $application_info{$curdb}{$app}{$k} += $_application_info{$curdb}{$app}{$k}; + } } } ### user_info ### - foreach my $u (keys %_user_info) { - foreach my $k (keys %{ $_user_info{$u} }) { - $user_info{$u}{$k} += $_user_info{$u}{$k}; + foreach my $curdb (keys %_user_info) + { + foreach my $u (keys %{$_user_info{$curdb}}) { + foreach my $k (keys %{ $_user_info{$curdb}{$u} }) { + $user_info{$curdb}{$u}{$k} += $_user_info{$curdb}{$u}{$k}; + } } } ### host_info ### - foreach my $h (keys %_host_info) { - foreach my $k (keys %{ $_host_info{$h} }) { - $host_info{$h}{$k} += $_host_info{$h}{$k}; + foreach my $curdb (keys %_host_info) + { + foreach my $h (keys %{$_host_info{$curdb}}) { + foreach my $k (keys %{ $_host_info{$curdb}{$h} }) { + $host_info{$curdb}{$h}{$k} += $_host_info{$curdb}{$h}{$k}; + } } } ### connection_info ### - foreach my $db (keys %{ $_connection_info{database} }) { - $connection_info{database}{$db} += $_connection_info{database}{$db}; - } + foreach my $curdb (keys %_connection_info) + { + foreach my $db (keys %{ $_connection_info{$curdb}{database} }) { + $connection_info{$curdb}{database}{$db} += $_connection_info{$curdb}{database}{$db}; + } - foreach my $db (keys %{ $_connection_info{database_user} }) { - foreach my $user (keys %{ $_connection_info{database_user}{$db} }) { - $connection_info{database_user}{$db}{$user} += $_connection_info{database_user}{$db}{$user}; + foreach my $db (keys %{ $_connection_info{$curdb}{database_user} }) { + foreach my $user (keys %{ $_connection_info{$curdb}{database_user}{$db} }) { + $connection_info{$curdb}{database_user}{$db}{$user} += $_connection_info{$curdb}{database_user}{$db}{$user}; + } } - } - foreach my $user (keys %{ $_connection_info{user} }) { - $connection_info{user}{$user} += $_connection_info{user}{$user}; - } + foreach my $db (keys %{ $_connection_info{$curdb}{database_host} }) { + foreach my $user (keys %{ $_connection_info{$curdb}{database_host}{$db} }) { + $connection_info{$curdb}{database_host}{$db}{$user} += $_connection_info{$curdb}{database_host}{$db}{$user}; + } + } - foreach my $host (keys %{ $_connection_info{host} }) { - $connection_info{host}{$host} += $_connection_info{host}{$host}; - } + foreach my $user (keys %{ $_connection_info{$curdb}{user} }) { + $connection_info{$curdb}{user}{$user} += $_connection_info{$curdb}{user}{$user}; + } - $connection_info{count} += $_connection_info{count}; + foreach my $host (keys %{ $_connection_info{$curdb}{host} }) { + $connection_info{$curdb}{host}{$host} += $_connection_info{$curdb}{host}{$host}; + } - foreach my $day (keys %{ $_connection_info{chronos} }) { - foreach my $hour (keys %{ $_connection_info{chronos}{$day} }) { + $connection_info{$curdb}{count} += $_connection_info{$curdb}{count}; - $connection_info{chronos}{$day}{$hour}{count} += $_connection_info{chronos}{$day}{$hour}{count} + foreach my $day (keys %{ $_connection_info{$curdb}{chronos} }) + { + foreach my $hour (keys %{ $_connection_info{$curdb}{chronos}{$day} }) { -############################################################################### -# May be used in the future to display more detailed information on connection -# -# foreach my $db (keys %{ $_connection_info{chronos}{$day}{$hour}{database} }) { -# $connection_info{chronos}{$day}{$hour}{database}{$db} += $_connection_info{chronos}{$day}{$hour}{database}{$db}; -# } -# -# foreach my $db (keys %{ $_connection_info{chronos}{$day}{$hour}{database_user} }) { -# foreach my $user (keys %{ $_connection_info{chronos}{$day}{$hour}{database_user}{$db} }) { -# $connection_info{chronos}{$day}{$hour}{database_user}{$db}{$user} += -# $_connection_info{chronos}{$day}{$hour}{database_user}{$db}{$user}; -# } -# } -# -# foreach my $user (keys %{ $_connection_info{chronos}{$day}{$hour}{user} }) { -# $connection_info{chronos}{$day}{$hour}{user}{$user} += -# $_connection_info{chronos}{$day}{$hour}{user}{$user}; -# } -# -# foreach my $host (keys %{ $_connection_info{chronos}{$day}{$hour}{host} }) { -# $connection_info{chronos}{$day}{$hour}{host}{$host} += -# $_connection_info{chronos}{$day}{$hour}{host}{$host}; -# } -############################################################################### + $connection_info{$curdb}{chronos}{$day}{$hour}{count} += $_connection_info{$curdb}{chronos}{$day}{$hour}{count}; + } } } @@ -577,6 +619,12 @@ sub load_stats } } + foreach my $db (keys %{ $_pgb_connection_info{database_host} }) { + foreach my $user (keys %{ $_pgb_connection_info{database_host}{$db} }) { + $pgb_connection_info{database_host}{$db}{$user} += $_pgb_connection_info{database_host}{$db}{$user}; + } + } + foreach my $user (keys %{ $_pgb_connection_info{user} }) { $pgb_connection_info{user}{$user} += $_pgb_connection_info{user}{$user}; } @@ -601,35 +649,40 @@ sub load_stats ### error_info ### - foreach my $q (keys %_error_info) { - $error_info{$q}{count} += $_error_info{$q}{count}; - foreach my $day (keys %{ $_error_info{$q}{chronos} }) { - foreach my $hour (keys %{$_error_info{$q}{chronos}{$day}}) { - $error_info{$q}{chronos}{$day}{$hour}{count} += $_error_info{$q}{chronos}{$day}{$hour}{count}; - foreach my $min (keys %{$_error_info{$q}{chronos}{$day}{$hour}{min}}) { - $error_info{$q}{chronos}{$day}{$hour}{min}{$min} += $_error_info{$q}{chronos}{$day}{$hour}{min}{$min}; + foreach my $curdb (keys %_error_info) + { + foreach my $q (keys %{$_error_info{$curdb}}) { + $error_info{$curdb}{$q}{count} += $_error_info{$curdb}{$q}{count}; + foreach my $day (keys %{ $_error_info{$curdb}{$q}{chronos} }) { + foreach my $hour (keys %{$_error_info{$curdb}{$q}{chronos}{$day}}) { + $error_info{$curdb}{$q}{chronos}{$day}{$hour}{count} += $_error_info{$curdb}{$q}{chronos}{$day}{$hour}{count}; + foreach my $min (keys %{$_error_info{$curdb}{$q}{chronos}{$day}{$hour}{min}}) { + $error_info{$curdb}{$q}{chronos}{$day}{$hour}{min}{$min} += $_error_info{$curdb}{$q}{chronos}{$day}{$hour}{min}{$min}; + } } } - } - for (my $i = 0; $i <= $#{$_error_info{$q}{date}}; $i++) { - &set_top_error_sample( $q, - $_error_info{$q}{date}[$i], - $_error_info{$q}{error}[$i], - $_error_info{$q}{detail}[$i], - $_error_info{$q}{context}[$i], - $_error_info{$q}{statement}[$i], - $_error_info{$q}{hint}[$i], - $_error_info{$q}{db}[$i], - $_error_info{$q}{user}[$i], - $_error_info{$q}{app}[$i], - $_error_info{$q}{remote}[$i] - ); + for (my $i = 0; $i <= $#{$_error_info{$curdb}{$q}{date}}; $i++) { + &set_top_error_sample( $curdb, $q, + $_error_info{$curdb}{$q}{date}[$i], + $_error_info{$curdb}{$q}{error}[$i], + $_error_info{$curdb}{$q}{detail}[$i], + $_error_info{$curdb}{$q}{context}[$i], + $_error_info{$curdb}{$q}{statement}[$i], + $_error_info{$curdb}{$q}{hint}[$i], + $_error_info{$curdb}{$q}{db}[$i], + $_error_info{$curdb}{$q}{user}[$i], + $_error_info{$curdb}{$q}{app}[$i], + $_error_info{$curdb}{$q}{remote}[$i], + $_error_info{$curdb}{$q}{sqlstate}[$i] + ); + } } } ### pgbouncer error_info ### - foreach my $q (keys %_pgb_error_info) { + foreach my $q (keys %_pgb_error_info) + { $pgb_error_info{$q}{count} += $_pgb_error_info{$q}{count}; foreach my $day (keys %{ $_pgb_error_info{$q}{chronos} }) { foreach my $hour (keys %{$_pgb_error_info{$q}{chronos}{$day}}) { @@ -640,8 +693,8 @@ sub load_stats } } for (my $i = 0; $i <= $#{$_pgb_error_info{$q}{date}}; $i++) { - &pgb_set_top_error_sample( $q, - $_pgb_error_info{$q}{date}[$i], + &pgb_set_top_error_sample($q, + $_pgb_error_info{$q}{date}[$i], $_pgb_error_info{$q}{error}[$i], $_pgb_error_info{$q}{db}[$i], $_pgb_error_info{$q}{user}[$i], @@ -666,71 +719,78 @@ sub load_stats ### per_minute_info ### - foreach my $day (keys %_per_minute_info) { - foreach my $hour (keys %{ $_per_minute_info{$day} }) { - foreach my $min (keys %{ $_per_minute_info{$day}{$hour} }) { - $per_minute_info{$day}{$hour}{$min}{connection}{count} += - ($_per_minute_info{$day}{$hour}{$min}{connection}{count} || 0); - $per_minute_info{$day}{$hour}{$min}{session}{count} += - ($_per_minute_info{$day}{$hour}{$min}{session}{count} || 0); - $per_minute_info{$day}{$hour}{$min}{query}{count} += - ($_per_minute_info{$day}{$hour}{$min}{query}{count} || 0); - $per_minute_info{$day}{$hour}{$min}{query}{duration} += $_per_minute_info{$day}{$hour}{$min}{query}{duration}; - $per_minute_info{$day}{$hour}{$min}{query}{min} = $_per_minute_info{$day}{$hour}{$min}{query}{min} if (!exists $per_minute_info{$day}{$hour}{$min}{query}{min} || ($per_minute_info{$day}{$hour}{$min}{query}{min} > $_per_minute_info{$day}{$hour}{$min}{query}{min})); - $per_minute_info{$day}{$hour}{$min}{query}{max} = $_per_minute_info{$day}{$hour}{$min}{query}{max} if (!exists $per_minute_info{$day}{$hour}{$min}{query}{max} || ($per_minute_info{$day}{$hour}{$min}{query}{max} < $_per_minute_info{$day}{$hour}{$min}{query}{max})); - - foreach my $sec (keys %{ $_per_minute_info{$day}{$hour}{$min}{connection}{second} }) { - $per_minute_info{$day}{$hour}{$min}{connection}{second}{$sec} += - ($_per_minute_info{$day}{$hour}{$min}{connection}{second}{$sec} || 0); - } - foreach my $sec (keys %{ $_per_minute_info{$day}{$hour}{$min}{session}{second} }) { - $per_minute_info{$day}{$hour}{$min}{session}{second}{$sec} += - ($_per_minute_info{$day}{$hour}{$min}{session}{second}{$sec} || 0); - } - foreach my $sec (keys %{ $_per_minute_info{$day}{$hour}{$min}{query}{second} }) { - $per_minute_info{$day}{$hour}{$min}{query}{second}{$sec} += - ($_per_minute_info{$day}{$hour}{$min}{query}{second}{$sec} || 0); - } - foreach my $action (@SQL_ACTION) { - next if (!exists $_per_minute_info{$day}{$hour}{$min}{$action}); - $per_minute_info{$day}{$hour}{$min}{$action}{count} += ($_per_minute_info{$day}{$hour}{$min}{$action}{count} || 0); - $per_minute_info{$day}{$hour}{$min}{$action}{duration} += ($_per_minute_info{$day}{$hour}{$min}{$action}{duration} || 0); - foreach my $sec (keys %{ $_per_minute_info{$day}{$hour}{$min}{$action}{second} }) { - $per_minute_info{$day}{$hour}{$min}{$action}{second}{$sec} += - ($_per_minute_info{$day}{$hour}{$min}{$action}{second}{$sec} || 0); + foreach my $curdb (keys %_per_minute_info) { + foreach my $day (keys %{$_per_minute_info{$curdb}}) { + foreach my $hour (keys %{ $_per_minute_info{$curdb}{$day} }) { + foreach my $min (keys %{ $_per_minute_info{$curdb}{$day}{$hour} }) { + $per_minute_info{$curdb}{$day}{$hour}{$min}{connection}{count} += + ($_per_minute_info{$curdb}{$day}{$hour}{$min}{connection}{count} || 0); + $per_minute_info{$curdb}{$day}{$hour}{$min}{session}{count} += + ($_per_minute_info{$curdb}{$day}{$hour}{$min}{session}{count} || 0); + $per_minute_info{$curdb}{$day}{$hour}{$min}{query}{count} += + ($_per_minute_info{$curdb}{$day}{$hour}{$min}{query}{count} || 0); + $per_minute_info{$curdb}{$day}{$hour}{$min}{query}{duration} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{query}{duration}; + $per_minute_info{$curdb}{$day}{$hour}{$min}{query}{min} = $_per_minute_info{$curdb}{$day}{$hour}{$min}{query}{min} if (!exists $per_minute_info{$curdb}{$day}{$hour}{$min}{query}{min} || ($per_minute_info{$curdb}{$day}{$hour}{$min}{query}{min} > $_per_minute_info{$curdb}{$day}{$hour}{$min}{query}{min})); + $per_minute_info{$curdb}{$day}{$hour}{$min}{query}{max} = $_per_minute_info{$curdb}{$day}{$hour}{$min}{query}{max} if (!exists $per_minute_info{$curdb}{$day}{$hour}{$min}{query}{max} || ($per_minute_info{$curdb}{$day}{$hour}{$min}{query}{max} < $_per_minute_info{$curdb}{$day}{$hour}{$min}{query}{max})); + + foreach my $sec (keys %{ $_per_minute_info{$curdb}{$day}{$hour}{$min}{connection}{second} }) { + $per_minute_info{$curdb}{$day}{$hour}{$min}{connection}{second}{$sec} += + ($_per_minute_info{$curdb}{$day}{$hour}{$min}{connection}{second}{$sec} || 0); } - } - foreach my $k ('prepare', 'bind','execute') { - if (exists $_per_minute_info{$day}{$hour}{$min}{$k}) { - $per_minute_info{$day}{$hour}{$min}{$k} += $_per_minute_info{$day}{$hour}{$min}{$k}; + foreach my $sec (keys %{ $_per_minute_info{$curdb}{$day}{$hour}{$min}{session}{second} }) { + $per_minute_info{$curdb}{$day}{$hour}{$min}{session}{second}{$sec} += + ($_per_minute_info{$curdb}{$day}{$hour}{$min}{session}{second}{$sec} || 0); + } + foreach my $sec (keys %{ $_per_minute_info{$curdb}{$day}{$hour}{$min}{query}{second} }) { + $per_minute_info{$curdb}{$day}{$hour}{$min}{query}{second}{$sec} += + ($_per_minute_info{$curdb}{$day}{$hour}{$min}{query}{second}{$sec} || 0); + } + foreach my $action (@SQL_ACTION) { + next if (!exists $_per_minute_info{$curdb}{$day}{$hour}{$min}{$action}); + $per_minute_info{$curdb}{$day}{$hour}{$min}{$action}{count} += ($_per_minute_info{$curdb}{$day}{$hour}{$min}{$action}{count} || 0); + $per_minute_info{$curdb}{$day}{$hour}{$min}{$action}{duration} += ($_per_minute_info{$curdb}{$day}{$hour}{$min}{$action}{duration} || 0); + foreach my $sec (keys %{ $_per_minute_info{$curdb}{$day}{$hour}{$min}{$action}{second} }) { + $per_minute_info{$curdb}{$day}{$hour}{$min}{$action}{second}{$sec} += + ($_per_minute_info{$curdb}{$day}{$hour}{$min}{$action}{second}{$sec} || 0); + } + } + foreach my $k ('prepare', 'bind','execute') { + if (exists $_per_minute_info{$curdb}{$day}{$hour}{$min}{$k}) { + $per_minute_info{$curdb}{$day}{$hour}{$min}{$k} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{$k}; + } + } + foreach my $log (keys %{ $_per_minute_info{$curdb}{$day}{$hour}{$min}{log_level} }) { + $per_minute_info{$curdb}{$day}{$hour}{$min}{log_level}{$log} += + ($_per_minute_info{$curdb}{$day}{$hour}{$min}{log_level}{$log} || 0); } - } - foreach my $log (keys %{ $_per_minute_info{$day}{$hour}{$min}{log_level} }) { - $per_minute_info{$day}{$hour}{$min}{log_level}{$log} += - ($_per_minute_info{$day}{$hour}{$min}{log_level}{$log} || 0); - } - $per_minute_info{$day}{$hour}{$min}{cancelled}{count} += $_per_minute_info{$day}{$hour}{$min}{cancelled}{count} - if defined $_per_minute_info{$day}{$hour}{$min}{cancelled}{count}; - $per_minute_info{$day}{$hour}{$min}{tempfile}{count} += $_per_minute_info{$day}{$hour}{$min}{tempfile}{count} - if defined $_per_minute_info{$day}{$hour}{$min}{tempfile}{count}; - $per_minute_info{$day}{$hour}{$min}{tempfile}{size} += $_per_minute_info{$day}{$hour}{$min}{tempfile}{size} - if defined $_per_minute_info{$day}{$hour}{$min}{tempfile}{size}; - - $per_minute_info{$day}{$hour}{$min}{checkpoint}{file_removed} += $_per_minute_info{$day}{$hour}{$min}{checkpoint}{file_removed}; - $per_minute_info{$day}{$hour}{$min}{checkpoint}{sync} += $_per_minute_info{$day}{$hour}{$min}{checkpoint}{sync}; - $per_minute_info{$day}{$hour}{$min}{checkpoint}{wbuffer} += $_per_minute_info{$day}{$hour}{$min}{checkpoint}{wbuffer}; - $per_minute_info{$day}{$hour}{$min}{checkpoint}{file_recycled} += $_per_minute_info{$day}{$hour}{$min}{checkpoint}{file_recycled}; - $per_minute_info{$day}{$hour}{$min}{checkpoint}{total} += $_per_minute_info{$day}{$hour}{$min}{checkpoint}{total}; - $per_minute_info{$day}{$hour}{$min}{checkpoint}{file_added} += $_per_minute_info{$day}{$hour}{$min}{checkpoint}{file_added}; - $per_minute_info{$day}{$hour}{$min}{checkpoint}{write} += $_per_minute_info{$day}{$hour}{$min}{checkpoint}{write}; - $per_minute_info{$day}{$hour}{$min}{autovacuum}{count} += $_per_minute_info{$day}{$hour}{$min}{autovacuum}{count}; - $per_minute_info{$day}{$hour}{$min}{autoanalyze}{count} += $_per_minute_info{$day}{$hour}{$min}{autoanalyze}{count}; - - $per_minute_info{$day}{$hour}{$min}{checkpoint}{sync_files} += $_per_minute_info{$day}{$hour}{$min}{checkpoint}{sync_files}; - $per_minute_info{$day}{$hour}{$min}{checkpoint}{sync_avg} += $_per_minute_info{$day}{$hour}{$min}{checkpoint}{sync_avg}; - $per_minute_info{$day}{$hour}{$min}{checkpoint}{sync_longest} = $_per_minute_info{$day}{$hour}{$min}{checkpoint}{sync_longest} - if ($_per_minute_info{$day}{$hour}{$min}{checkpoint}{sync_longest} > $per_minute_info{$day}{$hour}{$min}{checkpoint}{sync_longest}); + $per_minute_info{$curdb}{$day}{$hour}{$min}{cancelled}{count} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{cancelled}{count} + if defined $_per_minute_info{$curdb}{$day}{$hour}{$min}{cancelled}{count}; + $per_minute_info{$curdb}{$day}{$hour}{$min}{'tempfile'}{count} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{'tempfile'}{count} + if defined $_per_minute_info{$curdb}{$day}{$hour}{$min}{'tempfile'}{count}; + $per_minute_info{$curdb}{$day}{$hour}{$min}{'tempfile'}{size} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{'tempfile'}{size} + if defined $_per_minute_info{$curdb}{$day}{$hour}{$min}{'tempfile'}{size}; + + $per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{file_removed} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{file_removed}; + $per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync}; + $per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{wbuffer} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{wbuffer}; + $per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{file_recycled} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{file_recycled}; + $per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{total} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{total}; + $per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{file_added} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{file_added}; + $per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{write} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{write}; + $per_minute_info{$curdb}{$day}{$hour}{$min}{autovacuum}{count} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{autovacuum}{count}; + $per_minute_info{$curdb}{$day}{$hour}{$min}{autoanalyze}{count} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{autoanalyze}{count}; + + $per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync_files} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync_files}; + $per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync_avg} += $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync_avg}; + $per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync_longest} = $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync_longest} + if ($_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync_longest} > $per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{sync_longest}); + $per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{distance} = $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{distance}; + $per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{distance_count} = $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{distance_count}; + $per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{estimate} = $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{estimate}; + $per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{warnning} = $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{warning}; + $per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{warning_seconds} = $_per_minute_info{$curdb}{$day}{$hour}{$min}{checkpoint}{warning_seconds}; + } } } } @@ -744,13 +804,13 @@ sub load_stats ($_pgb_per_minute_info{$day}{$hour}{$min}{connection}{count} || 0); $pgb_per_minute_info{$day}{$hour}{$min}{session}{count} += ($_pgb_per_minute_info{$day}{$hour}{$min}{session}{count} || 0); - $pgb_per_minute_info{$day}{$hour}{$min}{t_req} += + $pgb_per_minute_info{$day}{$hour}{$min}{t_req} += ($_pgb_per_minute_info{$day}{$hour}{$min}{t_req} || 0); - $pgb_per_minute_info{$day}{$hour}{$min}{t_inbytes} += + $pgb_per_minute_info{$day}{$hour}{$min}{t_inbytes} += ($_pgb_per_minute_info{$day}{$hour}{$min}{t_inbytes} || 0); - $pgb_per_minute_info{$day}{$hour}{$min}{t_outbytes} += + $pgb_per_minute_info{$day}{$hour}{$min}{t_outbytes} += ($_pgb_per_minute_info{$day}{$hour}{$min}{t_outbytes} || 0); - $pgb_per_minute_info{$day}{$hour}{$min}{t_avgduration} += + $pgb_per_minute_info{$day}{$hour}{$min}{t_avgduration} += ($_pgb_per_minute_info{$day}{$hour}{$min}{t_avgduration} || 0); } } @@ -758,23 +818,26 @@ sub load_stats ### lock_info ### - foreach my $lock (keys %_lock_info) { - $lock_info{$lock}{count} += $_lock_info{$lock}{count}; + foreach my $curdb (keys %_lock_info) + { + foreach my $lock (keys %{$_lock_info{$curdb}}) { + $lock_info{$curdb}{$lock}{count} += $_lock_info{$curdb}{$lock}{count}; - foreach my $day (keys %{ $_lock_info{chronos} }) { - foreach my $hour (keys %{ $_lock_info{chronos}{$day} }) { - $lock_info{chronos}{$day}{$hour}{count} += $_lock_info{chronos}{$day}{$hour}{count}; - $lock_info{chronos}{$day}{$hour}{duration} += $_lock_info{chronos}{$day}{$hour}{duration}; + foreach my $day (keys %{ $_lock_info{$curdb}{chronos} }) { + foreach my $hour (keys %{ $_lock_info{$curdb}{chronos}{$day} }) { + $lock_info{$curdb}{chronos}{$day}{$hour}{count} += $_lock_info{$curdb}{chronos}{$day}{$hour}{count}; + $lock_info{$curdb}{chronos}{$day}{$hour}{duration} += $_lock_info{$curdb}{chronos}{$day}{$hour}{duration}; + } } - } - $lock_info{$lock}{duration} += $_lock_info{$lock}{duration}; + $lock_info{$curdb}{$lock}{duration} += $_lock_info{$curdb}{$lock}{duration}; - foreach my $type (keys %{$_lock_info{$lock}}) { - next if $type =~ /^(count|chronos|duration)$/; + foreach my $type (keys %{$_lock_info{$curdb}{$lock}}) { + next if $type =~ /^(count|chronos|duration)$/; - $lock_info{$lock}{$type}{count} += $_lock_info{$lock}{$type}{count}; - $lock_info{$lock}{$type}{duration} += $_lock_info{$lock}{$type}{duration}; + $lock_info{$curdb}{$lock}{$type}{count} += $_lock_info{$curdb}{$lock}{$type}{count}; + $lock_info{$curdb}{$lock}{$type}{duration} += $_lock_info{$curdb}{$lock}{$type}{duration}; + } } } @@ -784,128 +847,125 @@ sub load_stats ### normalyzed_info ### - foreach my $stmt (keys %_normalyzed_info) { - - if (!$_normalyzed_info{$stmt}{count}) { - $normalyzed_info{$stmt}{average} = 0; - } else { - $normalyzed_info{$stmt}{average} = $_normalyzed_info{$stmt}{duration} / $_normalyzed_info{$stmt}{count}; - $normalyzed_info{$stmt}{average} =~ s/(\.\d{3}).*/$1/; - } + foreach my $curdb (keys %_normalyzed_info) { + foreach my $stmt (keys %{$_normalyzed_info{$curdb}}) { - foreach my $dt (keys %{$_normalyzed_info{$stmt}{samples}} ) { - foreach my $k (keys %{$_normalyzed_info{$stmt}{samples}{$dt}} ) { - $normalyzed_info{$stmt}{samples}{$dt}{$k} = $_normalyzed_info{$stmt}{samples}{$dt}{$k}; + foreach my $dt (keys %{$_normalyzed_info{$curdb}{$stmt}{samples}} ) { + foreach my $k (keys %{$_normalyzed_info{$curdb}{$stmt}{samples}{$dt}} ) { + $normalyzed_info{$curdb}{$stmt}{samples}{$dt}{$k} = $_normalyzed_info{$curdb}{$stmt}{samples}{$dt}{$k}; + } } - } - # Keep only the top N samples - my $i = 1; - foreach my $k (sort {$b <=> $a} keys %{$normalyzed_info{$stmt}{samples}}) { - if ($i > $sample) { - delete $normalyzed_info{$stmt}{samples}{$k}; + # Keep only the top N samples + my $i = 1; + foreach my $k (sort {$b <=> $a} keys %{$normalyzed_info{$curdb}{$stmt}{samples}}) { + if ($i > $sample) { + delete $normalyzed_info{$curdb}{$stmt}{samples}{$k}; + } + $i++; } - $i++; - } - $normalyzed_info{$stmt}{count} += $_normalyzed_info{$stmt}{count}; + $normalyzed_info{$curdb}{$stmt}{count} += $_normalyzed_info{$curdb}{$stmt}{count}; - # Set min / max duration for this query - if (!exists $normalyzed_info{$stmt}{min} || ($normalyzed_info{$stmt}{min} > $_normalyzed_info{$stmt}{min})) { - $normalyzed_info{$stmt}{min} = $_normalyzed_info{$stmt}{min}; - } - if (!exists $normalyzed_info{$stmt}{max} || ($normalyzed_info{$stmt}{max} < $_normalyzed_info{$stmt}{max})) { - $normalyzed_info{$stmt}{max} = $_normalyzed_info{$stmt}{max}; - } + # Set min / max duration for this query + if (!exists $normalyzed_info{$curdb}{$stmt}{min} || ($normalyzed_info{$curdb}{$stmt}{min} > $_normalyzed_info{$curdb}{$stmt}{min})) { + $normalyzed_info{$curdb}{$stmt}{min} = $_normalyzed_info{$curdb}{$stmt}{min}; + } + if (!exists $normalyzed_info{$curdb}{$stmt}{max} || ($normalyzed_info{$curdb}{$stmt}{max} < $_normalyzed_info{$curdb}{$stmt}{max})) { + $normalyzed_info{$curdb}{$stmt}{max} = $_normalyzed_info{$curdb}{$stmt}{max}; + } - foreach my $day (keys %{$_normalyzed_info{$stmt}{chronos}} ) { - foreach my $hour (keys %{$_normalyzed_info{$stmt}{chronos}{$day}} ) { - $normalyzed_info{$stmt}{chronos}{$day}{$hour}{count} += - $_normalyzed_info{$stmt}{chronos}{$day}{$hour}{count}; - $normalyzed_info{$stmt}{chronos}{$day}{$hour}{duration} += - $_normalyzed_info{$stmt}{chronos}{$day}{$hour}{duration}; - foreach my $min (keys %{$_normalyzed_info{$stmt}{chronos}{$day}{$hour}{min}} ) { - $normalyzed_info{$stmt}{chronos}{$day}{$hour}{min}{$min} += - $_normalyzed_info{$stmt}{chronos}{$day}{$hour}{min}{$min}; - } - foreach my $min (keys %{$_normalyzed_info{$stmt}{chronos}{$day}{$hour}{min_duration}} ) { - $normalyzed_info{$stmt}{chronos}{$day}{$hour}{min_duration}{$min} += - $_normalyzed_info{$stmt}{chronos}{$day}{$hour}{min_duration}{$min}; + foreach my $day (keys %{$_normalyzed_info{$curdb}{$stmt}{chronos}} ) { + foreach my $hour (keys %{$_normalyzed_info{$curdb}{$stmt}{chronos}{$day}} ) { + $normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{count} += + $_normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{count}; + $normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{duration} += + $_normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{duration}; + foreach my $min (keys %{$_normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min}} ) { + $normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min}{$min} += + $_normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min}{$min}; + } + foreach my $min (keys %{$_normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min_duration}} ) { + $normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min_duration}{$min} += + $_normalyzed_info{$curdb}{$stmt}{chronos}{$day}{$hour}{min_duration}{$min}; + } } } - } - $normalyzed_info{$stmt}{duration} += $_normalyzed_info{$stmt}{duration}; + $normalyzed_info{$curdb}{$stmt}{duration} += $_normalyzed_info{$curdb}{$stmt}{duration}; - if (exists $_normalyzed_info{$stmt}{locks}) { - $normalyzed_info{$stmt}{locks}{count} += $_normalyzed_info{$stmt}{locks}{count}; - $normalyzed_info{$stmt}{locks}{wait} += $_normalyzed_info{$stmt}{locks}{wait}; - if (!exists $normalyzed_info{$stmt}{locks}{minwait} || ($normalyzed_info{$stmt}{locks}{minwait} > $_normalyzed_info{$stmt}{locks}{minwait})) { - $normalyzed_info{$stmt}{locks}{minwait} = $_normalyzed_info{$stmt}{locks}{minwait}; - } - if (!exists $normalyzed_info{$stmt}{locks}{maxwait} || ($normalyzed_info{$stmt}{locks}{maxwait} < $_normalyzed_info{$stmt}{locks}{maxwait})) { - $normalyzed_info{$stmt}{locks}{maxwait} = $_normalyzed_info{$stmt}{locks}{maxwait}; + if (exists $_normalyzed_info{$curdb}{$stmt}{locks}) { + $normalyzed_info{$curdb}{$stmt}{locks}{count} += $_normalyzed_info{$curdb}{$stmt}{locks}{count}; + $normalyzed_info{$curdb}{$stmt}{locks}{wait} += $_normalyzed_info{$curdb}{$stmt}{locks}{wait}; + if (!exists $normalyzed_info{$curdb}{$stmt}{locks}{minwait} || ($normalyzed_info{$curdb}{$stmt}{locks}{minwait} > $_normalyzed_info{$stmt}{locks}{minwait})) { + $normalyzed_info{$curdb}{$stmt}{locks}{minwait} = $_normalyzed_info{$curdb}{$stmt}{locks}{minwait}; + } + if (!exists $normalyzed_info{$curdb}{$stmt}{locks}{maxwait} || ($normalyzed_info{$curdb}{$stmt}{locks}{maxwait} < $_normalyzed_info{$curdb}{$stmt}{locks}{maxwait})) { + $normalyzed_info{$curdb}{$stmt}{locks}{maxwait} = $_normalyzed_info{$curdb}{$stmt}{locks}{maxwait}; + } } - } - if (exists $_normalyzed_info{$stmt}{tempfiles}) { - $normalyzed_info{$stmt}{tempfiles}{count} += $_normalyzed_info{$stmt}{tempfiles}{count}; - $normalyzed_info{$stmt}{tempfiles}{size} += $_normalyzed_info{$stmt}{tempfiles}{size}; - if (!exists $normalyzed_info{$stmt}{tempfiles}{minsize} || ($normalyzed_info{$stmt}{tempfiles}{minsize} > $_normalyzed_info{$stmt}{tempfiles}{minsize})) { - $normalyzed_info{$stmt}{tempfiles}{minsize} = $_normalyzed_info{$stmt}{tempfiles}{minsize}; - } - if (!exists $normalyzed_info{$stmt}{tempfiles}{maxsize} || ($normalyzed_info{$stmt}{tempfiles}{maxsize} < $_normalyzed_info{$stmt}{tempfiles}{maxsize})) { - $normalyzed_info{$stmt}{tempfiles}{maxsize} = $_normalyzed_info{$stmt}{tempfiles}{maxsize}; + if (exists $_normalyzed_info{$curdb}{$stmt}{tempfiles}) { + $normalyzed_info{$curdb}{$stmt}{tempfiles}{count} += $_normalyzed_info{$curdb}{$stmt}{tempfiles}{count}; + $normalyzed_info{$curdb}{$stmt}{tempfiles}{size} += $_normalyzed_info{$curdb}{$stmt}{tempfiles}{size}; + if (!exists $normalyzed_info{$curdb}{$stmt}{tempfiles}{minsize} || ($normalyzed_info{$curdb}{$stmt}{tempfiles}{minsize} > $_normalyzed_info{$curdb}{$stmt}{tempfiles}{minsize})) { + $normalyzed_info{$curdb}{$stmt}{tempfiles}{minsize} = $_normalyzed_info{$curdb}{$stmt}{tempfiles}{minsize}; + } + if (!exists $normalyzed_info{$curdb}{$stmt}{tempfiles}{maxsize} || ($normalyzed_info{$curdb}{$stmt}{tempfiles}{maxsize} < $_normalyzed_info{$curdb}{$stmt}{tempfiles}{maxsize})) { + $normalyzed_info{$curdb}{$stmt}{tempfiles}{maxsize} = $_normalyzed_info{$curdb}{$stmt}{tempfiles}{maxsize}; + } } - } - if (exists $_normalyzed_info{$stmt}{cancelled}) { - $normalyzed_info{$stmt}{cancelled}{count} += $_normalyzed_info{$stmt}{cancelled}{count}; - } + if (exists $_normalyzed_info{$curdb}{$stmt}{cancelled}) { + $normalyzed_info{$curdb}{$stmt}{cancelled}{count} += $_normalyzed_info{$curdb}{$stmt}{cancelled}{count}; + } - foreach my $u (keys %{$_normalyzed_info{$stmt}{users}} ) { - foreach my $k (keys %{$_normalyzed_info{$stmt}{users}{$u}} ) { - $normalyzed_info{$stmt}{users}{$u}{$k} += $_normalyzed_info{$stmt}{users}{$u}{$k}; + foreach my $u (keys %{$_normalyzed_info{$curdb}{$stmt}{users}} ) { + foreach my $k (keys %{$_normalyzed_info{$curdb}{$stmt}{users}{$u}} ) { + $normalyzed_info{$curdb}{$stmt}{users}{$u}{$k} += $_normalyzed_info{$curdb}{$stmt}{users}{$u}{$k}; + } } - } - foreach my $u (keys %{$_normalyzed_info{$stmt}{apps}} ) { - foreach my $k (keys %{$_normalyzed_info{$stmt}{apps}{$u}} ) { - $normalyzed_info{$stmt}{apps}{$u}{$k} += $_normalyzed_info{$stmt}{apps}{$u}{$k}; + foreach my $u (keys %{$_normalyzed_info{$curdb}{$stmt}{apps}} ) { + foreach my $k (keys %{$_normalyzed_info{$curdb}{$stmt}{apps}{$u}} ) { + $normalyzed_info{$curdb}{$stmt}{apps}{$u}{$k} += $_normalyzed_info{$curdb}{$stmt}{apps}{$u}{$k}; + } } } } ### session_info ### - foreach my $db (keys %{ $_session_info{database}}) { - $session_info{database}{$db}{count} += $_session_info{database}{$db}{count}; - $session_info{database}{$db}{duration} += $_session_info{database}{$db}{duration}; - } + foreach my $curdb (keys %_session_info) { + foreach my $db (keys %{ $_session_info{$curdb}{database}}) { + $session_info{$curdb}{database}{$db}{count} += $_session_info{$curdb}{database}{$db}{count}; + $session_info{$curdb}{database}{$db}{duration} += $_session_info{$curdb}{database}{$db}{duration}; + } - $session_info{count} += $_session_info{count}; + $session_info{$curdb}{count} += $_session_info{$curdb}{count}; - foreach my $day (keys %{ $_session_info{chronos}}) { - foreach my $hour (keys %{ $_session_info{chronos}{$day}}) { - $session_info{chronos}{$day}{$hour}{count} += $_session_info{chronos}{$day}{$hour}{count}; - $session_info{chronos}{$day}{$hour}{duration} += $_session_info{chronos}{$day}{$hour}{duration}; + foreach my $day (keys %{ $_session_info{$curdb}{chronos}}) { + foreach my $hour (keys %{ $_session_info{$curdb}{chronos}{$day}}) { + $session_info{$curdb}{chronos}{$day}{$hour}{count} += $_session_info{$curdb}{chronos}{$day}{$hour}{count}; + $session_info{$curdb}{chronos}{$day}{$hour}{duration} += $_session_info{$curdb}{chronos}{$day}{$hour}{duration}; + } } - } - foreach my $user (keys %{ $_session_info{user}}) { - $session_info{user}{$user}{count} += $_session_info{user}{$user}{count}; - $session_info{user}{$user}{duration} += $_session_info{user}{$user}{duration}; - } + foreach my $user (keys %{ $_session_info{$curdb}{user}}) { + $session_info{$curdb}{user}{$user}{count} += $_session_info{$curdb}{user}{$user}{count}; + $session_info{$curdb}{user}{$user}{duration} += $_session_info{$curdb}{user}{$user}{duration}; + } - $session_info{duration} += $_session_info{duration}; + $session_info{$curdb}{duration} += $_session_info{$curdb}{duration}; - foreach my $host (keys %{ $_session_info{host}}) { - $session_info{host}{$host}{count} += $_session_info{host}{$host}{count}; - $session_info{host}{$host}{duration} += $_session_info{host}{$host}{duration}; - } + foreach my $host (keys %{ $_session_info{$curdb}{host}}) { + $session_info{$curdb}{host}{$host}{count} += $_session_info{$curdb}{host}{$host}{count}; + $session_info{$curdb}{host}{$host}{duration} += $_session_info{$curdb}{host}{$host}{duration}; + } - foreach my $app (keys %{ $_session_info{app}}) { - $session_info{app}{$app}{count} += $_session_info{app}{$app}{count}; - $session_info{app}{$app}{duration} += $_session_info{app}{$app}{duration}; + foreach my $app (keys %{ $_session_info{$curdb}{app}}) { + $session_info{$curdb}{app}{$app}{count} += $_session_info{$curdb}{app}{$app}{count}; + $session_info{$curdb}{app}{$app}{duration} += $_session_info{$curdb}{app}{$app}{duration}; + } } ### pgbouncer session_info ### @@ -936,35 +996,51 @@ sub load_stats $pgb_session_info{host}{$host}{duration} += $_pgb_session_info{host}{$host}{duration}; } + ### tempfile_info ### - $tempfile_info{count} += $_tempfile_info{count} - if defined $_tempfile_info{count}; - $tempfile_info{size} += $_tempfile_info{size} - if defined $_tempfile_info{size}; - $tempfile_info{maxsize} = $_tempfile_info{maxsize} - if defined $_tempfile_info{maxsize} and ( not defined $tempfile_info{maxsize} - or $tempfile_info{maxsize} < $_tempfile_info{maxsize} ); + foreach my $curdb (keys %_tempfile_info) + { + $tempfile_info{$curdb}{count} += $_tempfile_info{$curdb}{count} + if defined $_tempfile_info{$curdb}{count}; + $tempfile_info{$curdb}{size} += $_tempfile_info{$curdb}{size} + if defined $_tempfile_info{$curdb}{size}; + $tempfile_info{$curdb}{maxsize} = $_tempfile_info{$curdb}{maxsize} + if defined $_tempfile_info{$curdb}{maxsize} and ( not defined $tempfile_info{$curdb}{maxsize} + or $tempfile_info{$curdb}{maxsize} < $_tempfile_info{$curdb}{maxsize} ); + } ### top_slowest ### - my @tmp_top_slowest = sort {$b->[0] <=> $a->[0]} (@top_slowest, @_top_slowest); - @top_slowest = (); - for (my $i = 0; $i <= $#tmp_top_slowest; $i++) { - push(@top_slowest, $tmp_top_slowest[$i]); + foreach my $curdb (keys %_top_slowest) + { + my @tmp_top_slowest = sort {$b->[0] <=> $a->[0]} (@{$top_slowest{$curdb}}, @{$_top_slowest{$curdb}}); + @{$top_slowest{$curdb}} = (); + for (my $i = 0; $i <= $#tmp_top_slowest; $i++) { + push(@{$top_slowest{$curdb}}, $tmp_top_slowest[$i]); + last if ($i == $end_top); + } } ### top_locked ### - my @tmp_top_locked_info = sort {$b->[0] <=> $a->[0]} (@top_locked_info, @_top_locked_info); - @top_locked_info = (); - for (my $i = 0; $i <= $#tmp_top_locked_info; $i++) { - push(@top_locked_info, $tmp_top_locked_info[$i]); + foreach my $curdb (keys %_top_locked_info) + { + my @tmp_top_locked_info = sort {$b->[0] <=> $a->[0]} (@{$top_locked_info{$curdb}}, @{$_top_locked_info{$curdb}}); + @{$top_locked_info{$curdb}} = (); + for (my $i = 0; $i <= $#tmp_top_locked_info; $i++) { + push(@{$top_locked_info{$curdb}}, $tmp_top_locked_info[$i]); + last if ($i == $end_top); + } } ### top_tempfile ### - my @tmp_top_tempfile_info = sort {$b->[0] <=> $a->[0]} (@top_tempfile_info, @_top_tempfile_info); - @top_tempfile_info = (); - for (my $i = 0; $i <= $#tmp_top_tempfile_info; $i++) { - push(@top_tempfile_info, $tmp_top_tempfile_info[$i]); + foreach my $curdb (keys %_top_tempfile_info) + { + my @tmp_top_tempfile_info = sort {$b->[0] <=> $a->[0]} (@{$top_tempfile_info{$curdb}}, @{$_top_tempfile_info{$curdb}}); + @{$top_tempfile_info{$curdb}} = (); + for (my $i = 0; $i <= $#tmp_top_tempfile_info; $i++) { + push(@{$top_tempfile_info{$curdb}}, $tmp_top_tempfile_info[$i]); + last if ($i == $end_top); + } } ### checkpoint_info ### @@ -975,50 +1051,62 @@ sub load_stats $checkpoint_info{total} += $_checkpoint_info{total}; $checkpoint_info{file_added} += $_checkpoint_info{file_added}; $checkpoint_info{write} += $_checkpoint_info{write}; + $checkpoint_info{distance} += $_checkpoint_info{distance}; + $checkpoint_info{estimate} += $_checkpoint_info{estimate}; + $checkpoint_info{warning} += $_checkpoint_info{warning}; + $checkpoint_info{warning_seconds} += $_checkpoint_info{warning_seconds}; #### Autovacuum info #### - $autovacuum_info{count} += $_autovacuum_info{count}; + foreach my $curdb (keys %_autovacuum_info) + { + $autovacuum_info{$curdb}{count} += $_autovacuum_info{$curdb}{count}; - foreach my $day (keys %{ $_autovacuum_info{chronos} }) { - foreach my $hour (keys %{ $_autovacuum_info{chronos}{$day} }) { - $autovacuum_info{chronos}{$day}{$hour}{count} += $_autovacuum_info{chronos}{$day}{$hour}{count}; + foreach my $day (keys %{ $_autovacuum_info{$curdb}{chronos} }) { + foreach my $hour (keys %{ $_autovacuum_info{$curdb}{chronos}{$day} }) { + $autovacuum_info{$curdb}{chronos}{$day}{$hour}{count} += $_autovacuum_info{$curdb}{chronos}{$day}{$hour}{count}; + } + } + foreach my $table (keys %{ $_autovacuum_info{$curdb}{tables} }) { + $autovacuum_info{$curdb}{tables}{$table}{vacuums} += $_autovacuum_info{$curdb}{tables}{$table}{vacuums}; + $autovacuum_info{$curdb}{tables}{$table}{idxscans} += $_autovacuum_info{$curdb}{tables}{$table}{idxscans}; + $autovacuum_info{$curdb}{tables}{$table}{tuples}{removed} += $_autovacuum_info{$curdb}{tables}{$table}{tuples}{removed}; + $autovacuum_info{$curdb}{tables}{$table}{pages}{removed} += $_autovacuum_info{$curdb}{tables}{$table}{pages}{removed}; + } + if ($_autovacuum_info{$curdb}{peak}{system_usage}{elapsed} > $autovacuum_info{$curdb}{peak}{system_usage}{elapsed}) { + $autovacuum_info{$curdb}{peak}{system_usage}{elapsed} = $_autovacuum_info{$curdb}{peak}{system_usage}{elapsed}; + $autovacuum_info{$curdb}{peak}{system_usage}{table} = $_autovacuum_info{$curdb}{peak}{system_usage}{table}; + $autovacuum_info{$curdb}{peak}{system_usage}{date} = $_autovacuum_info{$curdb}{peak}{system_usage}{date}; } } - foreach my $table (keys %{ $_autovacuum_info{tables} }) { - $autovacuum_info{tables}{$table}{vacuums} += $_autovacuum_info{tables}{$table}{vacuums}; - $autovacuum_info{tables}{$table}{idxscans} += $_autovacuum_info{tables}{$table}{idxscans}; - $autovacuum_info{tables}{$table}{tuples}{removed} += $_autovacuum_info{tables}{$table}{tuples}{removed}; - $autovacuum_info{tables}{$table}{pages}{removed} += $_autovacuum_info{tables}{$table}{pages}{removed}; - } - if ($_autovacuum_info{peak}{system_usage}{elapsed} > $autovacuum_info{peak}{system_usage}{elapsed}) { - $autovacuum_info{peak}{system_usage}{elapsed} = $_autovacuum_info{peak}{system_usage}{elapsed}; - $autovacuum_info{peak}{system_usage}{table} = $_autovacuum_info{peak}{system_usage}{table}; - $autovacuum_info{peak}{system_usage}{date} = $_autovacuum_info{peak}{system_usage}{date}; - } + #### Autoanalyze info #### - $autoanalyze_info{count} += $_autoanalyze_info{count}; + foreach my $curdb (keys %_autoanalyze_info) + { + $autoanalyze_info{$curdb}{count} += $_autoanalyze_info{$curdb}{count}; - foreach my $day (keys %{ $_autoanalyze_info{chronos} }) { - foreach my $hour (keys %{ $_autoanalyze_info{chronos}{$day} }) { - $autoanalyze_info{chronos}{$day}{$hour}{count} += $_autoanalyze_info{chronos}{$day}{$hour}{count}; + foreach my $day (keys %{ $_autoanalyze_info{$curdb}{chronos} }) { + foreach my $hour (keys %{ $_autoanalyze_info{$curdb}{chronos}{$day} }) { + $autoanalyze_info{$curdb}{chronos}{$day}{$hour}{count} += $_autoanalyze_info{$curdb}{chronos}{$day}{$hour}{count}; + } + } + foreach my $table (keys %{ $_autoanalyze_info{$curdb}{tables} }) { + $autoanalyze_info{$curdb}{tables}{$table}{analyzes} += $_autoanalyze_info{$curdb}{tables}{$table}{analyzes}; + } + if ($_autoanalyze_info{$curdb}{peak}{system_usage}{elapsed} > $autoanalyze_info{$curdb}{peak}{system_usage}{elapsed}) { + $autoanalyze_info{$curdb}{peak}{system_usage}{elapsed} = $_autoanalyze_info{$curdb}{peak}{system_usage}{elapsed}; + $autoanalyze_info{$curdb}{peak}{system_usage}{table} = $_autoanalyze_info{$curdb}{peak}{system_usage}{table}; + $autoanalyze_info{$curdb}{peak}{system_usage}{date} = $_autoanalyze_info{$curdb}{peak}{system_usage}{date}; } - } - foreach my $table (keys %{ $_autoanalyze_info{tables} }) { - $autoanalyze_info{tables}{$table}{analyzes} += $_autoanalyze_info{tables}{$table}{analyzes}; - } - if ($_autoanalyze_info{peak}{system_usage}{elapsed} > $autoanalyze_info{peak}{system_usage}{elapsed}) { - $autoanalyze_info{peak}{system_usage}{elapsed} = $_autoanalyze_info{peak}{system_usage}{elapsed}; - $autoanalyze_info{peak}{system_usage}{table} = $_autoanalyze_info{peak}{system_usage}{table}; - $autoanalyze_info{peak}{system_usage}{date} = $_autoanalyze_info{peak}{system_usage}{date}; } use strict; - + return; } + # Do minimal query formatting. # Add carriage return to be more human readable sub fmtquery @@ -1043,33 +1131,35 @@ sub fmtquery # Dump top slowest queries as EXPLAIN statement. sub dump_slowest_queries { + my $curdb = shift; + # Global information my $curdate = localtime(time); my $logfile_str = join(',', @log_files); - for (my $i = 0 ; $i <= $#top_slowest ; $i++) { + for (my $i = 0 ; $i <= $#{$top_slowest{$curdb}} ; $i++) { # Do not process request that are slower than $max_duration - next if ( $max_duration && ($top_slowest[$i]->[0] > $max_duration) ); + next if ( $max_duration && ($top_slowest{$curdb}[$i]->[0] > $max_duration) ); my $head = qq{-- Generated on $curdate -- Log file: $logfile_str -- Log start from $overall_stat{'first_log_ts'} to $overall_stat{'last_log_ts'} -- }; - $head .= "-- duration: $top_slowest[$i]->[0]\n" if ($top_slowest[$i]->[0]); - $head .= "-- database: $top_slowest[$i]->[3]\n" if ($top_slowest[$i]->[3]); - $head .= "-- user: $top_slowest[$i]->[4]\n" if ($top_slowest[$i]->[4]); - $head .= "-- remote: $top_slowest[$i]->[5]\n" if ($top_slowest[$i]->[5]); - $head .= "-- app: $top_slowest[$i]->[6]\n" if ($top_slowest[$i]->[6]); - $head .= "--, bind query: yes\n" if ($top_slowest[$i]->[7]); + $head .= "-- duration: $top_slowest{$curdb}[$i]->[0]\n" if ($top_slowest{$curdb}[$i]->[0]); + $head .= "-- database: $top_slowest{$curdb}[$i]->[3]\n" if ($top_slowest{$curdb}[$i]->[3]); + $head .= "-- user: $top_slowest{$curdb}[$i]->[4]\n" if ($top_slowest{$curdb}[$i]->[4]); + $head .= "-- remote: $top_slowest{$curdb}[$i]->[5]\n" if ($top_slowest{$curdb}[$i]->[5]); + $head .= "-- app: $top_slowest{$curdb}[$i]->[6]\n" if ($top_slowest{$curdb}[$i]->[6]); + $head .= "--, bind query: yes\n" if ($top_slowest{$curdb}[$i]->[7]); $head =~ s/^, //; my $explain = "EXPLAIN\n"; if ($analyze) { $explain = "BEGIN;\nEXPLAIN (ANALYZE, VERBOSE, BUFFERS)\n"; } - $explain .= "$top_slowest[$i]->[2]\n"; + $explain .= "$top_slowest{$curdb}[$i]->[2]\n"; $explain .= "ROLLBACK;\n" if ($analyze); if ($file_per_query) { my $fhqr = new IO::File; @@ -1097,14 +1187,16 @@ sub dump_slowest_queries # Dump top time consuming queries as EXPLAIN statement. sub dump_times_consuming_queries { + my $curdb = shift; + # Global information my $curdate = localtime(time); my $logfile_str = join(',', @log_files); my $rank = 1; - foreach my $k (sort {$normalyzed_info{$b}{count} <=> $normalyzed_info{$a}{count}} keys %normalyzed_info) { - next if (!$normalyzed_info{$k}{count}); - foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$k}{samples}}) { + foreach my $k (sort {$normalyzed_info{$curdb}{$b}{count} <=> $normalyzed_info{$curdb}{$a}{count}} keys %{$normalyzed_info{$curdb}}) { + next if (!$normalyzed_info{$curdb}{$k}{count}); + foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$curdb}{$k}{samples}}) { # Do not process request that are slower than $max_duration next if ( $max_duration && ( $d > $max_duration) ); @@ -1114,18 +1206,18 @@ sub dump_times_consuming_queries -- }; $head .= "-- duration: $d\n" if ($d); - $head .= "-- database: $normalyzed_info{$k}{samples}{$d}{db}\n" if ($normalyzed_info{$k}{samples}{$d}{db}); - $head .= "-- user: $normalyzed_info{$k}{samples}{$d}{user}\n" if ($normalyzed_info{$k}{samples}{$d}{user}); - $head .= "-- remote: $normalyzed_info{$k}{samples}{$d}{remote}\n" if ($normalyzed_info{$k}{samples}{$d}{remote}); - $head .= "-- app: $normalyzed_info{$k}{samples}{$d}{app}\n" if ($normalyzed_info{$k}{samples}{$d}{app}); - $head .= "--, bind query: yes\n" if ($normalyzed_info{$k}{samples}{$d}{bind}); + $head .= "-- database: $normalyzed_info{$curdb}{$k}{samples}{$d}{db}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{db}); + $head .= "-- user: $normalyzed_info{$curdb}{$k}{samples}{$d}{user}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{user}); + $head .= "-- remote: $normalyzed_info{$curdb}{$k}{samples}{$d}{remote}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{remote}); + $head .= "-- app: $normalyzed_info{$curdb}{$k}{samples}{$d}{app}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{app}); + $head .= "--, bind query: yes\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{bind}); $head =~ s/^, //; my $explain = "EXPLAIN\n"; if ($analyze) { $explain = "BEGIN;\nEXPLAIN (ANALYZE, VERBOSE, BUFFERS)\n"; } - $explain .= "$normalyzed_info{$k}{samples}{$d}{query}\n"; + $explain .= "$normalyzed_info{$curdb}{$k}{samples}{$d}{query}\n"; $explain .= "ROLLBACK;\n" if ($analyze); if ($file_per_query) { my $fhqr = new IO::File; @@ -1158,14 +1250,16 @@ sub dump_times_consuming_queries # Dump top normalized slowest queries as EXPLAIN statement. sub dump_normalized_slowest_queries { + my $curdb = shift; + # Global information my $curdate = localtime(time); my $logfile_str = join(',', @log_files); my $rank = 1; - foreach my $k (sort {$normalyzed_info{$b}{average} <=> $normalyzed_info{$a}{average}} keys %normalyzed_info) { - next if (!$normalyzed_info{$k}{count}); - foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$k}{samples}}) { + foreach my $k (sort {$normalyzed_info{$curdb}{$b}{average} <=> $normalyzed_info{$curdb}{$a}{average}} keys %{$normalyzed_info{$curdb}}) { + next if (!$normalyzed_info{$curdb}{$k}{count}); + foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$curdb}{$k}{samples}}) { # Do not process request that are slower than $max_duration next if ( $max_duration && ( $d > $max_duration) ); @@ -1175,18 +1269,18 @@ sub dump_normalized_slowest_queries -- }; $head .= "-- duration: $d\n" if ($d); - $head .= "-- database: $normalyzed_info{$k}{samples}{$d}{db}\n" if ($normalyzed_info{$k}{samples}{$d}{db}); - $head .= "-- user: $normalyzed_info{$k}{samples}{$d}{user}\n" if ($normalyzed_info{$k}{samples}{$d}{user}); - $head .= "-- remote: $normalyzed_info{$k}{samples}{$d}{remote}\n" if ($normalyzed_info{$k}{samples}{$d}{remote}); - $head .= "-- app: $normalyzed_info{$k}{samples}{$d}{app}\n" if ($normalyzed_info{$k}{samples}{$d}{app}); - $head .= "--, bind query: yes\n" if ($normalyzed_info{$k}{samples}{$d}{bind}); + $head .= "-- database: $normalyzed_info{$curdb}{$k}{samples}{$d}{db}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{db}); + $head .= "-- user: $normalyzed_info{$curdb}{$k}{samples}{$d}{user}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{user}); + $head .= "-- remote: $normalyzed_info{$curdb}{$k}{samples}{$d}{remote}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{remote}); + $head .= "-- app: $normalyzed_info{$curdb}{$k}{samples}{$d}{app}\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{app}); + $head .= "--, bind query: yes\n" if ($normalyzed_info{$curdb}{$k}{samples}{$d}{bind}); $head =~ s/^, //; my $explain = "EXPLAIN\n"; if ($analyze) { $explain = "BEGIN;\nEXPLAIN (ANALYZE, VERBOSE, BUFFERS)\n"; } - $explain .= "$normalyzed_info{$k}{samples}{$d}{query}\n"; + $explain .= "$normalyzed_info{$curdb}{$k}{samples}{$d}{query}\n"; $explain .= "ROLLBACK;\n" if ($analyze); if ($file_per_query) { my $fhqr = new IO::File; @@ -1219,6 +1313,8 @@ sub dump_normalized_slowest_queries # Export time consuming queries as CSV sub csv_times_consuming_queries { + my $curdb = shift; + my $fhcsv = undef; my $csv = Text::CSV->new({ @@ -1229,23 +1325,23 @@ sub csv_times_consuming_queries $csv->print($fhcsv, ['Database','Rank','Total_Duration','Times_Executed','Min','Max','Avg','Query']); my $rank = 1; - foreach my $k (sort {$normalyzed_info{$b}{count} <=> $normalyzed_info{$a}{count}} keys %normalyzed_info) { - next if (!$normalyzed_info{$k}{count}); - foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$k}{samples}}) { + foreach my $k (sort {$normalyzed_info{$curdb}{$b}{count} <=> $normalyzed_info{$curdb}{$a}{count}} keys %{$normalyzed_info{$curdb}}) { + next if (!$normalyzed_info{$curdb}{$k}{count}); + foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$curdb}{$k}{samples}}) { # Do not process request that are slower than $max_duration next if ( $max_duration && ( $d > $max_duration) ); - $normalyzed_info{$k}{average} = $normalyzed_info{$k}{duration} / $normalyzed_info{$k}{count}; + $normalyzed_info{$curdb}{$k}{average} = $normalyzed_info{$curdb}{$k}{duration} / $normalyzed_info{$curdb}{$k}{count}; $csv->print ($fhcsv, [ - $normalyzed_info{$k}{samples}{$d}{db}, + $normalyzed_info{$curdb}{$k}{samples}{$d}{db}, $rank, $d, - $normalyzed_info{$k}{count}, - $normalyzed_info{$k}{min}, - $normalyzed_info{$k}{max}, - $normalyzed_info{$k}{average}, - $normalyzed_info{$k}{samples}{$d}{query} + $normalyzed_info{$curdb}{$k}{count}, + $normalyzed_info{$curdb}{$k}{min}, + $normalyzed_info{$curdb}{$k}{max}, + $normalyzed_info{$curdb}{$k}{average}, + $normalyzed_info{$curdb}{$k}{samples}{$d}{query} ]); # Report only the first sample last; @@ -1261,6 +1357,8 @@ sub csv_times_consuming_queries # Export normalized slowest queries as CSV sub csv_normalized_queries { + my $curdb = shift; + my $fhcsv = undef; my $csv = Text::CSV->new({ @@ -1271,21 +1369,21 @@ sub csv_normalized_queries $csv->print($fhcsv, ['Database','Rank','Total_Duration','Times_Executed','Min','Max','Avg','Query']); my $rank = 1; - foreach my $k (sort {$normalyzed_info{$b}{average} <=> $normalyzed_info{$a}{average}} keys %normalyzed_info) { - next if (!$normalyzed_info{$k}{count}); - foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$k}{samples}}) { + foreach my $k (sort {$normalyzed_info{$curdb}{$b}{average} <=> $normalyzed_info{$curdb}{$a}{average}} keys %{$normalyzed_info{$curdb}}) { + next if (!$normalyzed_info{$curdb}{$k}{count}); + foreach my $d (sort {$b <=> $a} keys %{$normalyzed_info{$curdb}{$k}{samples}}) { # Do not process request that are slower than $max_duration next if ( $max_duration && ( $d > $max_duration) ); $csv->print ($fhcsv, [ - $normalyzed_info{$k}{samples}{$d}{db}, + $normalyzed_info{$curdb}{$k}{samples}{$d}{db}, $rank, $d, - $normalyzed_info{$k}{count}, - $normalyzed_info{$k}{min}, - $normalyzed_info{$k}{max}, - $normalyzed_info{$k}{average}, - $normalyzed_info{$k}{samples}{$d}{query} + $normalyzed_info{$curdb}{$k}{count}, + $normalyzed_info{$curdb}{$k}{min}, + $normalyzed_info{$curdb}{$k}{max}, + $normalyzed_info{$curdb}{$k}{average}, + $normalyzed_info{$curdb}{$k}{samples}{$d}{query} ]); # Report only the first sample last; @@ -1301,6 +1399,8 @@ sub csv_normalized_queries # Export slowest queries as CSV sub csv_slowest_queries { + my $curdb = shift; + my $fhcsv = undef; my $csv = Text::CSV->new({ @@ -1311,16 +1411,16 @@ sub csv_slowest_queries $csv->print($fhcsv, ['Database','Rank','Duration','Query']); my $rank = 1; - for (my $i = 0 ; $i <= $#top_slowest ; $i++) { + for (my $i = 0 ; $i <= $#{$top_slowest{$curdb}} ; $i++) { # Do not process request that are slower than $max_duration - next if ( $max_duration && ($top_slowest[$i]->[0] > $max_duration) ); + next if ( $max_duration && ($top_slowest{$curdb}[$i]->[0] > $max_duration) ); $csv->print ($fhcsv, [ - $top_slowest[$i]->[3], + $top_slowest{$curdb}[$i]->[3], $rank, - $top_slowest[$i]->[0], - $top_slowest[$i]->[2] + $top_slowest{$curdb}[$i]->[0], + $top_slowest{$curdb}[$i]->[2] ]); last if ($rank > $top); $rank++;