Replies: 18 comments 4 replies
-
This is probably a better question for uvicorn, but I'll take a stab at answering it. Full disclaimer, this is very likely not the "right way" to do this in uvicorn but...
log_config = uvicorn.config.LOGGING_CONFIG
log_config["formatters"]["access"]["fmt"] = "%(asctime)s - %(levelname)s - %(message)s"
uvicorn.run(app, log_config=log_config) The problem with just getting the logger and configuring it seems to be that when you call You could also try configuring your logging handlers after FastAPI starts up? Might have better luck as uvicorn won't be overriding at that point. @app.on_event("startup")
async def startup_event():
logger = logging.getLogger("uvicorn.access")
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
logger.addHandler(handler) The way I have that adds a new handler, it won't override the existing internal one. If that's okay for you it might be a better approach. |
Beta Was this translation helpful? Give feedback.
-
Doing :
is exactly what I was looking for ! |
Beta Was this translation helpful? Give feedback.
-
@Jackovic great to hear! If you're all set then go ahead and close the issue. Might be worth asking in https://github.com/encode/uvicorn if they would add some recommendations about configuring logging to their documentation. Might be similar to encode/uvicorn#491 which looks a bit stale. |
Beta Was this translation helpful? Give feedback.
-
@dbanty using I also seem to be seeing two entries. One colorized - without the timestamp, in uvicorn's default formatting (access log) and next line is in my format, with timestamp, no colors. I think there are multiple "handlers", and I'm overriding just one. How to debug this further ? |
Beta Was this translation helpful? Give feedback.
-
I recently came across the same issue and here's how I solve it:
uvicorn_log_config = uvicorn.config.LOGGING_CONFIG
del uvicorn_log_config["loggers"][""]
uvicorn.run(app, log_config=uvicorn_log_config)
console_formatter = uvicorn.logging.ColourizedFormatter(
"{levelprefix:<8} @ {name} : {message}",
style="{",
use_colors=True
) Hope this helps |
Beta Was this translation helpful? Give feedback.
-
@dbanty thanks so much, after an hour of trying to understand Uvicorn's strange logging behaviours you just made it all very clear. |
Beta Was this translation helpful? Give feedback.
-
There is another potential solution if you want to unify the uvicorn logging with your actual endpoints logging (a good idea in my opinion), by passing None to log_config. This will essentially stop uvicorn from patching the existing logging configuration:
Of course the default uvicorn coloring is lost but nothing stops you from setting a custom formatter in a global, transparent way that can also handle colors. |
Beta Was this translation helpful? Give feedback.
-
Is there a way to capture the output of exception/failure dumps? I notice that if there is a syntax error, it doesnt go to a file, it get thrown into journalctl, I am running the start.py containing the uvicorn.run() command with a service file. |
Beta Was this translation helpful? Give feedback.
-
For that doe we need to add configuration as i done here? It work for me. Thank you @dorinclisu for this suggestion. |
Beta Was this translation helpful? Give feedback.
-
Sorry, I'm a bit lost. This solution by @Jackovic works locally:
But how do we achieve this when using Gunicorn and uvicorn on production server?
/etc/app/config.py
Because we can't create Thank you |
Beta Was this translation helpful? Give feedback.
-
@houmie 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 You can now start uvicorn with You may need to change |
Beta Was this translation helpful? Give feedback.
-
@mandarvaze Thank you for your reply. It's actually more complicated with Gunicorn, because you don't have a clear entry point to pass in the config.
I have found a similar issue: encode/uvicorn#491 But it's not straight forward, as I need to subclass the worker it seems, which can't be found. Thanks |
Beta Was this translation helpful? Give feedback.
-
Is there a way to show response time in the logs? |
Beta Was this translation helpful? Give feedback.
-
Does anyone know if it is possible to disable logging for specific endpoints only? |
Beta Was this translation helpful? Give feedback.
-
As these are Uvicorn logs, I would recommend to ask this in that repo. |
Beta Was this translation helpful? Give feedback.
-
Thanks for the discussion here everyone! 👏 🙇 Thanks for reporting back and closing the issue @Jackovic 👍 |
Beta Was this translation helpful? Give feedback.
-
Hi, version: 1
disable_existing_loggers: False
formatters:
default:
"()": uvicorn.logging.DefaultFormatter
format: '%(levelprefix)s [%(asctime)s] %(message)s'
use_colors: null
datefmt: '%d-%m-%Y %H:%M:%S'
access:
"()": uvicorn.logging.AccessFormatter
format: '%(levelprefix)s [%(asctime)s] %(client_addr)s - "%(request_line)s" %(status_code)s'
datefmt: '%d-%m-%Y %H:%M:%S'
handlers:
default:
formatter: default
class: logging.StreamHandler
stream: ext://sys.stderr
access:
formatter: access
class: logging.StreamHandler
stream: ext://sys.stdout
loggers:
uvicorn:
level: INFO
handlers:
- default
propagate: no
uvicorn.error:
level: INFO
uvicorn.access:
level: INFO
handlers:
- access
propagate: no This configuration is copied and pasted from the default LOGGING_CONFIG of Uvicorn. I just added the timestamp (adding To run uvicorn with custom logging: An alternative way: from typing import Any, Dict
import uvicorn
from fastapi import FastAPI
from uvicorn.config import LOGGING_CONFIG
app = FastAPI()
def timestamp_log_config(uvicorn_log_config: Dict[str, Any]) -> Dict[str, Any]:
datefmt = '%d-%m-%Y %H:%M:%S'
formatters = uvicorn_log_config['formatters']
formatters['default']['fmt'] = '%(levelprefix)s [%(asctime)s] %(message)s'
formatters['access']['fmt'] = '%(levelprefix)s [%(asctime)s] %(client_addr)s - "%(request_line)s" %(status_code)s'
formatters['access']['datefmt'] = datefmt
formatters['default']['datefmt'] = datefmt
return uvicorn_log_config
if __name__ == '__main__':
uvicorn.run(app, log_config=timestamp_log_config(LOGGING_CONFIG)) |
Beta Was this translation helpful? Give feedback.
-
You can try to use the following code snippets. log_config = uvicorn.config.LOGGING_CONFIG
log_config["handlers"] = {
"default": {
"formatter": "default",
"class": "logging.handlers.TimedRotatingFileHandler",
"filename": "./log",
},
}
log_config["loggers"] = {
"uvicorn.access": {"handlers": ["default"], "level": "INFO"},
}
uvicorn.run(app, log_config=log_config) |
Beta Was this translation helpful? Give feedback.
-
Hello,
Thanks for FastAPI, easy to use in my Python projects !
However, I have an issue with logs.
In my Python project, I use :
And when i test my app I get in the console :
This 5 lines are exactly what I expected.
Now I want to have access to these logs because I want to re-format them.
So, if i am right, I have a logger managing :
and a logger managing :
Is it right ?
I have no problem to get access to the first, I can use :
and then change the formatter,
but, for the second I was expecting that :
will do the same, but I am unable to change the formatter for the log :
How I can do that in my Python 3.7 script with FastAPI 0.52.0 and Uvicorn 0.11.3 ?
Thank you.
Beta Was this translation helpful? Give feedback.
All reactions