---
title: "介绍"
description: "通过 evlog 了解你的应用中发生了什么：结构化日志、广泛事件，以及能够解释问题原因和修复方法的错误。"
canonical_url: "https://evlog.zhcndoc.com/start/introduction"
---
# 介绍

> 通过 evlog 了解你的应用中发生了什么：结构化日志、广泛事件，以及能够解释问题原因和修复方法的错误。

**evlog** 是一个 TypeScript 日志记录库，帮助你了解应用中发生了什么。从结构化日志开始，将一个请求的上下文汇总到一个广泛事件中，并将失败转化为能够解释问题原因和修复方法的错误。

刚接触 Node.js 中的结构化日志？[Node.js 中的结构化日志](https://evlog.zhcndoc.com/use-cases/structured-logging-nodejs)会带你完整走一遍流程。

在下一个项目中使用它，或将它与现有日志记录器结合使用。[快速开始](https://evlog.zhcndoc.com/start/quick-start)可以帮助你快速上手；[迁移示例](https://evlog.zhcndoc.com/learn/simple-logging)展示了如何将熟悉的日志记录模式引入 evlog。

灵感来自 [Boris Tane](https://x.com/boristane) 的 [Logging Sucks](https://loggingsucks.com/)。独立的 [evlog CLI](https://evlog.zhcndoc.com/cli/overview) 可以帮助你探索日志，并通过静态检查发现缺失的日志记录模式。

## 哲学

传统日志记录已失效。你的日志分散在数十个文件中。每个请求生成超过 10 行日志。当出现问题时，你只能通过 grep 在噪音中寻找信号。

**evlog** 采用了不同的方法：

<card-group>
<card icon="i-lucide-terminal" title="结构化日志">

用类型化、结构化的事件替代 `console.log`，并通过 drain 管线流转。拥有与 pino 或 consola 相同的级别过滤、脱敏以及美化/JSON 输出。

</card>

<card icon="i-lucide-layers" title="广泛事件">

在任意工作单元（请求、脚本或任务）中累积上下文，并一次性发出。两种模式可以共存，彼此都不是对方的升级版。

</card>

<card icon="i-lucide-shield-alert" title="结构化错误">

解释为什么发生以及如何修复的错误。

</card>

<card icon="i-lucide-palette" title="对开发者友好">

开发阶段人类可读，生产环境为可解析的 JSON。

</card>
</card-group>

<callout color="info" icon="i-lucide-globe">

没有运行 HTTP 框架？请参阅用于脚本、工作器和 CLI 的 [独立 TypeScript](https://evlog.zhcndoc.com/integrate/frameworks/standalone)，以及用于边缘运行时的 [Cloudflare Workers](https://evlog.zhcndoc.com/integrate/frameworks/cloudflare-workers)。

</callout>

## 为什么选择 evlog，而不是 pino、winston 或 consola

evlog 是一个功能完整的通用日志记录器，恰好也支持广泛事件。具体来说：

- **核心包没有运行时依赖。** 从日志记录器开始，并根据需要添加集成。有关包体积和基准测试，请参阅[性能](https://evlog.zhcndoc.com/reference/performance)。
- **在每种上下文中使用相同的 API**：脚本、框架、边缘运行时、浏览器、库代码。没有 `pino-http` 与 `pino` 的拆分，也不需要为每种环境单独配置 `consola` 报告器。
- **内置 why / fix / link 的结构化错误**：你的错误提示终于能告诉用户发生了什么以及该怎么做，你的值班人员也不必再逆向分析堆栈跟踪。
- **广泛事件是一条无需额外成本的升级路径**：当你需要关联一次操作中的上下文时，同一个日志记录器会为你提供 `log.set` + `log.emit`，而不是事后再拼接日志行。

请查看完整的 [功能对比](https://evlog.zhcndoc.com/reference/vs-other-loggers)（对等矩阵、诚实的差距和迁移片段），与 pino、winston 和 consola 逐项比较。

## 选择三种日志记录方式之一

evlog 为不同上下文提供三种 API。你可以在同一个项目中使用所有三种方式。

### 简单日志

即发即忘的结构化日志。替换 `console.log`、consola 或 pino：

```typescript [src/index.ts]
import { log } from 'evlog'

log.info('auth', '用户已登录')
log.error({ action: 'payment', error: 'card_declined', userId: 42 })
```

### 广泛事件

在任意操作过程中逐步累积上下文，然后发出一个全面的事件：

<code-group>

```typescript [scripts/sync-job.ts]
import { createLogger } from 'evlog'

const log = createLogger({ jobId: 'sync-001', queue: 'emails' })
log.set({ batch: { size: 50, processed: 50 } })
log.emit()
```

```typescript [src/worker.ts]
import { createRequestLogger } from 'evlog'

const log = createRequestLogger({ method: 'POST', path: '/api/checkout' })
log.set({ user: { id: 1, plan: 'pro' } })
log.emit()
```

</code-group>

使用框架集成时，日志记录器会在请求开始时创建，并在响应结束时发出。处理程序只需添加它在过程中获取的信息：

<framework-tabs>

```typescript [Nuxt]server/api/checkout.post.ts
import { useLogger } from 'evlog'

export default defineEventHandler(async (event) => {
  const log = useLogger(event)

  log.set({ user: { id: 1, plan: 'pro' } })
  return { success: true }
  // 在响应结束时自动发出
})
```

```typescript [Nitro]routes/api/checkout.post.ts
import { defineHandler } from 'nitro/h3'
import { useLogger } from 'evlog/nitro/v3'

export default defineHandler(async (event) => {
  const log = useLogger(event)

  log.set({ user: { id: 1, plan: 'pro' } })
  return { success: true }
  // auto-emitted on response end
})
```

```typescript [Next.js]app/api/checkout/route.ts
import { withEvlog, useLogger } from '@/lib/evlog'

export const POST = withEvlog(async () => {
  const log = useLogger()

  log.set({ user: { id: 1, plan: 'pro' } })
  return Response.json({ success: true })
  // auto-emitted on response end
})
```

```typescript [Hono]src/index.ts
app.post('/api/checkout', async (c) => {
  const log = c.get('log')

  log.set({ user: { id: 1, plan: 'pro' } })
  return c.json({ success: true })
  // auto-emitted on response end
})
```

```typescript [Express]src/index.ts
app.post('/api/checkout', async (req, res) => {
  const log = req.log

  log.set({ user: { id: 1, plan: 'pro' } })
  return res.json({ success: true })
  // auto-emitted on response end
})
```

</framework-tabs>

一个日志，包含所有上下文。理解发生的一切所需的一切都包含其中。

### 结构化错误

带有可操作上下文的错误：`why` 它发生，如何 `fix`，以及指向文档的 `link`：

<code-group>

```typescript [services/checkout.ts]
import { createError } from 'evlog'

throw createError({
  message: 'Payment failed',
  status: 402,
  why: '卡被发卡行拒绝（余额不足）',
  fix: '尝试其他支付方式或联系你的银行',
  link: 'https://docs.example.com/payments/declined',
})
```

```json [响应]
{
  "statusCode": 402,
  "message": "Payment failed",
  "data": {
    "why": "卡被发卡行拒绝（余额不足）",
    "fix": "尝试其他支付方式或联系你的银行",
    "link": "https://docs.example.com/payments/declined"
  }
}
```

</code-group>

## 为什么一个事件胜过十行日志

我们正在进入一个 AI 代理构建、调试和维护应用程序的时代。这些代理需要 **结构化上下文** 才能有效工作：

- **why**：根本原因，让代理理解哪里出了问题
- **fix**：可操作的解决方案，供代理建议或应用
- **link**：复杂问题的文档

传统的 `console.log` 和通用的 `throw new Error()` 无法提供可操作的上下文。evlog 的结构化输出旨在供人类和 AI 解析并采取行动。

## 下一步

- **试用 evlog：** 按照[安装](https://evlog.zhcndoc.com/start/installation)和[快速开始](https://evlog.zhcndoc.com/start/quick-start)进行操作。
- **决定它是否适合你的项目：** 阅读[选择 TypeScript 日志记录器](https://evlog.zhcndoc.com/start/typescript-logging-library)，或者如果你要开发新应用，请阅读[为什么从 evlog 开始](https://evlog.zhcndoc.com/start/why-evlog)。
- **探索相关概念：** [日志记录概览](https://evlog.zhcndoc.com/learn/overview)将简单日志、广泛事件和结构化错误串联起来。

---

- [快速开始](https://evlog.zhcndoc.com/start/quick-start)
- [GitHub](https://github.com/evloghq/evlog)


## Sitemap

See the full [sitemap](https://evlog.zhcndoc.com/sitemap.md) for all pages.
