File Coverage

blib/lib/HeliosX/Logger/Log4perl.pm
Criterion Covered Total %
statement 6 6 100.0
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 8 8 100.0


line stmt bran cond sub pod time code
1             package HeliosX::Logger::Log4perl;
2              
3 1     1   24004 use 5.008;
  1         4  
  1         34  
4 1     1   5 use base qw(Helios::Logger);
  1         1  
  1         706  
5             use strict;
6             use warnings;
7              
8             use Log::Log4perl;
9              
10             use Helios::LogEntry::Levels qw(:all);
11             use Helios::Error::LoggingError;
12              
13             our $VERSION = '1.00';
14              
15             =head1 NAME
16              
17             HeliosX::Logger::Log4perl - Helios::Logger subclass implementing logging to Log4perl for Helios
18              
19             =head1 SYNOPSIS
20              
21             # in your helios.ini
22             loggers=HeliosX::Logger::Log4perl
23             log4perl_conf=/path/to/log4perl.conf
24             log4perl_category=logging.category
25             log4perl_watch_interval=10
26             log4perl_priority_threshold=6
27            
28             # log4perl supports lots of options, so you can get creative
29             # e.g. log everything to log4perl,
30             # but specify which services go to which categories
31             [global]
32             internal_logging=off
33             loggers=HeliosX::Logger::Log4perl
34             log4perl_conf=/etc/helios_log4perl.conf
35            
36             # log all the MyApp::* services to the same log4perl category
37             [MyApp::MetajobBurstService]
38             log4perl_category=MyApp
39             [MyApp::IndexerService]
40             log4perl_category=MyApp
41             [MyApp::ReportingService]
42             log4perl_category=MyApp
43            
44             [YourApp]
45             # we won't specify a category here, so Helios will default to category 'YourApp'
46              
47             =head1 DESCRIPTION
48              
49             This class implements a Helios::Logger class to provide Helios applications
50             the logging capabilities of Log4perl.
51              
52             For information about configuring Log4perl, see the L documentation.
53              
54             =head1 HELIOS.INI CONFIGURATION
55              
56             =head2 log4perl_conf [REQUIRED]
57              
58             The location of the Log4perl configuration file. If specified in your
59             helios.ini [global] section, the conf file will apply to all of your
60             Helios services. You may also configure different conf files for specific
61             services by placing the log4perl_conf line in an individual service's
62             helios.ini section.
63              
64             See the Log4perl documentation for details about configuring Log4perl itself.
65              
66             =head2 log4perl_category
67              
68             The Log4perl "category" to log messages for this service. If declared in your
69             helios.ini [global] section, all Helios services will send log messages to the
70             specified category. If specified in a single service's section, only that
71             service will send log messages to the specified category. You may also declare
72             a default category in the [global] section, and specific categories for
73             particular Helios services, allowing certain services to log to their own
74             category but others to default to the global one.
75              
76             If log4perl_category is not specified, the Log4perl category will default to
77             the name of your service class.
78              
79             =head2 log4perl_watch_interval
80              
81             If specified, Log4perl will reread the log4perl_conf file after the given
82             number of seconds and update its configuration accordingly. If this isn't
83             specified, any changes to your conf file will require you to restart your
84             service daemon to pick up the new configuration.
85              
86             =head2 log4perl_priority_threshold
87              
88             Just like log_priority_threshold, but for syslogd. If you just want to log
89             messages of a certain priority or higher, you can set a numeric value for
90             log4perl_priority_threshold and any log messages of a higher value (lower
91             priority) will be discarded. The priority levels are defined in
92             Helios::LogEntry::Levels.
93              
94             =head3 Priority Translation
95              
96             Helios was originally developed using Sys::Syslog as its primary logging
97             system. It eventually developed its own internal logging subsystem, and
98             Helios 2.30 added the Helios::Logger interface to further modularize Helios's
99             logging capabilities and make it useful in more environments. Due to this
100             history, however, Helios defines 8 logging priorities versus Log4perl's 5.
101             HeliosX::Logger::Log4perl translates on-the-fly several of the priority levels
102             defined in Helios::LogEntry::Levels to Log4perl's levels:
103              
104             numeric value Helios::LogEntry::Levels Log::Log4perl::Level
105             0 LOG_EMERG $FATAL
106             1 LOG_ALERT $FATAL
107             2 LOG_CRIT $FATAL
108             3 LOG_ERR $ERROR
109             4 LOG_WARNING $WARN
110             5 LOG_NOTICE $INFO
111             6 LOG_INFO $INFO
112             7 LOG_DEBUG $DEBUG
113              
114             =head1 IMPLEMENTED METHODS
115              
116             =head2 init($config, $jobType)
117              
118             The init() method verifies log4perl_conf is set in helios.ini and can be read. It then calls
119             Log::Log4perl::init() or (if log4perl_watch_interval is set) Log::Log4perl::init_and_watch() to
120             set up the Log4perl system for logging.
121              
122             =cut
123              
124             sub init {
125             my $self = shift;
126             my $config = $self->getConfig();
127              
128             unless ( defined($config->{log4perl_conf}) && (-r $config->{log4perl_conf}) ) {
129             throw Helios::Error::LoggingError('CONFIGURATION ERROR: log4perl_conf not defined or cannot be read');
130             }
131            
132             if ( defined($config->{log4perl_watch_interval}) ) {
133             Log::Log4perl::init_and_watch($config->{log4perl_conf}, $config->{log4perl_watch_interval});
134             } else {
135             Log::Log4perl::init($config->{log4perl_conf});
136             }
137             return 1;
138             }
139              
140              
141             =head2 logMsg($job, $priority_level, $message)
142              
143             The logMsg() method logs the given message to the configured log4perl_category with the given
144             $priority_level.
145              
146              
147             =cut
148              
149             sub logMsg {
150             my $self = shift;
151             my $job = shift;
152             my $level = shift;
153             my $msg = shift;
154             my $config = $self->getConfig();
155             my $logger;
156              
157             # has log4perl been initialized yet?
158             unless ( Log::Log4perl->initialized() ) {
159             $self->init();
160             }
161              
162             # if syslog_priority_threshold is set & this priority
163             # isn't as bad as that, don't bother doing any syslog stuff
164             if ( defined($config->{log4perl_priority_threshold}) &&
165             $level > $config->{log4perl_priority_threshold} )
166             {
167             return;
168             }
169              
170             # if a l4p category was specified, get a logger for it
171             # otherwise, get a logger for the jobtype
172             if ( defined($config->{log4perl_category}) ) {
173             $logger = Log::Log4perl->get_logger($config->{log4perl_category});
174             } else {
175             $logger = Log::Log4perl->get_logger($self->getJobType());
176             }
177              
178             # assemble message from the parts we have
179             $msg = $self->assembleMsg($job, $level, $msg);
180              
181             # we shouldn't have to do a level check, since
182             # Helios::Service->logMsg() will default the level to LOG_INFO
183             # still, it can't hurt
184             if ( defined($level) ) {
185             SWITCH: {
186             if ($level eq LOG_DEBUG) { $logger->debug($msg); last SWITCH; }
187             if ($level eq LOG_INFO
188             || $level eq LOG_NOTICE) { $logger->info($msg); last SWITCH; }
189             if ($level eq LOG_WARNING) { $logger->warn($msg); last SWITCH; }
190             if ($level eq LOG_ERR) { $logger->error($msg); last SWITCH; }
191             if ($level eq LOG_CRIT
192             || $level eq LOG_ALERT
193             || $level eq LOG_EMERG) { $logger->fatal($msg); last SWITCH; }
194             throw Helios::Error::LoggingError('Invalid log level '.$level);
195             }
196             } else {
197             # $level wasn't defined, so we'll default to INFO
198             $logger->info($msg);
199             }
200             return 1;
201             }
202              
203              
204             =head2 assembleMsg($job, $priority_level, $msg)
205              
206             Given the information passed to logMsg(), assembleMsg() returns the text
207             string to be logged to the Log4perl category. Separating this step into its
208             own method allows you to easily override the default message format if you so
209             choose. Simply subclass HeliosX::Logger::Log4perl and override assembleMsg()
210             with your own message formatting method.
211              
212             =cut
213              
214             sub assembleMsg {
215             my ($self, $job, $level, $msg) = @_;
216             if ( defined($job) ) {
217             return 'Job:'.$job->getJobid().' '.$self->getJobType().' ('.$self->getHostname.') '.$msg;
218             } else {
219             return $self->getJobType().' ('.$self->getHostname.') '.$msg;
220             }
221             }
222              
223              
224              
225             1;
226             __END__