~percona-toolkit-dev/percona-toolkit/fix-log-parser-writer-bug-963225

« back to all changes in this revision

Viewing changes to t/lib/QueryReportFormatter.t

  • Committer: Daniel Nichter
  • Date: 2011-06-24 17:22:06 UTC
  • Revision ID: daniel@percona.com-20110624172206-c7q4s4ad6r260zz6
Add lib/, t/lib/, and sandbox/.  All modules are updated and passing on MySQL 5.1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/perl
 
2
 
 
3
BEGIN {
 
4
   die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n"
 
5
      unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH};
 
6
   unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib";
 
7
};
 
8
 
 
9
use strict;
 
10
use warnings FATAL => 'all';
 
11
use English qw(-no_match_vars);
 
12
use Test::More tests => 43;
 
13
 
 
14
use Data::Dumper;
 
15
$Data::Dumper::Indent    = 1;
 
16
$Data::Dumper::Sortkeys  = 1;
 
17
$Data::Dumper::Quotekeys = 0;
 
18
 
 
19
use Transformers;
 
20
use QueryReportFormatter;
 
21
use EventAggregator;
 
22
use QueryRewriter;
 
23
use QueryParser;
 
24
use Quoter;
 
25
use ReportFormatter;
 
26
use OptionParser;
 
27
use DSNParser;
 
28
use ReportFormatter;
 
29
use ExplainAnalyzer;
 
30
use Sandbox;
 
31
use MaatkitTest;
 
32
 
 
33
my $dp  = new DSNParser(opts=>$dsn_opts);
 
34
my $sb  = new Sandbox(basedir => '/tmp', DSNParser => $dp);
 
35
my $dbh = $sb->get_dbh_for('master', {no_lc=>1});  # for explain sparkline
 
36
 
 
37
my ($result, $events, $expected);
 
38
 
 
39
my $q   = new Quoter();
 
40
my $qp  = new QueryParser();
 
41
my $qr  = new QueryRewriter(QueryParser=>$qp);
 
42
my $o   = new OptionParser(description=>'qrf');
 
43
my $ex  = new ExplainAnalyzer(QueryRewriter => $qr, QueryParser => $qp);
 
44
 
 
45
$o->get_specs("$trunk/bin/pt-query-digest");
 
46
 
 
47
my $qrf = new QueryReportFormatter(
 
48
   OptionParser    => $o,
 
49
   QueryRewriter   => $qr,
 
50
   QueryParser     => $qp,
 
51
   Quoter          => $q, 
 
52
   ExplainAnalyzer => $ex,
 
53
);
 
54
 
 
55
my $ea  = new EventAggregator(
 
56
   groupby => 'fingerprint',
 
57
   worst   => 'Query_time',
 
58
   attributes => {
 
59
      Query_time    => [qw(Query_time)],
 
60
      Lock_time     => [qw(Lock_time)],
 
61
      user          => [qw(user)],
 
62
      ts            => [qw(ts)],
 
63
      Rows_sent     => [qw(Rows_sent)],
 
64
      Rows_examined => [qw(Rows_examined)],
 
65
      db            => [qw(db)],
 
66
   },
 
67
);
 
68
 
 
69
isa_ok($qrf, 'QueryReportFormatter');
 
70
 
 
71
$result = $qrf->rusage();
 
72
like(
 
73
   $result,
 
74
   qr/^# \S+ user time, \S+ system time, \S+ rss, \S+ vsz/s,
 
75
   'rusage report',
 
76
);
 
77
 
 
78
$events = [
 
79
   {  ts            => '071015 21:43:52',
 
80
      cmd           => 'Query',
 
81
      user          => 'root',
 
82
      host          => 'localhost',
 
83
      ip            => '',
 
84
      arg           => "SELECT id FROM users WHERE name='foo'",
 
85
      Query_time    => '8.000652',
 
86
      Lock_time     => '0.000109',
 
87
      Rows_sent     => 1,
 
88
      Rows_examined => 1,
 
89
      pos_in_log    => 1,
 
90
      db            => 'test3',
 
91
   },
 
92
   {  ts   => '071015 21:43:52',
 
93
      cmd  => 'Query',
 
94
      user => 'root',
 
95
      host => 'localhost',
 
96
      ip   => '',
 
97
      arg =>
 
98
         "INSERT IGNORE INTO articles (id, body,)VALUES(3558268,'sample text')",
 
99
      Query_time    => '1.001943',
 
100
      Lock_time     => '0.000145',
 
101
      Rows_sent     => 0,
 
102
      Rows_examined => 0,
 
103
      pos_in_log    => 2,
 
104
      db            => 'test1',
 
105
   },
 
106
   {  ts            => '071015 21:43:53',
 
107
      cmd           => 'Query',
 
108
      user          => 'bob',
 
109
      host          => 'localhost',
 
110
      ip            => '',
 
111
      arg           => "SELECT id FROM users WHERE name='bar'",
 
112
      Query_time    => '1.000682',
 
113
      Lock_time     => '0.000201',
 
114
      Rows_sent     => 1,
 
115
      Rows_examined => 2,
 
116
      pos_in_log    => 5,
 
117
      db            => 'test1',
 
118
   }
 
119
];
 
120
 
 
121
# Here's the breakdown of values for those three events:
 
122
 
123
# ATTRIBUTE     VALUE     BUCKET  VALUE        RANGE
 
124
# Query_time => 8.000652  326     7.700558026  range [7.700558026, 8.085585927)
 
125
# Query_time => 1.001943  284     0.992136979  range [0.992136979, 1.041743827)
 
126
# Query_time => 1.000682  284     0.992136979  range [0.992136979, 1.041743827)
 
127
#               --------          -----------
 
128
#               10.003277         9.684831984
 
129
#
 
130
# Lock_time  => 0.000109  97      0.000108186  range [0.000108186, 0.000113596)
 
131
# Lock_time  => 0.000145  103     0.000144980  range [0.000144980, 0.000152229)
 
132
# Lock_time  => 0.000201  109     0.000194287  range [0.000194287, 0.000204002)
 
133
#               --------          -----------
 
134
#               0.000455          0.000447453
 
135
#
 
136
# Rows_sent  => 1         284     0.992136979  range [0.992136979, 1.041743827)
 
137
# Rows_sent  => 0         0       0
 
138
# Rows_sent  => 1         284     0.992136979  range [0.992136979, 1.041743827)
 
139
#               --------          -----------
 
140
#               2                 1.984273958
 
141
#
 
142
# Rows_exam  => 1         284     0.992136979  range [0.992136979, 1.041743827)
 
143
# Rows_exam  => 0         0       0 
 
144
# Rows_exam  => 2         298     1.964363355, range [1.964363355, 2.062581523) 
 
145
#               --------          -----------
 
146
#               3                 2.956500334
 
147
 
 
148
# I hand-checked these values with my TI-83 calculator.
 
149
# They are, without a doubt, correct.
 
150
 
 
151
foreach my $event (@$events) {
 
152
   $event->{fingerprint} = $qr->fingerprint( $event->{arg} );
 
153
   $ea->aggregate($event);
 
154
}
 
155
$ea->calculate_statistical_metrics(apdex_t=>1);
 
156
$result = $qrf->header(
 
157
   ea      => $ea,
 
158
   select  => [ qw(Query_time Lock_time Rows_sent Rows_examined ts) ],
 
159
   orderby => 'Query_time',
 
160
);
 
