我有一个完整的,部署的,基于Express的项目,其中包含许多console.log()和console.error()语句。 该项目永远运行,将stdout和stderr指向2个单独的文件。
这一切都运行得很好,但现在我错过了时间戳 - 确切地知道错误发生的时间。
我可以在我的代码中进行某种搜索/替换,或使用一些覆盖每个文件中的控制台的npm模块,但我不想触及每个模型/路由文件,除非我绝对不得不这样做。
有没有办法,也许是Express中间件,可以让我为每次调用添加时间戳,还是我必须手动添加它?
答案 0 :(得分:98)
事实证明,可以覆盖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
...
答案 1 :(得分:23)
使用以下内容创建文件:
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 :(得分:9)
您也可以使用log-timestamp包。它非常简单,也可以自定义。
答案 3 :(得分:8)
如果您想要一个没有其他外部依赖关系的解决方案但想要保留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 :(得分:3)
app.use(morgan('[:date[web]] :method :url :status :res[content-length] - :remote-addr - :response-time ms'))
答案 5 :(得分: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);
答案 6 :(得分:1)
这不是一个直接的答案,但你有没有看过winston.js?它有更多的日志记录选项,包括记录到json文件或数据库。默认情况下,它们始终具有时间戳。只是一个想法。
答案 7 :(得分:1)
您可以使用https://nodejs.org/api/util.html中的util.log
功能。
答案 8 :(得分:1)
这个实现很简单,支持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 );
};
答案 9 :(得分:1)
我正在尝试覆盖console
对象-似乎运行良好。若要使用,请将下面的代码保存在文件中,然后导入以覆盖代理对象,然后照常使用。
(请注意,这需要babel转换,并且在不支持JavaScript Proxy
构造函数(例如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
呼叫。
答案 10 :(得分:0)
像这样使用事件监听器,
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)
});
快乐的编码:)