bind_logger¶
-
async
safir.middleware.
bind_logger
(request: Request, handler: Handler) → StreamResponse¶ Bind request metadata to the context-local structlog logger.
This is an aiohttp.web middleware.
- Parameters
request – The aiohttp.web request.
handler – The application’s request handler.
- Returns
The response with the
logger
key attached to it. This structlog-based logger is bound with context about the request. See Notes for details.- Return type
response
Notes
This middleware initializes a new response-local structlog logger with context bound to it. All logging calls within the context of a response include this context. This makes it easy to search, filter, and aggregate logs for a specififc request. For background, see http://www.structlog.org/en/stable/getting-started.html#building-a-context
The context fields are:
request_id
A random UUID4 string that uniquely identifies the request.
path
The path of the request.
method
The http method of the request.
Logger name
By default, the logger is named for the
logger_name
attribute of the configuration object (app["safir/config"]
). If that configuration is not set, the logger name falls back to__name__
.Examples
Setting up the middleware
Use the
safir.middleware.setup_middleware
function to set this up:app = web.Application() app["safir/config"] = Configuration() app.middlewares.append(bind_logger)
Remember that
bind_logger
names the logger according to thelogger_name
attribute of the configuration,app["safir/config"]
.Using the logger
Within a handler, you can access the logger directly from the
logger
key of the request object:@routes.get("/") async def get_index(request): logger = request["logger"] logger.info("Logged message", somekey="somevalue")
If the request object is not available, you can still get the logger through the
safir.logging.get_response_logger
function:from safir.logging import get_response_logger logger = get_response_logger() logger.info("My message", somekey="somevalue")
Under the hood, you can also get this logger from the
safir.logging.response_logger
context variable. For example:from safir.logging import response_logger logger = response_logger.get() logger.info("My message", somekey="somevalue")
The
response_logger.get()
syntax is becauseresponse_logger
is acontextvars.ContextVar
. AContextVar
is isolated to each asyncio Task, which makes it great for storing context specific to each reponse.The
request['logger']
andsafir.logging.get_response_logger
APIs are the best ways to get the logger.