File Coverage

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


line stmt bran cond sub pod time code
1             package Log::ger::Layout::Pattern;
2              
3 2     2   771991 use 5.010001;
  2         10  
4 2     2   12 use strict;
  2         4  
  2         60  
5 2     2   7 use warnings;
  2         5  
  2         169  
6              
7 2     2   1057 use Devel::Caller::Util;
  2         897  
  2         130  
8 2     2   1513 use Log::ger ();
  2         81  
  2         66  
9 2     2   509 use Time::HiRes qw(time);
  2         1219  
  2         16  
10              
11             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
12             our $DATE = '2024-01-22'; # DATE
13             our $DIST = 'Log-ger-Layout-Pattern'; # DIST
14             our $VERSION = '0.009'; # VERSION
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(%s:%d)",
50             $per_message_data{caller1}[3],
51             $per_message_data{caller1}[3] ? ' ' : '',
52             $per_message_data{caller0}[1],
53             $per_message_data{caller0}[2],
54             );
55             },
56             'L' => sub { $per_message_data{caller0}[2] },
57             'm' => sub { $_[0] },
58             'M' => sub {
59             $per_message_data{caller1}[3] // '';
60             },
61             'n' => sub { "\n" },
62             'p' => sub { $_[3] },
63             'P' => sub { $$ },
64             'r' => sub { sprintf("%.3f", $time_now - $time_start) },
65             'R' => sub { sprintf("%.3f", $time_now - $time_last ) },
66             'T' => sub {
67             join(", ", map { "$_->[3] called at $_->[1] line $_->[2]" }
68             @{ $per_message_data{callers} });
69             },
70             '_{vmsize}' => sub {
71             unless ($cache{pid_stat_time} &&
72             $cache{pid_stat_time} >= $time_now-1) {
73             open my $fh, "<", "/proc/$$/stat" or die;
74             $cache{pid_stat} = [split /\s+/, scalar(<$fh>)];
75             $cache{pid_stat_time} = $time_now;
76             close $fh;
77             }
78             sprintf("%d", $cache{pid_stat}[22]/1024);
79             },
80              
81             # test
82             #'z' => sub { use DD; my $i = 0; while (my @c = caller($i++)) { dd \@c } },
83             '%' => sub { '%' },
84             );
85              
86             sub meta { +{
87 17     17 0 85687 v => 2,
88             } }
89              
90             my $re = qr/%(_\{\w+\}|[A-Za-z%])/;
91             sub _layout {
92 17     17   58 my $format = shift;
93 17         42 my $packages_to_ignore = shift;
94 17         53 my $subroutines_to_ignore = shift;
95              
96 17         74 ($time_last, $time_now) = ($time_now, time());
97 17         55 %per_message_data = ();
98              
99 17         42 my %mentioned_formats;
100 17         209 while ($format =~ m/$re/g) {
101 20 50       114 if (exists $format_for{$1}) {
102 20         119 $mentioned_formats{$1} = 1;
103             } else {
104 0         0 die "Unknown format '%$1'";
105             }
106             }
107              
108 17 100 100     159 if ($mentioned_formats{C} ||
      100        
      100        
109             $mentioned_formats{F} ||
110             $mentioned_formats{L} ||
111             $mentioned_formats{l}
112             ) {
113             $per_message_data{caller0} =
114 4         23 [Devel::Caller::Util::caller (0, 0, $packages_to_ignore, $subroutines_to_ignore)];
115             }
116 17 100 66     454 if ($mentioned_formats{l} ||
117             $mentioned_formats{M}
118             ) {
119             $per_message_data{caller1} =
120 1         5 [Devel::Caller::Util::caller (1, 0, $packages_to_ignore, $subroutines_to_ignore)];
121             }
122 17 100       163 if ($mentioned_formats{T}) {
123             $per_message_data{callers} =
124 1         8 [Devel::Caller::Util::callers(0, 0, $packages_to_ignore, $subroutines_to_ignore)];
125             }
126              
127 17         389 $format =~ s#$re#$format_for{$1}->(@_)#eg;
  20         80  
128 17         133 $format;
129             }
130              
131             sub get_hooks {
132 17     17 0 266 my %plugin_conf = @_;
133              
134 17 50       71 $plugin_conf{format} or die "Please specify format";
135 17   33     151 $plugin_conf{packages_to_ignore} //= qr/\A(?:Try::Tiny|Log::ger(?:::.+)?)\z/;
136              
137             return {
138             create_layouter => [
139             __PACKAGE__, # key
140             50, # priority
141             sub { # hook
142 17     17   4363 my %hook_args = @_; # see Log::ger::Manual::Internals/"Arguments passed to hook"
143             my $layouter = sub {
144 17         25619 _layout($plugin_conf{format}, $plugin_conf{packages_to_ignore}, $plugin_conf{subroutines_to_ignore}, @_);
145 17         62 };
146 17         56 [$layouter];
147 17         152 }],
148             };
149             }
150              
151             1;
152             # ABSTRACT: Pattern layout
153              
154             __END__