Giter Club home page Giter Club logo

loggingex's Introduction

Logging Extensions

https://travis-ci.com/open-things/loggingex.svg?branch=master https://img.shields.io/pypi/v/loggingex.svg?color=green

Implements a few extensions for the standard python logging library.

Currently, this project lacks documentation. Sorry about that.

Logging Context Filter

Logging Context Filter injects context variables into LogRecord objects as extra fields.

Here's a usage example:

import logging
import sys

from loggingex.context import LoggingContextFilter, context

log = logging.getLogger()


def process_lines(lines):
    for index, line in enumerate(lines):
        line = line.strip()
        with context(current_line=index + 1):
            log.debug("processing line: %s", line)
            if not line:
                log.error("empty line!")
                continue
            log.info("processed line: %s", line)


def process_files(filenames):
    log.debug("starting...")
    for filename in filenames:
        with context(current_file=filename):
            log.info("processing file: %s", filename)
            with open(filename, "r") as f:
                process_lines(f)
            log.info("processed file: %s", filename)
    log.debug("work is complete!")


if __name__ == "__main__":
    formatter = logging.Formatter(
        "%(current_file)s:%(current_line)s:%(levelname)s: %(message)s"
    )
    handler = logging.StreamHandler(stream=sys.stdout)
    handler.setFormatter(formatter)
    handler.setLevel(logging.DEBUG)
    handler.addFilter(LoggingContextFilter())  # it's that simple
    logging.basicConfig(handlers=[handler], level=logging.DEBUG)

    with context(current_file="-", current_line="-"):
        # The context above sets default value, so that the formatter does
        # not crash, when they are not defined.
        process_files(sys.argv[1:])

loggingex's People

Contributors

paulius-maruska avatar

Stargazers

rob avatar Lukas Šalkauskas avatar

Watchers

James Cloos avatar  avatar

loggingex's Issues

Examples fail on python 3.5

Python 3.5 did not support type annotation on local variables (only comment style annotations are supported), so running examples with python 3.5 fails right now. Oops.

Restructure the project

Everything in one file approach used currently is kind of hard to maintain, hard to find things.

Split the files into modules.

Task context for Celery

I'm not even sure if celery has any kind of "middleware" we could implement.

Look into this, I guess.

Support for dynamic values

Currently only static values are supported - whatever keyword argument values you pass to context, that's what you're going to get added to the log records. This is good for a lot of cases, but not perfect for some others. One inconvenience with this, is that you have to reset the context each time a value changes.

Implement a dynamic value feature, so that it was possible to do something like this:

from loggingex.context import context, value

GLOBAL_VALUE = "initial value"

def value_lookup():
    return GLOBAL_VALUE

with context(global_value=value(lookup=value_lookup)):
    # some code that logs stuff
    GLOBAL_VALUE = "different value"
    # some code that logs stuff
    pass

Bug in decorator implementation

I haven't tested this yet, but there should be bug right now with the decorator.

ContextChange can not be applied twice, so if it is used as a decorator on recursive function, or the function is being called by multiple threads - it should raise an exception the second time it's called (but before the first call was completed).

Possible solution - copy ContextChange instance and apply the copy of it, within the decorated internal function, to make the ContextChange local variable. That should do the trick.

Make decorator more useful

This is related to #4.

Currently, be because the values are all static - context as decorator is rather useless. Once #4 is implemented, add some special helpers for automatically adding information about the decorated function and what arguments were passed to it at runtime.

With this feature, something like this, should become possible:

from loggingex.context import context, argument

@context(foo_args=argument(arg=True))
def foo(*args):
    return sum(args)

@context(bar_name=argument("name"), bar_message=argument(arg=0, kwarg="message"))
def bar(message, *, name="default"):
    print("%s: %s" % (name, message))

Note: When used as context manager, these argument values would be ignored (or some default values would need to be returned for them).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.