File Coverage

blib/lib/Log/MultiChannel.pm
Criterion Covered Total %
statement 144 194 74.2
branch 39 68 57.3
condition 6 9 66.6
subroutine 22 29 75.8
pod 15 23 65.2
total 226 323 69.9


line stmt bran cond sub pod time code
1             package Log::MultiChannel;
2 1     1   22341 use vars qw($VERSION);
  1         2  
  1         68  
3 1     1   5 use Term::ANSIColor qw(:constants);
  1         2  
  1         249  
4             $VERSION = '1.08';
5             # -------------------- Notice ---------------------
6             # Copyright 2014 Paul LaPointe
7             # www.PaullaPointe.com/Logging-MultiChannel
8             # This program is dual licensed under the (Perl) Artistic License 2.0,
9             # and the Lesser GNU General Public License 3.0 (LGPL).
10             #
11             # This program is free software: you can redistribute it and/or modify
12             # it under the terms of the GNU Lesser General Public License as published by
13             # the Free Software Foundation, either version 3 of the License, or
14             # (at your option) any later version.
15             #
16             # This program is distributed in the hope that it will be useful,
17             # but WITHOUT ANY WARRANTY; without even the implied warranty of
18             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19             # GNU Lesser General Public License 3.0 for more details.
20             # You should have received a copy of the GNU General Public License 3.0
21             # in the licenses directory along with this program. If not, see
22             # .
23             #
24             # You should have received a copy of the Artistic License 2.
25             # in the licenses directory along with this program. If not, see
26             # .
27             #
28             # -------------------- End Notice ---------------------
29             =head1 NAME
30              
31             Log::MultiChannel - A full featured module for implementing log messages on multiple channels to multiple targets.
32              
33             =head2 FEATURES
34              
35             Features:
36             - Multi-channel logging, with the ablity to enable or disable channels dynamically.
37              
38             - Channels can be mapped to multiple Log files for duplication of messages.
39              
40             - Channels can be optional color coded. Each log file can enable or disable the color feature.
41              
42             - Channels can be selectively enabled for messages from specific modules.
43              
44             Advanced features:
45              
46             - Channels can be mapped to your own handles (Eg. socket) for writting to things beside log files.
47              
48             - Each Log file can use its own print function, or default to the one provided.
49              
50             Features for limiting and cycling logs:
51              
52             - Log files can optionally be limited to a specific line count.
53              
54             - Old copies of log files can optional be perserved or overwritten.
55              
56             - Old log files can be optionally moved to a different directory.
57              
58             Coming soon:
59              
60             - Thread safety.
61              
62             =head1 AUTHOR
63              
64             Paul LaPointe -
65              
66             =head2 LICENSE
67              
68             This program is dual licensed under the (Perl) Artistic License 2.0,
69             and the Lesser GNU General Public License 3.0 (LGPL).
70              
71             =head2 BUGS
72              
73             Please report any bugs or feature requests to bugs@paullapointe.org
74              
75             Please visit for complete documentation, examples, and more.
76              
77             =head2 METHODS
78              
79             =head3 Log ( channel, message, additional args... )
80              
81             Channel can be any string.
82             Message is the log message to write.
83             Additional args can be passed in for use by a custom log handler.
84              
85             =head3 startLogging( filename, preserve, limit, oldDir, printHandler )
86              
87             filename - the fully qualified filename for the log.
88              
89             preserve - An option to retain old copies of the log before overwritting (0 or 1).
90              
91             limit - An optional limit on the number of lines that can be written before cycling this log.
92              
93             oldDir - Move old log files to this fully qualified directory when overwritting.
94              
95             printHandler - An optional special print handler for this file.
96             Three print handlers are included in the module itself:
97             - logPrint - This is includes the date (only when it changes), time, channel, source filename, source line. E.g:
98             ---- 2014 Oct 8 ----
99             17.50.49 INF t/smokeTest.t-25 This is a test.
100              
101             - logPrintVerbose - This is includes the date and time, channel, source filename, source line. E.g:
102             INF Wed Oct 8 23:42:25 2014 t/smokeTest.t-101 This is the logPrintVerbose handler.
103              
104             - logPrintSimple - E.g:
105             INF This is the logPrintSimple handler.
106              
107             =head3 startLoggingOnHandle ( name, fileHandle, printHandler )
108              
109             name - Any arbitrary name for this log.
110              
111             filehandle - The filehandle to log with.
112              
113             printHandler - An optional special print handler for this file
114              
115             =head3 stopLogging ( Log filename )
116              
117             This will stop logging to the given log file.
118              
119             =head3 closeLogs();
120              
121             This will stop logging to ALL files (including any custom filehandles).
122              
123             =head3 mapChannel ( Channel, Log filename1, Log filename2, ... )
124              
125             This will map a channel to one or more log files by their name.
126              
127             =head3 mapChannelToLog ( Channel, Log filename )
128              
129             Maps a channel to this specific log name.
130              
131             =head3 unmapChannel ( Channel, [Log filename] )
132              
133             Unmaps all logs from a channel, or from a specific log file.
134              
135             =head3 enableChannel ( Channel )
136              
137             Enables log messages from a specific channel.
138              
139             =head3 disableChannel ( Channel )
140              
141             Disables log messages from a specific channel.
142              
143             =head3 enableChannelForModule ( Channel, Module )
144              
145             Enables log messages from a specific module for the given channel.
146              
147             =head3 disableChannelForModule ( Channel, Module )
148              
149             Disabled log messages from a specific module for the given channel (overriden by channel control).
150              
151             =head3 assignColorCode ( Channel , Ascii color code )
152              
153             Assigns a (typically) ASCII color code to a specific channel
154              
155             =head3 enableColor ( LogFilename )
156              
157             Enables color on a specific log filename.
158              
159             =head3 disableColor ( LogFilename )
160              
161             Disables color on a specific log filename.
162              
163             =head3 logStats ()
164              
165             Returns a list with a count of all messages logged to each channel.
166              
167             =head3 EXAMPLES
168              
169             =head4 Example 1: The simplest use case:
170              
171             use Log::MultiChannel qw(Log);
172             Log::MultiChannel::startLogging('myLogFile.log');
173             Log('INF','This is an info message'); # This will default to the last log openned
174             ...
175             Log::MultiChannel::stopLogging('myLogFile.log');
176             exit;
177              
178             =head4 Example 2: Using multiple logs and channels:
179              
180             use Log::MultiChannel qw(Log);
181             Log::MultiChannel::startLogging('myLogFile1.log');
182             Log::MultiChannel::startLogging('myLogFile2.log');
183              
184             Log::MultiChannel::mapChannel('INF','myLogFile1.log'); # Put INF messages in myLogFile1.log
185             Log::MultiChannel::mapChannel('ERR','myLogFile2.log'); # Put ERR messages in myLogFile2.log
186              
187             Log('INF','This is an Error message for myLogFile1.log');
188             Log('ERR','This is an info message for myLogFile2.log');
189              
190             Log::MultiChannel::closeLogs(); # This will close ALL log files that are open
191             exit;
192              
193             =head4 Example 3: Tee-ing output to STDOUT and a log file:
194              
195             #!/usr/bin/perl
196             # Example 8: This will tee (copy) the output that is sent to a log file
197             # to STDOUT, so it can be seen as the program runs.
198             use strict;
199             use warnings;
200             use Log::MultiChannel qw(Log);
201              
202             Log::MultiChannel::startLogging('myLogFile1.log');
203             Log::MultiChannel::startLoggingOnHandle('STDOUT',\*STDOUT);
204              
205             Log::MultiChannel::mapChannel('INF','myLogFile1.log','STDOUT'); # Put INF messages in myLogFile1.log
206              
207             Log('INF','This is an Error message for myLogFile1.log, that will also be printed on STDOUT');
208              
209             Log::MultiChannel::closeLogs(); # This will close ALL log files that are open
210             exit;
211              
212             =head4 More Examples are available in the distribution and at http://paullapointe.org/MultiChannel
213              
214             =cut
215              
216 1     1   4 use strict;
  1         5  
  1         28  
