#node.js #logging #winston
#node.js #ведение журнала #winston
Вопрос:
Я использую winston logger версии 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 или мой printf()
метод неправильный?
Обратите внимание, что у меня есть репозиторий git, который воспроизводит эту проблему здесь.
Ответ №1:
ну, простое решение — добавить формат или псевдоним для временной метки 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' } ]
}
переходя к части объяснения, я на самом деле не уверен, почему временная метка перезаписывается, это довольно странно.
Комментарии:
1. Отлично, это работает, спасибо. Но как вы узнали, что указание формата исправит это?
2.Я этого не делал, это была дикая догадка. Я только что просмотрел один из своих проектов и обнаружил, что предоставляю формат даты. Я добавил это в ваш фрагмент, и это сработало. вот несколько полезных ссылок medium.com/@ThreePotatoteers/…github.com/winstonjs/logform#readme
Ответ №2:
Привет) Я пытался воспроизвести ваш случай, но не смог воспроизвести. Попробуйте этот код
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' });
Я проверил, в первом случае временная метка не определена. Во втором случае я получил временную метку: «это плохо». Winston не передает свою собственную временную метку в мою информацию журнала.
Комментарии:
1. Это потому, что в вашем
format:
свойстве не указано использовать включить временную метку. Попробуйте это (извините за форматирование):const logger = winston.createLogger({ format: winston.format.combine(winston.format.timestamp(), customFormat), transports: [ new winston.transports.Console({ level: 'debug' })]});
2. Я пошел дальше и включил более полный пример кода и репозиторий git в github.com/dland512/winston-formatting-issue