logging.py 1.76 KB
"""Runtime environment and logging bootstrap helpers."""

from __future__ import annotations

import os

from loguru import logger


RUNTIME_ENV_VARS = {
    "PYTHONIOENCODING": "utf-8",
    "PYTHONUTF8": "1",
    "PYTHONUNBUFFERED": "1",
}


def configure_runtime_environment() -> None:
    """Ensure Python subprocesses use UTF-8 and unbuffered output."""
    for key, value in RUNTIME_ENV_VARS.items():
        os.environ[key] = value


def patch_eventlet_disconnect_logging() -> None:
    """Suppress noisy disconnect stack traces from eventlet clients."""
    try:
        import eventlet.wsgi  # type: ignore
    except Exception as exc:  # pragma: no cover
        logger.debug(f"eventlet 不可用,跳过断连补丁: {exc}")
        return

    try:
        original_finish = eventlet.wsgi.HttpProtocol.finish  # type: ignore[attr-defined]
    except Exception as exc:  # pragma: no cover
        logger.debug(f"eventlet 缺少 HttpProtocol.finish,跳过断连补丁: {exc}")
        return

    def _safe_finish(self, *args, **kwargs):  # pragma: no cover
        try:
            return original_finish(self, *args, **kwargs)
        except (BrokenPipeError, ConnectionResetError, ConnectionAbortedError) as exc:
            try:
                environ = getattr(self, "environ", {}) or {}
                method = environ.get("REQUEST_METHOD", "")
                path = environ.get("PATH_INFO", "")
                logger.warning(f"客户端已主动断开,忽略异常: {method} {path} ({exc})")
            except Exception:
                logger.warning(f"客户端已主动断开,忽略异常: {exc}")
            return

    eventlet.wsgi.HttpProtocol.finish = _safe_finish  # type: ignore[attr-defined]
    logger.info("已为 eventlet 连接断开启用安全防护")