自托管

内存适配器

将宽事件存储在内存环形缓冲区中。可在任何运行时中工作——包括 Cloudflare Workers(workerd)在内——即使文件系统不可用也是如此。

Memory 适配器会将宽事件存储在模块级环形缓冲区中。与 文件系统适配器 不同,它没有运行时依赖,并且可以在任何地方运行——包括 Cloudflare Workers(workerd)、Deno Deploy,以及其他不提供 Node fs 模块的边缘运行时。

其主要使用场景是本地开发中的代理访问:在开发期间接入 drain,暴露一个轻量级 HTTP 端点,然后让你的 AI 代理通过 HTTP 获取结构化日志,而无需任何外部工具。

添加内存 drain 适配器

安装

Memory 适配器随 evlog 一起提供:

src/index.ts
import { createMemoryDrain, readMemoryLogs } from 'evlog/memory'

快速开始

// src/index.ts
import { Hono } from 'hono'
import { evlog } from 'evlog/hono'
import { createMemoryDrain, readMemoryLogs } from 'evlog/memory'

const app = new Hono()

app.use(evlog({ drain: createMemoryDrain() }))

// 仅限开发环境的端点——在生产环境中请限制访问或移除
app.get('/_evlog/logs', (c) => {
  return c.json(readMemoryLogs())
})

通过 HTTP 访问代理

暴露一个路由,让代理在本地开发会话期间检索结构化日志。使用 parseReadMemoryLogsQuery 让代理可以直接通过查询字符串传递过滤参数:

src/index.ts(Hono)
import { readMemoryLogs, parseReadMemoryLogsQuery } from 'evlog/memory'

// 仅限开发环境——代理会访问此端点来检索日志
if (process.env.NODE_ENV !== 'production') {
  app.get('/_evlog/logs', (c) => {
    return c.json(readMemoryLogs(parseReadMemoryLogsQuery(c.req.query())))
  })
}

现在,代理可以调用 /_evlog/logs?level=error&limit=50&since=2026-01-01T00:00:00Z,并且在传递给 readMemoryLogs 之前,查询参数会被强制转换为正确的类型。支持的查询参数:storesinceuntillevel(多个值可用逗号分隔)、limit

响应是一个 WideEvent 对象的 JSON 数组——与其他所有 evlog 适配器使用的形状相同。

配置

选项

选项类型默认值描述
maxEventsnumber1000在环形缓冲区中保留的最大事件数(最旧的会被丢弃)
storestring'default'命名缓冲区键——共享同一键的多个 drain 会共享同一个缓冲区
server/plugins/evlog-drain.ts
// 仅保留最近的 500 个事件
createMemoryDrain({ maxEvents: 500 })

// 使用命名存储以实现隔离
createMemoryDrain({ store: 'my-service' })

环境变量

变量Nuxt 别名描述
EVLOG_MEMORY_STORENUXT_EVLOG_MEMORY_STORE命名缓冲区键(默认:'default'
EVLOG_MEMORY_MAX_EVENTSNUXT_EVLOG_MEMORY_MAX_EVENTS环形缓冲区大小(默认:1000

配置优先级与其他适配器一致:覆盖项 → runtimeConfig.evlog.memory → 环境变量。

命名存储

使用命名存储来隔离来自不同服务的事件,或用于测试:

src/index.ts
import { createMemoryDrain, readMemoryLogs, clearMemoryLogs } from 'evlog/memory'

// 两个独立的缓冲区
const authDrain = createMemoryDrain({ store: 'auth' })
const apiDrain = createMemoryDrain({ store: 'api' })

// 从特定存储中读取
const authErrors = readMemoryLogs({ store: 'auth', level: 'error' })

// 清空某个存储(在测试中很有用)
clearMemoryLogs('auth')

查询

readMemoryLogs 支持与 readFsLogs 相同的过滤选项:

src/index.ts
import { readMemoryLogs } from 'evlog/memory'

// 所有事件
const all = readMemoryLogs()

// 仅错误
const errors = readMemoryLogs({ level: 'error' })

// 最近 10 分钟
const recent = readMemoryLogs({
  since: new Date(Date.now() - 10 * 60 * 1000),
})

// 自定义谓词
const slow = readMemoryLogs({
  filter: e => typeof e.duration === 'string' && e.duration.endsWith('s'),
})

// 最近的 50 个事件
const latest = readMemoryLogs({ limit: 50 })

readMemoryLogs 选项

选项类型描述
storestring要读取的命名存储(默认:'default'
sinceDate | string仅返回 timestamp >= since 的事件
untilDate | string仅返回 timestamp <= until 的事件
levelLogLevel | LogLevel[]按级别过滤
filter(event) => boolean自定义谓词
limitnumber最多返回 N 个最近匹配的事件

与网络 drain 结合使用

在本地使用内存适配器,同时在生产环境中发送到可观测性平台:

server/plugins/evlog-drain.ts
import { createMemoryDrain } from 'evlog/memory'
import { createAxiomDrain } from 'evlog/axiom'

const memory = createMemoryDrain()
const axiom = createAxiomDrain()

const drain = async (ctx) => {
  if (process.env.NODE_ENV === 'development') {
    await memory(ctx)
  } else {
    await axiom(ctx)
  }
}

环形缓冲区行为

该缓冲区是有界的:一旦达到 maxEvents,最旧的事件就会被丢弃,以便为新事件腾出空间。这意味着无论服务运行多久,内存使用量都会保持恒定。

环形缓冲区(maxEvents: 5)
写入事件 1–5 → [1, 2, 3, 4, 5]
写入事件  6  → [2, 3, 4, 5, 6]  (1 被丢弃)
写入事件 7–8 → [4, 5, 6, 7, 8]
当 worker/进程重启时,内存缓冲区会丢失。若需要持久化存储,请使用 文件系统适配器(基于 Node 的运行时)或 NuxtHub

直接 API 用法

对于高级用例,可以直接调用底层辅助函数:

src/index.ts
import { writeToMemory, readMemoryLogs, clearMemoryLogs, parseReadMemoryLogsQuery } from 'evlog/memory'

// 直接写入事件(跳过 drain 管道)
writeToMemory([event], { store: 'default', maxEvents: 1000 })

// 读取当前缓冲区
const events = readMemoryLogs()

// 将 HTTP 查询参数解析为 ReadMemoryLogsOptions
const opts = parseReadMemoryLogsQuery({ level: 'error', limit: '50' })
// → { level: 'error', limit: 50 }

// 用于测试时重置
clearMemoryLogs()

parseReadMemoryLogsQuery 类型转换规则

查询参数ReadMemoryLogsOptions 中的类型说明
storestring原样传递
sincestringISO 8601 字符串——由 readMemoryLogs 解析
untilstringISO 8601 字符串——由 readMemoryLogs 解析
levelLogLevel | LogLevel[]逗号分隔(error,warn)或重复数组;无效值会被丢弃
limitnumberparseInt;NaN → 省略

下一步