217 1     1   4 use warnings;
  1         0  
  1         28  
218             require Exporter;
219 1     1   494 use UNIVERSAL;
  1         10  
  1         3  
220 1     1   496 use IO::Handle;
  1         4640  
  1         1542  
221              
222             our @months = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
223             our @weekdays = qw( Sun Mon Tues Wed Thurs Fri Sat );
224              
225             our @ISA = 'Exporter';
226             our @EXPORT_OK = qw(Log startLogging startLoggingOnHandle stopLogging mapChannel unmapChannel enableChannel disableChannel enableChannelForModule disableChannelForModule assignColorCode enableColor disableColor logStats);
227              
228             my $defaultLog; # This tracks the last log file openned, which will be the default for unmapped channels
229              
230             my $channels; # This is a list of all available channels
231             # channel->{name}->{logs} - A list of all logs mapped to this channel
232             # channel->{name}->{count} - A count of all messages sent to this channel
233             # channel->{name}->{state} - 1 for on, 0 for off
234             # channel->{name}->{color} - An ascii color code to optional assign to the channel, for use with the default print handler
235              
236             my @logs; # This is a list of all available filehandles
237             # $logs[i]->{fh} - The actual filehandle
238             # $logs[i]->{count} - a count of messages sent to this filehandle since it was last openned or cycled
239             # $logs[i]->{limit} - a limit on the number of lines that can be printed to this filehandle before it will be cycled. 0 to disable cycling.
240             # $logs[i]->{oldDir} - a director name that old copies of this log will be moved to when overwritting.
241             # $logs[i]->{printHandler} - a print handler for this file
242             # $logs[i]->{filename} - the filename of for this filehandle
243             # $logs[i]->{colorOn} - This controls if this filehandle will use ascii color codes (for the default logPrint fn)
244             # $logs[i]->{currentYear} - The year of the last message printed on this log
245             # $logs[i]->{currentmday} - The current day of the month of the last message printed on this log
246              
247             my %filenameMap; # This maps a filename back to it's permenant Log object
248              
249              
250             # This will start a new log file and
251             # assign a set of channels to the log
252             # 0 - filename to open
253             # 1 - A limit for the number of lines written to this file, after which it will cycle
254             # 2 - A Code reference to a special print handler for this file
255             sub startLogging {
256 6     6 1 992 my $log;
257 6         24 $log->{filename} =shift; # Obviously, filename for the log
258 6         12 $log->{preserve} =shift; # An option to retain old copies of the log before overwritting.
259 6         15 $log->{limit} =shift; # An optional limit on the number of lines that can be written before cycling this log
260 6         10 $log->{oldDir} =shift; # Move old log files to this directory when overwritting
261 6         10 $log->{printHandler}=shift; # An optional special print handler for this file
262            
263             # If not provided, the printHandler will default to the std fn
264 6 50       20 unless ($log->{printHandler}) { $log->{printHandler}=\&logPrint; }
  6         21  
265            
266             # Check for an old copy of the log, and move it out of the way if desired
267 6 100       18 if ($log->{preserve}) {
268 1 50       16 if (-f $log->{filename}) { &moveOldLog($log); }
  1         4  
269             }
270              
271             # Open the file
272 6 50       806478 open($log->{fh}, ">$log->{filename}") or die ("Error! Unable to open log file $log->{filename} for writing.\n");
273 6         91 $log->{fh}->autoflush;
274            
275             # Now initialize this log
276 6         451 startLoggingInternal($log);
277             }
278             # This will start a new log file and
279             # assign a set of channels to the log
280             # 0 - Any arbitray name for this log, so we can work with it.
281             # 1 - The already openned filehandle
282             # 2 - A Code reference to a special print handler for this file
283             #
284             sub startLoggingOnHandle {
285 0     0 1 0 my $log;
286 0         0 $log->{filename} =shift; # In this case, just any name - it can be any string
287 0         0 $log->{fh} =shift; # Obviously, the fully qualified filename for the log
288 0         0 $log->{printHandler}=shift; # An optional special print handler for this file
289              
290 0         0 $log->{preserve}=0; # Disabled
291 0         0 $log->{limit} =0; # Disabled
292 0         0 $log->{oldDir} =''; # Disabled
293            
294             # If not provided, the printHandler will default to the std fn
295 0 0       0 unless ($log->{printHandler}) { $log->{printHandler}=\&logPrint; }
  0         0  
296              
297             # Now initialize this log
298 0         0 startLoggingInternal($log);
299             }
300              
301             # This sets up the
302             sub startLoggingInternal {
303 6     6 0 11 my $log=shift;
304              
305             # Reset the counter for this log
306 6         21 $log->{count}=0;
307              
308             # Initialize the last month day and year to 0
309 6         21 $log->{currentmday}=0;
310 6         10 $log->{currentYear}=0;
311            
312             # Also add this Log in the filenameMap, so we can easily find it with the name
313 6         55 $filenameMap{$log->{filename}}=$log;
314              
315             # Remember this most recent log as the new default for unmapped channels
316 6         9 $defaultLog=$log;
317              
318             # Add this new Log to our list
319 6         15 push @logs,$log;
320              
321 6         22 return $log->{fh};
322             }
323              
324             # This will set the handler of the specified log file
325             # to the provided handler
326             sub setPrintHandler {
327 3     3 0 295 my $logName=shift;
328 3         5 my $handler=shift;
329 3         4 my $log=$filenameMap{$logName};
330 3         3 $log->{printHandler}=\&{$handler};
  3         16  
331             }
332              
333             # This will map a set of channels to list of log files, specified by their name.
334             # Note! Channels are enabled by default. You must disable them if you want
335             # them turned off.
336             #
337             # Channels can be copied to multiple log files by calling this fn multiple
338             # times with different filenames.
339             #
340             sub mapChannel {
341 7     7 1 37 my $channel=shift;
342              
343             # Turn the channel on
344 7         17 enableChannel($channel);
345              
346             # Map the channel to each individual Log
347 7         72 foreach my $filename (@_) { &mapChannelToLog_Internal($channel,$filenameMap{$filename}); }
  7         18  
348             }
349              
350             # This will map a set of channels to a specific log file object.
351             # Note! Channels are enabled by default. You must disable them if you want
352             # them turned off.
353             #
354             # Channels can be copied to multiple log files by calling this fn multiple
355             # times with different logs.
356             #
357             # Eg.
358             sub mapChannelToLog_Internal {
359 10     10 0 12 my $channelName=shift;
360 10         12 my $log=shift;
361            
362             # If there is an existing list of logs for this channel
363             # add this log to it.
364 10 100       26 if ($channels->{$channelName}->{logs}) {
365 7         7 push @{$channels->{$channelName}->{logs}},$log;
  7         31  
366             }
367             else {
368             # If this is the first log mapped to this channel
369             # start a new list
370 3         5 my @newLogList=($log);
371 3         8 $channels->{$channelName}->{logs}=\@newLogList;
372             }
373             }
374              
375             # This will remove all the mappings for a channel,
376             # unmapChannel(Channel);
377             # unmapchannel(Channel,log);
378             sub unmapChannel {
379             # If there's a specific log file provided in arg 2
380             # unmap the channel from that log only
381 1 50   1 1 9 if ($_[1]) {
382 1         7 my $log=$filenameMap{$_[1]};
383             # Locate this log in the channels list of logs
384 1         3 my $index = 0;
385 1         1 $index++ until ${$channels->{$_[0]}->{logs}}[$index] eq $log;
  5         17  
386             # Now remove it
387 1         2 splice(@{$channels->{$_[0]}->{logs}}, $index, 1);
  1         4  
388             }
389             else {
390             # Otherwise, unmap it from all logs
391 0         0 undef $channels->{$_[0]}->{logs};
392             }
393             }
394              
395             # This will close down a log file handle
396             # Note it will NOT unmap any channels mapped to it
397             sub stopLogging {
398 0     0 1 0 my $filename=shift;
399 0         0 my $log=$filenameMap{$filename};
400              
401 0 0       0 if ($log->{fh}) { close($log->{fh}); undef $log->{fh}; }
  0         0  
  0         0  
402             }
403              
404             # Close all logs
405             sub closeLogs {
406 1     1 1 5 foreach my $log (@logs) {
407 5 50       13 if ($log->{fh}) { close($log->{fh}); undef $log->{fh}; }
  5         31  
  5         15  
408             }
409             }
410              
411             # These will enable (1) or disable (0) a particular log channel
412 11     11 1 24 sub enableChannel { $channels->{$_[0]}->{state}=1; $channels->{$_[0]}->{count}=0; }
  11         18  
413             sub disableChannel {
414 2 100   2 1 1104 if ($channels->{$_[0]}->{logs}) {
415 1         3 $channels->{$_[0]}->{state}=0;
416             }
417             else {
418 1         14 warn("This program has disabled channel $_[0] - but it has not been mapped to a log yet, so it will be re-enabled the first time it is used.");
419             }
420              
421             }
422              
423             # This will assign an (normally ascii) color code to a particular channel
424 2     2 1 501 sub assignColorCode { $channels->{$_[0]}->{color}=$_[1]; }
425              
426             # These will enable (1) or disable (0) a particular log channel, and particular module
427 0     0 1 0 sub enableChannelForModule { $channels->{$_[0]}->{"pkg:$_[1]"}=1; }
428 0     0 1 0 sub disableChannelForModule { undef $channels->{$_[0]}->{"pkg:$_[1]"}; }
429              
430             # These will enable or disable color codes for this particular Log
431 1     1 1 7 sub enableColor { my $log=$filenameMap{$_[0]}; $log->{colorOn}=1; }
  1         6  
432 0     0 1 0 sub disableColor { my $log=$filenameMap{$_[0]}; $log->{colorOn}=0; }
  0         0  
433              
434             # This is the main internal print routine for the logging.
435             # This function should not be called externally.
436             # These are the args:
437             # 0 - Epoch Time
438             # 1 - Local Time as a string
439             # 2 - Filehandle
440             # 3 - The log object
441             # 4 - source module
442             # 5 - source filename
443             # 6 - source line #
444             # 7 - desired color
445             # 8 - channel name
446             # 9 - message
447             # 10,etc - Additional parameters...
448              
449             sub logPrint {
450 15     15 0 16 my $fh=$_[2];
451 15         166 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($_[0]);
452 15         30 $year += 1900;
453              
454 15 100 66     70 if (($year!=$_[3]->{currentYear}) or ($mday!=$_[3]->{currentmday})) {
455 5         52 $_[3]->{currentYear}=$year;
456 5         8 $_[3]->{currentmday}=$mday;
457 5         259 printf $fh "---- $year $months[$mon] $mday ----\n";
458             }
459 15         48 $sec=sprintf("%02d", $sec);
460 15         31 my $timestamp="$hour.$min.$sec";
461              
462             # If color codes are turned on, add one now for the specified color
463 15 100       27 if ($_[7]) { print $fh $_[7]; }
  1         15  
464            
465             # Print the channel, date, line of code
466 15         191 printf $fh "%8s $_[8] %12s ",$timestamp,"$_[5]-$_[6]";
467              
468             # Print the line content
469 15         50 for (my $i=9;$i
470 15 50       29 if ($i>9) { printf $fh ','; }
  0         0  
471 15         108 printf $fh $_[$i];
472             }
473              
474             # If color codes are turned on, add one for black now
475 15 100       23 if ($_[7]) { print $fh RESET; }
  1         10  
476            
477             # end the line with a carriage return
478 15         328 print $fh "\n";
479             }
480              
481             # This is the main internal print routine for the logging.
482             # This function should not be called externally.
483             # These are the args:
484             # 0 - Epoch Time
485             # 1 - Local Time as a string
486             # 2 - Filehandle
487             # 3 - The log object
488             # 4 - source module
489             # 5 - source filename
490             # 6 - source line #
491             # 7 - desired color
492             # 8 - channel name
493             # 9 - message
494             # 10,etc - Additional parameters...
495             sub logPrintVerbose {
496 1     1 0 1 my $fh=$_[2];
497              
498             # If color codes are turned on, add one now for the specified color
499 1 50       4 if ($_[7]) { print $fh $_[7]; }
  0         0  
500            
501             # Print the channel, date, line of code
502 1         12 printf $fh "$_[8] %24s %12s ",$_[1],"$_[5]-$_[6]";
503              
504             # Print the line content
505 1         6 for (my $i=9;$i
506 1 50       3 if ($i>9) { printf $fh ','; }
  0         0  
507 1         8 printf $fh $_[$i];
508             }
509              
510             # If color codes are turned on, add one for black now
511 1 50       3 if ($_[7]) { print $fh RESET; }
  0         0  
512            
513             # end the line with a carriage return
514 1         7 print $fh "\n";
515             }
516              
517             # An alternative print function, that is color enabled,
518             # and will print the channel and message, no time or line of code
519             sub logPrintSimple {
520 1     1 0 3 my $fh=$_[2];
521              
522             # If color codes are turned on, add one now for the specified color
523 1 50       10 if ($_[7]) { print $fh $_[7]; }
  0         0  
524            
525             # Print the line content
526 1         11 printf $fh "$_[8] ";
527 1         6 for (my $i=9;$i
528 1 50       3 if ($i>9) { printf $fh ','; }
  0         0  
529 1         9 printf $fh $_[$i];
530             }
531              
532             # If color codes are turned on, add one for black now
533 1 50       3 if ($_[7]) { print $fh RESET; }
  0         0  
534            
535             # end the line with a carriage return
536 1         7 print $fh "\n";
537            
538             # Increment the log line counter
539 1         3 $_[3]->{count}++;
540             }
541              
542              
543             # This is the external function used to log messages on a particular
544             # channel. This are the args:
545             # 0 - channel
546             # 1 - message
547             sub Log {
548            
549 14 50   14 1 1241 unless ($_[0]) { return; }
  0         0  
550             # Check that the message is a defined value, and define it to an empty string if its not.
551 14 100       28 unless ($_[1]) { $_[1]=''; }
  1         22  
552              
553             # Check that this channel is actually mapped to a log
554 14 100       35 unless ($channels->{$_[0]}->{logs}) {
555 3 50       6 if ($defaultLog) {
556             # If its not, map it to the default log (last openned) and enable it.
557 3         10 &mapChannelToLog_Internal($_[0],$defaultLog);
558              
559             # Turn the channel on
560 3         8 enableChannel($_[0]);
561             }
562             else {
563 0         0 return; # Do nothing if there are no logs open
564             }
565             }
566            
567             # Only print if the channel is not enabled or if its enabled for a particular module
568 14         35 my ( $pkg, $srcfilename, $line ) = caller;
569 14 100 66     55 if (($channels->{$_[0]}->{state}) or ($channels->{$_[0]}->{"pkg-$pkg"})) {
570             # Get the time of the message
571 13         18 my $now=time();
572 13         367 my $localNow=localtime($now);
573 13         25 $channels->{$_[0]}->{count}++;
574              
575             # Print the message on each of the filehandles for this channel
576 13         13 foreach my $log (@{$channels->{$_[0]}->{logs}}) {
  13         38  
577             # Only print to this log if it has a filehandle
578 41 100       71 if ($log->{fh}) {
579 17 50       28 if ($log->{printHandler}) {
580 17         17 my $color;
581             # If this filehandle has color turned on, and this channel has a desired color, provide it
582 17 100       30 if ($log->{colorOn}) { $color=$channels->{$_[0]}->{color}; }
  1         3  
583 17         39 &{$log->{printHandler}}($now,$localNow,$log->{fh},$log,$pkg,$srcfilename,$line,$color,@_);
  17         34  
584            
585             # Increment the log line counter
586 17         24 $log->{count}++;
587            
588             # If we've hit the log line limit, cycle the log
589 17 50 66     78 if (($log->{limit}) and ($log->{count} > $log->{limit})) { &cycleLog($log); }
  0         0  
590             }
591             }
592             }
593             }
594             }
595              
596             # This will cycle a log file by closing it, and moving
597             # the current log to an archived filename. Then it will
598             # reopen the log.
599             # This function is overloaded - it could be called with
600             # a filename or filehandle
601             sub cycleLog {
602 0     0 0 0 my $log=shift;
603            
604             # Close the old log file
605 0 0       0 if ($log->{fh}) { close($log->{fh}); }
  0         0  
606              
607             # Move the old copy of the log out of the way
608 0 0       0 if ($log->{preserve}) { &moveOldLog($log); }
  0         0  
609              
610             # Reopen the file
611 0 0       0 open($log->{fh},">$log->{filename}") or die ("Error! Unable to open log file $log->{filename} for writing.\n");
612 0         0 $log->{fh}->autoflush;
613 0         0 $log->{count}=0;
614              
615 0         0 return $log->{fh};
616             }
617              
618             # This will move an old copy of a log out of the way
619             # so a new one can take it's place
620             sub moveOldLog {
621 1     1 0 2 my $log=shift;
622 1         3 my $filename=$log->{filename};
623              
624             # Get a timestamp, to add to the name of the old log file
625 1         15 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
626 1         4 $sec=sprintf("%02d", $sec);
627 1         3 $min=sprintf("%02d", $min);
628 1         2 $hour=sprintf("%02d", $hour);
629 1         2 $year += 1900;
630 1         5 my $timestamp="$year-".$months[$mon]."-".$mday."_"."$hour.$min.$sec";
631            
632             # Rename the old file with the timestamp
633 1         3 my $cmd="mv -f $filename $filename\.$timestamp";
634             # If there's an old dir specified, move the file there instead
635 1 50       4 if ($log->{oldDir}) {
636 0         0 my $shortFilename=$filename;
637 0         0 $shortFilename =~ s{.*/}{}; # Remove path
638 0         0 $cmd="mv -f $filename $log->{oldDir}/$shortFilename\.$timestamp";
639              
640             # Make sure that old dir directory actually exists first
641 0 0       0 unless (-d $log->{oldDir}) {
642 0         0 system("mkdir -p $log->{oldDir}");
643             }
644             }
645 1         3197 system($cmd);
646             }
647              
648             # This will show a breakdown of how many messages
649             # were logged on each channel since this fun
650             # was last called
651             sub logStats {
652 0     0 1   my @ret;
653 0           foreach my $channelName (keys %{$channels}) {
  0            
654 0           push @ret,"$channelName - $channels->{$channelName}->{count}";
655 0           $channels->{$channelName}->{count}=0;
656             }
657 0           return @ret;
658             }
659              
660             1;