The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Log::Any::Adapter::Daemontools::Config - Dynamic configuration settings used by Daemontools logging adapters

VERSION

version 0.102

SYNOPSIS

  # As many config objects as you need
  my $cfg= Log::Any::Adapter::Daemontools->new_config;
  my $cfg2= Log::Any::Adapter::daemontools->new_config;
  
  # Assign them to logging categories
  Log::Any::Adapter->set({ category => qr/^Foo::Bar/ }, 'Daemontools', config => $cfg );
  Log::Any::Adapter->set({ category => qr/^Baz/ },      'Daemontools', config => $cfg2 );
  
  # Update them later and existing adapters use the new settings
  $cfg->log_level('info');
  $cfg2->log_level('debug');

DESCRIPTION

When you use Log::Any::Adapter::Daemontools as the adapter for Log::Any, it creates one adapter per logging category. If you set the log level as an attribute of the adapter, each adapter will have a copy and there is no practical way to reach out and change them. (other than resetting the adapters with a new configuration, which is a slightly expensive operation, and awkward) So, to make dynamic configuration changes easy, adapters reference these Config objects which hold the shared state.

There is one default Config instance (global_config) but you can create as many as you want in order to handle different categories separately.

ATTRIBUTES

log_level

  $config->log_level            # returns level name
  $config->log_level( 'info' ); # 'info'
  $config->log_level( 99 );     # 'trace' (clamped to max)
  $config->log_level( 3 );      # 'error'
  $config->log_level( '+= 1' ); # 'warning'
  $config->log_level( '-= 9' ); # 'none' (clamped to min)

Get or set the current log level. Can be assigned with either a name or a number, or "+= N" syntax. (but use "log_level_adjust" for that) Returns the level name.

Accepts any of the names and aliases defined in Log::Adapter::Any::Util but also the string 'none' (and value -1) to completely stop all logging, or the string all (alias for trace) to enable all logging.

log_level_min

  # Our app should never have 'critical' squelched no matter how many '-q'
  # the user gives us
  $config->log_level_min('fatal');

Get or set the minimum allowed log level. Log levels below the minimum are silently clamped. Can be assigned either a name or number, or "+= N" syntax. Returns the level name.

log_level_max

Get or set the maximum allowed log level. Log levels above the maximum are silently clamped. Can be assigned either a name or number, or "+= N" syntax. Returns the level name.

output

This is the handle (or coderef) log messages are written to. (but if you set "writer" to a custom coderef, this attribute is ignored completely)

If it is a handle (either a GLOB ref or class which can('print')) we call its print method. If it is a coderef, we pass the same arguments that would be given to print.

If a message from Log::Any contains newlines, they are broken into separate strings (but still ending with newline) and passed as a list, so the print method or coderef should print its entire argument list.

The default is \*STDERR.

format

  $cfg->format( '$level eq "trace"? "$level: $_ at $file_brief line $line" : "$level_prefix$_"' )

This attrbute determines how messages are formatted into text lines. (But if you set "writer" to a custom coderef, this attribute is ignored completely.)

It is a string of perl code (or a coderef) which executes within the following context:

  $output->print( map { eval $format } split /\n/, $message );

The following variables and functions are available for your string of code:

$_

The line of message text

$category

The name of the Log::Any category the message came from

$level

The name of the log level

$level_prefix

The default prefix behavior ("$level: " for all levels except info, which is an empty string)

numeric_level(...)

The utility method from Log::Any::Adapter::Util, useful for comparing levels.

$file

The full filename from caller()

$file_brief

The filename from caller() minus the library path (best guess, no guarantees)

$line

The line number from caller()

$package

The package name from caller()

If you use a coderef, you get $_ (a single line of the message), and arguments of ($adapter, $level). It should return a string ending with newline.

  sub { my ($adapter, $level)= @_; return "$_\n"; }

The default value is '"$level_prefix$_\n"'

writer

If specified, this coderef overrides the routine that would have been built from "output" and "format".

Its arguments are:

  sub { my ($adapter, $level, $message)= @_; ... };

where $level is the level name, and adapter is an instance of Log::Any::Adapter::Daemontools. (and the adapter attributes you are probably most interested in are category and config).

METHODS

new

Constructor; accepts any of the attributes as arguments, as a hash or hashref.

init

  $config->init( argv => 1, level => 'warn', format => '"$level: $_ ($category)"' )

Different from a constructor, this method takes a hashref of short aliases and notations and calls various methods that might have effects outside of this object. The primary purpose is to provide convenient initialization of the global logging configuration.

DO NOT pass un-sanitized user input to init, because the format attribute is processed as perl code.

The following are provided:

env, or process_env
  env => $name_or_args

Convenient passthrough to "process_env" method.

If env is a hashref, it is passed directly. If it is a scalar, it is interpreted as a pre-defined "profile" of arguments.

