ASGI Logger Middleware
asgi-logger is a middleware-based access logger designed for ASGI servers, offering an alternative to the default Uvicorn logger. It is compatible with any ASGI application and provides customizable log formats. The current version is 0.1.0, released in November 2021, with development continuing on GitHub though without frequent PyPI releases.
Common errors
-
TypeError: a bytes-like object is required, not 'str' (often seen with Flask's app.logger or other non-ASGI native loggers)
cause Attempting to use a WSGI-centric logger (like Flask's `app.logger` directly) in an ASGI context without proper adaptation, or conflicts with how different loggers handle byte vs. string output.fixEnsure all logging is configured to work within the asynchronous ASGI context, ideally using standard Python `logging` or an ASGI-aware logger. If using Flask with Uvicorn, consider using a wrapper or ensuring Flask's logger doesn't interfere. -
ERROR: Exception in ASGI application Traceback (most recent call last): ... (KeyError: 'status')
cause An open issue indicates that the middleware can sometimes produce a `KeyError: 'status'`. This suggests an edge case where the 'status' key expected in the scope or event message is missing.fixThis is an unresolved issue in the current version. Monitor the `asgi-logger` GitHub repository for updates or workarounds. For now, careful error handling around the middleware or a custom middleware to catch such `KeyError` might be needed. -
Logs appear twice in the console.
cause This is a common issue when both `asgi-logger` and Uvicorn's default access logger are active simultaneously.fixDisable Uvicorn's default access logger by adding `logging.getLogger("uvicorn.access").handlers = []` to your application's entry point, before Uvicorn starts.
Warnings
- gotcha When using `asgi-logger` with Uvicorn, you must explicitly disable Uvicorn's default access logger to avoid duplicate log entries for each request.
- breaking The project was originally named `uvicorn-logger` and was later renamed to `asgi-logger`. If you were using an extremely old version under the previous name, imports and package names will need updating.
- gotcha There are known issues with `asgi-logger` sometimes duplicating the root path in logs, especially with Starlette 0.33+, and occasional `KeyError: 'status'` in the middleware. These are open issues on GitHub.
Install
-
pip install asgi-logger
Imports
- AccessLoggerMiddleware
from asgi_logger import AccessLoggerMiddleware
Quickstart
import logging
from fastapi import FastAPI
from fastapi.middleware import Middleware
from asgi_logger import AccessLoggerMiddleware
import uvicorn
# Instantiate FastAPI app
app = FastAPI(
middleware=[
Middleware(AccessLoggerMiddleware, format='%(client_addr)s - "%(request_line)s" %(status_code)s')
]
)
@app.get("/hello")
async def home():
return {"message": "Hello world!"}
# Important: Disable Uvicorn's default access logger to avoid duplicate logs
logging.getLogger("uvicorn.access").handlers = []
if __name__ == "__main__":
# To run, save this as main.py and execute: uvicorn main:app --port 8000
print("Navigate to http://127.0.0.1:8000/hello")
uvicorn.run(app, host="127.0.0.1", port=8000)