161
 
 
162
ok(
 
163
   no_diff(
 
164
      $result,
 
165
      "t/lib/samples/QueryReportFormatter/report006.txt",
 
166
      cmd_output => 1,
 
167
   ),
 
168
   'Global (header) report'
 
169
);
 
170
 
 
171
$result = $qrf->event_report(
 
172
   ea => $ea,
 
173
   # "users" is here to try to cause a failure
 
174
   select => [ qw(Query_time Lock_time Rows_sent Rows_examined ts db user users) ],
 
175
   item    => 'select id from users where name=?',
 
176
   rank    => 1,
 
177
   orderby => 'Query_time',
 
178
   reason  => 'top',
 
179
);
 
180
 
 
181
ok(
 
182
   no_diff(
 
183
      $result,
 
184
      "t/lib/samples/QueryReportFormatter/report007.txt",
 
185
      cmd_output => 1,
 
186
   ),
 
187
   'Event report'
 
188
);
 
189
 
 
190
$result = $qrf->chart_distro(
 
191
   ea     => $ea,
 
192
   attrib => 'Query_time',
 
193
   item   => 'select id from users where name=?',
 
194
);
 
195
 
 
196
ok(
 
197
   no_diff(
 
198
      $result,
 
199
      "t/lib/samples/QueryReportFormatter/report008.txt",
 
200
      cmd_output => 1,
 
201
   ),
 
202
   'Query_time distro'
 
203
);
 
204
 
 
205
SKIP: {
 
206
   skip 'Wider labels not used, not tested', 1;
 
207
$qrf = new QueryReportFormatter(label_width => 15);
 
208
 
 
209
$result = $qrf->event_report(
 
210
   $ea,
 
211
   # "users" is here to try to cause a failure
 
212
   select => [ qw(Query_time Lock_time Rows_sent Rows_examined ts db user users) ],
 
213
   where   => 'select id from users where name=?',
 
214
   rank    => 1,
 
215
   worst   => 'Query_time',
 
216
   reason  => 'top',
 
217
);
 
218
 
 
219
ok(
 
220
   no_diff(
 
221
      $result,
 
222
      "t/lib/samples/QueryReportFormatter/report017.txt",
 
223
      cmd_output => 1,
 
224
   ),
 
225
   'Event report with wider label'
 
226
);
 
227
 
 
228
$qrf = new QueryReportFormatter;
 
229
};
 
230
 
 
231
# ########################################################################
 
232
# This one is all about an event that's all zeroes.
 
233
# ########################################################################
 
234
$ea  = new EventAggregator(
 
235
   groupby => 'fingerprint',
 
236
   worst   => 'Query_time',
 
237
   attributes => {
 
238
      Query_time    => [qw(Query_time)],
 
239
      Lock_time     => [qw(Lock_time)],
 
240
      user          => [qw(user)],
 
241
      ts            => [qw(ts)],
 
242
      Rows_sent     => [qw(Rows_sent)],
 
243
      Rows_examined => [qw(Rows_examined)],
 
244
      db            => [qw(db)],
 
245
   },
 
246
);
 
247
 
 
248
$events = [
 
249
   {  bytes              => 30,
 
250
      db                 => 'mysql',
 
251
      ip                 => '127.0.0.1',
 
252
      arg                => 'administrator command: Connect',
 
253
      fingerprint        => 'administrator command: Connect',
 
254
      Rows_affected      => 0,
 
255
      user               => 'msandbox',
 
256
      Warning_count      => 0,
 
257
      cmd                => 'Admin',
 
258
      No_good_index_used => 'No',
 
259
      ts                 => '090412 11:00:13.118191',
 
260
      No_index_used      => 'No',
 
261
      port               => '57890',
 
262
      host               => '127.0.0.1',
 
263
      Thread_id          => 8,
 
264
      pos_in_log         => '0',
 
265
      Query_time         => '0',
 
266
      Error_no           => 0
 
267
   },
 
268
];
 
269
 
 
270
foreach my $event (@$events) {
 
271
   $event->{fingerprint} = $qr->fingerprint( $event->{arg} );
 
272
   $ea->aggregate($event);
 
273
}
 
274
$ea->calculate_statistical_metrics(apdex_t=>1);
 
275
 
 
276
$result = $qrf->header(
 
277
   ea      => $ea,
 
278
   select  => [ qw(Query_time Lock_time Rows_sent Rows_examined ts) ],
 
279
   orderby => 'Query_time',
 
280
);
 
281
 
 
282
ok(
 
283
   no_diff(
 
284
      $result,
 
285
      "t/lib/samples/QueryReportFormatter/report018.txt",
 
286
      cmd_output => 1,
 
287
   ),
 
288
   'Global report with all zeroes'
 
289
);
 
290
 
 
291
$result = $qrf->event_report(
 
292
   ea     => $ea,
 
293
   select => [ qw(Query_time Lock_time Rows_sent Rows_examined ts db user users) ],
 
294
   item    => 'administrator command: Connect',
 
295
   rank    => 1,
 
296
   orderby => 'Query_time',
 
297
   reason  => 'top',
 
298
);
 
299
 
 
300
ok(
 
301
   no_diff(
 
302
      $result,
 
303
      "t/lib/samples/QueryReportFormatter/report009.txt",
 
304
      cmd_output => 1,
 
305
   ),
 
306
   'Event report with all zeroes'
 
307
);
 
308
 
 
309
# This used to cause illegal division by zero in some cases.
 
310
$result = $qrf->chart_distro(
 
311
   ea     => $ea,
 
312
   attrib => 'Query_time',
 
313
   item   => 'administrator command: Connect',
 
314
);
 
315
 
 
316
ok(
 
317
   no_diff(
 
318
      $result,
 
319
      "t/lib/samples/QueryReportFormatter/report019.txt",
 
320
      cmd_output => 1,
 
321
   ),
 
322
   'Chart distro with all zeroes'
 
323
);
 
324
 
 
325
# #############################################################################
 
326
# Test bool (Yes/No) pretty printing.
 
327
# #############################################################################
 
328
$events = [
 
329
   {  ts            => '071015 21:43:52',
 
330
      cmd           => 'Query',
 
331
      arg           => "SELECT id FROM users WHERE name='foo'",
 
332
      Query_time    => '8.000652',
 
333
      Lock_time     => '0.002300',
 
334
      QC_Hit        => 'No',
 
335
      Filesort      => 'Yes',
 
336
      InnoDB_IO_r_bytes     => 2,
 
337
      InnoDB_pages_distinct => 20,
 
338
   },
 
339
   {  ts            => '071015 21:43:52',
 
340
      cmd           => 'Query',
 
341
      arg           => "SELECT id FROM users WHERE name='foo'",
 
342
      Query_time    => '1.001943',
 
343
      Lock_time     => '0.002320',
 
344
      QC_Hit        => 'Yes',
 
345
      Filesort      => 'Yes',
 
346
      InnoDB_IO_r_bytes     => 2,
 
347
      InnoDB_pages_distinct => 18,
 
348
   },
 
349
   {  ts            => '071015 21:43:53',
 
350
      cmd           => 'Query',
 
351
      arg           => "SELECT id FROM users WHERE name='bar'",
 
352
      Query_time    => '1.000682',
 
353
      Lock_time     => '0.003301',
 
354
      QC_Hit        => 'Yes',
 
355
      Filesort      => 'Yes',
 
356
      InnoDB_IO_r_bytes     => 3,
 
357
      InnoDB_pages_distinct => 11,
 
358
   }
 
359
];
 
360
 
 
361
$ea  = new EventAggregator(
 
362
   groupby => 'fingerprint',
 
363
   worst   => 'Query_time',
 
364
   ignore_attributes => [qw(arg cmd)],
 
365
);
 
