Winston: Tratamento proposto de informações[SPLAT]

Criado em 12 jul. 2018  ·  4Comentários  ·  Fonte: winstonjs/winston

Qual é o recurso?

Esta é uma proposta de manipulação diferenciada de objetos (JSON/array/other) para casos de uso mais versáteis.

Em suma, esta proposta abrange duas coisas.

  1. Dividir a análise info.meta de logform.splat
  2. Crie uma nova transformação que mova objetos para options.meta

Qual problema o recurso pretende resolver?

Vários usuários (por exemplo, #1377, #1381, eu mesmo) notaram que o tratamento de objetos/matrizes é diferente em V3 de V2. Na V2 esses tipos de objetos seriam armazenados no campo options.meta e poderiam ser processados ​​separadamente da mensagem, nível e objetos.

Na V3, há apenas um cenário/transformação em que options.meta é processado da mesma forma que na V2. Isso ocorre ao usar a transformação logform.splat. O Splat analisará corretamente o meta somente quando um token estiver presente no log. POR EXEMPLO:
logger.log('info', 'this is a string I want to splat %s', 'together', {an: 'object'})
vai resultar em:
info: this is a string I want to splat together {"meta":{"an":"object"}} // with .simple() transform

Se os usuários não quiserem usar o logform.splat, o info.meta não será processado. Em vez disso, os objetos meta serão deixados intocados em info[SPLAT].

Adicionar um formulário de log que copia todas as informações[SPLAT] para info[meta] atenderá às expectativas dos usuários da V2 e será mais flexível. (Como alternativa, adicionar diretamente o info[SPLAT] à saída do registrador e fornecer documentação sobre info[meta] => info[SPLAT] pode ser aceitável.)

Uma nova transformação (por exemplo, logform.captureAllMeta apenas para nomear) pode ser tão simples quanto:

// file captureAllMeta.js psuedo-code

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

O equivalente de

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

se tornaria

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

O código extraSplat pode ser removido de splat(), pois é tratado na transformação subsequente (nova).

Um benefício adicional é que, se os usuários não quiserem usar format.splat(), eles ainda poderão incluir format.captureAllMeta() como uma transformação independente.

A ausência desse recurso está bloqueando você ou sua equipe? Se sim, como?

Agora sabendo que info[SPLAT] armazena o que está faltando em info[meta], isso pode ser considerado uma lacuna de conhecimento/documentação.

Esse recurso é semelhante a um recurso existente em outra ferramenta?

Estende a compatibilidade V2 para V3.

Este é um recurso que você está preparado para implementar, com nosso suporte?

Sim, eu posso fazer o meu melhor para apoiar isso.

Para reproduzir o problema

  • _ winston versão?_

    • [ ] winston@2

    • [X] winston@3

  • _ node -v saídas:_ 6.10.0
  • _Sistema Operacional?_ (Windows, macOS ou Linux) Qualquer
  • _Idioma?_ (todos | TypeScript XX | ES6/7 | ES5 | Dart) todos

Qual é o problema?

Aqui está uma amostra de um código de transporte V2 com saída:

        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."]

Na V3, tentei replicar isso com o código a seguir, mas o resultado não exibiu o array.

    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

Comentários muito úteis

Então, acabei de perceber que usar format.splat() adiciona um objeto meta às informações, MAS apenas se você também usar interpolação. Se você não usar interpolação, o meta será apenas misturado ao objeto info.

Além disso, ao usar interpolação e meta, o format.simple() gera a meta como {meta:{METAOBJ}} em vez de apenas {METAOBJ} como v2.

Todos 4 comentários

Eu trabalhei nisso ontem à noite e criei uma ramificação com código que implementa o acima. Deixe-me saber se você quer que eu crie um PR no Logform para isso.

Aqui está um arquivo de teste que eu usei ...

'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('---')

com as seguintes saídas...

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
---

Adicionado suporte ao meu código para info.splat além de info[SPLAT].

Algo assim é necessário. Basicamente, se você não puder atualizar para a v3 sem tocar nas instruções de log existentes E conseguir obter meta como um objeto SEPARADO APÓS a interpolação, a v3 não é inicial para a maioria dos usuários existentes. Não tenho ideia de por que alguém pensou que era uma boa ideia misturar nível, mensagem e meta em um grande objeto. Está maduro para conflitos. info[Symbol.for('splat)] também não é confiável porque irá misturar valores de interpolação e meta juntos. Queremos meta SEPARADO.

Então, acabei de perceber que usar format.splat() adiciona um objeto meta às informações, MAS apenas se você também usar interpolação. Se você não usar interpolação, o meta será apenas misturado ao objeto info.

Além disso, ao usar interpolação e meta, o format.simple() gera a meta como {meta:{METAOBJ}} em vez de apenas {METAOBJ} como v2.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

JaehyunLee-B2LiNK picture JaehyunLee-B2LiNK  ·  3Comentários

KingRial picture KingRial  ·  3Comentários

anks333 picture anks333  ·  3Comentários

Infinitay picture Infinitay  ·  3Comentários

amiram picture amiram  ·  4Comentários