Log::ger::Manual::Internals - Log::ger internals
version 0.025.000
When an importer package does this:
use Log::ger;
Basically all Log::ger does is construct logging routines and install them to importer's package (target), e.g. log_warn, log_debug, log_is_debug and so on. Log::ger also records the target name. When a reinit is requested (e.g. due to a change of log level or outputs), Log::ger will again construct logging routines and install them to each target, replacing the old ones.
log_warn
log_debug
log_is_debug
In addition to installing routines to a package, Log::ger can also target a hash or an object (which is basically the same as installing to a package, but the routines will expect to be called as object methods instead of plain subroutines, i.e. they expect the first argument to be the object).
A routine that takes arguments supplied by the user to the logger routine (e.g. log_warn("blah %s", $args, ...) and converts it to the message (usually string) that is sent to the output (or the layouter, if there is one).
log_warn("blah %s", $args, ...)
A routine that takes the formatted message (usually a string) and converts it to the final message string that is sent to output.
A Perl module that supplies hooks.
A package that will be installed with logging routines. Aside from package, Log:;ger can also install routines to a hash or an object. Installing to an object is essentially the same as installing to a package: Log::ger will pick a "random" package for the object and install the routines there.
The process of constructing logger routines and installing them to targets. See "INIT" for more details about the process.
Hooks are how Log::ger provides its flexibility. At various times (phases), Log::ger will turn to running hooks to get some behavior or result. For example when wanting to construct a logging routine or formatting routine or before/after installing logging routines. Plugins, which are modules in the Log::ger::{Plugin,Output,Format,Layout,...} namespaces, can supply these hooks.
Hooks are stored in the %Global_Hooks variable, where the key is phase name and the value an array of hook records. There are also %Per_Package_Hooks, %Per_Object_Hooks, and %Per_Hash_Hooks to store per-target hooks that will only be used for specific targets. This way, the logging routines for each package and object/hash can be customized.
%Global_Hooks
%Per_Package_Hooks
%Per_Object_Hooks
%Per_Hash_Hooks
Each hook record is in the form of:
[$key, $prio, $coderef]
where $key is (plugin) package name, $prio is a number between 0-100 (the lower the number, the higher the priority and the earlier it is run), $coderef is the actual hook routine. A plugin is supposed to put only at most one hook per phase.
$key
$prio
$coderef
A hook routine is passed a hash argument and is expected to return an array:
[$result, $flow_control, ...]
By default each hook will be executed in order of its priority. $flow_control can be set to 1 by a hook to stop immediately after this hook instead of continuing to the next. Some phases will nevertheless stop after the first hook that returns non-undef $result. A hook that returns undef is effectively declining and causing Log::ger to move to the next hook in the chain.
$flow_control
$result
Some phases might return extra elements.
Aguments received by hook: target (str, can be package if installing to a package, or hash or object), target_arg (str, when target is package, will be the package name; when target is hash will be the hash; when target is object will be the object), init_args (hash, arguments passed to Log::ger when importing, e.g. {category => 'My::Package'}; it also serves as a per-target stash which survives reinit, by convention you can put stuffs here under keys that start with _). In some phases, hook will receive more arguments (see phase documentation below).
target
package
hash
object
target_arg
init_args
{category => 'My::Package'}
_
Available phases:
create_formatter
Used to construct formatter routine, which will be called with arguments from the user when she calls the logging routines.
It should return:
[\&formatter, $flow_control, $formatter_name]
$formatter_name is optional and defaults to default, which is the default formatter used for all logging routines.
$formatter_name
default
create_layouter
Used to construct layouter routine, which will be called with arguments ($fmsg, \%init_args, $lnum, $lname) where $fmsg is formatted message from the formatter, %init_args are arguments given to Log::ger->get_logger or to Log::ger's import(), $lnum is numeric level, $lname is string level.
($fmsg, \%init_args, $lnum, $lname)
$fmsg
%init_args
Log::ger->get_logger
$lnum
$lname
create_routine_names
Used to construct routine names. Hook must return this (all keys are optional):
[{ log_subs => [ [NAME, STR_LEVEL, FMT_NAME], ... ], log_methods => [ [NAME, STR_LEVEL, FMT_NAME], ... ], is_subs => [ [NAME, STR_LEVEL, FMT_NAME], ... ], is_methods => [ [NAME, STR_LEVEL, FMT_NAME], ... ], logml_subs => [ [NAME, undef , FMT_NAME], ... ], logml_methods => [ [NAME, undef , FMT_NAME], ... ], }, ...]
Where log_subs and log_methods are names of per-level log routines, is_subs an is_methods are names of per-level level detection routines, logml_subs and logml_methods are names of multiple-level log routines.
log_subs
log_methods
is_subs
is_methods
logml_subs
logml_methods
FMT_NAME is optional and defaults to default (the default formatter routine).
FMT_NAME
create_log_routine
Used to create per-level "log_level" routines which will be called with (\%init_args, $msg) arguments. Called for each routine specified in the log_subs (or log_methods) in the routine names (see documentation on create_routine_names phase). Extra arguments received by hook: name (routine name), level (numeric level), str_level.
(\%init_args, $msg)
name
level
str_level
create_is_routine
Used to create per-level "log_is_level" routines. Called for each routine specified in the is_subs (or is_methods) in the routine names (see documentation on create_routine_names phase). Extra Arguments received by hooks: name (routine name), level (numeric level), str_level.
create_logml_routine
Used to create multiple-level "log" routines which will be called with (\%init_args, $level, $msg) arguments. Called for each routine specified in the logml_subs (or logml_methods) in the routine names (see documentation on create_routine_names phase). Extra arguments received by hooks: name (routine name).
(\%init_args, $level, $msg)
before_install_routines
Extra arguments received by hooks: routines (array of routines to install), formatters (hashref of formatter routines, if any), layouter (layouter routine, if any).
routines
formatters
layouter
routine is in the form of:
routine
[ [$coderef, $name, $numlevel, $type], ... ]
Where $type is either log_sub, log_method, logml_sub, logml_method, is_sub, is_method.
$type
log_sub
log_method
logml_sub
logml_method
is_sub
is_method
after_install_routines
Extra arguments received by hooks: routines.
Aside from the global hooks, there are also per-target hooks, which are stored in %Per_Package_Hooks, %Per_Hash_Hooks, %Per_Object_Hooks.
This section describes what init_target(), which is the routine used to initialize a target, does.
init_target()
First, hooks in the create_formatter phase are run. This will collect one or more formatters. In the most common case, only the default formatter will be constructed. In some cases, like Log::ger::Like::LogAny, we want to use different formatters for method like warn and debug (arguments simply joined by space) and for methods like warnf and debugf (sprintf-style with data structure dumping, the default formatter used by Log::ger).
warn
debug
warnf
debugf
Next, hooks in the create_layouter phase are run. This will create a layouter (multiple layouters might be supported in the future, but for now we only use one layouter per target).
Next, hooks in the create_routine_names phase are run. This will produce a list of subroutine/method names to create, along with what formatter to use for each (the default is default). Plugins that want to mimic other interfaces like Log::ger::Like::LogAny or Log::ger::Like::Log4perl will want to add their hook here to provide names other than Log::ger's default. For example, Log4perl has uppercase subroutine names like WARN or DEBUG.
WARN
DEBUG
There are two types of routines that are created, logging routines (like log_warn, log_debug) and level detection routines, also called the "is" routines (like log_is_warn, log_is_debug). Logging routines in turn can be reguler, per-level routines or multilevel routines that accept numeric level as the first argument.
log_is_warn
Next, the logger routines are created by running the create_log_routine and create_logml_routine hooks, for each log level. The code from the hooks (usually from output plugins) are then combined with the formatter and layouter to form the final routine ready to be installed.
Likewise, the log level detection routines are created by running the create_is_routine hooks for each log level.
Before installing the routines, we give a chance to plugins to do stuffs in the before_install_routines phase. Some plugins use this phase to, e.g. fixup prototypes.
After installing the routines, we likewise give a chance to plugins to do stuffs in the after_install_routines phase. Some plugins like Log::ger::Plugin::OptAway this phase to actually replace the routines that are not needed with a no-op.
Log::ger can install logger routines to a package, or an object (which is similar to installing to a package), or a hash (usually for testing). The routines that are installed into package target are of type *_subs. The routines that are installed into object target package are of type *_methods. The routines that are installed into hash target are of type *_methods but they will expect to be called as a normal subroutine (i.e. no object reference as first $self argument).
*_subs
*_methods
$self
perlancar <perlancar@cpan.org>
This software is copyright (c) 2018, 2017 by perlancar@cpan.org.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
To install Log::ger::Manual, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Log::ger::Manual
CPAN shell
perl -MCPAN -e shell install Log::ger::Manual
For more information on module installation, please visit the detailed CPAN module installation guide.