File Coverage

blib/lib/Log/JSON/Lines.pm
Criterion Covered Total %
statement 72 73 98.6
branch 16 28 57.1
condition 5 6 83.3
subroutine 21 22 95.4
pod 14 14 100.0
total 128 143 89.5


line stmt bran cond sub pod time code
1             package Log::JSON::Lines;
2 2     2   135726 use 5.006; use strict; use warnings; our $VERSION = '0.01';
  2     2   16  
  2     2   19  
  2         6  
  2         41  
  2         9  
  2         3  
  2         103  
3 2     2   927 use JSON::Lines; use POSIX; use Time::HiRes;
  2     2   59502  
  2     2   21  
  2         1058  
  2         11959  
  2         11  
  2         6100  
  2         2554  
  2         8  
4 2     2   174 use Fcntl qw/ :flock /; use Clone;
  2     2   5  
  2         184  
  2         856  
  2         4694  
  2         1758  
5              
6             sub new {
7 1     1 1 98 my ($class, $file, $level, %jsonl_args) = @_;
8 1 50       17 bless {
9             _file => $file,
10             _jsonl => JSON::Lines->new( %jsonl_args ),
11             _level => defined $level ? $level : 8,
12             _levels => {
13             emerg => 1,
14             alert => 2,
15             crit => 3,
16             err => 4,
17             warning => 5,
18             notice => 6,
19             info => 7,
20             debug => 8,
21             },
22             }, $class;
23             }
24              
25 0     0 1 0 sub file { $_[0]->{_file} }
26              
27 18     18 1 46 sub levels { $_[0]->{_levels} }
28              
29 9     9 1 25 sub level { $_[0]->{_level} }
30              
31             sub jsonl {
32 4     4 1 18 $_[0]->{_jsonl}->clear_stream;
33 4         23 $_[0]->{_jsonl};
34             }
35              
36             sub log {
37 9     9 1 24 my($self, $level, $msg) = @_;
38             die "Invalid level ${level} passed to Log::JSON::Lines->log"
39 9 50       20 unless $self->levels->{$level};
40 9 100       18 return if $self->levels->{$level} > $self->level;
41 4 50       53 $msg = ! ref $msg ? { message => $msg } : Clone::clone($msg);
42 4         11 $msg->{level} = $level;
43 4         17 my ($epoch, $microseconds) = Time::HiRes::gettimeofday;
44 4         259 $msg->{timestamp} = sprintf "%s.%06.0f+00:00",
45             POSIX::strftime("%Y-%m-%dT%H:%M:%S", gmtime($epoch)),
46             $microseconds;
47 4         12 my @caller; my $i = 0; my @stack;
  4         10  
  4         5  
48 4         39 while(@caller = caller($i++)){
49 8 100       41 next if $caller[0] eq 'Log::JSON::Lines';
50 4         12 $stack[$i+1]->{module} = $caller[0];
51 4 50       39 $stack[$i+1]->{file} = $1 if $caller[1] =~ /([^\/]+)$/;;
52 4 50       23 $stack[$i+1]->{line} = $1 if $caller[2] =~ /(\d+)/;
53 4 50       38 $stack[$i]->{sub} = $1 if $caller[3] =~ /([^:]+)$/;
54             }
55             $msg->{stacktrace} = join '->', reverse map {
56 4 50       19 my $module = $_->{module} !~ m/^main$/ ? $_->{module} : $_->{file};
57             $_->{sub}
58             ? $module . '::' . $_->{sub} . ':' . $_->{line}
59             : $module . ':' . $_->{line}
60 4 50       23 } grep {
61 4         10 $_ && $_->{module} && $_->{line} && $_->{file}
62 16 50 100     63 } @stack;
      66        
63 4 50       11 delete $msg->{stacktrace} unless $msg->{stacktrace};
64 4         12 $msg = $self->jsonl->add_line($msg);
65 4 50       406 open my $fh, ">>", $self->{_file} or die "Cannot open log file $self->{_file}: $!";
66 4         42 flock $fh, LOCK_EX;
67 4 50       80 print $fh ($msg =~ m/\n$/ ? $msg : "$msg\n");
68 4         123 close $fh;
69 4         37 $msg;
70             }
71              
72             sub emerg {
73 1     1 1 3 my $self = shift;
74 1         4 $self->log('emerg', @_);
75             }
76              
77             sub alert {
78 1     1 1 3 my $self = shift;
79 1         4 $self->log('alert', @_);
80             }
81              
82             sub crit {
83 1     1 1 4 my $self = shift;
84 1         3 $self->log('crit', @_);
85             }
86              
87             sub err {
88 1     1 1 3 my $self = shift;
89 1         4 $self->log('err', @_);
90             }
91              
92             sub warning {
93 1     1 1 4 my $self = shift;
94 1         4 $self->log('warning', @_);
95             }
96              
97             sub notice {
98 1     1 1 3 my $self = shift;
99 1         3 $self->log('notice', @_);
100             }
101              
102             sub info {
103 1     1 1 2 my $self = shift;
104 1         3 $self->log('info', @_);
105             }
106              
107             sub debug {
108 1     1 1 2 my $self = shift;
109 1         3 $self->log('debug', @_);
110             }
111              
112             =head1 NAME
113              
114             Log::JSON::Lines - Log in JSONLines format
115              
116             =head1 VERSION
117              
118             Version 0.01
119              
120             =cut
121              
122             =head1 SYNOPSIS
123              
124             Quick summary of what the module does.
125              
126             use Log::JSON::Lines;
127              
128             my $logger = Log::JSON::Lines->new(
129             '/var/log/definition.log',
130             4,
131             pretty => 1,
132             canonical => 1
133             );
134            
135             $logger->log('info', 'Lets log JSON lines.');
136              
137             $logger->emerg({
138             message => 'emergency',
139             definition => [
140             'a serious, unexpected, and often dangerous situation requiring immediate action.'
141             ]
142             });
143            
144             $logger->alert({
145             message => 'alert',
146             definition => [
147             'quick to notice any unusual and potentially dangerous or difficult circumstances; vigilant.'
148             ]
149             });
150              
151             $logger->crit({
152             message => 'critical',
153             definition => [
154             'expressing adverse or disapproving comments or judgements.'
155             ]
156             });
157              
158             $logger->err({
159             message => 'error',
160             definition => [
161             'the state or condition of being wrong in conduct or judgement.'
162             ]
163             });
164              
165             # the below will not log as the severity level is set to 4 (error)
166              
167             $logger->warning({
168             message => 'warning',
169             definition => [
170             'a statement or event that warns of something or that serves as a cautionary example.'
171             ]
172             });
173              
174             $logger->notice({
175             message => 'notice',
176             definition => [
177             'the fact of observing or paying attention to something.'
178             ]
179             });
180              
181             $logger->info({
182             message => 'information',
183             definition => [
184             'what is conveyed or represented by a particular arrangement or sequence of things.'
185             ]
186             });
187              
188             $logger->debug({
189             message => 'debug',
190             definition => [
191             'identify and remove errors from (computer hardware or software).'
192             ]
193             });
194              
195             =head1 SUBROUTINES/METHODS
196              
197             =head2 new
198              
199             Instantiate a new Log::JSON::Lines object. This expects a filename and optionally a level which value is between 0 to 8 and params that will be passed through to instantiate the JSON::Lines object.
200              
201             my $logger = Log::JSON::Lines->new($filename, $severity_level, %JSON::Lines::params);
202              
203             =head2 file
204              
205             Returns the current log file name.
206              
207             $logger->file();
208              
209             =head2 levels
210              
211             Returns the severity level mapping.
212              
213             $logger->levels();
214              
215             =head2 level
216              
217             Returns the current severity level.
218              
219             $logger->level();
220              
221             =head2 jsonl
222              
223             Returns the JSON::Lines object used to encode the line.
224              
225             $logger->jsonl();
226              
227             =head2 log
228              
229             Log a message to the specified log file. This expects a severity level to be passed and either a string message or hashref containing information that you would like to log.
230              
231             $logger->log($severity, $message);
232              
233             =head2 emerg - 1
234              
235             Log a emerg line to the specified log file. This expects either a string or hashref containing information that you would like to log.
236              
237             $logger->emerg($message);
238              
239             =head2 alert - 2
240              
241             Log a alert line to the specified log file. This expects either a string or hashref containing information that you would like to log.
242              
243             $logger->alert($message);
244              
245             =head2 crit - 3
246              
247             Log a critical line to the specified log file. This expects either a string or hashref containing information that you would like to log.
248              
249             $logger->crit($message);
250              
251             =head2 err - 4
252              
253             Log a error line to the specified log file. This expects either a string or hashref containing information that you would like to log.
254              
255             $logger->err($message);
256              
257             =head2 warning - 5
258              
259             Log a warning line to the specified log file. This expects either a string or hashref containing information that you would like to log.
260              
261             $logger->warning($message);
262              
263             =head2 notice - 6
264              
265             Log a notice line to the specified log file. This expects either a string or hashref containing information that you would like to log.
266              
267             $logger->notice($message);
268              
269             =head2 info - 7
270              
271             Log a info line to the specified log file. This expects either a string or hashref containing information that you would like to log.
272              
273             $logger->info($message);
274              
275             =head2 debug - 8
276              
277             Log a debug line to the specified log file. This expects either a string or hashref containing information that you would like to log.
278              
279             $logger->debug($message);
280              
281             =head1 AUTHOR
282              
283             LNATION, C<< >>
284              
285             =head1 BUGS
286              
287             Please report any bugs or feature requests to C, or through
288             the web interface at L. I will be notified, and then you'll
289             automatically be notified of progress on your bug as I make changes.
290              
291             =head1 SUPPORT
292              
293             You can find documentation for this module with the perldoc command.
294              
295             perldoc Log::JSON::Lines
296              
297             You can also look for information at:
298              
299             =over 4
300              
301             =item * RT: CPAN's request tracker (report bugs here)
302              
303             L
304              
305             =item * CPAN Ratings
306              
307             L
308              
309             =item * Search CPAN
310              
311             L
312              
313             =back
314              
315             =head1 ACKNOWLEDGEMENTS
316              
317             =head1 LICENSE AND COPYRIGHT
318              
319             This software is Copyright (c) 2020 by LNATION.
320              
321             This is free software, licensed under:
322              
323             The Artistic License 2.0 (GPL Compatible)
324              
325             =cut
326              
327             1; # End of Log::JSON::Lines