2016-10-04 60 views
7

我正在开发一个API,它会进行大量的调用,其中一些需要根据各种原因进行彻底的日志记录。会记录要求个别良好的做法或混乱?

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

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

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

例:

显然,真正的代码要复杂得多,并且记录

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); 

为了不使用console.log

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); 

亲将是,如果一个功能失败或者在系统崩溃的情况下,我们可以准确地识别哪个呼叫导致了错误,以及它跟随哪个路径d更容易。因为我们已经可以推断出已经实现的不同输入/输出和其他日志记录所遵循的路径,所以它需要一个不可忽略的工作量来实现,并且可能并不那么有用。

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

是否有任何工具可以自动执行,我不应该在代码中关心它?

回答

1

我不能真正评论这是否是一般的惯例,但对于我最近研究过的产品来说,这是相当常见的做法。

根据使用情况,我可以在通过系统跟踪单个请求时看到很多价值。高流量API倾向于从中受益,正如由微服务组成的系统一样,您可能需要通过数字连接服务来跟踪请求。

例如,如果您有一个需要存储输入的API,将特定输入数据关联到发生故障的数据库写入可能非常有用。

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

我还没有看到任何节点,将抽象记录单个请求完全离开,但我没有找到。

0

记录请求但不写入stdout/stderr或文件是一种很好的做法。最好的办法是把它发送到像Logz这样的东西。io或自己的Logstash实例(可以安装在相同或不同的机器上)通过TCP套接字。 Logstash应连接到托管的AWS Elasticsearch服务或本地或远程机器上安装的服务。 如果日志的量并不大,这可能非常快使用泊坞窗 - 撰写(高吞吐量,我建议专用足智多谋服务器)

ELK堆栈是用于监视真棒工具集组装,日志聚合,advansed查询,以便找到通过成千上万的日志条目提供具体的请求和详细信息。它是面向搜索的nosql数据库,它几乎已经成为业界最先进的日志聚合工具之一。

Logstash通过不同的协议临危日志,并将其发送到NoSQL的Elasticsearch,然后您可以浏览,建立仪表板,并使用Kibana前端收集您的日志数据。

是有原因的,以X-请求-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

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

+0

我想跟进服务器内部的请求,作出回答的人的电话。我不需要在不同的服务器之间关注它。此外,Logging已经发送到服务器,我使用'console.log'来不显示代码连接和设置日志格式。 – DrakaSAN

+1

你可以试试这个:对node.js的http://github.com/winstonjs/winston – Remario

+0

多传输异步日志库,你可以使用某种模块的日志记录 - 比如'winston' - 他们有很多的插件的支持完全不同的传输并专门为该puprose进行操作 - 配置日志记录,记录uncaughtExceptions,创建适当的访问日志(即您想要的)。 ELK可以是本地的 - 简单地根据你在OP中的要求 - 这是一个完美的匹配。本地ELK可以以非常简单的方式安装 - 使用docker-compose。 – BlackStork

0
  1. 有你看着morgan。 它是表示中间件记录文件,db等中的每个请求。 也许你甚至可以将日志记录到logstash。现在

  2. ,而不是传递到UUID每个函数作为单独的参数,通过它在现有被传递给每一个功能的数据JSON。

我想你应该改变你的代码,包括在每一个日志消息UUID,因为它会帮助你很专注于基于UUID大的日志文件特别要求的踪迹。

希望它有帮助。

+0

问题是我不会将完整的请求传递给每个函数,因为这会破坏可读性,我想要的是一个干净的方式来访问每个函数的id,而不必通过它明确地传递和混乱我的代码。摩根看起来不错,但并没有解决整个问题。 – DrakaSAN

+0

@DrakaSAN嗨,我没有说要传递req对象到每个函数来调用,只是传递uuid作为额外的值在当前json被传递作为参数函数。 – KlwntSingh

+0

@DrakaSAN如果要在java中实现同样的事情,我们使用当前请求正在执行的线程的本地缓存。我们目前正在研究的节点应用程序中也达到了同样的效果。 – KlwntSingh