文件系统适配器将宽事件写入本地 NDJSON 文件(每行一个 JSON 对象,每天一个文件)。这使得:
- AI 代理集成 - 将技能指向
.evlog/logs/来解析结构化的日志用于调试和模式分析 - 本地开发调试 - 无需滚动终端即可获得持久的日志历史记录(
tail -f .evlog/logs/2026-03-14.jsonl) - 生产备份 - 与网络排放(Axiom、OTLP)结合,实现本地回退
提示
添加文件系统排放适配器,将 evlog 宽事件作为 NDJSON 文件本地写入。
1. 确定我正在使用的框架并遵循其 evlog 集成模式
2. 如果尚未安装 evlog,请进行安装
3. 从 'evlog/fs' 导入 createFsDrain
4. 将 createFsDrain() 接入我框架的排放配置
5. 日志默认写入 .evlog/logs/(每天一个文件,自动 .gitignore)
6. 可选配置 dir、maxFiles、maxSizePerFile 或 pretty 选项
7. 通过触发请求进行测试,并检查 .evlog/logs/*.jsonl
适配器文档: https://www.evlog.dev/adapters/fs
框架设置: https://www.evlog.dev/frameworks
安装
文件系统适配器随 evlog 一起打包提供:
src/index.ts
import { createFsDrain } from 'evlog/fs'
快速开始
无需凭据或环境变量。只需将排放接入你的框架:
// server/plugins/evlog-drain.ts
import { createFsDrain } from 'evlog/fs'
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('evlog:drain', createFsDrain())
})
import { createFsDrain } from 'evlog/fs'
app.use(evlog({ drain: createFsDrain() }))
import { createFsDrain } from 'evlog/fs'
app.use(evlog({ drain: createFsDrain() }))
import { createFsDrain } from 'evlog/fs'
await app.register(evlog, { drain: createFsDrain() })
import { createFsDrain } from 'evlog/fs'
app.use(evlog({ drain: createFsDrain() }))
import { createFsDrain } from 'evlog/fs'
EvlogModule.forRoot({ drain: createFsDrain() })
import { createFsDrain } from 'evlog/fs'
initLogger({ drain: createFsDrain() })
日志会立即出现在 .evlog/logs/ 中。
文件结构
.evlog/logs 目录布局
.evlog/
logs/
2026-03-14.jsonl ← 每天一个文件
2026-03-13.jsonl
2026-03-12.jsonl
每个 .jsonl 文件包含每行一个 JSON 对象(NDJSON 格式),使其易于解析、搜索和流式处理。
在首次写入时会自动在
.evlog/ 祖先目录内(如果存在)或配置的 dir 中创建 .gitignore。日志文件永远不会提交到版本控制中。配置
选项
| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
dir | string | '.evlog/logs' | 日志文件目录 |
maxFiles | number | undefined | 保留的最大文件数(自动删除最旧的) |
maxSizePerFile | number | undefined | 旋转前的文件最大字节数 |
pretty | boolean | false | 美化打印 JSON(多行,可读) |
示例
server/plugins/evlog-drain.ts
// 仅保留最近 7 天的日志
createFsDrain({ maxFiles: 7 })
// 在 10MB 处旋转文件,保留 30 个文件
createFsDrain({
maxSizePerFile: 10 * 1024 * 1024,
maxFiles: 30,
})
// 美化打印以便人工阅读
createFsDrain({ pretty: true })
// 自定义目录
createFsDrain({ dir: '/var/log/myapp' })
文件旋转
默认情况下,每天创建一个新文件(2026-03-14.jsonl)。当设置了 maxSizePerFile 时,适配器会在当前文件超过限制时创建带后缀的文件:
旋转后的日志文件
.evlog/logs/
2026-03-14.jsonl ← 基础文件(完整)
2026-03-14.1.jsonl ← 第一次旋转
2026-03-14.2.jsonl ← 第二次旋转
清理
当设置了 maxFiles 时,适配器会在每次写入后自动删除最旧的 .jsonl 文件,仅保留最新的文件。
与网络排放结合使用
将 FS 适配器与网络排放结合使用以实现本地备份:
server/plugins/evlog-drain.ts
import { createFsDrain } from 'evlog/fs'
import { createAxiomDrain } from 'evlog/axiom'
const fs = createFsDrain({ maxFiles: 7 })
const axiom = createAxiomDrain()
const drain = async (ctx) => {
await Promise.allSettled([fs(ctx), axiom(ctx)])
}
查询日志
实时流式传输
终端
tail -f .evlog/logs/2026-03-14.jsonl
使用 jq 搜索
终端
# 查找错误
cat .evlog/logs/2026-03-14.jsonl | jq 'select(.level == "error")'
# 慢请求(duration 是类似 "706ms" 或 "1.23s" 的格式化字符串)
cat .evlog/logs/2026-03-14.jsonl | jq 'select(.duration | test("^[0-9.]+s"))'
# 按路径请求
cat .evlog/logs/2026-03-14.jsonl | jq 'select(.path == "/api/checkout")'
使用 grep 搜索
终端
# 查找所有错误
grep '"level":"error"' .evlog/logs/2026-03-14.jsonl
# 按请求 ID 查找
grep 'req_abc123' .evlog/logs/*.jsonl
直接 API 用法
对于高级用例,使用更低级别的写入函数:
src/index.ts
import { writeToFs, writeBatchToFs } from 'evlog/fs'
await writeToFs(event, {
dir: '.evlog/logs',
pretty: false,
})
await writeBatchToFs(events, {
dir: '.evlog/logs',
pretty: false,
})
AI 日志分析
文件系统排放与 analyze-logs 代理技能 配对使用。安装后,你的 AI 助手可以直接读取 NDJSON 日志以调试错误、跟踪请求并调查性能,而无需任何外部工具。