Lggr

Simplified python logging

View the Project on GitHub peterldowns/lggr

Lggr - easy python logging

Have you ever tried to do anything with the python logging module?

I have. I didn't like it at all. The API was very confusing. Instead of dealing with all of its intricacies, I decided to roll my own.

I've been inspired by dabeaz's presentation on coroutines and Kenneth Reitz's presentation on better python libraries.

How does it work?

Create a logger object.

import lggr
d = lggr.Lggr()

Add a coroutine (or any function or object with send and close methods) to consume log messages. lggr includes some default ones:

You can choose to add different coroutines to different levels of logging. Maybe you want to receive emails for all of your critical messages, but only print to stderr for everything else.

d.add(d.ALL, lggr.Printer()) # d.ALL is a shortcut to add a coroutine to all levels
d.add(d.CRITICAL, lggr.Emailer("peterldowns@gmail.com"))

Do some logging.

d.info("Hello, world!")
d.warning("Something seems to have gone {desc}", {"desc":"amuck!"})
d.critical("Someone {} us {} the {}!", "set", "up", "bomb")
d.close() # stop logging

What kind of information can I log?

Anything you want. Log messages are created using str.format, so you can really create anything you want. The default format includes access to the following variables:

If you want to use any extra information, simply pass in a dict with the named argument extra:

>>> d.config['defaultfmt'] = '{name} sez: {logmessage}'
>>> d.info("This is the {}", "message", extra={"name":"Peter"})
Peter sez: This is the message

A stack_info example

stack_info is cool because it lets you do really helpful tracebacks to where exactly your logging function is being called. For example, with some logger d, I could run the following:

d.config['defaultfmt'] = '{asctime} ({levelname}) {logmessage}\nIn {pathname}, line {lineno}:\n{codecontext}'

def outer(a):
    def inner(b):
        def final(c):
            d.critical("Easy as {}, {}, {}!", a, b, c)
        return final
    return inner

outer(1)(2)(3)

output:

Mon Apr  2 23:31:22 2012 (CRITICAL) Easy as a, b, c!
In test.py, line 29:
d.config['defaultfmt'] = '{asctime} ({levelname}) {logmessage}\nIn {pathname}, line {lineno}:\n{codecontext}'

def outer(a):
    def inner(b):
        def final(c):
>           d.critical("Easy as {}, {}, {}!", a, b, c)
        return final
    return inner

outer(1)(2)(3)

What's next?

I'm still working on text-sending and IRC/IM-writing log functions - maybe one of you could help?

Who did this?

Peter Downs.
peterldowns@gmail.com
@peterldowns