Skip to content
Elogs
Esc
navigateopen⌘Jpreview
On this page

Elysia 2 适配

Elogs 在 Elysia 2 open beta 上的适配说明,以及升级时的所有破坏性变更

Elysia 2 “DayDream” 是 Elysia 框架的一次完整重写。它重命名了所有生命周期钩子、改动了 Elysia 的类型泛型,并把 WebSocket 支持拆成 opt-in 插件。Elogs 无法在单一构建里同时兼容两个大版本,所以发布为两条独立分支。

兼容性矩阵

Elysia Elogs npm tag 安装
1.4.x 6.x latest bun add @eastgold15/elogs
>= 2.0.0-beta.2 7.x-next next bun add @eastgold15/elogs@next elysia@next

next 分支紧跟 Elysia 2 beta,在 Elysia 2 稳定前还可能继续引入破坏性变更。

你应用里的变化

Elysia 2 移除了所有生命周期方法的 on 前缀,也没有留下别名。如果你在 Elogs 钩子周围注册了自定义钩子,需要重命名:

Elysia 1.4 Elysia 2
.onStart() .setup()
.onStop() .cleanup()
.onRequest() .request()
.onTransform() .transform()
.onBeforeHandle() .beforeHandle()
.onAfterHandle() .afterHandle()
.onAfterResponse() .afterResponse()
.onMapResponse() .mapResponse()
.onError() .error()
.as('scoped') .as('plugin')

resolve 被移除,derive 现在在 beforeHandle 阶段运行。Elogs 派生 ctx.logbeforeHandle,所以在 beforeHandle、route handler 和 afterHandle 都能拿到 —— 但 parsetransform 拿不到了。如果你需要更早记日志,用 store.logger(在 request 钩子里已经设好)。

WebSocket 路由需要 opt-in provider,createWsHandlerWrapper 才能包到东西:

import { Elysia } from 'elysia'
import { websocket } from 'elysia/websocket'
import { createElogs, createWsHandlerWrapper } from '@eastgold15/elogs'

const logging = createElogs()
const wrapWs = createWsHandlerWrapper()

const app = new Elysia()
  .use(websocket())
  .use(logging)
  .ws('/ws', {
    ...wrapWs({
      message(ws, message) {
        ws.send(message)
      }
    })
  })

trace 和自动 HEAD 路由也按同样方式搬到 elysia/traceelysia/auto-head

哪些没变

Elogs 自身的 API 没变:createElogs(options)preset / config 形态、store.loggerctx.loguseLogger()createWsHandlerWrapper,以及 createElogs/otelcreateElogs/ai 子路径 —— 都跟 6.x 行为一致。

单点 onError 设计

Elogs 2.x 重写了错误处理模型,从 1.x 时代的“多 handler 链”简化成一个钩子只做一件事。这背后的动机是响应格式和错误日志记录是两个正交的关注点,把它们绑在一起会让两边都难以替换。

设计要点

  • 插件在 .error(logOnErrorHook) 钩子里记录日志
  • 钩子不 return value —— 错误继续传播到用户的 .error(MyClass, fn) 或 Elysia 默认的 application/problem+json 响应
  • 钩子捕获所有进入错误管道的错误 —— 无论路由 throw 还是 return Response(status >= 400),都会触发(Elysia 2 语义)
  • 翻译器(autoTranslate)只决定日志级别和内容;翻译后丢弃,原 error 继续以原形态传播

实现位置在 packages/elogs/src/plugin.ts:265-308,核心结构:

const logOnErrorHook: ErrorHandler = (ctx) => {
  // 1) 可选:跑 autoTranslate 链得到 effectiveError(只用来决定 status)
  // 2) 提取 status(从 error.status 或 HTTPError.status,默认 500)
  // 3) 按 status 写一条 ERROR / WARNING / INFO 日志
  // 4) 回显 X-Request-Id 到响应头
  // 5) **不 return** —— 错误继续向下游传播
}

已删除的 API

下面是 1.x → 2.x 错误处理模型的破坏性变更清单。这些名字都不再存在,不能在新代码里使用:

旧 API 替代方案
applyErrorLogging(error, request, store) 已被 .error(logOnErrorHook) 钩子取代,无需手动调用
LogixlysiaErrorClass 用 Elysia 2 原生 class extends HTTPError
LogixlysiaErrorClasses 用 Elysia 2 原生 class extends HTTPError
createErrorHandler(options) 改为用户用 Elysia 2 原生 .error(handler)
userErrorHandlers 用户在自己 app 上注册 .error(MyClass, fn)
fallbackErrorHandler 改为 Elysia 默认 problem 响应 + Elogs 日志钩子
errors 配置项 全部移除,改用 .error() 链 + autoTranslate 配置

旧的 extractErrorStatus 也已下放到内部,改名 extractStatus 后作为公开工具导出(供 translator 复用),不再是 Elogs 的对外约定。

自定义错误响应 Elysia 2 原生 .error()

想要自定义某个错误类的响应格式,直接用 Elysia 2 原生钩子。Elogs 的钩子会先跑,写完日志后把控制权交回,你的钩子再决定响应形态:

import { Elysia, problem } from 'elysia'
import { createElogs, httpError, errorMap } from '@eastgold15/elogs'
import { translateDrizzleError } from '@eastgold15/elogs/translator'

class NotFoundError extends Error {
  status = 404
}

const app = new Elysia()
  .use(
    createElogs({
      // 自动把 Drizzle 错误翻译成 4xx/5xx,只影响日志级别
      autoTranslate: { db: 'drizzle' },
    })
  )
  // 你的 .error() 在 Elogs 之后注册,日志已写好
  .error(NotFoundError, ({ code }) => {
    return problem(404, { detail: code ?? 'not found' })
  })
  .error('DrizzleError', (ctx) => {
    const code = (ctx.error as { code?: string }).code ?? 'UNKNOWN'
    return problem(409, { detail: `duplicate: ${code}` })
  })
  .get('/users/:id', ({ params }) => {
    if (params.id === '404') {
      throw httpError(404, 'user not found')
    }
    throw new Error('boom')
  })

翻译器 vs 错误响应

翻译器和错误响应是两条独立的线,不要混:

  • autoTranslate —— 决定日志怎么记(级别 + 内容),原 error 不动
  • .error(MyClass, fn) —— 决定响应怎么发,可能完全覆盖 Elogs 默认的 problem 响应

完整 Drizzle 翻译示例见 Database errorshttpError(status, msg)errorMap() 仍是用户工具,只是不再被插件自动注册。

Elysia 2 框架行为对你的日志

两个框架行为变化会反映在日志内容里:

  • 错误默认以 RFC 9457 problem document 形式报告。
  • NODE_ENV=production,未处理错误的 message 不再发回客户端,返回的 Error 序列化时也不会带 cause

这两个都不影响 Elogs 写入的内容 —— 完整 error 仍然服务端全量记录,具体范围由 logErrorPayloadautoRedact 决定。

Last updated on August 15, 2026

Was this page helpful?