Files
percona-toolkit/t/lib/QueryReportFormatter.t
Sveta Smirnova 5c999ca3e0 PT-2340 - Support MySQL 8.4
- Removed runtime.txt after discussion with Anastasia Alexandrova
- Added "use VersionParser" into tests in t/lib when needed
- Removed word master from tests for pt-archiver, pt-config-diff, pt-deadlock-logger, pt-duplicate-key-checker, pt-find, pt-fk-error-logger, pt-heartbeat, pt-index-usage, pt-ioprofile, pt-kill, pt-mysql-summary
- Removed word slave from tests for pt-archiver, pt-config-diff, pt-deadlock-logger, pt-duplicate-key-checker, pt-find, pt-fk-error-logger, pt-heartbeat, pt-index-usage, pt-ioprofile, pt-kill, pt-mysql-summary
- Updated modules for pt-archiver, pt-config-diff, pt-deadlock-logger, pt-duplicate-key-checker, pt-find, pt-fk-error-logger, pt-heartbeat, pt-index-usage, pt-ioprofile, pt-kill, pt-mysql-summary
- Changed mysql_ssl patch, so it is now short option s
- Added a check for existing zombies in t/pt-kill/execute_command.t
- Added bin/pt-galera-log-explainer to .gitignore
2024-07-27 01:59:52 +03:00

1429 lines
38 KiB
Perl

