Closed ThinksFast closed 1 year ago
Okay, I can reproduce this. It's definitely unexpected behaviour.
Turns out not to be a bug after all, I just can't read ;)
There are multiple things happening here:
app
"__main__"
(__name__
will be set to "__main__"
if you run a python module directly like this, that's why the __name__ == "__main__"
thing works)NoneType: None
is caused because you are using logger.exception
outside of an exception handler. See the docs on logger.exceptionIt works with request.logger
because that is accessing the "starlite"
logger.
I think our documentation is a bit misleading here if you're unfamiliar with Python logging (or in general)
Thanks for the feedback! I have been running the program by calling this from terminal: uvicorn main:app
. Which would have set name == "main"
. So that makes sense it's not calling the correct logger. Although this previously was working for me, I haven't changed my logging config, and the on_startup
functions in my production app would log INFO
statements just fine.
But I'm not sure why Starlite 1.30 would log the extra lines from Uvicorn, if I'm running the program the same way. uvicorn main:app
And if I set logger = logging.getLogger("app")
, it still doesn't log INFO
or DEBUG
statements.
But I'm not sure why Starlite 1.30 would log the extra lines from Uvicorn, if I'm running the program the same way.
uvicorn main:app
Starlite isn't. Uvicorn is. You're configuring neither Starlite's not Uvicorn's logger here. You are configuring an independent logger called "app"
And if I set
logger = logging.getLogger("app")
, it still doesn't logINFO
orDEBUG
statements.
You need to put the getLogger
inside log_on_start_up
. If you're getting it before that, it's not configured yet.
I just tried modifying the on_startup function to include getLogger
, and it still doesn't log INFO
or DEBUG
.
This function:
async def log_on_start_up():
logger = logging.getLogger("app")
logger.debug("Logging debug")
logger.info("Logging info")
logger.warning("Logging warning")
logger.exception("Logging exception")
logger.error("Logging error")
logger.critical("Logging critical")
Generates these logs on startup:
INFO: Started server process [52312]
INFO: Waiting for application startup.
Logging warning
Logging exception
NoneType: None
Logging error
Logging critical
INFO: Application startup complete.
And if I add a formatter
to the logger, I still get the same logs on startup... i.e. they're not formatted. So does this mean the logger is not configured when the on_startup
functions run?
Here's a complete example:
import logging
import uvicorn
from starlite import Starlite, LoggingConfig, get, Request, State, Template, Controller
logging_config = LoggingConfig(
loggers={
"app": {
"level": "DEBUG",
"handlers": ["queue_listener"],
}
},
formatters={
"standard": {
"format": "%(asctime)s loglevel=%(levelname)-6s logger=%(name)s %(funcName)s() L%(lineno)-4d %(message)s"
}
},
)
logger = logging.getLogger("app")
async def log_on_start_up():
logger = logging.getLogger("app")
logger.debug("Logging debug")
logger.info("Logging info")
logger.warning("Logging warning")
logger.exception("Logging exception")
logger.error("Logging error")
logger.critical("Logging critical")
class FrontEnd(Controller):
@get("/")
async def serveHomepage(self, request: Request, state: State) -> Template:
request.logger.info("Serving Homepage")
return Template(
name="homepage.html.j2",
context={"request": request},
)
app = Starlite(
route_handlers=[FrontEnd],
logging_config=logging_config,
on_startup=[log_on_start_up],
debug=True,
)
if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=8000)
import logging
import uvicorn
from starlite import Starlite, LoggingConfig, get
logging_config = LoggingConfig(
loggers={
"app": {
"level": "DEBUG",
"handlers": ["queue_listener"],
}
}
)
async def log_on_start_up():
logger = logging.getLogger("app")
logger.debug("Logging debug")
logger.info("Logging info")
logger.warning("Logging warning")
logger.error("Logging error")
logger.critical("Logging critical")
@get("/")
async def home() -> dict[str, str]:
"""Handler function that returns a greeting dictionary."""
return {"hello": "world"}
app = Starlite(
route_handlers=[home],
logging_config=logging_config,
on_startup=[log_on_start_up],
debug=True,
)
if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=8000)
This works for me.
Doesn't for me. I get this logged on startup with the code you provided. Running Python 3.11, Starlite 1.43.0.
$ uvicorn main:app --reload
INFO: Will watch for changes in these directories: ['/Users/ThinksFast/Documents/GitHub/starlite-mcve']
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [52606] using StatReload
INFO: Started server process [52608]
INFO: Waiting for application startup.
Logging warning
Logging error
Logging critical
INFO: Application startup complete.
This is very odd. Can you reproduce it in a new venv?
Also, can you post the results of pip freeze
?
Strange. It does log correctly in a new environment. But it's also double-logging:
INFO: Started server process [53798]
INFO: Waiting for application startup.
DEBUG - 2022-12-02 18:38:46,782 - app - logmain - Logging debug
DEBUG - 2022-12-02 18:38:46,782 - app - logmain - Logging debug
INFO - 2022-12-02 18:38:50,071 - app - logmain - Logging info
INFO - 2022-12-02 18:38:50,071 - app - logmain - Logging info
WARNING - 2022-12-02 18:38:53,179 - app - logmain - Logging warning
WARNING - 2022-12-02 18:38:53,179 - app - logmain - Logging warning
ERROR - 2022-12-02 18:38:54,307 - app - logmain - Logging error
ERROR - 2022-12-02 18:38:54,307 - app - logmain - Logging error
CRITICAL - 2022-12-02 18:38:55,513 - app - logmain - Logging critical
CRITICAL - 2022-12-02 18:38:55,513 - app - logmain - Logging critical
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
Here's the pip freeze from my original environment:
The duplicate entries are expected and are caused by propagation. You can check this by adding "propagate": False
to your config.
@ThinksFast Can this be closed?
Sorry, I've been traveling and haven't had a chance to work on this. But I just tried implementing propagate=False
in the minimal example and it still logs twice. Not sure why, but I'll dig into the logging docs and play with this some more.
I'm also not able to get the production app correctly logging on my local, even when I recreate a new environment from scratch.
I should be able to spend some time on this in the next two days, I'll report back soon!
ping @ThinksFast - this will be closed tomorrow. please check.
Ok, life has been a bit busy this week. I’ll close the ticket for now and reopen it if I can’t resolve it on my own.
Minor update: I switched to picologging and now all my log statements are logged. The only code I changed was the import statement:
From: import logging
To: import picologging as logging
And now in my production app, this code logs correctly... 🤷♂️
logger = logging.getLogger("app")
logger.info("Logging info level")
Describe the bug Outside of a request handler, I'm unable to log
debug
orinfo
level statements. Onlywarning
and above will log.To Reproduce Here is an MCVE:
On Starlite 1.43.0 in Python 3.11, the app logs the following on startup. Notice
info
anddebug
do not get logged.I have another environment with Python 3.10 and Starlite 1.30 installed. The same code logs some additional lines from Uvicorn, and the log formatting is different, but the
on_startup
logging still doesn't print out the info or debug levels.Additional context I have a production app which has logging in place for several
on_startup
functions. The logging in the functions has always worked for me, until recently. But I'm not sure what change I made that caused the logging to disappear.... was it a Starlite update, or some dependency, I'm not sure.I did test logging in a request handler, and info-level logging works..
request.logger.info("Log me in a request")
will get logged. Its only outside of request handlers that the logging seems to be ignored forinfo
anddebug
levels.