my $progress = 0;
my $error_only = 0;
my @exclude_query = ();
+my $disable_error = 0;
my $NUMPROGRESS = 10000;
my @DIMENSIONS = (800,300);
"image-format=s"=> \$img_format,
"w|watch-mode!" => \$error_only,
"exclude-query=s" => \@exclude_query,
+ "disable-error!"=> \$disable_error,
);
if ($ver) {
$tmpfh->close();
unlink($outfile) if (-e $outfile);
+# -w and --disable-error can't go together
+if ($error_only && $disable_error) {
+ die "FATAL: please choose between no error report and reporting errors only.\n";
+}
+
# Testing regex syntaxe
if ($#exclude_query >= 0) {
foreach my $r (@exclude_query) {
--exclude-query regex : any query matching the given regex will be excluded
from the report. For example: "^(COPY|VACUUM|COMMIT)"
you can use this option multiple time.
+ --disable-error : do not generate error report.
Examples:
print $fh "Query peak: ", &comma_numbers($overall_stat{'query_peak'}{$_}), " queries/s at $_";
last;
}
- my $fmt_errors = &comma_numbers($overall_stat{'errors_number'}) || 0;
- my $fmt_unique_error = &comma_numbers(scalar keys %{$overall_stat{'unique_normalized_errors'}}) || 0;
- print $fh qq{
+ if (!$disable_error) {
+ my $fmt_errors = &comma_numbers($overall_stat{'errors_number'}) || 0;
+ my $fmt_unique_error = &comma_numbers(scalar keys %{$overall_stat{'unique_normalized_errors'}}) || 0;
+ print $fh qq{
Number of errors: $fmt_errors
Number of unique normalized errors: $fmt_unique_error
};
+ }
if ($tempfile_info{count}) {
my $fmt_temp_maxsise = &comma_numbers($tempfile_info{maxsize}) || 0;
my $fmt_temp_avsize = &comma_numbers(sprintf("%.2f", ($tempfile_info{maxsize}/$tempfile_info{count})));
$idx++;
}
- print $fh "\n- Most frequent errors (N) ---------------------------------------------\n\n";
- print $fh "Rank Times reported Error\n";
- $idx = 1;
- foreach my $k (sort {$error_info{$b}{count} <=> $error_info{$a}{count}} keys %error_info) {
- next if (!$error_info{$k}{count});
- last if ($idx > $top);
- print $fh "$idx) " . &comma_numbers($error_info{$k}{count}) . " - $k\n";
- print $fh "--\n";
- if ($error_info{$k}{count} > 1) {
- my $j = 1;
- for (my $i = 0; $i <= $#{$error_info{$k}{date}}; $i++) {
- print $fh "\t- Example $j: $error_info{$k}{date}[$i] - $error_info{$k}{error}[$i]\n";
- print $fh "\t\tDetail: $error_info{$k}{detail}[$i]\n" if ($error_info{$k}{detail}[$i]);
- $j++;
+ if (!$disable_error) {
+ print $fh "\n- Most frequent errors (N) ---------------------------------------------\n\n";
+ print $fh "Rank Times reported Error\n";
+ $idx = 1;
+ foreach my $k (sort {$error_info{$b}{count} <=> $error_info{$a}{count}} keys %error_info) {
+ next if (!$error_info{$k}{count});
+ last if ($idx > $top);
+ print $fh "$idx) " . &comma_numbers($error_info{$k}{count}) . " - $k\n";
+ print $fh "--\n";
+ if ($error_info{$k}{count} > 1) {
+ my $j = 1;
+ for (my $i = 0; $i <= $#{$error_info{$k}{date}}; $i++) {
+ print $fh "\t- Example $j: $error_info{$k}{date}[$i] - $error_info{$k}{error}[$i]\n";
+ print $fh "\t\tDetail: $error_info{$k}{detail}[$i]\n" if ($error_info{$k}{detail}[$i]);
+ $j++;
+ }
+ } elsif ($error_info{$k}{detail}[0]) {
+ print $fh "\t- Example: $error_info{$k}{date}[0] - $k";
+ print $fh "\t\tDetail: $error_info{$k}{detail}[0]\n";
+ } else {
+ print $fh "\t- Example: $error_info{$k}{date}[0] - $k\n";
}
- } elsif ($error_info{$k}{detail}[0]) {
- print $fh "\t- Example: $error_info{$k}{date}[0] - $k";
- print $fh "\t\tDetail: $error_info{$k}{detail}[0]\n";
- } else {
- print $fh "\t- Example: $error_info{$k}{date}[0] - $k\n";
+ $idx++;
}
- $idx++;
}
print $fh "\n\n";
print $fh "Report generated by <a href=\"https://github.com/dalibo/pgbadger\">PgBadger</a> $VERSION.\n";
<a href="#NormalizedQueriesMostTimeReport">Queries that took up the most time (N)</a> |
<a href="#NormalizedQueriesMostFrequentReport">Most frequent queries (N)</a> |
<a href="#NormalizedQueriesSlowestAverageReport">Slowest queries (N)</a><br />
+};
+ if (!$disable_error) {
+ print $fh qq{
<a href="#NormalizedErrorsMostFrequentReport">Most frequent errors (N)</a> |
};
+ }
if (scalar keys %lock_info > 0) {
print $fh qq{<a href="#LocksByTypeReport">Locks by type</a> |};
}
print $fh qq{<li><a href="#ConnectionsHostReport">Connections per host</a></li><li>};
}
-
- print $fh qq{<a href="#SlowestQueriesReport">Slowest queries</a></li><li><a href="#NormalizedQueriesMostTimeReport">Queries that took up the most time (N)</a></li><li><a href="#NormalizedQueriesMostFrequentReport">Most frequent queries (N)</a></li><li><a href="#NormalizedQueriesSlowestAverageReport">Slowest queries (N)</a></li><li><a href="#NormalizedErrorsMostFrequentReport">Most frequent errors (N)</a></li>
- </ul>
+ print $fh qq{<a href="#SlowestQueriesReport">Slowest queries</a></li><li><a href="#NormalizedQueriesMostTimeReport">Queries that took up the most time (N)</a></li><li><a href="#NormalizedQueriesMostFrequentReport">Most frequent queries (N)</a></li><li><a href="#NormalizedQueriesSlowestAverageReport">Slowest queries (N)</a></li>
+};
+ if (!$disable_error) {
+ print $fh "<li><a href=\"#NormalizedErrorsMostFrequentReport\">Most frequent errors (N)</a></li>\n";
+ }
+ print $fh qq{</ul>
</div>
<div id="littleTocTitle">Table of contents</div>
</div>
print $fh "<li>Query peak: ", &comma_numbers($overall_stat{'query_peak'}{$_}), " queries/s at $_</li>";
last;
}
- my $fmt_errors = &comma_numbers($overall_stat{'errors_number'}) || 0;
- my $fmt_unique_error = &comma_numbers(scalar keys %{$overall_stat{'unique_normalized_errors'}}) || 0;
- print $fh qq{
+ if (!$disable_error) {
+ my $fmt_errors = &comma_numbers($overall_stat{'errors_number'}) || 0;
+ my $fmt_unique_error = &comma_numbers(scalar keys %{$overall_stat{'unique_normalized_errors'}}) || 0;
+ print $fh qq{
<li>Number of errors: $fmt_errors</li>
<li>Number of unique normalized errors: $fmt_unique_error</li>
</ul>
</td><td valign="top">
<ul>
};
+ }
if ($tempfile_info{count}) {
my $fmt_temp_maxsise = &comma_numbers($tempfile_info{maxsize}) || 0;
my $fmt_temp_avsize = &comma_numbers(sprintf("%.2f", $tempfile_info{maxsize}/$tempfile_info{count}));
}
print $fh "</table>\n";
- print $fh qq{
+ if (!$disable_error) {
+ print $fh qq{
<h2 id="NormalizedErrorsMostFrequentReport">Most frequent errors (N) <a href="#top" title="Back to top">^</a></h2>
<table class="queryList">
<tr>
</tr>
};
- $idx = 1;
- foreach my $k (sort {$error_info{$b}{count} <=> $error_info{$a}{count}} keys %error_info) {
- next if (!$error_info{$k}{count});
- last if ($idx > $top);
- my $col = $idx % 2;
- print $fh "<tr class=\"row$col\"><td class=\"center top\">$idx</td><td class=\"relevantInformation top center\"><div class=\"tooltipLink\"><span class=\"information\">", &comma_numbers($error_info{$k}{count}), "</span>";
- print $fh "<div class=\"tooltip\"><table><tr><th>Day</th><th>Time</th><th>Count</th></tr>";
- foreach my $d (sort keys %{$error_info{$k}{chronos}}) {
- my $c = 1;
- $d =~ /^\d{4}(\d{2})(\d{2})$/;
- my $zday = "$abbr_month{$1} $2";
- foreach my $h (sort keys %{$error_info{$k}{chronos}{$d}}) {
- my $colb = $c % 2;
- $zday = " " if ($c > 1);
- print $fh "<tr class=\"row$colb\"><td>$zday</td><td>$h</td><td>", &comma_numbers($error_info{$k}{chronos}{$d}{$h}{count}), "</td></tr>";
- $c++;
+ $idx = 1;
+ foreach my $k (sort {$error_info{$b}{count} <=> $error_info{$a}{count}} keys %error_info) {
+ next if (!$error_info{$k}{count});
+ last if ($idx > $top);
+ my $col = $idx % 2;
+ print $fh "<tr class=\"row$col\"><td class=\"center top\">$idx</td><td class=\"relevantInformation top center\"><div class=\"tooltipLink\"><span class=\"information\">", &comma_numbers($error_info{$k}{count}), "</span>";
+ print $fh "<div class=\"tooltip\"><table><tr><th>Day</th><th>Time</th><th>Count</th></tr>";
+ foreach my $d (sort keys %{$error_info{$k}{chronos}}) {
+ my $c = 1;
+ $d =~ /^\d{4}(\d{2})(\d{2})$/;
+ my $zday = "$abbr_month{$1} $2";
+ foreach my $h (sort keys %{$error_info{$k}{chronos}{$d}}) {
+ my $colb = $c % 2;
+ $zday = " " if ($c > 1);
+ print $fh "<tr class=\"row$colb\"><td>$zday</td><td>$h</td><td>", &comma_numbers($error_info{$k}{chronos}{$d}{$h}{count}), "</td></tr>";
+ $c++;
+ }
}
- }
- print $fh "</table></div></div></td>\n";
- if ($error_info{$k}{count} > 1) {
- print $fh "<td><div class=\"error\">$k</div>";
- print $fh "<input type=\"button\" class=\"examplesButton\" id=\"button_NormalizedErrorsMostFrequentReport_$idx\" name=\"button_NormalizedErrorsMostFrequentReport_$idx\" value=\"Show examples\" onclick=\"javascript:toggle('button_NormalizedErrorsMostFrequentReport_$idx', 'examples_NormalizedErrorsMostFrequentReport_$idx', 'examples');\" /><div id=\"examples_NormalizedErrorsMostFrequentReport_$idx\" class=\"examples\" style=\"display:none;\">";
- for (my $i = 0; $i <= $#{$error_info{$k}{date}}; $i++) {
- my $c = $i % 2;
- print $fh "<div class=\"example$c\" title=\"$error_info{$k}{date}[$i]\">$error_info{$k}{error}[$i]</div>\n";
- print $fh "<div class=\"errorInformation$c\">Detail: $error_info{$k}{detail}[$i]</div>\n" if ($error_info{$k}{detail}[$i]);
+ print $fh "</table></div></div></td>\n";
+ if ($error_info{$k}{count} > 1) {
+ print $fh "<td><div class=\"error\">$k</div>";
+ print $fh "<input type=\"button\" class=\"examplesButton\" id=\"button_NormalizedErrorsMostFrequentReport_$idx\" name=\"button_NormalizedErrorsMostFrequentReport_$idx\" value=\"Show examples\" onclick=\"javascript:toggle('button_NormalizedErrorsMostFrequentReport_$idx', 'examples_NormalizedErrorsMostFrequentReport_$idx', 'examples');\" /><div id=\"examples_NormalizedErrorsMostFrequentReport_$idx\" class=\"examples\" style=\"display:none;\">";
+ for (my $i = 0; $i <= $#{$error_info{$k}{date}}; $i++) {
+ my $c = $i % 2;
+ print $fh "<div class=\"example$c\" title=\"$error_info{$k}{date}[$i]\">$error_info{$k}{error}[$i]</div>\n";
+ print $fh "<div class=\"errorInformation$c\">Detail: $error_info{$k}{detail}[$i]</div>\n" if ($error_info{$k}{detail}[$i]);
+ }
+ print $fh "</div>";
+ } elsif ($error_info{$k}{detail}[0]) {
+ print $fh "<td><div class=\"error\" title=\"$error_info{$k}{date}[0]\">$k</div>";
+ print $fh "<div class=\"errorInformation\">Detail: $error_info{$k}{detail}[0]</div>\n";
+ } else {
+ print $fh "<td><div class=\"error\" title=\"$error_info{$k}{date}[0]\">$k</div>";
}
- print $fh "</div>";
- } elsif ($error_info{$k}{detail}[0]) {
- print $fh "<td><div class=\"error\" title=\"$error_info{$k}{date}[0]\">$k</div>";
- print $fh "<div class=\"errorInformation\">Detail: $error_info{$k}{detail}[0]</div>\n";
- } else {
- print $fh "<td><div class=\"error\" title=\"$error_info{$k}{date}[0]\">$k</div>";
+ print $fh "</td></tr>\n";
+ $idx++;
}
- print $fh "</td></tr>\n";
- $idx++;
+ print $fh "</table>\n";
}
- print $fh "</table>\n";
# Dump the html footer
&html_footer();
# Store errors statistics
if ($cur_info{query}) {
delete $conn_received{$cur_info{pid}};
- if ($cur_info{loglevel} =~ /WARNING|ERROR|FATAL|PANIC|HINT/) {
- $cur_info{query} = substr($cur_info{query}, 0, $maxlength) . '[...]' if (($maxlength > 0) && (length($cur_info{query}) > $maxlength));
- $cur_info{query} = $cur_info{loglevel} . ": " . $cur_info{query};
- $overall_stat{'errors_number'}++;
- my $normalized_error = &normalize_error($cur_info{query});
- $overall_stat{'unique_normalized_errors'}{"$normalized_error"}++;
- # Store normalyzed error count
- $error_info{$normalized_error}{count}++;
- # Store normalyzed error count per time
- $error_info{$normalized_error}{chronos}{"$cur_info{year}$cur_info{month}$cur_info{day}"}{"$cur_info{hour}"}{count}++;
- # Store normalyzed query samples
- my $cur_last_log_date = "$cur_info{year}-$cur_info{month}-$cur_info{day} $cur_info{hour}:$cur_info{min}:$cur_info{sec}";
- if ($t_loglevel =~ /DETAIL|STATEMENT/) {
- &set_top_error_sample($normalized_error, $cur_last_log_date, $cur_info{query}, $t_query);
- } else {
- &set_top_error_sample($normalized_error, $cur_last_log_date, $cur_info{query});
+ if (!$disable_error) {
+ if ($cur_info{loglevel} =~ /WARNING|ERROR|FATAL|PANIC|HINT/) {
+ $cur_info{query} = substr($cur_info{query}, 0, $maxlength) . '[...]' if (($maxlength > 0) && (length($cur_info{query}) > $maxlength));
+ $cur_info{query} = $cur_info{loglevel} . ": " . $cur_info{query};
+ $overall_stat{'errors_number'}++;
+ my $normalized_error = &normalize_error($cur_info{query});
+ $overall_stat{'unique_normalized_errors'}{"$normalized_error"}++;
+ # Store normalyzed error count
+ $error_info{$normalized_error}{count}++;
+ # Store normalyzed error count per time
+ $error_info{$normalized_error}{chronos}{"$cur_info{year}$cur_info{month}$cur_info{day}"}{"$cur_info{hour}"}{count}++;
+ # Store normalyzed query samples
+ my $cur_last_log_date = "$cur_info{year}-$cur_info{month}-$cur_info{day} $cur_info{hour}:$cur_info{min}:$cur_info{sec}";
+ if ($t_loglevel =~ /DETAIL|STATEMENT/) {
+ &set_top_error_sample($normalized_error, $cur_last_log_date, $cur_info{query}, $t_query);
+ } else {
+ &set_top_error_sample($normalized_error, $cur_last_log_date, $cur_info{query});
+ }
+ %cur_info = ();
+ return;
}
- %cur_info = ();
- return;
}
# Process complete query but not debug/info logs