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
loggerkey 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_idA random UUID4 string that uniquely identifies the request.
pathThe path of the request.
methodThe http method of the request.
Logger name
By default, the logger is named for the
logger_nameattribute 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_middlewarefunction to set this up:app = web.Application() app["safir/config"] = Configuration() app.middlewares.append(bind_logger)
Remember that
bind_loggernames the logger according to thelogger_nameattribute of the configuration,app["safir/config"].Using the logger
Within a handler, you can access the logger directly from the
loggerkey 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_loggerfunction: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_loggercontext 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_loggeris acontextvars.ContextVar. AContextVaris isolated to each asyncio Task, which makes it great for storing context specific to each reponse.The
request['logger']andsafir.logging.get_response_loggerAPIs are the best ways to get the logger.