package Guardian::Logger; use strict; use warnings; use Exporter qw(import); our @EXPORT_OK = qw(New Log GetLogLevels); use Sys::Syslog qw(:DEFAULT setlogsock); # Hash which stores all supported log levels and their priority. my %loglevels = ( 'off' => '0', 'err' => '1', 'info' => '1', 'debug' => '2', ); # This hash contains the supported log facilities and their corresponding subroutines. my %logfacilities = ( "console" => \&LogFacilityConsole, "syslog" => \&LogFacilitySyslog, ); # ## The "New" (Logger) function. # ## This function is responsible to initialize the Logger as a class based object. ## It has to be called once before logging can be done. # ## The following arguments must be passed, when initializing a new Logger: ## "LogLevel" and "LogFacility" with valid values from above. # sub New (%) { my ( $class, %args ) = @_; my $self = \%args; # Fail, if some critical arguments are missing. unless ((exists($self->{LogLevel})) && (exists($self->{LogFacility}))) { die "Could not initialize the Logger: Too less arguments are given.\n"; } # Use bless to make "$self" to an object of class "$class". bless($self, $class); # Return the class object. return $self; } # ## The main "Log" function. # ## This function is used to handle the messages which are generated on various ## points in the main programm or its modules. Those messages will contain usefull ## information or deeper details about errors. # ## The Log function takes care about the configured loglevel and transmitts the ## log messages to the configured log facility. # sub Log ($$) { my $self = shift; my ($level, $message) = @_; # Check if we got an invalid loglevel. unless(exists($loglevels{$level})) { &Log("err", "The logger has been called with an invalid loglevel ($level)!\n"); return; } # Get value for the current used loglevel. my $current_level = $loglevels{$self->{LogLevel}}; # Get value for the required loglevel. my $required_level = $loglevels{$level}; # Compare the current and required level to determine, # if the message should be handled. if ($current_level >= $required_level) { # Get the facility, which should be used. my $use_facility = $self->{LogFacility}; # Transmit log message to the correct log facility. $logfacilities{$use_facility}->($level, $message); } } # ## The Update (Logger) settings function # ## This function is used to update the object settings of the ## initialized Logger class. # sub Update (%) { my ($self, %args) = @_; # Map the new hash keys and values to the existing one inside # the class. map { $self->{ $_ } = $args{ $_ } } keys %args; } # ## GetLogLevels function. # ## This really simple function just returns the hash which ## contains all supported log levels. # sub LogLevels () { # Nothing to do, just return the loglevels hash. return %loglevels; } # ## LogFacilityConsole function. # ## This is a very simple log facility which just prints the given log ## message to STDOUT. # sub LogFacilityConsole ($$) { my ($type, $message) = @_; # Print message on STDOUT. print STDOUT "\[$type\] $message\n"; } # ## LogFacilitySyslog function. # ## This log facility sends a given log message to the system log service (syslog). # sub LogFacilitySyslog ($$) { my ($type, $message) = @_; # The syslog function works best with an array based input, # so generate one before passing the message details to syslog. my @syslog = ("$type", "<$type> $message"); # Establish the connection to the syslog service. openlog('guardian', 'cons,pid', 'user'); # Send the log message. syslog(@syslog); # Close the log handle. closelog(); } 1;