updated the sylog and activity log file handling to accomodate differences from boots...
[OpenSRF.git] / src / perlmods / 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;                                           # 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
43 our $logger = "OpenSRF::Utils::Logger";
44
45 # log levels
46 sub ACTIVITY    { return -1; }
47 sub NONE                        { return 0;     }
48 sub ERROR               { return 1;     }
49 sub WARN                        { return 2;     }
50 sub INFO                        { return 3;     }
51 sub DEBUG               { return 4;     }
52 sub INTERNAL    { return 5;     }
53 sub ALL                 { return 100; }
54
55 my $isclient;  # true if we control the osrf_xid
56
57 # load up our config options
58 sub set_config {
59
60         return if defined $config;
61
62         $config = OpenSRF::Utils::Config->current;
63         if( !defined($config) ) {
64                 $loglevel = INFO();
65                 warn "*** Logger found no config.  Using STDERR ***\n";
66         }
67
68         $loglevel =  $config->bootstrap->loglevel; 
69
70         $logfile = $config->bootstrap->logfile;
71         if($logfile =~ /^syslog/) {
72                 $syslog_enabled = 1;
73                 $logfile_enabled = 0;
74         $logfile = $config->bootstrap->syslog;
75                 $facility = $logfile;
76                 $logfile = undef;
77                 $facility = _fac_to_const($facility);
78                 openlog($service, 0, $facility);
79
80         } else { $logfile = "$logfile"; }
81
82
83     if($syslog_enabled) {
84         # --------------------------------------------------------------
85         # if we're syslogging, see if we have a special syslog facility 
86         # for activity logging.  If not, use the syslog facility for
87         # standard logging
88         # --------------------------------------------------------------
89         $act_syslog_enabled = 1;
90         $act_logfile_enabled = 0;
91         $actfac = $config->bootstrap->actlog || $config->bootstrap->syslog;
92         $actfac = _fac_to_const($actfac);
93         $actfile = undef;
94     } else {
95         # --------------------------------------------------------------
96         # we're not syslogging, use any specified activity log file.
97         # Fall back to the standard log file otherwise
98         # --------------------------------------------------------------
99                 $act_syslog_enabled = 0;
100                 $act_logfile_enabled = 1;
101         $actfile = $config->bootstrap->actlog || $config->bootstrap->logfile;
102     }
103
104
105         $isclient = (OpenSRF::Utils::Config->current->bootstrap->client =~ /^true$/iog) ?  1 : 0;
106 }
107
108 sub _fac_to_const {
109         my $name = shift;
110         return LOG_LOCAL0 unless $name;
111         return LOG_LOCAL0 if $name =~ /local0/i;
112         return LOG_LOCAL1 if $name =~ /local1/i;
113         return LOG_LOCAL2 if $name =~ /local2/i;
114         return LOG_LOCAL3 if $name =~ /local3/i;
115         return LOG_LOCAL4 if $name =~ /local4/i;
116         return LOG_LOCAL5 if $name =~ /local5/i;
117         return LOG_LOCAL6 if $name =~ /local6/i;
118         return LOG_LOCAL7 if $name =~ /local7/i;
119         return LOG_LOCAL0;
120 }
121
122 sub is_syslog {
123         set_config();
124         return $syslog_enabled;
125 }
126
127 sub is_act_syslog {
128         set_config();
129         return $act_syslog_enabled;
130 }
131
132 sub is_filelog {
133         set_config();
134         return $logfile_enabled;
135 }
136
137 sub is_act_filelog {
138         set_config();
139         return $act_logfile_enabled;
140 }
141
142 sub set_service {
143         my( $self, $svc ) = @_;
144         $service = $svc;        
145         if( is_syslog() ) {
146                 closelog();
147                 openlog($service, 0, $facility);
148         }
149 }
150
151 sub error {
152         my( $self, $msg, $level ) = @_;
153         $level = ERROR() unless defined ($level);
154         _log_message( $msg, $level );
155 }
156
157 sub warn {
158         my( $self, $msg, $level ) = @_;
159         $level = WARN() unless defined ($level);
160         _log_message( $msg, $level );
161 }
162
163 sub info {
164         my( $self, $msg, $level ) = @_;
165         $level = INFO() unless defined ($level);
166         _log_message( $msg, $level );
167 }
168
169 sub debug {
170         my( $self, $msg, $level ) = @_;
171         $level = DEBUG() unless defined ($level);
172         _log_message( $msg, $level );
173 }
174
175 sub internal {
176         my( $self, $msg, $level ) = @_;
177         $level = INTERNAL() unless defined ($level);
178         _log_message( $msg, $level );
179 }
180
181 sub activity {
182         my( $self, $msg ) = @_;
183         _log_message( $msg, ACTIVITY() );
184 }
185
186 # for backward compability
187 sub transport {
188         my( $self, $msg, $level ) = @_;
189         $level = DEBUG() unless defined ($level);
190         _log_message( $msg, $level );
191 }
192
193
194 # ----------------------------------------------------------------------
195 # creates a new xid if necessary
196 # ----------------------------------------------------------------------
197 my $osrf_xid = '';
198 my $osrf_xid_inc = 0;
199 sub mk_osrf_xid {
200    return unless $isclient;
201    $osrf_xid_inc++;
202    return $osrf_xid = "$^T${$}$osrf_xid_inc";
203 }
204
205 sub set_osrf_xid { 
206    return if $isclient; # if we're a client, we control our xid
207    $osrf_xid = $_[1]; 
208 }
209
210 sub get_osrf_xid { return $osrf_xid; }
211 # ----------------------------------------------------------------------
212
213    
214 sub _log_message {
215         my( $msg, $level ) = @_;
216         return if $level > $loglevel;
217
218         my $l; my $n; 
219         my $fac = $facility;
220
221         if ($level == ERROR())                  {$l = LOG_ERR; $n = "ERR "; }
222         elsif ($level == WARN())                {$l = LOG_WARNING; $n = "WARN"; }
223         elsif ($level == INFO())                {$l = LOG_INFO; $n = "INFO"; }  
224         elsif ($level == DEBUG())               {$l = LOG_DEBUG; $n = "DEBG"; }
225         elsif ($level == INTERNAL())    {$l = LOG_DEBUG; $n = "INTL"; }
226         elsif ($level == ACTIVITY())    {$l = LOG_INFO; $n = "ACT"; $fac = $actfac; }
227
228         my( undef, $file, $line_no ) = caller(1);
229    $file =~ s#/.*/##og;
230
231         # help syslog with the formatting
232         $msg =~ s/\%/\%\%/gso if( is_act_syslog() or is_syslog() );
233
234         $msg = "[$n:"."$$".":$file:$line_no:$osrf_xid] $msg";
235
236         $msg = substr($msg, 0, 1536); 
237
238         if( $level == ACTIVITY() ) {
239                 if( is_act_syslog() ) { syslog( $fac | $l, $msg ); } 
240                 elsif( is_act_filelog() ) { _write_file( $msg, 1 ); }
241
242         } else {
243                 if( is_syslog() ) { syslog( $fac | $l, $msg ); }
244                 elsif( is_filelog() ) { _write_file($msg); }
245         }
246 }
247
248
249 sub _write_file {
250         my( $msg, $isact) = @_;
251         my $file = $logfile;
252         $file = $actfile if $isact;
253         my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);  
254         $year += 1900; $mon += 1;
255         sysopen( SINK, $file, O_NONBLOCK|O_WRONLY|O_APPEND|O_CREAT ) 
256                 or die "Cannot sysopen $logfile: $!";
257         binmode(SINK, ':utf8');
258         print SINK "[$year-$mon-$mday $hour:$min:$sec] $service $msg\n";
259         close( SINK );
260 }
261
262
263
264 1;