前后端统一日志系统 + MCP Server 设计方案
创建日期:2026-05-11
状态:设计完成,待实施
Context
问题:
- 前端没有统一日志系统,只有散落的
console.*调用(约26个文件),没有全局错误边界,没有错误上报能力
- 后端有完善的日志封装(
pkg/logger/),但前后端日志完全割裂,无法通过traceID串联
- Claude Code无法直接访问项目日志,调试时需要手动查看终端或日志文件
目标:
- 创建前端统一logger模块,与后端日志格式对齐
- 前端日志上报到后端,写入同一日志文件
- 创建MCP Server,让Claude Code能实时查看和过滤日志
一、整体架构
Browser (Vue 3 App) Go Backend (lina-core)
+---------------------+ +---------------------------+
| Frontend Logger | -- POST /api/v1/ | Log Receive API |
| (packages/effects/ | logs/batch --> | (api/log + controller) |
| logger/) | | |
| | | Backend Logger |
| - debug/info/warn/ | | (pkg/logger/) |
| error | | - glog wrapper |
| - structured JSON | | - structured + traceID |
| - traceID from resp| | |
| - batch buffer + | | Log Files (disk) |
| periodic flush | | {Y-m-d}.log |
+---------------------+ +---------------------------+
|
v
+---------------------------+
| MCP Server |
| (hack/tools/log-mcp/) |
| |
| Tools: |
| - list_logs |
| - tail_logs (SSE/stream) |
| - filter_logs |
| - get_log_stats |
| |
| Sources: |
| - Backend log files |
| - Frontend log buffer |
| (via API query) |
+---------------------------+
|
v
Claude Code (MCP Client)
数据流
[前端] Logger.info("message")
↓ 内存缓冲
[前端] LogTransport.flush()
↓ POST /api/v1/logs/batch
[后端] LogController.Batch()
↓ logger.Infof(ctx, "[FRONTEND] [info] message")
[后端] GoFrame glog → 写入日志文件
↑ 读取
[MCP Server] logreader → 过滤/解析
↓ stdio
[Claude Code] 查看日志
二、TraceID 传递机制
[Backend generates TraceID]
|
v
GoFrame HTTP middleware adds TraceID to context
|
v
Response middleware adds X-Trace-Id header to every HTTP response
|
v
Frontend Axios response interceptor extracts X-Trace-Id
|
v
Frontend Logger stores currentTraceId (module-level)
|
v
Every LogEntry includes traceId field
|
v
POST /api/v1/logs/batch sends traceId to backend
|
v
Backend log handler writes [FRONTEND] log with traceId
|
v
MCP server can filter all logs (backend + frontend) by the same traceId
2.1 后端:暴露TraceID响应头
修改文件:apps/lina-core/internal/service/middleware/middleware_response.go
在Response方法中,r.Response.WriteJson(response)之前添加:
// Expose traceID in response header for frontend correlation
if traceID := r.GetTraceId(); traceID != "" {
r.Response.Header().Set("X-Trace-Id", traceID)
}
GoFrame的r.GetTraceId()在请求上下文中自动注入traceID(当logger.extensions.traceIDEnabled: true时)。
2.2 前端:提取并存储TraceID
在apps/web-antd/src/api/request.ts添加响应拦截器:
let currentTraceId: string | undefined;
client.addResponseInterceptor({
fulfilled: (response) => {
const traceId = response.headers?.['x-trace-id'];
if (traceId) {
currentTraceId = traceId;
}
return response;
},
});
export function getCurrentTraceId() { return currentTraceId; }
2.3 配置开关
TraceID传播遵循现有的logger.extensions.traceIDEnabled配置。禁用时后端不生成traceID,前端logger无traceID运行。
三、后端日志接收API
3.1 API定义
新建文件:apps/lina-core/api/log/v1/log_batch.go
package v1
import "github.com/gogf/gf/v2/frame/g"
// BatchReq accepts a batch of frontend log entries for ingestion.
type BatchReq struct {
g.Meta `path:"/logs/batch" method:"post" tags:"Log Management" summary:"Ingest frontend log batch" dc:"Accepts a batch of frontend browser log entries for unified server-side storage and observability."`
Entries []LogEntry `json:"entries" dc:"Array of frontend log entries" eg:"[{\"level\":\"info\",\"message\":\"test\"}]"`
}
// LogEntry represents a single frontend log record.
type LogEntry struct {
Level string `json:"level" dc:"Log level: debug, info, warn, error" eg:"info"`
Message string `json:"message" dc:"Log message content" eg:"user login succeeded"`
TraceId string `json:"traceId,omitempty" dc:"Request trace ID from backend response header" eg:"abc123"`
Module string `json:"module,omitempty" dc:"Frontend module name" eg:"auth"`
Timestamp string `json:"timestamp" dc:"ISO 8601 timestamp" eg:"2026-05-11T10:30:00Z"`
Context map[string]interface{} `json:"context,omitempty" dc:"Additional structured context fields"`
Stack string `json:"stack,omitempty" dc:"Error stack trace if applicable"`
}
// BatchRes confirms log ingestion.
type BatchRes struct {
Accepted int `json:"accepted" dc:"Number of entries accepted" eg:"5"`
}
3.2 Controller
新建文件:apps/lina-core/internal/controller/log/log_new.go
package log
import logapi "lina-core/api/log"
// ControllerV1 handles frontend log ingestion.
type ControllerV1 struct{}
// NewV1 creates a log controller instance.
func NewV1() logapi.IV1 {
return &ControllerV1{}
}
新建文件:apps/lina-core/internal/controller/log/log_v1_batch.go
Controller逻辑:
- 遍历entries,用
logger.Infof(ctx, "[FRONTEND] [%s] %s %v", level, message, context)写入
- 带traceID的entry会自动被GoFrame日志系统捕获
- 返回accepted数量
3.3 路由注册
修改文件:apps/lina-core/internal/cmd/cmd_http_routes.go
在bindPublicStaticAPIRoutes调用中添加logCtrl.Batch(公开路由,无需认证):
logCtrl := logctrl.NewV1()
bindPublicStaticAPIRoutes(
group,
healthCtrl.Get,
authCtrl.Login,
logCtrl.Batch, // 新增
i18nCtrl.RuntimeLocales,
// ...
)
公开路由的原因:前端可能在认证失败时也需要上报日志。
3.4 日志格式
前端日志写入后端日志文件时使用[FRONTEND]前缀标记。结构化JSON模式下的示例:
{
"time": "2026-05-11T10:30:00+08:00",
"level": "INFO",
"content": "[FRONTEND] [info] user login succeeded",
"traceId": "abc123",
"caller": "log/log_v1_batch.go:45"
}
3.5 配置
修改文件:apps/lina-core/manifest/config/config.yaml
# Frontend log ingestion configuration
logIngest:
# Whether to accept frontend log entries
enabled: true
# Maximum entries per batch request
maxBatchSize: 100
# Rate limit: max batches per minute per IP
rateLimit: 60
四、前端Logger模块
4.1 文件位置
apps/lina-vben/packages/effects/logger/
与request、hooks等高层effects模块位置一致。
packages/effects/logger/
package.json
src/
index.ts # 公开API导出
logger.ts # Logger类
types.ts # 类型定义
transport.ts # 批量缓冲 + 定时上报
trace.ts # traceID提取
4.2 类型定义
// types.ts
export enum LogLevel {
DEBUG = 'debug',
INFO = 'info',
WARN = 'warn',
ERROR = 'error',
}
export interface LogEntry {
level: LogLevel;
message: string;
timestamp: string; // ISO 8601
traceId?: string;
source: 'frontend';
module?: string; // caller module name, e.g. 'user', 'auth'
context?: Record<string, unknown>;
stack?: string; // error stack trace when applicable
}
export interface LoggerConfig {
level: LogLevel; // minimum level to emit
enableConsole: boolean; // mirror to console in dev
enableTransport: boolean; // send to backend
bufferSize: number; // max entries before forced flush
flushInterval: number; // ms between periodic flushes
endpoint: string; // backend API path
}
4.3 Logger类
// logger.ts
class Logger {
constructor(config?: Partial<LoggerConfig>)
// 包级风格API,对齐后端模式
debug(message: string, context?: Record<string, unknown>): void
info(message: string, context?: Record<string, unknown>): void
warn(message: string, context?: Record<string, unknown>): void
error(message: string, context?: Record<string, unknown>): void
// 格式化版本(对齐后端 Infof/Warningf 风格)
debugf(format: string, ...args: unknown[]): void
infof(format: string, ...args: unknown[]): void
warnf(format: string, ...args: unknown[]): void
errorf(format: string, ...args: unknown[]): void
// 模块级子logger
child(module: string): Logger
// 立即刷新待发送条目
flush(): Promise<void>
// 手动设置traceID(通常自动提取)
setTraceId(traceId: string): void
}
export function createLogger(config?: Partial<LoggerConfig>): Logger
使用示例:
import { createLogger } from '@vben/logger';
const logger = createLogger({ level: LogLevel.DEBUG });
// 简单用法
logger.info('user login succeeded', { username: 'admin', ip: '127.0.0.1' });
// 格式化用法
logger.infof('user login succeeded username=%s ip=%s', 'admin', '127.0.0.1');
// 模块级子logger
const authLogger = logger.child('auth');
authLogger.warn('token about to expire', { userId: 123, expiresIn: '5m' });
// 错误带堆栈
try {
// ...
} catch (err) {
logger.error('request failed', { url: '/api/v1/user', error: err });
}
4.4 Transport
// transport.ts
class LogTransport {
private buffer: LogEntry[] = [];
private flushTimer: ReturnType<typeof setInterval> | null = null;
constructor(config: LoggerConfig)
// 添加到缓冲区;缓冲区满时触发flush
enqueue(entry: LogEntry): void
// POST缓冲条目到后端,清空缓冲区
async flush(): Promise<void>
// 启动定时flush
start(): void
// 停止定时器,flush剩余
stop(): Promise<void>
}
- 内存缓冲,达到
bufferSize(默认50条)或定时(默认30秒)触发flush
- POST到
/api/v1/logs/batch
- 页面卸载时用
navigator.sendBeacon兜底
4.5 TraceID提取
// trace.ts
export function extractTraceId(headers: Record<string, string>): string | undefined {
return headers['x-trace-id'] || headers['X-Trace-Id'] || undefined;
}
4.6 package.json
{
"name": "@vben/logger",
"version": "5.6.0",
"type": "module",
"sideEffects": ["**/*.css"],
"exports": {
".": {
"types": "./src/index.ts",
"default": "./src/index.ts"
}
},
"dependencies": {
"@vben/request": "workspace:*"
}
}
五、前端集成
5.1 bootstrap.ts 安装全局错误处理
修改文件:apps/lina-vben/apps/web-antd/src/bootstrap.ts
在createApp(App)之后添加:
import { createLogger } from '@vben/logger';
const logger = createLogger({ level: 'info' });
// Vue全局错误处理器
app.config.errorHandler = (err, instance, info) => {
logger.error('uncaught vue error', {
error: err instanceof Error ? err.message : String(err),
stack: err instanceof Error ? err.stack : undefined,
componentInfo: info,
});
};
// 未处理的Promise rejection
window.addEventListener('unhandledrejection', (event) => {
logger.error('unhandled promise rejection', {
reason: event.reason?.message || String(event.reason),
});
});
5.2 迁移console调用
将26个文件中的console.log/warn/error替换为logger调用:
// Before
console.error('component adapter not found:', name);
// After
import { logger } from '#/logger';
logger.error('component adapter not found', { name });
关键文件:
src/api/request.ts
src/adapter/component/index.ts
src/components/upload/src/hook.ts
src/plugins/access-filter.ts
src/plugins/slot-registry.ts
- 多个
views/system/下的组件
六、MCP Server
6.1 技术选型:Go
理由:
- 项目Go-first,所有后端工具都在Go(
hack/tools/)
- MCP Go SDK成熟(
github.com/mark3labs/mcp-go)
- 需要读取GoFrame日志文件,Go处理文件系统自然
- 可以添加到现有
go.work工作区
- 独立二进制,无需Node.js依赖
6.2 文件位置
hack/tools/log-mcp/
main.go # MCP server入口
server.go # MCP server配置和工具注册
tool_logs.go # list_logs, filter_logs工具实现
tool_tail.go # tail_logs工具实现
tool_stats.go # get_log_stats工具实现
logreader.go # 日志文件发现、解析、过滤
config.go # 配置
go.mod
go.sum
添加到go.work:
use (
// ...existing...
./hack/tools/log-mcp
)
6.3 配置
hack/tools/log-mcp/config.yaml:
logMcp:
# 后端日志文件目录(与主配置的logger.path相同)
backendLogPath: ""
# 后端日志文件模式
backendLogFile: "{Y-m-d}.log"
# LinaPro后端API地址(查询前端日志)
backendApiUrl: "http://localhost:8080"
# 单次查询最大返回行数
maxLines: 1000
# Tail轮询间隔
tailInterval: "2s"
6.4 MCP工具定义
Tool 1: list_logs
列出可用日志文件。
{
"name": "list_logs",
"description": "List available log files from backend and frontend sources",
"inputSchema": {
"type": "object",
"properties": {
"source": {
"type": "string",
"enum": ["backend", "frontend", "all"],
"description": "Which log source to list",
"default": "all"
},
"date": {
"type": "string",
"description": "Filter by date (YYYY-MM-DD), defaults to today"
}
}
}
}
返回:[{ filename, source, date, size, lineCount }]
Tool 2: filter_logs
查询和过滤历史日志。
{
"name": "filter_logs",
"description": "Query and filter log entries from backend or frontend logs",
"inputSchema": {
"type": "object",
"properties": {
"source": { "type": "string", "enum": ["backend", "frontend", "all"], "default": "all" },
"level": { "type": "string", "enum": ["debug", "info", "warn", "error", "all"], "default": "all" },
"keyword": { "type": "string", "description": "Search keyword (case-insensitive)" },
"traceId": { "type": "string", "description": "Filter by specific trace ID" },
"module": { "type": "string", "description": "Filter by frontend module name" },
"since": { "type": "string", "description": "Start time (ISO 8601 or relative like '1h', '30m')" },
"until": { "type": "string", "description": "End time (ISO 8601)" },
"limit": { "type": "number", "description": "Max entries to return (default 100, max 1000)", "default": 100 }
}
}
}
返回:匹配的日志条目数组。
Tool 3: tail_logs
实时日志跟踪(tail -f模式)。
{
"name": "tail_logs",
"description": "Stream new log entries in real-time (tail -f mode)",
"inputSchema": {
"type": "object",
"properties": {
"source": { "type": "string", "enum": ["backend", "frontend", "all"], "default": "all" },
"level": { "type": "string", "enum": ["debug", "info", "warn", "error", "all"], "default": "all" },
"keyword": { "type": "string", "description": "Only show lines containing this keyword" },
"follow": { "type": "boolean", "description": "true to start streaming, false to stop", "default": true }
}
}
}
实现:MCP server维护tail状态,follow=true时启动goroutine轮询文件末尾,follow=false时停止。
Tool 4: get_log_stats
日志统计。
{
"name": "get_log_stats",
"description": "Get log statistics: entry counts by level, error rate, recent error summary",
"inputSchema": {
"type": "object",
"properties": {
"source": { "type": "string", "enum": ["backend", "frontend", "all"], "default": "all" },
"since": { "type": "string", "description": "Start time for stats (default: last 1 hour)" }
}
}
}
返回:{ total, byLevel: {debug, info, warn, error}, recentErrors: [...], topModules: [...] }
6.5 日志文件读取
logreader.go负责:
- 扫描日志目录,发现
{Y-m-d}.log文件
- 解析文本格式(
2026-05-11 10:30:00.000 [INFO] content {trace-id})和JSON格式
- 按级别、关键词、traceID、时间范围过滤
- 文件末尾跟踪(
os.File.Seek + 轮询)
- 检测文件轮换(新一天、文件重命名)
6.6 Claude Code集成
在.claude/settings.json中配置:
{
"mcpServers": {
"lina-logs": {
"command": "go",
"args": ["run", ".", "--log-path", "./temp/logs"],
"cwd": "hack/tools/log-mcp"
}
}
}
七、关键文件清单
新建文件
| 文件 |
说明 |
apps/lina-vben/packages/effects/logger/package.json |
前端logger包配置 |
apps/lina-vben/packages/effects/logger/src/index.ts |
公开API导出 |
apps/lina-vben/packages/effects/logger/src/logger.ts |
Logger类实现 |
apps/lina-vben/packages/effects/logger/src/types.ts |
类型定义 |
apps/lina-vben/packages/effects/logger/src/transport.ts |
批量缓冲上报 |
apps/lina-vben/packages/effects/logger/src/trace.ts |
traceID提取 |
apps/lina-core/api/log/v1/log_batch.go |
日志接收API DTO |
apps/lina-core/internal/controller/log/log_new.go |
Controller构造函数 |
apps/lina-core/internal/controller/log/log_v1_batch.go |
批量接收实现 |
hack/tools/log-mcp/main.go |
MCP server入口 |
hack/tools/log-mcp/server.go |
MCP server配置 |
hack/tools/log-mcp/tool_logs.go |
list/filter工具 |
hack/tools/log-mcp/tool_tail.go |
tail工具 |
hack/tools/log-mcp/tool_stats.go |
统计工具 |
hack/tools/log-mcp/logreader.go |
日志文件读取 |
hack/tools/log-mcp/config.go |
配置 |
hack/tools/log-mcp/go.mod |
Go模块定义 |
修改文件
| 文件 |
修改内容 |
apps/lina-core/internal/service/middleware/middleware_response.go |
添加X-Trace-Id响应头 |
apps/lina-core/internal/cmd/cmd_http_routes.go |
注册log controller路由 |
apps/lina-core/manifest/config/config.yaml |
添加logIngest配置段 |
apps/lina-vben/apps/web-antd/src/api/request.ts |
添加traceID拦截器 |
apps/lina-vben/apps/web-antd/src/bootstrap.ts |
安装全局错误处理器 |
apps/lina-vben/apps/web-antd/package.json |
添加@vben/logger依赖 |
go.work |
添加log-mcp模块 |
| 26个console.*文件 |
迁移到logger |
八、实现步骤
Phase 1: 后端 - TraceID 响应头暴露(1-2小时)
- 修改
middleware_response.go设置X-Trace-Id响应头
- curl验证响应头包含
X-Trace-Id
- 编写单元测试
Phase 2: 后端 - 日志接收API(2-3小时)
- 创建
api/log/ DTO文件
- 实现
controller/log/批量接收
- 在
cmd_http_routes.go注册路由(公开组)
- 添加
logIngest配置段
- 编写单元测试
- 运行
make ctrl生成骨架
Phase 3: 前端 - Logger模块(3-4小时)
- 创建
packages/effects/logger/包结构
- 实现Logger类(级别过滤、子logger、格式化输出)
- 实现LogTransport(批量缓冲、定时flush、sendBeacon兜底)
- 实现trace.ts
- 编写单元测试
- 发布为
@vben/logger workspace包
Phase 4: 前端 - 集成(2-3小时)
- 添加
@vben/logger依赖到apps/web-antd/package.json
- 修改
request.ts添加traceID响应拦截器
- 修改
bootstrap.ts创建全局logger实例并安装错误处理器
- 迁移26个
console.*调用到logger
- 配置transport POST到
/api/v1/logs/batch
Phase 5: MCP Server(4-5小时)
- 创建
hack/tools/log-mcp/ Go模块
- 实现
logreader.go:文件发现、文本/JSON解析、过滤、跟踪
- 实现
tool_logs.go:list_logs和filter_logs
- 实现
tool_tail.go:tail_logs(follow/unfollow)
- 实现
tool_stats.go:get_log_stats聚合
- 实现
server.go:MCP server设置、工具注册、stdio传输
- 添加到
go.work
- 测试Claude Code MCP客户端
- 编写README文档
九、验证方式
| Phase |
验证方法 |
| Phase 1 |
curl -v http://localhost:8080/api/v1/health 检查响应头包含X-Trace-Id |
| Phase 2 |
curl -X POST http://localhost:8080/api/v1/logs/batch -d '{"entries":[{"level":"info","message":"test"}]}' 返回accepted=1,日志文件包含[FRONTEND] |
| Phase 3 |
前端代码import { createLogger } from '@vben/logger',调用logger.info('test'),Network面板有请求 |
| Phase 4 |
触发前端错误,全局错误处理器捕获并上报 |
| Phase 5 |
启动MCP server,Claude Code调用list_logs、filter_logs、tail_logs工具 |
本方案遵循LinaPro项目的SDD开发流程,实施前建议先创建OpenSpec变更提案。
前后端统一日志系统 + MCP Server 设计方案
Context
问题:
console.*调用(约26个文件),没有全局错误边界,没有错误上报能力pkg/logger/),但前后端日志完全割裂,无法通过traceID串联目标:
一、整体架构
数据流
二、TraceID 传递机制
2.1 后端:暴露TraceID响应头
修改文件:
apps/lina-core/internal/service/middleware/middleware_response.go在
Response方法中,r.Response.WriteJson(response)之前添加:GoFrame的
r.GetTraceId()在请求上下文中自动注入traceID(当logger.extensions.traceIDEnabled: true时)。2.2 前端:提取并存储TraceID
在
apps/web-antd/src/api/request.ts添加响应拦截器:2.3 配置开关
TraceID传播遵循现有的
logger.extensions.traceIDEnabled配置。禁用时后端不生成traceID,前端logger无traceID运行。三、后端日志接收API
3.1 API定义
新建文件:
apps/lina-core/api/log/v1/log_batch.go3.2 Controller
新建文件:
apps/lina-core/internal/controller/log/log_new.go新建文件:
apps/lina-core/internal/controller/log/log_v1_batch.goController逻辑:
logger.Infof(ctx, "[FRONTEND] [%s] %s %v", level, message, context)写入3.3 路由注册
修改文件:
apps/lina-core/internal/cmd/cmd_http_routes.go在
bindPublicStaticAPIRoutes调用中添加logCtrl.Batch(公开路由,无需认证):公开路由的原因:前端可能在认证失败时也需要上报日志。
3.4 日志格式
前端日志写入后端日志文件时使用
[FRONTEND]前缀标记。结构化JSON模式下的示例:{ "time": "2026-05-11T10:30:00+08:00", "level": "INFO", "content": "[FRONTEND] [info] user login succeeded", "traceId": "abc123", "caller": "log/log_v1_batch.go:45" }3.5 配置
修改文件:
apps/lina-core/manifest/config/config.yaml四、前端Logger模块
4.1 文件位置
apps/lina-vben/packages/effects/logger/与
request、hooks等高层effects模块位置一致。4.2 类型定义
4.3 Logger类
使用示例:
4.4 Transport
bufferSize(默认50条)或定时(默认30秒)触发flush/api/v1/logs/batchnavigator.sendBeacon兜底4.5 TraceID提取
4.6 package.json
{ "name": "@vben/logger", "version": "5.6.0", "type": "module", "sideEffects": ["**/*.css"], "exports": { ".": { "types": "./src/index.ts", "default": "./src/index.ts" } }, "dependencies": { "@vben/request": "workspace:*" } }五、前端集成
5.1 bootstrap.ts 安装全局错误处理
修改文件:
apps/lina-vben/apps/web-antd/src/bootstrap.ts在
createApp(App)之后添加:5.2 迁移console调用
将26个文件中的
console.log/warn/error替换为logger调用:关键文件:
src/api/request.tssrc/adapter/component/index.tssrc/components/upload/src/hook.tssrc/plugins/access-filter.tssrc/plugins/slot-registry.tsviews/system/下的组件六、MCP Server
6.1 技术选型:Go
理由:
hack/tools/)github.com/mark3labs/mcp-go)go.work工作区6.2 文件位置
添加到
go.work:6.3 配置
hack/tools/log-mcp/config.yaml:
6.4 MCP工具定义
Tool 1:
list_logs列出可用日志文件。
{ "name": "list_logs", "description": "List available log files from backend and frontend sources", "inputSchema": { "type": "object", "properties": { "source": { "type": "string", "enum": ["backend", "frontend", "all"], "description": "Which log source to list", "default": "all" }, "date": { "type": "string", "description": "Filter by date (YYYY-MM-DD), defaults to today" } } } }返回:
[{ filename, source, date, size, lineCount }]Tool 2:
filter_logs查询和过滤历史日志。
{ "name": "filter_logs", "description": "Query and filter log entries from backend or frontend logs", "inputSchema": { "type": "object", "properties": { "source": { "type": "string", "enum": ["backend", "frontend", "all"], "default": "all" }, "level": { "type": "string", "enum": ["debug", "info", "warn", "error", "all"], "default": "all" }, "keyword": { "type": "string", "description": "Search keyword (case-insensitive)" }, "traceId": { "type": "string", "description": "Filter by specific trace ID" }, "module": { "type": "string", "description": "Filter by frontend module name" }, "since": { "type": "string", "description": "Start time (ISO 8601 or relative like '1h', '30m')" }, "until": { "type": "string", "description": "End time (ISO 8601)" }, "limit": { "type": "number", "description": "Max entries to return (default 100, max 1000)", "default": 100 } } } }返回:匹配的日志条目数组。
Tool 3:
tail_logs实时日志跟踪(tail -f模式)。
{ "name": "tail_logs", "description": "Stream new log entries in real-time (tail -f mode)", "inputSchema": { "type": "object", "properties": { "source": { "type": "string", "enum": ["backend", "frontend", "all"], "default": "all" }, "level": { "type": "string", "enum": ["debug", "info", "warn", "error", "all"], "default": "all" }, "keyword": { "type": "string", "description": "Only show lines containing this keyword" }, "follow": { "type": "boolean", "description": "true to start streaming, false to stop", "default": true } } } }实现:MCP server维护tail状态,
follow=true时启动goroutine轮询文件末尾,follow=false时停止。Tool 4:
get_log_stats日志统计。
{ "name": "get_log_stats", "description": "Get log statistics: entry counts by level, error rate, recent error summary", "inputSchema": { "type": "object", "properties": { "source": { "type": "string", "enum": ["backend", "frontend", "all"], "default": "all" }, "since": { "type": "string", "description": "Start time for stats (default: last 1 hour)" } } } }返回:
{ total, byLevel: {debug, info, warn, error}, recentErrors: [...], topModules: [...] }6.5 日志文件读取
logreader.go负责:{Y-m-d}.log文件2026-05-11 10:30:00.000 [INFO] content {trace-id})和JSON格式os.File.Seek+ 轮询)6.6 Claude Code集成
在
.claude/settings.json中配置:{ "mcpServers": { "lina-logs": { "command": "go", "args": ["run", ".", "--log-path", "./temp/logs"], "cwd": "hack/tools/log-mcp" } } }七、关键文件清单
新建文件
apps/lina-vben/packages/effects/logger/package.jsonapps/lina-vben/packages/effects/logger/src/index.tsapps/lina-vben/packages/effects/logger/src/logger.tsapps/lina-vben/packages/effects/logger/src/types.tsapps/lina-vben/packages/effects/logger/src/transport.tsapps/lina-vben/packages/effects/logger/src/trace.tsapps/lina-core/api/log/v1/log_batch.goapps/lina-core/internal/controller/log/log_new.goapps/lina-core/internal/controller/log/log_v1_batch.gohack/tools/log-mcp/main.gohack/tools/log-mcp/server.gohack/tools/log-mcp/tool_logs.gohack/tools/log-mcp/tool_tail.gohack/tools/log-mcp/tool_stats.gohack/tools/log-mcp/logreader.gohack/tools/log-mcp/config.gohack/tools/log-mcp/go.mod修改文件
apps/lina-core/internal/service/middleware/middleware_response.goapps/lina-core/internal/cmd/cmd_http_routes.goapps/lina-core/manifest/config/config.yamlapps/lina-vben/apps/web-antd/src/api/request.tsapps/lina-vben/apps/web-antd/src/bootstrap.tsapps/lina-vben/apps/web-antd/package.jsongo.work八、实现步骤
Phase 1: 后端 - TraceID 响应头暴露(1-2小时)
middleware_response.go设置X-Trace-Id响应头X-Trace-IdPhase 2: 后端 - 日志接收API(2-3小时)
api/log/DTO文件controller/log/批量接收cmd_http_routes.go注册路由(公开组)logIngest配置段make ctrl生成骨架Phase 3: 前端 - Logger模块(3-4小时)
packages/effects/logger/包结构@vben/loggerworkspace包Phase 4: 前端 - 集成(2-3小时)
@vben/logger依赖到apps/web-antd/package.jsonrequest.ts添加traceID响应拦截器bootstrap.ts创建全局logger实例并安装错误处理器console.*调用到logger/api/v1/logs/batchPhase 5: MCP Server(4-5小时)
hack/tools/log-mcp/Go模块logreader.go:文件发现、文本/JSON解析、过滤、跟踪tool_logs.go:list_logs和filter_logstool_tail.go:tail_logs(follow/unfollow)tool_stats.go:get_log_stats聚合server.go:MCP server设置、工具注册、stdio传输go.work九、验证方式
curl -v http://localhost:8080/api/v1/health检查响应头包含X-Trace-Idcurl -X POST http://localhost:8080/api/v1/logs/batch -d '{"entries":[{"level":"info","message":"test"}]}'返回accepted=1,日志文件包含[FRONTEND]import { createLogger } from '@vben/logger',调用logger.info('test'),Network面板有请求list_logs、filter_logs、tail_logs工具本方案遵循LinaPro项目的SDD开发流程,实施前建议先创建OpenSpec变更提案。