File: Syslog.pm

package info (click to toggle)
liblog-report-perl 1.40-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 568 kB
  • sloc: perl: 2,905; makefile: 8
file content (128 lines) | stat: -rw-r--r-- 3,344 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# Copyrights 2007-2025 by [Mark Overmeer <markov@cpan.org>].
#  For other contributors see ChangeLog.
# See the manual pages for details on the licensing terms.
# Pod stripped from pm file by OODoc 2.03.
# This code is part of distribution Log-Report. Meta-POD processed with
# OODoc into POD and HTML manual-pages.  See README.md
# Copyright Mark Overmeer.  Licensed under the same terms as Perl itself.

package Log::Report::Dispatcher::Syslog;{
our $VERSION = '1.40';
}

use base 'Log::Report::Dispatcher';

use warnings;
use strict;

use Log::Report 'log-report';

use Sys::Syslog        qw/:standard :extended :macros/;
use Log::Report::Util  qw/@reasons expand_reasons/;
use Encode             qw/encode/;

use File::Basename qw/basename/;

my %default_reasonToPrio =
  ( TRACE   => LOG_DEBUG
  , ASSERT  => LOG_DEBUG
  , INFO    => LOG_INFO
  , NOTICE  => LOG_NOTICE
  , WARNING => LOG_WARNING
  , MISTAKE => LOG_WARNING
  , ERROR   => LOG_ERR
  , FAULT   => LOG_ERR
  , ALERT   => LOG_ALERT
  , FAILURE => LOG_EMERG
  , PANIC   => LOG_CRIT
  );

@reasons==keys %default_reasonToPrio
    or panic __"not all reasons have a default translation";


my $active;

sub init($)
{   my ($self, $args) = @_;
    $args->{format_reason} ||= 'IGNORE';

    $self->SUPER::init($args);

    error __x"max one active syslog dispatcher, attempt for {new} have {old}"
      , new => $self->name, old => $active
        if $active;
    $active   = $self->name;

    setlogsock(delete $args->{logsocket})
        if $args->{logsocket};

    my $ident = delete $args->{identity} || basename $0;
    my $flags = delete $args->{flags}    || 'pid,nowait';
    my $fac   = delete $args->{facility} || 'user';
    openlog $ident, $flags, $fac;   # doesn't produce error.

    $self->{LRDS_incl_dom} = delete $args->{include_domain};
    $self->{LRDS_charset}  = delete $args->{charset} || "utf-8";
    $self->{LRDS_format}   = $args->{format} || sub {$_[0]};

    $self->{prio} = +{ %default_reasonToPrio };
    if(my $to_prio = delete $args->{to_prio})
    {   my @to = @$to_prio;
        while(@to)
        {   my ($reasons, $level) = splice @to, 0, 2;
            my @reasons = expand_reasons $reasons;

            my $prio    = Sys::Syslog::xlate($level);
            error __x"syslog level '{level}' not understood", level => $level
                if $prio eq -1;

            $self->{prio}{$_} = $prio for @reasons;
        }
    }

    $self;
}

sub close()
{   my $self = shift;
    undef $active;
    closelog;

    $self->SUPER::close;
}

#--------------

sub format(;$)
{   my $self = shift;
    @_ ? $self->{LRDS_format} = shift : $self->{LRDS_format};
}

#--------------

sub log($$$$$)
{   my ($self, $opts, $reason, $msg, $domain) = @_;
    my $text   = $self->translate($opts, $reason, $msg) or return;
    my $format = $self->format;

    # handle each line in message separately
    $text    =~ s/\s+$//s;
    my @text = split /\n/, $format->($text, $domain, $msg, %$opts);

    my $prio    = $self->reasonToPrio($reason);
    my $charset = $self->{LRDS_charset};

    if($self->{LRDS_incl_dom} && $domain)
    {   $domain  =~ s/\%//g;    # security
        syslog $prio, "$domain %s", encode($charset, shift @text);
    }

    syslog $prio, "%s", encode($charset, $_)
        for @text;
}


sub reasonToPrio($) { $_[0]->{prio}{$_[1]} }

1;