-
-
Notifications
You must be signed in to change notification settings - Fork 203
-
I have a very simple Quart app that I use for some local home automation. I'd like to log the default Quart requests to a file instead of the console/stdout.
When the app starts and a request is made (curl http://localhost/info), the following is printed to console/stdout:
* Serving Quart app 'app2'
* Debug mode: False
* Please use an ASGI server (e.g. Hypercorn) directly in production
* Running on http://0.0.0.0:5000 (CTRL + C to quit)
[2024年05月14日 09:11:52 -0500] [17720] [INFO] Running on http://0.0.0.0:5000 (CTRL + C to quit)
[2024年05月14日 09:12:02 -0500] [17720] [INFO] 127.0.0.1:64062 GET /info 1.1 200 16 11965
[2024年05月14日 09:12:02 -0500] [17720] [INFO] 127.0.0.1:64062 GET /info 1.1 - - 12964
I would like to be able to console log the last two lines (info about the request) to a log file. Despite many attempts to do so, I can never it to work. The closest I have gotten is with this code:
hypercorn_logger = logging.getLogger('hypercorn') hypercorn_logger.addHandler(logging.FileHandler('test.log', 'w'))
However, it only logs this line to the file: Running on http://0.0.0.0:5000 (CTRL + C to quit). What am I missing?
Demo App Code
import logging from quart import Quart app = Quart(__name__) @app.route('/info') async def info(): return "here's some info" if __name__ == '__main__': app.run(host='0.0.0.0')
Versions:
- Quart 0.19.5
- Hypercorn 0.16.0
Beta Was this translation helpful? Give feedback.
All reactions
The reason is that when you use the development server with app.run() Quart overrides the Hypercorn config.
You can either use Hypercorn directly (like described here), or do this:
from collections.abc import Awaitable, Callable, Coroutine from hypercorn.asyncio import serve from hypercorn.config import Config as HyperConfig from quart import Quart class App(Quart): def run_task( self, host: str = "127.0.0.1", port: int = 5000, debug: bool | None = None, ca_certs: str | None = None, certfile: str | None = None, keyfile: str | None = None, shutdown_trigger: Callable[..., Awaitable[None]] | None = None, ) -> Coroutine[
Replies: 1 comment 3 replies
-
The easiest way if you use Hypercorn is to set the accesslog variable in the config file.
Beta Was this translation helpful? Give feedback.
All reactions
-
if you use Hypercorn
I think Hypercorn gets used behind the scenes, right? I'm still running it as a Quart app with app.run().
When attempting to configure the Hypercorn accesslog option I still get the same behavior. My log file generates Running on http://127.0.0.1:5000 (CTRL + C to quit) to the specified FileHandler, but no other request information makes it there.
Am I setting the variable incorrectly?
import logging from quart import Quart from hypercorn.config import Config app = Quart(__name__) config = Config() config.accesslog = '-' hypercorn_logger = logging.getLogger('hypercorn') hypercorn_logger.addHandler(logging.FileHandler('test.log', 'w')) @app.route('/info') async def info(): return "here's some info" if __name__ == '__main__': app.run()
Beta Was this translation helpful? Give feedback.
All reactions
-
The reason is that when you use the development server with app.run() Quart overrides the Hypercorn config.
You can either use Hypercorn directly (like described here), or do this:
from collections.abc import Awaitable, Callable, Coroutine from hypercorn.asyncio import serve from hypercorn.config import Config as HyperConfig from quart import Quart class App(Quart): def run_task( self, host: str = "127.0.0.1", port: int = 5000, debug: bool | None = None, ca_certs: str | None = None, certfile: str | None = None, keyfile: str | None = None, shutdown_trigger: Callable[..., Awaitable[None]] | None = None, ) -> Coroutine[None, None, None]: config = HyperConfig() config.access_log_format = "%(h)s %(r)s %(s)s %(b)s %(D)s" config.accesslog = "test.log" # I modified this config.bind = [f"{host}:{port}"] config.ca_certs = ca_certs config.certfile = certfile if debug is not None: self.debug = debug config.errorlog = "-" # I modified this config.keyfile = keyfile return serve(self, config, shutdown_trigger=shutdown_trigger) app = App(__name__) @app.route("/info") async def info(): return "here's some info" if __name__ == "__main__": app.run()
Beta Was this translation helpful? Give feedback.
All reactions
-
Thank you for taking the time to explain what's going on. I had a hunch that Quart was doing something goofy with Hypercorn but I couldn't find those references that you pointed out so I appreciate it.
It looks like the best thing to do is to run it using Hypercorn which I think I'll do; easy enough to spin up the app that way instead of overriding those properties. Thanks again.
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 1