Author image Kent Fredric (PAUSE Custodial Account)


Log::Contextual::WarnLogger::Fancy - A modernish default lightweight logger


Log::Contextual::WarnLogger::Fancy is a re-implementation of Log::Contextual::WarnLogger with a few conveniences added.


Group Prefixes

  package My::Project::Package;

  my $logger = Log::Contextual::WarnLogger::Fancy->new(
    env_prefix       => 'MY_PROJECT_PACKAGE',   # control this level only
    group_env_prefix => 'MY_PROJECT',           # shared control for all components

This allows adding targeted granular debug tracing to selected packages within a project, or within all packages in a project, without having to resort to heavyweight loggers.

  MY_PROJECT_UPTO=debug           # debug the whole project
  MY_PROJECT_PACKAGE_UPTO=trace   # trace level on ::Package

Since 0.002000, group_env_prefix can be an ArrayRef ordered by "narrowest" to "broadest" inclusion.

  my $logger = Log::Contextual::WarnLogger::Fancy->new(
    env_prefix       => 'MY_PROJECT_PACKAGE',     # control this level only
    group_env_prefix => [ 'MY_PROJECT', 'MY' ],   # shared control for all components

Default upto level.

Because it seems like you'd want to make log_warn and log_fatal visible on the controlling terminal, its useful not to need to set MY_PROJECT_UPTO= in your environment just to get some useful output.

Instead, by default, ::Fancy assumes a default upto value of warn, and you can adjust this via

  my $logger = Log::Contextual::WarnLogger::Fancy->new(
    default_upto     => 'info',

And from then on, you can use log_warn { ... } with the same convenience as warn ... and know that your user will see it, and that if they bolt on some advanced logging system, that those warnings will flow nicely into it.

ANSI Colors

In order to make log output faster to visually scan, ANSI Colour codes are used to indicate various log levels.

  trace => plain
  debug => blue
  info  => white
  warn  => yellow
  error => magenta
  fatal => red

Padded Log Level Labels

Because some of us are anal as hell, the following just looks messy:

  [trace] message
  [info] message
  [fatal] message

So level labels are constantly padded to 5 characters.

  [trace] message
  [info ] message  # Aaaaah. (~˘▾˜)/
  [fatal] message

Per Logger Origin Labels

Because the recommended usage of ::WarnLogger::Fancy results in creating a logger instance per package, each logger instance can be customized with a prefix to give more context when used in bulk.

  my $logger = Log::Contextual::WarnLogger::Fancy->new(
    label         => __PACKAGE__
    label_length  => 16,


  [trace    Some::Package] A trace message
  [info    Other::Package] An info message
  [warn     Some::Package] A warning
  [fatal My::Oth¦:Package] A fatal warning

Additionally, Origin Labels are constant-sized where specified, defaulting to 16 characters long, either left-padded to meet that length, or infix condensed to 16 characters.

Currently, the infix character of choice is ¦ ( chr(166) U+00A6 BROKEN BAR ) which may be superficially similar to | ( chr(124) U+007C VERTICAL LINE )

Chosen as such because its the only character I could find that

  • Is unlikely to be in common usage

  • Will be visually distinct

  • Will be likely to be understood in its context without elaborate explanation

  • Will likely render as intended on all output terminals

  • Won't require magic with turning on UTF8 Support

¦ is the same in both UTF-8, ISO-8859-1 and Windows-1252, with only CP437 being an outlier with FEMININE ORDINAL INDICATOR ( Equiv of U+00AA )

I'd have ideally used ( U+2026 HORIZONTAL ELLIPSIS ), but getting UTF-8 magic is filled with challenges.

( It however still might be implemented this way in future )


Custom Logging Levels

::WarnLogger has one feature that adds a bit of complexity, and there's additional implementation confusion for me in mapping/understanding the existing code.

Specifically with regards to AUTOLOAD and how it implements custom logging levels differently from stock levels.

The plumbing is in place to implement it in a similar way, but its not clear to me if this feature is a "Good idea" or not at this time.

So the glue is in place for people who are sure they need it, but its intentionally obscure to serve as a disincentive. ( Please file a bug/contact me somehow if you are sure this is a good idea, preferably with explanations on how you plan on using it with example code )


Kent Fredric


This software is copyright (c) 2016 by Kent Fredric

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