Winston 记录器自定义格式覆盖时间戳
Winston logger custom format overwriting timestamp
我在节点应用程序中使用 winston 记录器版本 3.3.3。我有一个用于输出的自定义格式化程序,如下所示:
const winston = require('winston');
const jsonStr = require('fast-safe-stringify');
const customFormat = winston.format.printf(data => {
const { level, message, timestamp } = data;
const args = data[Symbol.for('splat')];
let strArgs = '';
if (args) {
strArgs = args.map(jsonStr).join(' ');
}
return `${timestamp} ${level}: ${message} ${strArgs}\n`;
});
logger = winston.createLogger({
level: 'debug',
format: winston.format.combine(winston.format.timestamp(), customFormat),
transports: [new winston.transports.Console()]
});
logger.log('debug', 'hi', 123, { a: 1, b: 'two' });
logger.log('debug', 'hi', { timestamp: 'this is bad' });
这让我可以记录具有多个不同类型参数的内容:
logger.log('debug', 'hi', 123, { a: 1, b: 'two' });
> 2020-11-11T19:01:46.942Z debug: hi 123 {"a":1,"b":"two"}
这就是我想要的。问题是,如果我记录一个包含名为 timestamp
的字段的对象,它会覆盖格式化程序中的 timestamp
字段。
logger.log('debug', 'hi', { timestamp: 'this is bad' } );
> this is bad debug: hi {"timestamp":"this is bad"}
所以现在记录器的时间戳是字符串 "this is bad"
,这是不好的。如果我将 data
参数输出到 printf()
方法,我会看到:
{
timestamp: 'this is bad',
level: 'debug',
message: 'hi',
[Symbol(level)]: 'debug',
[Symbol(splat)]: [ { timestamp: 'this is bad' } ] }
}
所以你可以看到 timestamp
字段显然被我传入的参数覆盖了。只有当 log()
方法的第三个参数是一个对象时才会发生这种情况属性 称为 timestamp
。所以这很好:
logger.log('debug', 'hi', 123, { timestamp: 'this is fine' } );
data: {
level: 'debug',
message: 'hi',
timestamp: '2020-11-11T19:08:27.326Z',
[Symbol(level)]: 'debug',
[Symbol(splat)]: [ 123, { timestamp: 'this is fine' } ]
}
> 2020-11-11T19:08:27.326Z debug: hi 123 {"timestamp":"this is fine"}
这是winston的bug还是我的printf()
方法不对?
请注意,我有一个重现此问题的 git 存储库 here。
嘿)我试图重现你的案例,但我无法重现。试试这个代码
const winston = require('winston');
const customFormat = winston.format.printf((data) => {
const { level, message, timestamp } = data;
console.log('data', data);
const args = data[Symbol.for('splat')];
let strArgs = '';
if (args) {
console.log('args', args);
strArgs = args.map((argument) => JSON.stringify(argument)).join(' ');
}
return `${timestamp} ${level}: ${message} ${strArgs}\n`;
});
const logger = winston.createLogger({
format: customFormat,
transports: [
new winston.transports.Console({
level: 'debug',
}),
],
});
logger.log('debug', 'hi', 123, { a: 1, b: 'two' });
// logger.log('debug', 'hi', { timestamp: 'this is bad' });
我检查过,在第一种情况下时间戳未定义。在第二种情况下,我得到了时间戳:'this is bad'。温斯顿没有将他自己的时间戳传递到我的日志信息中。
一个简单的解决方案是在 timeStamp.format()
中为时间戳添加格式或别名,如下所示
logger = winston.createLogger({
level: 'debug',
format: winston.format.combine(
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), // can also alias
customFormat
),
transports: [new winston.transports.Console()]
});
logger.log('debug', 'hi', { timestamp: 'this is bad' } );
// outputs
2020-11-19 20:08:36 debug: hi {"timestamp":"this is bad"}
{
timestamp: '2020-11-19 20:08:36',
level: 'debug',
message: 'hi',
[Symbol(level)]: 'debug',
[Symbol(splat)]: [ { timestamp: 'this is bad' } ]
}
来到解释部分我实际上不确定为什么 timeStamp 被覆盖这很奇怪。
我在节点应用程序中使用 winston 记录器版本 3.3.3。我有一个用于输出的自定义格式化程序,如下所示:
const winston = require('winston');
const jsonStr = require('fast-safe-stringify');
const customFormat = winston.format.printf(data => {
const { level, message, timestamp } = data;
const args = data[Symbol.for('splat')];
let strArgs = '';
if (args) {
strArgs = args.map(jsonStr).join(' ');
}
return `${timestamp} ${level}: ${message} ${strArgs}\n`;
});
logger = winston.createLogger({
level: 'debug',
format: winston.format.combine(winston.format.timestamp(), customFormat),
transports: [new winston.transports.Console()]
});
logger.log('debug', 'hi', 123, { a: 1, b: 'two' });
logger.log('debug', 'hi', { timestamp: 'this is bad' });
这让我可以记录具有多个不同类型参数的内容:
logger.log('debug', 'hi', 123, { a: 1, b: 'two' });
> 2020-11-11T19:01:46.942Z debug: hi 123 {"a":1,"b":"two"}
这就是我想要的。问题是,如果我记录一个包含名为 timestamp
的字段的对象,它会覆盖格式化程序中的 timestamp
字段。
logger.log('debug', 'hi', { timestamp: 'this is bad' } );
> this is bad debug: hi {"timestamp":"this is bad"}
所以现在记录器的时间戳是字符串 "this is bad"
,这是不好的。如果我将 data
参数输出到 printf()
方法,我会看到:
{
timestamp: 'this is bad',
level: 'debug',
message: 'hi',
[Symbol(level)]: 'debug',
[Symbol(splat)]: [ { timestamp: 'this is bad' } ] }
}
所以你可以看到 timestamp
字段显然被我传入的参数覆盖了。只有当 log()
方法的第三个参数是一个对象时才会发生这种情况属性 称为 timestamp
。所以这很好:
logger.log('debug', 'hi', 123, { timestamp: 'this is fine' } );
data: {
level: 'debug',
message: 'hi',
timestamp: '2020-11-11T19:08:27.326Z',
[Symbol(level)]: 'debug',
[Symbol(splat)]: [ 123, { timestamp: 'this is fine' } ]
}
> 2020-11-11T19:08:27.326Z debug: hi 123 {"timestamp":"this is fine"}
这是winston的bug还是我的printf()
方法不对?
请注意,我有一个重现此问题的 git 存储库 here。
嘿)我试图重现你的案例,但我无法重现。试试这个代码
const winston = require('winston');
const customFormat = winston.format.printf((data) => {
const { level, message, timestamp } = data;
console.log('data', data);
const args = data[Symbol.for('splat')];
let strArgs = '';
if (args) {
console.log('args', args);
strArgs = args.map((argument) => JSON.stringify(argument)).join(' ');
}
return `${timestamp} ${level}: ${message} ${strArgs}\n`;
});
const logger = winston.createLogger({
format: customFormat,
transports: [
new winston.transports.Console({
level: 'debug',
}),
],
});
logger.log('debug', 'hi', 123, { a: 1, b: 'two' });
// logger.log('debug', 'hi', { timestamp: 'this is bad' });
我检查过,在第一种情况下时间戳未定义。在第二种情况下,我得到了时间戳:'this is bad'。温斯顿没有将他自己的时间戳传递到我的日志信息中。
一个简单的解决方案是在 timeStamp.format()
中为时间戳添加格式或别名,如下所示
logger = winston.createLogger({
level: 'debug',
format: winston.format.combine(
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), // can also alias
customFormat
),
transports: [new winston.transports.Console()]
});
logger.log('debug', 'hi', { timestamp: 'this is bad' } );
// outputs
2020-11-19 20:08:36 debug: hi {"timestamp":"this is bad"}
{
timestamp: '2020-11-19 20:08:36',
level: 'debug',
message: 'hi',
[Symbol(level)]: 'debug',
[Symbol(splat)]: [ { timestamp: 'this is bad' } ]
}
来到解释部分我实际上不确定为什么 timeStamp 被覆盖这很奇怪。