the-bastion/lib/perl/OVH/SimpleLog.pm
2023-11-08 13:21:20 +01:00

133 lines
3.3 KiB
Perl

package OVH::SimpleLog;
# vim: set filetype=perl ts=4 sw=4 sts=4 et:
use common::sense;
# Simple package to log either to a file, to syslog, or to both
# Exports the _log, _warn and _err routines to do so
use base qw (Exporter);
our @EXPORT = qw(_log _warn _err); ## no critic (ProhibitAutomaticExportation)
use Term::ANSIColor;
use Sys::Syslog qw{};
# Log file handler
my $LOG_FH;
# Syslog
my $FACILITY;
# Program name
my $PROGNAME;
# Incremented at each call of _err and _warn, count can be
# fetched with nb_errors() and nb_warnings()
my $NB_ERRORS = 0;
my $NB_WARNINGS = 0;
BEGIN {
# Extract program base name
$PROGNAME = $0;
if ($PROGNAME =~ /\/([^\/]+)$/) {
$PROGNAME = $1;
}
}
# Set a log file
sub setLogFile {
my $filename = shift;
if (not open($LOG_FH, '>>', $filename)) {
_warn("Unable to open log file '$filename' ($!)");
return 0;
}
return 1;
}
sub setSyslog {
# if we previously opened syslog, close it
closeSyslog();
# then (re)open it with the wanted facility
$FACILITY = shift;
Sys::Syslog::openlog($PROGNAME . "[$$]", 'nofatal', $FACILITY);
return 1;
}
sub closeSyslog {
Sys::Syslog::closelog() if $FACILITY;
undef $FACILITY;
return 1;
}
sub _log { _display('LOG', @_); return 1; } ## no critic (ProhibitUnusedPrivateSubroutines)
sub _warn { _display('WARN', @_); $NB_WARNINGS++; return 1; }
sub _err { _display('ERR', @_); $NB_ERRORS++; return 1; } ## no critic (ProhibitUnusedPrivateSubroutines)
# Display a message
sub _display {
my $level = shift;
my $message = shift;
# Prepare message and possibly color
my $color = '';
my $fullmsg = $message;
my $OUT = 'STDOUT';
if ($level eq 'ERR') {
$color = 'red';
$fullmsg = "ERROR: $message";
$OUT = 'STDERR';
}
elsif ($level eq 'WARN') {
$color = 'yellow';
$fullmsg = "WARN: $message";
$OUT = 'STDERR';
}
# If it's not for a terminal, don't colorize log
# perlcritic doesn't like -t, but IO::Interactive is not in core as per corelist
$color = '' if not -t $OUT; ## no critic (ProhibitInteractiveTest)
my $coloredmsg = $fullmsg;
$coloredmsg = colored($fullmsg, $color) if $color;
if ($OUT eq 'STDERR') {
print STDERR $coloredmsg . "\n";
}
else {
print $coloredmsg. "\n";
}
# Print on a log file (if needed)
if ($LOG_FH) {
printf $LOG_FH "%s [%6s] %s: %s\n", scalar(localtime()), $level, $PROGNAME, $message;
}
# Push to syslog (only if a facility has been defined, which means openlog() has been called)
if ($FACILITY) {
# valid levels: DEBUG, INFO, NOTICE, WARNING, ERR, EMERG
my $priority = uc($level);
$priority = 'WARNING' if $priority eq 'WARN';
$priority = 'INFO' if (!grep { $priority eq $_ } qw{ DEBUG NOTICE WARNING ERR EMERG });
eval { Sys::Syslog::syslog($priority, $fullmsg); };
if ($@) {
print STDERR "Couldn't syslog, report to administrator ($@)\n";
}
}
return 1;
}
sub nb_errors { return $NB_ERRORS; }
sub nb_warnings { return $NB_WARNINGS; }
END {
close($LOG_FH) if (defined $LOG_FH);
Sys::Syslog::closelog() if (defined $FACILITY);
}
1;