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