Source code for structlog.dev

# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the MIT License.  See the LICENSE file in the root of this
# repository for complete details.

"""
Helpers that aim to make development with ``structlog`` more pleasant.
"""

from __future__ import absolute_import, division, print_function

from six import StringIO

try:
    import colorama
except ImportError:
    colorama = None

__all__ = [
    "ConsoleRenderer",
]


_MISSING = (
    "{who} requires the {package} package installed.  "
    "If you want to use the helpers from structlog.dev, it is strongly "
    "recommended to install structlog using `pip install structlog[dev]`."
)
_EVENT_WIDTH = 30  # pad the event name to so many characters


def _pad(s, l):
    """
    Pads *s* to length *l*.
    """
    missing = l - len(s)
    return s + " " * (missing if missing > 0 else 0)


if colorama is not None:
    RESET_ALL = colorama.Style.RESET_ALL
    BRIGHT = colorama.Style.BRIGHT
    DIM = colorama.Style.DIM
    RED = colorama.Fore.RED
    BLUE = colorama.Fore.BLUE
    CYAN = colorama.Fore.CYAN
    MAGENTA = colorama.Fore.MAGENTA
    YELLOW = colorama.Fore.YELLOW
    GREEN = colorama.Fore.GREEN


[docs]class ConsoleRenderer(object): """ Render `event_dict` nicely aligned, in colors, and ordered. :param int pad_event: Pad the event to this many characters. Requires the colorama_ package. .. _colorama: https://pypi.python.org/pypi/colorama/ .. versionadded:: 16.0.0 """ def __init__(self, pad_event=_EVENT_WIDTH): if colorama is None: raise SystemError( _MISSING.format( who=self.__class__.__name__, package="colorama" ) ) colorama.init() self._pad_event = pad_event self._level_to_color = { "critical": RED, "exception": RED, "error": RED, "warn": YELLOW, "warning": YELLOW, "info": GREEN, "debug": GREEN, "notset": colorama.Back.RED, } for key in self._level_to_color.keys(): self._level_to_color[key] += BRIGHT self._longest_level = len(max( self._level_to_color.keys(), key=lambda e: len(e) )) def __call__(self, _, __, event_dict): sio = StringIO() ts = event_dict.pop("timestamp", None) if ts is not None: sio.write( # can be a number if timestamp is UNIXy DIM + str(ts) + RESET_ALL + " " ) level = event_dict.pop("level", None) if level is not None: sio.write( "[" + self._level_to_color[level] + _pad(level, self._longest_level) + RESET_ALL + "] " ) sio.write( BRIGHT + _pad(event_dict.pop("event"), self._pad_event) + RESET_ALL + " " ) logger_name = event_dict.pop("logger", None) if logger_name is not None: sio.write( "[" + BLUE + BRIGHT + logger_name + RESET_ALL + "] " ) stack = event_dict.pop("stack", None) exc = event_dict.pop("exception", None) sio.write( " ".join( CYAN + key + RESET_ALL + "=" + MAGENTA + repr(event_dict[key]) + RESET_ALL for key in sorted(event_dict.keys()) ) ) if stack is not None: sio.write("\n" + stack) if exc is not None: sio.write("\n\n" + "=" * 79 + "\n") if exc is not None: sio.write("\n" + exc) return sio.getvalue()