node.js中一个常用的日志记录的中间件morgan

288 阅读3分钟

一个常用的 Express 中间件是 morgan,它是一个 HTTP 请求日志记录中间件,用于记录每个请求的详细信息,如请求方法、URL、状态码、响应时间等。morgan 是 Express 生态系统中非常流行的日志记录工具,广泛应用于开发和生产环境中。


1. morgan 的功能

  • 记录 HTTP 请求的详细信息。
  • 支持多种预定义的日志格式(如 combinedcommondevshorttiny)。
  • 支持自定义日志格式。
  • 可以将日志输出到控制台、文件或其他流中。

2. 使用 morgan 的示例

2.1 基本用法

const express = require('express');
const morgan = require('morgan');

const app = express();

// 使用默认的 'dev' 格式记录日志
app.use(morgan('dev'));

app.get('/', (req, res) => {
  res.send('Hello, World!');
});

app.listen(3000, () => {
  console.log('Server is running on http://localhost:3000');
});
  • 当访问 http://localhost:3000 时,控制台会输出类似以下的日志:
GET / 200 12.123 ms - 13
  • GET:请求方法。
  • /:请求的 URL。
  • 200:响应状态码。
  • 12.123 ms:响应时间。
  • 13:响应内容的长度。

2.2 使用其他预定义格式

app.use(morgan('combined')); // 使用 'combined' 格式
  • combined 格式会输出更详细的信息,包括远程地址、请求时间、HTTP 版本等。

2.3 将日志写入文件

const fs = require('fs');
const path = require('path');

// 创建一个写入流
const accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), { flags: 'a' });

// 将日志写入文件
app.use(morgan('combined', { stream: accessLogStream }));

3. morgan 的实现原理

3.1 中间件的基本结构

morgan 是一个标准的 Express 中间件,其核心是一个函数,接收请求对象(req)、响应对象(res)和 next 函数作为参数。它的基本结构如下:

function morgan(format, options) {
  return (req, res, next) => {
    // 记录日志的逻辑
    next();
  };
}

3.2 日志格式

morgan 支持预定义格式和自定义格式。预定义格式是通过字符串定义的,例如 devcombined 等。自定义格式可以通过函数或字符串模板实现。

  • 预定义格式

    • dev:简洁的开发环境日志。
    • combined:详细的日志,包括远程地址、请求时间等。
    • common:Apache 风格的日志。
    • short:简短的日志。
    • tiny:极简的日志。
  • 自定义格式

    app.use(morgan(':method :url :status :res[content-length] - :response-time ms'));
    

3.3 日志记录逻辑

morgan 的核心逻辑是在请求完成时(即响应结束时)记录日志。它通过监听响应对象的 finish 事件来实现:

function morgan(format, options) {
  return (req, res, next) => {
    const start = Date.now();

    // 监听响应结束事件
    res.on('finish', () => {
      const duration = Date.now() - start;
      const log = `${req.method} ${req.url} ${res.statusCode} ${duration}ms`;
      console.log(log); // 输出日志
    });

    next();
  };
}

3.4 支持输出到流

morgan 支持将日志输出到任意流(如文件流、控制台流等)。通过 options.stream 参数可以指定输出目标:

function morgan(format, options) {
  const stream = options.stream || process.stdout;

  return (req, res, next) => {
    const start = Date.now();

    res.on('finish', () => {
      const duration = Date.now() - start;
      const log = `${req.method} ${req.url} ${res.statusCode} ${duration}ms\n`;
      stream.write(log); // 将日志写入流
    });

    next();
  };
}

4. 自定义日志中间件的实现

如果你想实现一个简单的日志中间件,可以参考以下代码:

function logger(req, res, next) {
  const start = Date.now();

  res.on('finish', () => {
    const duration = Date.now() - start;
    console.log(`${req.method} ${req.url} ${res.statusCode} ${duration}ms`);
  });

  next();
}

app.use(logger);

5. 总结

  • morgan 的功能:记录 HTTP 请求的详细信息,支持多种日志格式和输出目标。
  • 实现原理:通过监听响应对象的 finish 事件,在请求完成时记录日志。
  • 自定义日志中间件:可以基于 morgan 的原理实现自己的日志中间件。

morgan 是一个非常强大且灵活的日志记录工具,能够帮助开发者更好地监控和调试 Express 应用。