# 日志中间件

URL: https://caijiao.org/koa/middleware/logger
Source: docs/koa/middleware/logger.md
Description: 了解如何在 Koa 中使用日志中间件，记录请求信息、错误日志等，帮助进行应用监控与调试。

在开发 Web 应用时，日志记录是至关重要的，它可以帮助开发人员监控应用的运行状态、调试问题以及分析用户行为。在 [Koa](/koa/) 中，你可以轻松地集成日志中间件，记录请求的详细信息、错误信息等。常用的日志中间件是 `koa-logger` 和自定义日志中间件。

## 1. 安装日志中间件

首先，我们可以使用 `koa-logger` 来记录请求的基本信息。`koa-logger` 是一个轻量级的 Koa 中间件，用于记录 HTTP 请求日志。

```bash
npm install koa-logger
````

### 示例：安装并使用 `koa-logger`

```js
const Koa = require('koa');
const logger = require('koa-logger');
const app = new Koa();

// 使用 koa-logger 中间件记录请求日志
app.use(logger());

app.use((ctx) => {
  ctx.body = 'Hello Koa!';
});

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});
```

在这个示例中，`koa-logger` 会在每个请求之后打印请求的日志信息。日志会包括请求的 HTTP 方法、URL、响应时间等。

### 示例日志输出

```
GET / 200 4ms
```

其中，`GET` 是请求方法，`/` 是请求路径，`200` 是 HTTP 响应状态码，`4ms` 是请求处理的时间。

## 2. 自定义日志格式

你可以通过传递格式化函数来定制日志的输出格式。例如，记录请求的详细信息，如请求头、IP 地址、请求体等。

### 示例：自定义日志格式

```js
const logger = require('koa-logger');

app.use(logger((str, args) => {
  // 自定义日志格式：输出请求方法、请求 URL 和响应时间
  return `${args[0]} ${args[1]} - ${args[3]}ms`;
}));
```

通过这种方式，你可以自定义日志格式，适应特定的调试和监控需求。

## 3. 错误日志记录

在应用中，记录错误日志非常重要，尤其是在调试和生产环境中。你可以通过自定义中间件来捕获和记录应用中的错误。

### 示例：捕获错误并记录日志

```js
app.use(async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    console.error('Error:', err.message);  // 输出错误日志
    ctx.status = err.status || 500;
    ctx.body = err.message;
  }
});
```

在这个示例中，我们使用 `try-catch` 语句来捕获 Koa 中间件链中的错误，并通过 `console.error()` 打印错误信息到日志。

## 4. 使用 Winston 记录日志

如果你需要更强大的日志记录功能（如日志等级、日志持久化等），你可以结合 `winston` 等日志库来实现更复杂的日志记录。

首先，安装 `winston`：

```bash
npm install winston
```

### 示例：使用 `winston` 记录日志

```js
const winston = require('winston');

const logger = winston.createLogger({
  transports: [
    new winston.transports.Console({ level: 'info' }),
    new winston.transports.File({ filename: 'combined.log', level: 'info' }),
  ],
});

app.use(async (ctx, next) => {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  logger.info(`${ctx.method} ${ctx.url} - ${ms}ms`);
});
```

在这个示例中，我们使用 `winston` 来将日志输出到控制台和文件。你可以根据需求调整日志级别、输出方式以及其他配置。

## 5. 日志级别与分类

Winston 和其他日志库支持不同的日志级别，如 `info`、`warn`、`error` 等。你可以根据日志的严重程度选择适合的级别进行记录。

### 示例：使用不同的日志级别

```js
logger.info('This is an info message');
logger.warn('This is a warning message');
logger.error('This is an error message');
```

* **`info`**：用于记录常规信息，如正常请求。
* **`warn`**：用于记录警告信息，如请求中的潜在问题。
* **`error`**：用于记录错误信息，如请求失败或应用错误。

## 6. 日志持久化

对于生产环境中的日志，通常需要将日志持久化到文件或外部日志服务中，以便后期分析和监控。`winston` 和其他日志库通常提供了文件输出选项，可以将日志记录到本地文件或远程服务器。

### 示例：将日志输出到文件

```js
new winston.transports.File({ filename: 'logs/application.log' })
```

你可以通过此方式将日志持久化到文件中，以便后期查看或处理。

## 7. 总结

日志中间件是 Koa 应用中不可或缺的一部分。通过使用 `koa-logger`、`winston` 或自定义中间件，你可以方便地记录应用中的请求日志和错误信息。适当的日志管理和持久化能够帮助开发人员更好地调试问题、监控应用性能，并为运维提供有价值的信息。

在生产环境中，日志不仅是调试工具，还是保证系统稳定和高效运行的关键因素之一。合理配置日志级别、记录方式以及存储位置，可以大大提高系统的可靠性和可维护性。
