【问题标题】:Time requests in NodeJS/ExpressNodeJS/Express 中的时间请求
【发布时间】:2013-08-30 17:35:38
【问题描述】:

对进入我的节点应用程序的所有请求进行计时的最佳方法是什么?基本上我想在请求开始时获取当前时间戳,然后在请求结束时再次获取差异并记录它。关于在 NodeJS 和 Express 中执行此操作的最佳方法的建议?

这是我的应用的外观示例(虽然比这复杂得多)。

var express = require('express'),
    http = require('http'),
    app = express();

app.get('/', function (req, res, next) {
    res.send(200, 'hi');
});

app.get('/about', function(req, res, next) {
   res.send(200, 'something else');
});

var server = http.createServer(app);
server.listen(9000);
console.log("Express server listening...");

我想为所有请求计时。所以我想计时//about 以及我可能添加的任何其他端点。

【问题讨论】:

    标签: node.js express


    【解决方案1】:

    这可能会奏效:http://www.senchalabs.org/connect/responseTime.html

    app.use(express.responseTime());
    

    或者做这样的事情:

    app.use(function(req, res, next) { req.start = Date.now(); next(); });
    
    app.get(...);
    app.get(...);
    
    app.use(function(req, res) { var time = Date.now() - req.start; });
    

    这要求你的所有路由都调用next()

    或者这个(与 responseTime 中间件相同,但不设置标头):

    app.use(function(req, res, next) {
        var start = Date.now();
        res.on('header', function() {
            var duration = Date.now() - start;
            // log duration
        });
        next();
    });
    

    header 事件由 Express 中的 Connect 中间件触发,该事件已从版本 4 中删除。请按照此答案获取解决方案 - https://stackoverflow.com/a/27348342/4969957

    您可以侦听'finish' 事件,而不是侦听res 上的'header' 事件(该事件在标头发送后触发),具体取决于您要测量的内容。

    【讨论】:

    • 谢谢。正是我想要的。
    • 这是唯一一个似乎理解了 express 中间件基础知识的答案。 +1
    • 这是完美的。我将它与 Rollbar 结合使用以报告慢速路线
    • 第二个选项(带有'finish')是最好的。
    • 批准的答案有两个问题:1)我应该注意到并不是每个请求都进入“完成”状态,在现实生活中客户端可以在响应发送之前关闭连接。在这种情况下,Node.js 只发出 res.on('close') 事件。 2) JavaScript Date 类(例如 Date.getTime())有几个缺点,例如限制为毫秒(很难测量函数执行时间只有几分之一毫秒)和容易受到时钟漂移的影响。我写了一篇关于测量请求持续时间的帖子,请查看 (slao.io/blog/posts/request-duration)
    【解决方案2】:

    您可以为此使用内置的console.timeconsole.timeEnd 函数:

    console.time('handler name');
    ... handle the request
    console.timeEnd('handler name');
    

    输出到控制台:

    handler name: 62ms
    

    【讨论】:

    • 酷,这是否可以作为所有路由的节点中间件包装?
    • 如何将其应用于 node/express 应用程序?这在哪里包装所有请求?
    • 一般不能应用,不行。
    【解决方案3】:

    您可以将模块morgan 添加到您的中间件并像这样使用它-

    const morgan = require('morgan')
    ...
    ...
    const app = express()
    app.use(morgan('dev'))
    

    那么日志将如下所示:

    // :method :url :status :response-time ms - :res[content-length]
    GET /myroute 200 339.051 ms - 242
    

    检查morgan :)

    【讨论】:

      【解决方案4】:

      或者,如果您想要更大的时间分辨率,您可以使用 process.hrtime() 或使用我构建的模块,该模块使用 hrtime,但会为您提供很多额外信息,例如平均值、中位数、总时间等。该模块称为 @ 987654322@。这是一个例子:

      var t = require("exectimer");
      
      app.use(function(req, res, next) {
        var tick = new t.Tick("responseTime");
        tick.start();
        res.on('header', function() {
          tick.stop();
        });
        next();
      });
      
      // when ready check the results with this:
      var responseTime = t.timers.responseTime;
      console.log(responseTime.min()); // minimal response time
      console.log(responseTime.max()); // minimal response time
      console.log(responseTime.mean()); // mean response time
      console.log(responseTime.median()); // median response time
      

      它非常准确,具有纳秒级的分辨率,没有额外的依赖。

      【讨论】:

        【解决方案5】:
        export const measureRequestDuration = (req, res, next) => {
        const start = Date.now();
        res.once('finish', () => {
            const duration = Date.now() - start; 
            console.log("Time taken to process " + req.originalUrl + " is: " + 
          duration);
           });
         next();
        };
        

        然后

        app.use(measureRequestDuration);
        

        【讨论】:

          【解决方案6】:

          当您第一次获得请求的句柄时,只需以毫秒为单位获取当前时间(例如通过new Date()),然后是您完成响应的时间,并将差值作为经过的时间(以毫秒为单位)。

          http.createServer(function(req, res) {
            res.timeStart = new Date();
            // ...
            res.end(...);
            var timeStop = new Date();
            console.log('Elapsed ' + (timeStop-req.timeStart) + 'ms');
          });
          

          请注意,您可以减去日期,因为Date#valueOf() 返回的时间以毫秒为单位。

          【讨论】:

          • 如果我只有一个处理程序,那不是有效吗?我有几十个处理程序和端点。
          • @tbeauvais:您可以将“timeStart”附加到响应本身,请参阅我更新的答案。
          • 我用我的应用外观示例更新了我的问题。也许我遗漏了一些东西,但我仍然看不到这对多个端点如何工作(除了我向每个我试图避免的处理程序添加那段代码)。
          【解决方案7】:

          我猜 express 的响应时间中间件是 Trevor Dixon 在第一个答案中提到的。它现在允许您设置回调以获取响应时间,以防您不需要在响应中设置 X-Response-Time 标头。 https://github.com/expressjs/response-time#responsetimefn

          【讨论】:

          • 补充答案时,您可以只评论它而不是创建新答案
          猜你喜欢
          • 1970-01-01
          • 2019-06-26
          • 2017-09-27
          • 1970-01-01
          • 2018-06-10
          • 2018-10-05
          • 2022-07-04
          • 1970-01-01
          • 2016-08-20
          相关资源
          最近更新 更多