1# $Id: Logger.pm,v 1.22 2005/06/10 18:31:32 vipul Exp $ 2 3package Razor2::Logger; 4 5use strict; 6use Razor2::Syslog; 7use Time::HiRes qw(gettimeofday); 8use POSIX qw(strftime); 9use IO::File; 10# 2003/09/10 Anne Bennett: syslog of our choice (uses socket, 11# does not assume network listener). 12use Sys::Syslog; 13 14# designed to be inherited module 15# but can stand alone. 16 17sub new { 18 19 my ($class, %args) = @_; 20 my %self = ( %args ); 21 my $self = bless \%self, $class; 22 23 my $prefix = $args{LogPrefix} || 'razord2'; 24 my $facility = $args{LogFacility} || 'local3'; 25 my $loghost = $args{LogHost} || '127.0.0.1'; 26 27 if ($self->{LogTo} eq 'syslog') { 28 $$self{syslog} = new Razor2::Syslog (Facility=> $facility, Priority => 'debug', Name => $prefix, SyslogHost => $loghost); 29 $self->{LogType} = 'syslog'; 30 } elsif ($self->{LogTo} =~ /^file:(.*)$/) { 31 $self->{LogType} = 'file'; 32 my $name = $1; chomp $name; 33 open (LOGF, ">>$name") or do { 34 if ($self->{DontDie}) { 35 open LOGF, ">>/dev/null" or do { 36 print STDERR "Failed to open /dev/null, $!\n"; 37 }; 38 } else { 39 die $!; 40 } 41 }; 42 LOGF->autoflush(1); 43 $self->{fd} = *LOGF{IO}; 44 } elsif ($self->{LogTo} eq 'sys-syslog') { 45 # 2003/09/10 Anne Bennett: syslog of our choice (uses socket, 46 # does not assume network listener). 47 $self->{LogType} = 'sys-syslog'; 48 openlog($prefix,"pid",$facility); 49 } elsif ($self->{LogTo} eq 'stdout') { 50 $self->{LogType} = 'file'; 51 $self->{fd} = *STDOUT{IO}; 52 } elsif ($self->{LogTo} eq 'stderr') { 53 $self->{LogType} = 'file'; 54 $self->{fd} = *STDERR{IO}; 55 } else { 56 $self->{LogType} = 'file'; 57 $self->{fd} = *STDERR{IO}; 58 } 59 60 $self->{LogTimeFormat} ||= "%b %d %H:%M:%S"; # formatting from strftime() 61 $self->{LogDebugLevel} = exists $self->{LogDebugLevel} ? $self->{LogDebugLevel} : 5; 62 $self->{Log2FileDir} ||= "/tmp"; 63 64 # 2002/11/27 Anne Bennett: log this at level 2 so we can set level 65 # 1 (to get errors only) and avoid this unneeded line. 66 $self->log(2,"[bootup] Logging initiated LogDebugLevel=$self->{LogDebugLevel} to $self->{LogTo}"); 67 68 return $self; 69 70} 71 72 73sub log { 74 75 my ($self, $prio, $message) = @_; 76 77 return unless $prio <= $self->{LogDebugLevel}; 78 79 my ($package, $filename, $line) = caller; 80 $filename =~ s:.*/::; 81 82 if ($self->{LogType} eq 'syslog') { 83 84 my $logstr = sprintf("[%2d] %s\n", $prio, $message); 85 $logstr =~ s/\n+\n$/\n/; 86 $self->{syslog}->send($logstr, Priority => 'debug'); 87 88 } elsif ($self->{LogType} eq 'sys-syslog') { 89 # 2003/09/10 Anne Bennett: syslog of our choice (uses socket, 90 # does not assume network listener). 91 my $logstr = sprintf("[%2d] %s\n", $prio, $message); 92 $logstr =~ s/\n+$//g; 93 syslog("debug",$logstr); 94 95 } elsif ($self->{LogType} eq 'file') { 96 97 my $now_string; 98 if ($self->{LogTimestamp}) { 99 my ($seconds, $microseconds) = gettimeofday; 100 $now_string = strftime $self->{LogTimeFormat}, localtime($seconds); 101 $now_string .= sprintf ".%06d ", $microseconds; 102 } 103 104 my $logstr = sprintf("%s[%d]: [%2d] %s\n", $self->{LogPrefix}, $$, $prio, $message); 105 $logstr =~ s/\n+\n$/\n/; 106 my $fd = $self->{fd}; 107 print $fd "$now_string$logstr"; 108 109 } 110 111 return 1; 112} 113 114sub log2file { 115 my ($self, $prio, $textref, $fn_ext) = @_; 116 117 return unless $prio <= $self->{LogDebugLevel}; 118 119 unless (ref($textref) eq 'SCALAR') { 120 print "log2file: not a scalar ref ($fn_ext)\n"; 121 return; 122 } 123 my $len = length($$textref); 124 my $fn = "$self->{Log2FileDir}/razor.$$.$fn_ext"; 125 126 if (open OUT, ">$fn") { 127 print OUT $$textref; 128 close OUT; 129 $self->log($prio,"log2file: wrote message len=$len to file: $fn"); 130 } else { 131 $self->log($prio,"log2file: could not write to $fn: $!"); 132 } 133} 134 1351; 136 137