Better Auth 集成
evlog/better-auth 会将匿名的 wide 事件转换为已识别的事件。每个请求都会自动包含发起者信息——无需手动 log.set({ user })。
前置条件
在你的应用中将 Better Auth 作为直接依赖使用。evlog 不会捆绑 Better Auth。该集成经过 Better Auth >=1.6.9 的测试(与 playground 使用相同的主版本)。
pnpm add better-auth
bun add better-auth
yarn add better-auth
npm install better-auth
添加 Better Auth 用户识别
快速开始
一个中间件,所有请求都会被识别:
import { createAuthMiddleware } from 'evlog/better-auth'
const identify = createAuthMiddleware(auth, {
exclude: ['/api/auth/**'],
})
export default defineEventHandler(async (event) => {
if (!event.context.log) return
await identify(event.context.log, event.headers, event.path)
})
import { withEvlog, useLogger } from '@/lib/evlog'
import { createAuthMiddleware } from 'evlog/better-auth'
import { auth } from '@/lib/auth'
const identify = createAuthMiddleware(auth)
export const POST = withEvlog(async (request: Request) => {
const log = useLogger()
await identify(log, request.headers)
log.set({ action: 'checkout' })
return Response.json({ success: true })
})
import { createAuthMiddleware } from 'evlog/better-auth'
const identify = createAuthMiddleware(auth, {
exclude: ['/api/auth/**'],
})
app.use(async (req, res, next) => {
await identify(req.log, req.headers, req.path)
next()
})
import { createAuthMiddleware } from 'evlog/better-auth'
const identify = createAuthMiddleware(auth, {
exclude: ['/api/auth/**'],
})
app.use(async (c, next) => {
await identify(c.get('log'), c.req.raw.headers, c.req.path)
await next()
})
import { createAuthMiddleware } from 'evlog/better-auth'
const identify = createAuthMiddleware(auth, {
exclude: ['/api/auth/**'],
})
app.addHook('onRequest', async (request) => {
await identify(request.log, request.headers, request.url)
})
import { createAuthMiddleware } from 'evlog/better-auth'
const identify = createAuthMiddleware(auth, {
exclude: ['/api/auth/**'],
})
app.derive(async ({ log, request }) => {
await identify(log, request.headers, new URL(request.url).pathname)
return {}
})
import { createAuthMiddleware } from 'evlog/better-auth'
import { useLogger } from 'evlog/nestjs'
const identify = createAuthMiddleware(auth, {
exclude: ['/api/auth/**'],
})
@Injectable()
export class AuthIdentifyMiddleware implements NestMiddleware {
async use(req: Request, res: Response, next: NextFunction) {
await identify(useLogger(), req.headers, req.path)
next()
}
}
import { identifyUser } from 'evlog/better-auth'
import { createLogger } from 'evlog'
const log = createLogger()
const session = await auth.api.getSession({ headers })
if (session) identifyUser(log, session)
log.emit()
现在你的 wide 事件包含了用户信息:
{
"level": "info",
"method": "POST",
"path": "/api/checkout",
"status": 200,
"duration": "120ms",
"requestId": "a5669202-7765-4f59-b6f0-b9f40ce71599",
"cart": { "items": 3, "total": 9999 }
}
{
"level": "info",
"method": "POST",
"path": "/api/checkout",
"status": 200,
"duration": "120ms",
"requestId": "a5669202-7765-4f59-b6f0-b9f40ce71599",
"userId": "QBX9tPjJQExWawAbNll75",
"user": {
"id": "QBX9tPjJQExWawAbNll75",
"name": "Hugo Richard",
"email": "hugo@example.com",
"emailVerified": true,
"createdAt": "2024-01-15T10:00:00.000Z"
},
"session": {
"id": "Xhmh6TxKJQrVKFX0Y0II",
"expiresAt": "2024-01-22T10:00:00.000Z",
"ipAddress": "192.168.1.42",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)",
"createdAt": "2024-01-15T10:00:00.000Z"
},
"auth": {
"resolvedIn": 12,
"identified": true
},
"cart": { "items": 3, "total": 9999 }
}
工作原理
request → wide event·anonymous
request flow
- middleware
route check · skip auth/**
- getSession(headers)
reads cookie · 12ms
db read · 0ms - identifyUser(log, session)
safe-fields whitelist
- emit wide event
all fields drained
wide event
$POST/api/checkout200· 120ms
requestId: "a566ef91-…"
cart: { items: 3, total: 9999 }
added by better-auth
userId: "QBX9tPjJQExWawAbNll75"
user.id: "QBX9tPjJQExWawAbNll75"
user.name: "Hugo Richard"
user.email: "hugo@example.com"
session.id: "Xhmh6TxKJQrVKFX0Y0II"
session.expiresAt: "2024-01-22T10:00:00Z"
auth.resolvedIn: 12
auth.identified: true
resolved0ms
fields added0 / 8
manual log.set calls0
该集成会从请求 cookie 中解析 Better Auth 会话,提取安全白名单中的用户和会话字段,将它们设置到 logger 上,然后触发 onIdentify(或 onAnonymous)hook。默认会跳过认证路由。解析耗时会记录在 auth.resolvedIn 中,因此你可以将认证延迟与 wide 事件的其他部分一起绘制成图表。
接下来去哪
公共 API
| 导出 | 描述 |
|---|---|
identifyUser(log, session) | 核心辅助函数——从会话中提取安全字段并将其设置到 logger 上。如果已识别则返回 true。 |
createAuthMiddleware(auth) | 返回一个异步的 (log, headers, path?) => Promise<boolean> 函数,支持路由过滤、计时和 hooks。 |
createAuthIdentifier(auth) | 用于独立 Nitro 应用的 Nitro request hook 工厂。参见 性能。 |
maskEmail(email) | 隐藏邮箱:hugo@example.com → h***@example.com。 |