记录请求单独进行良好操作还是混乱?

时间:2016-10-04 16:03:24

标签: javascript node.js logging

我正在开发一个API,它会进行大量的调用,其中一些需要因各种原因进行彻底记录。

现在,我记录了函数中发生的所有输入/输出/处理,并且API工作正常,因此似乎没有必要增加日志记录量。

但是我想到的一个想法就是为每个传入的API调用分配一个UUID,这将跟随内部函数的记录。

虽然它会创建相当数量的附加参数来跟随每个函数中的UUID,但我想知道它是否是常见的做法,如果我应该在需要之前实现它,并且要做的更改量是管理。

例如:

显然,真正的代码要复杂得多,并且不使用console.log进行日志记录

const express = require('express'),
    fs = require('fs'),
    config = require('./config.json'),
    app = express();

function foo(bar, callback) {
    console.log(bar);
    fs.open(bar, (err, data) => {
        if(err) {
            console.err(err);
            callback(err);
        } else {
            console.log(data)
            callback(null, data);
        }
    });
}

app.get('/foo', (req, res) => {
    console.log(req.body);
    foo(req.body.bar, (err, result) => {
        if(err) {
            console.err(err);
            res.send(err);
        } else {
            console.log(result)
            res.send(null, result);
        }
    });
});

app.listen(config.port);

要:

const express = require('express'),
    UUID = require('uuid-generator'),
    fs = require('fs'),
    config = require('./config.json'),
    app = express();

function foo(uuid, bar, callback) {
    console.log(uuid + ': ' + bar);
    fs.open(bar, (err, data) => {
        if(err) {
            console.err(uuid + ': ' + err);
            callback(err);
        } else {
            console.log(uuid + ': ' + data)
            callback(null, data);
        }
    });
}

app.use((req, res, next) => {
    req.id = new UUID();
    next();
});

app.get('/foo', (req, res) => {
    console.log(req.id + ': ' + req.body);
    foo(req.id, req.body.bar, (err, result) => {
        if(err) {
            console.err(req.id + ': ' + err);
            res.send(err);
        } else {
            console.log(req.id + ': ' + result)
            res.send(null, result);
        }
    });
});

app.listen(config.port);

专家将是,如果功能失败,或者在系统崩溃的情况下,我们可以准确地识别哪个调用导致错误,以及更容易遵循哪个路径。

问题是,它需要实现的工作量不可忽略,并且可能没那么有用,因为我们已经可以推断出不同输入/输出和已经实现的其他日志记录所遵循的路径。

TL:DR :通常的做法是以如此级别的粒度记录每个请求,还是保留用于特定用例?

是否有任何工具可以将其自动化,我不应该在代码中关注它?

3 个答案:

答案 0 :(得分:1)

我无法评论这是否是一般的惯例,但对我最近研究过的产品来说,这是相当普遍的做法。

根据用例,我可以看到通过系统跟踪单个请求有很多价值。高流量API往往会从中受益,因为由微服务组成的系统可能需要通过连接服务的数字来跟踪请求。

例如,如果您有一个需要存储输入的API,那么能够将特定输入数据与失败的数据库写入相关联非常有用。

如果您确定要为请求添加UUID,那么express-request-id中间件是一个非常有用的模块,可以为您生成UUID并将其添加到响应标头中。如果传入请求标头上存在UUID,也可以使用它,而不是使用它,这对于跟踪服务之间的请求很有用。

我没有看到任何节点会抽象完全记录个别请求,但我没有找到它。

答案 1 :(得分:0)

记录请求但不是stdout / stderr或文件是一种很好的做法。最好的方法是通过TCP套接字将它发送到类似Logz.io或自己的Logstash实例(可以安装在相同或不同的机器上)。 Logstash应连接到受管AWS Elasticsearch服务或本地或远程计算机上安装的服务。 如果日志量不大,可以使用docker-compose快速组装(对于高吞吐量,我推荐专用的资源丰富的服务器)

ELK Stack是用于监控,日志聚合和优先查询的强大工具集,以便通过成千上万的日志条目查找特定请求及其详细信息。它是面向搜索的nosql数据库,已经几乎成为业界最先进的日志聚合工具之一。

Logstash通过不同协议接收日志,将它们发送到NoSQL Elasticsearch,然后您可以使用Kibana前端浏览,构建仪表板和聚合日志数据。

有理由添加已经建议的X-Request-Id标头,以及日志中的其他基础架构元数据和时间指标。

这个项目允许您在本地计算机上设置整个ELK工具集 https://github.com/deviantony/docker-elk

记录可以通过以下方式完成: - https://www.npmjs.com/package/winston(使用https://www.npmjs.com/package/winston-logstash) - https://www.npmjs.com/package/bunyanhttps://www.npmjs.com/package/bunyan-logstash

这两个库都有大量插件用于其他类型的日志记录

答案 2 :(得分:0)

  1. 你有没有看过morgan。 它是表达中间件来记录文件,数据库等中的每个请求。 可能你甚至可以将日志扔到logstash。

  2. 现在,不要将UUID作为单独的参数传递给每个函数,而是将其传递给传递给每个函数的现有数据json。

  3. 我认为您应该更改代码以在每条日志消息中包含uuid,因为它可以帮助您专注于基于uuid的大型日志文件中特定请求的跟踪。

    希望它有所帮助。