Files
MoviePilot/app/utils/stdio.py
2026-04-21 11:26:56 +08:00

85 lines
2.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from __future__ import annotations
import io
import logging
import sys
import threading
from logging.handlers import RotatingFileHandler
from pathlib import Path
class RotatingLineStream(io.TextIOBase):
"""
将 stdout/stderr 按行写入滚动日志文件。
这里不复用业务 logger避免 stdout 日志再次回流到控制台或普通业务日志文件,
同时保证启动阶段的 print/uvicorn 输出也能按配置滚动。
"""
def __init__(self, log_file: Path, max_bytes: int, backup_count: int):
super().__init__()
self._buffer = ""
self._lock = threading.Lock()
logger_name = f"moviepilot-stdio::{log_file}"
self._logger = logging.getLogger(logger_name)
self._logger.setLevel(logging.INFO)
self._logger.propagate = False
self._logger.handlers.clear()
handler = RotatingFileHandler(
filename=str(log_file),
maxBytes=max_bytes,
backupCount=backup_count,
encoding="utf-8",
)
handler.setFormatter(logging.Formatter("%(message)s"))
self._logger.addHandler(handler)
@property
def encoding(self) -> str:
return "utf-8"
def writable(self) -> bool:
return True
def isatty(self) -> bool:
return False
def write(self, message: str) -> int:
if not message:
return 0
with self._lock:
self._buffer += message.replace("\r\n", "\n")
while "\n" in self._buffer:
line, self._buffer = self._buffer.split("\n", 1)
self._logger.info(line)
return len(message)
def flush(self) -> None:
with self._lock:
if self._buffer:
self._logger.info(self._buffer)
self._buffer = ""
for handler in self._logger.handlers:
handler.flush()
def configure_rotating_stdio(
*, log_file: Path, max_bytes: int, backup_count: int
) -> RotatingLineStream:
"""
将当前进程的 stdout/stderr 统一重定向到同一个滚动日志流。
"""
log_file.parent.mkdir(parents=True, exist_ok=True)
stream = RotatingLineStream(
log_file=log_file,
max_bytes=max_bytes,
backup_count=backup_count,
)
sys.stdout = stream
sys.stderr = stream
return stream