向所有控制台消息添加时间戳


93

我有一个完整的,已部署的,基于Express的项目,整个过程中都有许多console.log()和console.error()语句。该项目永远使用,将stdout和stderr定向到2个单独的文件。

一切都很好,但是现在我缺少时间戳了-确切知道何时发生错误。

我可以在整个代码中进行某种搜索/替换,或者使用某些npm模块来覆盖每个文件中的控制台,但是除非绝对必要,否则我不想触摸每个模型/路径文件。

有没有一种方法,也许是Express中间件,可以让我在每个调用中添加时间戳,还是必须手动添加?


Answers:


116

事实证明,您可以覆盖app.js文件顶部的控制台功能,并使它在所有其他模块中生效。我得到的结果好坏参半,因为我的一个模块被分叉为child_process。一旦将行也复制到该文件的顶部,所有工作就可以了。

作为记录,我安装了模块console-stamp(npm install console-stamp --save),并将此行添加到app.js和childProcess.js的顶部:

// add timestamps in front of log messages
require('console-stamp')(console, '[HH:MM:ss.l]');

我现在的问题是,:date连接记录器的格式使用UTC格式,而不是我在其他控制台调用中使用的格式。通过注册我自己的时间格式可以很容易地解决此问题(并且,副作用是,需要使用随附的dateformat模块console stamp,而不是安装另一个模块):

// since logger only returns a UTC version of date, I'm defining my own date format - using an internal module from console-stamp
express.logger.format('mydate', function() {
    var df = require('console-stamp/node_modules/dateformat');
    return df(new Date(), 'HH:MM:ss.l');
});
app.use(express.logger('[:mydate] :method :url :status :res[content-length] - :remote-addr - :response-time ms'));

现在,我的日志文件看起来井井有条(更好的是,可解析):

[15:09:47.746] staging server listening on port 3000
[15:09:49.322] connected to database server xxxxx successfully
[15:09:52.743] GET /product 200 - - 127.0.0.1 - 214 ms
[15:09:52.929] GET /stylesheets/bootstrap-cerulean.min.css 304 - - 127.0.0.1 - 8 ms
[15:09:52.935] GET /javascripts/vendor/require.js 304 - - 127.0.0.1 - 3 ms
[15:09:53.085] GET /javascripts/product.js 304 - - 127.0.0.1 - 2 ms
...

2
我找不到它的文档,但看来“:mm”表示月份,“:MM”是您实际要使用的格式
Laurent Sigal 2014年

2
您应该根据@ user603124的内容更改分钟部分。在几分钟内,字符串为:MMgithub.com/starak/node-console-stamp
sucotronic 2014年

感谢您的评论。更正!
旅行技术专家

2
好像你不再需要包装HH:MM:ss.l括号-它会自动做
杰夫


34

模块:“ log-timestamp”对我有用。

参见 https://www.npmjs.com/package/log-timestamp

npm install log-timestamp

使用简单

console.log('Before log-timestamp');
require('log-timestamp');
console.log('After log-timestamp');

结果

Before log-timestamp
[2012-08-23T20:08:32.000Z] After log-timestamp

26

创建具有以下内容的文件:

var log = console.log;

console.log = function(){
  log.apply(console, [Date.now()].concat(arguments));
};

在您记录任何内容之前,请先在您的应用程序中使用它。为...做同样的事情console.error如果需要,请。

请注意,console.log("he%s", "y") // "hey"如果您使用此解决方案,它将破坏变量插入()。如果需要,只需先记录时间戳:

log.call(console, Date.now());
log.apply(console, arguments);

2
如果是相同的应用程序/进程,则不会。控制台是一个全局对象,因此,如果您劫持这样的一个功能,它将继续为共享该全局对象的所有文件劫持。
Andreas Hultgren 2013年

因此,应该/应该将其放置在app.js文件中?
Traveling Tech Guy 2013年

1
是。<最少15个字符...>
Andreas Hultgren

1
我建议改用console-stamp
Jacek Pietal,2016年

1
这不是一个好的解决方案-它要么破坏变量插入(因此不能用作替换变量),要么在不同的行上打印日期和日志输出。
乔治Y.

16

如果您想要一个没有其他外部依赖关系的解决方案,但又想保留console.log的全部功能(多个参数,变量插入),则可以使用以下代码:

var log = console.log;

console.log = function () {
    var first_parameter = arguments[0];
    var other_parameters = Array.prototype.slice.call(arguments, 1);

    function formatConsoleDate (date) {
        var hour = date.getHours();
        var minutes = date.getMinutes();
        var seconds = date.getSeconds();
        var milliseconds = date.getMilliseconds();

        return '[' +
               ((hour < 10) ? '0' + hour: hour) +
               ':' +
               ((minutes < 10) ? '0' + minutes: minutes) +
               ':' +
               ((seconds < 10) ? '0' + seconds: seconds) +
               '.' +
               ('00' + milliseconds).slice(-3) +
               '] ';
    }

    log.apply(console, [formatConsoleDate(new Date()) + first_parameter].concat(other_parameters));
};

您可以修改formatConsoleDate函数以设置所需日期的格式。

此代码仅需在您的主JavaScript文件顶部编写一次。

console.log("he%s", "y") 将打印如下内容:

[12:22:55.053] hey

4
谢谢,这个“没有依赖项”的答案正是我所需要的。
RdR


3
app.use(morgan('[:date[web]] :method :url :status :res[content-length] - :remote-addr - :response-time ms'))

2

此实现很简单,支持console.log的原始功能(传递单个对象和变量替换),不使用外部模块,并且在对console.log的一次调用中打印了所有内容:

var origlog = console.log;

console.log = function( obj, ...placeholders ){
    if ( typeof obj === 'string' )
        placeholders.unshift( Date.now() + " " + obj );
    else
    {
        // This handles console.log( object )
        placeholders.unshift( obj );
        placeholders.unshift( Date.now() + " %j" );
    }

    origlog.apply( this, placeholders );
};

2

如果愿意,可以通过扩展Node在“ Console”类中的构建来为应用程序创建自定义记录器。请参考以下实现

"use strict";

const moment = require('moment');
const util = require('util');
const Console = require('console').Console;

class Logger extends Console {
    constructor(stdout, stderr, ...otherArgs) {
        super(stdout, stderr, ...otherArgs);
    }

    log(...args) {
        super.log(moment().format('D MMM HH:mm:ss'), '-', util.format(...args));
    }

    error(...args) {
        super.error(moment().format('D MMM HH:mm:ss'), '-', util.format(...args));
    }
}

module.exports = (function() {
    return new Logger(process.stdout, process.stderr); 
}());

之后,您可以在代码中将其用作:

const logger = require('./logger');

logger.log('hello world', 123456);
logger.error('some error occurred', err);


1

这不是直接的答案,但是您是否研究过winston.js?它具有更多的日志记录选项,包括记录到json文件或数据库。这些默认情况下总是带有时间戳。只是一个想法。


我已经研究过很多事情,现在,我想的东西添加到现有部署项目-不接触太多的代码
旅游科技人


1

我正在尝试覆盖该console对象-似乎运行良好。若要使用,请将下面的代码保存在文件中,然后导入以覆盖代理对象,然后照常使用。

(请注意,这需要babel转换,并且在不支持JavaScriptProxy构造函数的环境(例如IE 11)中无法使用)。

import console from './console-shadow.js'

console.log(...)
console.warn(...)
console.error(...)
// console-shadow.js

// Only these functions are shadowed by default
const overwrites = ['log', 'warn', 'info', 'error']

export default new Proxy(
  // Proxy (overwrite console methods here)
  {},

  // Handler
  {
    get: (obj, prop) =>
      prop in obj
        ? obj[prop]
        : overwrites.includes(prop)
        ? (...args) => console[prop].call(console, new Date(), ...args)
        : console[prop],
  }
)

基本上,我使用JavaScript代理对象覆盖了控制台对象。打电话时.log.warn等时,被覆盖的控制台将检查您所调用的函数是否是函数,如果是,它将在日志语句中插入一个日期作为第一个参数,然后是所有参数。

我认为该console对象实际上有很多作用,但我并不完全了解。所以,我只能拦截console.logconsole.infoconsole.warnconsole.error电话。


-1

这样使用事件监听器,

process.on('error', function() { 
   console.log('Error Occurred.');

   var d = Date(Date.now()).toString();
   console.log.call(console, d); // Wed Aug 07 2019 23:40:07 GMT+0100 (GMT+01:00)
});

快乐的编码:)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.