Details from http://structlog.rtfd.org
Additional motivation from kartar and mipsytipsy
A single log message is not as important than many in aggregate. We need machines to aggregate data from many logs/messages. Machines need structured data, or they have to do expensive string parsing. Composing structured logs isn't more difficult than flat messages for humans. The data we log is structured to begin with. Why flatten it?
# Import it
>>> from structlog import get_logger
>>> log = get_logger()
# `structlog.get_logger is a drop-in replacement for stdlib's `logging.getLogger`
# You can log something like usual, including arbitrary metadata as kwargs. Defaults are sane.
>>> log.warn("trouble's a brewin'", when='soon')
2017-04-24 09:30.33 trouble's a brewin' when=soon
# You can log things that aren't strings.
>>> log.debug('logging things that are not strings', x={'flat': 'is better than nested'}, y=range(3))
2017-04-24 11:48.31 logging things that are not strings current_status=monkeying around x={'flat': 'is better than nested'} y=[0, 1, 2]
# All kwargs are formatted using structlog.processors.KeyValueRenderer, which uses `repr`.
# You can choose to always log something in a given context.
>>> log = log.bind(current_status='monkeying around')
>>> log.info('Normal things happening here.')
2017-04-24 09:32.55 Normal things happening here. current_status=monkeying around
# Note above that `log.bind` does not mutate the _current_ log object. It returns a BoundLogger.
It isn't an either-or proposal. The existing log statements will continue to work in concert with structlog. Python's builtin logging
module is actually quite excellent, and most projects have a bunch of log statements already written using it. The main reason to favor structlog is the open-schema structured logging and bindings.