]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/perl/lib/OpenSRF/Utils/Logger.pm
return the trace-augmented message as written to the log
[OpenSRF.git] / src / perl / lib / OpenSRF / Utils / Logger.pm
1 package OpenSRF::Utils::Logger;
2 # vim:ts=4:noet:
3 use strict;
4 use vars qw($AUTOLOAD @EXPORT_OK %EXPORT_TAGS);
5 use Exporter;
6 use Unix::Syslog qw(:macros :subs);
7 use base qw/OpenSRF Exporter/;
8 use FileHandle;
9 use Time::HiRes qw(gettimeofday);
10 use OpenSRF::Utils::Config;
11 use Fcntl;
12
13 =head1
14
15 Logger code
16
17 my $logger = OpenSRF::Utils::Logger;
18 $logger->error( $msg );
19
20 For backwards compability, a log level may also be provided to each log
21 function thereby overriding the level defined by the function.
22
23 i.e. $logger->error( $msg, WARN );  # logs at log level WARN
24
25 =cut
26
27 @EXPORT_OK = qw/ NONE ERROR WARN INFO DEBUG INTERNAL /;
28 push @EXPORT_OK, '$logger';
29
30 %EXPORT_TAGS = ( level => [ qw/ NONE ERROR WARN INFO DEBUG INTERNAL / ], logger => [ '$logger' ] );
31
32 my $config;                                                     # config handle
33 my $loglevel = INFO();                          # global log level
34 my $logfile;                                            # log file
35 my $facility;                                           # syslog facility
36 my $actfac;                                                     # activity log syslog facility
37 my $actfile;                                            # activity log file
38 my $service = $0;                       # default service name
39 my $syslog_enabled = 0;                 # is syslog enabled?
40 my $act_syslog_enabled = 0;     # is syslog enabled?
41 my $logfile_enabled = 1;                # are we logging to a file?
42 my $act_logfile_enabled = 1;    # are we logging to a file?
43 my $max_log_msg_len = 1536;                     # SYSLOG default maximum is 2048
44
45 our $logger = "OpenSRF::Utils::Logger";
46
47 # log levels
48 sub ACTIVITY    { return -1; }
49 sub NONE                        { return 0;     }
50 sub ERROR               { return 1;     }
51 sub WARN                        { return 2;     }
52 sub INFO                        { return 3;     }
53 sub DEBUG               { return 4;     }
54 sub INTERNAL    { return 5;     }
55 sub ALL                 { return 100; }
56
57 my $isclient;  # true if we control the osrf_xid
58
59 # load up our config options
60 sub set_config {
61
62         return if defined $config;
63
64         $config = OpenSRF::Utils::Config->current;
65         if( !defined($config) ) {
66                 $loglevel = INFO();
67                 warn "*** Logger found no config.  Using STDERR ***\n";
68                 return;
69         }
70
71         $loglevel =  $config->bootstrap->loglevel; 
72
73         if ($config->bootstrap->loglength) {
74                 $max_log_msg_len = $config->bootstrap->loglength;
75         }
76
77         $logfile = $config->bootstrap->logfile;
78         if($logfile =~ /^syslog/) {
79                 $syslog_enabled = 1;
80                 $logfile_enabled = 0;
81         $logfile = $config->bootstrap->syslog;
82                 $facility = $logfile;
83                 $logfile = undef;
84                 $facility = _fac_to_const($facility);
85                 openlog($service, 0, $facility);
86
87         } else { $logfile = "$logfile"; }
88
89
90     if($syslog_enabled) {
91         # --------------------------------------------------------------
92         # if we're syslogging, see if we have a special syslog facility 
93         # for activity logging.  If not, use the syslog facility for
94         # standard logging
95         # --------------------------------------------------------------
96         $act_syslog_enabled = 1;
97         $act_logfile_enabled = 0;
98         $actfac = $config->bootstrap->actlog || $config->bootstrap->syslog;
99         $actfac = _fac_to_const($actfac);
100         $actfile = undef;
101     } else {
102         # --------------------------------------------------------------
103         # we're not syslogging, use any specified activity log file.
104         # Fall back to the standard log file otherwise
105         # --------------------------------------------------------------
106                 $act_syslog_enabled = 0;
107                 $act_logfile_enabled = 1;
108         $actfile = $config->bootstrap->actlog || $config->bootstrap->logfile;
109     }
110
111         my $client = OpenSRF::Utils::Config->current->bootstrap->client();
112         if (!$client) {
113                 $isclient = 0;
114                 return;
115         }
116         $isclient = ($client =~ /^true$/iog) ?  1 : 0;
117 }
118
119 sub _fac_to_const {
120         my $name = shift;
121         return LOG_LOCAL0 unless $name;
122         return LOG_LOCAL0 if $name =~ /local0/i;
123         return LOG_LOCAL1 if $name =~ /local1/i;
124         return LOG_LOCAL2 if $name =~ /local2/i;
125         return LOG_LOCAL3 if $name =~ /local3/i;
126         return LOG_LOCAL4 if $name =~ /local4/i;
127         return LOG_LOCAL5 if $name =~ /local5/i;
128         return LOG_LOCAL6 if $name =~ /local6/i;
129         return LOG_LOCAL7 if $name =~ /local7/i;
130         return LOG_LOCAL0;
131 }
132
133 sub is_syslog {
134         set_config();
135         return $syslog_enabled;
136 }
137
138 sub is_act_syslog {
139         set_config();
140         return $act_syslog_enabled;
141 }
142
143 sub is_filelog {
144         set_config();
145         return $logfile_enabled;
146 }
147
148 sub is_act_filelog {
149         set_config();
150         return $act_logfile_enabled;
151 }
152
153 sub set_service {
154         my( $self, $svc ) = @_;
155         $service = $svc;        
156         if( is_syslog() ) {
157                 closelog();
158                 openlog($service, 0, $facility);
159         }
160 }
161
162 sub error {
163         my( $self, $msg, $level ) = @_;
164         $level = ERROR() unless defined ($level);
165         _log_message( $msg, $level );
166 }
167
168 sub warn {
169         my( $self, $msg, $level ) = @_;
170         $level = WARN() unless defined ($level);
171         _log_message( $msg, $level );
172 }
173
174 sub info {
175         my( $self, $msg, $level ) = @_;
176         $level = INFO() unless defined ($level);
177         _log_message( $msg, $level );
178 }
179
180 sub debug {
181         my( $self, $msg, $level ) = @_;
182         $level = DEBUG() unless defined ($level);
183         _log_message( $msg, $level );
184 }
185
186 sub internal {
187         my( $self, $msg, $level ) = @_;
188         $level = INTERNAL() unless defined ($level);
189         _log_message( $msg, $level );
190 }
191
192 sub activity {
193         my( $self, $msg ) = @_;
194         _log_message( $msg, ACTIVITY() );
195 }
196
197 # for backward compability
198 sub transport {
199         my( $self, $msg, $level ) = @_;
200         $level = DEBUG() unless defined ($level);
201         _log_message( $msg, $level );
202 }
203
204
205 # ----------------------------------------------------------------------
206 # creates a new xid if necessary
207 # ----------------------------------------------------------------------
208 my $osrf_xid = '';
209 my $osrf_xid_inc = 0;
210 sub mk_osrf_xid {
211    return unless $isclient;
212    $osrf_xid_inc++;
213    return $osrf_xid = "$^T${$}$osrf_xid_inc";
214 }
215
216 sub set_osrf_xid { 
217    return if $isclient; # if we're a client, we control our xid
218    $osrf_xid = $_[1]; 
219 }
220
221 sub get_osrf_xid { return $osrf_xid; }
222 # ----------------------------------------------------------------------
223
224    
225 sub _log_message {
226         my( $msg, $level ) = @_;
227         return if $level > $loglevel;
228
229         my $l; my $n; 
230         my $fac = $facility;
231
232         if ($level == ERROR())                  {$l = LOG_ERR; $n = "ERR "; }
233         elsif ($level == WARN())                {$l = LOG_WARNING; $n = "WARN"; }
234         elsif ($level == INFO())                {$l = LOG_INFO; $n = "INFO"; }  
235         elsif ($level == DEBUG())               {$l = LOG_DEBUG; $n = "DEBG"; }
236         elsif ($level == INTERNAL())    {$l = LOG_DEBUG; $n = "INTL"; }
237         elsif ($level == ACTIVITY())    {$l = LOG_INFO; $n = "ACT"; $fac = $actfac; }
238
239         my( undef, $file, $line_no ) = caller(1);
240    $file =~ s#/.*/##og;
241
242         # help syslog with the formatting
243         $msg =~ s/\%/\%\%/gso if( is_act_syslog() or is_syslog() );
244
245         $msg = "[$n:"."$$".":$file:$line_no:$osrf_xid] $msg";
246
247         # Trim the message to the configured maximum log message length
248         $msg = substr($msg, 0, $max_log_msg_len); 
249
250         if( $level == ACTIVITY() ) {
251                 if( is_act_syslog() ) { syslog( $fac | $l, $msg ); } 
252                 elsif( is_act_filelog() ) { _write_file( $msg, 1 ); }
253
254         } else {
255                 if( is_syslog() ) { syslog( $fac | $l, $msg ); }
256                 elsif( is_filelog() ) { _write_file($msg); }
257         }
258
259         return $msg;
260 }
261
262 sub _write_file {
263         my ($msg, $isact) = @_;
264         my $file = $isact ? $actfile : $logfile;
265         my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);  
266         $year += 1900; $mon += 1;
267
268     if ($file) {
269         sysopen( SINK, $file, O_NONBLOCK|O_WRONLY|O_APPEND|O_CREAT ) 
270             or die "Cannot sysopen $file: $!";
271     } else {
272         open (SINK, ">&2");  # print to STDERR as warned
273     }
274         binmode(SINK, ':utf8');
275         printf SINK "[%04d-%02d-%02d %02d:%02d:%02d] %s %s\n", $year, $mon, $mday, $hour, $min, $sec, $service, $msg;
276         close( SINK );
277 }
278
279 1;
280