Profiles:

1
  { debug => 'DEBUG' }
argv, or process_argv
  argv => $name_or_args

Convenient passthrough to "process_argv".

If argv is a hashref, it is passed directly. If it is a scalar, it is interpreted as a pre-defined "profile" of arguments.

Profiles:

1
'gnu'
  {
    bundle  => 1,
    verbose => qr/^(--verbose|-v)$/,
    quiet   => qr/^(--quiet|-q)$/,
    stop    => '--'
  }
'consume'
  {
    bundle  => 1,
    verbose => [ '--verbose', '-v' ],
    quiet   => [ '--quiet', '-q' ],
    stop    => '--',
    remove  => 1,
  }
signals, handle_signals, or install_signal_handlers
  signals => [ $v, $q ],
  signals => { verbose => $v, quiet => $q },

Convenient passthrough to "install_signal_handlers".

If signals is an arrayref of length 2, they are used as the verbose and quiet parameters, respectively. If it is a hashref, it is passed directly.

level, or log_level

Sets "log_level"

min, level_min, or log_level_min

Sets "log_level_min"

max, level_max, or log_level_max

Sets "log_level_max"

format

Sets "format"

out, or output

Sets "output"

writer

Sets "writer"

log_level_num

The current log level, returned as a number. This is NOT a writeable attribute, just a shortcut for numeric_level( $config->log_level ).

log_level_min_num

The current minimum, returned as a number. This is NOT a writeable attribute, just a shortcut for numeric_level( $config->log_level_min ).

log_level_max_num

The current maximum, returned as a number. This is NOT a writeable attribute, just a shortcut for numeric_level( $config->log_level_max ).

log_level_adjust

  $config->log_level_adjust(-2);

Add or subtract a number from the current log level. The value is clamped to the current minimum and maximum. (positive increases logging verbosity, and negative decreases it)

process_env

  $config->process_env( debug => $ENV_VAR_NAME );
  # and/or
  $config->process_env( log_level => $ENV_VAR_NAME );

Request that this package check for the named variable(s), and if set, interpret it either as a debug level or a log level, and then set "log_level".

A log_level environment variable is applied directly to the "log_level" attribute.

A "debug level" environment variable refers to the typical Unix practice of a variable named DEBUG where 0 is disabled, 1 is enabled, and larger numbers increase the verbosity. This results in the following mapping: 2=trace, 1=debug, 0=info, -1=notice and so on. Larger numbers are clamped to 'trace'.

process_argv

  $self->process_argv( bundle => ..., verbose => ..., quiet => ..., stop => ..., remove => ... )

Scans (and optionally modifies) @ARGV using method "parse_log_level_opts", with the supplied options, and updates the log level accordingly.

parse_log_level_opts

  $level_offset= $class->parse_log_level_opts(
    array   => $arrayref, # required
    verbose => $strings_or_regexes,
    quiet   => $strings_or_regexes,
    stop    => $strings_or_regexes,
    bundle  => $bool, # defaults to false
    remove  => $bool, # defaults to false
  );

Scans the elements of 'array' looking for patterns listed in 'verbose', 'quiet', or 'stop'. Each match of a pattern in 'quiet' subtracts one from the return value, and each match of a pattern in 'verbose' adds one. Stops iterating the array if any pattern in 'stop' matches.

If 'bundle' is true, then this routine will also split apart "bundled options", so for example

  --foo -wbmvrcd --bar

is processed as if it were

  --foo -w -b -m -v -r -c -d --bar

If 'remove' is true, then this routine will alter the array to remove matching elements for 'quiet' and 'verbose' patterns. It can also remove the bundled arguments if bundling is enabled:

  @array= ( '--foo', '-qvvqlkj', '--verbose' );
  my $n= parse_log_level_opts(
    array => \@array,
    quiet => [ '-q', '--quiet' ],
    verbose => [ '-v', '--verbose' ],
    bundle => 1,
    remove => 1
  );
  # $n = -1
  # @array = ( '--foo', '-lkj' );

install_signal_handlers

  $config->handle_signals( verbose => $verbose_sig, quiet => $quiet_sig );

Install signal handlers (probably USR1, USR2) which increase or decrease the log level.

Basically:

  $SIG{ $verbose_sig }= sub { $config->log_level_adjust(1); }
    if $verbose_sig;
  
  $SIG{ $quiet_sig   }= sub { $config->log_level_adjust(-1); }
    if $quiet_sig;

compiled_writer

This returns the "writer" attribute if it is defined, or the compiled result of "output" and "format" otherwise. If it builds a writer from "output", it will also enable autoflush on that file handle.

AUTHOR

Michael Conrad <mike@nrdvana.net>

COPYRIGHT AND LICENSE

This software is copyright (c) 2019 by Michael Conrad.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.