Syslog.pm 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package Trog::Log::Syslog;
  2. use 5.040;
  3. use re '/aa';
  4. use parent qw{Log::Dispatch::Output};
  5. use Log::Syslog::Fast qw{:protos :formats};
  6. =head1 Trog::Log::Syslog
  7. A Log::Dispatch output which hands each line to the syslog of the machine, over
  8. its unix socket. From there journald and rsyslog have it, and whatever they
  9. forward it to.
  10. Name it in the C<loggers> of tpsgi.ini:
  11. loggers = Trog::Log::Syslog
  12. tPSGI then adds it to its own logger, and TCMS passes the same list to
  13. log_init(), so both write here as well as to the rotated file.
  14. Lines go out as C<daemon>, tagged C<tcms>, at the severity of their level.
  15. Each keeps the timestamp that Trog::Log puts at its front, so a line on a log
  16. collector reads the same as the line in the file.
  17. =head1 Termination Conditions
  18. new() dies when it cannot connect to the socket. A line that cannot be sent
  19. later is dropped without a word: the file output has it, and a request that
  20. fails because its log line did not arrive is worse than a line that did not
  21. arrive.
  22. =head1 METHODS
  23. =head2 new(%options) = Trog::Log::Syslog
  24. Takes what tPSGI hands every logger, C<min_level> and C<log_dir>, and ignores
  25. C<log_dir>. C<socket> is where to send, F</dev/log> unless a test says
  26. otherwise. C<ident> is the tag, C<tcms> unless given.
  27. =cut
  28. # LOG_DAEMON, from sys/syslog.h.
  29. my $DAEMON = 3;
  30. sub new ( $class, %p ) {
  31. my $self = bless( {}, $class );
  32. $self->_basic_init( map { exists $p{$_} ? ( $_ => $p{$_} ) : () } qw{name min_level max_level} );
  33. my $socket = $p{socket} // '/dev/log';
  34. my $ident = $p{ident} // 'tcms';
  35. # The sender is left out of the format, as syslog(3) leaves it out when it
  36. # writes to this socket, because the receiver is this machine.
  37. $self->{syslog} = Log::Syslog::Fast->new( LOG_UNIX, $socket, 0, $DAEMON, 6, '', $ident );
  38. $self->{syslog}->set_format(LOG_RFC3164_LOCAL);
  39. return $self;
  40. }
  41. =head2 log_message(%p)
  42. Called by Log::Dispatch for each line at or above C<min_level>.
  43. =cut
  44. sub log_message ( $self, %p ) {
  45. # Log::Dispatch numbers its levels from debug at 0 to emergency at 7, and
  46. # syslog numbers its severities the other way round.
  47. my $severity = 7 - $self->_level_as_number( $p{level} );
  48. # Trog::Log ends every line with a newline, which a syslog message does
  49. # not carry.
  50. chomp( my $message = $p{message} );
  51. local $@;
  52. eval {
  53. $self->{syslog}->set_severity($severity);
  54. $self->{syslog}->send( $message, time );
  55. 1;
  56. };
  57. return;
  58. }
  59. 1;