line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Net::SolarWinds::FileRotationBase;
|
2
|
|
|
|
|
|
|
|
3
|
5
|
|
|
5
|
|
418
|
use strict;
|
|
5
|
|
|
|
|
5
|
|
|
5
|
|
|
|
|
105
|
|
4
|
5
|
|
|
5
|
|
13
|
use warnings;
|
|
5
|
|
|
|
|
5
|
|
|
5
|
|
|
|
|
86
|
|
5
|
5
|
|
|
5
|
|
2009
|
use IO::File;
|
|
5
|
|
|
|
|
11759
|
|
|
5
|
|
|
|
|
506
|
|
6
|
5
|
|
|
5
|
|
2180
|
use File::Copy qw(move);
|
|
5
|
|
|
|
|
8040
|
|
|
5
|
|
|
|
|
237
|
|
7
|
5
|
|
|
5
|
|
20
|
use base qw(Net::SolarWinds::ConstructorHash);
|
|
5
|
|
|
|
|
21
|
|
|
5
|
|
|
|
|
1180
|
|
8
|
5
|
|
|
5
|
|
20
|
use Carp qw(croak);
|
|
5
|
|
|
|
|
4
|
|
|
5
|
|
|
|
|
2362
|
|
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
|
2426
|
my ( $class, %args ) = @_;
|
76
|
|
|
|
|
|
|
|
77
|
13
|
|
|
|
|
11
|
my $max_size=1024 * 1024 * 8;
|
78
|
13
|
|
|
|
|
54
|
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
|
|
|
|
|
28
|
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
|
4
|
my ($self,$glob)=@_;
|
102
|
|
|
|
|
|
|
|
103
|
1
|
|
|
|
|
1
|
$self->{mirror}=$glob;
|
104
|
|
|
|
|
|
|
|
105
|
1
|
|
|
|
|
2
|
my $fh=$self->get_fh;
|
106
|
1
|
50
|
|
|
|
3
|
return unless $fh;
|
107
|
1
|
|
|
|
|
2
|
*$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
|
1010
|
my ($self) = @_;
|
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
|
120
|
17
|
100
|
|
|
|
49
|
return $self->{filename} if exists $self->{filename};
|
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
my $filename =
|
123
|
|
|
|
|
|
|
$self->{folder}
|
124
|
|
|
|
|
|
|
. $self->{pathconncat}
|
125
|
|
|
|
|
|
|
. $self->{basefilename} . '.'
|
126
|
10
|
|
|
|
|
26
|
. $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
|
54
|
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
|
|
|
|
180
|
return $self->{fh} if exists $self->{fh};
|
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
# if we got here then we have no file handle!
|
143
|
|
|
|
|
|
|
|
144
|
6
|
|
|
|
|
9
|
my $filename = $self->generate_filename;
|
145
|
|
|
|
|
|
|
|
146
|
6
|
|
|
|
|
24
|
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
|
|
|
|
423
|
croak qq{Failed to create file "$filename" error was: $!\n}
|
152
|
|
|
|
|
|
|
unless defined($fh);
|
153
|
|
|
|
|
|
|
|
154
|
6
|
|
|
|
|
18
|
$fh->autoflush( $self->{autoflush} );
|
155
|
|
|
|
|
|
|
|
156
|
6
|
|
|
|
|
137
|
$self->{fh} = $fh;
|
157
|
6
|
100
|
|
|
|
10
|
if(defined($self->{mirror})) {
|
158
|
2
|
|
|
|
|
2
|
my $mirror=$self->{mirror};
|
159
|
2
|
|
|
|
|
4
|
*$mirror=$fh;
|
160
|
|
|
|
|
|
|
}
|
161
|
|
|
|
|
|
|
|
162
|
6
|
|
|
|
|
7
|
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
|
695
|
my ($self) = @_;
|
174
|
|
|
|
|
|
|
|
175
|
3
|
|
|
|
|
3
|
my $max_files = $self->{maxfilecount};
|
176
|
3
|
|
|
|
|
4
|
my $basefile = $self->generate_filename;
|
177
|
3
|
|
|
|
|
6
|
ROTATE_LOOP: for ( my $count = $max_files ; $count > 0 ; --$count ) {
|
178
|
|
|
|
|
|
|
|
179
|
6
|
|
|
|
|
7
|
my $targetfile = qq{$basefile.$count};
|
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
# skip this file if it does not exist
|
182
|
6
|
100
|
|
|
|
40
|
next ROTATE_LOOP unless ( -e $targetfile );
|
183
|
|
|
|
|
|
|
|
184
|
3
|
|
|
|
|
3
|
my $next_count = 1 + $count;
|
185
|
3
|
|
|
|
|
4
|
my $nextfile = $basefile . '.' . ($next_count);
|
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
# last file check
|
188
|
3
|
100
|
|
|
|
6
|
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
|
|
|
|
4
|
unlink $nextfile if -e $nextfile;
|
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
# delete the elder file
|
196
|
1
|
|
|
|
|
52
|
unlink $targetfile;
|
197
|
1
|
|
|
|
|
3
|
next ROTATE_LOOP;
|
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
}
|
200
|
|
|
|
|
|
|
|
201
|
2
|
|
|
|
|
39
|
move( $targetfile, $nextfile );
|
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
}
|
204
|
3
|
|
|
|
|
84
|
my $nextfile = qq{$basefile.1};
|
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
# move the current file to the .1 position
|
207
|
3
|
|
|
|
|
5
|
$self->close_fh;
|
208
|
3
|
|
|
|
|
7
|
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
|
4
|
my ($self) = @_;
|
221
|
|
|
|
|
|
|
|
222
|
4
|
100
|
|
|
|
7
|
return 1 unless exists $self->{fh};
|
223
|
|
|
|
|
|
|
|
224
|
3
|
|
|
|
|
3
|
my $fh = $self->{fh};
|
225
|
|
|
|
|
|
|
|
226
|
3
|
|
|
|
|
3
|
delete $self->{fh};
|
227
|
|
|
|
|
|
|
|
228
|
3
|
|
|
|
|
26
|
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
|
1513
|
my ( $self, @data ) = @_;
|
239
|
60
|
|
|
|
|
80
|
my $fh = $self->get_fh;
|
240
|
|
|
|
|
|
|
|
241
|
60
|
50
|
|
|
|
166
|
return 0 unless $fh;
|
242
|
|
|
|
|
|
|
|
243
|
60
|
50
|
|
|
|
399
|
return 0 unless print $fh @data;
|
244
|
|
|
|
|
|
|
|
245
|
60
|
50
|
|
|
|
549
|
return 1 unless $self->{autorotate};
|
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
#auto rotate file checks
|
248
|
60
|
|
|
|
|
105
|
my $pos = tell($fh);
|
249
|
|
|
|
|
|
|
|
250
|
60
|
50
|
|
|
|
348
|
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;
|