#!/usr/bin/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 Data::Dumper;
$Data::Dumper::Indent = 1;
$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Quotekeys = 0;
use Transformers;
use QueryReportFormatter;
use EventAggregator;
use QueryRewriter;
use QueryParser;
use Quoter;
use ReportFormatter;
use OptionParser;
use DSNParser;
use VersionParser;
use ReportFormatter;
use ExplainAnalyzer;
use Sandbox;
use PerconaTest;
my $dp = new DSNParser(opts=>$dsn_opts);
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
my $dbh = $sb->get_dbh_for('source', {no_lc=>1}); # for explain sparkline
my ($result, $events, $expected);
my $q = new Quoter();
my $qp = new QueryParser();
my $qr = new QueryRewriter(QueryParser=>$qp);
my $o = new OptionParser(description=>'qrf');
my $ex = new ExplainAnalyzer(QueryRewriter => $qr, QueryParser => $qp);
$o->get_specs("$trunk/bin/pt-query-digest");
my $qrf = new QueryReportFormatter(
OptionParser => $o,
QueryRewriter => $qr,
QueryParser => $qp,
Quoter => $q,
ExplainAnalyzer => $ex,
);
my $ea = new EventAggregator(
groupby => 'fingerprint',
worst => 'Query_time',
attributes => {
Query_time => [qw(Query_time)],
Lock_time => [qw(Lock_time)],
user => [qw(user)],
ts => [qw(ts)],
Rows_sent => [qw(Rows_sent)],
Rows_examined => [qw(Rows_examined)],
db => [qw(db)],
},
);
isa_ok($qrf, 'QueryReportFormatter');
$result = $qrf->rusage();
like(
$result,
qr/^# \S+ user time, \S+ system time, \S+ rss, \S+ vsz/s,
'rusage report',
);
$events = [
{ ts => '071015 21:43:52',
cmd => 'Query',
user => 'root',
host => 'localhost',
ip => '',
arg => "SELECT id FROM users WHERE name='foo'",
Query_time => '8.000652',
Lock_time => '0.000109',
Rows_sent => 1,
Rows_examined => 1,
pos_in_log => 1,
db => 'test3',
},
{ ts => '071015 21:43:52',
cmd => 'Query',
user => 'root',
host => 'localhost',
ip => '',
arg =>
"INSERT IGNORE INTO articles (id, body,)VALUES(3558268,'sample text')",
Query_time => '1.001943',
Lock_time => '0.000145',
Rows_sent => 0,
Rows_examined => 0,
pos_in_log => 2,
db => 'test1',
},
{ ts => '071015 21:43:53',
cmd => 'Query',
user => 'bob',
host => 'localhost',
ip => '',
arg => "SELECT id FROM users WHERE name='bar'",
Query_time => '1.000682',
Lock_time => '0.000201',
Rows_sent => 1,
Rows_examined => 2,
pos_in_log => 5,
db => 'test1',
}
];
# Here's the breakdown of values for those three events:
#
# ATTRIBUTE VALUE BUCKET VALUE RANGE
# Query_time => 8.000652 326 7.700558026 range [7.700558026, 8.085585927)
# Query_time => 1.001943 284 0.992136979 range [0.992136979, 1.041743827)
# Query_time => 1.000682 284 0.992136979 range [0.992136979, 1.041743827)
# -------- -----------
# 10.003277 9.684831984
#
# Lock_time => 0.000109 97 0.000108186 range [0.000108186, 0.000113596)
# Lock_time => 0.000145 103 0.000144980 range [0.000144980, 0.000152229)
# Lock_time => 0.000201 109 0.000194287 range [0.000194287, 0.000204002)
# -------- -----------
# 0.000455 0.000447453
#
# Rows_sent => 1 284 0.992136979 range [0.992136979, 1.041743827)
# Rows_sent => 0 0 0
# Rows_sent => 1 284 0.992136979 range [0.992136979, 1.041743827)
# -------- -----------
# 2 1.984273958
#
# Rows_exam => 1 284 0.992136979 range [0.992136979, 1.041743827)
# Rows_exam => 0 0 0
# Rows_exam => 2 298 1.964363355, range [1.964363355, 2.062581523)
# -------- -----------
# 3 2.956500334
# I hand-checked these values with my TI-83 calculator.
# They are, without a doubt, correct.
foreach my $event (@$events) {
$event->{fingerprint} = $qr->fingerprint( $event->{arg} );
$ea->aggregate($event);
}
$ea->calculate_statistical_metrics(apdex_t=>1);
$result = $qrf->header(
ea => $ea,
select => [ qw(Query_time Lock_time Rows_sent Rows_examined ts) ],
orderby => 'Query_time',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report006.txt",
cmd_output => 1,
),
'Global (header) report'
);
$result = $qrf->event_report(
ea => $ea,
# "users" is here to try to cause a failure
select => [ qw(Query_time Lock_time Rows_sent Rows_examined ts db user users) ],
item => 'select id from users where name=?',
rank => 1,
orderby => 'Query_time',
reason => 'top',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report007.txt",
cmd_output => 1,
),
'Event report'
);
{
# pt-query-digest prints negative byte offset
# https://bugs.launchpad.net/percona-toolkit/+bug/887638
# printf "%d" can't really handle large values in some systems.
# Given a large enough log file, it will start printing
# negative values. The workaround is to use %.f instead. I haven't
# researched what the recommended solution for this is, but
# it's such an uncommon case and that it's not worth the time.
# This bug should really only affect 32-bit machines, and even then
# only those were the underlaying compiler's printf("%d") coerces the
# argument into a signed int.
my $item = 'select id from users where name=?';
local $ea->results->{samples}->{$item}->{pos_in_log} = 1e+33;
$result = $qrf->event_report(
ea => $ea,
# "users" is here to try to cause a failure
select => [ qw(Query_time Lock_time Rows_sent Rows_examined ts db user users) ],
item => $item,
rank => 1,
orderby => 'Query_time',
reason => 'top',
);
unlike(
$result,
qr/at byte -/,
"Bug 887638: pt-query-digest prints negative byte offset"
);
}
$result = $qrf->chart_distro(
ea => $ea,
attrib => 'Query_time',
item => 'select id from users where name=?',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report008.txt",
cmd_output => 1,
),
'Query_time distro'
);
SKIP: {
skip 'Wider labels not used, not tested', 1;
$qrf = new QueryReportFormatter(label_width => 15);
$result = $qrf->event_report(
$ea,
# "users" is here to try to cause a failure
select => [ qw(Query_time Lock_time Rows_sent Rows_examined ts db user users) ],
where => 'select id from users where name=?',
rank => 1,
worst => 'Query_time',
reason => 'top',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report017.txt",
cmd_output => 1,
),
'Event report with wider label'
);
$qrf = new QueryReportFormatter;
};
# ########################################################################
# This one is all about an event that's all zeroes.
# ########################################################################
$ea = new EventAggregator(
groupby => 'fingerprint',
worst => 'Query_time',
attributes => {
Query_time => [qw(Query_time)],
Lock_time => [qw(Lock_time)],
user => [qw(user)],
ts => [qw(ts)],
Rows_sent => [qw(Rows_sent)],
Rows_examined => [qw(Rows_examined)],
db => [qw(db)],
},
);
$events = [
{ bytes => 30,
db => 'mysql',
ip => '127.0.0.1',
arg => 'administrator command: Connect',
fingerprint => 'administrator command: Connect',
Rows_affected => 0,
user => 'msandbox',
Warning_count => 0,
cmd => 'Admin',
No_good_index_used => 'No',
ts => '090412 11:00:13.118191',
No_index_used => 'No',
port => '57890',
host => '127.0.0.1',
Thread_id => 8,
pos_in_log => '0',
Query_time => '0',
Error_no => 0
},
];
foreach my $event (@$events) {
$event->{fingerprint} = $qr->fingerprint( $event->{arg} );
$ea->aggregate($event);
}
$ea->calculate_statistical_metrics(apdex_t=>1);
$result = $qrf->header(
ea => $ea,
select => [ qw(Query_time Lock_time Rows_sent Rows_examined ts) ],
orderby => 'Query_time',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report018.txt",
cmd_output => 1,
),
'Global report with all zeroes'
);
$result = $qrf->event_report(
ea => $ea,
select => [ qw(Query_time Lock_time Rows_sent Rows_examined ts db user users) ],
item => 'administrator command: Connect',
rank => 1,
orderby => 'Query_time',
reason => 'top',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report009.txt",
cmd_output => 1,
),
'Event report with all zeroes'
);
# This used to cause illegal division by zero in some cases.
$result = $qrf->chart_distro(
ea => $ea,
attrib => 'Query_time',
item => 'administrator command: Connect',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report019.txt",
cmd_output => 1,
),
'Chart distro with all zeroes'
);
# #############################################################################
# Test bool (Yes/No) pretty printing.
# #############################################################################
$events = [
{ ts => '071015 21:43:52',
cmd => 'Query',
arg => "SELECT id FROM users WHERE name='foo'",
Query_time => '8.000652',
Lock_time => '0.002300',
QC_Hit => 'No',
Filesort => 'Yes',
InnoDB_IO_r_bytes => 2,
InnoDB_pages_distinct => 20,
},
{ ts => '071015 21:43:52',
cmd => 'Query',
arg => "SELECT id FROM users WHERE name='foo'",
Query_time => '1.001943',
Lock_time => '0.002320',
QC_Hit => 'Yes',
Filesort => 'Yes',
InnoDB_IO_r_bytes => 2,
InnoDB_pages_distinct => 18,
},
{ ts => '071015 21:43:53',
cmd => 'Query',
arg => "SELECT id FROM users WHERE name='bar'",
Query_time => '1.000682',
Lock_time => '0.003301',
QC_Hit => 'Yes',
Filesort => 'Yes',
InnoDB_IO_r_bytes => 3,
InnoDB_pages_distinct => 11,
}
];
$ea = new EventAggregator(
groupby => 'fingerprint',
worst => 'Query_time',
ignore_attributes => [qw(arg cmd)],
);
foreach my $event (@$events) {
$event->{fingerprint} = $qr->fingerprint( $event->{arg} );
$ea->aggregate($event);
}
$ea->calculate_statistical_metrics();
$result = $qrf->header(
ea => $ea,
orderby => 'Query_time',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report020.txt",
cmd_output => 1,
),
'Bool (Yes/No) pretty printer'
);
$events = [
{ ts => '071015 21:43:52',
cmd => 'Query',
arg => "SELECT id FROM users WHERE name='foo'",
Query_time => '8.000652',
Lock_time => '0.002300',
QC_Hit => 'No',
Filesort => 'No',
InnoDB_IO_r_bytes => 2,
InnoDB_pages_distinct => 20,
},
];
$ea->reset_aggregated_data();
foreach my $event (@$events) {
$event->{fingerprint} = $qr->fingerprint( $event->{arg} );
$ea->aggregate($event);
}
$ea->calculate_statistical_metrics();
$result = $qrf->header(
ea => $ea,
orderby => 'Query_time',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report023.txt",
cmd_output => 1,
),
'No Boolean sub-header in gobal report when all zero bools'
);
$result = $qrf->event_report(
ea => $ea,
orderby => 'Query_time',
item => 'select id from users where name=?',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report024.txt",
cmd_output => 1,
),
'No Boolean sub-header in event report with all zero bools'
);
# #############################################################################
# Test attrib sorting.
# #############################################################################
# This test uses the $ea from the Bool pretty printer test above.
my $sorted = $qrf->sort_attribs($ea);
is_deeply(
$sorted,
{
num => [qw(Query_time Lock_time)],
innodb => [qw(InnoDB_IO_r_bytes InnoDB_pages_distinct)],
bool => [qw(Filesort QC_Hit)],
string => [qw()],
},
'sort_attribs()'
) or print Dumper($sorted);
# Make an ea with most of the common attributes.
$events = [
{ ts => '071015 21:43:52',
cmd => 'Query',
arg => "SELECT id FROM users WHERE name='foo'",
bytes => length("SELECT id FROM users WHERE name='foo'"),
db => "db1",
user => "myuser",
host => "127.0.0.1",
Thread_id => 555,
Query_time => '8.000652',
Lock_time => '0.002300',
Rows_sent => 100,
Rows_examined => 5000000,
Rows_read => 123456789,
QC_Hit => 'No',
Filesort => 'Yes',
Merge_passes => 50,
InnoDB_IO_r_bytes => 2,
InnoDB_pages_distinct => 20,
},
];
$ea = new EventAggregator(
groupby => 'fingerprint',
worst => 'Query_time',
ignore_attributes => [qw(arg cmd)],
type_for => { Thread_id => 'string' },
);
foreach my $event (@$events) {
$event->{fingerprint} = $qr->fingerprint( $event->{arg} );
$ea->aggregate($event);
}
$ea->calculate_statistical_metrics();
$sorted = $qrf->sort_attribs($ea);
is_deeply(
$sorted,
{
num => [qw(Query_time Lock_time Rows_sent Rows_examined Rows_read Merge_passes bytes)],
innodb => [qw(InnoDB_IO_r_bytes InnoDB_pages_distinct)],
bool => [qw(Filesort QC_Hit)],
string => [qw(db host Thread_id user)],
},
'more sort_attribs()'
) or print Dumper($sorted);
# ############################################################################
# Test that --[no]zero-bool removes 0% vals.
# ############################################################################
$events = [
{ ts => '071015 21:43:52',
cmd => 'Query',
arg => "SELECT id FROM users WHERE name='foo'",
Query_time => '8.000652',
Lock_time => '0.002300',
QC_Hit => 'No',
Filesort => 'No',
},
{ ts => '071015 21:43:52',
cmd => 'Query',
arg => "SELECT id FROM users WHERE name='foo'",
Query_time => '1.001943',
Lock_time => '0.002320',
QC_Hit => 'Yes',
Filesort => 'No',
},
{ ts => '071015 21:43:53',
cmd => 'Query',
arg => "SELECT id FROM users WHERE name='bar'",
Query_time => '1.000682',
Lock_time => '0.003301',
QC_Hit => 'Yes',
Filesort => 'No',
}
];
$ea = new EventAggregator(
groupby => 'fingerprint',
worst => 'Query_time',
ignore_attributes => [qw(arg cmd)],
);
foreach my $event (@$events) {
$event->{fingerprint} = $qr->fingerprint( $event->{arg} );
$ea->aggregate($event);
}
$ea->calculate_statistical_metrics();
$result = $qrf->header(
ea => $ea,
# select => [ $ea->get_attributes() ],
orderby => 'Query_time',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report021.txt",
cmd_output => 1,
),
'No zero bool vals'
);
# #############################################################################
# Issue 458: mk-query-digest Use of uninitialized value in division (/) at
# line 3805
# #############################################################################
use SlowLogParser;
my $p = new SlowLogParser();
sub report_from_file {
my $ea2 = new EventAggregator(
groupby => 'fingerprint',
worst => 'Query_time',
);
my ( $file ) = @_;
$file = "$trunk/$file";
my @e;
my @callbacks;
push @callbacks, sub {
my ( $event ) = @_;
my $group_by_val = $event->{arg};
return 0 unless defined $group_by_val;
$event->{fingerprint} = $qr->fingerprint($group_by_val);
return $event;
};
push @callbacks, sub {
$ea2->aggregate(@_);
};
eval {
open my $fh, "<", $file or die "Cannot open $file: $OS_ERROR";
my %args = (
next_event => sub { return <$fh>; },
tell => sub { return tell($fh); },
);
while ( my $e = $p->parse_event(%args) ) {
$_->($e) for @callbacks;
}
close $fh;
};
die $EVAL_ERROR if $EVAL_ERROR;
$ea2->calculate_statistical_metrics();
my %top_spec = (
attrib => 'Query_time',
orderby => 'sum',
total => 100,
count => 100,
);
my ($worst, $other) = $ea2->top_events(%top_spec);
my $top_n = scalar @$worst;
my $report = '';
foreach my $rank ( 1 .. $top_n ) {
$report .= $qrf->event_report(
ea => $ea2,
# select => [ $ea2->get_attributes() ],
item => $worst->[$rank - 1]->[0],
rank => $rank,
orderby => 'Query_time',
reason => '',
);
}
return $report;
}
# The real bug is in QueryReportFormatter, and there's nothing particularly
# interesting about this sample, but we just want to make sure that the
# timestamp prop shows up only in the one event. The bug is that it appears
eval {
report_from_file('t/lib/samples/slowlogs/slow029.txt');
};
is(
$EVAL_ERROR,
'',
'event_report() does not die on empty attributes (issue 458)'
);
# #############################################################################
# Test that format_string_list() truncates long strings.
# #############################################################################
$events = [
{ ts => '071015 21:43:52',
cmd => 'Query',
arg => "SELECT id FROM users WHERE name='foo'",
Query_time => 1,
foo => "Hi. I'm a very long string. I'm way over the 78 column width that we try to keep lines limited to so text wrapping doesn't make things look all funky and stuff.",
},
];
$ea = new EventAggregator(
groupby => 'fingerprint',
worst => 'Query_time',
ignore_attributes => [qw(arg cmd)],
);
foreach my $event (@$events) {
$event->{fingerprint} = $qr->fingerprint( $event->{arg} );
$ea->aggregate($event);
}
$ea->calculate_statistical_metrics();
$result = $qrf->event_report(
ea => $ea,
select => [ qw(Query_time foo) ],
item => 'select id from users where name=?',
rank => 1,
orderby => 'Query_time',
reason => 'top',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report010.txt",
cmd_output => 1,
),
"Don't truncate one long string"
);
$ea->reset_aggregated_data();
push @$events,
{ ts => '071015 21:43:55',
cmd => 'Query',
arg => "SELECT id FROM users WHERE name='foo'",
Query_time => 2,
foo => "Me too! I'm a very long string yay! I'm also over the 78 column width that we try to keep lines limited to."
};
foreach my $event (@$events) {
$event->{fingerprint} = $qr->fingerprint( $event->{arg} );
$ea->aggregate($event);
}
$ea->calculate_statistical_metrics();
$result = $qrf->event_report(
ea => $ea,
select => [ qw(Query_time foo) ],
item => 'select id from users where name=?',
rank => 1,
orderby => 'Query_time',
reason => 'top',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report011.txt",
cmd_output => 1,
),
"Don't truncate multiple long strings"
);
$ea->reset_aggregated_data();
push @$events,
{ ts => '071015 21:43:55',
cmd => 'Query',
arg => "SELECT id FROM users WHERE name='foo'",
Query_time => 3,
foo => 'Number 3 long string, but I\'ll exceed the line length so I\'ll only show up as "more" :-('
};
foreach my $event (@$events) {
$event->{fingerprint} = $qr->fingerprint( $event->{arg} );
$ea->aggregate($event);
}
$ea->calculate_statistical_metrics();
$result = $qrf->event_report(
ea => $ea,
select => [ qw(Query_time foo) ],
item => 'select id from users where name=?',
rank => 1,
orderby => 'Query_time',
reason => 'top',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report012.txt",
cmd_output => 1,
),
"Don't truncate multiple strings longer than whole line"
);
# #############################################################################
# Issue 478: mk-query-digest doesn't count errors and hosts right
# #############################################################################
# We decided that string attribs shouldn't be listed in the global header.
$events = [
{
cmd => 'Query',
arg => "SELECT id FROM users WHERE name='foo'",
Query_time => '8.000652',
user => 'bob',
},
{
cmd => 'Query',
arg => "SELECT id FROM users WHERE name='foo'",
Query_time => '1.001943',
user => 'bob',
},
{
cmd => 'Query',
arg => "SELECT id FROM users WHERE name='bar'",
Query_time => '1.000682',
user => 'bob',
}
];
$ea = new EventAggregator(
groupby => 'fingerprint',
worst => 'Query_time',
ignore_attributes => [qw(arg cmd)],
);
foreach my $event (@$events) {
$event->{fingerprint} = $qr->fingerprint( $event->{arg} );
$ea->aggregate($event);
}
$ea->calculate_statistical_metrics();
$result = $qrf->header(
ea => $ea,
select => $ea->get_attributes(),
orderby => 'Query_time',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report022.txt",
cmd_output => 1,
),
'No string attribs in global report (issue 478)'
);
# #############################################################################
# Issue 744: Option to show all Hosts
# #############################################################################
# Don't shorten IP addresses.
$events = [
{
cmd => 'Query',
arg => "foo",
Query_time => '8.000652',
host => '123.123.123.456',
},
{
cmd => 'Query',
arg => "foo",
Query_time => '8.000652',
host => '123.123.123.789',
},
];
$ea = new EventAggregator(
groupby => 'arg',
worst => 'Query_time',
ignore_attributes => [qw(arg cmd)],
);
foreach my $event (@$events) {
$ea->aggregate($event);
}
$ea->calculate_statistical_metrics();
$result = $qrf->event_report(
ea => $ea,
select => [ qw(Query_time host) ],
item => 'foo',
rank => 1,
orderby => 'Query_time',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report013.txt",
cmd_output => 1,
),
"IPs not shortened"
);
# Add another event so we get "... N more" to make sure that IPs
# are still not shortened.
push @$events,
{
cmd => 'Query',
arg => "foo",
Query_time => '8.000652',
host => '123.123.123.999',
};
$ea->aggregate($events->[-1]);
$ea->calculate_statistical_metrics();
$result = $qrf->event_report(
ea => $ea,
select => [ qw(Query_time host) ],
item => 'foo',
rank => 1,
orderby => 'Query_time',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report014.txt",
cmd_output => 1,
),
"IPs not shortened with more"
);
# Don't shorten hostnames
$events = [
{
cmd => 'Query',
arg => "foo",
Query_time => '8.000652',
host => 'a-really-long-host-name',
},
{
cmd => 'Query',
arg => "foo",
Query_time => '8.000652',
host => '123.123.123.789',
},
];
$ea = new EventAggregator(
groupby => 'arg',
worst => 'Query_time',
ignore_attributes => [qw(arg cmd)],
);
foreach my $event (@$events) {
$ea->aggregate($event);
}
$ea->calculate_statistical_metrics();
my $no_trim_qrf = new QueryReportFormatter(
OptionParser => $o,
QueryRewriter => $qr,
QueryParser => $qp,
Quoter => $q,
ExplainAnalyzer => $ex,
max_hostname_length => 0,
);
$result = $no_trim_qrf->event_report(
ea => $ea,
select => [ qw(Query_time host) ],
item => 'foo',
rank => 1,
orderby => 'Query_time',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report014_no_trim.txt",
cmd_output => 1,
),
"Hostnames were not trimmed"
);
$no_trim_qrf = new QueryReportFormatter(
OptionParser => $o,
QueryRewriter => $qr,
QueryParser => $qp,
Quoter => $q,
ExplainAnalyzer => $ex,
max_hostname_length => 12,
max_line_length => 200,
);
$result = $no_trim_qrf->event_report(
ea => $ea,
select => [ qw(Query_time host) ],
item => 'foo',
rank => 1,
orderby => 'Query_time',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report014_trim_12.txt",
cmd_output => 1,
),
"Hostnames were not trimmed"
);
$result = $qrf->event_report(
ea => $ea,
select => [ qw(Query_time host) ],
item => 'foo',
rank => 1,
orderby => 'Query_time',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report015.txt",
cmd_output => 1,
),
"Show all hosts"
);
# #############################################################################
# Issue 948: mk-query-digest treats InnoDB_rec_lock_wait value as number
# instead of time
# #############################################################################
$events = [
{
cmd => 'Query',
arg => "foo",
Query_time => '8.000652',
InnoDB_rec_lock_wait => 0.001,
InnoDB_IO_r_wait => 0.002,
InnoDB_queue_wait => 0.003,
},
];
$ea = new EventAggregator(
groupby => 'arg',
worst => 'Query_time',
ignore_attributes => [qw(arg cmd)],
);
foreach my $event (@$events) {
$ea->aggregate($event);
}
$ea->calculate_statistical_metrics();
$result = $qrf->event_report(
ea => $ea,
select => [ qw(Query_time InnoDB_rec_lock_wait InnoDB_IO_r_wait InnoDB_queue_wait) ],
item => 'foo',
rank => 1,
orderby => 'Query_time',
);
ok(
no_diff(
$result,
"t/lib/samples/QueryReportFormatter/report016.txt",
cmd_output => 1,
),
"_wait attribs treated as times (issue 948)"
);
# #############################################################################
# print_reports()
# #############################################################################
$events = [
{
cmd => 'Query',
arg => "select col from tbl where id=42",
fingerprint => "select col from tbl where id=?",
Query_time => '1.000652',
Lock_time => '0.001292',
ts => '071015 21:43:52',
pos_in_log => 123,
db => 'foodb',
},
];
$ea = new EventAggregator(
groupby => 'fingerprint',
worst => 'Query_time',
);
foreach my $event ( @$events ) {
$ea->aggregate($event);
}
$ea->calculate_statistical_metrics(apdex_t=>1);
# Reset opts in case anything above left something set.
@ARGV = qw();
$o->get_opts();
$qrf = new QueryReportFormatter(
OptionParser => $o,
QueryRewriter => $qr,
QueryParser => $qp,
Quoter => $q,
ExplainAnalyzer => $ex,
);
ok(
no_diff(
sub { $qrf->print_reports(
reports => [qw(header query_report profile)],
ea => $ea,
worst => [['select col from tbl where id=?','top',1]],
other => [],
orderby => 'Query_time',
groupby => 'fingerprint',
variations => [qw(arg)],
); },
"t/lib/samples/QueryReportFormatter/report001.txt",
),
"print_reports(header, query_report, profile)"
);
ok(
no_diff(
sub { $qrf->print_reports(
reports => [qw(profile query_report header)],
ea => $ea,
worst => [['select col from tbl where id=?','top',1]],
orderby => 'Query_time',
groupby => 'fingerprint',
variations => [qw(arg)],
); },
"t/lib/samples/QueryReportFormatter/report003.txt",
),
"print_reports(profile, query_report, header)",
);
$events = [
{
Query_time => '0.000286',
Warning_count => 0,
arg => 'PREPARE SELECT i FROM d.t WHERE i=?',
fingerprint => 'prepare select i from d.t where i=?',
bytes => 35,
cmd => 'Query',
db => undef,
pos_in_log => 0,
ts => '091208 09:23:49.637394',
Statement_id => 2,
},
{
Query_time => '0.030281',
Warning_count => 0,
arg => 'EXECUTE SELECT i FROM d.t WHERE i="3"',
fingerprint => 'execute select i from d.t where i=?',
bytes => 37,
cmd => 'Query',
db => undef,
pos_in_log => 1106,
ts => '091208 09:23:49.637892',
Statement_id => 2,
},
];
$ea = new EventAggregator(
groupby => 'fingerprint',
worst => 'Query_time',
type_for => {
Statement_id => 'string',
},
);
foreach my $event ( @$events ) {
$ea->aggregate($event);
}
$ea->calculate_statistical_metrics();
ok(
no_diff(
sub {
$qrf->print_reports(
reports => ['query_report','prepared'],
ea => $ea,
worst => [
['execute select i from d.t where i=?', 'top',1],
['prepare select i from d.t where i=?', 'top',2],
],
orderby => 'Query_time',
groupby => 'fingerprint',
variations => [qw(arg)],
);
},
"t/lib/samples/QueryReportFormatter/report002.txt",
),
"print_reports(query_report, prepared)"
);
push @$events,
{
Query_time => '1.030281',
arg => 'update foo set col=1 where 1',
fingerprint => 'update foo set col=? where ?',
bytes => 37,
cmd => 'Query',
pos_in_log => 100,
ts => '091208 09:23:49.637892',
},
$ea = new EventAggregator(
groupby => 'fingerprint',
worst => 'Query_time',
);
foreach my $event ( @$events ) {
$ea->aggregate($event);
}
$ea->calculate_statistical_metrics();
ok(
no_diff(
sub {
$qrf->print_reports(
reports => ['profile'],
ea => $ea,
worst => [
['update foo set col=? where ?', 'top',1]
],
other => [
['execute select i from d.t where i=?','misc',2],
['prepare select i from d.t where i=?','misc',3],
],
orderby => 'Query_time',
groupby => 'fingerprint',
);
},
"t/lib/samples/QueryReportFormatter/report004.txt",
),
"MISC items in profile"
);
# #############################################################################
# EXPLAIN report
# #############################################################################
SKIP: {
skip 'Cannot connect to sandbox master', 3 unless $dbh;
$sb->load_file('source', "t/lib/samples/QueryReportFormatter/table.sql");
@ARGV = qw(--explain F=/tmp/12345/my.sandbox.cnf);
$o->get_opts();
$qrf = new QueryReportFormatter(
OptionParser => $o,
QueryRewriter => $qr,
QueryParser => $qp,
Quoter => $q,
ExplainAnalyzer => $ex,
);
my $qrf = new QueryReportFormatter(
OptionParser => $o,
QueryRewriter => $qr,
QueryParser => $qp,
Quoter => $q,
dbh => $dbh,
ExplainAnalyzer => $ex,
);
my $explain = load_file(
$sandbox_version ge '5.7' ? "t/lib/samples/QueryReportFormatter/report031-5.7.txt"
: $sandbox_version eq '5.6' ? "t/lib/samples/QueryReportFormatter/report031.txt"
: $sandbox_version ge '5.1' ? "t/lib/samples/QueryReportFormatter/report025.txt"
: "t/lib/samples/QueryReportFormatter/report026.txt");
# 32
my $explain_report = $qrf->explain_report("select * from qrf.t where i=2", 'qrf');
$explain_report =~ s/filtered: 100(\s+)/filtered: 100.00$1/;
is(
$explain_report,
$explain,
"explain_report()"
);
$sb->wipe_clean($dbh);
$dbh->disconnect();
}
# #############################################################################
# files and date reports.
# #############################################################################
like(
$qrf->date(),
qr/# Current date: .+?\d+:\d+:\d+/,
"date report"
);
is(
$qrf->files(files=>[{name=>"foo"},{name=>"bar"}]),
"# Files: foo, bar\n",
"files report"
);
like(
$qrf->hostname(),
qr/# Hostname: .+?/,
"hostname report"
);
# #############################################################################
# Test report grouping.
# #############################################################################
$events = [
{
cmd => 'Query',
arg => "select col from tbl where id=42",
fingerprint => "select col from tbl where id=?",
Query_time => '1.000652',
Lock_time => '0.001292',
ts => '071015 21:43:52',
pos_in_log => 123,
db => 'foodb',
},
];
$ea = new EventAggregator(
groupby => 'fingerprint',
worst => 'Query_time',
);
foreach my $event ( @$events ) {
$ea->aggregate($event);
}
$ea->calculate_statistical_metrics();
@ARGV = qw();
$o->get_opts();
$qrf = new QueryReportFormatter(
OptionParser => $o,
QueryRewriter => $qr,
QueryParser => $qp,
Quoter => $q,
ExplainAnalyzer => $ex,
);
my $output = output(
sub { $qrf->print_reports(
reports => [qw(rusage date files header query_report profile)],
ea => $ea,
worst => [['select col from tbl where id=?','top',1]],
orderby => 'Query_time',
groupby => 'fingerprint',
files => [{name=>"foo"},{name=>"bar"}],
group => {map {$_=>1} qw(rusage date files header)},
); }
);
like(
$output,
qr/
^#\s.+?\suser time.+?vsz$
^#\sCurrent date:.+?$
^#\sFiles:\sfoo,\sbar$
/mx,
"grouped reports"
);
# #############################################################################
# Issue 1124: Make mk-query-digest profile include variance-to-mean ratio
# #############################################################################
$events = [
{
Query_time => "1.000000",
arg => "select c from t where id=1",
fingerprint => "select c from t where id=?",
cmd => 'Query',
pos_in_log => 0,
},
{
Query_time => "5.500000",
arg => "select c from t where id=2",
fingerprint => "select c from t where id=?",
cmd => 'Query',
pos_in_log => 0,
},
{
Query_time => "2.000000",
arg => "select c from t where id=3",
fingerprint => "select c from t where id=?",
cmd => 'Query',
pos_in_log => 0,
},
{
Query_time => "9.000000",
arg => "select c from t where id=4",
fingerprint => "select c from t where id=?",
cmd => 'Query',
pos_in_log => 0,
},
];
$ea = new EventAggregator(
groupby => 'fingerprint',
worst => 'Query_time',
);
foreach my $event ( @$events ) {
$ea->aggregate($event);
}
$ea->calculate_statistical_metrics();
ok(
no_diff(
sub {
$qrf->print_reports(
reports => ['profile'],
ea => $ea,
worst => [
['select c from t where id=?', 'top',1],
],
orderby => 'Query_time',
groupby => 'fingerprint',
);
},
"t/lib/samples/QueryReportFormatter/report005.txt",
),
"Variance-to-mean ration (issue 1124)"
);
# ############################################################################
# Bug 887688: Prepared statements crash pt-query-digest
# ############################################################################
# PREP without EXEC
$events = [
{
Query_time => '0.000286',
Warning_count => 0,
arg => 'PREPARE SELECT i FROM d.t WHERE i=?',
fingerprint => 'prepare select i from d.t where i=?',
bytes => 35,
cmd => 'Query',
db => undef,
pos_in_log => 0,
ts => '091208 09:23:49.637394',
Statement_id => 1,
},
];
$ea = new EventAggregator(
groupby => 'fingerprint',
worst => 'Query_time',
type_for => {
Statement_id => 'string',
},
);
foreach my $event ( @$events ) {
$ea->aggregate($event);
}
$ea->calculate_statistical_metrics();
ok(
no_diff(
sub {
$qrf->print_reports(
reports => ['prepared'],
ea => $ea,
worst => [
['prepare select i from d.t where i=?', 'top', 1],
],
orderby => 'Query_time',
groupby => 'fingerprint',
variations => [qw(arg)],
);
},
"t/lib/samples/QueryReportFormatter/report030.txt",
),
"PREP without EXEC (bug 887688)"
);
# #############################################################################
# Done.
# #############################################################################
$output = '';
{
local *STDERR;
open STDERR, '>', \$output;
$qrf->_d('Complete test coverage');
}
like(
$output,
qr/Complete test coverage/,
'_d() works'
);
ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
done_testing;
exit;