Log::Log4perl::Layout::PatternLayout::Stacktrace - implement %S


 use Log::Log4perl::Layout::PatternLayout::Stacktrace;


 use Log::Log4perl::Layout::PatternLayout::Stacktrace -char => $letter;


 use Log::Log4perl::Layout::PatternLayout::Stacktrace ();
 Log::Log4perl::Layout::PatternLayout::Stacktrace::register_cspec $char


This module is a subclass of Stacktrace::Configurable. It implements a slightly different default format and, mainly, registers the letter S (or alternatively any letter you specify as value of the char or -char options to the import method) as custom cspec with Log::Log4perl::Layout::PatternLayout.

If the module is required or used without calling import, e.g. use Log::Log4perl::Layout::PatternLayout::Stacktrace (), no custom cspec is registered. You can do it later by calling

 Log::Log4perl::Layout::PatternLayout::Stacktrace::register_cspec $char

How to generate a stack trace?

The simplest way is to include %S (or whatever letter you registered) in your layout specification. This then uses the default stack trace format.

Alternatively, you can specify your own stack trace format putting it in curlies after the %S like %S{[%*n] %f (%l)}. Note, the curlies parser in Log::Log4perl::Layout::PatternLayout is not smart enough to match nesting pairs of braces. It simply matches up to the next closing brace character.

To overcome that you may put your actual format in an environment variable and use it in the curlies: %S{env=ENVVAR}.

The default format

The default format is designed to be used in a layout pattern like this


That is, first something is printed. In this case it is the actual message, %M. Then comes the stack trace (%S) followed by a newline.

The resulting output will then look like this:

 The message
     ==== START STACK TRACE ===
     [1] at t/100-l4p.t line 65
             __ANON__ (Log::Log4perl::Logger=HASH(0x17c36e0), "The message")
     [2] at t/100-l4p.t line 20
             l1 ()
     === END STACK TRACE ===

You may notice there is a newline after the message. That's part of the default format.

The default format also allows you to silence a stack trace completely. It checks the environment variable L4P_STACKTRACE. If set to off, no or 0, %S evaluates to the empty string.

There is another environment variable, L4P_STACKTRACE_A. It controls what to do with complex data types like arrayrefs or objects.

For example, if you specify L4P_STACKTRACE_A=dump=CODE,dump=ARRAY,deparse,multiline=12 you might see this output:

 The message
     ==== START STACK TRACE ===
     [1] at t/100-l4p.t line 65
             __ANON__ (
                 "The message"
     [2] at t/100-l4p.t line 20
             l1 (
                 sub {    use warnings;    use strict 'refs';    2;},
     === END STACK TRACE ===

Look at frame #2. It does not say CODE(...) as you might expect for a subroutine parameter. Instead it deparses the function. Also, if you look at the 2nd parameter which is an arrayref. It is dumped with Data::Dumper.

The last environment variable adhered to by the default format is L4P_STACKTRACE_MAX. It limits the number of frames printed. If for instance set to 5, then only the topmost 5 frames are printed.

See StackTrace::Configurable for more information.

To be precise, the default format is this:

 '%[nr=1,n]b%[nr=1,s=    ==== START STACK TRACE ===]b%[nr=1,n]b'.
 '%4b[%*n] at %f line %l%[n]b'.
 '%12b%[skip_package]s %[env=L4P_STACKTRACE_A]a'.
 '%[nr!L4P_STACKTRACE_MAX,c=%n    ... %C frames cut off]b'.
 '%[nr=$,n]b%[nr=$,s=    === END STACK TRACE ===]b'

Overloaded "", tied variables etc.

Stack traces are often used in combination with exceptions. Further, in Perl operators can be overloaded. This module uses the "" operator to stringify variables. What happens if this operator is overloaded and the overloading function itself dies triggering a new stack trace? In that case we see infinite recursion. You might argue that stringifying code that dies is a bug by itself and I agree. Though, it does not hurt to forbid this kind of recursion.

So, if you see in your expected stacktrace somewhere the string (recursion detected), that's the reason. A recursing stacktrace has been disrupted.


Torsten Förtsch <>


Copyright 2014- Torsten Förtsch


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