366
foreach my $event (@$events) {
 
367
   $event->{fingerprint} = $qr->fingerprint( $event->{arg} );
 
368
   $ea->aggregate($event);
 
369
}
 
370
$ea->calculate_statistical_metrics();
 
371
$result = $qrf->header(
 
372
   ea      => $ea,
 
373
   orderby => 'Query_time',
 
374
);
 
375
 
 
376
ok(
 
377
   no_diff(
 
378
      $result,
 
379
      "t/lib/samples/QueryReportFormatter/report020.txt",
 
380
      cmd_output => 1,
 
381
   ),
 
382
   'Bool (Yes/No) pretty printer'
 
383
);
 
384
 
 
385
$events = [
 
386
   {  ts            => '071015 21:43:52',
 
387
      cmd           => 'Query',
 
388
      arg           => "SELECT id FROM users WHERE name='foo'",
 
389
      Query_time    => '8.000652',
 
390
      Lock_time     => '0.002300',
 
391
      QC_Hit        => 'No',
 
392
      Filesort      => 'No',
 
393
      InnoDB_IO_r_bytes     => 2,
 
394
      InnoDB_pages_distinct => 20,
 
395
   },
 
396
];
 
397
$ea->reset_aggregated_data();
 
398
foreach my $event (@$events) {
 
399
   $event->{fingerprint} = $qr->fingerprint( $event->{arg} );
 
400
   $ea->aggregate($event);
 
401
}
 
402
$ea->calculate_statistical_metrics();
 
403
 
 
404
$result = $qrf->header(
 
405
   ea      => $ea,
 
406
   orderby => 'Query_time',
 
407
);
 
408
ok(
 
409
   no_diff(
 
410
      $result,
 
411
      "t/lib/samples/QueryReportFormatter/report023.txt",
 
412
      cmd_output => 1,
 
413
   ),
 
414
   'No Boolean sub-header in gobal report when all zero bools'
 
415
);
 
416
 
 
417
$result = $qrf->event_report(
 
418
   ea      => $ea,
 
419
   orderby => 'Query_time',
 
420
   item    => 'select id from users where name=?',
 
421
);
 
422
ok(
 
423
   no_diff(
 
424
      $result,
 
425
      "t/lib/samples/QueryReportFormatter/report024.txt",
 
426
      cmd_output => 1,
 
427
   ),
 
428
   'No Boolean sub-header in event report with all zero bools'
 
429
);
 
430
 
 
431
# #############################################################################
 
432
# Test attrib sorting.
 
433
# #############################################################################
 
434
 
 
435
# This test uses the $ea from the Bool pretty printer test above.
 
436
my $sorted = $qrf->sort_attribs($ea->get_attributes(), $ea);
 
437
is_deeply(
 
438
   $sorted,
 
439
   {
 
440
      num    => [qw(Query_time Lock_time)],
 
441
      innodb => [qw(InnoDB_IO_r_bytes InnoDB_pages_distinct)],
 
442
      bool   => [qw(Filesort QC_Hit)],
 
443
      string => [qw()],
 
444
   },
 
445
   'sort_attribs()'
 
446
) or print Dumper($sorted);
 
447
 
 
448
# Make an ea with most of the common attributes.
 
449
$events = [
 
450
   {  ts            => '071015 21:43:52',
 
451
      cmd           => 'Query',
 
452
      arg           => "SELECT id FROM users WHERE name='foo'",
 
453
      bytes         => length("SELECT id FROM users WHERE name='foo'"),
 
454
      db            => "db1",
 
455
      user          => "myuser",
 
456
      host          => "127.0.0.1",
 
457
      Thread_id     => 555,
 
458
      Query_time    => '8.000652',
 
459
      Lock_time     => '0.002300',
 
460
      Rows_sent     => 100,
 
461
      Rows_examined => 5000000,
 
462
      Rows_read     => 123456789,
 
463
      QC_Hit        => 'No',
 
464
      Filesort      => 'Yes',
 
465
      Merge_passes  => 50,
 
466
      InnoDB_IO_r_bytes     => 2,
 
467
      InnoDB_pages_distinct => 20,
 
468
   },
 
469
];
 
470
 
 
471
$ea  = new EventAggregator(
 
472
   groupby => 'fingerprint',
 
473
   worst   => 'Query_time',
 
474
   ignore_attributes => [qw(arg cmd)],
 
475
   type_for => { Thread_id => 'string' },
 
476
);
 
477
foreach my $event (@$events) {
 
478
   $event->{fingerprint} = $qr->fingerprint( $event->{arg} );
 
479
   $ea->aggregate($event);
 
480
}
 
481
$ea->calculate_statistical_metrics();
 
482
 
 
483
$sorted = $qrf->sort_attribs($ea->get_attributes(), $ea);
 
484
is_deeply(
 
485
   $sorted,
 
486
   {
 
487
      num    => [qw(Query_time Lock_time Rows_sent Rows_examined Rows_read Merge_passes bytes)],
 
488
      innodb => [qw(InnoDB_IO_r_bytes InnoDB_pages_distinct)],
 
489
      bool   => [qw(Filesort QC_Hit)],
 
490
      string => [qw(db host Thread_id user)],
 
491
   },
 
492
   'more sort_attribs()'
 
493
) or print Dumper($sorted);
 
494
 
 
495
# ############################################################################
 
496
# Test that --[no]zero-bool removes 0% vals.
 
497
# ############################################################################
 
498
$events = [
 
499
   {  ts            => '071015 21:43:52',
 
500
      cmd           => 'Query',
 
501
      arg           => "SELECT id FROM users WHERE name='foo'",
 
502
      Query_time    => '8.000652',
 
503
      Lock_time     => '0.002300',
 
504
      QC_Hit        => 'No',
 
505
      Filesort      => 'No',
 
506
   },
 
507
   {  ts            => '071015 21:43:52',
 
508
      cmd           => 'Query',
 
509
      arg           => "SELECT id FROM users WHERE name='foo'",
 
510
      Query_time    => '1.001943',
 
511
      Lock_time     => '0.002320',
 
512
      QC_Hit        => 'Yes',
 
513
      Filesort      => 'No',
 
514
   },
 
515
   {  ts            => '071015 21:43:53',
 
516
      cmd           => 'Query',
 
517
      arg           => "SELECT id FROM users WHERE name='bar'",
 
518
      Query_time    => '1.000682',
 
519
      Lock_time     => '0.003301',
 
520
      QC_Hit        => 'Yes',
 
521
      Filesort      => 'No',
 
522
   }
 
523
];
 
524
 
 
525
$ea  = new EventAggregator(
 
526
   groupby => 'fingerprint',
 
527
   worst   => 'Query_time',
 
528
   ignore_attributes => [qw(arg cmd)],
 
529
);
 
530
foreach my $event (@$events) {
 
531
   $event->{fingerprint} = $qr->fingerprint( $event->{arg} );
 
532
   $ea->aggregate($event);
 
533
}
 
534
$ea->calculate_statistical_metrics();
 
535
$result = $qrf->header(
 
536
   ea        => $ea,
 
537
   # select    => [ $ea->get_attributes() ],
 
538
   orderby   => 'Query_time',
 
539
   zero_bool => 0,
 
540
);
 
541
 
 
542
ok(
 
543
   no_diff(
 
544
      $result,
 
545
      "t/lib/samples/QueryReportFormatter/report021.txt",
 
546
      cmd_output => 1,
 
547
   ),
 
548
   'No zero bool vals'
 
549
);
 
550
 
 
551
# #############################################################################
 
552
# Issue 458: mk-query-digest Use of uninitialized value in division (/) at
 
553
# line 3805
 
554
# #############################################################################
 
555
use SlowLogParser;
 
556
my $p = new SlowLogParser();
 
557
 
 
558
sub report_from_file {
 
559
   my $ea2 = new EventAggregator(
 
560
      groupby => 'fingerprint',
 
561
      worst   => 'Query_time',
 
562
   );
 
563
   my ( $file ) = @_;
 
564
   $file = "$trunk/$file";
 
565
   my @e;
 
566
   my @callbacks;
 
567
   push @callbacks, sub {
 
568
      my ( $event ) = @_;
 
569
      my $group_by_val = $event->{arg};
 
570
      return 0 unless defined $group_by_val;
 
571
      $event->{fingerprint} = $qr->fingerprint($group_by_val);
 
572
      return $event;
 
573
   };
 
574
   push @callbacks, sub {
 
575
      $ea2->aggregate(@_);
 
576
   };
 
577
   eval {
 
578
      open my $fh, "<", $file or die "Cannot open $file: $OS_ERROR";
 
579
      my %args = (
 
580
         next_event => sub { return <$fh>;      },
 
581
         tell       => sub { return tell($fh);  },
 
582
      );
 
583
      while ( my $e = $p->parse_event(%args) ) {
 
584
         $_->($e) for @callbacks;
 
585
      }
 
586
      close $fh;
 
587
   };
 
588
   die $EVAL_ERROR if $EVAL_ERROR;
 
589
   $ea2->calculate_statistical_metrics();
 
590
   my %top_spec = (
 
591
      attrib  => 'Query_time',
 
592
      orderby => 'sum',
 
593
      total   => 100,
 
594
      count   => 100,
 
595
   );
 
596
   my ($worst, $other) = $ea2->top_events(%top_spec);
 
597
   my $top_n = scalar @$worst;
 
598
   my $report = '';
 
599
   foreach my $rank ( 1 .. $top_n ) {
 
600
      $report .= $qrf->event_report(
 
601
         ea      => $ea2,
 
602
         # select  => [ $ea2->get_attributes() ],
 
603
         item    => $worst->[$rank - 1]->[0],
 
604
         rank    => $rank,
 
605
         orderby => 'Query_time',
 
606
         reason  => '',
 
607
      );
 
608
   }
 
609
   return $report;
 
610
}
 
611
 
 
612
# The real bug is in QueryReportFormatter, and there's nothing particularly
 
613
# interesting about this sample, but we just want to make sure that the
 
614
# timestamp prop shows up only in the one event.  The bug is that it appears
 
615
eval {
 
616
   report_from_file('t/lib/samples/slowlogs/slow029.txt');
 
617
};
 
618
is(
 
619
   $EVAL_ERROR,
 
620
   '',
 
621
   'event_report() does not die on empty attributes (issue 458)'
 
622
);
 
623
 
 
624
# #############################################################################
 
625
# Test that format_string_list() truncates long strings.
 
626
# #############################################################################
 
627
 
 
628
$events = [
 
629
   {  ts   => '071015 21:43:52',
 
630
      cmd  => 'Query',
 
631
      arg  => "SELECT id FROM users WHERE name='foo'",
 
632
      Query_time => 1,
 
633
      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.",
 
634
   },
 
635
];
 
636
 
 
637
$ea  = new EventAggregator(
 
638
   groupby => 'fingerprint',
 
639
   worst   => 'Query_time',
 
640
   ignore_attributes => [qw(arg cmd)],
 
641
);
 
642
foreach my $event (@$events) {
 
643
   $event->{fingerprint} = $qr->fingerprint( $event->{arg} );
 
644
   $ea->aggregate($event);
 
645
}
 
646
$ea->calculate_statistical_metrics();
 
647
$result = $qrf->event_report(
 
648
   ea      => $ea,
 
649
   select  => [ qw(Query_time foo) ],
 
650
   item    => 'select id from users where name=?',
 
651
   rank    => 1,
 
652
   orderby => 'Query_time',
 
653
   reason  => 'top',
 
654
);
 
655
 
 
656
ok(
 
657
   no_diff(
 
658
      $result,
 
659
      "t/lib/samples/QueryReportFormatter/report010.txt",
 
660
      cmd_output => 1,
 
661
   ),
 
662
   'Truncate one long string'
 
663
);
 
664
 
 
665
$ea->reset_aggregated_data();
 
666
push @$events,
 
667
   {  ts   => '071015 21:43:55',
 
668
      cmd  => 'Query',
 
669
      arg  => "SELECT id FROM users WHERE name='foo'",
 
670
      Query_time => 2,
 
671
      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."
 
672
   };
 
673
 
 
674
foreach my $event (@$events) {
 
675
   $event->{fingerprint} = $qr->fingerprint( $event->{arg} );
 
676
   $ea->aggregate($event);
 
677
}
 
678
$ea->calculate_statistical_metrics();
 
679
$result = $qrf->event_report(
 
680
   ea      => $ea,
 
681
   select  => [ qw(Query_time foo) ],
 
682
   item    => 'select id from users where name=?',
 
683
   rank    => 1,
 
684
   orderby => 'Query_time',
 
685
   reason  => 'top',
 
686
);
 
687
 
 
688
ok(
 
689
   no_diff(
 
690
      $result,
 
691
      "t/lib/samples/QueryReportFormatter/report011.txt",
 
692
      cmd_output => 1,
 
693
   ),
 
694
   'Truncate multiple long strings'
 
695
);
 
696
 
 
697
$ea->reset_aggregated_data();
 
698
push @$events,
 
699
   {  ts   => '071015 21:43:55',
 
700
      cmd  => 'Query',
 
701
      arg  => "SELECT id FROM users WHERE name='foo'",
 
702
      Query_time => 3,
 
703
      foo  => 'Number 3 long string, but I\'ll exceed the line length so I\'ll only show up as "more" :-('
 
704
   };
 
705
 
 
706
foreach my $event (@$events) {
 
707
   $event->{fingerprint} = $qr->fingerprint( $event->{arg} );
 
708
   $ea->aggregate($event);
 
709
}
 
710
$ea->calculate_statistical_metrics();
 
711
$result = $qrf->event_report(
 
712
   ea      => $ea,
 
713
   select  => [ qw(Query_time foo) ],
 
714
   item    => 'select id from users where name=?',
 
715
   rank    => 1,
 
716
   orderby => 'Query_time',
 
717
   reason  => 'top',
 
718
);
 
719
 
 
720
ok(
 
721
   no_diff(
 
722
      $result,
 
723
      "t/lib/samples/QueryReportFormatter/report012.txt",
 
724
      cmd_output => 1,
 
725
   ),
 
726
   'Truncate multiple strings longer than whole line'
 
727
);
 
728
 
 
729
# #############################################################################
 
730
# Issue 478: mk-query-digest doesn't count errors and hosts right
 
731
# #############################################################################
 
732
 
 
733
# We decided that string attribs shouldn't be listed in the global header.
 
734
$events = [
 
735
   {
 
736
      cmd           => 'Query',
 
737
      arg           => "SELECT id FROM users WHERE name='foo'",
 
738
      Query_time    => '8.000652',
 
739
      user          => 'bob',
 
740
   },
 
741
   {
 
742
      cmd           => 'Query',
 
743
      arg           => "SELECT id FROM users WHERE name='foo'",
 
744
      Query_time    => '1.001943',
 
745
      user          => 'bob',
 
746
   },
 
747
   {
 
748
      cmd           => 'Query',
 
749
      arg           => "SELECT id FROM users WHERE name='bar'",
 
750
      Query_time    => '1.000682',
 
751
      user          => 'bob',
 
752
   }
 
753
];
 
754
 
 
755
$ea  = new EventAggregator(
 
756
   groupby => 'fingerprint',
 
757
   worst   => 'Query_time',
 
758
   ignore_attributes => [qw(arg cmd)],
 
759
);
 
760
foreach my $event (@$events) {
 
761
   $event->{fingerprint} = $qr->fingerprint( $event->{arg} );
 
762
   $ea->aggregate($event);
 
763
}
 
764
$ea->calculate_statistical_metrics();
 
765
$result = $qrf->header(
 
766
   ea      => $ea,
 
767
   select  => $ea->get_attributes(),
 
768
   orderby => 'Query_time',
 
769
);
 
770
 
 
771
ok(
 
772
   no_diff(
 
773
      $result,
 
774
      "t/lib/samples/QueryReportFormatter/report022.txt",
 
775
      cmd_output => 1,
 
776
   ),
 
777
   'No string attribs in global report (issue 478)'
 
778
);
 
779
 
 
780
# #############################################################################
 
781
# Issue 744: Option to show all Hosts
 
782
# #############################################################################
 
783
 
 
784
# Don't shorten IP addresses.
 
785
$events = [
 
786
   {
 
787
      cmd        => 'Query',
 
788
      arg        => "foo",
 
789
      Query_time => '8.000652',
 
790
      host       => '123.123.123.456',
 
791
   },
 
792
   {
 
793
      cmd        => 'Query',
 
794
      arg        => "foo",
 
795
      Query_time => '8.000652',
 
796
      host       => '123.123.123.789',
 
797
   },
 
798
];
 
799
 
 
800
$ea  = new EventAggregator(
 
801
   groupby => 'arg',
 
802
   worst   => 'Query_time',
 
803
   ignore_attributes => [qw(arg cmd)],
 
804
);
 
805
foreach my $event (@$events) {
 
806
   $ea->aggregate($event);
 
807
}
 
808
$ea->calculate_statistical_metrics();
 
809
$result = $qrf->event_report(
 
810
   ea      => $ea,
 
811
   select  => [ qw(Query_time host) ],
 
812
   item    => 'foo',
 
813
   rank    => 1,
 
814
   orderby => 'Query_time',
 
815
);
 
816
 
 
817
ok(
 
818
   no_diff(
 
819
      $result,
 
820
      "t/lib/samples/QueryReportFormatter/report013.txt",
 
821
      cmd_output => 1,
 
822
   ),
 
823
   "IPs not shortened"
 
824
);
 
825
 
 
826
# Add another event so we get "... N more" to make sure that IPs
 
827
# are still not shortened.
 
828
push @$events, 
 
829
   {
 
830
      cmd        => 'Query',
 
831
      arg        => "foo",
 
832
      Query_time => '8.000652',
 
833
      host       => '123.123.123.999',
 
834
   };
 
835
$ea->aggregate($events->[-1]);
 
836
$ea->calculate_statistical_metrics();
 
837
$result = $qrf->event_report(
 
838
   ea      => $ea,
 
839
   select  => [ qw(Query_time host) ],
 
840
   item    => 'foo',
 
841
   rank    => 1,
 
842
   orderby => 'Query_time',
 
843
);
 
844
 
 
845
ok(
 
846
   no_diff(
 
847
      $result,
 
848
      "t/lib/samples/QueryReportFormatter/report014.txt",
 
849
      cmd_output => 1,
 
850
   ),
 
851
   "IPs not shortened with more"
 
852
);
 
853
 
 
854
# Test show_all.
 
855
@ARGV = qw(--show-all host);
 
856
$o->get_opts();
 
857
$result = $qrf->event_report(
 
858
   ea       => $ea,
 
859
   select   => [ qw(Query_time host) ],
 
860
   item     => 'foo',
 
861
   rank     => 1,
 
862
   orderby  => 'Query_time',
 
863
);
 
864
 
 
865
ok(
 
866
   no_diff(
 
867
      $result,
 
868
      "t/lib/samples/QueryReportFormatter/report015.txt",
 
869
      cmd_output => 1,
 
870
   ),
 
871
   "Show all hosts"
 
872
);
 
873
 
 
874
# #############################################################################
 
875
# Issue 948: mk-query-digest treats InnoDB_rec_lock_wait value as number
 
876
# instead of time
 
877
# #############################################################################
 
878
 
 
879
$events = [
 
880
   {
 
881
      cmd        => 'Query',
 
882
      arg        => "foo",
 
883
      Query_time => '8.000652',
 
884
      InnoDB_rec_lock_wait => 0.001,
 
885
      InnoDB_IO_r_wait     => 0.002,
 
886
      InnoDB_queue_wait    => 0.003,
 
887
   },
 
888
];
 
889
 
 
890
$ea  = new EventAggregator(
 
891
   groupby => 'arg',
 
892
   worst   => 'Query_time',
 
893
   ignore_attributes => [qw(arg cmd)],
 
894
);
 
895
foreach my $event (@$events) {
 
896
   $ea->aggregate($event);
 
897
}
 
898
$ea->calculate_statistical_metrics();
 
899
$result = $qrf->event_report(
 
900
   ea      => $ea,
 
901
   select  => [ qw(Query_time InnoDB_rec_lock_wait InnoDB_IO_r_wait InnoDB_queue_wait) ],
 
902
   item    => 'foo',
 
903
   rank    => 1,
 
904
   orderby => 'Query_time',
 
905
);
 
906
 
 
907
ok(
 
908
   no_diff(
 
909
      $result,
 
910
      "t/lib/samples/QueryReportFormatter/report016.txt",
 
911
      cmd_output => 1,
 
912
   ),
 
913
   "_wait attribs treated as times (issue 948)"
 
914
);
 
915
 
 
916
# #############################################################################
 
917
# print_reports()
 
918
# #############################################################################
 
919
$events = [
 
920
   {
 
921
      cmd         => 'Query',
 
922
      arg         => "select col from tbl where id=42",
 
923
      fingerprint => "select col from tbl where id=?",
 
924
      Query_time  => '1.000652',
 
925
      Lock_time   => '0.001292',
 
926
      ts          => '071015 21:43:52',
 
927
      pos_in_log  => 123,
 
928
      db          => 'foodb',
 
929
   },
 
930
];
 
931
$ea = new EventAggregator(
 
932
   groupby => 'fingerprint',
 
933
   worst   => 'Query_time',
 
934
);
 
935
foreach my $event ( @$events ) {
 
936
   $ea->aggregate($event);
 
937
}
 
938
$ea->calculate_statistical_metrics(apdex_t=>1);
 
939
 
 
940
# Reset opts in case anything above left something set.
 
941
@ARGV = qw();
 
942
$o->get_opts();
 
943
 
 
944
# Normally, the report subs will make their own ReportFormatter but
 
945
# that package isn't visible to QueryReportFormatter right now so we
 
946
# make ReportFormatters and pass them in.  Since ReporFormatters can't
 
947
# be shared, we can only test one subreport at a time, else the
 
948
# prepared statements subreport will reuse/reprint stuff from the
 
949
# profile subreport.  And the line width is 82 because that's the new
 
950
# default to accommodate the EXPLAIN sparkline (issue 1141).
 
951
my $report = new ReportFormatter(line_width=>82);
 
952
$qrf->set_report_formatter(report=>'profile', formatter=>$report);
 
953
ok(
 
954
   no_diff(
 
955
      sub { $qrf->print_reports(
 
956
         reports    => [qw(header query_report profile)],
 
957
         ea         => $ea,
 
958
         worst      => [['select col from tbl where id=?','top',1]],
 
959
         other      => [],
 
960
         orderby    => 'Query_time',
 
961
         groupby    => 'fingerprint',
 
962
         variations => [qw(arg)],
 
963
      ); },
 
964
      "t/lib/samples/QueryReportFormatter/report001.txt",
 
965
   ),
 
966
   "print_reports(header, query_report, profile)"
 
967
);
 
968
 
 
969
$report = new ReportFormatter(line_width=>82);
 
970
$qrf->set_report_formatter(report=>'profile', formatter=>$report);
 
971
ok(
 
972
   no_diff(
 
973
      sub { $qrf->print_reports(
 
974
         reports    => [qw(profile query_report header)],
 
975
         ea         => $ea,
 
976
         worst      => [['select col from tbl where id=?','top',1]],
 
977
         orderby    => 'Query_time',
 
978
         groupby    => 'fingerprint',
 
979
         variations => [qw(arg)],
 
980
      ); },
 
981
      "t/lib/samples/QueryReportFormatter/report003.txt",
 
982
   ),
 
983
   "print_reports(profile, query_report, header)",
 
984
);
 
985
 
 
986
$events = [
 
987
   {
 
988
      Query_time    => '0.000286',
 
989
      Warning_count => 0,
 
990
      arg           => 'PREPARE SELECT i FROM d.t WHERE i=?',
 
991
      fingerprint   => 'prepare select i from d.t where i=?',
 
992
      bytes         => 35,
 
993
      cmd           => 'Query',
 
994
      db            => undef,
 
995
      pos_in_log    => 0,
 
996
      ts            => '091208 09:23:49.637394',
 
997
      Statement_id  => 2,
 
998
   },
 
999
   {
 
1000
      Query_time    => '0.030281',
 
1001
      Warning_count => 0,
 
1002
      arg           => 'EXECUTE SELECT i FROM d.t WHERE i="3"',
 
1003
      fingerprint   => 'execute select i from d.t where i=?',
 
1004
      bytes         => 37,
 
1005
      cmd           => 'Query',
 
1006
      db            => undef,
 
1007
      pos_in_log    => 1106,
 
1008
      ts            => '091208 09:23:49.637892',
 
1009
      Statement_id  => 2,
 
1010
   },
 
1011
];
 
1012
$ea = new EventAggregator(
 
1013
   groupby => 'fingerprint',
 
1014
   worst   => 'Query_time',
 
1015
);
 
1016
foreach my $event ( @$events ) {
 
1017
   $ea->aggregate($event);
 
1018
}
 
1019
$ea->calculate_statistical_metrics();
 
1020
$report = new ReportFormatter(
 
1021
   line_width   => 82,
 
1022
   extend_right => 1,
 
1023
);
 
1024
$qrf->set_report_formatter(report=>'prepared', formatter=>$report);
 
1025
ok(
 
1026
   no_diff(
 
1027
      sub {
 
1028
         $qrf->print_reports(
 
1029
            reports => ['query_report','prepared'],
 
1030
            ea      => $ea,
 
1031
            worst   => [
 
1032
               ['execute select i from d.t where i=?', 'top',1],
 
1033
               ['prepare select i from d.t where i=?', 'top',2],
 
1034
            ],
 
1035
            orderby    => 'Query_time',
 
1036
            groupby    => 'fingerprint',
 
1037
            variations => [qw(arg)],
 
1038
         );
 
1039
      },
 
1040
      "t/lib/samples/QueryReportFormatter/report002.txt",
 
1041
   ),
 
1042
   "print_reports(query_report, prepared)"
 
1043
);
 
1044
 
 
1045
push @$events,
 
1046
   {
 
1047
      Query_time    => '1.030281',
 
1048
      arg           => 'update foo set col=1 where 1',
 
1049
      fingerprint   => 'update foo set col=? where ?',
 
1050
      bytes         => 37,
 
1051
      cmd           => 'Query',
 
1052
      pos_in_log    => 100,
 
1053
      ts            => '091208 09:23:49.637892',
 
1054
   },
 
1055
$ea = new EventAggregator(
 
1056
   groupby => 'fingerprint',
 
1057
   worst   => 'Query_time',
 
1058
);
 
1059
foreach my $event ( @$events ) {
 
1060
   $ea->aggregate($event);
 
1061
}
 
1062
$ea->calculate_statistical_metrics();
 
1063
$report = new ReportFormatter(
 
1064
   line_width   => 82,
 
1065
   extend_right => 1,
 
1066
);
 
1067
$qrf->set_report_formatter(report=>'profile', formatter=>$report);
 
1068
ok(
 
1069
   no_diff(
 
1070
      sub {
 
1071
         $qrf->print_reports(
 
1072
            reports => ['profile'],
 
1073
            ea      => $ea,
 
1074
            worst   => [
 
1075
               ['update foo set col=? where ?', 'top',1]
 
1076
            ],
 
1077
            other => [
 
1078
               ['execute select i from d.t where i=?','misc',2],
 
1079
               ['prepare select i from d.t where i=?','misc',3],
 
1080
            ],
 
1081
            orderby => 'Query_time',
 
1082
            groupby => 'fingerprint',
 
1083
         );
 
1084
      },
 
1085
      "t/lib/samples/QueryReportFormatter/report004.txt",
 
1086
   ),
 
1087
   "MISC items in profile"
 
1088
);
 
1089
 
 
1090
# #############################################################################
 
1091
# EXPLAIN report
 
1092
# #############################################################################
 
1093
SKIP: {
 
1094
   skip 'Cannot connect to sandbox master', 3 unless $dbh;
 
1095
   $sb->load_file('master', "t/lib/samples/QueryReportFormatter/table.sql");
 
1096
 
 
1097
   @ARGV = qw(--explain F=/tmp/12345/my.sandbox.cnf);
 
1098
   $o->get_opts();
 
1099
 
 
1100
   my $qrf = new QueryReportFormatter(
 
1101
      OptionParser    => $o,
 
1102
      QueryRewriter   => $qr,
 
1103
      QueryParser     => $qp,
 
1104
      Quoter          => $q, 
 
1105
      dbh             => $dbh,
 
1106
      ExplainAnalyzer => $ex,
 
1107
   );
 
1108
 
 
1109
   my $explain = load_file(
 
1110
      $sandbox_version ge '5.1'
 
1111
         ? "t/lib/samples/QueryReportFormatter/report025.txt"
 
1112
         : "t/lib/samples/QueryReportFormatter/report026.txt");
 
1113
 
 
1114
   is(
 
1115
      $qrf->explain_report("select * from qrf.t where i=2", 'qrf'),
 
1116
      $explain,
 
1117
      "explain_report()"
 
1118
   );
 
1119
 
 
1120
   my $arg = "select t1.i from t as t1 join t as t2 where t1.i < t2.i and t1.v is not null order by t1.i";
 
1121
   my $fingerprint = $qr->fingerprint($arg);
 
1122
 
 
1123
   $events = [
 
1124
      {
 
1125
         Query_time    => '0.000286',
 
1126
         arg           => $arg,
 
1127
         fingerprint   => $fingerprint,
 
1128
         bytes         => length $arg,
 
1129
         cmd           => 'Query',
 
1130
         db            => 'qrf',
 
1131
         pos_in_log    => 0,
 
1132
         ts            => '091208 09:23:49.637394',
 
1133
      },
 
1134
   ];
 
1135
   $ea = new EventAggregator(
 
1136
      groupby => 'fingerprint',
 
1137
      worst   => 'Query_time',
 
1138
   );
 
1139
   foreach my $event ( @$events ) {
 
1140
      $ea->aggregate($event);
 
1141
   }
 
1142
   $ea->calculate_statistical_metrics();
 
1143
 
 
1144
   # Make sure that explain_sparkline() does USE db like explain_report()
 
1145
   # does because by mqd defaults expalin_sparline() is called by profile()
 
1146
   # so if it doesn't USE db then the EXPLAIN will fail.  Here we reset
 
1147
   # the db to something else because we already called explain_report()
 
1148
   # above which did USE qrf.
 
1149
   $dbh->do("USE mysql");
 
1150
   my $explain_sparkline = $qrf->explain_sparkline($arg, 'qrf');
 
1151
   is(
 
1152
      $explain_sparkline,
 
1153
      "TF>aI",
 
1154
      "explain_sparkling() uses db"
 
1155
   );
 
1156
 
 
1157
   $report = new ReportFormatter(
 
1158
      line_width   => 82,
 
1159
      extend_right => 1,
 
1160
   );
 
1161
   $qrf->set_report_formatter(report=>'profile', formatter=>$report);
 
1162
   $dbh->do("USE mysql");  # same reason as above ^; force use db from event
 
1163
   ok(
 
1164
      no_diff(
 
1165
         sub {
 
1166
            $qrf->print_reports(
 
1167
               reports => ['profile', 'query_report'],
 
1168
               ea      => $ea,
 
1169
               worst   => [ [$fingerprint, 'top',  1], ],
 
1170
               other   => [ [$fingerprint, 'misc', 2], ],
 
1171
               orderby => 'Query_time',
 
1172
               groupby => 'fingerprint',
 
1173
            );
 
1174
         },
 
1175
         ($sandbox_version ge '5.1' ?
 
1176
              "t/lib/samples/QueryReportFormatter/report027.txt"
 
1177
            : "t/lib/samples/QueryReportFormatter/report029.txt"),
 
1178
      ),
 
1179
      "EXPLAIN sparkline (issue 1141)"
 
1180
   );
 
1181
 
 
1182
   $sb->wipe_clean($dbh);
 
1183
   $dbh->disconnect();
 
1184
}
 
1185
 
 
1186
# #############################################################################
 
1187
# files and date reports.
 
1188
# #############################################################################
 
1189
like(
 
1190
   $qrf->date(),
 
1191
   qr/# Current date: .+?\d+:\d+:\d+/,
 
1192
   "date report"
 
1193
);
 
1194
 
 
1195
is(
 
1196
   $qrf->files(files=>[qw(foo bar)]),
 
1197
   "# Files: foo, bar\n",
 
1198
   "files report"
 
1199
);
 
1200
 
 
1201
like(
 
1202
   $qrf->hostname(),
 
1203
   qr/# Hostname: .+?/,
 
1204
   "hostname report"
 
1205
);
 
1206
 
 
1207
# #############################################################################
 
1208
# Test report grouping.
 
1209
# #############################################################################
 
1210
$events = [
 
1211
   {
 
1212
      cmd         => 'Query',
 
1213
      arg         => "select col from tbl where id=42",
 
1214
      fingerprint => "select col from tbl where id=?",
 
1215
      Query_time  => '1.000652',
 
1216
      Lock_time   => '0.001292',
 
1217
      ts          => '071015 21:43:52',
 
1218
      pos_in_log  => 123,
 
1219
      db          => 'foodb',
 
1220
   },
 
1221
];
 
1222
$ea = new EventAggregator(
 
1223
   groupby => 'fingerprint',
 
1224
   worst   => 'Query_time',
 
1225
);
 
1226
foreach my $event ( @$events ) {
 
1227
   $ea->aggregate($event);
 
1228
}
 
1229
$ea->calculate_statistical_metrics();
 
1230
@ARGV = qw();
 
1231
$o->get_opts();
 
1232
$report = new ReportFormatter(line_width=>82);
 
1233
$qrf    = new QueryReportFormatter(
 
1234
   OptionParser    => $o,
 
1235
   QueryRewriter   => $qr,
 
1236
   QueryParser     => $qp,
 
1237
   Quoter          => $q, 
 
1238
   ExplainAnalyzer => $ex,
 
1239
);
 
1240
$qrf->set_report_formatter(report=>'profile', formatter=>$report);
 
1241
my $output = output(
 
1242
   sub { $qrf->print_reports(
 
1243
      reports => [qw(rusage date files header query_report profile)],
 
1244
      ea      => $ea,
 
1245
      worst   => [['select col from tbl where id=?','top',1]],
 
1246
      orderby => 'Query_time',
 
1247
      groupby => 'fingerprint',
 
1248
      files   => [qw(foo bar)],
 
1249
      group   => {map {$_=>1} qw(rusage date files header)},
 
1250
   ); }
 
1251
);
 
1252
like(
 
1253
   $output,
 
1254
   qr/
 
1255
^#\s.+?\suser time.+?vsz$
 
1256
^#\sCurrent date:.+?$
 
1257
^#\sFiles:\sfoo,\sbar$
 
1258
   /mx,
 
1259
   "grouped reports"
 
1260
);
 
1261
 
 
1262
# #############################################################################
 
1263
# Issue 1124: Make mk-query-digest profile include variance-to-mean ratio
 
1264
# #############################################################################
 
1265
 
 
1266
$events = [
 
1267
   {
 
1268
      Query_time    => "1.000000",
 
1269
      arg           => "select c from t where id=1",
 
1270
      fingerprint   => "select c from t where id=?",
 
1271
      cmd           => 'Query',
 
1272
      pos_in_log    => 0,
 
1273
   },
 
1274
   {
 
1275
      Query_time    => "5.500000",
 
1276
      arg           => "select c from t where id=2",
 
1277
      fingerprint   => "select c from t where id=?",
 
1278
      cmd           => 'Query',
 
1279
      pos_in_log    => 0,
 
1280
   },
 
1281
   {
 
1282
      Query_time    => "2.000000",
 
1283
      arg           => "select c from t where id=3",
 
1284
      fingerprint   => "select c from t where id=?",
 
1285
      cmd           => 'Query',
 
1286
      pos_in_log    => 0,
 
1287
   },
 
1288
   {
 
1289
      Query_time    => "9.000000",
 
1290
      arg           => "select c from t where id=4",
 
1291
      fingerprint   => "select c from t where id=?",
 
1292
      cmd           => 'Query',
 
1293
      pos_in_log    => 0,
 
1294
   },
 
1295
];
 
1296
$ea = new EventAggregator(
 
1297
   groupby => 'fingerprint',
 
1298
   worst   => 'Query_time',
 
1299
);
 
1300
foreach my $event ( @$events ) {
 
1301
   $ea->aggregate($event);
 
1302
}
 
1303
$ea->calculate_statistical_metrics();
 
1304
$report = new ReportFormatter(
 
1305
   line_width   => 82,
 
1306
   extend_right => 1,
 
1307
);
 
1308
$qrf->set_report_formatter(report=>'profile', formatter=>$report);
 
1309
ok(
 
1310
   no_diff(
 
1311
      sub {
 
1312
         $qrf->print_reports(
 
1313
            reports => ['profile'],
 
1314
            ea      => $ea,
 
1315
            worst   => [
 
1316
               ['select c from t where id=?', 'top',1],
 
1317
            ],
 
1318
            orderby => 'Query_time',
 
1319
            groupby => 'fingerprint',
 
1320
         );
 
1321
      },
 
1322
      "t/lib/samples/QueryReportFormatter/report005.txt",
 
1323
   ),
 
1324
   "Variance-to-mean ration (issue 1124)"
 
1325
);
 
1326
 
 
1327
# #############################################################################
 
1328
# Issue 1141: Add "spark charts" to mk-query-digest profile
 
1329
# #############################################################################
 
1330
sub proc_events {
 
1331
   my ( %args ) = @_;
 
1332
   my ($arg, $attrib, $vals) = @args{qw(arg attrib vals)};
 
1333
 
 
1334
   my $bytes       = length $arg;
 
1335
   my $fingerprint = $qr->fingerprint($arg);
 
1336
 
 
1337
   $events = [];
 
1338
   foreach my $val ( @$vals ) {
 
1339
      push @$events, {
 
1340
         bytes       => $bytes,
 
1341
         arg         => $arg,
 
1342
         fingerprint => $fingerprint,
 
1343
         $attrib     => $val,
 
1344
      }
 
1345
   }
 
1346
 
 
1347
   $ea = new EventAggregator(
 
1348
      groupby => 'fingerprint',
 
1349
      worst   => 'Query_time',
 
1350
   );
 
1351
   foreach my $event (@$events) {
 
1352
      $ea->aggregate($event);
 
1353
   }
 
1354
   $ea->calculate_statistical_metrics(apdex_t=>1);
 
1355
 
 
1356
   # Seeing the full chart helps determine what the
 
1357
   # sparkline should look like.
 
1358
   if ( $args{chart} ) {
 
1359
      $result = $qrf->chart_distro(
 
1360
         ea     => $ea,
 
1361
         item   => 'select c from t',
 
1362
         attrib => 'Query_time',
 
1363
      );
 
1364
      print $result;
 
1365
   }
 
1366
 
 
1367
   return;
 
1368
};
 
1369
 
 
1370
# Test sparklines in isolation.
 
1371
proc_events(
 
1372
   arg    => 'select c from t',
 
1373
   attrib => 'Query_time',
 
1374
   vals   => [qw(0 0 0)],
 
1375
);
 
1376
$result = $qrf->distro_sparkline(
 
1377
   ea     => $ea,
 
1378
   item   => 'select c from t',
 
1379
   attrib => 'Query_time',
 
1380
);
 
1381
is(
 
1382
   $result,
 
1383
   "        ",
 
1384
   "Sparkchart line - all zeros"
 
1385
);
 
1386
 
 
1387
#   1us
 
1388
#  10us
 
1389
# 100us  ################################################
 
1390
#   1ms  ################################
 
1391
#  10ms  ################################
 
1392
# 100ms  ################################################################
 
1393
#    1s  ################
 
1394
#  10s+
 
1395
proc_events(
 
1396
   arg    => 'select c from t',
 
1397
   attrib => 'Query_time',
 
1398
   vals   => [qw(0.100000 0.500000 0.000600 0.008000 0.990000 1.000000 0.400000 0.003000 0.000200 0.000100 0.010000 0.020000)],
 
1399
);
 
1400
$result = $qrf->distro_sparkline(
 
1401
   ea     => $ea,
 
1402
   item   => 'select c from t',
 
1403
   attrib => 'Query_time',
 
1404
);
 
1405
is(
 
1406
   $result,
 
1407
   "  -..^_ ",
 
1408
   "Sparkchart line 1"
 
1409
);
 
1410
 
 
1411
#   1us
 
1412
#  10us
 
1413
# 100us
 
1414
#   1ms
 
1415
#  10ms  ################################
 
1416
# 100ms  ################################################################
 
1417
#    1s  ########
 
1418
#  10s+
 
1419
proc_events(
 
1420
   arg    => 'select c from t',
 
1421
   attrib => 'Query_time',
 
1422
   vals   => [qw(0.01 0.03 0.08 0.09 0.3 0.5 0.5 0.6 0.7 0.5 0.5 0.9 1.0)],
 
1423
);
 
1424
$result = $qrf->distro_sparkline(
 
1425
   ea     => $ea,
 
1426
   item   => 'select c from t',
 
1427
   attrib => 'Query_time',
 
1428
);
 
1429
is(
 
1430
   $result,
 
1431
   "    .^_ ",
 
1432
   "Sparkchart line 2"
 
1433
);
 
1434
 
 
1435
#   1us  ################################################################
 
1436
#  10us  ################################################################
 
1437
# 100us  ################################################################
 
1438
#   1ms  ################################################################
 
1439
#  10ms  ################################################################
 
1440
# 100ms  ################################################################
 
1441
#    1s  ################################################################
 
1442
#  10s+
 
1443
proc_events(
 
1444
   arg    => 'select c from t',
 
1445
   attrib => 'Query_time',
 
1446
   vals   => [qw(0.000003 0.000030 0.000300 0.003000 0.030000 0.300000 3)],
 
1447
);
 
1448
$result = $qrf->distro_sparkline(
 
1449
   ea     => $ea,
 
1450
   item   => 'select c from t',
 
1451
   attrib => 'Query_time',
 
1452
);
 
1453
is(
 
1454
   $result,
 
1455
   "^^^^^^^ ",
 
1456
   "Sparkchart line - vals in all ranges except 10s+"
 
1457
);
 
1458
 
 
1459
 
 
1460
#   1us  ################################################################
 
1461
#  10us  ################################################################
 
1462
# 100us
 
1463
#   1ms
 
1464
#  10ms
 
1465
# 100ms
 
1466
#    1s  ################################################################
 
1467
#  10s+  ################################################################
 
1468
proc_events(
 
1469
   arg    => 'select c from t',
 
1470
   attrib => 'Query_time',
 
1471
   vals   => [qw(0.000003 0.000030 0.000003 0.000030 3 3 30 30)],
 
1472
);
 
1473
$result = $qrf->distro_sparkline(
 
1474
   ea     => $ea,
 
1475
   item   => 'select c from t',
 
1476
   attrib => 'Query_time',
 
1477
);
 
1478
is(
 
1479
   $result,
 
1480
   "^^    ^^",
 
1481
   "Sparkchart line - twin peaks"
 
1482
);
 
1483
 
 
1484
# Test that that ^ sparkchart appears in the event header properly.
 
1485
$result = $qrf->event_report(
 
1486
   ea      => $ea,
 
1487
   select  => [ qw(Query_time) ],
 
1488
   item    => 'select c from t',
 
1489
   rank    => 1,
 
1490
   orderby => 'Query_time',
 
1491
   reason  => 'top',
 
1492
);
 
1493
ok(
 
1494
   no_diff(
 
1495
      $result,
 
1496
      "t/lib/samples/QueryReportFormatter/report028.txt",
 
1497
      cmd_output => 1,
 
1498
   ),
 
1499
   'Sparkchart in event header'
 
1500
);
 
1501
 
 
1502
# #############################################################################
 
1503
# Done.
 
1504
# #############################################################################
 
1505
$output = '';
 
1506
{
 
1507
   local *STDERR;
 
1508
   open STDERR, '>', \$output;
 
1509
   $qrf->_d('Complete test coverage');
 
1510
}
 
1511
like(
 
1512
   $output,
 
1513
   qr/Complete test coverage/,
 
1514
   '_d() works'
 
1515
);
 
1516
exit;