Acrux
view release on metacpan or search on metacpan
lib/Acrux/Log.pm view on Meta::CPAN
my $logger = $log->logger;
This method returns the logger object or undef if not exists
=head2 notice
$log->notice('Normal, but significant, condition...');
$log->notice('Ok', 'then');
Log C<notice> message
=head2 provider
print $log->provider;
Returns provider name (C<external>, C<handle>, C<file> or C<syslog>)
=head2 trace
$log->trace('Whatever');
$log->trace('Who', 'cares');
Log C<trace> message
=head2 warn
$log->warn('Dont do that Dave...');
$log->warn('No', 'really');
Log C<warn> message
=head1 HISTORY
See C<Changes> file
=head1 TO DO
See C<TODO> file
=head1 SEE ALSO
L<Sys::Syslog>
=head1 AUTHOR
Serż Minus (Sergey Lepenkov) L<https://www.serzik.com> E<lt>abalama@cpan.orgE<gt>
=head1 COPYRIGHT
Copyright (C) 1998-2026 D&D Corporation
=head1 LICENSE
This program is distributed under the terms of the Artistic License Version 2.0
See the C<LICENSE> file or L<https://opensource.org/license/artistic-2-0> for details
=cut
use Carp qw/carp croak/;
use Scalar::Util qw/blessed/;
use Sys::Syslog qw//;
use File::Basename qw/basename/;
use IO::File qw//;
use Fcntl qw/:flock/;
use Encode qw/find_encoding/;
use Time::HiRes qw/time/;
use Acrux::Util qw/color/;
use constant {
LOGOPTS => 'ndelay,pid', # For Sys::Syslog
SEPARATOR => ' ',
LOGFORMAT => '%s',
};
my %LOGLEVELS = (
'trace' => Sys::Syslog::LOG_DEBUG, # 7 debug-level message
'debug' => Sys::Syslog::LOG_DEBUG, # 7 debug-level message
'info' => Sys::Syslog::LOG_INFO, # 6 informational message
'notice' => Sys::Syslog::LOG_NOTICE, # 5 normal, but significant, condition
'warn' => Sys::Syslog::LOG_WARNING, # 4 warning conditions
'error' => Sys::Syslog::LOG_ERR, # 3 error conditions
'fatal' => Sys::Syslog::LOG_CRIT, # 2 critical conditions
'crit' => Sys::Syslog::LOG_CRIT, # 2 critical conditions
'alert' => Sys::Syslog::LOG_ALERT, # 1 action must be taken immediately
'emerg' => Sys::Syslog::LOG_EMERG, # 0 system is unusable
);
my %MAGIC = (
'trace' => 8,
'debug' => 7,
'info' => 6,
'notice' => 5,
'warn' => 4, 'warning' => 4,
'error' => 3, 'err' => 3,
'fatal' => 2, 'crit' => 2, 'critical' => 2,
'alert' => 1,
'emerg' => 0, 'emergency' => 0,
);
my %COLORS = (
'trace' => 'white',
'debug' => 'bright_white',
'info' => 'cyan',
'notice' => 'green',
'warn' => 'yellow',
'error' => 'red',
'fatal' => 'bright_red', 'crit' => 'bright_magenta',
'alert' => 'white on_red',
'emerg' => 'bright_white on_red',
);
my %SHORT = ( # Log::Log4perl::Level notation
0 => 'fatal', 1 => 'fatal', 2 => 'fatal',
3 => 'error',
4 => 'warn',
5 => 'info', 6 => 'info',
7 => 'debug',
8 => 'trace',
);
my $ENCODING = find_encoding('UTF-8') or croak qq/Encoding "UTF-8" not found/;
sub new {
my $class = shift;
my $args = @_ ? @_ > 1 ? {@_} : {%{$_[0]}} : {};
$args->{facility} ||= Sys::Syslog::LOG_USER;
$args->{ident} ||= basename($0);
$args->{logopt} ||= LOGOPTS;
$args->{logger} ||= undef;
$args->{level} ||= 'debug';
$args->{file} ||= undef;
$args->{handle} ||= undef;
$args->{provider} = 'unknown';
$args->{autoclean} ||= 0;
$args->{prefix} ||= '';
$args->{format} ||= undef;
$args->{color} ||= 0;
# Check level
$args->{level} = lc($args->{level});
unless (exists $MAGIC{$args->{level}}) {
carp "Incorrect log level specified. Well be used debug log level by default";
$args->{level} = 'debug';
}
# Instance
my $self = bless {%$args}, $class;
# Set formatter
$self->{format} ||= $self->{short} ? \&_short : $self->{color} ? \&_color : \&_default;
# External logger object specified directly
if ($args->{logger}) {
$self->{provider} = "external";
unless (blessed($args->{logger})) {
printf STDERR "Blessed reference expected in \"logger\" attribute. Logging to STDERR instead.\n";
$self->{provider} = "handle";
$self->{handle} = IO::Handle->new_from_fd(fileno(STDERR), "w");
}
}
# Handler specified directly
elsif ($args->{handle}) {
$self->{provider} = "handle";
return $self;
}
# File rules
elsif ($args->{file}) { # File
my $file = $args->{file};
# Open syslog socket
if ($file =~ /^\:?syslog\:?$/i or $file eq '@') {
Sys::Syslog::openlog($args->{ident}, $args->{logopt}, $args->{facility});
$self->{provider} = "syslog";
$self->{file} = "syslog";
}
# Use STDOUT handle
elsif ($file =~ /^\:?stdout\:?$/i or $file eq '-') {
$self->{provider} = "handle";
$self->{handle} = IO::Handle->new_from_fd(fileno(STDOUT), "w");
$self->{file} = "stdout";
}
# Use STDERR handle
elsif ($file =~ /^\:?stderr\:?$/i or $file eq '=') {
$self->{provider} = "handle";
$self->{handle} = IO::Handle->new_from_fd(fileno(STDERR), "w");
$self->{file} = "stderr";
}
# Open log file handle
else {
$self->{provider} = "file";
$self->{handle} = IO::File->new($file, ">>");
unless (defined $self->{handle}) { # Error
printf STDERR "Can't open log file \"%s\" for writing (%s). Logging to STDERR instead.\n",
$file, $!;
$self->{provider} = "handle";
$self->{handle} = IO::Handle->new_from_fd(fileno(STDERR), "w");
}
}
}
# Default: STDERR (since 0.10)
else {
$self->{provider} = "handle";
$self->{handle} = IO::Handle->new_from_fd(fileno(STDERR), "w");
}
return $self;
}
sub file { shift->{file} }
sub level {
( run in 1.288 second using v1.01-cache-2.11-cpan-b16cb0d3907 )