SuperAPI AI 工具集

analyze-logs

部署与运维

查看项目

更新于 10-15 15:07

技能介绍

用途

analyze-logs 用于读取并分析来自本地 .evlog/logs/ 目录的结构化宽事件日志,帮助调试错误、排查性能问题、理解应用行为。

适用时机:

  • 用户要求调试错误、排查 bug,或理解某次失败的原因
  • 用户询问请求模式、慢端点或错误率
  • 用户询问应用“发生了什么”或“现在什么情况”
  • 用户要求分析日志、查看近期错误或回顾应用行为
  • 用户提到他们看到的具体错误信息或状态码

主要能力

该技能可读取由 evlog 文件系统 drain 写入的 .jsonl 日志,按日期组织(如 2026-03-14.jsonl),并优先从最新文件开始分析。

通过 CLI 分析

优先使用项目已安装的 CLI 副本(如 pnpm evlog)。按需拉取的包装器(npx、bunx、npm exec)会在项目未安装时安装 @evlog/cli,运行一个 lockfile 从未锁定的版本,执行前应先询问。

示例命令:

pnpm evlog logs --json                       # 最近 50 条事件
pnpm evlog logs errors --since 1h --json     # 失败的事件
pnpm evlog logs slow --over 1s --json        # 慢请求,最慢的在前
pnpm evlog logs "$REQUEST_ID" --json         # 某个请求,所有带该 id 的事件
pnpm evlog logs stats --json                 # 按路由:计数、错误、p50、p95;按状态与级别
pnpm evlog logs --where 'payment.amount>5000' --where audit.outcome=failure --json

--json 是一个信封结构(sources、view、matched、events;stats 则携带 stats)。可用筛选:--since、--until、--level、--path、--status(500 或 5xx)、--where(支持 field=value、field>n、field~regex、field、!field,作用于任意点分字段,可重复)、--limit、--dir(指定非默认目录)、--url(针对通过 HTTP 暴露 readMemoryLogs() 的内存 drain 应用)。从 monorepo 根目录运行时读取每个应用的 .evlog/logs 并为每个事件打标签。

直接读取文件

日志格式有两种:

  • NDJSON(默认,pretty: false):每行一个紧凑 JSON 对象,逐行解析。
  • Pretty(pretty: true):每个事件为多行缩进 JSON。可通过读取整个文件并按顶层对象切分(如 JSON.parse('[' + content.replace(/}\n{/g, '},{') + ']'))或使用流式 JSON 解析器解析。

检测方式:检查文件开头若干字节,若第二个字符是换行或 ", 则为 NDJSON;若为空格或换行后跟空格,则为 pretty 格式。

搜索顺序

