truncating long log lines that go to syslog, as it kills the perl sprintf for some...
[Evergreen.git] / OpenSRF / 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
28 %EXPORT_TAGS = ( level => [ qw/ NONE ERROR WARN INFO DEBUG INTERNAL / ] );
29
30 my $config;                                                     # config handle
31 my $loglevel;                                           # global log level
32 my $logfile;                                            # log file
33 my $facility;                                           # syslog facility
34 my $actfac;                                                     # activity log syslog facility
35 my $actfile;                                            # activity log file
36 my $service = $0;                       # default service name
37 my $syslog_enabled = 0;                 # is syslog enabled?
38 my $act_syslog_enabled = 0;     # is syslog enabled?
39 my $logfile_enabled = 1;                # are we logging to a file?
40 my $act_logfile_enabled = 1;    # are we logging to a file?
41 my $logdir;                                                     # log file directory
42
43 # log levels
44 sub ACTIVITY    { return -1; }
45 sub NONE                        { return 0;     }
46 sub ERROR               { return 1;     }
47 sub WARN                        { return 2;     }
48 sub INFO                        { return 3;     }
49 sub DEBUG               { return 4;     }
50 sub INTERNAL    { return 5;     }
51 sub ALL                 { return 100; }
52
53 # load up our config options
54 sub set_config {
55
56         return if defined $config;
57
58         $config = OpenSRF::Utils::Config->current;
59         if( !defined($config) ) {
60                 $loglevel = INFO();
61                 warn "*** Logger found no config.  Using STDERR ***\n";
62         }
63
64         $loglevel =  $config->bootstrap->debug; 
65         if($loglevel =~ /error/i){ $loglevel = ERROR(); }
66         elsif($loglevel =~ /warn/i){ $loglevel = WARN(); }
67         elsif($loglevel =~ /info/i){ $loglevel = INFO(); }
68         elsif($loglevel =~ /debug/i){ $loglevel = DEBUG(); }
69         elsif($loglevel =~ /internal/i){ $loglevel = INTERNAL(); }
70         else{$loglevel= INFO(); }
71
72         my $logdir = $config->bootstrap->log_dir;
73
74         $logfile = $config->bootstrap->logfile;
75         if($logfile =~ /^syslog/) {
76                 $syslog_enabled = 1;
77                 $logfile_enabled = 0;
78                 $logfile =~ s/^syslog:?//;
79                 $facility = $logfile;
80                 $logfile = undef;
81                 $facility = _fac_to_const($facility);
82                 openlog($service, 0, $facility);
83
84         } else { $logfile = "$logdir/$logfile"; }
85
86         $actfile = $config->bootstrap->actlog;
87         if($actfile =~ /^syslog/) {
88                 $act_syslog_enabled = 1;
89                 $act_logfile_enabled = 0;
90                 $actfile =~ s/^syslog:?//;
91                 $actfac = $actfile || "local1";
92                 $actfile = undef;
93                 $actfac = _fac_to_const($actfac);
94
95         } else { $actfile = "$logdir/$actfile"; }
96
97         #warn "Level: $loglevel, Fac: $facility, Act: $actfac\n";
98 }
99
100 sub _fac_to_const {
101         my $name = shift;
102         return LOG_LOCAL0 unless $name;
103         return LOG_LOCAL0 if $name =~ /local0/i;
104         return LOG_LOCAL1 if $name =~ /local1/i;
105         return LOG_LOCAL2 if $name =~ /local2/i;
106         return LOG_LOCAL3 if $name =~ /local3/i;
107         return LOG_LOCAL4 if $name =~ /local4/i;
108         return LOG_LOCAL5 if $name =~ /local5/i;
109         return LOG_LOCAL6 if $name =~ /local6/i;
110         return LOG_LOCAL7 if $name =~ /local7/i;
111         return LOG_LOCAL0;
112 }
113
114 sub is_syslog {
115         set_config();
116         return $syslog_enabled;
117 }
118
119 sub is_act_syslog {
120         set_config();
121         return $act_syslog_enabled;
122 }
123
124 sub is_filelog {
125         set_config();
126         return $logfile_enabled;
127 }
128
129 sub is_act_filelog {
130         set_config();
131         return $act_logfile_enabled;
132 }
133
134 sub set_service {
135         my( $self, $svc ) = @_;
136         $service = $svc;        
137         if( is_syslog() ) {
138                 closelog();
139                 openlog($service, 0, $facility);
140         }
141 }
142
143 sub error {
144         my( $self, $msg, $level ) = @_;
145         $level = ERROR() unless defined ($level);
146         _log_message( $msg, $level );
147 }
148
149 sub warn {
150         my( $self, $msg, $level ) = @_;
151         $level = WARN() unless defined ($level);
152         _log_message( $msg, $level );
153 }
154
155 sub info {
156         my( $self, $msg, $level ) = @_;
157         $level = INFO() unless defined ($level);
158         _log_message( $msg, $level );
159 }
160
161 sub debug {
162         my( $self, $msg, $level ) = @_;
163         $level = DEBUG() unless defined ($level);
164         _log_message( $msg, $level );
165 }
166
167 sub internal {
168         my( $self, $msg, $level ) = @_;
169         $level = INTERNAL() unless defined ($level);
170         _log_message( $msg, $level );
171 }
172
173 sub activity {
174         my( $self, $msg ) = @_;
175         _log_message( $msg, ACTIVITY() );
176 }
177
178 # for backward compability
179 sub transport {
180         my( $self, $msg, $level ) = @_;
181         $level = DEBUG() unless defined ($level);
182         _log_message( $msg, $level );
183 }
184
185
186
187 sub _log_message {
188         my( $msg, $level ) = @_;
189         return if $level > $loglevel;
190
191         my $l; my $n; 
192         my $fac = $facility;
193
194         if ($level == ERROR())                  {$l = LOG_ERR; $n = "ERR "; }
195         elsif ($level == WARN())                {$l = LOG_WARNING; $n = "WARN"; }
196         elsif ($level == INFO())                {$l = LOG_INFO; $n = "INFO"; }  
197         elsif ($level == DEBUG())               {$l = LOG_DEBUG; $n = "DEBG"; }
198         elsif ($level == INTERNAL())    {$l = LOG_DEBUG; $n = "INTL"; }
199         elsif ($level == ACTIVITY())    {$l = LOG_INFO; $n = "ACT"; $fac = $actfac; }
200
201         #my( $pack, $file, $line_no ) = @caller;
202
203         $msg = "[$n:"."$$".":::] $msg";
204
205         if( $level == ACTIVITY() ) {
206                 if( is_act_syslog() ) { syslog( $fac | $l, substr($msg,0,100) ); } 
207                 elsif( is_act_filelog() ) { _write_file( $msg, 1 ); }
208
209         } else {
210                 if( is_syslog() ) { syslog( $fac | $l, substr($msg,0,100) ); }
211                 elsif( is_filelog() ) { _write_file($msg); }
212         }
213 }
214
215
216 sub _write_file {
217         my( $msg, $isact) = @_;
218         my $file = $logfile;
219         $file = $actfile if $isact;
220         my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);  
221         $year += 1900; $mon += 1;
222         sysopen( SINK, $file, O_NONBLOCK|O_WRONLY|O_APPEND|O_CREAT ) 
223                 or die "Cannot sysopen $logfile: $!";
224         binmode(SINK, ':utf8');
225         print SINK "[$year-$mon-$mday $hour:$min:$sec] $service $msg\n";
226         close( SINK );
227 }
228
229
230
231 1;