Beekeeper

 view release on metacpan or  search on metacpan

lib/Beekeeper/Logger.pm  view on Meta::CPAN

use JSON::XS;
use Exporter 'import';
use Time::HiRes;

my $JSON;

our @EXPORT_OK = qw(
    LOG_FATAL
    LOG_ALERT
    LOG_CRIT
    LOG_ERROR
    LOG_WARN
    LOG_NOTICE
    LOG_INFO
    LOG_DEBUG
    LOG_TRACE
    %LOG_LABEL
);

our %EXPORT_TAGS = ('log_levels' => \@EXPORT_OK );

our %LOG_LABEL = (
    &LOG_FATAL  => 'fatal',
    &LOG_ALERT  => 'alert',
    &LOG_CRIT   => 'critical',
    &LOG_ERROR  => 'error',
    &LOG_WARN   => 'warning',
    &LOG_NOTICE => 'notice',
    &LOG_INFO   => 'info',
    &LOG_DEBUG  => 'debug',
    &LOG_TRACE  => 'trace',
);


sub new {
    my $class = shift;

    my $self = {
        worker_class => undef,
        foreground   => undef,
        log_file     => undef,
        service      => undef,
        host         => undef,
        pool         => undef,
        _BUS         => undef,
        @_
    };

    unless ($self->{service}) {
        # Make an educated guess based on worker class
        my $service = lc $self->{worker_class};
        $service =~ s/::/-/g;
        $service =~ s/-worker$//;

        $self->{service} = $service;
    }

    unless ($self->{log_file}) {
        # Use a single log file per service
        my $dir  = '/var/log';
        my $user = getpwuid($>);
        my $file = $self->{service} . '.log';
        ($user) = ($user =~ m/(\w+)/); # untaint

        $self->{log_file} = (-d "$dir/$user") ? "$dir/$user/$file" : "$dir/$file";
    }

    unless ($self->{foreground}) {

        my $log_file = $self->{log_file};

        # If running as root temporarily restore uid and gid to allow opening
        local $> = $< if ($< == 0);
        local $) = $( if ($( == 0);

        if (open(my $fh, '>>', $log_file)) {
            # Send STDERR and STDOUT to log file
            open(STDERR, '>&', $fh) or die "Can't redirect STDERR to $log_file: $!";
            open(STDOUT, '>&', $fh) or die "Can't redirect STDOUT to $log_file: $!";
        }
        else {
            # Probably no permissions to open the log file
            warn "Can't open log file $log_file: $!";
        }
    }

    bless $self, $class;
    return $self; 
}

sub log {
    my ($self, $level, @msg) = @_;

    my $msg = join(' ', map { defined $_ ? "$_" : 'undef' } @msg );
    chomp($msg);

    my $now = Time::HiRes::time;
    my $ms = int(($now * 1000) % 1000);
    my @t = reverse((localtime)[0..5]); $t[0] += 1900; $t[1]++;
    my $tstamp = sprintf("%4d-%02d-%02d %02d:%02d:%02d.%03d", @t, $ms);

    ## 1. Log to local file

    print STDERR "[$tstamp][$$][$LOG_LABEL{$level}] $msg\n";

    ## 2. Log to topic

    my $bus = $self->{_BUS};
    return unless $bus && $bus->{is_connected};

    # JSON-RPC notification

    $JSON = JSON::XS->new->utf8->allow_blessed->convert_blessed unless defined $JSON;

    my $json = $JSON->encode({
        jsonrpc => '2.0',
        method  => $LOG_LABEL{$level},
        params  => {
            level   => $level,
            service => $self->{service},
            host    => $self->{host},



( run in 3.790 seconds using v1.01-cache-2.11-cpan-d8267643d1d )