| File: | blib/lib/Log/Abstraction/Backend.pm |
| Coverage: | 100.0% |
| line | stmt | bran | cond | sub | time | code |
|---|---|---|---|---|---|---|
| 1 | package Log::Abstraction::Backend; | |||||
| 2 | ||||||
| 3 | # Base class of the backends that Log::Abstraction sends messages to | |||||
| 4 | 37 37 37 | 139 22 175 | use strict; | |||
| 5 | 37 37 37 | 28 24 386 | use warnings; | |||
| 6 | ||||||
| 7 | 37 37 37 | 31 16 2374 | use Carp (); | |||
| 8 | ||||||
| 9 | our $VERSION = '0.40'; | |||||
| 10 | ||||||
| 11 | # Carp and croak from a backend report the code that called Log::Abstraction, | |||||
| 12 | # not Log::Abstraction itself. The subclasses trust this package through | |||||
| 13 | # @ISA, and so Log::Abstraction too | |||||
| 14 | our @CARP_NOT = ('Log::Abstraction'); | |||||
| 15 | ||||||
| 16 | # True while a message is being handed to Log::Any or Log::Dispatch. If that | |||||
| 17 | # brings it back to a Log::Abstraction (e.g. through | |||||
| 18 | # Log::Any::Adapter::Abstraction), it isn't forwarded again, which would | |||||
| 19 | # loop. Set with local by the log_any and log_dispatch backends, and read by | |||||
| 20 | # Log::Abstraction::_log to find the original caller | |||||
| 21 | our $FORWARDING = 0; | |||||
| 22 | ||||||
| 23 - 79 | =head1 NAME
Log::Abstraction::Backend - base class of the Log::Abstraction backends
=head1 VERSION
0.40
=head1 DESCRIPTION
For use by L<Log::Abstraction> only. C<Log::Abstraction-E<gt>new()> builds
one object of a C<Log::Abstraction::Backend::*> class for each place a
message goes to (a file, an array, syslog ...), and each message is passed to
every one of them. The configuration given to C<new()> is not changed.
The backends are:
Log::Abstraction::Backend::Array array, or logger => \@array
Log::Abstraction::Backend::Code logger => \&code
Log::Abstraction::Backend::Fd fd
Log::Abstraction::Backend::File file, or logger => $path
Log::Abstraction::Backend::Journald journald
Log::Abstraction::Backend::LogAny log_any, or a Log::Any logger
Log::Abstraction::Backend::LogDispatch log_dispatch, or a Log::Dispatch object
Log::Abstraction::Backend::Object any other object as the logger
Log::Abstraction::Backend::Sendmail sendmail
Log::Abstraction::Backend::Syslog syslog
=head1 METHODS
=head2 new
my $backend = Log::Abstraction::Backend::File->new(
file => $path,
level => 4, # numeric threshold, or undef for none
format => $format, # or undef
);
Stores its arguments. They have already been checked by
C<Log::Abstraction-E<gt>new()>; C<level> is a syslog number (0-7).
=head3 API SPECIFICATION
=head4 Input
{
level => { type => 'integer', min => 0, max => 7, optional => 1 },
format => { type => 'string', min => 1, optional => 1 },
# and the destination, under the backend's own key (file, fd,
# array, sendmail ...)
}
=head4 Output
{ type => 'object', isa => 'Log::Abstraction::Backend' }
=cut | |||||
| 80 | ||||||
| 81 | sub new { | |||||
| 82 | 1743 | 5253 | my ($class, %args) = @_; | |||
| 83 | ||||||
| 84 | 1743 | 1963 | return bless { %args }, $class; | |||
| 85 | } | |||||
| 86 | ||||||
| 87 - 104 | =head2 wants
next unless $backend->wants($event);
True if the backend has no level of its own, or the message is at that level
or more severe.
=head3 API SPECIFICATION
=head4 Input
{ event => { type => 'hashref', schema => { priority => { type => 'integer', min => 0, max => 7 } } } }
=head4 Output
{ type => 'boolean' }
=cut | |||||
| 105 | ||||||
| 106 | sub wants { | |||||
| 107 | 11025 | 4415 | my ($self, $event) = @_; | |||
| 108 | ||||||
| 109 | 11025 | 9044 | return 1 unless(defined($self->{'level'})); | |||
| 110 | 56 | 149 | return $event->{'priority'} <= $self->{'level'}; | |||
| 111 | } | |||||
| 112 | ||||||
| 113 - 133 | =head2 text
my $message = $backend->text($event, $event->{text});
The message formatted with the backend's own C<format>, if it has one,
otherwise the default given.
=head3 API SPECIFICATION
=head4 Input
{
event => { type => 'hashref', schema => { render => { type => 'coderef' } } },
default => { type => 'string' },
}
=head4 Output
{ type => 'string' }
=cut | |||||
| 134 | ||||||
| 135 | sub text { | |||||
| 136 | 86 | 64 | my ($self, $event, $default) = @_; | |||
| 137 | ||||||
| 138 | 86 | 108 | return defined($self->{'format'}) ? $event->{'render'}->($self->{'format'}) : $default; | |||
| 139 | } | |||||
| 140 | ||||||
| 141 - 184 | =head2 emit
$backend->emit($logger, $event);
Sends a message, which has passed the logger's level, to the backend.
C<$logger> is the C<Log::Abstraction> object. C<$event> is a hash
reference built by C<Log::Abstraction> for each message:
level the level name, e.g. 'warn'
priority its syslog number (0-7)
message the message, its parts joined and redacted
parts the message's parts (an array reference)
fields the structured fields (a hash reference), or undef
fields_text the fields as key=value text, or undef
text the message with fields_text appended
entry the history entry (a list, as an array reference)
class, file, line, ctx for CODE references
render format a line: $event->{render}->($format), undef for
the logger's format
write write a line to a path (which it checks) or a handle:
$event->{write}->($target, $line)
send_email, hold_email send or keep for later an email:
$event->{send_email}->(\%sendmail, $body)
The closures are how a backend uses Log::Abstraction's private methods.
Subclasses must override this.
=head3 API SPECIFICATION
=head4 Input
{
logger => { type => 'object', isa => 'Log::Abstraction' },
event => { type => 'hashref' }, # the keys above
}
=head4 Output
None. The base class's emit() croaks "<class>: emit() is not
implemented"; a subclass's sends the message. A failed delivery is
carped, not fatal; a configuration error (e.g. an invalid sendmail
host) still croaks.
=cut | |||||
| 185 | ||||||
| 186 | sub emit { | |||||
| 187 | 1 | 1 | my $self = shift; | |||
| 188 | ||||||
| 189 | 1 | 6 | Carp::croak(ref($self), ': emit() is not implemented'); | |||
| 190 | } | |||||
| 191 | ||||||
| 192 - 208 | =head1 AUTHOR Nigel Horne C<njh@nigelhorne.com> =head1 SEE ALSO L<Log::Abstraction> =head1 COPYRIGHT AND LICENSE Copyright (C) 2025-2026 Nigel Horne Usage is subject to the GPL2 licence terms. If you use it, please let me know. =cut | |||||
| 209 | ||||||
| 210 | 1; | |||||