You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Morgan实现请求与响应的日志拆分?

Splitting Request and Response Logs with Morgan Middleware

Great question! Morgan's flexibility makes splitting request and response logging straightforward—you just need to leverage its immediate option and pay attention to middleware ordering. Here's a step-by-step breakdown tailored to your use case:

Key Background: How Morgan Triggers Logs

By default, Morgan waits until the response finishes loading (when the finish event fires on the response object) to write logs. But when you set immediate: true, Morgan logs the moment a request hits your server—before any route handlers or business logic run. This is the core trick to separating request and response logs.

Step 1: Register Two Morgan Instances (In the Right Order)

Express executes middleware in the exact order you register them, so follow this sequence:

  1. First, add the request logging middleware (with immediate: true) to capture incoming requests immediately.
  2. Place your route handlers, authentication middleware, body parsers, etc., next.
  3. Finally, add the response logging middleware (using Morgan's default behavior, no immediate flag) to log details after the response is sent to the client.

Example Code (Matching Your Winston Setup)

Here’s how to adapt your existing code into two distinct loggers:

// Request logger: Runs the second a request arrives
app.use(morgan('[:date[clf]] :remote-addr :method :url HTTP/:http-version :remote-user :referrer :user-agent', {
  immediate: true,
  stream: { 
    write: (message) => { winston.info(`REQUEST: ${message.trim()}`); } 
  }
}));

// --- Your route handlers and other middleware go here ---
// app.get('/api/data', yourRouteHandler);
// app.use(bodyParser.json());

// Response logger: Runs after the response is sent to the client
app.use(morgan('[:date[clf]] :remote-addr :url :status :res[content-length] :response-time ms', {
  stream: { 
    write: (message) => { winston.info(`RESPONSE: ${message.trim()}`); } 
  }
}));

Breakdown of the Setup

  • Request Log: The immediate: true flag ensures we only log request-specific details (no response data like :status or :response-time—those don’t exist yet). Prefixing with REQUEST: makes it easy to distinguish these logs in your Winston output.
  • Response Log: Without the immediate flag, Morgan waits for the response to complete, so we can safely include response-specific fields like status code, content length, and response time. Prefixing with RESPONSE: clarifies these logs.

Why Order Can’t Be Reversed

If you swap the order, the response logger (default behavior) would still work, but the request logger would run after your route handlers—defeating the purpose of capturing the request as it arrives. Always place the immediate: true logger first.

Bonus: Extending to Other Use Cases

You can expand this pattern to match the other combinations you mentioned:

  • Write all request logs to a file: Replace the request logger’s stream with fs.createWriteStream('./requests.log', { flags: 'a' })
  • Output only error responses to the console: Add a skip function to the response logger (like the official example):
    app.use(morgan('dev', {
      skip: (req, res) => res.statusCode < 400,
      stream: process.stdout // Logs errors directly to console
    }));
    

内容的提问来源于stack exchange,提问作者falsarella

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:20:38