Context Variables

Historically, structlog only supported thread-local context binding. With the introduction of contextvars in Python 3.7, there is now a way of having a global context that is local to the current context and even works in concurrent code such as code using asyncio.

For that structlog provides a the structlog.contextvars module with a set of functions to bind variables to a context-local context. This context is safe to be used in asynchronous code.

The general flow is:

>>> from structlog.contextvars import (
...     bind_contextvars,
...     clear_contextvars,
...     merge_contextvars,
...     unbind_contextvars,
... )
>>> from structlog import configure
>>> configure(
...     processors=[
...         merge_contextvars,
...         structlog.processors.KeyValueRenderer(key_order=["event", "a"]),
...     ]
... )
>>> log = structlog.get_logger()
>>> # At the top of your request handler (or, ideally, some general
>>> # middleware), clear the threadlocal context and bind some common
>>> # values:
>>> clear_contextvars()
>>> bind_contextvars(a=1, b=2)
>>> # Then use loggers as per normal
>>> # (perhaps by using structlog.get_logger() to create them).
>>> log.msg("hello")
event='hello' a=1 b=2
>>> # Use unbind_contextvars to remove a variable from the context
>>> unbind_contextvars("b")
>>> log.msg("world")
event='world' a=1
>>> # And when we clear the threadlocal state again, it goes away.
>>> # a=None is printed due to the key_order argument passed to
>>> # KeyValueRenderer, but it is NOT present anymore.
>>> clear_contextvars()
>>> log.msg("hi there")
event='hi there' a=None