bind_logger¶
-
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
safir/logger
key of the request object:@routes.get("/") async def get_index(request): logger = request["safir/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["safir/logger"]
andsafir.logging.get_response_logger
APIs are the best ways to get the logger.