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