File Coverage

blib/lib/Net/SolarWinds/FileRotationBase.pm
Criterion Covered Total %
statement 69 70 98.5
branch 19 26 73.0
condition n/a
subroutine 13 13 100.0
pod 6 7 85.7
total 107 116 92.2


line stmt bran cond sub pod time code
1             package Net::SolarWinds::FileRotationBase;
2            
3 5     5   780 use strict;
  5         17  
  5         186  
4 5     5   43 use warnings;
  5         14  
  5         213  
5 5     5   3582 use IO::File;
  5         19473  
  5         904  
6 5     5   3196 use File::Copy qw(move);
  5         13225  
  5         406  
7 5     5   243 use base qw(Net::SolarWinds::ConstructorHash);
  5         20  
  5         1778  
8 5     5   44 use Carp qw(croak);
  5         15  
  5         3768  
9            
10             =pod
11            
12             =head1 NAME
13            
14             Net::SolarWinds::FileRotationBase - base file rotation framework
15            
16             =head1 SYNOPSIS
17            
18             use base qw(Net::SolarWinds::FileRotationBase);
19            
20             =head1 DESCRIPTION
21            
22             This modle is intended to be used as a base module for modules that require an auto file rotation framework. Auto file rotation is handled by file size.
23            
24            
25             =head1 OO Methods
26            
27            
28             =over 3
29            
30             =cut
31            
32             =item * Object constructor
33            
34             The object constructor for this class has a collection of optional arguments. Arguments are passed to the constructor in key value pairs.
35            
36             Constructor useage example:
37            
38             my $fr=new Net::SolarWinds::FileRotationBase(folder=>'/var/logs/myapp',basefilename=>'someapp');
39            
40             Argument list is as follows (default values shown):
41            
42             # Fully quallified system path to the log file
43             filename=>'/path/to/some/file.log'
44            
45             # sets the folder files will be created and rotated under
46             folder=>'.',
47            
48             # sets the basefilename
49             basefilename => 'DefaultFile',
50            
51             # used to concat the folder and filenames togeather
52             pathconncat => '/',
53            
54             # sets thefile extention to be used
55             ext => 'log',
56            
57             # sets the number of files to keep in rotation
58             maxfilecount => 3,
59            
60             # sets the max file size ( 8mb )
61             maxsize => 1024 * 1024 * 8,
62            
63             # sets the autoflush state ( handy for real time info in the file )
64             autoflush => 1,
65            
66             # sets the file auto rotation flag
67             autorotate => 1,
68            
69             # glob ref will be overwritten with the current fh
70             mirror=>undef|\*STDERR
71            
72             =cut
73            
74             sub new {
75 13     13 0 4344 my ( $class, %args ) = @_;
76            
77 13         35 my $max_size=1024 * 1024 * 8;
78 13         100 my $self = $class->SUPER::new(
79             folder => '.',
80             basefilename => 'DefaultFile',
81             pathconncat => '/',
82             ext => 'log',
83             maxfilecount => 3,
84             maxsize => $max_size,
85             autoflush => 1,
86             autorotate => 1,
87             mirror =>undef,
88             %args
89             );
90            
91 13         56 return $self;
92             }
93            
94             =item * $fr->set_mirror(\*STDERR);
95            
96             Sets a file handle to be mirroed to:
97            
98             =cut
99            
100             sub set_mirror {
101 1     1 1 7 my ($self,$glob)=@_;
102            
103 1         3 $self->{mirror}=$glob;
104            
105 1         4 my $fh=$self->get_fh;
106 1 50       5 return unless $fh;
107 1         4 *$glob=$fh;
108             }
109            
110             =item * my $filename=$fr->generate_filename;
111            
112             Retuns the filename of the active file.
113            
114             =cut
115            
116             sub generate_filename {
117 17     17 1 2329 my ($self) = @_;
118            
119            
120 17 100       82 return $self->{filename} if exists $self->{filename};
121            
122             my $filename =
123             $self->{folder}
124             . $self->{pathconncat}
125             . $self->{basefilename} . '.'
126 10         48 . $self->{ext};
127             }
128            
129             =item * my $fh=$fr->get_fh;
130            
131             Returns the active filehandle.
132            
133             =cut
134            
135             sub get_fh {
136 66     66 1 180 my ($self) = @_;
137            
138             # assumes this is defined correctly if it exists..
139             # if some one mucks with the internals this can be painful!
140 66 100       294 return $self->{fh} if exists $self->{fh};
141            
142             # if we got here then we have no file handle!
143            
144 6         18 my $filename = $self->generate_filename;
145            
146 6         44 my $fh = new IO::File(qq{>>$filename});
147            
148             # failed to open the file?
149             # well this is pretty much the end of the world..
150             # time to blame some one else!
151 6 50       695 croak qq{Failed to create file "$filename" error was: $!\n}
152             unless defined($fh);
153            
154 6         35 $fh->autoflush( $self->{autoflush} );
155            
156 6         255 $self->{fh} = $fh;
157 6 100       21 if(defined($self->{mirror})) {
158 2         6 my $mirror=$self->{mirror};
159 2         8 *$mirror=$fh;
160             }
161            
162 6         15 return $fh;
163             }
164            
165            
166             =item * $fr->rotate_files
167            
168             Forces log files to be rotated now!
169            
170             =cut
171            
172             sub rotate_files {
173 3     3 1 1370 my ($self) = @_;
174            
175 3         7 my $max_files = $self->{maxfilecount};
176 3         10 my $basefile = $self->generate_filename;
177 3         11 ROTATE_LOOP: for ( my $count = $max_files ; $count > 0 ; --$count ) {
178            
179 6         17 my $targetfile = qq{$basefile.$count};
180            
181             # skip this file if it does not exist
182 6 100       49 next ROTATE_LOOP unless ( -e $targetfile );
183            
184 3         7 my $next_count = 1 + $count;
185 3         7 my $nextfile = $basefile . '.' . ($next_count);
186            
187             # last file check
188 3 100       11 if ( $next_count > $max_files ) {
189            
190             # this is the last file to manage in the list
191             # we look for one after it and remove it as well
192             # out of the goodness of our heart
193 1 50       7 unlink $nextfile if -e $nextfile;
194            
195             # delete the elder file
196 1         73 unlink $targetfile;
197 1         5 next ROTATE_LOOP;
198            
199             }
200            
201 2         9 move( $targetfile, $nextfile );
202            
203             }
204 3         117 my $nextfile = qq{$basefile.1};
205            
206             # move the current file to the .1 position
207 3         11 $self->close_fh;
208 3         12 return move( $basefile, $nextfile );
209            
210             }
211            
212            
213             =item * $fr->close_fh;
214            
215             Closes the current active file handle.
216            
217             =cut
218            
219             sub close_fh {
220 4     4 1 10 my ($self) = @_;
221            
222 4 100       14 return 1 unless exists $self->{fh};
223            
224 3         7 my $fh = $self->{fh};
225            
226 3         6 delete $self->{fh};
227            
228 3         38 return close($fh);
229             }
230            
231             =item * $fr->write_to_file("Something to write to my file\n");
232            
233             Writes the list of arguments to the target file.
234            
235             =cut
236            
237             sub write_to_file {
238 60     60 1 2848 my ( $self, @data ) = @_;
239 60         242 my $fh = $self->get_fh;
240            
241 60 50       321 return 0 unless $fh;
242            
243 60 50       871 return 0 unless print $fh @data;
244            
245 60 50       1307 return 1 unless $self->{autorotate};
246            
247             #auto rotate file checks
248 60         260 my $pos = tell($fh);
249            
250 60 50       832 return 1 unless $pos >= $self->{maxsize};
251            
252 0           return $self->rotate_files;
253            
254             }
255            
256             =pod
257            
258             =back
259            
260             =head1 AUTHOR
261            
262             Michael Shipper
263            
264             =cut
265            
266             1;