feat: Add documentation for log quick reference and viewing research.

This commit is contained in:
SXP-Simon
2026-02-08 00:02:41 +08:00
parent 4477c8b862
commit 19a6214f17
2 changed files with 1134 additions and 0 deletions
+457
View File
@@ -0,0 +1,457 @@
# TraceID 日志增强指南 + AstrBot 日志查看
> **核心观点**`contextvars + logging.Filter` 方案是对 AstrBot logger 的增强,不是替换。日志仍通过 AstrBot 输出,只是自动注入 trace_id。
---
## 🔍 日志查看入口(三种方式)
### 1️⃣ 控制台输出(最简单,开发环境推荐)
**启动 AstrBot 后,直接在终端看日志**
```bash
python main.py
# 输出示例:
[10:30:45] [Plug] [INFO ] [group_daily:45]: [123456789-1707292800] 开始分析群
[10:30:46] [Plug] [INFO ] [group_daily:46]: [123456789-1707292800] 获取 256 条消息
[10:30:47] [Plug] [INFO ] [group_daily:47]: [123456789-1707292800] 话题分析完成
[10:30:48] [Plug] [ERROR] [group_daily:50]: [123456789-1707292800] LLM 超时
TraceID(自动注入)
```
**优点**
- ✅ 零配置,启动即可看
- ✅ 实时显示,彩色输出
- ✅ 容易识别错误
### 2️⃣ 日志文件(生产环境标配)
**在 `astrbot_config.yml` 中启用文件日志**
```yaml
log_file_enable: true
log_file_path: "logs/astrbot.log" # 日志文件路径
log_file_max_mb: 20 # 文件大小限制(轮转)
```
**查看方式**
```bash
# Linux/Mac 实时查看
tail -f logs/astrbot.log
# Windows PowerShell 实时查看
Get-Content -Path logs/astrbot.log -Wait
# 搜索特定群的所有日志
grep "123456789" logs/astrbot.log
# 查看最后 100 行
tail -100 logs/astrbot.log
```
**优点**
- ✅ 永久保存
- ✅ 支持搜索和分析
- ✅ 生产环境必须
### 3️⃣ AstrBot Dashboard(最舒服,Web 界面)
**方式 AAstrBot 内置 Dashboard(如果启用了)**
```
访问:http://localhost:8000
→ 日志 / Logs 菜单
→ 可看实时日志流
```
**方式 BAstrbot-dashboard 独立工具**
```bash
# 安装独立的 dashboard 包
pip install astrbot-dashboard
# 启动(连接本地 AstrBot
astrbot-dashboard
# 浏览器打开
# http://localhost:6185/#/console
```
**优点**
- ✅ Web 界面直观
- ✅ 实时流式显示
- ✅ 支持过滤和搜索
---
## ✅ 为什么使用 contextvars + logging.Filter
### 核心原因:**自动 TraceID 注入**
```
现状问题: 使用 contextvars 后:
────────────────────────────────────────────────────
logger.info("开始") logger.info("开始")
logger.info("获取消息") → logger.info("获取消息")
logger.error("超时") logger.error("超时")
输出: 输出:
[INFO] 开始 [trace_id:123] [INFO] 开始
[INFO] 获取消息 [trace_id:123] [INFO] 获取消息
[ERROR] 超时 [trace_id:123] [ERROR] 超时
❌ 100 个群并发时看不出 ✅ 清晰看出所有日志属于
谁的日志在哪里 同一个分析任务!
```
### 有没有利用 AstrBot 现有日志?
**完全利用了!** 这是在 AstrBot logger 上添加一层装饰器:
```
你的代码: logger.info("message")
[TraceIDFilter](新增)← 自动注入 trace_id
[AstrBot Logger](已有)
├─ ColoredFormatter
├─ StreamHandler(控制台)
└─ RotatingFileHandler(文件)
```
### 代码实现(简化版)
```python
# src/utils/trace.py
import contextvars
import logging
from astrbot.api import logger
# 全局 ContextVar
_trace_id: contextvars.ContextVar[str] = contextvars.ContextVar('trace_id', default='')
# 自定义 Filter
class TraceIDFilter(logging.Filter):
def filter(self, record):
record.trace_id = _trace_id.get('') or 'no-trace'
return True
# 注册到 AstrBot logger(在插件初始化时)
logger.addFilter(TraceIDFilter())
# 使用(在分析开始处)
async def analyze_group(group_id: str):
import time
# 设置 trace_id
_trace_id.set(f"{group_id}-{int(time.time())}")
try:
logger.info("开始分析") # 自动包含 trace_id
# ... 分析逻辑
finally:
_trace_id.set('') # 清理
```
### 输出效果
```bash
$ tail -f logs/astrbot.log | grep trace_id
[123456789-1707292800] [10:30:45] [Plug] [INFO ] [group_daily:45]: 开始分析群
[123456789-1707292800] [10:30:46] [Plug] [INFO ] [group_daily:46]: 获取 256 条消息
[123456789-1707292800] [10:30:47] [Plug] [INFO ] [group_daily:47]: 话题分析完成
[123456789-1707292800] [10:30:48] [Plug] [ERROR] [group_daily:50]: LLM 超时
```
---
## 🏗️ 架构流程图
```
┌─────────────────────────────────────────────────────────────┐
│ AstrBot 应用 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 核心组件/插件 │
│ │ │
│ ├─→ logger.info("message") │
│ └─→ logger.error("error") │
│ │
│ ▼ │
│ ┌──────────────────────────────────────┐ │
│ │ LogQueueHandler (日志处理器) │ │
│ │ 接收 logging.LogRecord │ │
│ └──────────────────────────────────────┘ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ LogBroker (日志代理) │ │
│ │ - log_cache: deque(maxlen=500) [环形缓冲区] │ │
│ │ - subscribers: List[Queue] [订阅者队列] │ │
│ │ │ │
│ │ publish(log_entry): │ │
│ │ 1. 添加到 log_cache │ │
│ │ 2. 分发给所有 subscribers │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ ├──────────────────┬─────────────────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌───────────────┐ ┌──────────────┐ │
│ │ Dashboard │ │ Trace Logger │ │ 其他订阅者 │ │
│ │ SSE 连接 │ │ (可选) │ │ (可选) │ │
│ │ (实时推送) │ │ (文件/内存) │ │ │ │
│ └─────────────┘ └───────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 数据输出 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. Dashboard UI (/:console) │
│ - 实时日志显示 │
│ - 级别过滤 │
│ │
│ 2. 日志文件 (可选) │
│ - data/logs/astrbot.log │
│ - data/logs/astrbot.trace.log │
│ │
│ 3. 浏览器 Memory │
│ - SSE 缓存 (断网重连补发) │
│ │
└─────────────────────────────────────────────────────────────┘
```
---
## 📁 文件位置速查
| 类型 | 位置 | 启用方式 |
|------|------|--------|
| **普通日志** | `data/logs/astrbot.log` | `log_file_enable: true` |
| **Trace 日志** | `data/logs/astrbot.trace.log` | `trace_log_enable: true` |
| **配置文件** | `data/cmd_config.json` | 直接编辑 |
| **数据目录** | `data/` | 环境变量 `ASTRBOT_ROOT` |
---
## 🔧 配置项清单
### 日志配置(最常用)
```json
{
"log_level": "INFO", // DEBUG|INFO|WARNING|ERROR|CRITICAL
"log_file_enable": false, // 启用文件日志
"log_file_path": "logs/astrbot.log", // 相对于 data/ 目录
"log_file_max_mb": 20, // 单个文件最大大小
"trace_enable": false, // 启用 Trace 记录
"trace_log_enable": false, // 启用 Trace 文件日志
"trace_log_path": "logs/astrbot.trace.log", // Trace 文件位置
"trace_log_max_mb": 20
}
```
---
## 💻 代码使用速查
### 记录日志(最常用)
```python
from astrbot.core import logger
logger.debug("Debug message")
logger.info("Info message")
logger.warning("Warning message")
logger.error("Error message")
logger.critical("Critical error")
```
### Trace 追踪(链路追踪)
```python
from astrbot.core.utils.trace import TraceSpan
span = TraceSpan(
name="operation_name",
sender_name="ComponentA",
message_outline="Brief description"
)
span.record("stage1", key1="value1")
span.record("stage2", key2="value2")
```
### 订阅日志流(高级)
```python
import asyncio
async def listen_logs(log_broker):
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)
```
---
## 🚀 常见操作
### ❓ 如何启用文件日志?
1. 打开 `data/cmd_config.json`
2. 修改:
```json
"log_file_enable": true,
"log_file_path": "logs/astrbot.log"
```
3. 重启应用
### ❓ 如何查看特定群的日志?
```bash
# 方式 1: Dashboard 中搜索 group_id
http://localhost:6185/#/console
# 方式 2: 命令行查询
grep "QQGroup:123456789" data/logs/astrbot.log
```
### ❓ 如何用 span_id 追踪完整请求?
```bash
# Trace 日志包含 span_id,可追踪单个请求的全生命周期
grep "span_id.*abc-123-def" data/logs/astrbot.trace.log
# 或在 Dashboard 的 /trace 页面实时查看
```
### ❓ 日志缓存大小是多少?
- **内存缓存**: 最近 500 条日志(deque with maxlen=500
- **Dashboard 前端缓存**: 最近 1000 条日志
- **文件日志**: 单个文件 20MB,自动轮转(3 个备份)
### ❓ 日志是否会自动删除?
- **内存缓存**: 自动淘汰(先进先出,保持最近 500 条)
- **文件日志**: 不自动删除,需手动管理或配置轮转
- **Dashboard 前端**: 页面关闭后清空
---
## 📊 日志格式示例
### Console 日志输出
```
[12:34:56] [Core] [INFO] [astrbot.py:123]: Application started successfully
[12:34:57] [Plug] [WARN] [plugin.py:45]: Missing dependency: requests
[12:35:00] [Core] [ERRO] [error.py:78]: Connection timeout to server [v4.14.4]
```
格式:`[时间] [来源] [级别] [文件:行号]: 消息`
### Trace JSON 日志
```json
[2024-01-01 12:34:56] {"type":"trace","span_id":"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx","name":"group_analysis","sender_name":"QQGroup:123456789","action":"start","fields":{"group_id":"123456789","step":"initialization"}}
```
---
## 🎨 日志级别和颜色
| 级别 | 缩写 | 颜色 | 含义 |
|------|------|------|------|
| DEBUG | DBUG | 🟢 绿色 | 调试信息 |
| INFO | INFO | 🔵 青色 | 一般信息 |
| WARNING | WARN | 🟡 黄色 | 警告信息 |
| ERROR | ERRO | 🔴 红色 | 错误信息 |
| CRITICAL | CRIT | 🟣 紫色 | 严重错误 |
---
## 📈 性能指标
| 项目 | 值 | 说明 |
|------|-----|------|
| 日志缓存大小 | 500 条 | 环形缓冲区 |
| Dashboard 前端缓存 | 1000 条 | 浏览器内存 |
| SSE 队列大小 | 510 条 | maxsize = CACHED_SIZE + 10 |
| 日志文件大小 | 20MB | 单个文件,可配置 |
| 备份文件数 | 3 个 | 自动轮转 |
| SSE 连接超时 | None | 永不超时 |
---
## 🔐 安全相关
### 日志中的敏感信息
```python
# ❌ 不要直接记录密钥
logger.info(f"API key: {api_key}")
# ✅ 使用脱敏
logger.info(f"API key: {api_key[:8]}...")
# ✅ 或使用占位符
logger.info(f"Using API key: ***")
```
### Dashboard 访问认证
- 默认用户名:`astrbot`
- 默认密码:(MD5 哈希,需在配置中修改)
- JWT Token:用于 API 认证
---
## 🔗 相关链接
| 资源 | 位置 |
|------|------|
| 完整文档 | `LOG_VIEWING_RESEARCH.md` |
| 日志实现 | `astrbot/core/log.py` |
| Trace 系统 | `astrbot/core/utils/trace.py` |
| Dashboard API | `astrbot/dashboard/routes/log.py` |
| 前端组件 | `dashboard/src/components/shared/ConsoleDisplayer.vue` |
| 默认配置 | `astrbot/core/config/default.py` |
---
## ✅ 检查清单
### 开发调试
- [ ] Dashboard 可以实时看到日志
- [ ] 日志级别设置为 DEBUG
- [ ] Trace 追踪已启用(if needed
### 生产部署
- [ ] 日志级别设置为 INFO
- [ ] 文件日志已启用(for persistence
- [ ] 日志轮转已配置
- [ ] 监控系统已连接
### 问题诊断
- [ ] 日志中包含 span_idfor tracing
- [ ] 时间戳正确(for correlation
- [ ] 日志级别适当(not too verbose
---
*最后更新:2024年 | AstrBot v4.14.4*
+677
View File
@@ -0,0 +1,677 @@
# AstrBot 日志查看方式研究报告
## 概述
本文档详细说明了 AstrBot 的日志系统架构、查看方式、以及如何在代码中集成日志查看功能。
---
## 1. 日志文件默认位置
### 1.1 日志文件存储位置
根据配置,AstrBot 的日志文件存储在以下位置:
| 日志类型 | 默认位置 | 配置键 | 说明 |
|---------|--------|-------|------|
| **普通日志** | `data/logs/astrbot.log` | `log_file_path` | 主应用日志,记录应用运行信息 |
| **Trace 日志** | `data/logs/astrbot.trace.log` | `trace_log_path` | 链路追踪日志,记录请求跨度信息 |
### 1.2 日志文件配置参数
```python
# 配置文件位置: 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 代码):
```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`):
```javascript
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 对象结构:
```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](dashboard/src/views/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](dashboard/src/views/TracePage.vue)
功能:
- ✅ 实时链路追踪显示
- ✅ Trace 启用/禁用开关
- ✅ Trace 事件详细信息展示
#### 日志显示器组件
**组件**: [ConsoleDisplayer.vue](dashboard/src/components/shared/ConsoleDisplayer.vue)
特性:
- 日志级别色彩标记
- ANSI 颜色代码转换为 HTML 样式
- 日志缓存最多保留 1000 条(configurable
- 自动滚动到最新日志
---
## 3. LogBroker 架构(发布-订阅模式)
### 3.1 LogBroker 类设计
**位置**: `astrbot/core/log.py`
```python
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 日志项结构
```python
log_entry = {
"level": "INFO", # 日志级别
"time": 1697787296.123, # Unix 时间戳
"data": "Log message text", # 格式化的日志文本
}
```
### 3.4 在代码中集成 LogBroker
#### 启动应用时初始化
```python
# 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 中使用
```python
# 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 启用配置
**配置项**
```python
"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`
```python
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**
```json
{
"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 格式,每行一条):
```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 查询** - 用于追踪单个请求
```bash
grep "span_id.*abc123" data/logs/astrbot.trace.log
```
---
## 5. 日志访问方式总结
### 5.1 实时日志查看
| 方式 | 说明 | 适用场景 |
|------|------|---------|
| **Dashboard Console** | 浏览器访问 `http://localhost:6185/#/console` | 实时监控、界面友好 |
| **REST API SSE** | `GET /api/live-log`Server-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.log`NDJSON 格式) | 离线分析 |
| **span_id 查询** | 按 span_id 追踪单个请求 | `grep` 搜索 |
---
## 6. 插件/群分析日志集成示例
### 6.1 为群分析日志添加 Trace ID
对于"QQ 群日常分析插件"`astrbot_plugin_qq_group_daily_analysis`),可以这样集成日志追踪:
```python
# 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
**通过命令行**
```bash
# 查找特定群的日志
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 配置日志级别
```python
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 日志
```python
# 启用 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 环境变量支持
**根目录自定义**(可选):
```bash
export ASTRBOT_ROOT=/path/to/root
# 数据目录将为 /path/to/root/data
```
---
## 9. 代码示例汇总
### 9.1 获取日志记录器
```python
from astrbot.core import logger
# 已配置的全局日志记录器
logger.info("Message")
logger.debug("Debug message")
logger.warning("Warning")
logger.error("Error")
logger.critical("Critical error")
```
### 9.2 创建自定义日志记录器
```python
from astrbot.core import LogManager
# 获取命名日志记录器
plugin_logger = LogManager.GetLogger("my_plugin")
plugin_logger.info("Plugin message")
```
### 9.3 发起 Trace 追踪
```python
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 订阅日志流(自定义)
```python
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`
```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 追踪整个分析流程
- 涉及多群并发时日志清晰分离
**查询示例**
```bash
# 查找 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 代码分析生成。*