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-03-11'; # DATE
5             our $DIST = 'Log-ger-Layout-Pattern'; # DIST
6             our $VERSION = '0.006'; # VERSION
7              
8 1     1   2216 use 5.010001;
  1         4  
9 1     1   5 use strict;
  1         2  
  1         17  
10 1     1   4 use warnings;
  1         2  
  1         24  
11              
12 1     1   410 use Devel::Caller::Util;
  1         325  
  1         35  
13 1     1   6 use Log::ger ();
  1         1  
  1         15  
14 1     1   430 use Time::HiRes qw(time);
  1         1100  
  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              
22             our %format_for = (
23             'c' => sub { $_[1]{category} },
24             'C' => sub { $per_message_data{caller0}[0] },
25             'd' => sub {
26             my @t = localtime($time_now);
27             sprintf(
28             "%04d-%02d-%02dT%02d:%02d:%02d",
29             $t[5]+1900, $t[4]+1, $t[3],
30             $t[2], $t[1], $t[0],
31             );
32             },
33             'D' => sub {
34             my @t = gmtime($time_now);
35             sprintf(
36             "%04d-%02d-%02dT%02d:%02d:%02d",
37             $t[5]+1900, $t[4]+1, $t[3],
38             $t[2], $t[1], $t[0],
39             );
40             },
41             'F' => sub { $per_message_data{caller0}[1] },
42             'H' => sub {
43             require Sys::Hostname;
44             Sys::Hostname::hostname();
45             },
46             'l' => sub {
47             sprintf(
48             "%s (%s:%d)",
49             $per_message_data{caller1}[3] // '',
50             $per_message_data{caller0}[1],
51             $per_message_data{caller0}[2],
52             );
53             },
54             'L' => sub { $per_message_data{caller0}[2] },
55             'm' => sub { $_[0] },
56             'M' => sub {
57             $per_message_data{caller1}[3] // '';
58             },
59             'n' => sub { "\n" },
60             'p' => sub { $_[3] },
61             'P' => sub { $$ },
62             'r' => sub { sprintf("%.3f", $time_now - $time_start) },
63             'R' => sub { sprintf("%.3f", $time_now - $time_last ) },
64             'T' => sub {
65             join(", ", map { "$_->[3] called at $_->[1] line $_->[2]" }
66             @{ $per_message_data{callers} });
67             },
68             # test
69             #'z' => sub { use DD; my $i = 0; while (my @c = caller($i++)) { dd \@c } },
70             '%' => sub { '%' },
71             );
72              
73             sub meta { +{
74 17     17 0 35255 v => 2,
75             } }
76              
77             sub _layout {
78 17     17   53 my $format = shift;
79 17         26 my $packages_to_ignore = shift;
80 17         33 my $subroutines_to_ignore = shift;
81              
82 17         45 ($time_last, $time_now) = ($time_now, time());
83 17         38 %per_message_data = ();
84              
85 17         20 my %mentioned_formats;
86 17         79 while ($format =~ m/%(.)/g) {
87 20 50       55 if (exists $format_for{$1}) {
88 20         57 $mentioned_formats{$1} = 1;
89             } else {
90 0         0 die "Unknown format '%$1'";
91             }
92             }
93              
94 17 100 100     94 if ($mentioned_formats{C} ||
      100        
      100        
95             $mentioned_formats{F} ||
96             $mentioned_formats{L} ||
97             $mentioned_formats{l}
98             ) {
99             $per_message_data{caller0} =
100 4         11 [Devel::Caller::Util::caller (0, 0, $packages_to_ignore, $subroutines_to_ignore)];
101             }
102 17 100 66     339 if ($mentioned_formats{l} ||
103             $mentioned_formats{M}
104             ) {
105             $per_message_data{caller1} =
106 1         3 [Devel::Caller::Util::caller (1, 0, $packages_to_ignore, $subroutines_to_ignore)];
107             }
108 17 100       99 if ($mentioned_formats{T}) {
109             $per_message_data{callers} =
110 1         5 [Devel::Caller::Util::callers(0, 0, $packages_to_ignore, $subroutines_to_ignore)];
111             }
112              
113 17         278 $format =~ s#%(.)#$format_for{$1}->(@_)#eg;
  20         53  
114 17         81 $format;
115             }
116              
117             sub get_hooks {
118 17     17 0 177 my %plugin_conf = @_;
119              
120 17 50       41 $plugin_conf{format} or die "Please specify format";
121             $plugin_conf{packages_to_ignore} //= [
122 17   50     84 "Log::ger",
123             "Log::ger::Layout::Pattern",
124             "Try::Tiny",
125             ];
126              
127             return {
128             create_layouter => [
129             __PACKAGE__, # key
130             50, # priority
131             sub { # hook
132 17     17   2737 my %hook_args = @_; # see Log::ger::Manual::Internals/"Arguments passed to hook"
133             my $layouter = sub {
134 17         15990 _layout($plugin_conf{format}, $plugin_conf{packages_to_ignore}, $plugin_conf{subroutines_to_ignore}, @_);
135 17         47 };
136 17         41 [$layouter];
137 17         93 }],
138             };
139             }
140              
141             1;
142             # ABSTRACT: Pattern layout
143              
144             __END__