HEX
Server: LiteSpeed
System: Linux houston.panomity.com 6.8.0-100-generic #100-Ubuntu SMP PREEMPT_DYNAMIC Tue Jan 13 16:40:06 UTC 2026 x86_64
User: nudepix (1011)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //opt/OpenManusWeb/app/web/log_handler.py
"""
简单的日志处理模块,用于Web应用日志捕获
"""
import threading
from contextlib import contextmanager
from datetime import datetime
from typing import Dict, List

from loguru import logger


# 全局日志存储
session_logs: Dict[str, List[Dict]] = {}
_lock = threading.Lock()


# 注册自定义日志处理器,按会话ID分类存储日志
class SessionLogHandler:
    def __init__(self, session_id: str):
        self.session_id = session_id

    def __call__(self, record):
        log_entry = {
            # "time": record["time"].strftime("%Y-%m-%d %H:%M:%S.%f"),
            # "level": record["level"].name,
            "message": record,
            "timestamp": datetime.now().timestamp(),
        }

        with _lock:
            if self.session_id not in session_logs:
                session_logs[self.session_id] = []
            session_logs[self.session_id].append(log_entry)

        # 传递记录,继续处理链
        return True


class SimpleLogCapture:
    """简单的日志捕获器,提供类似logger的接口"""

    def __init__(self, session_id: str):
        self.session_id = session_id

    def info(self, message: str) -> None:
        """记录信息级别日志"""
        add_log(self.session_id, "INFO", message)
        logger.info(message)

    def warning(self, message: str) -> None:
        """记录警告级别日志"""
        add_log(self.session_id, "WARNING", message)
        logger.warning(message)

    def error(self, message: str) -> None:
        """记录错误级别日志"""
        add_log(self.session_id, "ERROR", message)
        logger.error(message)

    def debug(self, message: str) -> None:
        """记录调试级别日志"""
        add_log(self.session_id, "DEBUG", message)
        logger.debug(message)

    def exception(self, message: str) -> None:
        """记录异常级别日志"""
        add_log(self.session_id, "ERROR", message)
        logger.exception(message)


@contextmanager
def capture_session_logs(session_id: str):
    """
    上下文管理器,用于捕获指定会话的日志
    返回一个SimpleLogCapture实例,而不是直接返回日志列表
    """
    # 创建该会话的日志存储
    with _lock:
        if session_id not in session_logs:
            session_logs[session_id] = []

    # 添加会话特定的日志处理器
    handler_id = logger.add(SessionLogHandler(session_id))

    # 创建一个简单的日志捕获器
    log_capture = SimpleLogCapture(session_id)

    try:
        # 返回日志捕获器而不是日志列表
        yield log_capture
    finally:
        # 移除临时添加的处理器
        logger.remove(handler_id)


def add_log(session_id: str, level: str, message: str) -> None:
    """添加日志到指定会话"""
    with _lock:
        if session_id not in session_logs:
            session_logs[session_id] = []

        session_logs[session_id].append(
            {
                "time": datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"),
                "level": level,
                "message": message,
                "timestamp": datetime.now().timestamp(),
            }
        )


def get_logs(session_id: str) -> List[Dict]:
    """获取指定会话的日志"""
    with _lock:
        return session_logs.get(session_id, [])[:]


def clear_logs(session_id: str) -> None:
    """清除指定会话的日志"""
    with _lock:
        if session_id in session_logs:
            session_logs[session_id] = []