我正在开发一个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 :通常的做法是以如此级别的粒度记录每个请求,还是保留用于特定用例?
是否有任何工具可以将其自动化,我不应该在代码中关注它?
答案 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/bunyan(https://www.npmjs.com/package/bunyan-logstash)
这两个库都有大量插件用于其他类型的日志记录
答案 2 :(得分:0)
你有没有看过morgan。 它是表达中间件来记录文件,数据库等中的每个请求。 可能你甚至可以将日志扔到logstash。
现在,不要将UUID作为单独的参数传递给每个函数,而是将其传递给传递给每个函数的现有数据json。
我认为您应该更改代码以在每条日志消息中包含uuid,因为它可以帮助您专注于基于uuid的大型日志文件中特定请求的跟踪。
希望它有所帮助。