|
|
import asyncio |
|
|
import logging |
|
|
import signal |
|
|
|
|
|
from gunicorn import glogging |
|
|
from gunicorn.app.base import BaseApplication |
|
|
from uvicorn.workers import UvicornWorker |
|
|
|
|
|
from langflow.logging.logger import InterceptHandler |
|
|
|
|
|
|
|
|
class LangflowUvicornWorker(UvicornWorker): |
|
|
CONFIG_KWARGS = {"loop": "asyncio"} |
|
|
|
|
|
def _install_sigint_handler(self) -> None: |
|
|
"""Install a SIGQUIT handler on workers. |
|
|
|
|
|
- https://github.com/encode/uvicorn/issues/1116 |
|
|
- https://github.com/benoitc/gunicorn/issues/2604 |
|
|
""" |
|
|
loop = asyncio.get_running_loop() |
|
|
loop.add_signal_handler(signal.SIGINT, self.handle_exit, signal.SIGINT, None) |
|
|
|
|
|
async def _serve(self) -> None: |
|
|
|
|
|
self._install_sigint_handler() |
|
|
await super()._serve() |
|
|
|
|
|
|
|
|
class Logger(glogging.Logger): |
|
|
"""Implements and overrides the gunicorn logging interface. |
|
|
|
|
|
This class inherits from the standard gunicorn logger and overrides it by |
|
|
replacing the handlers with `InterceptHandler` in order to route the |
|
|
gunicorn logs to loguru. |
|
|
""" |
|
|
|
|
|
def __init__(self, cfg) -> None: |
|
|
super().__init__(cfg) |
|
|
logging.getLogger("gunicorn.error").handlers = [InterceptHandler()] |
|
|
logging.getLogger("gunicorn.access").handlers = [InterceptHandler()] |
|
|
|
|
|
|
|
|
class LangflowApplication(BaseApplication): |
|
|
def __init__(self, app, options=None) -> None: |
|
|
self.options = options or {} |
|
|
|
|
|
self.options["worker_class"] = "langflow.server.LangflowUvicornWorker" |
|
|
self.options["logger_class"] = Logger |
|
|
self.application = app |
|
|
super().__init__() |
|
|
|
|
|
def load_config(self) -> None: |
|
|
config = {key: value for key, value in self.options.items() if key in self.cfg.settings and value is not None} |
|
|
for key, value in config.items(): |
|
|
self.cfg.set(key.lower(), value) |
|
|
|
|
|
def load(self): |
|
|
return self.application |
|
|
|