File Coverage

blib/lib/Log/MultiChannel.pm
Criterion Covered Total %
statement 146 196 74.4
branch 39 68 57.3
condition 6 9 66.6
subroutine 22 29 75.8
pod 15 23 65.2
total 228 325 70.1


line stmt bran cond sub pod time code
1             package Log::MultiChannel;
2 1     1   25418 use vars qw($VERSION);
  1         1  
  1         45  
3 1     1   4 use Term::ANSIColor qw(:constants);
  1         1  
  1         242  
4             $VERSION = '1.10';
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   5 use strict;
  1         5  
  1         27  
217 1     1   3 use warnings;
  1         1  
  1         25  
218             require Exporter;
219 1     1   509 use UNIVERSAL;
  1         10  
  1         4  
220 1     1   516 use IO::Handle;
  1         4709  
  1         1602  
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 1016 my $log;
257 6         17 $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         10 $log->{limit} =shift; # An optional limit on the number of lines that can be written before cycling this log
260 6         9 $log->{oldDir} =shift; # Move old log files to this directory when overwritting
261 6         7 $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       17 unless ($log->{printHandler}) { $log->{printHandler}=\&logPrint; }
  6         15  
265            
266             # Check for an old copy of the log, and move it out of the way if desired
267 6 100       14 if ($log->{preserve}) {
268 1 50       14 if (-f $log->{filename}) { &moveOldLog($log); }
  1         3  
269             }
270              
271             # Open the file
272 6 50       496 open($log->{fh}, ">$log->{filename}") or die ("Error! Unable to open log file $log->{filename} for writing.\n");
273 6         52 $log->{fh}->autoflush;
274            
275             # Now initialize this log
276 6         258 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 8 my $log=shift;
304              
305             # Reset the counter for this log
306 6         12 $log->{count}=0;
307              
308             # Initialize the last month day and year to 0
309 6         17 $log->{currentmday}=0;
310 6         11 $log->{currentYear}=0;
311            
312             # Also add this Log in the filenameMap, so we can easily find it with the name
313 6         14 $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         10 push @logs,$log;
320              
321 6         13 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 428 my $logName=shift;
328 3         5 my $handler=shift;
329 3         6 my $log=$filenameMap{$logName};
330 3         4 $log->{printHandler}=\&{$handler};
  3         28  
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 41 my $channel=shift;
342              
343             # Turn the channel on
344 7         15 enableChannel($channel);
345              
346             # Map the channel to each individual Log
347 7         14 foreach my $filename (@_) { &mapChannelToLog_Internal($channel,$filenameMap{$filename}); }
  7         12  
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 14 my $channelName=shift;
360 10         10 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       19 if ($channels->{$channelName}->{logs}) {
365 7         7 push @{$channels->{$channelName}->{logs}},$log;
  7         24  
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         9 $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 10 if ($_[1]) {
382 1         3 my $log=$filenameMap{$_[1]};
383             # Locate this log in the channels list of logs
384 1         3 my $index = 0;
385 1         2 $index++ until ${$channels->{$_[0]}->{logs}}[$index] eq $log;
  5         14  
386             # Now remove it
387 1         3 splice(@{$channels->{$_[0]}->{logs}}, $index, 1);
  1         5  
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 9 foreach my $log (@logs) {
407 5 50       7 if ($log->{fh}) { close($log->{fh}); undef $log->{fh}; }
  5         27  
  5         11  
408             }
409             }
410              
411             # These will enable (1) or disable (0) a particular log channel
412 11     11 1 19 sub enableChannel { $channels->{$_[0]}->{state}=1; $channels->{$_[0]}->{count}=0; }
  11         14  
413             sub disableChannel {
414 2 100   2 1 802 if ($channels->{$_[0]}->{logs}) {
415 1         3 $channels->{$_[0]}->{state}=0;
416             }
417             else {
418 1         15 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 656 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 12 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 14 my $fh=$_[2];
451 15         180 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($_[0]);
452 15         28 $year += 1900;
453              
454 15 100 66     74 if (($year!=$_[3]->{currentYear}) or ($mday!=$_[3]->{currentmday})) {
455 5         9 $_[3]->{currentYear}=$year;
456 5         8 $_[3]->{currentmday}=$mday;
457 5         189 printf $fh "---- $year $months[$mon] $mday ----\n";
458             }
459              
460 15         48 $sec=sprintf("%02d", $sec);
461 15         21 $min=sprintf("%02d", $min);
462 15         19 $hour=sprintf("%02d", $hour);
463 15         25 my $timestamp="$hour:$min:$sec";
464              
465             # If color codes are turned on, add one now for the specified color
466 15 100       26 if ($_[7]) { print $fh $_[7]; }
  1         17  
467            
468             # Print the channel, date, line of code
469 15         188 printf $fh "%8s $_[8] %12s ",$timestamp,"$_[5]-$_[6]";
470              
471             # Print the line content
472 15         55 for (my $i=9;$i
473 15 50       27 if ($i>9) { print $fh ','; }
  0         0  
474 15         114 print $fh $_[$i];
475             }
476              
477             # If color codes are turned on, add one for black now
478 15 100       26 if ($_[7]) { print $fh RESET; }
  1         13  
479            
480             # end the line with a carriage return
481 15         387 print $fh "\n";
482             }
483              
484             # This is the main internal print routine for the logging.
485             # This function should not be called externally.
486             # These are the args:
487             # 0 - Epoch Time
488             # 1 - Local Time as a string
489             # 2 - Filehandle
490             # 3 - The log object
491             # 4 - source module
492             # 5 - source filename
493             # 6 - source line #
494             # 7 - desired color
495             # 8 - channel name
496             # 9 - message
497             # 10,etc - Additional parameters...
498             sub logPrintVerbose {
499 1     1 0 3 my $fh=$_[2];
500              
501             # If color codes are turned on, add one now for the specified color
502 1 50       5 if ($_[7]) { print $fh $_[7]; }
  0         0  
503            
504             # Print the channel, date, line of code
505 1         19 printf $fh "$_[8] %24s %12s ",$_[1],"$_[5]-$_[6]";
506              
507             # Print the line content
508 1         6 for (my $i=9;$i
509 1 50       3 if ($i>9) { print $fh ','; }
  0         0  
510 1         7 print $fh $_[$i];
511             }
512              
513             # If color codes are turned on, add one for black now
514 1 50       5 if ($_[7]) { print $fh RESET; }
  0         0  
515            
516             # end the line with a carriage return
517 1         6 print $fh "\n";
518             }
519              
520             # An alternative print function, that is color enabled,
521             # and will print the channel and message, no time or line of code
522             sub logPrintSimple {
523 1     1 0 3 my $fh=$_[2];
524              
525             # If color codes are turned on, add one now for the specified color
526 1 50       15 if ($_[7]) { print $fh $_[7]; }
  0         0  
527            
528             # Print the line content
529 1         24 printf $fh "$_[8] ";
530 1         8 for (my $i=9;$i
531 1 50       4 if ($i>9) { print $fh ','; }
  0         0  
532 1         21 print $fh $_[$i];
533             }
534              
535             # If color codes are turned on, add one for black now
536 1 50       5 if ($_[7]) { print $fh RESET; }
  0         0  
537            
538             # end the line with a carriage return
539 1         9 print $fh "\n";
540            
541             # Increment the log line counter
542 1         5 $_[3]->{count}++;
543             }
544              
545              
546             # This is the external function used to log messages on a particular
547             # channel. This are the args:
548             # 0 - channel
549             # 1 - message
550             sub Log {
551            
552 14 50   14 1 1314 unless ($_[0]) { return; }
  0         0  
553             # Check that the message is a defined value, and define it to an empty string if its not.
554 14 100       25 unless ($_[1]) { $_[1]=''; }
  1         3  
555              
556             # Check that this channel is actually mapped to a log
557 14 100       35 unless ($channels->{$_[0]}->{logs}) {
558 3 50       7 if ($defaultLog) {
559             # If its not, map it to the default log (last openned) and enable it.
560 3         10 &mapChannelToLog_Internal($_[0],$defaultLog);
561              
562             # Turn the channel on
563 3         8 enableChannel($_[0]);
564             }
565             else {
566 0         0 return; # Do nothing if there are no logs open
567             }
568             }
569            
570             # Only print if the channel is not enabled or if its enabled for a particular module
571 14         40 my ( $pkg, $srcfilename, $line ) = caller;
572 14 100 66     51 if (($channels->{$_[0]}->{state}) or ($channels->{$_[0]}->{"pkg-$pkg"})) {
573             # Get the time of the message
574 13         20 my $now=time();
575 13         365 my $localNow=localtime($now);
576 13         30 $channels->{$_[0]}->{count}++;
577              
578             # Print the message on each of the filehandles for this channel
579 13         13 foreach my $log (@{$channels->{$_[0]}->{logs}}) {
  13         33  
580             # Only print to this log if it has a filehandle
581 41 100       79 if ($log->{fh}) {
582 17 50       32 if ($log->{printHandler}) {
583 17         12 my $color;
584             # If this filehandle has color turned on, and this channel has a desired color, provide it
585 17 100       33 if ($log->{colorOn}) { $color=$channels->{$_[0]}->{color}; }
  1         7  
586 17         41 &{$log->{printHandler}}($now,$localNow,$log->{fh},$log,$pkg,$srcfilename,$line,$color,@_);
  17         44  
587            
588             # Increment the log line counter
589 17         27 $log->{count}++;
590            
591             # If we've hit the log line limit, cycle the log
592 17 50 66     93 if (($log->{limit}) and ($log->{count} > $log->{limit})) { &cycleLog($log); }
  0         0  
593             }
594             }
595             }
596             }
597             }
598              
599             # This will cycle a log file by closing it, and moving
600             # the current log to an archived filename. Then it will
601             # reopen the log.
602             # This function is overloaded - it could be called with
603             # a filename or filehandle
604             sub cycleLog {
605 0     0 0 0 my $log=shift;
606            
607             # Close the old log file
608 0 0       0 if ($log->{fh}) { close($log->{fh}); }
  0         0  
609              
610             # Move the old copy of the log out of the way
611 0 0       0 if ($log->{preserve}) { &moveOldLog($log); }
  0         0  
612              
613             # Reopen the file
614 0 0       0 open($log->{fh},">$log->{filename}") or die ("Error! Unable to open log file $log->{filename} for writing.\n");
615 0         0 $log->{fh}->autoflush;
616 0         0 $log->{count}=0;
617              
618 0         0 return $log->{fh};
619             }
620              
621             # This will move an old copy of a log out of the way
622             # so a new one can take it's place
623             sub moveOldLog {
624 1     1 0 2 my $log=shift;
625 1         1 my $filename=$log->{filename};
626              
627             # Get a timestamp, to add to the name of the old log file
628 1         15 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
629 1         4 $sec=sprintf("%02d", $sec);
630 1         2 $min=sprintf("%02d", $min);
631 1         2 $hour=sprintf("%02d", $hour);
632 1         2 $year += 1900;
633 1         5 my $timestamp="$year-".$months[$mon]."-".$mday."_"."$hour:$min:$sec";
634            
635             # Rename the old file with the timestamp
636 1         3 my $cmd="mv -f $filename $filename\.$timestamp";
637             # If there's an old dir specified, move the file there instead
638 1 50       3 if ($log->{oldDir}) {
639 0         0 my $shortFilename=$filename;
640 0         0 $shortFilename =~ s{.*/}{}; # Remove path
641 0         0 $cmd="mv -f $filename $log->{oldDir}/$shortFilename\.$timestamp";
642              
643             # Make sure that old dir directory actually exists first
644 0 0       0 unless (-d $log->{oldDir}) {
645 0         0 system("mkdir -p $log->{oldDir}");
646             }
647             }
648 1         3089 system($cmd);
649             }
650              
651             # This will show a breakdown of how many messages
652             # were logged on each channel since this fun
653             # was last called
654             sub logStats {
655 0     0 1   my @ret;
656 0           foreach my $channelName (keys %{$channels}) {
  0            
657 0           push @ret,"$channelName - $channels->{$channelName}->{count}";
658 0           $channels->{$channelName}->{count}=0;
659             }
660 0           return @ret;
661             }
662              
663             1;