NAME
Log::Dispatch
- Dispatching multi-source, multi-destination logging
SYNOPSIS
use Log::Dispatch;
use Log::Dispatch::Destination;
use Log::Dispatch::Source;
class DBDestination does Log::Ddispatch::Destination {
method report(Log::Dispatch::Msg:D $message) {
... # Implement writing log messages to a database table
}
}
class MyApp does Log::Dispatch::Source {
has Log::Dispatch:D $!logger .= new;
has Str:D $.log-file is required;
submethod TWEAK {
$!logger.add: Log::Dispatch::TTY, :max-level(LOG-LEVEL::DEBUG);
$!logger.add: 'File', file => $!log-file;
$!logger.add: DBDestination;
}
method do-an-action {
my Bool $success;
my $diagnostics;
self.log: :debug, "Trying an action...";
... # Do something
if $success {
self.log: "All done";
}
else {
self.log: :critical, "Something is wrong! Cause: ", $diagnostics;
}
}
}
DESCRIPTION
This module provide a means to have multiple log destinations withing single application with extra hassle but with easy support for concurrency.
Model
The model this module is based upon is built around a single dispatcher, which can be considered as a minimalistic wrapper around a Supplier
. The dispatcher accepts message objects from sources and dispatches them into destinations.
A source here is any instance of a class consuming Log::Dispatch::Source
role.
A destination is an instance of a class consuming Log::Dispatch::Destination
role. It represented an endpoint where messages are to be submitted to.
For example, one may have an application and wants to log its messages into a file and on the console. This is as simple as adding does Log::Dispatch::Source
to the declaration of our application class. And by having something like the following example anywhere in application code:
my $logger = Log::Dispatch.new;
$logger.add: 'File', :max-level(LOG-LEVEL::DEBUG), $log-file-name;
$logger.add: Log::Dispatch::TTY;
Note that the application would then log all messages into a log file, but only the essential ones to the console.
It worth to mention that each destination code is by default gets its own thread. For a source it is normally sufficient just to use log
method provided by Log::Dispatch::Source
role.
Processors
A processor is an end-point attached to the dispatcher. The module provides two kinds of processors: source and destination implemented, correspondingly, by Log::Dispatch::Source
and Log::Dispatch::Destination
roles.
Log::Dispatch::Processor
role is just an interface requiring attach
method to be implemented.
Destinations
Currently the module only provides two destination end-points: Log::Dispatch::TTY
and Log::Dispatch::File
. Syslog support may be added later.
The multi-destination concept with per-destination maximum log-level support implies that there is no way to optimize away some possibly unused calls to the method log
because any message, no matter what log-level it is assigned with, must be accepted and emitted into dispatcher's Supply
.
Log Levels
The number and names of log levels are taken from syslog standard exactly for the reason it is the most common logging standard existing around.
Levels are provided as LOG-LEVEL
enum values declared by Log::Dispatch::Types
module. Here is the list in the ascending order:
Non-polluting
This module tries to reduce namespace pollution to the absolute minimum. The only symbol exported is LOG-LEVEL
enumeration type for comparatively simple registration of a destination, as in the above example from the Model section.
METHODS
multi method add(Log::Dispatch::Processor:D $processor --
Nil)>
Adds an end-point object $processor
to the dispatcher.
Note that the attach
method of a custom processor is expected to return a Promise
which is to be kept only and only when the processor is ready. The meaning of being ready would then depend on the end-point type only.
multi method add(Log::Dispatch::Processor:U $processor, *%params)
This method creates an instance of the $processor
type using %params
as constructor parameters. The resulting instance is then gets registered with the dispatcher.
multi method add(
Str
:D $processor, *%params)
This method determines processor type based on the name provided in $processor
parameter and then instantiates it as described for the previous method candidate.
The following rules are used to resolve the type:
if it contains a colon pair :: then the name is used as-is
otherwise the name is prefixed with Log::Dispatch:: prefix
the resulting name is used to load a module of the same name with require
See the example in the Model section above.
shutdown
Can only be issued once on a dispatcher. Any subsequent call to the method is ignored.
Closes the dispatching supply by invoking method done
on the Supplier
.
The method can be invoked manually when absolutely necessary. But normally is it called inside an END
phaser to ensure that the logging capabilities are available up until the complete stop of the application.
Supply
Produces a new supply to be tapped upon
Emits Log::Dispatch::Msg
object into the dispatching supply.
SEE ALSO
Log::Dispatch::File
, Log::Dispatch::TTY
, Log::Dispatch::Types
, Log::Dispatch::Source
, Log::Dispatch::Destination
, Log::Dispatch::Msg
AUTHOR
Vadim Belman vrurg@cpan.org
LICENSE
Atristic 2.0