先检查项目根目录下的 .evlog/logs/,再检查应用目录内的 .evlog/logs/(monorepo:apps/*/.evlog/logs/)。查找日志文件:

.evlog/logs/*.jsonl
*/.evlog/logs/*.jsonl
apps/*/.evlog/logs/*.jsonl

程序化读取

evlog 附带读取器:来自 evlog/fs 的 readFsLogs() 与 tailFsLogs(),是异步生成器,能处理两种格式、日期排序与过滤。当项目已安装 evlog 且分析需求超出快速 grep 时优先使用。

内存 drain 备选

部分应用使用 Memory 适配器(evlog/memory),通过仅开发环境的 HTTP 端点经 readMemoryLogs() 暴露近期事件。若 .evlog/logs/ 为空但应用接入了 createMemoryDrain(),则改为查询该端点。

使用方式

未找到日志时

接线新的 drain 前,可尝试 npx evlog doctor --json(只读),检查 evlog 是否已安装、本地 .evlog/logs drain 是否存在。可选,CLI 不可用则跳过。

文件系统 drain 可能未启用。在 Nuxt、Nitro、Next.js、TanStack Start、Hono、Express、Fastify 上,最快路径是 CLI,它能检测框架并一次性接好 fs drain:

npx evlog init --dry-run --yes   # 先预览
npx evlog init --yes --drain fs  # 应用

运行前需询问。其他框架(或用户拒绝)时,手动设置:

import { createFsDrain } from 'evlog/fs'

// Nuxt / Nitro: server/plugins/evlog-drain.ts
export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('evlog:drain', createFsDrain())
})

// Hono / Express / Elysia: 在中间件选项中传入
app.use(evlog({ drain: createFsDrain() }))

// Fastify: 在插件选项中传入
await app.register(evlog, { drain: createFsDrain() })

// NestJS: 在模块选项中传入
EvlogModule.forRoot({ drain: createFsDrain() })

// Standalone: 传给 initLogger
initLogger({ drain: createFsDrain() })

设置后,用户需触发一些请求以生成日志,然后重新分析。

日志格式

每行是一个自包含 JSON 对象(宽事件)。关键字段:

  • timestamp(string):ISO 8601 时间戳
  • level(string):info、warn、error、debug
  • service(string):服务名
  • environment(string):development、production 等
  • method(string):HTTP 方法
  • path(string):请求路径(/api/checkout)
  • status(number):HTTP 响应状态码
  • duration(string):请求耗时,人类可读格式("234ms")
  • durationMs(number):请求耗时毫秒值,筛选和排序使用此字段
  • requestId(string):唯一请求标识
  • error(object):错误详情 name、message、stack、statusCode、data
  • error.data.why(string):发生了什么的可读解释
  • error.data.fix(string):建议的修复
  • source(string):browser 日志为 client,服务端日志该字段缺省
  • userAgent(object):解析后的浏览器/操作系统/设备信息

其他字段均为通过 log.set() 添加的应用特定上下文(如 user、cart、payment)。

分析步骤

步骤 1:读取最近的日志文件。读取最新 .jsonl,每行独立解析。

步骤 2:识别相关事件。按用户问题过滤:

  • 错误:level 为 error 或 fatal、status >= 500,或事件带 error 对象,即 evlog logs errors 匹配的内容。单独的 4xx 状态属客户端,不计入;但带上述两种信号之一的 4xx 事件仍会匹配,可通过读取 status 或传 --status 4xx 查看全部
  • 特定端点:按 path 匹配
  • 慢请求:按 durationMs 过滤(如 durationMs > 500)
  • 特定用户/操作:按应用特定字段匹配
  • 客户端问题:按 "source":"client" 过滤
  • 时间范围:比较 timestamp

步骤 3:分析并解释。对每个相关事件:

  • 发生了什么:概括 path、method、status、level
  • 为何失败(错误):读取 error.message、error.data.why 与堆栈
  • 如何修复:查看 error.data.fix
  • 上下文:检查应用特定字段获取业务上下文
  • 模式:寻找重复错误、性能退化或相关失败

分析模式

  • 找出所有错误:过滤 level === "error",按 error.message 或 path 分组,寻找重复模式与常见失败模式
  • 找出慢请求:过滤 durationMs > 1000,按 durationMs 降序,寻找特定端点与时段模式
  • 追踪特定请求:过滤 requestId,得到单个宽事件
  • 按端点看错误率:按 path 分组,统计各路径总数与错误数,寻找高错误率端点
  • 客户端与服务器错误:按 source === "client" 与无 source 字段拆分,比较错误模式,寻找无对应服务端错误的客户端错误(网络问题)

注意事项

  • 每行是完整自包含事件,与传统日志不同,无需关联多行,一行即包含一个请求的全部上下文
  • error.data.why 与 error.data.fix 是 evlog 特有的结构化错误字段,存在时提供最具可操作性的信息
  • duration 带单位(如 "706ms"),durationMs 为毫秒值,筛选排序用 durationMs
  • 带 "source":"client" 的事件源于浏览器端日志,经 HTTP drain 端点发送到服务器
  • 日志文件已自动加入 .gitignore,仅存在于应用运行的本地机器或服务器上

限制

资料未提供价格、收费模式、平台限制或性能指标等信息。日志分析依赖应用已接入 evlog 的 drain;若无日志,需先完成接入并触发请求后重新分析。高版本或按需拉取的 CLI 包装器可能运行未锁定的发布版本,执行前应先询问。