How to disable traceback logging on error?
App example:
import uvicorn
from starlette.applications import Starlette
from starlette.requests import Request
from starlette.responses import JSONResponse
app = Starlette(debug=False)
@app.route("/ping")
def ping(_: Request) -> JSONResponse:
raise Exception("ERROR")
@app.exception_handler(Exception)
def exception_handler(_: Request, e: Exception):
print(f"Unhandled exception: {e}")
return JSONResponse({}, status_code=500)
uvicorn.run(app, host="127.0.0.1", port=8000)
When I call ping endpoint, I get the following message in the log:
INFO: Started server process [11002]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
Unhandled exception: ERROR
INFO: 127.0.0.1:53874 - "GET /ping HTTP/1.1" 500 Internal Server Error
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "/home/gleb/Projects/vertical/.venv/lib/python3.8/site-packages/uvicorn/protocols/http/httptools_impl.py", line 385, in run_asgi
result = await app(self.scope, self.receive, self.send)
File "/home/gleb/Projects/vertical/.venv/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
return await self.app(scope, receive, send)
File "/home/gleb/Projects/vertical/.venv/lib/python3.8/site-packages/starlette/applications.py", line 102, in __call__
await self.middleware_stack(scope, receive, send)
File "/home/gleb/Projects/vertical/.venv/lib/python3.8/site-packages/starlette/middleware/errors.py", line 181, in __call__
raise exc from None
File "/home/gleb/Projects/vertical/.venv/lib/python3.8/site-packages/starlette/middleware/errors.py", line 159, in __call__
await self.app(scope, receive, _send)
File "/home/gleb/Projects/vertical/.venv/lib/python3.8/site-packages/starlette/exceptions.py", line 82, in __call__
raise exc from None
File "/home/gleb/Projects/vertical/.venv/lib/python3.8/site-packages/starlette/exceptions.py", line 71, in __call__
await self.app(scope, receive, sender)
File "/home/gleb/Projects/vertical/.venv/lib/python3.8/site-packages/starlette/routing.py", line 550, in __call__
await route.handle(scope, receive, send)
File "/home/gleb/Projects/vertical/.venv/lib/python3.8/site-packages/starlette/routing.py", line 227, in handle
await self.app(scope, receive, send)
File "/home/gleb/Projects/vertical/.venv/lib/python3.8/site-packages/starlette/routing.py", line 43, in app
response = await run_in_threadpool(func, request)
File "/home/gleb/Projects/vertical/.venv/lib/python3.8/site-packages/starlette/concurrency.py", line 34, in run_in_threadpool
return await loop.run_in_executor(None, func, *args)
File "/usr/lib/python3.8/concurrent/futures/thread.py", line 57, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/gleb/Projects/vertical/app.py", line 11, in ping
raise Exception("ERROR")
Exception: ERROR
Despite the fact that I handled the error, the log was still written and even with traceback.
As I went deeper, I realized that this log was written by the uvicorn.error. I can disable this logger, but I want it to write information about the server.
How do I disable this traceback and messages like Exception in ASGI application correctly?
starlette version: 0.13.2
uvicorn version: 0.11.3
I think your exception is getting caught by the ErrorMiddleware. Try the same with an exception that isn't excatly Exception - try using a subtype/custom exception.
(From my check using ValueError for example doesn't lead to a traceback, if handled)
@aviramha Hi! Yes, this exception caught by ErrorMiddleware. It works the way I want it to. I have a lot of exception handlers that caught Exception subclasses and they don't write a traceback.
But I should handle the Exception class: write log and return custom Response object with special content. I don't want that traceback was logged. How to hide it?
I think the desire is that only true unexepcted exceptions would reach ServerErrorMiddleware, hence it can never be suppressed.
If you really want to suppress it, which is not recommended IMO you could subclass Starlette and implement build_middleware_stack, removing the ServerErrorMiddleware or writing your own one.
(Application code shouldn't lead to any scenario where you have the base Exception type..)
I found better solution:
from starlette.middleware import base
class ExceptionHandlerMiddleware(base.BaseHTTPMiddleware):
async def dispatch(
self,
request: Request,
handler: base.RequestResponseEndpoint,
) -> Response:
try:
return await handler(request)
except Exception as e:
app_logger.error(f"Caught unhandled {e.__class__} exception: {e}")
return server_error()
Most helpful comment
I found better solution: