Winston: 建议处理信息[SPLAT]

创建于 2018-07-12  ·  4评论  ·  资料来源: winstonjs/winston

有什么特点?

这是针对更通用的用例对对象(JSON/数组/其他)的不同处理的提议。

简而言之,这个提议包括两件事。

  1. 从 logform.splat 中拆分出 info.meta 解析
  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] 中保持不变。

添加一个将所有 info[SPLAT] 复制到 info[meta] 的 logform 将既满足 V2 用户的期望,又更加灵活。 (或者,直接将 info[SPLAT] 添加到记录器输出并提供有关 info[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

    • [X] 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."]

在 V3 中,我尝试使用以下代码复制它,但结果没有显示数组。

    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() 确实会在信息中添加一个元对象,但前提是你还使用了插值。 如果您不使用插值,则元数据只是混合到 info 对象中。

此外,当使用插值和元时,format.simple() 将元输出为 {meta:{METAOBJ}} 而不是像 v2 那样仅 {METAOBJ}。

所有4条评论

我昨晚做了这个工作,并创建了一个带有实现上述代码的分支。 如果您希望我为此在 Logform 中创建 PR,请告诉我。

这是我使用的测试文件...

'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() 确实会在信息中添加一个元对象,但前提是你还使用了插值。 如果您不使用插值,则元数据只是混合到 info 对象中。

此外,当使用插值和元时,format.simple() 将元输出为 {meta:{METAOBJ}} 而不是像 v2 那样仅 {METAOBJ}。

此页面是否有帮助?
0 / 5 - 0 等级