mirror of
https://github.com/percona/percona-toolkit.git
synced 2026-04-25 02:00:07 +08:00
Added JSONReportFormatter, a subclass of QueryReportFormatter that does what it says on the tin. WIP as it does not report profile or prepared statement data yet
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
{
|
||||
package JSONReportFormatter;
|
||||
use Mo;
|
||||
use JSON;
|
||||
|
||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
|
||||
extends qw(QueryReportFormatter);
|
||||
|
||||
override [qw(rusage date hostname files header profile prepared)] => sub {
|
||||
return;
|
||||
};
|
||||
|
||||
override event_report => sub {
|
||||
my ($self, %args) = @_;
|
||||
return $self->event_report_values(%args);
|
||||
};
|
||||
|
||||
override query_report => sub {
|
||||
my ($self, %args) = @_;
|
||||
foreach my $arg ( qw(ea worst orderby groupby) ) {
|
||||
die "I need a $arg argument" unless defined $arg;
|
||||
}
|
||||
my $ea = $args{ea};
|
||||
my $groupby = $args{groupby};
|
||||
my $worst = $args{worst};
|
||||
|
||||
my $q = $self->Quoter;
|
||||
my $qv = $self->{QueryReview};
|
||||
my $qr = $self->{QueryRewriter};
|
||||
|
||||
my $query_report_vals = $self->query_report_values(%args);
|
||||
|
||||
# Sort the attributes, removing any hidden attributes.
|
||||
my $attribs = $self->sort_attribs(
|
||||
($args{select} ? $args{select} : $ea->get_attributes()),
|
||||
$ea,
|
||||
);
|
||||
|
||||
ITEM:
|
||||
foreach my $vals ( @$query_report_vals ) {
|
||||
my $item = $vals->{item};
|
||||
my $samp_query = $vals->{samp_query};
|
||||
# ###############################################################
|
||||
# Print the standard query analysis report.
|
||||
# ###############################################################
|
||||
$vals->{event_report} = $self->event_report(
|
||||
%args,
|
||||
item => $item,
|
||||
sample => $ea->results->{samples}->{$item},
|
||||
rank => $vals->{rank},
|
||||
reason => $vals->{reason},
|
||||
attribs => $attribs,
|
||||
db => $vals->{default_db},
|
||||
);
|
||||
|
||||
if ( $groupby eq 'fingerprint' ) {
|
||||
if ( $item =~ m/^(?:[\(\s]*select|insert|replace)/ ) {
|
||||
if ( $item !~ m/^(?:insert|replace)/ ) { # No EXPLAIN
|
||||
$vals->{for_explain} = "EXPLAIN /*!50100 PARTITIONS*/\n$samp_query\\G\n";
|
||||
$vals->{explain_report} = $self->explain_report($samp_query, $vals->{default_db});
|
||||
}
|
||||
}
|
||||
else {
|
||||
my $converted = $qr->convert_to_select($samp_query);
|
||||
if ( $converted
|
||||
&& $converted =~ m/^[\(\s]*select/i ) {
|
||||
$vals->{for_explain} = "EXPLAIN /*!50100 PARTITIONS*/\n$converted\\G\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( $groupby eq 'tables' ) {
|
||||
my ( $db, $tbl ) = $q->split_unquote($item);
|
||||
$vals->{tables_report} = $self->tables_report([$db, $tbl]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return encode_json($query_report_vals) . "\n";
|
||||
};
|
||||
|
||||
1;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
BEGIN {
|
||||
die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n"
|
||||
unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH};
|
||||
unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib";
|
||||
};
|
||||
|
||||
use strict;
|
||||
use warnings FATAL => 'all';
|
||||
use English qw(-no_match_vars);
|
||||
use Test::More;
|
||||
|
||||
use PerconaTest;
|
||||
require "$trunk/bin/pt-query-digest";
|
||||
|
||||
my @args = qw(--output json);
|
||||
my $sample = "$trunk/t/lib/samples";
|
||||
my $results = "t/pt-query-digest/samples";
|
||||
|
||||
ok(
|
||||
no_diff(
|
||||
sub { pt_query_digest::main(@args, "$sample/slowlogs/empty") },
|
||||
"$results/empty_report.txt",
|
||||
),
|
||||
'json output for empty log'
|
||||
);
|
||||
|
||||
ok(
|
||||
no_diff(
|
||||
sub { pt_query_digest::main(@args, "$sample/slowlogs/slow002.txt") },
|
||||
"$results/output_json_slow002.txt"
|
||||
),
|
||||
'json output for slow002'
|
||||
);
|
||||
|
||||
# --type tcpdump
|
||||
|
||||
ok(
|
||||
no_diff(
|
||||
sub { pt_query_digest::main(qw(--type tcpdump --limit 10 --watch-server 127.0.0.1:12345),
|
||||
@args, "$sample/tcpdump/tcpdump021.txt") },
|
||||
"$results/output_json_tcpdump021.txt",
|
||||
),
|
||||
'json output for for tcpdump021',
|
||||
);
|
||||
|
||||
# #############################################################################
|
||||
# Done.
|
||||
# #############################################################################
|
||||
done_testing;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
[{"event_report":{"time_range":"all events occurred at 2007-12-18 11:48:27","variance_to_mean":0,"reason":"top","qps":0,"counts":{"class_cnt":1,"global_cnt":8},"concurrency":0,"checksum":"66825DDC008FFA89","pos_in_log":338,"attributes":{"bool":[["Full_scan","100","0"]],"innodb":[],"num":[["Query_time","95","726ms","726ms","726ms","726ms","726ms",0,"726ms"],["Lock_time","29","91us","91us","91us","91us","91us",0,"91us"],["Rows_sent","0","0","0","0","0","0","0","0"],["Rows_examined","100","61.48k","61.48k","61.48k","61.48k","61.48k","0","61.48k"],["Merge_passes","0","0","0","0","0","0","0","0"],["bytes","25","129","129","129","129","129","0","129"]],"string":[["db",{"min":"db1","max":"db1","unq":{"db1":1},"cnt":1}],["host",{"min":"","max":"","unq":{"":1},"cnt":1}],["user",{"min":"[SQL_SLAVE]","max":"[SQL_SLAVE]","unq":{"[SQL_SLAVE]":1},"cnt":1}]]},"groupby":"fingerprint"},"reason":"top","item":"update d?tuningdetail_?_? n inner join d?gonzo a using(gonzo) set n.column? = a.column?, n.word? = a.word?","samp_query":"update db2.tuningdetail_21_265507 n\n inner join db1.gonzo a using(gonzo) \n set n.column1 = a.column1, n.word3 = a.word3","for_explain":"EXPLAIN /*!50100 PARTITIONS*/\nselect n.column1 = a.column1, n.word3 = a.word3 from db2.tuningdetail_21_265507 n\n inner join db1.gonzo a using(gonzo) \\G\n","tables":[["db2","tuningdetail_21_265507"],["db1","gonzo"]],"rank":1,"default_db":"db1"}]
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
[{"event_report":{"time_range":"all events occurred at 2009-12-08 09:23:49.637394","variance_to_mean":0,"reason":"top","qps":0,"counts":{"class_cnt":1,"global_cnt":3},"concurrency":0,"checksum":"AA8E9FA785927259","pos_in_log":0,"attributes":{"bool":[],"innodb":[],"num":[["Query_time","50","286us","286us","286us","286us","286us",0,"286us"],["Rows_affected","0","0","0","0","0","0","0","0"],["bytes","35","35","35","35","35","35","0","35"],["Warning_count","0","0","0","0","0","0","0","0"]],"string":[["Error_no",{"min":"none","max":"none","unq":{"none":1},"cnt":1}],["host",{"min":"127.0.0.1","max":"127.0.0.1","unq":{"127.0.0.1":1},"cnt":1}],["Statement_id",{"min":2,"max":2,"unq":{"2":1},"cnt":1}]]},"groupby":"fingerprint"},"reason":"top","item":"prepare select i from d.t where i=?","samp_query":"PREPARE SELECT i FROM d.t WHERE i=?","for_explain":"EXPLAIN /*!50100 PARTITIONS*/\nSELECT i FROM d.t WHERE i=?\\G\n","tables":[["d","t"]],"rank":1,"default_db":null},{"event_report":{"time_range":"all events occurred at 2009-12-08 09:23:49.637892","variance_to_mean":0,"reason":"top","qps":0,"counts":{"class_cnt":1,"global_cnt":3},"concurrency":0,"checksum":"3F79759E7FA2F117","pos_in_log":1106,"attributes":{"bool":[["No_index_used","100","0"]],"innodb":[],"num":[["Query_time","49","281us","281us","281us","281us","281us",0,"281us"],["Rows_affected","0","0","0","0","0","0","0","0"],["bytes","37","37","37","37","37","37","0","37"],["Warning_count","0","0","0","0","0","0","0","0"]],"string":[["Error_no",{"min":"none","max":"none","unq":{"none":1},"cnt":1}],["host",{"min":"127.0.0.1","max":"127.0.0.1","unq":{"127.0.0.1":1},"cnt":1}],["Statement_id",{"min":"2","max":"2","unq":{"2":1},"cnt":1}]]},"groupby":"fingerprint"},"reason":"top","item":"execute select i from d.t where i=?","samp_query":"EXECUTE SELECT i FROM d.t WHERE i=\"3\"","for_explain":"EXPLAIN /*!50100 PARTITIONS*/\nSELECT i FROM d.t WHERE i=\"3\"\\G\n","tables":[["d","t"]],"rank":2,"default_db":null},{"samp_query":"administrator command: Quit","tables":[],"event_report":{"time_range":"all events occurred at 2009-12-08 09:23:49.638381","variance_to_mean":0,"reason":"top","qps":0,"counts":{"class_cnt":1,"global_cnt":3},"concurrency":0,"checksum":"AA353644DE4C4CB4","pos_in_log":1850,"attributes":{"bool":[],"innodb":[],"num":[["Query_time","0",0,0,0,0,0,0,0],["Rows_affected","0","0","0","0","0","0","0","0"],["bytes","27","27","27","27","27","27","0","27"],["Warning_count","0","0","0","0","0","0","0","0"]],"string":[["Error_no",{"min":"none","max":"none","unq":{"none":1},"cnt":1}],["host",{"min":"127.0.0.1","max":"127.0.0.1","unq":{"127.0.0.1":1},"cnt":1}]]},"groupby":"fingerprint"},"reason":"top","item":"administrator command: Quit","rank":3,"default_db":null}]
|
||||
Reference in New Issue
Block a user