File Coverage

blib/lib/Log/ger/Layout/Pattern.pm
Criterion Covered Total %
statement 44 45 97.7
branch 8 10 80.0
condition 12 14 85.7
subroutine 10 10 100.0
pod 0 2 0.0
total 74 81 91.3


line stmt bran cond sub pod time code
1             package Log::ger::Layout::Pattern;
2              
3             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
4             our $DATE = '2020-04-19'; # DATE
5             our $DIST = 'Log-ger-Layout-Pattern'; # DIST
6             our $VERSION = '0.007'; # VERSION
7              
8 1     1   2727 use 5.010001;
  1         3  
9 1     1   5 use strict;
  1         2  
  1         20  
10 1     1   5 use warnings;
  1         2  
  1         25  
11              
12 1     1   469 use Devel::Caller::Util;
  1         405  
  1         42  
13 1     1   6 use Log::ger ();
  1         2  
  1         19  
14 1     1   518 use Time::HiRes qw(time);
  1         1401  
  1         4  
15              
16             our $time_start = time();
17             our $time_now = $time_start;
18             our $time_last = $time_start;
19              
20             my %per_message_data;
21             my %cache;
22              
23             our %format_for = (
24             'c' => sub { $_[1]{category} },
25             'C' => sub { $per_message_data{caller0}[0] },
26             'd' => sub {
27             my @t = localtime($time_now);
28             sprintf(
29             "%04d-%02d-%02dT%02d:%02d:%02d",
30             $t[5]+1900, $t[4]+1, $t[3],
31             $t[2], $t[1], $t[0],
32             );
33             },
34             'D' => sub {
35             my @t = gmtime($time_now);
36             sprintf(
37             "%04d-%02d-%02dT%02d:%02d:%02d",
38             $t[5]+1900, $t[4]+1, $t[3],
39             $t[2], $t[1], $t[0],
40             );
41             },
42             'F' => sub { $per_message_data{caller0}[1] },
43             'H' => sub {
44             require Sys::Hostname;
45             Sys::Hostname::hostname();
46             },
47             'l' => sub {
48             sprintf(
49             "%s (%s:%d)",
50             $per_message_data{caller1}[3] // '',
51             $per_message_data{caller0}[1],
52             $per_message_data{caller0}[2],
53             );
54             },
55             'L' => sub { $per_message_data{caller0}[2] },
56             'm' => sub { $_[0] },
57             'M' => sub {
58             $per_message_data{caller1}[3] // '';
59             },
60             'n' => sub { "\n" },
61             'p' => sub { $_[3] },
62             'P' => sub { $$ },
63             'r' => sub { sprintf("%.3f", $time_now - $time_start) },
64             'R' => sub { sprintf("%.3f", $time_now - $time_last ) },
65             'T' => sub {
66             join(", ", map { "$_->[3] called at $_->[1] line $_->[2]" }
67             @{ $per_message_data{callers} });
68             },
69             '_{vmsize}' => sub {
70             unless ($cache{pid_stat_time} &&
71             $cache{pid_stat_time} >= $time_now-1) {
72             open my $fh, "/proc/$$/stat" or die;
73             $cache{pid_stat} = [split /\s+/, scalar(<$fh>)];
74             $cache{pid_stat_time} = $time_now;
75             close $fh;
76             }
77             sprintf("%d", $cache{pid_stat}[22]/1024);
78             },
79              
80             # test
81             #'z' => sub { use DD; my $i = 0; while (my @c = caller($i++)) { dd \@c } },
82             '%' => sub { '%' },
83             );
84              
85             sub meta { +{
86 17     17 0 43576 v => 2,
87             } }
88              
89             my $re = qr/%(_\{\w+\}|[A-Za-z%])/;
90             sub _layout {
91 17     17   36 my $format = shift;
92 17         26 my $packages_to_ignore = shift;
93 17         38 my $subroutines_to_ignore = shift;
94              
95 17         54 ($time_last, $time_now) = ($time_now, time());
96 17         42 %per_message_data = ();
97              
98 17         24 my %mentioned_formats;
99 17         127 while ($format =~ m/$re/g) {
100 20 50       73 if (exists $format_for{$1}) {
101 20         87 $mentioned_formats{$1} = 1;
102             } else {
103 0         0 die "Unknown format '%$1'";
104             }
105             }
106              
107 17 100 100     119 if ($mentioned_formats{C} ||
      100        
      100        
108             $mentioned_formats{F} ||
109             $mentioned_formats{L} ||
110             $mentioned_formats{l}
111             ) {
112             $per_message_data{caller0} =
113 4         13 [Devel::Caller::Util::caller (0, 0, $packages_to_ignore, $subroutines_to_ignore)];
114             }
115 17 100 66     368 if ($mentioned_formats{l} ||
116             $mentioned_formats{M}
117             ) {
118             $per_message_data{caller1} =
119 1         3 [Devel::Caller::Util::caller (1, 0, $packages_to_ignore, $subroutines_to_ignore)];
120             }
121 17 100       123 if ($mentioned_formats{T}) {
122             $per_message_data{callers} =
123 1         7 [Devel::Caller::Util::callers(0, 0, $packages_to_ignore, $subroutines_to_ignore)];
124             }
125              
126 17         341 $format =~ s#$re#$format_for{$1}->(@_)#eg;
  20         75  
127 17         105 $format;
128             }
129              
130             sub get_hooks {
131 17     17 0 210 my %plugin_conf = @_;
132              
133 17 50       49 $plugin_conf{format} or die "Please specify format";
134             $plugin_conf{packages_to_ignore} //= [
135 17   50     105 "Log::ger",
136             "Log::ger::Layout::Pattern",
137             "Try::Tiny",
138             ];
139              
140             return {
141             create_layouter => [
142             __PACKAGE__, # key
143             50, # priority
144             sub { # hook
145 17     17   3402 my %hook_args = @_; # see Log::ger::Manual::Internals/"Arguments passed to hook"
146             my $layouter = sub {
147 17         19988 _layout($plugin_conf{format}, $plugin_conf{packages_to_ignore}, $plugin_conf{subroutines_to_ignore}, @_);
148 17         52 };
149 17         49 [$layouter];
150 17         119 }],
151             };
152             }
153              
154             1;
155             # ABSTRACT: Pattern layout
156              
157             __END__