112

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

这一切都很好,但现在我错过了时间戳 - 确切地知道错误发生的时间。

我可以在我的代码中进行某种搜索/替换,或者在每个文件中使用一些覆盖控制台的 npm 模块,但我不想触及每个模型/路由文件,除非我绝对必须这样做。

有没有办法,也许是 Express 中间件,可以让我为每次调用添加时间戳,还是我必须手动添加?

4

13 回答 13

134

事实证明,您可以覆盖 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
...
于 2013-09-15T23:30:02.407 回答
57

模块日志时间戳对我有用。

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
于 2018-05-11T10:16:33.377 回答
31

使用以下内容创建一个文件:

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);
于 2013-09-15T18:03:49.613 回答
20

如果您想要一个没有其他外部依赖的解决方案,但又想保留 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
于 2016-04-27T10:33:57.437 回答
9

您还可以使用log-timestamp包。它非常简单,也可以自定义。

于 2016-02-15T09:14:56.077 回答
5

这个实现很简单,支持 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 );
};
于 2018-01-14T09:12:09.957 回答
4

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

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

于 2020-01-07T14:34:53.973 回答
3

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

于 2013-09-15T15:50:38.390 回答
3
app.use(morgan('[:date[web]] :method :url :status :res[content-length] - :remote-addr - :response-time ms'))
于 2018-06-29T19:43:01.973 回答
1

您可以使用https://nodejs.org/api/util.html中的函数util.log

请注意,它自 6.0.0 版以来已被弃用。

对于更高版本,您应该“改用第三方模块”。

于 2016-01-14T14:50:25.543 回答
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.log, console.info, console.warn,console.error电话。

于 2020-05-04T07:48:42.857 回答
1

为了避免安装外部模块,一种更基本的方法可能是实现一个简单的功能,例如:

function timeStamp(message){
    console.log ( '[' + new Date().toISOString().substring(11,23) + '] -', message )
}

然后我只是这样称呼它:

timeStamp('this is my logline!!');

结果将是:

 LOG  [15:22:30.682] - this is my logline!!

当然,您可以将日期格式化为您需要的最佳格式,并将功能扩展为 console.error、debug 等。

于 2021-10-20T15:31:13.397 回答
-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)
});

快乐编码:)

于 2019-08-07T21:54:09.547 回答