File Coverage

blib/lib/Log/Handler/Output/File/Stamper.pm
Criterion Covered Total %
statement 61 76 80.2
branch 10 26 38.4
condition n/a
subroutine 15 15 100.0
pod 2 2 100.0
total 88 119 73.9


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Log::Handler::Output::File::Stamper - Log messages to a file(with stamp in the filename).
4              
5              
6             =head1 SYNOPSIS
7              
8             use Log::Handler::Output::File::Stamper;
9              
10             my $log = Log::Handler::Output::File::Stamper->new(
11             filename => "foo%d{yyyyMMdd}.log",
12             );
13              
14             $log->log(message => 'log message'); # => foo20130113.log
15              
16              
17             =head1 DESCRIPTION
18              
19             This module is subclasses C for logging to date/time/pid
20             stamped files. See L for instructions on usage.
21              
22             This module differs only on the following points:
23              
24             =over 4
25              
26             =item fork()-safe
27              
28             This module will close and re-open the logfile after a fork.
29             Instead, there are no Cs to open a log file. It is C mode only.
30             And C option was removed(It is always set 1:enabled).
31              
32             =item multitasking-safe
33              
34             This module uses flock() to lock the file while writing to it.
35             Then also C option was removed(means always set 1:enabled).
36              
37             =item stamped filenames
38              
39             This module supports a special tag in the filename that will expand to
40             the current date/time/pid. See also L
41              
42             =back
43              
44              
45             =head1 METHODS
46              
47             =head2 new()
48              
49             Call C to create a new Log::Handler::Output::File::Stamper object.
50              
51             =head2 log()
52              
53             Call C if you want to log messages to the log file(with stamp).
54              
55             You can check other methods in L document.
56              
57              
58             =head1 REPOSITORY
59              
60             Log::Handler::Output::File::Stamper is hosted on github
61            
62              
63              
64             =head1 AUTHOR
65              
66             Dai Okabayashi Ebayashi@cpan.orgE
67              
68             Source codes of this module were borrowed from below modules, very very thanks.
69              
70             L, L
71              
72              
73             =head1 SEE ALSO
74              
75             L, L
76              
77              
78             =head1 LICENSE
79              
80             This module is free software; you can redistribute it and/or
81             modify it under the same terms as Perl itself. See L.
82              
83             =cut
84              
85             package Log::Handler::Output::File::Stamper;
86 2     2   128914 use strict;
  2         5  
  2         91  
87 2     2   12 use warnings;
  2         4  
  2         77  
88 2     2   13 use Carp qw/croak/;
  2         8  
  2         159  
89 2     2   2159 use Log::Handler::Output::File;
  2         37539  
  2         61  
90 2     2   58 use Fcntl qw( :flock O_WRONLY O_APPEND O_TRUNC O_EXCL O_CREAT );
  2         6  
  2         427  
91 2     2   1851 use Log::Stamper;
  2         3474  
  2         141  
92              
93             our @ISA = qw/Log::Handler::Output::File/;
94              
95             our $VERSION = '0.03';
96             our $ERRSTR = "";
97              
98             our $TIME_HIRES_AVAILABLE = undef;
99             BEGIN {
100 2     2   145 eval { require Time::HiRes; };
  2         1974  
101 2 50       2162 if ($@) {
102 0         0 $TIME_HIRES_AVAILABLE = 0;
103             } else {
104 2         4304 $TIME_HIRES_AVAILABLE = 1;
105             }
106             }
107              
108             sub new {
109 2     2 1 2367 my $class = shift;
110 2         17 my $opts = $class->_validate(@_);
111              
112 2         269 my $self = bless $opts, $class;
113              
114             # force options
115 2         13 $self->{mode} = O_WRONLY | O_APPEND | O_CREAT; # append
116 2         4 $self->{reopen} = 1;
117 2         5 $self->{filelock} = 1;
118              
119             # split pathname into path, basename, extension
120 2 50       23 if ($self->{filename} =~ /^(.*)\%d\{([^\}]*)\}(.*)$/) {
    0          
121 2         12 $self->{_stamper_filename_prefix} = $1;
122 2         8 $self->{_stamper_filename_postfix} = $3;
123 2         16 $self->{_stamper_filename_format} = Log::Stamper->new($2);
124 2         520 $self->{filename} = $self->_create_file_name();
125             }
126             elsif ($self->{filename} =~ /^(.*)(\.[^\.]+)$/) {
127 0         0 $self->{_stamper_filename_prefix} = $1;
128 0         0 $self->{_stamper_filename_postfix} = $2;
129 0         0 $self->{_stamper_filename_format} = Log::Stamper->new('-yyyy-MM-dd');
130 0         0 $self->{filename} = $self->_create_file_name();
131             }
132             else {
133 0         0 $self->{_stamper_filename_prefix} = $self->{filename};
134 0         0 $self->{_stamper_filename_postfix} = '';
135 0         0 $self->{_stamper_filename_format} = Log::Stamper->new('.yyyy-MM-dd');
136 0         0 $self->{filename} = $self->_create_file_name();
137             }
138              
139             # open the log file permanent
140 2 50       11 if ($self->{fileopen}) {
141 2 50       7 $self->_open
142             or croak $self->errstr;
143             }
144              
145 2         7 return $self;
146             }
147              
148             sub log {
149 1     1 1 1503 my $self = shift;
150              
151 1         4 $self->_file_stamp;
152 1 50       4 $self->_fork_safe or return;
153              
154 1         11 $self->SUPER::log(@_);
155             }
156              
157             #
158             # private stuff
159             #
160             sub _open {
161 2     2   5 my $self = shift;
162              
163 2 50       16 $self->SUPER::_open(@_) or return;
164 2         314 $self->{_stamper_fh_pid} = $$;
165 2         12 return 1;
166             }
167              
168             sub _fork_safe {
169 1     1   2 my $self = shift;
170              
171 1 50       4 if ($self->{fileopen}) {
172 1         4 my $pid = $$;
173 1 50       26 if ( $self->{_stamper_fh_pid} !~ m!^$pid$! ) {
174 0 0       0 $self->close or return;
175 0 0       0 $self->_open or return;
176             }
177             }
178              
179 1         4 return 1;
180             }
181              
182             sub _file_stamp {
183 1     1   3 my $self = shift;
184              
185 1         4 my $filename = $self->_create_file_name;
186 1 50       6 if ($filename ne $self->{filename}) {
187 0         0 $self->{filename} = $filename;
188 0         0 $self->{_stamper_fh_pid} = 'x' # force reopen
189             }
190              
191 1         23 return 1;
192             }
193              
194             sub _create_file_name {
195 3     3   6 my $self = shift;
196              
197 3         13 return $self->{_stamper_filename_prefix}
198             . $self->_format()
199             . $self->{_stamper_filename_postfix};
200             }
201              
202             sub _format {
203 3     3   6 my $self = shift;
204              
205 3         10 my $result = $self->{_stamper_filename_format}->format($self->_current_time);
206 3         190 $result =~ s/(\$+)/sprintf('%0'.length($1).'.'.length($1).'u', $$)/eg;
  0         0  
207 3         14 return $result;
208             }
209              
210             sub _current_time {
211 3 50   3   10 if($TIME_HIRES_AVAILABLE) {
212 0         0 return(Time::HiRes::gettimeofday());
213             }
214             else {
215 3         15 return(time(), 0);
216             }
217             }
218              
219             1;