我有一个完整的,已部署的,基于Express的项目,整个过程中都有许多console.log()和console.error()语句。该项目永远使用,将stdout和stderr定向到2个单独的文件。
一切都很好,但是现在我缺少时间戳了-确切知道何时发生错误。
我可以在整个代码中进行某种搜索/替换,或者使用某些npm模块来覆盖每个文件中的控制台,但是除非绝对必要,否则我不想触摸每个模型/路径文件。
有没有一种方法,也许是Express中间件,可以让我在每个调用中添加时间戳,还是必须手动添加?
我有一个完整的,已部署的,基于Express的项目,整个过程中都有许多console.log()和console.error()语句。该项目永远使用,将stdout和stderr定向到2个单独的文件。
一切都很好,但是现在我缺少时间戳了-确切知道何时发生错误。
我可以在整个代码中进行某种搜索/替换,或者使用某些npm模块来覆盖每个文件中的控制台,但是除非绝对必要,否则我不想触摸每个模型/路径文件。
有没有一种方法,也许是Express中间件,可以让我在每个调用中添加时间戳,还是必须手动添加?
Answers:
事实证明,您可以覆盖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
...
模块:“ 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
创建具有以下内容的文件:
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);
如果您想要一个没有其他外部依赖关系的解决方案,但又想保留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
您也可以使用log-timestamp包。这非常简单,也可以自定义。
此实现很简单,支持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 );
};
如果愿意,可以通过扩展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);
这不是直接的答案,但是您是否研究过winston.js?它具有更多的日志记录选项,包括记录到json文件或数据库。这些默认情况下总是带有时间戳。只是一个想法。
我正在尝试覆盖该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电话。