litestar-org / litestar

Production-ready, Light, Flexible and Extensible ASGI API framework | Effortlessly Build Performant APIs
https://litestar.dev/
MIT License
5.42k stars 372 forks source link

Docs: Add example for `gunicorn` with `uvicorn` workers #2876

Open byte-bot-app[bot] opened 10 months ago

byte-bot-app[bot] commented 10 months ago

Add documentation examples for gunicorn w/ uvicorn workers. See the X post below for a user asking a question on this topic.

Ref:

Bad Messages:

Anyone doing gunicorn w/ unicorn workers? https://x.com/greeduan/status/1732048433408627005?s=46&t=p4oNoKNiN6WSSW5RCWU7_w @greeduan @LitestarAPI do you have any guide for logging when using gunicorn with uvicorn? Spent a few hours and I still can't figure out how to get the app logs out to the gunicorn logs. Meanwhile with Django it's plug-n-play. Not good for prod.

Reported by peter in Discord: <#919193495690936353>: no but it would be nice to have an example for that


[!NOTE]
While we are open for sponsoring on GitHub Sponsors and OpenCollective, we also utilize Polar.sh to engage in pledge-based sponsorship.

Check out all issues funded or available for funding on our Polar.sh dashboard

  • If you would like to see an issue prioritized, make a pledge towards it!
  • We receive the pledge once the issue is completed & verified
  • This, along with engagement in the community, helps us know which features are a priority to our users.

Fund with Polar

JacobCoffee commented 10 months ago

This relates to #2609, partially

peterschutt commented 10 months ago

We were specifically talking about logging with gunicorn workers - great to have a full example, but just want to make sure that the logging topic doesn't get lost.

provinzkraut commented 9 months ago

Thinking about this, I'm not sure if this is actually Litestar specific? The logging setup of gunicorn with uvicorn workers will be exactly the same as for any other ASGI apps. Maybe we don't need to re-invent the wheel here and could just link to existing documentation?

winstxnhdw commented 3 months ago

Thinking about this, I'm not sure if this is actually Litestar specific? The logging setup of gunicorn with uvicorn workers will be exactly the same as for any other ASGI apps. Maybe we don't need to re-invent the wheel here and could just link to existing documentation?

Tried doing it the same way as I did it with FastAPI, but any stray exceptions aren't being logged out.

provinzkraut commented 3 months ago

Litestar's logging behaviour of exception is different than FastAPI's, but this is independent of the server being used. Exceptions aren't logged by default if you're not in debug mode. You can configure this by setting log_exceptions="always" in the logging config: https://docs.litestar.dev/latest/reference/logging/config.html#litestar.logging.config.LoggingConfig.log_exceptions

winstxnhdw commented 3 months ago

Litestar's logging behaviour of exception is different than FastAPI's, but this is independent of the server being used. Exceptions aren't logged by default if you're not in debug mode. You can configure this by setting log_exceptions="always" in the logging config: https://docs.litestar.dev/latest/reference/logging/config.html#litestar.logging.config.LoggingConfig.log_exceptions

It still doesn't log anything out.

class TranscribeController(Controller):
    path = '/transcribe'

    @post()
    async def transcribe(self, data: Annotated[UploadFile, Body(media_type=RequestEncodingType.MULTI_PART)]) -> bytes:
        content = await data.read()
        raise Exception(content)
        return content

def initialise() -> Litestar:
    return Litestar(
        logging_config=LoggingConfig(log_exceptions='always'),
        route_handlers=[TranscribeController],
    )

It works fine on Uvicorn though, but with Gunicorn, it disappears.

provinzkraut commented 3 months ago

How are you running gunicorn? I tested it and it works just fine.


In any case, as I mentioned before, this isn't unique to Litestar. It has to do with how gunicorn handles logging. See for example this issue which describes the same behaviour you're experiencing, but with FastAPI.

winstxnhdw commented 3 months ago

How are you running gunicorn? I tested it and it works just fine.

In any case, as I mentioned before, this isn't unique to Litestar. It has to do with how gunicorn handles logging. See for example this issue which describes the same behaviour you're experiencing, but with FastAPI.

I am well familiar with that issue and I have worked around it and still managed to get my exceptions printed.

# gunicorn.conf.py

from server import initialise
from server.config import Config

wsgi_app = f'{initialise.__module__}:{initialise.__name__}()'
reload = False
preload_app = True
bind = f'0.0.0.0:{Config.server_port}'
workers = Config.worker_count
worker_class = 'uvicorn.workers.UvicornWorker'
timeout = 300
provinzkraut commented 3 months ago

That's your config but how are you running it? Is it perhaps inside a container (the bind to 0.0.0.0 suggests that)?

winstxnhdw commented 3 months ago

Nope, it's not containerised. Running it in a poetry venv with poetry run gunicorn and that's it.

provinzkraut commented 3 months ago

What platform are you on?

provinzkraut commented 3 months ago

I don't know why but it seems to be the preload_app = True in your gunicorn config. Adding that causes the logs to disappear.

I've found this issue which seems to describe this exact behaviour, but apparently it has been fixed since.

winstxnhdw commented 3 months ago

I have tested on my personal Windows laptop and within a Linux VPS. I'll try disabling preload_app tomorrow but preload_app is quite important IIRC.

winstxnhdw commented 3 months ago

Yeah, I have confirmed that it is indeed preload_app that's causing this issue, and I believe this is on Litestar's end because all my FastAPI applications are completely fine with this setting.

JacobCoffee commented 2 months ago

not familiar with the issue - just interjecting here quickly - but with the advent of process management in Uvicorn, it may help your particular situation? (to swap from Gunicorn)

provinzkraut commented 2 months ago

Yeah, I have confirmed that it is indeed preload_app that's causing this issue, and I believe this is on Litestar's end because all my FastAPI applications are completely fine with this setting.

This seems odd. I'm still not 100% convinced this is a bug on our end, but would you mind opening a separate issue for this? It's not really a documentation thing in any case, because this should work