1# -*- perl -*- 2# 3# $Id: Log.pm,v 1.3 1999/09/26 14:50:13 joe Exp $ 4# 5# Net::Daemon - Base class for implementing TCP/IP daemons 6# 7# Copyright (C) 1998, Jochen Wiedmann 8# Am Eisteich 9 9# 72555 Metzingen 10# Germany 11# 12# Phone: +49 7123 14887 13# Email: joe@ispsoft.de 14# 15# All rights reserved. 16# 17# You may distribute this package under the terms of either the GNU 18# General Public License or the Artistic License, as specified in the 19# Perl README file. 20# 21############################################################################ 22 23require 5.004; 24use strict; 25 26 27package Net::Daemon::Log; 28 29$Net::Daemon::Log::VERSION = '0.01'; 30 31 32############################################################################ 33# 34# Name: Log (Instance method) 35# 36# Purpose: Does logging 37# 38# Inputs: $self - Server instance 39# 40# Result: TRUE, if the client has successfully authorized, FALSE 41# otherwise. 42# 43############################################################################ 44 45 46sub OpenLog($) { 47 my $self = shift; 48 return 1 unless ref($self); 49 return $self->{'logfile'} if defined($self->{'logfile'}); 50 if ($Config::Config{'archname'} =~ /win32/i) { 51 require Win32::EventLog; 52 $self->{'eventLog'} = Win32::EventLog->new(ref($self), '') 53 or die "Cannot open EventLog:" . &Win32::GetLastError(); 54 $self->{'$eventId'} = 0; 55 } else { 56 eval { require Sys::Syslog }; 57 if ($@) { 58 die "Cannot open Syslog: $@"; 59 } 60 if ($^O ne 'solaris' && $^O ne 'freebsd' && 61 defined(&Sys::Syslog::setlogsock) && 62 eval { &Sys::Syslog::_PATH_LOG() }) { 63 &Sys::Syslog::setlogsock('unix'); 64 } 65 &Sys::Syslog::openlog($self->{'logname'} || ref($self), 'pid', 66 $self->{'facility'} || 'daemon'); 67 } 68 $self->{'logfile'} = 0; 69} 70 71sub Log ($$$;@) { 72 my($self, $level, $format, @args) = @_; 73 my $logfile = !ref($self) || $self->OpenLog(); 74 75 my $tid = ''; 76 if (ref($self) && $self->{'mode'}) { 77 if ($self->{'mode'} eq 'ithreads') { 78 if (my $sthread = threads->self()) { 79 $tid = $sthread->tid() . ", "; 80 } 81 } elsif ($self->{'mode'} eq 'threads') { 82 if (my $sthread = Thread->self()) { 83 $tid = $sthread->tid() . ", "; 84 } 85 } 86 } 87 if ($logfile) { 88 my $logtime = $self->LogTime(); 89 if (ref($logfile)) { 90 $logfile->print(sprintf("$logtime $level, $tid$format\n", @args)); 91 } else { 92 printf STDERR ("$logtime $level, $tid$format\n", @args); 93 } 94 } elsif (my $eventLog = $self->{'eventLog'}) { 95 my($type, $category); 96 if ($level eq 'debug') { 97 $type = Win32::EventLog::EVENTLOG_INFORMATION_TYPE(); 98 $category = 10; 99 } elsif ($level eq 'notice') { 100 $type = Win32::EventLog::EVENTLOG_INFORMATION_TYPE(); 101 $category = 20; 102 } else { 103 $type = Win32::EventLog::EVENTLOG_ERROR_TYPE(); 104 $category = 50; 105 } 106 $eventLog->Report({ 107 'Category' => $category, 108 'EventType' => $type, 109 'EventID' => ++$self->{'eventId'}, 110 'Strings' => sprintf($format, @args), 111 'Data' => $tid 112 }); 113 } else { 114 &Sys::Syslog::syslog($level, "$tid$format", @args); 115 } 116} 117 118sub Debug ($$;@) { 119 my $self = shift; 120 if (!ref($self) || $self->{'debug'}) { 121 my $fmt = shift; 122 $self->Log('debug', $fmt, @_); 123 } 124} 125 126sub Error ($$;@) { 127 my $self = shift; my $fmt = shift; 128 $self->Log('err', $fmt, @_); 129} 130 131sub Fatal ($$;@) { 132 my $self = shift; my $fmt = shift; 133 my $msg = sprintf($fmt, @_); 134 $self->Log('err', $msg); 135 my($package, $filename, $line) = caller(); 136 die "$msg at $filename line $line."; 137} 138 139sub LogTime { scalar(localtime) } 140 141 1421; 143 144__END__ 145 146=head1 NAME 147 148Net::Daemon::Log - Utility functions for logging 149 150 151=head1 SYNOPSIS 152 153 # Choose logging method: syslog or Win32::EventLog 154 $self->{'facility'} = 'mail'; # Default: Daemon 155 $self->{'logfile'} = undef; # Default 156 157 # Choose logging method: stderr 158 $self->{'logfile'} = 1; 159 160 # Choose logging method: IO handle 161 my $file = IO::File->new("my.log", "a"); 162 $self->{'logfile'} = $file; 163 164 165 # Debugging messages (equivalent): 166 $self->Log('debug', "This is a debugging message"); 167 $self->Debug("This is a debugging message"); 168 169 # Error messages (equivalent): 170 $self->Log('err', "This is an error message"); 171 $self->Error("This is an error message"); 172 173 # Fatal error messages (implies 'die') 174 $self->Fatal("This is a fatal error message"); 175 176 177=head1 WARNING 178 179THIS IS ALPHA SOFTWARE. It is *only* 'Alpha' because the interface (API) 180is not finalised. The Alpha status does not reflect code quality or 181stability. 182 183 184=head1 DESCRIPTION 185 186Net::Daemon::Log is a utility class for portable logging messages. 187By default it uses syslog (Unix) or Win32::EventLog (Windows), but 188logging messages can also be redirected to stderr or a log file. 189 190 191=head2 Generic Logging 192 193 $self->Log($level, $msg, @args); 194 195This is the generic interface. The logging level is in syslog style, 196thus one of the words 'debug', 'info', 'notice', 'err' or 'crit'. 197You'll rarely need info and notice and I can hardly imagine a reason 198for crit (critical). In 95% of all cases debug and err will be 199sufficient. 200 201The logging string $msg is a format string similar to printf. 202 203 204=head2 Utility methods 205 206 $self->Debug($msg, @args); 207 $self->Error($msg, @args); 208 $self->Fatal($msg, @args); 209 210These are replacements for logging with levels debug and err. The difference 211between the latter two is that Fatal includes throwing a Perl exception. 212 213 214=head2 Chossing a logging target 215 216By default logging will happen to syslog (Unix) or EventLog (Windows). 217However you may choose logging to stderr by setting 218 219 $self->{'logfile'} = 1; 220 221This is required if neither of syslog and EventLog is available. An 222alternative option is setting 223 224 $self->{'logfile'} = $handle; 225 226where $handle is any object supporting a I<print> method, for example 227an IO::Handle object. Usually the logging target is choosen as soon 228as you call $self->Log() the first time. However, you may force 229choosing the target by doing a 230 231 $self->OpenLog(); 232 233before calling Log the first time. 234 235 236=head1 MULTITHREADING 237 238The Multithreading capabitities of this class are depending heavily 239on the underlying classes Sys::Syslog, Win32::EventLog or IO::Handle. 240If they are thread safe, you can well assume that this package is 241too. (The exception being that you should better call 242$self->OpenLog() before threading.) 243 244 245=head1 AUTHOR AND COPYRIGHT 246 247 Net::Daemon is Copyright (C) 1998, Jochen Wiedmann 248 Am Eisteich 9 249 72555 Metzingen 250 Germany 251 252 Phone: +49 7123 14887 253 Email: joe@ispsoft.de 254 255 All rights reserved. 256 257 You may distribute this package under the terms of either the GNU 258 General Public License or the Artistic License, as specified in the 259 Perl README file. 260 261 262=head1 SEE ALSO 263 264L<Net::Daemon(3)>, L<Sys::Syslog(3)>, L<Win32::EventLog(3)>, 265L<IO::Handle(3)> 266 267=cut 268 269