stacklogger — stack-aware logging extension

stacklogger provides a stack-aware extension of the standard library’s logging facility. With stacklogger, you can add useful information to your log messages without changing any library code, adding extra dependencies for your users to install or decreasing performance.

Installing stacklogger

You can install the latest stable version of stacklogger using pip:

$ pip install stacklogger

Public repositories for the project are hosted at github and bitbucket, so you can use either git or Mercurial to get a copy of the project’s code and history:

$ hg clone http://bitbucket.org/wcmaier/stacklogger
$ git clone git://github.com/wcmaier/stacklogger.git

If you notice a problem with stacklogger, please report it using the github issue tracker (or, if you have a fix, send a pull request).

A note about versions

stacklogger is developed along two branches. The first, ‘default’ (or ‘master’ in git) contains new features and possible bugs – this branch is the active development branch. The second, ‘stable’, contains releases both major and minor as well as bugfixes. If you’d like to help improve stacklogger, take a look at default/master. Otherwise, stick with stable.

Basic Usage

stacklogger will fit easily into your project if you’re already using the standard logging module. If not, take a look at the provided tutorials. Once your project is logging correctly, simply replace the usual Logger class with StackLogger:

import logging

from stacklogger import StackLogger

logging.setLoggerClass(StackLogger)
logging.basicConfig(
    level=logging.DEBUG,
    format="%(funcName)s %(message)s",
)

You won’t see any difference unless you configure the Formatter to include the ‘funcName’ in log messages. StackLogger inspects the calling stack to discover useful information that the standard logger doesn’t include when it emits log messages. For example, StackLogger will figure out the class of a method that calls one of the logging methods. Given the above logging configuration, consider the following example:

class Eggs(object):

    def scramble(self):
        log = logging.getLogger("breakfast")
        log.debug("scrambling")

eggs = Eggs()
eggs.scramble()

The above snippet should produce output like the following:

Foo.scramble scrambling

Enabling StackLogger shouldn’t slow your application or library down any more than using the default Logger implementation. Simple tests show essentially no difference in performance between the two implementations; in fact, Logger already looks at the interpreter stack each time it’s called. StackLogger is a bit smarter about how it figures out where a calling function was defined, but it doesn’t cost much more than regular logging.

Caveat

StackLogger tries pretty hard to figure out where a caller of a logging method was defined. It is able to provide much more information than the standard library Logger, but there are some things that even StackLogger can’t (reasonably) figure out:

  • lambdas will always appear as <lambda>;
  • static methods will only show the name of the method – it’s not possible to discover the name of the class in which the method was defined.

Other somewhat exotic calling contexts — like classmethods — are supported. See the test suite for more examples.

API

stacklogger.srcfile(fname)

Sanitize a Python module’s filename.

This function produces filenames similar to logging._srcfile and those returned by inspect.getsourcefile().

stacklogger.callingframe(frame)

Return info about the first non-logging related frame from frame‘s stack.

stacklogger.framefunc(frame)

Return a string representation of the code object at frame.

frame should be a Python interpreter stack frame with a current code object (or a sequence with such a frame as its first element). framefunc() will try to determine where the calling function was defined; if the function was defined in a class (as with properties, methods and classmethods), the class’ name will be prepended to the function name (like class.function).

class stacklogger.StackLogger(name, level=0)

Bases: logging.Logger

A logging channel.

A StackLogger inspects the calling context of a logging.LogRecord, adding useful information like the class where a method was defined to the standard logging.Formatter ‘funcName’ attribute.

findCaller()

Return the filename, line number and function name of the caller’s frame.

Table Of Contents

This Page