Files
astrbot_plugin_qq_group_dai…/docs/LOG_VIEWING_RESEARCH.md
T

18 KiB
Raw Blame History

AstrBot 日志查看方式研究报告

概述

本文档详细说明了 AstrBot 的日志系统架构、查看方式、以及如何在代码中集成日志查看功能。


1. 日志文件默认位置

1.1 日志文件存储位置

根据配置,AstrBot 的日志文件存储在以下位置:

日志类型 默认位置 配置键 说明
普通日志 data/logs/astrbot.log log_file_path 主应用日志,记录应用运行信息
Trace 日志 data/logs/astrbot.trace.log trace_log_path 链路追踪日志,记录请求跨度信息

1.2 日志文件配置参数

# 配置文件位置: astrbot/core/config/default.py
DEFAULT_CONFIG = {
    "log_level": "INFO",                    # 日志级别(DEBUG, INFO, WARNING, ERROR, CRITICAL
    "log_file_enable": False,               # 是否启用文件日志(默认禁用)
    "log_file_path": "logs/astrbot.log",   # 日志文件相对路径(相对于 data/ 目录)
    "log_file_max_mb": 20,                  # 单个日志文件最大大小(MB
    "trace_enable": False,                  # 是否启用 Trace 记录
    "trace_log_enable": False,              # 是否启用 Trace 文件日志
    "trace_log_path": "logs/astrbot.trace.log",  # Trace 日志文件路径
    "trace_log_max_mb": 20,                 # Trace 日志文件最大大小
}

1.3 日志目录基路径

  • 根数据目录: data/
  • 日志目录: data/logs/
  • 获取方法Python 代码):
    from astrbot.core.utils.astrbot_path import get_astrbot_data_path
    log_dir = os.path.join(get_astrbot_data_path(), "logs")
    

1.4 日志文件轮转配置

