use Data::Dumper;
use POSIX qw(strftime getpid);
-use Scalar::Util qw(blessed reftype);
+use Scalar::Util qw(blessed refaddr weaken);
use Time::HiRes qw(gettimeofday tv_interval);
-use YAML;
use SL::Request ();
+use SL::YAML;
use strict;
use utf8;
$self->message(WARN, $message);
}
-sub _clone_for_dump {
- my ($src) = @_;
+sub clone_for_dump {
+ my ($src, $dumped) = @_;
- return undef unless defined($src);
- return $src->as_debug_info if blessed($src) && $src->can('as_debug_info');
- return [ map { _clone_for_dump($_) } @{ $src } ] if reftype($src) eq 'ARRAY';
- return { map { ($_ => _clone_for_dump($src->{$_})) } keys %{ $src } } if reftype($src) eq 'HASH';
- return "$src";
+ return undef if !defined($src);
+ return $src if !ref($src);
+
+ $dumped ||= {};
+ my $addr = refaddr($src);
+
+ return $dumped->{$addr} if $dumped->{$addr // ''};
+
+
+ if (blessed($src) && $src->can('as_debug_info')) {
+ $dumped->{$addr} = $src->as_debug_info;
+
+ } elsif (ref($src) eq 'ARRAY') {
+ $dumped->{$addr} = [];
+
+ foreach my $entry (@{ $src }) {
+ my $exists = !!$dumped->{refaddr($entry) // ''};
+ push @{ $dumped->{$addr} }, clone_for_dump($entry, $dumped);
+
+ weaken($dumped->{$addr}->[-1]) if $exists;
+
+ }
+
+ } elsif (ref($src) =~ m{^(?:HASH|Form|SL::.+)$}) {
+ $dumped->{$addr} = {};
+
+ foreach my $key (keys %{ $src }) {
+ my $exists = !!$dumped->{refaddr($src->{$key}) // ''};
+ $dumped->{$addr}->{$key} = clone_for_dump($src->{$key}, $dumped);
+
+ weaken($dumped->{$addr}->{$key}) if $exists;
+ }
+ }
+
+ return $dumped->{$addr} // "$src";
}
sub dump {
my ($self, $level, $name, $variable, %options) = @_;
- $variable = _clone_for_dump($variable);
+ $variable = clone_for_dump($variable);
my $dumper = Data::Dumper->new([$variable]);
$dumper->Sortkeys(1);
$dumper->Indent(2);
sub dump_yaml {
my ($self, $level, $name, $variable) = @_;
- $self->message($level, "dumping ${name}:\n" . YAML::Dump($variable));
+ $self->message($level, "dumping ${name}:\n" . SL::YAML::Dump($variable));
}
sub dump_sql_result {
return;
}
- my @texts = map { ref $_ ? YAML::Dump($_) : $_ } ($item1, $item2);
+ my @texts = map { ref $_ ? SL::YAML::Dump($_) : $_ } ($item1, $item2);
$self->message($level, Text::Diff::diff(\$texts[0], \$texts[1], \%params));
}
sub level2string {
no warnings;
# use $_[0] as a bit mask and return levelstrings separated by /
- join '/', qw(info debug1 debug2 query trace error_call_trace request_timer WARNING)[ grep { (reverse split //, sprintf "%08b", $_[0])[$_] } 0..7 ]
+ join '/', qw(info debug1 debug2 query trace error_call_trace request_timer request WARNING trace2 show_caller)[ grep { (reverse split //, sprintf "%011b", $_[0])[$_] } 0..11 ]
}
sub begin_request {
return 1 unless want_request_timer();
my $now = $self->get_request_time;
- my $diff = int((($now - ($self->{previous_log_time} // 0)) * 10_000 + 5) / 10);
+
+ return 1 unless $now;
+
+ my $diff = $self->{previous_log_time} ? int((($now - ($self->{previous_log_time} // 0)) * 10_000 + 5) / 10) : $now * 10_0000 + 5;
$self->{previous_log_time} = $now;
$self->_write("time", "${now}s Δ ${diff}ms" . (@slurp ? " (@slurp)" : ''));