【问题标题】:Logging all requests in Node.js/Express在 Node.js/Express 中记录所有请求
【发布时间】:2017-06-25 07:00:25
【问题描述】:

在我的小型 node.js 应用程序中,我想使用 express 记录所有传入的请求,所以我最终得到了这个:

var bodyParser = require('body-parser');

module.exports = function(app) {
   app.set("port", 50001);
   app.set("json spaces", 2);
   app.use(bodyParser.json());
   app.use(function (error, req, res, next) {
      app.logger.info("received from "+req.get("X-Forwarded-For")+" : "+req.method+" "+req.originalUrl+" (Authorization: "+req.get("Authorization")+")");
      //does not work if json is malformed
      //app.logger.info("content :"+JSON.stringify(req.body));
      if (error /*instanceof SyntaxError*/) {
         res.status(400);
         app.logger.error(error);
         res.json({ error:{msg: error.message}});
      } else {
         next();
      }
   });
   app.use(app.auth.initialize());
};

不幸的是,我只在出现错误时通过app.logger.info 行获取日志(在我的情况下,正文中的 JSON 字符串格式不正确)。我在这里错过了什么?

【问题讨论】:

    标签: json node.js express logging winston


    【解决方案1】:

    Expressjs 会根据你给它的回调类型来调整它的功能(这在 JS 库中并不常见,所以人们对此感到困惑也就不足为奇了)。

    如果你在回调有四个参数的情况下这样做:

    app.use(function(error, req, res, next) {...});
    

    然后 Express 假定这是一个仅出错的中间件处理程序,并且只会在出现错误时调用。在the express doc 中,请参阅标记为错误处理中间件 的部分。请注意该页面的这个特定部分:

    定义错误处理中间件函数的方式与其他函数相同 中间件函数,除了有四个参数而不是三个, 特别是签名(err、req、res、next)):

    还有,这是专门针对 error handling middleware 的文档的整个部分。

    如果你只使用三个参数:

    app.use(function(req, res, next) {...});
    

    那么,它是一个正常的中间件,在没有错误时调用。我不确定他们是否提供了一种同时获得两者的方法。但是,当然,作为一种解决方法,您可以将日志记录代码放入一个函数中,然后从两个独立的中间件处理程序调用该函数,一个用于错误,一个用于非错误。

    【讨论】:

      【解决方案2】:

      使用摩根https://github.com/expressjs/morgan

      安装摩根

      $ npm install morgan
      

      在 index.js 或 app.js 或 server.js 文件中包含 morgan(package.json 中 script 标签指向的文件)

      var morgan = require('morgan')
      

      然后在所有应用调用之前添加下面。

      app.use(morgan('combined'))
      

      完整示例

      var express = require('express')
      var morgan = require('morgan')
      
      var app = express()
      
      app.use(morgan('combined'))
      
      app.get('/', function (req, res) {
        res.send('hello, world!')
      })
      

      示例输出行如下所示:

      ::1 - - [31/May/2021:09:03:14 +0000] "GET / HTTP/1.1" 200 2078 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36"
      

      【讨论】:

      • 它是否记录正文?
      • 它不会记录正文。在每个请求上记录 body/params/query 将使您的控制台不整洁。
      • 测试需要它
      【解决方案3】:

      DEBUG='*'DEBUG='express:router' 环境变量

      它没有显示很多关于请求的信息,但它显示了路径和方法,这对于基本的应用程序来说可能已经足够了,而且因为它不需要任何额外的设置,所以很方便。

      DEBUG='*' 启用所有日志并且更容易键入:

      DEBUG='*' ./app.js
      

      或者更具体的DEBUG='express:router' 是您在具有大量中间件的复杂应用程序中通常需要的,否则DEBUG='*' 可能会产生大量输出:

      DEBUG='express:router' ./app.js
      

      例如与你好世界:

      #!/usr/bin/env node
      
      const express = require('express')
      const app = express()
      const port = 3000
      
      app.get('/', (req, res) => {
        res.send('Hello World!')
      })
      
      app.listen(port, () => {
        console.log(`Example app listening at http://localhost:${port}`)
      })
      

      然后当我在浏览器上玩不同的 URL 时,我可以看到如下日志:

        express:router dispatching GET / +3m
        express:router query  : / +0ms
        express:router expressInit  : / +0ms
        express:router dispatching GET /asdf +10s
        express:router query  : /asdf +0ms
        express:router expressInit  : /asdf +0ms
        finalhandler default 404 +3m
        express:router dispatching GET /asdf?qwer=zxcv +17s
        express:router query  : /asdf?qwer=zxcv +0ms
        express:router expressInit  : /asdf?qwer=zxcv +0ms
        finalhandler default 404 +17s
      

      文档地址:https://expressjs.com/en/guide/debugging.html

      在 express 4.17.1 上测试。

      【讨论】:

        【解决方案4】:

        npm 安装正文解析器

        并使用这个sn-p,

        const express = require('express')
        const morganBody = require("morgan-body")
        const bodyParser = require("body-parser")
        
        const app = express()
        const port = 8888
        
        // must parse body before morganBody as body will be logged
        app.use(bodyParser.json());
        
        // hook morganBody to express app
        morganBody(app, {logAllReqHeader:true, maxBodyLength:5000});
        
        app.get('/', (req, res) => {
          res.send('Hello World!')
        
        })
        
        app.listen(port, () => {
          console.log(`Example app listening at http://localhost:${port}`)
        })
        

        【讨论】:

          【解决方案5】:

          你可以使用 try/catch

          try {
             var jsonBody = JSON.stringify(req.body);
             app.logger.info("content :" + jsonBody);
          } catch (err) { 
              app.logger.error("content error, error type: invalid json, error msg:" + err);
          }
          

          【讨论】:

          • 谢谢,但请求日志也不显示带有 try/catch 块。我编辑了我的问题以删除正文内容的部分,因为我真正的问题是没有错误时丢失的日志!
          猜你喜欢
          • 1970-01-01
          • 2013-11-19
          • 1970-01-01
          • 1970-01-01
          • 2019-02-17
          • 1970-01-01
          • 2017-02-27
          • 2021-10-14
          • 2017-02-05
          相关资源
          最近更新 更多