Winston: Предлагаемая обработка информации[SPLAT]

Созданный на 12 июл. 2018  ·  4Комментарии  ·  Источник: winstonjs/winston

В чем особенность?

Это предложение по другой обработке объектов (JSON/массив/другое) для более универсальных вариантов использования.

Короче говоря, это предложение охватывает две вещи.

  1. Разделить синтаксический анализ info.meta из logform.splat
  2. Создайте новое преобразование, которое перемещает объекты в options.meta.

Какую проблему призвана решить функция?

Различные пользователи (например, #1377, #1381, я) отмечали, что обработка объектов/массивов в V3 отличается от V2. В V2 эти типы объектов будут храниться в поле options.meta и могут обрабатываться отдельно от сообщения, уровня и объектов.

В V3 есть только один сценарий/преобразование, в котором options.meta обрабатывается так же, как и в V2. Это при использовании преобразования logform.splat. Splat будет правильно анализировать метаданные только при наличии токена в журнале. НАПРИМЕР:
logger.log('info', 'this is a string I want to splat %s', 'together', {an: 'object'})
приведет к:
info: this is a string I want to splat together {"meta":{"an":"object"}} // with .simple() transform

Если пользователи не хотят использовать logform.splat, info.meta не будет обрабатываться. Вместо этого метаобъекты останутся нетронутыми в info[SPLAT].

Добавление формы журнала, которая копирует всю информацию [SPLAT] в информацию [meta], удовлетворит ожидания пользователей версии 2 и будет более гибким. (В качестве альтернативы может быть приемлемо прямое добавление информации [SPLAT] к выходным данным регистратора и предоставление документации по информации [meta] => info[SPLAT].)

Новое преобразование (например, logform.captureAllMeta просто для названия) может быть таким простым, как:

// file captureAllMeta.js psuedo-code

module.exports = transform((info, opts) => {
  if (info[SPLAT]) {
    info.meta = info[SPLAT]
  return info;
});

Эквивалент

format.combine(
        format.splat(),
        ...
    )

станет

format.combine(
        format.splat(),
        format.captureAllMeta(),
        ...
        // still need to have a formatter for options.meta.  maybe a separate feature request.
    )

Код extraSplat может быть удален из splat(), так как он обрабатывается в последующем (новом) преобразовании.

Дополнительным преимуществом является то, что если пользователи не хотят использовать format.splat(), они все равно могут включить format.captureAllMeta() как отдельное преобразование.

Отсутствие этой функции блокирует вас или вашу команду? Если да, то как?

Теперь, зная, что в info[SPLAT] хранится то, чего не хватает в info[meta], это можно считать пробелом в знаниях/документации.

Эта функция похожа на существующую функцию в другом инструменте?

Расширяет совместимость с версиями V2 и V3.

Готовы ли вы реализовать эту функцию при нашей поддержке?

Да, я могу сделать все возможное, чтобы поддержать это.

Чтобы воспроизвести проблему

  • _ Версия winston ?_

    • [ ] winston@2

    • [Х] winston@3

  • _ node -v выходы:_ 6.10.0
  • _Операционная система?_ (Windows, macOS или Linux) Любая
  • _Язык?_ (все | TypeScript XX | ES6/7 | ES5 | Dart) все

В чем проблема?

Вот пример транспортного кода V2 с выводом:

        logger = winston.createLogger({
            transports: [
                new (winston.transports.Console)({
                    timestamp: function () {
                        return dateFormat(Date.now(), "HH:MM:ss.l");
                    },
                    formatter: function (options) {
                        // Return string will be passed to logger.
                        return options.timestamp() + ' ' + winston.config.colorize(options.level, options.level.toUpperCase()) + ' ' + (undefined !== options.message ? options.message : '') +
                            (options.meta && Object.keys(options.meta).length ? '\n\t' + JSON.stringify(options.meta) : '');
                    },
                    colorize: true,
                    level: container.settings.get('logLevel') || 'info',
                    stderrLevels: [],
                    handleExceptions: true,
                    humanReadableUnhandledException: true
                })
            ]
        });


// results of Winston<strong i="33">@2</strong>
08:31:30.363 DEBUG Server starting complete.
        ["Server https started.","Server http started.","Server SSDP started.","Server MDNS started."]

В версии 3 я попытался воспроизвести это с помощью следующего кода, но в результате массив не отображался.

    const processObj = logform.format(info => {
             console.log('raw: ', raw)
            return info
        }
    )

    const myFormat = printf(info => {
        info.timestamp = dateFormat(Date.now(), "m/d/yy HH:MM:ss.l")
        return `${info.timestamp} ${info.level}: ${info.message}`;
    });

        logger = createLogger({
            level: container.settings.get('logLevel') || 'info',
            format: combine(
                processObj(),
                format.json(),
                timestamp({format: () => new Date().toLocaleString()}),
                format.colorize(),
                format.align(),
                format.splat(),
                myFormat
            ),
            transports: [new transports.Console()]
        });
        logger.exceptions.handle()
        logger.exitOnError = false;

results = [ 'Not starting https server.', 'Server http started.', 'Server SSDP started.', 'Server MDNS started.']
logger.debug('Server status', results)

// results of winston<strong i="6">@3</strong> -- missing the results array
6/25/18 08:16:30.501 debug:     Server starting complete.
investigate

Самый полезный комментарий

Итак, я только что понял, что использование format.splat() добавляет к информации метаобъект, НО только если вы также использовали интерполяцию. Если вы не используете интерполяцию, метаданные просто смешиваются с информационным объектом.

Также при использовании интерполяции и метаданных format.simple() выводит метаданные как {meta:{METAOBJ}}, а не просто {METAOBJ}, как v2.

Все 4 Комментарий

Я работал над этим прошлой ночью и создал ветку с кодом, реализующим вышеизложенное. Дайте мне знать, если вы хотите, чтобы я создал для этого PR в Logform.

Вот тестовый файл, который я использовал...

'use strict';

const winston = require('winston');
const logform = require('logform')
const {SPLAT} = require('triple-beam');


const {createLogger, format, transports} = require('winston');
var logger = createLogger({
    format: format.combine(

        format.splat()
        , format.captureAllMeta()
        ,
        logform.format.printf(info => {

            // return `${info.timestamp} [${info.label}] ${info.level}: ${info.message}`;
            if ((!info.meta.length)) {
                return (`${info.level}: ${info.message}`);

            }
            else {
                return (`${info.level}: ${info.message}\n\t${JSON.stringify(info.meta)}`);

            }
        })
    ),
    transports: [new transports.Console()]
});


let count = 1

logger.log('info', count + '. this is a string I want to splat %s', 'together', {an: 'object'})
count += 1
console.log('---')

logger.log('info', count + '.this is a string followed by an object and an array', {an: 'object'}, ['an', 'array'])
count += 1
console.log('---')

logger.log('info', count + '.this is a string followed by an object and an array', ['an', 'array'], {an: 'object'})
count += 1
console.log('---')


logger.log('info', count + '. string followed by', 'a string')
console.log('---')
count += 1

logger.log('info', count + '. string followed by 2', 'separate', 'strings')
console.log('---')
count += 1

logger.log('info', count + '. string followed by', {an: 'object'})
console.log('---')
count += 1

logger.log('info', count + '. string followed by 2', {an: 'object'}, ['an', 'array'])
console.log('---')
count += 1

logger.log('info', count + '. string with token followed by string %s', 'string')
console.log('---')
count += 1

logger.log('info', count + '. string with token followed by obj %j', {idunno: 'notsure'})
console.log('---')
count += 1

logger.log('info', count + '. string with token followed by string %s and then objects', 'or here', {an: 'object'}, ['i', 'am', 'missed'])
console.log('---')
count += 1

logger.log('info', count + '. string with two tokens %s %s followed by one ', 'string')
console.log('---')
count += 1

logger.log('info', count + '. string with two tokens %s %j followed by one string and one object', 'string', {an: 'object'}, [1,2,3])
count += 1
console.log('---')


logger.info({message: 'just an object', [SPLAT]: {more:'stuff'}})
count += 1
console.log('---')

logger.info(['an','array'])
count += 1
console.log('---')

logger.info(['an','array',{with:'object'}])
count += 1
console.log('---')


logger.log({
    level: 'info',
    message: '%d: The answer to life, the universe and everything',
    splat: [42]
})
count += 1
console.log('---')

logger.log({
    level: 'info',
    message: '%d: The answer to life, the universe and everything',
    splat: [43],
    [Symbol.for('splat')]: [44]
})
count += 1
console.log('---')

logger.log({
    level: 'info',
    message: '%d: The answer to life, the universe and everything'
})
count += 1
console.log('---')

со следующими выводами...

info: 1. this is a string I want to splat together
    [{"an":"object"}]
---
info: 2.this is a string followed by an object and an array
    [{"an":"object"},["an","array"]]
---
info: 3.this is a string followed by an object and an array
    [["an","array"],{"an":"object"}]
---
info: 4. string followed by
    ["a string"]
---
info: 5. string followed by 2
    ["separate","strings"]
---
info: 6. string followed by
    [{"an":"object"}]
---
info: 7. string followed by 2
    [{"an":"object"},["an","array"]]
---
info: 8. string with token followed by string string
---
info: 9. string with token followed by obj {"idunno":"notsure"}
---
info: 10. string with token followed by string or here and then objects
    [{"an":"object"},["i","am","missed"]]
---
info: 11. string with two tokens string %s followed by one
---
info: 12. string with two tokens string {"an":"object"} followed by one string and one object
    [[1,2,3]]
---
info: just an object
    [{"more":"stuff"}]
---
info: an,array
---
info: an,array,[object Object]  // expected... no %j token
---
info: 42: The answer to life, the universe and everything
---
info: 44: The answer to life, the universe and everything
---
info: %d: The answer to life, the universe and everything
---

В мой код добавлена ​​поддержка для info.splat в дополнение к info[SPLAT].

Что-то вроде этого нужно. По сути, если вы не можете перейти на v3, не касаясь существующих операторов журнала, И иметь возможность получить мета как ОТДЕЛЬНЫЙ объект ПОСЛЕ интерполяции, тогда v3 не подходит для большинства существующих пользователей. Я понятия не имею, почему кто-то решил, что это хорошая идея — смешать уровень, сообщение и мету в один большой объект. Он созрел для конфликтов. info[Symbol.for('splat)] также ненадежен, потому что он будет смешивать значения интерполяции и мета вместе. Мы хотим мета ОТДЕЛЬНО.

Итак, я только что понял, что использование format.splat() добавляет к информации метаобъект, НО только если вы также использовали интерполяцию. Если вы не используете интерполяцию, метаданные просто смешиваются с информационным объектом.

Также при использовании интерполяции и метаданных format.simple() выводит метаданные как {meta:{METAOBJ}}, а не просто {METAOBJ}, как v2.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги