mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-11 13:40:07 +00:00
Updated some files that still used the old ReportFormatter
This commit is contained in:
@@ -2641,8 +2641,7 @@ sub _d {
|
|||||||
{
|
{
|
||||||
package ReportFormatter;
|
package ReportFormatter;
|
||||||
|
|
||||||
use strict;
|
use Mo;
|
||||||
use warnings FATAL => 'all';
|
|
||||||
use English qw(-no_match_vars);
|
use English qw(-no_match_vars);
|
||||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||||
|
|
||||||
@@ -2652,40 +2651,102 @@ use POSIX qw(ceil);
|
|||||||
eval { require Term::ReadKey };
|
eval { require Term::ReadKey };
|
||||||
my $have_term = $EVAL_ERROR ? 0 : 1;
|
my $have_term = $EVAL_ERROR ? 0 : 1;
|
||||||
|
|
||||||
sub new {
|
|
||||||
my ( $class, %args ) = @_;
|
|
||||||
my @required_args = qw();
|
|
||||||
foreach my $arg ( @required_args ) {
|
|
||||||
die "I need a $arg argument" unless $args{$arg};
|
|
||||||
}
|
|
||||||
my $self = {
|
|
||||||
underline_header => 1,
|
|
||||||
line_prefix => '# ',
|
|
||||||
line_width => 78,
|
|
||||||
column_spacing => ' ',
|
|
||||||
extend_right => 0,
|
|
||||||
truncate_line_mark => '...',
|
|
||||||
column_errors => 'warn',
|
|
||||||
truncate_header_side => 'left',
|
|
||||||
strip_whitespace => 1,
|
|
||||||
%args, # args above can be overriden, args below cannot
|
|
||||||
n_cols => 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
if ( ($self->{line_width} || '') eq 'auto' ) {
|
has underline_header => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Bool',
|
||||||
|
default => sub { 1 },
|
||||||
|
);
|
||||||
|
has line_prefix => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { '# ' },
|
||||||
|
);
|
||||||
|
has line_width => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Int',
|
||||||
|
default => sub { 78 },
|
||||||
|
);
|
||||||
|
has column_spacing => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { ' ' },
|
||||||
|
);
|
||||||
|
has extend_right => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Bool',
|
||||||
|
default => sub { '' },
|
||||||
|
);
|
||||||
|
has truncate_line_mark => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { '...' },
|
||||||
|
);
|
||||||
|
has column_errors => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { 'warn' },
|
||||||
|
);
|
||||||
|
has truncate_header_side => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { 'left' },
|
||||||
|
);
|
||||||
|
has strip_whitespace => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Bool',
|
||||||
|
default => sub { 1 },
|
||||||
|
);
|
||||||
|
has title => (
|
||||||
|
is => 'rw',
|
||||||
|
isa => 'Str',
|
||||||
|
predicate => 'has_title',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
has n_cols => (
|
||||||
|
is => 'rw',
|
||||||
|
isa => 'Int',
|
||||||
|
default => sub { 0 },
|
||||||
|
init_arg => undef,
|
||||||
|
);
|
||||||
|
|
||||||
|
has cols => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'ArrayRef',
|
||||||
|
init_arg => undef,
|
||||||
|
default => sub { [] },
|
||||||
|
clearer => 'clear_cols',
|
||||||
|
);
|
||||||
|
|
||||||
|
has lines => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'ArrayRef',
|
||||||
|
init_arg => undef,
|
||||||
|
default => sub { [] },
|
||||||
|
clearer => 'clear_lines',
|
||||||
|
);
|
||||||
|
|
||||||
|
has truncate_headers => (
|
||||||
|
is => 'rw',
|
||||||
|
isa => 'Bool',
|
||||||
|
default => sub { undef },
|
||||||
|
init_arg => undef,
|
||||||
|
clearer => 'clear_truncate_headers',
|
||||||
|
);
|
||||||
|
|
||||||
|
sub BUILDARGS {
|
||||||
|
my $class = shift;
|
||||||
|
my $args = $class->SUPER::BUILDARGS(@_);
|
||||||
|
|
||||||
|
if ( ($args->{line_width} || '') eq 'auto' ) {
|
||||||
die "Cannot auto-detect line width because the Term::ReadKey module "
|
die "Cannot auto-detect line width because the Term::ReadKey module "
|
||||||
. "is not installed" unless $have_term;
|
. "is not installed" unless $have_term;
|
||||||
($self->{line_width}) = GetTerminalSize();
|
($args->{line_width}) = GetTerminalSize();
|
||||||
}
|
PTDEBUG && _d('Line width:', $args->{line_width});
|
||||||
PTDEBUG && _d('Line width:', $self->{line_width});
|
|
||||||
|
|
||||||
return bless $self, $class;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub set_title {
|
return $args;
|
||||||
my ( $self, $title ) = @_;
|
|
||||||
$self->{title} = $title;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub set_columns {
|
sub set_columns {
|
||||||
@@ -2701,7 +2762,7 @@ sub set_columns {
|
|||||||
die "Column does not have a name" unless defined $col_name;
|
die "Column does not have a name" unless defined $col_name;
|
||||||
|
|
||||||
if ( $col->{width} ) {
|
if ( $col->{width} ) {
|
||||||
$col->{width_pct} = ceil(($col->{width} * 100) / $self->{line_width});
|
$col->{width_pct} = ceil(($col->{width} * 100) / $self->line_width());
|
||||||
PTDEBUG && _d('col:', $col_name, 'width:', $col->{width}, 'chars =',
|
PTDEBUG && _d('col:', $col_name, 'width:', $col->{width}, 'chars =',
|
||||||
$col->{width_pct}, '%');
|
$col->{width_pct}, '%');
|
||||||
}
|
}
|
||||||
@@ -2728,10 +2789,10 @@ sub set_columns {
|
|||||||
|
|
||||||
$col->{right_most} = 1 if $i == $#cols;
|
$col->{right_most} = 1 if $i == $#cols;
|
||||||
|
|
||||||
push @{$self->{cols}}, $col;
|
push @{$self->cols}, $col;
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->{n_cols} = scalar @cols;
|
$self->n_cols( scalar @cols );
|
||||||
|
|
||||||
if ( ($used_width || 0) > 100 ) {
|
if ( ($used_width || 0) > 100 ) {
|
||||||
die "Total width_pct for all columns is >100%";
|
die "Total width_pct for all columns is >100%";
|
||||||
@@ -2741,15 +2802,15 @@ sub set_columns {
|
|||||||
my $wid_per_col = int((100 - $used_width) / scalar @auto_width_cols);
|
my $wid_per_col = int((100 - $used_width) / scalar @auto_width_cols);
|
||||||
PTDEBUG && _d('Line width left:', (100-$used_width), '%;',
|
PTDEBUG && _d('Line width left:', (100-$used_width), '%;',
|
||||||
'each auto width col:', $wid_per_col, '%');
|
'each auto width col:', $wid_per_col, '%');
|
||||||
map { $self->{cols}->[$_]->{width_pct} = $wid_per_col } @auto_width_cols;
|
map { $self->cols->[$_]->{width_pct} = $wid_per_col } @auto_width_cols;
|
||||||
}
|
}
|
||||||
|
|
||||||
$min_hdr_wid += ($self->{n_cols} - 1) * length $self->{column_spacing};
|
$min_hdr_wid += ($self->n_cols() - 1) * length $self->column_spacing();
|
||||||
PTDEBUG && _d('min header width:', $min_hdr_wid);
|
PTDEBUG && _d('min header width:', $min_hdr_wid);
|
||||||
if ( $min_hdr_wid > $self->{line_width} ) {
|
if ( $min_hdr_wid > $self->line_width() ) {
|
||||||
PTDEBUG && _d('Will truncate headers because min header width',
|
PTDEBUG && _d('Will truncate headers because min header width',
|
||||||
$min_hdr_wid, '> line width', $self->{line_width});
|
$min_hdr_wid, '> line width', $self->line_width());
|
||||||
$self->{truncate_headers} = 1;
|
$self->truncate_headers(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -2758,14 +2819,14 @@ sub set_columns {
|
|||||||
sub add_line {
|
sub add_line {
|
||||||
my ( $self, @vals ) = @_;
|
my ( $self, @vals ) = @_;
|
||||||
my $n_vals = scalar @vals;
|
my $n_vals = scalar @vals;
|
||||||
if ( $n_vals != $self->{n_cols} ) {
|
if ( $n_vals != $self->n_cols() ) {
|
||||||
$self->_column_error("Number of values $n_vals does not match "
|
$self->_column_error("Number of values $n_vals does not match "
|
||||||
. "number of columns $self->{n_cols}");
|
. "number of columns " . $self->n_cols());
|
||||||
}
|
}
|
||||||
for my $i ( 0..($n_vals-1) ) {
|
for my $i ( 0..($n_vals-1) ) {
|
||||||
my $col = $self->{cols}->[$i];
|
my $col = $self->cols->[$i];
|
||||||
my $val = defined $vals[$i] ? $vals[$i] : $col->{undef_value};
|
my $val = defined $vals[$i] ? $vals[$i] : $col->{undef_value};
|
||||||
if ( $self->{strip_whitespace} ) {
|
if ( $self->strip_whitespace() ) {
|
||||||
$val =~ s/^\s+//g;
|
$val =~ s/^\s+//g;
|
||||||
$val =~ s/\s+$//;
|
$val =~ s/\s+$//;
|
||||||
$vals[$i] = $val;
|
$vals[$i] = $val;
|
||||||
@@ -2774,7 +2835,7 @@ sub add_line {
|
|||||||
$col->{min_val} = min($width, ($col->{min_val} || $width));
|
$col->{min_val} = min($width, ($col->{min_val} || $width));
|
||||||
$col->{max_val} = max($width, ($col->{max_val} || $width));
|
$col->{max_val} = max($width, ($col->{max_val} || $width));
|
||||||
}
|
}
|
||||||
push @{$self->{lines}}, \@vals;
|
push @{$self->lines}, \@vals;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2782,26 +2843,28 @@ sub get_report {
|
|||||||
my ( $self, %args ) = @_;
|
my ( $self, %args ) = @_;
|
||||||
|
|
||||||
$self->_calculate_column_widths();
|
$self->_calculate_column_widths();
|
||||||
$self->_truncate_headers() if $self->{truncate_headers};
|
if ( $self->truncate_headers() ) {
|
||||||
|
$self->_truncate_headers();
|
||||||
|
}
|
||||||
$self->_truncate_line_values(%args);
|
$self->_truncate_line_values(%args);
|
||||||
|
|
||||||
my @col_fmts = $self->_make_column_formats();
|
my @col_fmts = $self->_make_column_formats();
|
||||||
my $fmt = ($self->{line_prefix} || '')
|
my $fmt = $self->line_prefix()
|
||||||
. join($self->{column_spacing}, @col_fmts);
|
. join($self->column_spacing(), @col_fmts);
|
||||||
PTDEBUG && _d('Format:', $fmt);
|
PTDEBUG && _d('Format:', $fmt);
|
||||||
|
|
||||||
(my $hdr_fmt = $fmt) =~ s/%([^-])/%-$1/g;
|
(my $hdr_fmt = $fmt) =~ s/%([^-])/%-$1/g;
|
||||||
|
|
||||||
my @lines;
|
my @lines;
|
||||||
push @lines, sprintf "$self->{line_prefix}$self->{title}" if $self->{title};
|
push @lines, $self->line_prefix() . $self->title() if $self->has_title();
|
||||||
push @lines, $self->_truncate_line(
|
push @lines, $self->_truncate_line(
|
||||||
sprintf($hdr_fmt, map { $_->{name} } @{$self->{cols}}),
|
sprintf($hdr_fmt, map { $_->{name} } @{$self->cols}),
|
||||||
strip => 1,
|
strip => 1,
|
||||||
mark => '',
|
mark => '',
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( $self->{underline_header} ) {
|
if ( $self->underline_header() ) {
|
||||||
my @underlines = map { '=' x $_->{print_width} } @{$self->{cols}};
|
my @underlines = map { '=' x $_->{print_width} } @{$self->cols};
|
||||||
push @lines, $self->_truncate_line(
|
push @lines, $self->_truncate_line(
|
||||||
sprintf($fmt, map { $_ || '' } @underlines),
|
sprintf($fmt, map { $_ || '' } @underlines),
|
||||||
mark => '',
|
mark => '',
|
||||||
@@ -2812,19 +2875,23 @@ sub get_report {
|
|||||||
my $vals = $_;
|
my $vals = $_;
|
||||||
my $i = 0;
|
my $i = 0;
|
||||||
my @vals = map {
|
my @vals = map {
|
||||||
my $val = defined $_ ? $_ : $self->{cols}->[$i++]->{undef_value};
|
my $val = defined $_ ? $_ : $self->cols->[$i++]->{undef_value};
|
||||||
$val = '' if !defined $val;
|
$val = '' if !defined $val;
|
||||||
$val =~ s/\n/ /g;
|
$val =~ s/\n/ /g;
|
||||||
$val;
|
$val;
|
||||||
} @$vals;
|
} @$vals;
|
||||||
my $line = sprintf($fmt, @vals);
|
my $line = sprintf($fmt, @vals);
|
||||||
if ( $self->{extend_right} ) {
|
if ( $self->extend_right() ) {
|
||||||
$line;
|
$line;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$self->_truncate_line($line);
|
$self->_truncate_line($line);
|
||||||
}
|
}
|
||||||
} @{$self->{lines}};
|
} @{$self->lines};
|
||||||
|
|
||||||
|
$self->clear_cols();
|
||||||
|
$self->clear_lines();
|
||||||
|
$self->clear_truncate_headers();
|
||||||
|
|
||||||
return join("\n", @lines) . "\n";
|
return join("\n", @lines) . "\n";
|
||||||
}
|
}
|
||||||
@@ -2832,7 +2899,7 @@ sub get_report {
|
|||||||
sub truncate_value {
|
sub truncate_value {
|
||||||
my ( $self, $col, $val, $width, $side ) = @_;
|
my ( $self, $col, $val, $width, $side ) = @_;
|
||||||
return $val if length $val <= $width;
|
return $val if length $val <= $width;
|
||||||
return $val if $col->{right_most} && $self->{extend_right};
|
return $val if $col->{right_most} && $self->extend_right();
|
||||||
$side ||= $col->{truncate_side};
|
$side ||= $col->{truncate_side};
|
||||||
my $mark = $col->{truncate_mark};
|
my $mark = $col->{truncate_mark};
|
||||||
if ( $side eq 'right' ) {
|
if ( $side eq 'right' ) {
|
||||||
@@ -2852,8 +2919,8 @@ sub _calculate_column_widths {
|
|||||||
my ( $self ) = @_;
|
my ( $self ) = @_;
|
||||||
|
|
||||||
my $extra_space = 0;
|
my $extra_space = 0;
|
||||||
foreach my $col ( @{$self->{cols}} ) {
|
foreach my $col ( @{$self->cols} ) {
|
||||||
my $print_width = int($self->{line_width} * ($col->{width_pct} / 100));
|
my $print_width = int($self->line_width() * ($col->{width_pct} / 100));
|
||||||
|
|
||||||
PTDEBUG && _d('col:', $col->{name}, 'width pct:', $col->{width_pct},
|
PTDEBUG && _d('col:', $col->{name}, 'width pct:', $col->{width_pct},
|
||||||
'char width:', $print_width,
|
'char width:', $print_width,
|
||||||
@@ -2877,7 +2944,7 @@ sub _calculate_column_widths {
|
|||||||
|
|
||||||
PTDEBUG && _d('Extra space:', $extra_space);
|
PTDEBUG && _d('Extra space:', $extra_space);
|
||||||
while ( $extra_space-- ) {
|
while ( $extra_space-- ) {
|
||||||
foreach my $col ( @{$self->{cols}} ) {
|
foreach my $col ( @{$self->cols} ) {
|
||||||
if ( $col->{auto_width}
|
if ( $col->{auto_width}
|
||||||
&& ( $col->{print_width} < $col->{max_val}
|
&& ( $col->{print_width} < $col->{max_val}
|
||||||
|| $col->{print_width} < $col->{header_width})
|
|| $col->{print_width} < $col->{header_width})
|
||||||
@@ -2892,8 +2959,8 @@ sub _calculate_column_widths {
|
|||||||
|
|
||||||
sub _truncate_headers {
|
sub _truncate_headers {
|
||||||
my ( $self, $col ) = @_;
|
my ( $self, $col ) = @_;
|
||||||
my $side = $self->{truncate_header_side};
|
my $side = $self->truncate_header_side();
|
||||||
foreach my $col ( @{$self->{cols}} ) {
|
foreach my $col ( @{$self->cols} ) {
|
||||||
my $col_name = $col->{name};
|
my $col_name = $col->{name};
|
||||||
my $print_width = $col->{print_width};
|
my $print_width = $col->{print_width};
|
||||||
next if length $col_name <= $print_width;
|
next if length $col_name <= $print_width;
|
||||||
@@ -2906,10 +2973,10 @@ sub _truncate_headers {
|
|||||||
|
|
||||||
sub _truncate_line_values {
|
sub _truncate_line_values {
|
||||||
my ( $self, %args ) = @_;
|
my ( $self, %args ) = @_;
|
||||||
my $n_vals = $self->{n_cols} - 1;
|
my $n_vals = $self->n_cols() - 1;
|
||||||
foreach my $vals ( @{$self->{lines}} ) {
|
foreach my $vals ( @{$self->lines} ) {
|
||||||
for my $i ( 0..$n_vals ) {
|
for my $i ( 0..$n_vals ) {
|
||||||
my $col = $self->{cols}->[$i];
|
my $col = $self->cols->[$i];
|
||||||
my $val = defined $vals->[$i] ? $vals->[$i] : $col->{undef_value};
|
my $val = defined $vals->[$i] ? $vals->[$i] : $col->{undef_value};
|
||||||
my $width = length $val;
|
my $width = length $val;
|
||||||
|
|
||||||
@@ -2935,9 +3002,9 @@ sub _truncate_line_values {
|
|||||||
sub _make_column_formats {
|
sub _make_column_formats {
|
||||||
my ( $self ) = @_;
|
my ( $self ) = @_;
|
||||||
my @col_fmts;
|
my @col_fmts;
|
||||||
my $n_cols = $self->{n_cols} - 1;
|
my $n_cols = $self->n_cols() - 1;
|
||||||
for my $i ( 0..$n_cols ) {
|
for my $i ( 0..$n_cols ) {
|
||||||
my $col = $self->{cols}->[$i];
|
my $col = $self->cols->[$i];
|
||||||
|
|
||||||
my $width = $col->{right_most} && !$col->{right_justify} ? ''
|
my $width = $col->{right_most} && !$col->{right_justify} ? ''
|
||||||
: $col->{print_width};
|
: $col->{print_width};
|
||||||
@@ -2950,12 +3017,12 @@ sub _make_column_formats {
|
|||||||
|
|
||||||
sub _truncate_line {
|
sub _truncate_line {
|
||||||
my ( $self, $line, %args ) = @_;
|
my ( $self, $line, %args ) = @_;
|
||||||
my $mark = defined $args{mark} ? $args{mark} : $self->{truncate_line_mark};
|
my $mark = defined $args{mark} ? $args{mark} : $self->truncate_line_mark();
|
||||||
if ( $line ) {
|
if ( $line ) {
|
||||||
$line =~ s/\s+$// if $args{strip};
|
$line =~ s/\s+$// if $args{strip};
|
||||||
my $len = length($line);
|
my $len = length($line);
|
||||||
if ( $len > $self->{line_width} ) {
|
if ( $len > $self->line_width() ) {
|
||||||
$line = substr($line, 0, $self->{line_width} - length $mark);
|
$line = substr($line, 0, $self->line_width() - length $mark);
|
||||||
$line .= $mark if $mark;
|
$line .= $mark if $mark;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2965,7 +3032,7 @@ sub _truncate_line {
|
|||||||
sub _column_error {
|
sub _column_error {
|
||||||
my ( $self, $err ) = @_;
|
my ( $self, $err ) = @_;
|
||||||
my $msg = "Column error: $err";
|
my $msg = "Column error: $err";
|
||||||
$self->{column_errors} eq 'die' ? die $msg : warn $msg;
|
$self->column_errors() eq 'die' ? die $msg : warn $msg;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4443,7 +4510,7 @@ sub main {
|
|||||||
foreach my $var ( sort keys %$diffs ) {
|
foreach my $var ( sort keys %$diffs ) {
|
||||||
$report->add_line($var, @{$diffs->{$var}});
|
$report->add_line($var, @{$diffs->{$var}});
|
||||||
}
|
}
|
||||||
$report->set_title(
|
$report->title(
|
||||||
"$n_diffs config difference" . ($n_diffs > 1 ? 's' : ''));
|
"$n_diffs config difference" . ($n_diffs > 1 ? 's' : ''));
|
||||||
print $report->get_report();
|
print $report->get_report();
|
||||||
}
|
}
|
||||||
|
@@ -1232,6 +1232,7 @@ sub Mo::import {
|
|||||||
_set_package_isa($caller, @_);
|
_set_package_isa($caller, @_);
|
||||||
_set_inherited_metadata($caller);
|
_set_inherited_metadata($caller);
|
||||||
},
|
},
|
||||||
|
override => \&override,
|
||||||
has => sub {
|
has => sub {
|
||||||
my $names = shift;
|
my $names = shift;
|
||||||
for my $attribute ( ref $names ? @$names : $names ) {
|
for my $attribute ( ref $names ? @$names : $names ) {
|
||||||
@@ -1528,6 +1529,16 @@ BEGIN {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub override {
|
||||||
|
my ($methods, $code) = @_;
|
||||||
|
my $caller = scalar caller;
|
||||||
|
|
||||||
|
for my $method ( ref($methods) ? @$methods : $methods ) {
|
||||||
|
my $full_method = "${caller}::${method}";
|
||||||
|
*{_glob_for $full_method} = $code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
@@ -2319,8 +2330,7 @@ sub _d {
|
|||||||
{
|
{
|
||||||
package ReportFormatter;
|
package ReportFormatter;
|
||||||
|
|
||||||
use strict;
|
use Mo;
|
||||||
use warnings FATAL => 'all';
|
|
||||||
use English qw(-no_match_vars);
|
use English qw(-no_match_vars);
|
||||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||||
|
|
||||||
@@ -2330,40 +2340,102 @@ use POSIX qw(ceil);
|
|||||||
eval { require Term::ReadKey };
|
eval { require Term::ReadKey };
|
||||||
my $have_term = $EVAL_ERROR ? 0 : 1;
|
my $have_term = $EVAL_ERROR ? 0 : 1;
|
||||||
|
|
||||||
sub new {
|
|
||||||
my ( $class, %args ) = @_;
|
|
||||||
my @required_args = qw();
|
|
||||||
foreach my $arg ( @required_args ) {
|
|
||||||
die "I need a $arg argument" unless $args{$arg};
|
|
||||||
}
|
|
||||||
my $self = {
|
|
||||||
underline_header => 1,
|
|
||||||
line_prefix => '# ',
|
|
||||||
line_width => 78,
|
|
||||||
column_spacing => ' ',
|
|
||||||
extend_right => 0,
|
|
||||||
truncate_line_mark => '...',
|
|
||||||
column_errors => 'warn',
|
|
||||||
truncate_header_side => 'left',
|
|
||||||
strip_whitespace => 1,
|
|
||||||
%args, # args above can be overriden, args below cannot
|
|
||||||
n_cols => 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
if ( ($self->{line_width} || '') eq 'auto' ) {
|
has underline_header => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Bool',
|
||||||
|
default => sub { 1 },
|
||||||
|
);
|
||||||
|
has line_prefix => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { '# ' },
|
||||||
|
);
|
||||||
|
has line_width => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Int',
|
||||||
|
default => sub { 78 },
|
||||||
|
);
|
||||||
|
has column_spacing => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { ' ' },
|
||||||
|
);
|
||||||
|
has extend_right => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Bool',
|
||||||
|
default => sub { '' },
|
||||||
|
);
|
||||||
|
has truncate_line_mark => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { '...' },
|
||||||
|
);
|
||||||
|
has column_errors => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { 'warn' },
|
||||||
|
);
|
||||||
|
has truncate_header_side => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { 'left' },
|
||||||
|
);
|
||||||
|
has strip_whitespace => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Bool',
|
||||||
|
default => sub { 1 },
|
||||||
|
);
|
||||||
|
has title => (
|
||||||
|
is => 'rw',
|
||||||
|
isa => 'Str',
|
||||||
|
predicate => 'has_title',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
has n_cols => (
|
||||||
|
is => 'rw',
|
||||||
|
isa => 'Int',
|
||||||
|
default => sub { 0 },
|
||||||
|
init_arg => undef,
|
||||||
|
);
|
||||||
|
|
||||||
|
has cols => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'ArrayRef',
|
||||||
|
init_arg => undef,
|
||||||
|
default => sub { [] },
|
||||||
|
clearer => 'clear_cols',
|
||||||
|
);
|
||||||
|
|
||||||
|
has lines => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'ArrayRef',
|
||||||
|
init_arg => undef,
|
||||||
|
default => sub { [] },
|
||||||
|
clearer => 'clear_lines',
|
||||||
|
);
|
||||||
|
|
||||||
|
has truncate_headers => (
|
||||||
|
is => 'rw',
|
||||||
|
isa => 'Bool',
|
||||||
|
default => sub { undef },
|
||||||
|
init_arg => undef,
|
||||||
|
clearer => 'clear_truncate_headers',
|
||||||
|
);
|
||||||
|
|
||||||
|
sub BUILDARGS {
|
||||||
|
my $class = shift;
|
||||||
|
my $args = $class->SUPER::BUILDARGS(@_);
|
||||||
|
|
||||||
|
if ( ($args->{line_width} || '') eq 'auto' ) {
|
||||||
die "Cannot auto-detect line width because the Term::ReadKey module "
|
die "Cannot auto-detect line width because the Term::ReadKey module "
|
||||||
. "is not installed" unless $have_term;
|
. "is not installed" unless $have_term;
|
||||||
($self->{line_width}) = GetTerminalSize();
|
($args->{line_width}) = GetTerminalSize();
|
||||||
}
|
PTDEBUG && _d('Line width:', $args->{line_width});
|
||||||
PTDEBUG && _d('Line width:', $self->{line_width});
|
|
||||||
|
|
||||||
return bless $self, $class;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub set_title {
|
return $args;
|
||||||
my ( $self, $title ) = @_;
|
|
||||||
$self->{title} = $title;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub set_columns {
|
sub set_columns {
|
||||||
@@ -2379,7 +2451,7 @@ sub set_columns {
|
|||||||
die "Column does not have a name" unless defined $col_name;
|
die "Column does not have a name" unless defined $col_name;
|
||||||
|
|
||||||
if ( $col->{width} ) {
|
if ( $col->{width} ) {
|
||||||
$col->{width_pct} = ceil(($col->{width} * 100) / $self->{line_width});
|
$col->{width_pct} = ceil(($col->{width} * 100) / $self->line_width());
|
||||||
PTDEBUG && _d('col:', $col_name, 'width:', $col->{width}, 'chars =',
|
PTDEBUG && _d('col:', $col_name, 'width:', $col->{width}, 'chars =',
|
||||||
$col->{width_pct}, '%');
|
$col->{width_pct}, '%');
|
||||||
}
|
}
|
||||||
@@ -2406,10 +2478,10 @@ sub set_columns {
|
|||||||
|
|
||||||
$col->{right_most} = 1 if $i == $#cols;
|
$col->{right_most} = 1 if $i == $#cols;
|
||||||
|
|
||||||
push @{$self->{cols}}, $col;
|
push @{$self->cols}, $col;
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->{n_cols} = scalar @cols;
|
$self->n_cols( scalar @cols );
|
||||||
|
|
||||||
if ( ($used_width || 0) > 100 ) {
|
if ( ($used_width || 0) > 100 ) {
|
||||||
die "Total width_pct for all columns is >100%";
|
die "Total width_pct for all columns is >100%";
|
||||||
@@ -2419,15 +2491,15 @@ sub set_columns {
|
|||||||
my $wid_per_col = int((100 - $used_width) / scalar @auto_width_cols);
|
my $wid_per_col = int((100 - $used_width) / scalar @auto_width_cols);
|
||||||
PTDEBUG && _d('Line width left:', (100-$used_width), '%;',
|
PTDEBUG && _d('Line width left:', (100-$used_width), '%;',
|
||||||
'each auto width col:', $wid_per_col, '%');
|
'each auto width col:', $wid_per_col, '%');
|
||||||
map { $self->{cols}->[$_]->{width_pct} = $wid_per_col } @auto_width_cols;
|
map { $self->cols->[$_]->{width_pct} = $wid_per_col } @auto_width_cols;
|
||||||
}
|
}
|
||||||
|
|
||||||
$min_hdr_wid += ($self->{n_cols} - 1) * length $self->{column_spacing};
|
$min_hdr_wid += ($self->n_cols() - 1) * length $self->column_spacing();
|
||||||
PTDEBUG && _d('min header width:', $min_hdr_wid);
|
PTDEBUG && _d('min header width:', $min_hdr_wid);
|
||||||
if ( $min_hdr_wid > $self->{line_width} ) {
|
if ( $min_hdr_wid > $self->line_width() ) {
|
||||||
PTDEBUG && _d('Will truncate headers because min header width',
|
PTDEBUG && _d('Will truncate headers because min header width',
|
||||||
$min_hdr_wid, '> line width', $self->{line_width});
|
$min_hdr_wid, '> line width', $self->line_width());
|
||||||
$self->{truncate_headers} = 1;
|
$self->truncate_headers(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -2436,14 +2508,14 @@ sub set_columns {
|
|||||||
sub add_line {
|
sub add_line {
|
||||||
my ( $self, @vals ) = @_;
|
my ( $self, @vals ) = @_;
|
||||||
my $n_vals = scalar @vals;
|
my $n_vals = scalar @vals;
|
||||||
if ( $n_vals != $self->{n_cols} ) {
|
if ( $n_vals != $self->n_cols() ) {
|
||||||
$self->_column_error("Number of values $n_vals does not match "
|
$self->_column_error("Number of values $n_vals does not match "
|
||||||
. "number of columns $self->{n_cols}");
|
. "number of columns " . $self->n_cols());
|
||||||
}
|
}
|
||||||
for my $i ( 0..($n_vals-1) ) {
|
for my $i ( 0..($n_vals-1) ) {
|
||||||
my $col = $self->{cols}->[$i];
|
my $col = $self->cols->[$i];
|
||||||
my $val = defined $vals[$i] ? $vals[$i] : $col->{undef_value};
|
my $val = defined $vals[$i] ? $vals[$i] : $col->{undef_value};
|
||||||
if ( $self->{strip_whitespace} ) {
|
if ( $self->strip_whitespace() ) {
|
||||||
$val =~ s/^\s+//g;
|
$val =~ s/^\s+//g;
|
||||||
$val =~ s/\s+$//;
|
$val =~ s/\s+$//;
|
||||||
$vals[$i] = $val;
|
$vals[$i] = $val;
|
||||||
@@ -2452,7 +2524,7 @@ sub add_line {
|
|||||||
$col->{min_val} = min($width, ($col->{min_val} || $width));
|
$col->{min_val} = min($width, ($col->{min_val} || $width));
|
||||||
$col->{max_val} = max($width, ($col->{max_val} || $width));
|
$col->{max_val} = max($width, ($col->{max_val} || $width));
|
||||||
}
|
}
|
||||||
push @{$self->{lines}}, \@vals;
|
push @{$self->lines}, \@vals;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2460,26 +2532,28 @@ sub get_report {
|
|||||||
my ( $self, %args ) = @_;
|
my ( $self, %args ) = @_;
|
||||||
|
|
||||||
$self->_calculate_column_widths();
|
$self->_calculate_column_widths();
|
||||||
$self->_truncate_headers() if $self->{truncate_headers};
|
if ( $self->truncate_headers() ) {
|
||||||
|
$self->_truncate_headers();
|
||||||
|
}
|
||||||
$self->_truncate_line_values(%args);
|
$self->_truncate_line_values(%args);
|
||||||
|
|
||||||
my @col_fmts = $self->_make_column_formats();
|
my @col_fmts = $self->_make_column_formats();
|
||||||
my $fmt = ($self->{line_prefix} || '')
|
my $fmt = $self->line_prefix()
|
||||||
. join($self->{column_spacing}, @col_fmts);
|
. join($self->column_spacing(), @col_fmts);
|
||||||
PTDEBUG && _d('Format:', $fmt);
|
PTDEBUG && _d('Format:', $fmt);
|
||||||
|
|
||||||
(my $hdr_fmt = $fmt) =~ s/%([^-])/%-$1/g;
|
(my $hdr_fmt = $fmt) =~ s/%([^-])/%-$1/g;
|
||||||
|
|
||||||
my @lines;
|
my @lines;
|
||||||
push @lines, sprintf "$self->{line_prefix}$self->{title}" if $self->{title};
|
push @lines, $self->line_prefix() . $self->title() if $self->has_title();
|
||||||
push @lines, $self->_truncate_line(
|
push @lines, $self->_truncate_line(
|
||||||
sprintf($hdr_fmt, map { $_->{name} } @{$self->{cols}}),
|
sprintf($hdr_fmt, map { $_->{name} } @{$self->cols}),
|
||||||
strip => 1,
|
strip => 1,
|
||||||
mark => '',
|
mark => '',
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( $self->{underline_header} ) {
|
if ( $self->underline_header() ) {
|
||||||
my @underlines = map { '=' x $_->{print_width} } @{$self->{cols}};
|
my @underlines = map { '=' x $_->{print_width} } @{$self->cols};
|
||||||
push @lines, $self->_truncate_line(
|
push @lines, $self->_truncate_line(
|
||||||
sprintf($fmt, map { $_ || '' } @underlines),
|
sprintf($fmt, map { $_ || '' } @underlines),
|
||||||
mark => '',
|
mark => '',
|
||||||
@@ -2490,19 +2564,23 @@ sub get_report {
|
|||||||
my $vals = $_;
|
my $vals = $_;
|
||||||
my $i = 0;
|
my $i = 0;
|
||||||
my @vals = map {
|
my @vals = map {
|
||||||
my $val = defined $_ ? $_ : $self->{cols}->[$i++]->{undef_value};
|
my $val = defined $_ ? $_ : $self->cols->[$i++]->{undef_value};
|
||||||
$val = '' if !defined $val;
|
$val = '' if !defined $val;
|
||||||
$val =~ s/\n/ /g;
|
$val =~ s/\n/ /g;
|
||||||
$val;
|
$val;
|
||||||
} @$vals;
|
} @$vals;
|
||||||
my $line = sprintf($fmt, @vals);
|
my $line = sprintf($fmt, @vals);
|
||||||
if ( $self->{extend_right} ) {
|
if ( $self->extend_right() ) {
|
||||||
$line;
|
$line;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$self->_truncate_line($line);
|
$self->_truncate_line($line);
|
||||||
}
|
}
|
||||||
} @{$self->{lines}};
|
} @{$self->lines};
|
||||||
|
|
||||||
|
$self->clear_cols();
|
||||||
|
$self->clear_lines();
|
||||||
|
$self->clear_truncate_headers();
|
||||||
|
|
||||||
return join("\n", @lines) . "\n";
|
return join("\n", @lines) . "\n";
|
||||||
}
|
}
|
||||||
@@ -2510,7 +2588,7 @@ sub get_report {
|
|||||||
sub truncate_value {
|
sub truncate_value {
|
||||||
my ( $self, $col, $val, $width, $side ) = @_;
|
my ( $self, $col, $val, $width, $side ) = @_;
|
||||||
return $val if length $val <= $width;
|
return $val if length $val <= $width;
|
||||||
return $val if $col->{right_most} && $self->{extend_right};
|
return $val if $col->{right_most} && $self->extend_right();
|
||||||
$side ||= $col->{truncate_side};
|
$side ||= $col->{truncate_side};
|
||||||
my $mark = $col->{truncate_mark};
|
my $mark = $col->{truncate_mark};
|
||||||
if ( $side eq 'right' ) {
|
if ( $side eq 'right' ) {
|
||||||
@@ -2530,8 +2608,8 @@ sub _calculate_column_widths {
|
|||||||
my ( $self ) = @_;
|
my ( $self ) = @_;
|
||||||
|
|
||||||
my $extra_space = 0;
|
my $extra_space = 0;
|
||||||
foreach my $col ( @{$self->{cols}} ) {
|
foreach my $col ( @{$self->cols} ) {
|
||||||
my $print_width = int($self->{line_width} * ($col->{width_pct} / 100));
|
my $print_width = int($self->line_width() * ($col->{width_pct} / 100));
|
||||||
|
|
||||||
PTDEBUG && _d('col:', $col->{name}, 'width pct:', $col->{width_pct},
|
PTDEBUG && _d('col:', $col->{name}, 'width pct:', $col->{width_pct},
|
||||||
'char width:', $print_width,
|
'char width:', $print_width,
|
||||||
@@ -2555,7 +2633,7 @@ sub _calculate_column_widths {
|
|||||||
|
|
||||||
PTDEBUG && _d('Extra space:', $extra_space);
|
PTDEBUG && _d('Extra space:', $extra_space);
|
||||||
while ( $extra_space-- ) {
|
while ( $extra_space-- ) {
|
||||||
foreach my $col ( @{$self->{cols}} ) {
|
foreach my $col ( @{$self->cols} ) {
|
||||||
if ( $col->{auto_width}
|
if ( $col->{auto_width}
|
||||||
&& ( $col->{print_width} < $col->{max_val}
|
&& ( $col->{print_width} < $col->{max_val}
|
||||||
|| $col->{print_width} < $col->{header_width})
|
|| $col->{print_width} < $col->{header_width})
|
||||||
@@ -2570,8 +2648,8 @@ sub _calculate_column_widths {
|
|||||||
|
|
||||||
sub _truncate_headers {
|
sub _truncate_headers {
|
||||||
my ( $self, $col ) = @_;
|
my ( $self, $col ) = @_;
|
||||||
my $side = $self->{truncate_header_side};
|
my $side = $self->truncate_header_side();
|
||||||
foreach my $col ( @{$self->{cols}} ) {
|
foreach my $col ( @{$self->cols} ) {
|
||||||
my $col_name = $col->{name};
|
my $col_name = $col->{name};
|
||||||
my $print_width = $col->{print_width};
|
my $print_width = $col->{print_width};
|
||||||
next if length $col_name <= $print_width;
|
next if length $col_name <= $print_width;
|
||||||
@@ -2584,10 +2662,10 @@ sub _truncate_headers {
|
|||||||
|
|
||||||
sub _truncate_line_values {
|
sub _truncate_line_values {
|
||||||
my ( $self, %args ) = @_;
|
my ( $self, %args ) = @_;
|
||||||
my $n_vals = $self->{n_cols} - 1;
|
my $n_vals = $self->n_cols() - 1;
|
||||||
foreach my $vals ( @{$self->{lines}} ) {
|
foreach my $vals ( @{$self->lines} ) {
|
||||||
for my $i ( 0..$n_vals ) {
|
for my $i ( 0..$n_vals ) {
|
||||||
my $col = $self->{cols}->[$i];
|
my $col = $self->cols->[$i];
|
||||||
my $val = defined $vals->[$i] ? $vals->[$i] : $col->{undef_value};
|
my $val = defined $vals->[$i] ? $vals->[$i] : $col->{undef_value};
|
||||||
my $width = length $val;
|
my $width = length $val;
|
||||||
|
|
||||||
@@ -2613,9 +2691,9 @@ sub _truncate_line_values {
|
|||||||
sub _make_column_formats {
|
sub _make_column_formats {
|
||||||
my ( $self ) = @_;
|
my ( $self ) = @_;
|
||||||
my @col_fmts;
|
my @col_fmts;
|
||||||
my $n_cols = $self->{n_cols} - 1;
|
my $n_cols = $self->n_cols() - 1;
|
||||||
for my $i ( 0..$n_cols ) {
|
for my $i ( 0..$n_cols ) {
|
||||||
my $col = $self->{cols}->[$i];
|
my $col = $self->cols->[$i];
|
||||||
|
|
||||||
my $width = $col->{right_most} && !$col->{right_justify} ? ''
|
my $width = $col->{right_most} && !$col->{right_justify} ? ''
|
||||||
: $col->{print_width};
|
: $col->{print_width};
|
||||||
@@ -2628,12 +2706,12 @@ sub _make_column_formats {
|
|||||||
|
|
||||||
sub _truncate_line {
|
sub _truncate_line {
|
||||||
my ( $self, $line, %args ) = @_;
|
my ( $self, $line, %args ) = @_;
|
||||||
my $mark = defined $args{mark} ? $args{mark} : $self->{truncate_line_mark};
|
my $mark = defined $args{mark} ? $args{mark} : $self->truncate_line_mark();
|
||||||
if ( $line ) {
|
if ( $line ) {
|
||||||
$line =~ s/\s+$// if $args{strip};
|
$line =~ s/\s+$// if $args{strip};
|
||||||
my $len = length($line);
|
my $len = length($line);
|
||||||
if ( $len > $self->{line_width} ) {
|
if ( $len > $self->line_width() ) {
|
||||||
$line = substr($line, 0, $self->{line_width} - length $mark);
|
$line = substr($line, 0, $self->line_width() - length $mark);
|
||||||
$line .= $mark if $mark;
|
$line .= $mark if $mark;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2643,7 +2721,7 @@ sub _truncate_line {
|
|||||||
sub _column_error {
|
sub _column_error {
|
||||||
my ( $self, $err ) = @_;
|
my ( $self, $err ) = @_;
|
||||||
my $msg = "Column error: $err";
|
my $msg = "Column error: $err";
|
||||||
$self->{column_errors} eq 'die' ? die $msg : warn $msg;
|
$self->column_errors() eq 'die' ? die $msg : warn $msg;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5686,6 +5764,7 @@ use Time::Local qw(timegm timelocal);
|
|||||||
use Digest::MD5 qw(md5_hex);
|
use Digest::MD5 qw(md5_hex);
|
||||||
use B qw();
|
use B qw();
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
require Exporter;
|
require Exporter;
|
||||||
our @ISA = qw(Exporter);
|
our @ISA = qw(Exporter);
|
||||||
our %EXPORT_TAGS = ();
|
our %EXPORT_TAGS = ();
|
||||||
@@ -5704,6 +5783,7 @@ our @EXPORT_OK = qw(
|
|||||||
crc32
|
crc32
|
||||||
encode_json
|
encode_json
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/;
|
our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/;
|
||||||
our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/;
|
our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/;
|
||||||
|
@@ -2770,6 +2770,7 @@ use Time::Local qw(timegm timelocal);
|
|||||||
use Digest::MD5 qw(md5_hex);
|
use Digest::MD5 qw(md5_hex);
|
||||||
use B qw();
|
use B qw();
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
require Exporter;
|
require Exporter;
|
||||||
our @ISA = qw(Exporter);
|
our @ISA = qw(Exporter);
|
||||||
our %EXPORT_TAGS = ();
|
our %EXPORT_TAGS = ();
|
||||||
@@ -2788,6 +2789,7 @@ our @EXPORT_OK = qw(
|
|||||||
crc32
|
crc32
|
||||||
encode_json
|
encode_json
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/;
|
our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/;
|
||||||
our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/;
|
our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/;
|
||||||
@@ -5721,8 +5723,7 @@ sub _d {
|
|||||||
{
|
{
|
||||||
package ReportFormatter;
|
package ReportFormatter;
|
||||||
|
|
||||||
use strict;
|
use Mo;
|
||||||
use warnings FATAL => 'all';
|
|
||||||
use English qw(-no_match_vars);
|
use English qw(-no_match_vars);
|
||||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||||
|
|
||||||
@@ -5732,40 +5733,102 @@ use POSIX qw(ceil);
|
|||||||
eval { require Term::ReadKey };
|
eval { require Term::ReadKey };
|
||||||
my $have_term = $EVAL_ERROR ? 0 : 1;
|
my $have_term = $EVAL_ERROR ? 0 : 1;
|
||||||
|
|
||||||
sub new {
|
|
||||||
my ( $class, %args ) = @_;
|
|
||||||
my @required_args = qw();
|
|
||||||
foreach my $arg ( @required_args ) {
|
|
||||||
die "I need a $arg argument" unless $args{$arg};
|
|
||||||
}
|
|
||||||
my $self = {
|
|
||||||
underline_header => 1,
|
|
||||||
line_prefix => '# ',
|
|
||||||
line_width => 78,
|
|
||||||
column_spacing => ' ',
|
|
||||||
extend_right => 0,
|
|
||||||
truncate_line_mark => '...',
|
|
||||||
column_errors => 'warn',
|
|
||||||
truncate_header_side => 'left',
|
|
||||||
strip_whitespace => 1,
|
|
||||||
%args, # args above can be overriden, args below cannot
|
|
||||||
n_cols => 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
if ( ($self->{line_width} || '') eq 'auto' ) {
|
has underline_header => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Bool',
|
||||||
|
default => sub { 1 },
|
||||||
|
);
|
||||||
|
has line_prefix => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { '# ' },
|
||||||
|
);
|
||||||
|
has line_width => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Int',
|
||||||
|
default => sub { 78 },
|
||||||
|
);
|
||||||
|
has column_spacing => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { ' ' },
|
||||||
|
);
|
||||||
|
has extend_right => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Bool',
|
||||||
|
default => sub { '' },
|
||||||
|
);
|
||||||
|
has truncate_line_mark => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { '...' },
|
||||||
|
);
|
||||||
|
has column_errors => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { 'warn' },
|
||||||
|
);
|
||||||
|
has truncate_header_side => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { 'left' },
|
||||||
|
);
|
||||||
|
has strip_whitespace => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Bool',
|
||||||
|
default => sub { 1 },
|
||||||
|
);
|
||||||
|
has title => (
|
||||||
|
is => 'rw',
|
||||||
|
isa => 'Str',
|
||||||
|
predicate => 'has_title',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
has n_cols => (
|
||||||
|
is => 'rw',
|
||||||
|
isa => 'Int',
|
||||||
|
default => sub { 0 },
|
||||||
|
init_arg => undef,
|
||||||
|
);
|
||||||
|
|
||||||
|
has cols => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'ArrayRef',
|
||||||
|
init_arg => undef,
|
||||||
|
default => sub { [] },
|
||||||
|
clearer => 'clear_cols',
|
||||||
|
);
|
||||||
|
|
||||||
|
has lines => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'ArrayRef',
|
||||||
|
init_arg => undef,
|
||||||
|
default => sub { [] },
|
||||||
|
clearer => 'clear_lines',
|
||||||
|
);
|
||||||
|
|
||||||
|
has truncate_headers => (
|
||||||
|
is => 'rw',
|
||||||
|
isa => 'Bool',
|
||||||
|
default => sub { undef },
|
||||||
|
init_arg => undef,
|
||||||
|
clearer => 'clear_truncate_headers',
|
||||||
|
);
|
||||||
|
|
||||||
|
sub BUILDARGS {
|
||||||
|
my $class = shift;
|
||||||
|
my $args = $class->SUPER::BUILDARGS(@_);
|
||||||
|
|
||||||
|
if ( ($args->{line_width} || '') eq 'auto' ) {
|
||||||
die "Cannot auto-detect line width because the Term::ReadKey module "
|
die "Cannot auto-detect line width because the Term::ReadKey module "
|
||||||
. "is not installed" unless $have_term;
|
. "is not installed" unless $have_term;
|
||||||
($self->{line_width}) = GetTerminalSize();
|
($args->{line_width}) = GetTerminalSize();
|
||||||
}
|
PTDEBUG && _d('Line width:', $args->{line_width});
|
||||||
PTDEBUG && _d('Line width:', $self->{line_width});
|
|
||||||
|
|
||||||
return bless $self, $class;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub set_title {
|
return $args;
|
||||||
my ( $self, $title ) = @_;
|
|
||||||
$self->{title} = $title;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub set_columns {
|
sub set_columns {
|
||||||
@@ -5781,7 +5844,7 @@ sub set_columns {
|
|||||||
die "Column does not have a name" unless defined $col_name;
|
die "Column does not have a name" unless defined $col_name;
|
||||||
|
|
||||||
if ( $col->{width} ) {
|
if ( $col->{width} ) {
|
||||||
$col->{width_pct} = ceil(($col->{width} * 100) / $self->{line_width});
|
$col->{width_pct} = ceil(($col->{width} * 100) / $self->line_width());
|
||||||
PTDEBUG && _d('col:', $col_name, 'width:', $col->{width}, 'chars =',
|
PTDEBUG && _d('col:', $col_name, 'width:', $col->{width}, 'chars =',
|
||||||
$col->{width_pct}, '%');
|
$col->{width_pct}, '%');
|
||||||
}
|
}
|
||||||
@@ -5808,10 +5871,10 @@ sub set_columns {
|
|||||||
|
|
||||||
$col->{right_most} = 1 if $i == $#cols;
|
$col->{right_most} = 1 if $i == $#cols;
|
||||||
|
|
||||||
push @{$self->{cols}}, $col;
|
push @{$self->cols}, $col;
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->{n_cols} = scalar @cols;
|
$self->n_cols( scalar @cols );
|
||||||
|
|
||||||
if ( ($used_width || 0) > 100 ) {
|
if ( ($used_width || 0) > 100 ) {
|
||||||
die "Total width_pct for all columns is >100%";
|
die "Total width_pct for all columns is >100%";
|
||||||
@@ -5821,15 +5884,15 @@ sub set_columns {
|
|||||||
my $wid_per_col = int((100 - $used_width) / scalar @auto_width_cols);
|
my $wid_per_col = int((100 - $used_width) / scalar @auto_width_cols);
|
||||||
PTDEBUG && _d('Line width left:', (100-$used_width), '%;',
|
PTDEBUG && _d('Line width left:', (100-$used_width), '%;',
|
||||||
'each auto width col:', $wid_per_col, '%');
|
'each auto width col:', $wid_per_col, '%');
|
||||||
map { $self->{cols}->[$_]->{width_pct} = $wid_per_col } @auto_width_cols;
|
map { $self->cols->[$_]->{width_pct} = $wid_per_col } @auto_width_cols;
|
||||||
}
|
}
|
||||||
|
|
||||||
$min_hdr_wid += ($self->{n_cols} - 1) * length $self->{column_spacing};
|
$min_hdr_wid += ($self->n_cols() - 1) * length $self->column_spacing();
|
||||||
PTDEBUG && _d('min header width:', $min_hdr_wid);
|
PTDEBUG && _d('min header width:', $min_hdr_wid);
|
||||||
if ( $min_hdr_wid > $self->{line_width} ) {
|
if ( $min_hdr_wid > $self->line_width() ) {
|
||||||
PTDEBUG && _d('Will truncate headers because min header width',
|
PTDEBUG && _d('Will truncate headers because min header width',
|
||||||
$min_hdr_wid, '> line width', $self->{line_width});
|
$min_hdr_wid, '> line width', $self->line_width());
|
||||||
$self->{truncate_headers} = 1;
|
$self->truncate_headers(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -5838,14 +5901,14 @@ sub set_columns {
|
|||||||
sub add_line {
|
sub add_line {
|
||||||
my ( $self, @vals ) = @_;
|
my ( $self, @vals ) = @_;
|
||||||
my $n_vals = scalar @vals;
|
my $n_vals = scalar @vals;
|
||||||
if ( $n_vals != $self->{n_cols} ) {
|
if ( $n_vals != $self->n_cols() ) {
|
||||||
$self->_column_error("Number of values $n_vals does not match "
|
$self->_column_error("Number of values $n_vals does not match "
|
||||||
. "number of columns $self->{n_cols}");
|
. "number of columns " . $self->n_cols());
|
||||||
}
|
}
|
||||||
for my $i ( 0..($n_vals-1) ) {
|
for my $i ( 0..($n_vals-1) ) {
|
||||||
my $col = $self->{cols}->[$i];
|
my $col = $self->cols->[$i];
|
||||||
my $val = defined $vals[$i] ? $vals[$i] : $col->{undef_value};
|
my $val = defined $vals[$i] ? $vals[$i] : $col->{undef_value};
|
||||||
if ( $self->{strip_whitespace} ) {
|
if ( $self->strip_whitespace() ) {
|
||||||
$val =~ s/^\s+//g;
|
$val =~ s/^\s+//g;
|
||||||
$val =~ s/\s+$//;
|
$val =~ s/\s+$//;
|
||||||
$vals[$i] = $val;
|
$vals[$i] = $val;
|
||||||
@@ -5854,7 +5917,7 @@ sub add_line {
|
|||||||
$col->{min_val} = min($width, ($col->{min_val} || $width));
|
$col->{min_val} = min($width, ($col->{min_val} || $width));
|
||||||
$col->{max_val} = max($width, ($col->{max_val} || $width));
|
$col->{max_val} = max($width, ($col->{max_val} || $width));
|
||||||
}
|
}
|
||||||
push @{$self->{lines}}, \@vals;
|
push @{$self->lines}, \@vals;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5862,26 +5925,28 @@ sub get_report {
|
|||||||
my ( $self, %args ) = @_;
|
my ( $self, %args ) = @_;
|
||||||
|
|
||||||
$self->_calculate_column_widths();
|
$self->_calculate_column_widths();
|
||||||
$self->_truncate_headers() if $self->{truncate_headers};
|
if ( $self->truncate_headers() ) {
|
||||||
|
$self->_truncate_headers();
|
||||||
|
}
|
||||||
$self->_truncate_line_values(%args);
|
$self->_truncate_line_values(%args);
|
||||||
|
|
||||||
my @col_fmts = $self->_make_column_formats();
|
my @col_fmts = $self->_make_column_formats();
|
||||||
my $fmt = ($self->{line_prefix} || '')
|
my $fmt = $self->line_prefix()
|
||||||
. join($self->{column_spacing}, @col_fmts);
|
. join($self->column_spacing(), @col_fmts);
|
||||||
PTDEBUG && _d('Format:', $fmt);
|
PTDEBUG && _d('Format:', $fmt);
|
||||||
|
|
||||||
(my $hdr_fmt = $fmt) =~ s/%([^-])/%-$1/g;
|
(my $hdr_fmt = $fmt) =~ s/%([^-])/%-$1/g;
|
||||||
|
|
||||||
my @lines;
|
my @lines;
|
||||||
push @lines, sprintf "$self->{line_prefix}$self->{title}" if $self->{title};
|
push @lines, $self->line_prefix() . $self->title() if $self->has_title();
|
||||||
push @lines, $self->_truncate_line(
|
push @lines, $self->_truncate_line(
|
||||||
sprintf($hdr_fmt, map { $_->{name} } @{$self->{cols}}),
|
sprintf($hdr_fmt, map { $_->{name} } @{$self->cols}),
|
||||||
strip => 1,
|
strip => 1,
|
||||||
mark => '',
|
mark => '',
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( $self->{underline_header} ) {
|
if ( $self->underline_header() ) {
|
||||||
my @underlines = map { '=' x $_->{print_width} } @{$self->{cols}};
|
my @underlines = map { '=' x $_->{print_width} } @{$self->cols};
|
||||||
push @lines, $self->_truncate_line(
|
push @lines, $self->_truncate_line(
|
||||||
sprintf($fmt, map { $_ || '' } @underlines),
|
sprintf($fmt, map { $_ || '' } @underlines),
|
||||||
mark => '',
|
mark => '',
|
||||||
@@ -5892,19 +5957,23 @@ sub get_report {
|
|||||||
my $vals = $_;
|
my $vals = $_;
|
||||||
my $i = 0;
|
my $i = 0;
|
||||||
my @vals = map {
|
my @vals = map {
|
||||||
my $val = defined $_ ? $_ : $self->{cols}->[$i++]->{undef_value};
|
my $val = defined $_ ? $_ : $self->cols->[$i++]->{undef_value};
|
||||||
$val = '' if !defined $val;
|
$val = '' if !defined $val;
|
||||||
$val =~ s/\n/ /g;
|
$val =~ s/\n/ /g;
|
||||||
$val;
|
$val;
|
||||||
} @$vals;
|
} @$vals;
|
||||||
my $line = sprintf($fmt, @vals);
|
my $line = sprintf($fmt, @vals);
|
||||||
if ( $self->{extend_right} ) {
|
if ( $self->extend_right() ) {
|
||||||
$line;
|
$line;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$self->_truncate_line($line);
|
$self->_truncate_line($line);
|
||||||
}
|
}
|
||||||
} @{$self->{lines}};
|
} @{$self->lines};
|
||||||
|
|
||||||
|
$self->clear_cols();
|
||||||
|
$self->clear_lines();
|
||||||
|
$self->clear_truncate_headers();
|
||||||
|
|
||||||
return join("\n", @lines) . "\n";
|
return join("\n", @lines) . "\n";
|
||||||
}
|
}
|
||||||
@@ -5912,7 +5981,7 @@ sub get_report {
|
|||||||
sub truncate_value {
|
sub truncate_value {
|
||||||
my ( $self, $col, $val, $width, $side ) = @_;
|
my ( $self, $col, $val, $width, $side ) = @_;
|
||||||
return $val if length $val <= $width;
|
return $val if length $val <= $width;
|
||||||
return $val if $col->{right_most} && $self->{extend_right};
|
return $val if $col->{right_most} && $self->extend_right();
|
||||||
$side ||= $col->{truncate_side};
|
$side ||= $col->{truncate_side};
|
||||||
my $mark = $col->{truncate_mark};
|
my $mark = $col->{truncate_mark};
|
||||||
if ( $side eq 'right' ) {
|
if ( $side eq 'right' ) {
|
||||||
@@ -5932,8 +6001,8 @@ sub _calculate_column_widths {
|
|||||||
my ( $self ) = @_;
|
my ( $self ) = @_;
|
||||||
|
|
||||||
my $extra_space = 0;
|
my $extra_space = 0;
|
||||||
foreach my $col ( @{$self->{cols}} ) {
|
foreach my $col ( @{$self->cols} ) {
|
||||||
my $print_width = int($self->{line_width} * ($col->{width_pct} / 100));
|
my $print_width = int($self->line_width() * ($col->{width_pct} / 100));
|
||||||
|
|
||||||
PTDEBUG && _d('col:', $col->{name}, 'width pct:', $col->{width_pct},
|
PTDEBUG && _d('col:', $col->{name}, 'width pct:', $col->{width_pct},
|
||||||
'char width:', $print_width,
|
'char width:', $print_width,
|
||||||
@@ -5957,7 +6026,7 @@ sub _calculate_column_widths {
|
|||||||
|
|
||||||
PTDEBUG && _d('Extra space:', $extra_space);
|
PTDEBUG && _d('Extra space:', $extra_space);
|
||||||
while ( $extra_space-- ) {
|
while ( $extra_space-- ) {
|
||||||
foreach my $col ( @{$self->{cols}} ) {
|
foreach my $col ( @{$self->cols} ) {
|
||||||
if ( $col->{auto_width}
|
if ( $col->{auto_width}
|
||||||
&& ( $col->{print_width} < $col->{max_val}
|
&& ( $col->{print_width} < $col->{max_val}
|
||||||
|| $col->{print_width} < $col->{header_width})
|
|| $col->{print_width} < $col->{header_width})
|
||||||
@@ -5972,8 +6041,8 @@ sub _calculate_column_widths {
|
|||||||
|
|
||||||
sub _truncate_headers {
|
sub _truncate_headers {
|
||||||
my ( $self, $col ) = @_;
|
my ( $self, $col ) = @_;
|
||||||
my $side = $self->{truncate_header_side};
|
my $side = $self->truncate_header_side();
|
||||||
foreach my $col ( @{$self->{cols}} ) {
|
foreach my $col ( @{$self->cols} ) {
|
||||||
my $col_name = $col->{name};
|
my $col_name = $col->{name};
|
||||||
my $print_width = $col->{print_width};
|
my $print_width = $col->{print_width};
|
||||||
next if length $col_name <= $print_width;
|
next if length $col_name <= $print_width;
|
||||||
@@ -5986,10 +6055,10 @@ sub _truncate_headers {
|
|||||||
|
|
||||||
sub _truncate_line_values {
|
sub _truncate_line_values {
|
||||||
my ( $self, %args ) = @_;
|
my ( $self, %args ) = @_;
|
||||||
my $n_vals = $self->{n_cols} - 1;
|
my $n_vals = $self->n_cols() - 1;
|
||||||
foreach my $vals ( @{$self->{lines}} ) {
|
foreach my $vals ( @{$self->lines} ) {
|
||||||
for my $i ( 0..$n_vals ) {
|
for my $i ( 0..$n_vals ) {
|
||||||
my $col = $self->{cols}->[$i];
|
my $col = $self->cols->[$i];
|
||||||
my $val = defined $vals->[$i] ? $vals->[$i] : $col->{undef_value};
|
my $val = defined $vals->[$i] ? $vals->[$i] : $col->{undef_value};
|
||||||
my $width = length $val;
|
my $width = length $val;
|
||||||
|
|
||||||
@@ -6015,9 +6084,9 @@ sub _truncate_line_values {
|
|||||||
sub _make_column_formats {
|
sub _make_column_formats {
|
||||||
my ( $self ) = @_;
|
my ( $self ) = @_;
|
||||||
my @col_fmts;
|
my @col_fmts;
|
||||||
my $n_cols = $self->{n_cols} - 1;
|
my $n_cols = $self->n_cols() - 1;
|
||||||
for my $i ( 0..$n_cols ) {
|
for my $i ( 0..$n_cols ) {
|
||||||
my $col = $self->{cols}->[$i];
|
my $col = $self->cols->[$i];
|
||||||
|
|
||||||
my $width = $col->{right_most} && !$col->{right_justify} ? ''
|
my $width = $col->{right_most} && !$col->{right_justify} ? ''
|
||||||
: $col->{print_width};
|
: $col->{print_width};
|
||||||
@@ -6030,12 +6099,12 @@ sub _make_column_formats {
|
|||||||
|
|
||||||
sub _truncate_line {
|
sub _truncate_line {
|
||||||
my ( $self, $line, %args ) = @_;
|
my ( $self, $line, %args ) = @_;
|
||||||
my $mark = defined $args{mark} ? $args{mark} : $self->{truncate_line_mark};
|
my $mark = defined $args{mark} ? $args{mark} : $self->truncate_line_mark();
|
||||||
if ( $line ) {
|
if ( $line ) {
|
||||||
$line =~ s/\s+$// if $args{strip};
|
$line =~ s/\s+$// if $args{strip};
|
||||||
my $len = length($line);
|
my $len = length($line);
|
||||||
if ( $len > $self->{line_width} ) {
|
if ( $len > $self->line_width() ) {
|
||||||
$line = substr($line, 0, $self->{line_width} - length $mark);
|
$line = substr($line, 0, $self->line_width() - length $mark);
|
||||||
$line .= $mark if $mark;
|
$line .= $mark if $mark;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6045,7 +6114,7 @@ sub _truncate_line {
|
|||||||
sub _column_error {
|
sub _column_error {
|
||||||
my ( $self, $err ) = @_;
|
my ( $self, $err ) = @_;
|
||||||
my $msg = "Column error: $err";
|
my $msg = "Column error: $err";
|
||||||
$self->{column_errors} eq 'die' ? die $msg : warn $msg;
|
$self->column_errors() eq 'die' ? die $msg : warn $msg;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7850,7 +7919,7 @@ sub main {
|
|||||||
long_last_column => 1,
|
long_last_column => 1,
|
||||||
extend_right => 1,
|
extend_right => 1,
|
||||||
);
|
);
|
||||||
$profile->set_title("Profile");
|
$profile->title("Profile");
|
||||||
$profile->set_columns(
|
$profile->set_columns(
|
||||||
{ name => 'Query ID', },
|
{ name => 'Query ID', },
|
||||||
{ name => 'NOTE', right_justify => 1, },
|
{ name => 'NOTE', right_justify => 1, },
|
||||||
|
282
bin/pt-upgrade
282
bin/pt-upgrade
@@ -2025,6 +2025,7 @@ use Time::Local qw(timegm timelocal);
|
|||||||
use Digest::MD5 qw(md5_hex);
|
use Digest::MD5 qw(md5_hex);
|
||||||
use B qw();
|
use B qw();
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
require Exporter;
|
require Exporter;
|
||||||
our @ISA = qw(Exporter);
|
our @ISA = qw(Exporter);
|
||||||
our %EXPORT_TAGS = ();
|
our %EXPORT_TAGS = ();
|
||||||
@@ -2043,6 +2044,7 @@ our @EXPORT_OK = qw(
|
|||||||
crc32
|
crc32
|
||||||
encode_json
|
encode_json
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/;
|
our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/;
|
||||||
our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/;
|
our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/;
|
||||||
@@ -2984,15 +2986,6 @@ sub calculate_statistical_metrics {
|
|||||||
$classes->{$class}->{$attrib}->{all},
|
$classes->{$class}->{$attrib}->{all},
|
||||||
$classes->{$class}->{$attrib}
|
$classes->{$class}->{$attrib}
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( $args{apdex_t} && $attrib eq 'Query_time' ) {
|
|
||||||
$class_metrics->{$class}->{$attrib}->{apdex_t} = $args{apdex_t};
|
|
||||||
$class_metrics->{$class}->{$attrib}->{apdex}
|
|
||||||
= $self->calculate_apdex(
|
|
||||||
t => $args{apdex_t},
|
|
||||||
samples => $classes->{$class}->{$attrib}->{all},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3117,9 +3110,6 @@ sub metrics {
|
|||||||
median => $metrics->{classes}->{$where}->{$attrib}->{median} || 0,
|
median => $metrics->{classes}->{$where}->{$attrib}->{median} || 0,
|
||||||
pct_95 => $metrics->{classes}->{$where}->{$attrib}->{pct_95} || 0,
|
pct_95 => $metrics->{classes}->{$where}->{$attrib}->{pct_95} || 0,
|
||||||
stddev => $metrics->{classes}->{$where}->{$attrib}->{stddev} || 0,
|
stddev => $metrics->{classes}->{$where}->{$attrib}->{stddev} || 0,
|
||||||
|
|
||||||
apdex_t => $metrics->{classes}->{$where}->{$attrib}->{apdex_t},
|
|
||||||
apdex => $metrics->{classes}->{$where}->{$attrib}->{apdex},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3435,51 +3425,6 @@ sub _deep_copy_attrib_vals {
|
|||||||
return $copy;
|
return $copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub calculate_apdex {
|
|
||||||
my ( $self, %args ) = @_;
|
|
||||||
my @required_args = qw(t samples);
|
|
||||||
foreach my $arg ( @required_args ) {
|
|
||||||
die "I need a $arg argument" unless $args{$arg};
|
|
||||||
}
|
|
||||||
my ($t, $samples) = @args{@required_args};
|
|
||||||
|
|
||||||
if ( $t <= 0 ) {
|
|
||||||
die "Invalid target threshold (T): $t. T must be greater than zero";
|
|
||||||
}
|
|
||||||
|
|
||||||
my $f = 4 * $t;
|
|
||||||
PTDEBUG && _d("Apdex T =", $t, "F =", $f);
|
|
||||||
|
|
||||||
my $satisfied = 0;
|
|
||||||
my $tolerating = 0;
|
|
||||||
my $frustrated = 0; # just for debug output
|
|
||||||
my $n_samples = 0;
|
|
||||||
BUCKET:
|
|
||||||
for my $bucket ( keys %$samples ) {
|
|
||||||
my $n_responses = $samples->{$bucket};
|
|
||||||
my $response_time = $buck_vals[$bucket];
|
|
||||||
|
|
||||||
if ( $response_time <= $t ) {
|
|
||||||
$satisfied += $n_responses;
|
|
||||||
}
|
|
||||||
elsif ( $response_time <= $f ) {
|
|
||||||
$tolerating += $n_responses;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$frustrated += $n_responses;
|
|
||||||
}
|
|
||||||
|
|
||||||
$n_samples += $n_responses;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $apdex = sprintf('%.2f', ($satisfied + ($tolerating / 2)) / $n_samples);
|
|
||||||
PTDEBUG && _d($n_samples, "samples,", $satisfied, "satisfied,",
|
|
||||||
$tolerating, "tolerating,", $frustrated, "frustrated, Apdex score:",
|
|
||||||
$apdex);
|
|
||||||
|
|
||||||
return $apdex;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub _get_value {
|
sub _get_value {
|
||||||
my ( $self, %args ) = @_;
|
my ( $self, %args ) = @_;
|
||||||
my ($event, $attrib, $alts) = @args{qw(event attribute alternates)};
|
my ($event, $attrib, $alts) = @args{qw(event attribute alternates)};
|
||||||
@@ -8179,8 +8124,7 @@ sub _d {
|
|||||||
{
|
{
|
||||||
package ReportFormatter;
|
package ReportFormatter;
|
||||||
|
|
||||||
use strict;
|
use Mo;
|
||||||
use warnings FATAL => 'all';
|
|
||||||
use English qw(-no_match_vars);
|
use English qw(-no_match_vars);
|
||||||
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||||
|
|
||||||
@@ -8190,40 +8134,102 @@ use POSIX qw(ceil);
|
|||||||
eval { require Term::ReadKey };
|
eval { require Term::ReadKey };
|
||||||
my $have_term = $EVAL_ERROR ? 0 : 1;
|
my $have_term = $EVAL_ERROR ? 0 : 1;
|
||||||
|
|
||||||
sub new {
|
|
||||||
my ( $class, %args ) = @_;
|
|
||||||
my @required_args = qw();
|
|
||||||
foreach my $arg ( @required_args ) {
|
|
||||||
die "I need a $arg argument" unless $args{$arg};
|
|
||||||
}
|
|
||||||
my $self = {
|
|
||||||
underline_header => 1,
|
|
||||||
line_prefix => '# ',
|
|
||||||
line_width => 78,
|
|
||||||
column_spacing => ' ',
|
|
||||||
extend_right => 0,
|
|
||||||
truncate_line_mark => '...',
|
|
||||||
column_errors => 'warn',
|
|
||||||
truncate_header_side => 'left',
|
|
||||||
strip_whitespace => 1,
|
|
||||||
%args, # args above can be overriden, args below cannot
|
|
||||||
n_cols => 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
if ( ($self->{line_width} || '') eq 'auto' ) {
|
has underline_header => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Bool',
|
||||||
|
default => sub { 1 },
|
||||||
|
);
|
||||||
|
has line_prefix => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { '# ' },
|
||||||
|
);
|
||||||
|
has line_width => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Int',
|
||||||
|
default => sub { 78 },
|
||||||
|
);
|
||||||
|
has column_spacing => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { ' ' },
|
||||||
|
);
|
||||||
|
has extend_right => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Bool',
|
||||||
|
default => sub { '' },
|
||||||
|
);
|
||||||
|
has truncate_line_mark => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { '...' },
|
||||||
|
);
|
||||||
|
has column_errors => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { 'warn' },
|
||||||
|
);
|
||||||
|
has truncate_header_side => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Str',
|
||||||
|
default => sub { 'left' },
|
||||||
|
);
|
||||||
|
has strip_whitespace => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'Bool',
|
||||||
|
default => sub { 1 },
|
||||||
|
);
|
||||||
|
has title => (
|
||||||
|
is => 'rw',
|
||||||
|
isa => 'Str',
|
||||||
|
predicate => 'has_title',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
has n_cols => (
|
||||||
|
is => 'rw',
|
||||||
|
isa => 'Int',
|
||||||
|
default => sub { 0 },
|
||||||
|
init_arg => undef,
|
||||||
|
);
|
||||||
|
|
||||||
|
has cols => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'ArrayRef',
|
||||||
|
init_arg => undef,
|
||||||
|
default => sub { [] },
|
||||||
|
clearer => 'clear_cols',
|
||||||
|
);
|
||||||
|
|
||||||
|
has lines => (
|
||||||
|
is => 'ro',
|
||||||
|
isa => 'ArrayRef',
|
||||||
|
init_arg => undef,
|
||||||
|
default => sub { [] },
|
||||||
|
clearer => 'clear_lines',
|
||||||
|
);
|
||||||
|
|
||||||
|
has truncate_headers => (
|
||||||
|
is => 'rw',
|
||||||
|
isa => 'Bool',
|
||||||
|
default => sub { undef },
|
||||||
|
init_arg => undef,
|
||||||
|
clearer => 'clear_truncate_headers',
|
||||||
|
);
|
||||||
|
|
||||||
|
sub BUILDARGS {
|
||||||
|
my $class = shift;
|
||||||
|
my $args = $class->SUPER::BUILDARGS(@_);
|
||||||
|
|
||||||
|
if ( ($args->{line_width} || '') eq 'auto' ) {
|
||||||
die "Cannot auto-detect line width because the Term::ReadKey module "
|
die "Cannot auto-detect line width because the Term::ReadKey module "
|
||||||
. "is not installed" unless $have_term;
|
. "is not installed" unless $have_term;
|
||||||
($self->{line_width}) = GetTerminalSize();
|
($args->{line_width}) = GetTerminalSize();
|
||||||
}
|
PTDEBUG && _d('Line width:', $args->{line_width});
|
||||||
PTDEBUG && _d('Line width:', $self->{line_width});
|
|
||||||
|
|
||||||
return bless $self, $class;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub set_title {
|
return $args;
|
||||||
my ( $self, $title ) = @_;
|
|
||||||
$self->{title} = $title;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub set_columns {
|
sub set_columns {
|
||||||
@@ -8239,7 +8245,7 @@ sub set_columns {
|
|||||||
die "Column does not have a name" unless defined $col_name;
|
die "Column does not have a name" unless defined $col_name;
|
||||||
|
|
||||||
if ( $col->{width} ) {
|
if ( $col->{width} ) {
|
||||||
$col->{width_pct} = ceil(($col->{width} * 100) / $self->{line_width});
|
$col->{width_pct} = ceil(($col->{width} * 100) / $self->line_width());
|
||||||
PTDEBUG && _d('col:', $col_name, 'width:', $col->{width}, 'chars =',
|
PTDEBUG && _d('col:', $col_name, 'width:', $col->{width}, 'chars =',
|
||||||
$col->{width_pct}, '%');
|
$col->{width_pct}, '%');
|
||||||
}
|
}
|
||||||
@@ -8266,10 +8272,10 @@ sub set_columns {
|
|||||||
|
|
||||||
$col->{right_most} = 1 if $i == $#cols;
|
$col->{right_most} = 1 if $i == $#cols;
|
||||||
|
|
||||||
push @{$self->{cols}}, $col;
|
push @{$self->cols}, $col;
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->{n_cols} = scalar @cols;
|
$self->n_cols( scalar @cols );
|
||||||
|
|
||||||
if ( ($used_width || 0) > 100 ) {
|
if ( ($used_width || 0) > 100 ) {
|
||||||
die "Total width_pct for all columns is >100%";
|
die "Total width_pct for all columns is >100%";
|
||||||
@@ -8279,15 +8285,15 @@ sub set_columns {
|
|||||||
my $wid_per_col = int((100 - $used_width) / scalar @auto_width_cols);
|
my $wid_per_col = int((100 - $used_width) / scalar @auto_width_cols);
|
||||||
PTDEBUG && _d('Line width left:', (100-$used_width), '%;',
|
PTDEBUG && _d('Line width left:', (100-$used_width), '%;',
|
||||||
'each auto width col:', $wid_per_col, '%');
|
'each auto width col:', $wid_per_col, '%');
|
||||||
map { $self->{cols}->[$_]->{width_pct} = $wid_per_col } @auto_width_cols;
|
map { $self->cols->[$_]->{width_pct} = $wid_per_col } @auto_width_cols;
|
||||||
}
|
}
|
||||||
|
|
||||||
$min_hdr_wid += ($self->{n_cols} - 1) * length $self->{column_spacing};
|
$min_hdr_wid += ($self->n_cols() - 1) * length $self->column_spacing();
|
||||||
PTDEBUG && _d('min header width:', $min_hdr_wid);
|
PTDEBUG && _d('min header width:', $min_hdr_wid);
|
||||||
if ( $min_hdr_wid > $self->{line_width} ) {
|
if ( $min_hdr_wid > $self->line_width() ) {
|
||||||
PTDEBUG && _d('Will truncate headers because min header width',
|
PTDEBUG && _d('Will truncate headers because min header width',
|
||||||
$min_hdr_wid, '> line width', $self->{line_width});
|
$min_hdr_wid, '> line width', $self->line_width());
|
||||||
$self->{truncate_headers} = 1;
|
$self->truncate_headers(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -8296,14 +8302,14 @@ sub set_columns {
|
|||||||
sub add_line {
|
sub add_line {
|
||||||
my ( $self, @vals ) = @_;
|
my ( $self, @vals ) = @_;
|
||||||
my $n_vals = scalar @vals;
|
my $n_vals = scalar @vals;
|
||||||
if ( $n_vals != $self->{n_cols} ) {
|
if ( $n_vals != $self->n_cols() ) {
|
||||||
$self->_column_error("Number of values $n_vals does not match "
|
$self->_column_error("Number of values $n_vals does not match "
|
||||||
. "number of columns $self->{n_cols}");
|
. "number of columns " . $self->n_cols());
|
||||||
}
|
}
|
||||||
for my $i ( 0..($n_vals-1) ) {
|
for my $i ( 0..($n_vals-1) ) {
|
||||||
my $col = $self->{cols}->[$i];
|
my $col = $self->cols->[$i];
|
||||||
my $val = defined $vals[$i] ? $vals[$i] : $col->{undef_value};
|
my $val = defined $vals[$i] ? $vals[$i] : $col->{undef_value};
|
||||||
if ( $self->{strip_whitespace} ) {
|
if ( $self->strip_whitespace() ) {
|
||||||
$val =~ s/^\s+//g;
|
$val =~ s/^\s+//g;
|
||||||
$val =~ s/\s+$//;
|
$val =~ s/\s+$//;
|
||||||
$vals[$i] = $val;
|
$vals[$i] = $val;
|
||||||
@@ -8312,7 +8318,7 @@ sub add_line {
|
|||||||
$col->{min_val} = min($width, ($col->{min_val} || $width));
|
$col->{min_val} = min($width, ($col->{min_val} || $width));
|
||||||
$col->{max_val} = max($width, ($col->{max_val} || $width));
|
$col->{max_val} = max($width, ($col->{max_val} || $width));
|
||||||
}
|
}
|
||||||
push @{$self->{lines}}, \@vals;
|
push @{$self->lines}, \@vals;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8320,26 +8326,28 @@ sub get_report {
|
|||||||
my ( $self, %args ) = @_;
|
my ( $self, %args ) = @_;
|
||||||
|
|
||||||
$self->_calculate_column_widths();
|
$self->_calculate_column_widths();
|
||||||
$self->_truncate_headers() if $self->{truncate_headers};
|
if ( $self->truncate_headers() ) {
|
||||||
|
$self->_truncate_headers();
|
||||||
|
}
|
||||||
$self->_truncate_line_values(%args);
|
$self->_truncate_line_values(%args);
|
||||||
|
|
||||||
my @col_fmts = $self->_make_column_formats();
|
my @col_fmts = $self->_make_column_formats();
|
||||||
my $fmt = ($self->{line_prefix} || '')
|
my $fmt = $self->line_prefix()
|
||||||
. join($self->{column_spacing}, @col_fmts);
|
. join($self->column_spacing(), @col_fmts);
|
||||||
PTDEBUG && _d('Format:', $fmt);
|
PTDEBUG && _d('Format:', $fmt);
|
||||||
|
|
||||||
(my $hdr_fmt = $fmt) =~ s/%([^-])/%-$1/g;
|
(my $hdr_fmt = $fmt) =~ s/%([^-])/%-$1/g;
|
||||||
|
|
||||||
my @lines;
|
my @lines;
|
||||||
push @lines, sprintf "$self->{line_prefix}$self->{title}" if $self->{title};
|
push @lines, $self->line_prefix() . $self->title() if $self->has_title();
|
||||||
push @lines, $self->_truncate_line(
|
push @lines, $self->_truncate_line(
|
||||||
sprintf($hdr_fmt, map { $_->{name} } @{$self->{cols}}),
|
sprintf($hdr_fmt, map { $_->{name} } @{$self->cols}),
|
||||||
strip => 1,
|
strip => 1,
|
||||||
mark => '',
|
mark => '',
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( $self->{underline_header} ) {
|
if ( $self->underline_header() ) {
|
||||||
my @underlines = map { '=' x $_->{print_width} } @{$self->{cols}};
|
my @underlines = map { '=' x $_->{print_width} } @{$self->cols};
|
||||||
push @lines, $self->_truncate_line(
|
push @lines, $self->_truncate_line(
|
||||||
sprintf($fmt, map { $_ || '' } @underlines),
|
sprintf($fmt, map { $_ || '' } @underlines),
|
||||||
mark => '',
|
mark => '',
|
||||||
@@ -8350,19 +8358,23 @@ sub get_report {
|
|||||||
my $vals = $_;
|
my $vals = $_;
|
||||||
my $i = 0;
|
my $i = 0;
|
||||||
my @vals = map {
|
my @vals = map {
|
||||||
my $val = defined $_ ? $_ : $self->{cols}->[$i++]->{undef_value};
|
my $val = defined $_ ? $_ : $self->cols->[$i++]->{undef_value};
|
||||||
$val = '' if !defined $val;
|
$val = '' if !defined $val;
|
||||||
$val =~ s/\n/ /g;
|
$val =~ s/\n/ /g;
|
||||||
$val;
|
$val;
|
||||||
} @$vals;
|
} @$vals;
|
||||||
my $line = sprintf($fmt, @vals);
|
my $line = sprintf($fmt, @vals);
|
||||||
if ( $self->{extend_right} ) {
|
if ( $self->extend_right() ) {
|
||||||
$line;
|
$line;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$self->_truncate_line($line);
|
$self->_truncate_line($line);
|
||||||
}
|
}
|
||||||
} @{$self->{lines}};
|
} @{$self->lines};
|
||||||
|
|
||||||
|
$self->clear_cols();
|
||||||
|
$self->clear_lines();
|
||||||
|
$self->clear_truncate_headers();
|
||||||
|
|
||||||
return join("\n", @lines) . "\n";
|
return join("\n", @lines) . "\n";
|
||||||
}
|
}
|
||||||
@@ -8370,7 +8382,7 @@ sub get_report {
|
|||||||
sub truncate_value {
|
sub truncate_value {
|
||||||
my ( $self, $col, $val, $width, $side ) = @_;
|
my ( $self, $col, $val, $width, $side ) = @_;
|
||||||
return $val if length $val <= $width;
|
return $val if length $val <= $width;
|
||||||
return $val if $col->{right_most} && $self->{extend_right};
|
return $val if $col->{right_most} && $self->extend_right();
|
||||||
$side ||= $col->{truncate_side};
|
$side ||= $col->{truncate_side};
|
||||||
my $mark = $col->{truncate_mark};
|
my $mark = $col->{truncate_mark};
|
||||||
if ( $side eq 'right' ) {
|
if ( $side eq 'right' ) {
|
||||||
@@ -8390,8 +8402,8 @@ sub _calculate_column_widths {
|
|||||||
my ( $self ) = @_;
|
my ( $self ) = @_;
|
||||||
|
|
||||||
my $extra_space = 0;
|
my $extra_space = 0;
|
||||||
foreach my $col ( @{$self->{cols}} ) {
|
foreach my $col ( @{$self->cols} ) {
|
||||||
my $print_width = int($self->{line_width} * ($col->{width_pct} / 100));
|
my $print_width = int($self->line_width() * ($col->{width_pct} / 100));
|
||||||
|
|
||||||
PTDEBUG && _d('col:', $col->{name}, 'width pct:', $col->{width_pct},
|
PTDEBUG && _d('col:', $col->{name}, 'width pct:', $col->{width_pct},
|
||||||
'char width:', $print_width,
|
'char width:', $print_width,
|
||||||
@@ -8415,7 +8427,7 @@ sub _calculate_column_widths {
|
|||||||
|
|
||||||
PTDEBUG && _d('Extra space:', $extra_space);
|
PTDEBUG && _d('Extra space:', $extra_space);
|
||||||
while ( $extra_space-- ) {
|
while ( $extra_space-- ) {
|
||||||
foreach my $col ( @{$self->{cols}} ) {
|
foreach my $col ( @{$self->cols} ) {
|
||||||
if ( $col->{auto_width}
|
if ( $col->{auto_width}
|
||||||
&& ( $col->{print_width} < $col->{max_val}
|
&& ( $col->{print_width} < $col->{max_val}
|
||||||
|| $col->{print_width} < $col->{header_width})
|
|| $col->{print_width} < $col->{header_width})
|
||||||
@@ -8430,8 +8442,8 @@ sub _calculate_column_widths {
|
|||||||
|
|
||||||
sub _truncate_headers {
|
sub _truncate_headers {
|
||||||
my ( $self, $col ) = @_;
|
my ( $self, $col ) = @_;
|
||||||
my $side = $self->{truncate_header_side};
|
my $side = $self->truncate_header_side();
|
||||||
foreach my $col ( @{$self->{cols}} ) {
|
foreach my $col ( @{$self->cols} ) {
|
||||||
my $col_name = $col->{name};
|
my $col_name = $col->{name};
|
||||||
my $print_width = $col->{print_width};
|
my $print_width = $col->{print_width};
|
||||||
next if length $col_name <= $print_width;
|
next if length $col_name <= $print_width;
|
||||||
@@ -8444,10 +8456,10 @@ sub _truncate_headers {
|
|||||||
|
|
||||||
sub _truncate_line_values {
|
sub _truncate_line_values {
|
||||||
my ( $self, %args ) = @_;
|
my ( $self, %args ) = @_;
|
||||||
my $n_vals = $self->{n_cols} - 1;
|
my $n_vals = $self->n_cols() - 1;
|
||||||
foreach my $vals ( @{$self->{lines}} ) {
|
foreach my $vals ( @{$self->lines} ) {
|
||||||
for my $i ( 0..$n_vals ) {
|
for my $i ( 0..$n_vals ) {
|
||||||
my $col = $self->{cols}->[$i];
|
my $col = $self->cols->[$i];
|
||||||
my $val = defined $vals->[$i] ? $vals->[$i] : $col->{undef_value};
|
my $val = defined $vals->[$i] ? $vals->[$i] : $col->{undef_value};
|
||||||
my $width = length $val;
|
my $width = length $val;
|
||||||
|
|
||||||
@@ -8473,9 +8485,9 @@ sub _truncate_line_values {
|
|||||||
sub _make_column_formats {
|
sub _make_column_formats {
|
||||||
my ( $self ) = @_;
|
my ( $self ) = @_;
|
||||||
my @col_fmts;
|
my @col_fmts;
|
||||||
my $n_cols = $self->{n_cols} - 1;
|
my $n_cols = $self->n_cols() - 1;
|
||||||
for my $i ( 0..$n_cols ) {
|
for my $i ( 0..$n_cols ) {
|
||||||
my $col = $self->{cols}->[$i];
|
my $col = $self->cols->[$i];
|
||||||
|
|
||||||
my $width = $col->{right_most} && !$col->{right_justify} ? ''
|
my $width = $col->{right_most} && !$col->{right_justify} ? ''
|
||||||
: $col->{print_width};
|
: $col->{print_width};
|
||||||
@@ -8488,12 +8500,12 @@ sub _make_column_formats {
|
|||||||
|
|
||||||
sub _truncate_line {
|
sub _truncate_line {
|
||||||
my ( $self, $line, %args ) = @_;
|
my ( $self, $line, %args ) = @_;
|
||||||
my $mark = defined $args{mark} ? $args{mark} : $self->{truncate_line_mark};
|
my $mark = defined $args{mark} ? $args{mark} : $self->truncate_line_mark();
|
||||||
if ( $line ) {
|
if ( $line ) {
|
||||||
$line =~ s/\s+$// if $args{strip};
|
$line =~ s/\s+$// if $args{strip};
|
||||||
my $len = length($line);
|
my $len = length($line);
|
||||||
if ( $len > $self->{line_width} ) {
|
if ( $len > $self->line_width() ) {
|
||||||
$line = substr($line, 0, $self->{line_width} - length $mark);
|
$line = substr($line, 0, $self->line_width() - length $mark);
|
||||||
$line .= $mark if $mark;
|
$line .= $mark if $mark;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8503,7 +8515,7 @@ sub _truncate_line {
|
|||||||
sub _column_error {
|
sub _column_error {
|
||||||
my ( $self, $err ) = @_;
|
my ( $self, $err ) = @_;
|
||||||
my $msg = "Column error: $err";
|
my $msg = "Column error: $err";
|
||||||
$self->{column_errors} eq 'die' ? die $msg : warn $msg;
|
$self->column_errors() eq 'die' ? die $msg : warn $msg;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9443,7 +9455,7 @@ sub _report_diff_checksums {
|
|||||||
return unless keys %{$self->{diffs}->{checksums}};
|
return unless keys %{$self->{diffs}->{checksums}};
|
||||||
|
|
||||||
my $report = new ReportFormatter();
|
my $report = new ReportFormatter();
|
||||||
$report->set_title('Checksum differences');
|
$report->title('Checksum differences');
|
||||||
$report->set_columns(
|
$report->set_columns(
|
||||||
$args{query_id_col},
|
$args{query_id_col},
|
||||||
@{$args{host_cols}},
|
@{$args{host_cols}},
|
||||||
@@ -9474,7 +9486,7 @@ sub _report_diff_col_vals {
|
|||||||
return unless keys %{$self->{diffs}->{col_vals}};
|
return unless keys %{$self->{diffs}->{col_vals}};
|
||||||
|
|
||||||
my $report = new ReportFormatter();
|
my $report = new ReportFormatter();
|
||||||
$report->set_title('Column value differences');
|
$report->title('Column value differences');
|
||||||
$report->set_columns(
|
$report->set_columns(
|
||||||
$args{query_id_col},
|
$args{query_id_col},
|
||||||
{
|
{
|
||||||
@@ -9509,7 +9521,7 @@ sub _report_diff_row_counts {
|
|||||||
return unless keys %{$self->{diffs}->{row_counts}};
|
return unless keys %{$self->{diffs}->{row_counts}};
|
||||||
|
|
||||||
my $report = new ReportFormatter();
|
my $report = new ReportFormatter();
|
||||||
$report->set_title('Row count differences');
|
$report->title('Row count differences');
|
||||||
my $hostno = 0;
|
my $hostno = 0;
|
||||||
$report->set_columns(
|
$report->set_columns(
|
||||||
$args{query_id_col},
|
$args{query_id_col},
|
||||||
@@ -9785,7 +9797,7 @@ sub _report_diff_big {
|
|||||||
return unless keys %{$self->{diffs}->{big}};
|
return unless keys %{$self->{diffs}->{big}};
|
||||||
|
|
||||||
my $report = new ReportFormatter();
|
my $report = new ReportFormatter();
|
||||||
$report->set_title('Big query time differences');
|
$report->title('Big query time differences');
|
||||||
my $hostno = 0;
|
my $hostno = 0;
|
||||||
$report->set_columns(
|
$report->set_columns(
|
||||||
$args{query_id_col},
|
$args{query_id_col},
|
||||||
@@ -9822,7 +9834,7 @@ sub _report_diff_in_bucket {
|
|||||||
return unless keys %{$self->{diffs}->{in_bucket}};
|
return unless keys %{$self->{diffs}->{in_bucket}};
|
||||||
|
|
||||||
my $report = new ReportFormatter();
|
my $report = new ReportFormatter();
|
||||||
$report->set_title('Significant query time differences');
|
$report->title('Significant query time differences');
|
||||||
my $hostno = 0;
|
my $hostno = 0;
|
||||||
$report->set_columns(
|
$report->set_columns(
|
||||||
$args{query_id_col},
|
$args{query_id_col},
|
||||||
@@ -10141,7 +10153,7 @@ sub _report_diff_warnings {
|
|||||||
return unless keys %{$self->{diffs}->{warnings}};
|
return unless keys %{$self->{diffs}->{warnings}};
|
||||||
|
|
||||||
my $report = new ReportFormatter(extend_right => 1);
|
my $report = new ReportFormatter(extend_right => 1);
|
||||||
$report->set_title('New warnings');
|
$report->title('New warnings');
|
||||||
$report->set_columns(
|
$report->set_columns(
|
||||||
$args{query_id_col},
|
$args{query_id_col},
|
||||||
{ name => 'Host', },
|
{ name => 'Host', },
|
||||||
@@ -10175,7 +10187,7 @@ sub _report_diff_levels {
|
|||||||
return unless keys %{$self->{diffs}->{levels}};
|
return unless keys %{$self->{diffs}->{levels}};
|
||||||
|
|
||||||
my $report = new ReportFormatter(extend_right => 1);
|
my $report = new ReportFormatter(extend_right => 1);
|
||||||
$report->set_title('Warning level differences');
|
$report->title('Warning level differences');
|
||||||
my $hostno = 0;
|
my $hostno = 0;
|
||||||
$report->set_columns(
|
$report->set_columns(
|
||||||
$args{query_id_col},
|
$args{query_id_col},
|
||||||
@@ -10213,7 +10225,7 @@ sub _report_diff_warning_counts {
|
|||||||
return unless keys %{$self->{diffs}->{warning_counts}};
|
return unless keys %{$self->{diffs}->{warning_counts}};
|
||||||
|
|
||||||
my $report = new ReportFormatter();
|
my $report = new ReportFormatter();
|
||||||
$report->set_title('Warning count differences');
|
$report->title('Warning count differences');
|
||||||
my $hostno = 0;
|
my $hostno = 0;
|
||||||
$report->set_columns(
|
$report->set_columns(
|
||||||
$args{query_id_col},
|
$args{query_id_col},
|
||||||
@@ -12375,7 +12387,7 @@ sub report_errors {
|
|||||||
return unless keys %$errors;
|
return unless keys %$errors;
|
||||||
|
|
||||||
my $rf = new ReportFormatter(extend_right=>1);
|
my $rf = new ReportFormatter(extend_right=>1);
|
||||||
$rf->set_title('Errors');
|
$rf->title('Errors');
|
||||||
$rf->set_columns(
|
$rf->set_columns(
|
||||||
{ name => 'Query ID' },
|
{ name => 'Query ID' },
|
||||||
{ name => 'Host', },
|
{ name => 'Host', },
|
||||||
|
@@ -298,7 +298,7 @@ sub _report_diff_big {
|
|||||||
return unless keys %{$self->{diffs}->{big}};
|
return unless keys %{$self->{diffs}->{big}};
|
||||||
|
|
||||||
my $report = new ReportFormatter();
|
my $report = new ReportFormatter();
|
||||||
$report->set_title('Big query time differences');
|
$report->title('Big query time differences');
|
||||||
my $hostno = 0;
|
my $hostno = 0;
|
||||||
$report->set_columns(
|
$report->set_columns(
|
||||||
$args{query_id_col},
|
$args{query_id_col},
|
||||||
@@ -347,7 +347,7 @@ sub _report_diff_in_bucket {
|
|||||||
return unless keys %{$self->{diffs}->{in_bucket}};
|
return unless keys %{$self->{diffs}->{in_bucket}};
|
||||||
|
|
||||||
my $report = new ReportFormatter();
|
my $report = new ReportFormatter();
|
||||||
$report->set_title('Significant query time differences');
|
$report->title('Significant query time differences');
|
||||||
my $hostno = 0;
|
my $hostno = 0;
|
||||||
$report->set_columns(
|
$report->set_columns(
|
||||||
$args{query_id_col},
|
$args{query_id_col},
|
||||||
|
@@ -874,7 +874,7 @@ sub _report_diff_checksums {
|
|||||||
return unless keys %{$self->{diffs}->{checksums}};
|
return unless keys %{$self->{diffs}->{checksums}};
|
||||||
|
|
||||||
my $report = new ReportFormatter();
|
my $report = new ReportFormatter();
|
||||||
$report->set_title('Checksum differences');
|
$report->title('Checksum differences');
|
||||||
$report->set_columns(
|
$report->set_columns(
|
||||||
$args{query_id_col},
|
$args{query_id_col},
|
||||||
@{$args{host_cols}},
|
@{$args{host_cols}},
|
||||||
@@ -905,7 +905,7 @@ sub _report_diff_col_vals {
|
|||||||
return unless keys %{$self->{diffs}->{col_vals}};
|
return unless keys %{$self->{diffs}->{col_vals}};
|
||||||
|
|
||||||
my $report = new ReportFormatter();
|
my $report = new ReportFormatter();
|
||||||
$report->set_title('Column value differences');
|
$report->title('Column value differences');
|
||||||
$report->set_columns(
|
$report->set_columns(
|
||||||
$args{query_id_col},
|
$args{query_id_col},
|
||||||
{
|
{
|
||||||
@@ -940,7 +940,7 @@ sub _report_diff_row_counts {
|
|||||||
return unless keys %{$self->{diffs}->{row_counts}};
|
return unless keys %{$self->{diffs}->{row_counts}};
|
||||||
|
|
||||||
my $report = new ReportFormatter();
|
my $report = new ReportFormatter();
|
||||||
$report->set_title('Row count differences');
|
$report->title('Row count differences');
|
||||||
my $hostno = 0;
|
my $hostno = 0;
|
||||||
$report->set_columns(
|
$report->set_columns(
|
||||||
$args{query_id_col},
|
$args{query_id_col},
|
||||||
|
@@ -324,7 +324,7 @@ sub _report_diff_warnings {
|
|||||||
return unless keys %{$self->{diffs}->{warnings}};
|
return unless keys %{$self->{diffs}->{warnings}};
|
||||||
|
|
||||||
my $report = new ReportFormatter(extend_right => 1);
|
my $report = new ReportFormatter(extend_right => 1);
|
||||||
$report->set_title('New warnings');
|
$report->title('New warnings');
|
||||||
$report->set_columns(
|
$report->set_columns(
|
||||||
$args{query_id_col},
|
$args{query_id_col},
|
||||||
{ name => 'Host', },
|
{ name => 'Host', },
|
||||||
@@ -358,7 +358,7 @@ sub _report_diff_levels {
|
|||||||
return unless keys %{$self->{diffs}->{levels}};
|
return unless keys %{$self->{diffs}->{levels}};
|
||||||
|
|
||||||
my $report = new ReportFormatter(extend_right => 1);
|
my $report = new ReportFormatter(extend_right => 1);
|
||||||
$report->set_title('Warning level differences');
|
$report->title('Warning level differences');
|
||||||
my $hostno = 0;
|
my $hostno = 0;
|
||||||
$report->set_columns(
|
$report->set_columns(
|
||||||
$args{query_id_col},
|
$args{query_id_col},
|
||||||
@@ -396,7 +396,7 @@ sub _report_diff_warning_counts {
|
|||||||
return unless keys %{$self->{diffs}->{warning_counts}};
|
return unless keys %{$self->{diffs}->{warning_counts}};
|
||||||
|
|
||||||
my $report = new ReportFormatter();
|
my $report = new ReportFormatter();
|
||||||
$report->set_title('Warning count differences');
|
$report->title('Warning count differences');
|
||||||
my $hostno = 0;
|
my $hostno = 0;
|
||||||
$report->set_columns(
|
$report->set_columns(
|
||||||
$args{query_id_col},
|
$args{query_id_col},
|
||||||
|
Reference in New Issue
Block a user