当启用文件日志时,AstrBot 使用 RotatingFileHandler

  • 最大单个文件大小:log_file_max_mb(默认 20MB
  • 备份文件数量:3 个
  • 超过大小后自动轮转:astrbot.log.1, astrbot.log.2, astrbot.log.3

2. Dashboard 中的日志查看功能

2.1 Dashboard 路由和 API

AstrBot Dashboard 提供以下日志相关的 REST API(代码位置:astrbot/dashboard/routes/log.py):

API 端点 方法 功能 说明
/api/live-log GET 实时日志流 Server-Sent Events (SSE) 连接,推送实时日志
/api/log-history GET 日志历史 获取缓存的日志历史(JSON 格式)
/api/trace/settings GET Trace 设置查询 获取当前 Trace 启用状态
/api/trace/settings POST Trace 设置更新 更新 Trace 启用/禁用状态

2.2 实时日志流(SSE

连接方式

前端代码Vue.js,位置:dashboard/src/stores/common.js):

fetch('/api/live-log', {
  method: 'GET',
  headers: {
    'Content-Type': 'multipart/form-data',
    'Authorization': 'Bearer ' + localStorage.getItem('token')
  },
  cache: 'no-cache',
}).then(response => {
  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  // 处理流式数据...
})

SSE 消息格式

后端返回的 SSE 消息格式(astrbot/dashboard/routes/log.py):

id: {timestamp}
data: {json_object}

JSON 对象结构:

{
  "type": "log",
  "level": "INFO",
  "data": "[12:34:56] [Core] [INFO] [file.py:123]: Log message",
  "time": 1697787296.123456,
  "uuid": "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
}

日志缓存和重放

  • 缓存大小: 最多 500 条日志(常量 CACHED_SIZE = 500
  • 缓存数据结构: deque(maxlen=500)(环形缓冲区)
  • 浏览器断网重连: 发送 Last-Event-ID 请求头,服务端根据时间戳重放缺失的日志

2.3 Dashboard 前端界面

控制台页面(Console

路由: /console
组件: ConsolePage.vue

功能:

  • 实时日志显示(通过 SSE 连接)
  • 日志级别过滤(DEBUG, INFO, WARNING, ERROR, CRITICAL
  • 自动滚动开关
  • pip 包安装界面

日志样式:

[12:34:56] [Core] [INFO] [astrbot.py:123]: AstrBot started successfully
[12:34:57] [Plug] [WARN] [plugin.py:45]: Missing dependency
[12:35:00] [Core] [ERRO] [error.py:78]: Connection timeout [v4.14.4]

链路追踪页面(Trace

路由: /trace
组件: TracePage.vue

功能:

  • 实时链路追踪显示
  • Trace 启用/禁用开关
  • Trace 事件详细信息展示

日志显示器组件

组件: ConsoleDisplayer.vue

特性:

  • 日志级别色彩标记
  • ANSI 颜色代码转换为 HTML 样式
  • 日志缓存最多保留 1000 条(configurable
  • 自动滚动到最新日志

3. LogBroker 架构(发布-订阅模式)

3.1 LogBroker 类设计

位置: astrbot/core/log.py

class LogBroker:
    """日志代理类, 用于缓存和分发日志消息"""

    def __init__(self):
        self.log_cache = deque(maxlen=CACHED_SIZE)  # 环形缓冲区
        self.subscribers: list[Queue] = []          # 订阅者列表

    def register(self) -> Queue:
        """注册新的订阅者,返回一个队列用于接收日志"""
        q = Queue(maxsize=CACHED_SIZE + 10)
        self.subscribers.append(q)
        return q

    def unregister(self, q: Queue):
        """取消订阅"""
        self.subscribers.remove(q)

    def publish(self, log_entry: dict):
        """发布日志到所有订阅者(非阻塞方式)"""
        self.log_cache.append(log_entry)
        for q in self.subscribers:
            try:
                q.put_nowait(log_entry)
            except asyncio.QueueFull:
                pass  # 订阅者队列满,丢弃该日志

3.2 工作流程图

日志记录器 (logger)
    ↓
LogQueueHandler (日志处理器)
    ↓
LogBroker.publish(log_entry)
    ├→ 添加到 log_cache(环形缓冲区)
    └→ 分发给所有订阅者的队列
         ├→ Dashboard SSE 连接
         ├→ Trace 日志记录器
         └→ 其他订阅者

3.3 日志项结构

log_entry = {
    "level": "INFO",           # 日志级别
    "time": 1697787296.123,   # Unix 时间戳
    "data": "Log message text", # 格式化的日志文本
}

3.4 在代码中集成 LogBroker

启动应用时初始化

# main.py 或 cmd_run.py
from astrbot.core import LogBroker, LogManager, logger

# 创建日志代理
log_broker = LogBroker()

# 将日志处理器连接到 LogBroker
LogManager.set_queue_handler(logger, log_broker)

# 传递给应用初始化器
core_lifecycle = InitialLoader(db, log_broker)

在 Dashboard 中使用

# dashboard/routes/log.py
class LogRoute(Route):
    def __init__(self, context: RouteContext, log_broker: LogBroker) -> None:
        self.log_broker = log_broker
        # 注册 API 路由...

    async def log(self) -> QuartResponse:
        """SSE 日志流"""
        queue = self.log_broker.register()  # 注册订阅者
        try:
            while True:
                message = await queue.get()  # 等待日志
                yield _format_log_sse(message, current_ts)
        finally:
            self.log_broker.unregister(queue)  # 取消订阅

4. Trace 日志系统

4.1 Trace 概念

Trace 日志用于记录请求的整个链路,包括:

  • 跨度信息(span_id
  • 请求发起者(sender_name
  • 操作阶段(action
  • 自定义字段(fields

4.2 Trace 启用配置

配置项

"trace_enable": False,              # 启用 Trace 记录
"trace_log_enable": False,          # 启用 Trace 文件日志
"trace_log_path": "logs/astrbot.trace.log",  # Trace 日志文件路径

Dashboard 设置: /api/trace/settings 端点可动态启用/禁用 Trace

4.3 使用 TraceSpan 记录链路

代码位置: astrbot/core/utils/trace.py

from astrbot.core.utils.trace import TraceSpan

# 创建 Trace 跨度
span = TraceSpan(
    name="group_analysis",
    umo="qq_group",
    sender_name="QQGroup:123456789",
    message_outline="Daily analysis request"
)

# 记录不同阶段的操作
span.record("start", step="initialization")
span.record("process", data_count=1000)
span.record("end", result_code=200)

4.4 Trace 日志格式

发布到 LogBroker

{
  "type": "trace",
  "level": "TRACE",
  "time": 1697787296.123,
  "span_id": "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx",
  "name": "group_analysis",
  "umo": "qq_group",
  "sender_name": "QQGroup:123456789",
  "message_outline": "Daily analysis request",
  "action": "start",
  "fields": {"step": "initialization"}
}

写入文件JSON 格式,每行一条):

[2024-01-01 12:34:56] {"type":"trace","span_id":"...","name":"group_analysis",...}

4.5 Trace 查询方式

  1. Dashboard UI (/trace 路由)

    • 实时查看所有 Trace 事件
    • 可启用/禁用 Trace 记录
  2. 日志文件查询

    • 文件位置:data/logs/astrbot.trace.log
    • 使用 jq 或 Python 解析 NDJSON 格式
  3. span_id 查询 - 用于追踪单个请求

    grep "span_id.*abc123" data/logs/astrbot.trace.log
    

5. 日志访问方式总结

5.1 实时日志查看

方式 说明 适用场景
Dashboard Console 浏览器访问 http://localhost:6185/#/console 实时监控、界面友好
REST API SSE GET /api/live-logServer-Sent Events 集成第三方系统
文件直接查看 tail -f data/logs/astrbot.log 服务器终端查看

5.2 历史日志查看

方式 说明 命令/代码
Dashboard History GET /api/log-history 返回缓存的日志 返回最近 500 条
文件查询 日志文件存储在 data/logs/astrbot.log grep 或编辑器打开
日志分析 Python/shell 脚本处理日志文件 自定义分析

5.3 Trace 日志查看

方式 说明 对应 API
Dashboard Trace 实时追踪链路,浏览器访问 /trace SSE 推送
Trace 文件 data/logs/astrbot.trace.logNDJSON 格式) 离线分析
span_id 查询 按 span_id 追踪单个请求 grep 搜索

6. 插件/群分析日志集成示例

6.1 为群分析日志添加 Trace ID

对于"QQ 群日常分析插件"astrbot_plugin_qq_group_daily_analysis),可以这样集成日志追踪:

# main.py 或分析模块
from astrbot import logger
from astrbot.core.utils.trace import TraceSpan

class GroupAnalyzer:
    def analyze_group(self, group_id: str):
        # 创建追踪跨度
        span = TraceSpan(
            name="group_daily_analysis",
            umo="qq_group",
            sender_name=f"QQGroup:{group_id}",
            message_outline=f"Daily analysis for group {group_id}"
        )
        
        try:
            span.record("start", group_id=group_id)
            logger.info(f"[GroupAnalysis] Starting analysis for group: {group_id}")
            
            # 分析逻辑...
            data = self._fetch_messages(group_id)
            span.record("fetch_complete", message_count=len(data))
            
            # 处理数据...
            result = self._process_data(data)
            span.record("process_complete", result_code=200)
            
            logger.info(f"[GroupAnalysis] Analysis complete for {group_id}")
            return result
            
        except Exception as e:
            span.record("error", error_type=type(e).__name__, error_msg=str(e))
            logger.error(f"[GroupAnalysis] Error analyzing group {group_id}: {e}")
            raise

6.2 查询特定群的日志

在 Dashboard 中

  1. 打开 /console 页面
  2. 输入日志过滤器(或查看所有日志)
  3. 搜索 GroupAnalysis 或特定的 group_id

通过命令行

# 查找特定群的日志
grep "QQGroup:123456789" data/logs/astrbot.log

# 或查找 Trace 日志
grep "group_id.*123456789" data/logs/astrbot.trace.log

6.3 日志格式确保

在日志中需要包含:

  • 时间戳: 自动添加(格式 HH:MM:SS
  • 日志级别: DEBUG, INFO, WARNING, ERROR, CRITICAL
  • 来源标记: [Core] 或 [Plug]
  • 文件和行号: 自动添加
  • 消息内容: 手动添加

示例日志行

[12:34:56] [Plug] [INFO] [group_analyzer.py:145]: [GroupAnalysis] Analysis complete for QQGroup:123456789

7. LogManager 高级配置

7.1 配置日志级别

from astrbot.core import LogManager, logger

# 根据配置设置日志级别
config = {
    "log_level": "DEBUG",
    "log_file_enable": True,
    "log_file_path": "logs/astrbot.log",
    "log_file_max_mb": 50,
}

LogManager.configure_logger(logger, config)

7.2 配置 Trace 日志

# 启用 Trace 日志文件
config = {
    "trace_enable": True,
    "trace_log_enable": True,
    "trace_log_path": "logs/astrbot.trace.log",
    "trace_log_max_mb": 30,
}

LogManager.configure_trace_logger(config)

7.3 日志过滤器

LogManager 自动添加以下过滤器:

过滤器 功能 输出示例
PluginFilter 标记日志来源(Core/Plug [Core][Plug]
FileNameFilter 修改文件名格式 folder.filename
LevelNameFilter 4 字母缩写 DBUG, INFO, WARN, ERRO, CRIT
AstrBotVersionTagFilter 在 WARNING 及以上追加版本 [v4.14.4]

8. 日志配置管理

8.1 配置文件路径

  • 配置文件: data/cmd_config.json
  • 默认配置: astrbot/core/config/default.py
  • 编辑方式:
    1. 直接编辑 JSON 文件
    2. 通过 Dashboard 管理面板修改(未来功能)

8.2 配置更新

配置更改后,需要重启应用以生效(或通过 API 动态更新)。

8.3 环境变量支持

根目录自定义(可选):

export ASTRBOT_ROOT=/path/to/root
# 数据目录将为 /path/to/root/data

9. 代码示例汇总

9.1 获取日志记录器

from astrbot.core import logger

# 已配置的全局日志记录器
logger.info("Message")
logger.debug("Debug message")
logger.warning("Warning")
logger.error("Error")
logger.critical("Critical error")

9.2 创建自定义日志记录器

from astrbot.core import LogManager

# 获取命名日志记录器
plugin_logger = LogManager.GetLogger("my_plugin")
plugin_logger.info("Plugin message")

9.3 发起 Trace 追踪

from astrbot.core.utils.trace import TraceSpan

span = TraceSpan(
    name="custom_operation",
    umo="custom_type",
    sender_name="CustomOperator",
    message_outline="Operation description"
)

span.record("stage1", param1="value1")
span.record("stage2", param2="value2", status="success")

9.4 订阅日志流(自定义)

import asyncio
from astrbot.core import LogBroker

# 从 LogBroker 获取日志队列
log_broker = app.log_broker  # 从应用上下文获取

async def listen_logs():
    queue = log_broker.register()
    try:
        while True:
            log_entry = await queue.get()
            print(f"[{log_entry['level']}] {log_entry['data']}")
    finally:
        log_broker.unregister(queue)

# 运行监听器
asyncio.run(listen_logs())

10. 常见问题和最佳实践

10.1 为什么文件日志默认禁用?

  • 性能考虑(避免磁盘 I/O 开销)
  • 容器环境中不需要持久化
  • 大多数用户通过 Dashboard 查看日志

10.2 启用文件日志的步骤

  1. 编辑 data/cmd_config.json
    {
      "log_file_enable": true,
      "log_file_path": "logs/astrbot.log",
      "log_file_max_mb": 50
    }
    
  2. 重启 AstrBot 应用
  3. 日志将写入 data/logs/astrbot.log

10.3 日志级别选择

  • DEBUG: 开发调试,包含所有详细信息
  • INFO: 生产环境推荐,记录重要事件
  • WARNING: 只记录警告和错误
  • ERROR: 仅记录错误
  • CRITICAL: 仅记录严重错误

10.4 Trace ID 用于群分析追踪

对于"QQ 群日常分析"场景:

  • 每个群的分析请求都有唯一的 span_id
  • 可通过此 ID 追踪整个分析流程
  • 涉及多群并发时日志清晰分离

查询示例

# 查找 span_id 相关的所有日志
grep "span_id: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx" data/logs/astrbot.trace.log

10.5 性能考虑

  • 日志缓存: 最多 500 条,超出自动淘汰(先进先出)
  • SSE 连接: 断网自动重连,支持日志补发
  • 文件轮转: 单个文件超过 20MB(可配置)自动轮转

11. 相关文件速查表

功能 文件路径
日志核心逻辑 astrbot/core/log.py
日志管理器 astrbot/core/log.py (LogManager 类)
Trace 系统 astrbot/core/utils/trace.py
Dashboard API astrbot/dashboard/routes/log.py
默认配置 astrbot/core/config/default.py
路径工具 astrbot/core/utils/astrbot_path.py
Dashboard Console UI dashboard/src/views/ConsolePage.vue
日志显示器组件 dashboard/src/components/shared/ConsoleDisplayer.vue
Trace UI dashboard/src/views/TracePage.vue
公共 Store dashboard/src/stores/common.js

12. 总结

日志查看的完整流程

  1. 应用启动

    • LogBroker 初始化
    • LogQueueHandler 连接到日志记录器
  2. 日志产生

    • 应用或插件调用 logger.info() 等方法
    • LogQueueHandler 拦截日志记录
  3. 日志分发

    • LogBroker.publish() 添加到缓存
    • 分发给所有订阅者(Dashboard SSE、Trace 日志等)
  4. 用户查看

    • Dashboard Console: 实时看到日志
    • REST API: 获取历史日志或 SSE 流
    • 文件: 直接查看 data/logs/astrbot.log
  5. Trace 追踪

    • 创建 TraceSpan 记录请求链路
    • Dashboard /trace 实时查看
    • 或通过 span_id 在文件中查询

推荐使用方式

  • 开发调试: Dashboard /console 页面
  • 生产监控: 启用文件日志 + 日志收集系统
  • 问题诊断: 通过 span_id 追踪完整请求链路
  • 群分析: 在日志中包含 group_id,便于后续查询

本文档基于 AstrBot v4.14.4 代码分析生成。