Skip to content

Instantly share code, notes, and snippets.

@liviaerxin
Last active June 5, 2025 07:23
Show Gist options
  • Save liviaerxin/d320e33cbcddcc5df76dd92948e5be3b to your computer and use it in GitHub Desktop.
Save liviaerxin/d320e33cbcddcc5df76dd92948e5be3b to your computer and use it in GitHub Desktop.
FastAPI and Uvicorn Logging #python #fastapi #uvicorn #logging

FastAPI and Uvicorn Logging

When running FastAPI app, all the logs in console are from Uvicorn and they do not have timestamp and other useful information. As Uvicorn applies python logging module, we can override Uvicorn logging formatter by applying a new logging configuration.

Meanwhile, it's able to unify the your endpoints logging with the Uvicorn logging by configuring all of them in the config file log_conf.yaml.

Before overriding:

uvicorn main:app --reload
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [34318] using StatReload
INFO:     Started server process [34320]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     127.0.0.1:50062 - "GET / HTTP/1.1" 200 OK

After applying log_conf.yaml:

uvicorn main:app --reload --log-config=log_conf.yaml
2023-03-08 15:40:41,170 - uvicorn.error - INFO - Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
2023-03-08 15:40:41,170 - uvicorn.error - INFO - Started reloader process [34322] using StatReload
2023-03-08 15:40:41,297 - asyncio - DEBUG - Using selector: EpollSelector
2023-03-08 15:40:41,432 - uvicorn.error - INFO - Started server process [34324]
2023-03-08 15:40:41,432 - uvicorn.error - INFO - Waiting for application startup.
2023-03-08 15:40:41,432 - uvicorn.error - INFO - Application startup complete.
2023-03-08 15:48:21,450 - main - INFO - request / endpoint!
2023-03-08 15:48:21,450 - uvicorn.access - INFO - 127.0.0.1:59782 - "GET / HTTP/1.1" 200

logs with FastAPI and Uvicorn · tiangolo/fastapi · Discussion #7457 · GitHub

Python Comprehensive Logging using YAML Configuration · GitHub

version: 1
disable_existing_loggers: False
formatters:
default:
# "()": uvicorn.logging.DefaultFormatter
format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
access:
# "()": uvicorn.logging.AccessFormatter
format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:
default:
formatter: default
class: logging.StreamHandler
stream: ext://sys.stderr
access:
formatter: access
class: logging.StreamHandler
stream: ext://sys.stdout
loggers:
uvicorn.error:
level: INFO
handlers:
- default
propagate: no
uvicorn.access:
level: INFO
handlers:
- access
propagate: no
root:
level: DEBUG
handlers:
- default
propagate: no
from fastapi import FastAPI
import logging
logger = logging.getLogger(__name__)
app = FastAPI()
@app.get("/")
async def func():
logger.info(f"request / endpoint!")
return {"message": "hello world!"}
uvicorn>=0.20.0
fastapi>=0.89.1
PyYAML>=6.0
@adosib
Copy link

adosib commented Nov 15, 2024

If you only really care about logging some extra info for HTTP requests, I've found @app.middleware("http") to be the silver bullet. Excellent example at this SO answer.

@hegerdes
Copy link

Tank you so much for this!

In case you also want to use gunicorn, you just have to convert the conf to JSON and start gunicorn with --log-config-json log_conf.json.
The loggers for gunicorn are called:

"gunicorn.error": {
    "level": "INFO",
    "handlers": [
        "default"
    ],
    "propagate": "no"
},
"gunicorn.access": {
    "level": "INFO",
    "handlers": [
        "access"
    ],
    "propagate": "no"
}

@msissican
Copy link

It is very helpful, thanks a lot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment