【问题标题】:Common logging for node, express application -- best practice?节点的通用日志记录,快速应用程序——最佳实践?
【发布时间】:2012-11-25 19:22:24
【问题描述】:

我正在开发一个带有几十个模块并使用 bunyan 进行日志记录的 node.js 应用程序(JSON 输出、多个可配置的流)。我一直在寻找如何在所有模块中实现实例的好例子,但还没有看到我可以从中学习的看起来非常干净的例子。

下面说明了一种可行的方法,但对我来说似乎很不优雅(丑陋)。我一般是 node 和 commonjs javascript 的新手,所以寻找有关如何改进它的建议。

模块:./lib/logger

// load config file (would like this to be passed in to the constructor)
nconf.file({ file: fileConfig});
var logSetting = nconf.get('log');

// instantiate the logger
var Bunyan = require('bunyan');
var log = new Bunyan({
    name: logSetting.name,
streams : [
        { stream  : process.stdout, 
        level : logSetting.stdoutLevel},
        {    path : logSetting.logfile, 
            level : logSetting.logfileLevel}
    ],
serializers : Bunyan.stdSerializers
});

function Logger() {
};

Logger.prototype.info = function info(e) { log.info(e) };
Logger.prototype.debug = function debug(e) { log.debug(e) };
Logger.prototype.trace = function trace(e) { log.trace(e) };
Logger.prototype.error = function error(e) { log.error(e) };
Logger.prototype.warn = function warn(e) {  log.warn(e) };

module.exports = Logger;

模块:主应用程序

// create the logger
var logger = require('./lib/logger)
var log = new logger();

// note: would like to pass in options -->  new logger(options)


module: any project module using logger
// open the logger (new, rely on singleton...)
var logger = require('./lib/logger');
var log = new logger();

view the gist

有什么建议吗?

编辑:

我已经修改了构造函数,使单例模式显式(而不是隐式作为“要求”行为的一部分。

var log = null;
function Logger(option) {

// make the singleton pattern explicit
if (!Logger.log) {
    Logger.log = this;
}
    return Logger.log;
};  

然后把初始化改成带个options参数

// initialize the logger 
Logger.prototype.init = function init(options) {
log = new Bunyan({
    name: options.name,
    streams : [
        { stream  : process.stdout, 
            level : options.stdoutLevel},
        {    path : options.logfile, 
            level : options.logfileLevel}
    ],
    serializers : Bunyan.stdSerializers     
    });
};

【问题讨论】:

  • 你所拥有的看起来像是使用 require 的功能构建的基本单例。您可以实现自己的单例,但不一定会更好。也许可以进行依赖注入?
  • 感谢您的回复——是的,这是一个基本的单例。有几件事困扰着我(a)单例行为是隐含的,而不是显式的,(b)我还没有找到一种干净的方式让构造函数接受参数(比如选项 JSON),而不必确定是否它们已经被前一个模块加载,并且 (c) 将引用(作为参数)传递给每个模块的替代方法看起来很混乱/冗长。
  • 感谢您的回复!是的,它是一个基本的单例,尽管它似乎是一种隐含的行为,而不是一种定义的行为。我看过 [不良做法?] (stackoverflow.com/questions/9733201/…)、[单例模式] (jasonwyatt.tumblr.com/post/8087061585/…) 以及 [对单例使用 require] (stackoverflow.com/questions/5608685/…),它们似乎比上述更能解决构造函数的行为。

标签: javascript node.js express logging bunyan


【解决方案1】:

Singleton pattern in nodejs - is it needed? 实际上,Node 的环境中可能不需要单例。您需要做的就是在一个单独的文件中创建一个记录器,例如 logger.js:

var bunyan = 要求(“bunyan”); // 班扬依赖 var logger = bunyan.createLogger({name: "myLogger"}); module.exports = 记录器;

然后,从另一个模块中检索此记录器:

var logger = require("./logger"); logger.info("任何你喜欢的");

【讨论】:

  • 我喜欢这种方法,但是在第一次使用之前如何配置记录器呢?我想以这种方式使用它,但我想设置输出路径。我尝试在 logger.js 中包含“init”函数并在其中设置“module.exports”,但这并不好。
  • @lixiang 这不是每次需要的时候都会创建一个新的logger实例吗?
  • @PixMach,不,require 模块将缓存对象实例
  • 哦,这意味着 require("./logger") 实际上是一个单例,不是吗?
  • @mogsie,是的,如果我们导出一个 object 它的单例。如果我们导出一个函数,它就不是一个单例。
【解决方案2】:

如果你在 node.js 中使用 express,那么你可以试试这个。 默认情况下,Express 中禁用日志记录。您必须做一些事情才能让日志为您的应用程序工作。对于访问日志,我们需要使用Logger中间件;对于错误日志,我们将使用 Forever。希望对您有所帮助.. 这是一个很好的例子 How to Logging Access 和 node.js 中的错误

【讨论】:

  • 谢谢,这是一个有用的参考。我已经在使用 Bunyan 的快速日志记录中间件中使用了类似的模式,我正在努力创建一个干净的包装类,它允许我在所有模块中使用相同的实例,并使用允许传入选项的初始化方法。将发布我想出的...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-02
  • 1970-01-01
  • 2018-03-27
  • 1970-01-01
  • 1970-01-01
  • 2021-08-05
  • 2010-10-08
相关资源
最近更新 更多