これは、より用途の広いユースケースのためのオブジェクト(JSON /配列/その他)のさまざまな処理に関する提案です。
つまり、この提案は2つのことをカバーしています。
さまざまなユーザー(たとえば、#1377、#1381、私自身)は、オブジェクト/配列の処理がV3とV2で異なることに気づきました。 V2では、これらのオブジェクトタイプはoptions.meta
フィールドに格納され、メッセージ、レベル、およびオブジェクトとは別に処理できます。
V3では、options.metaがV2と同じように処理されるシナリオ/トランスフォームは1つだけです。 これは、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]にコピーするログフォームを追加すると、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
winston@3
node -v
出力:_6.10.0次に、出力付きの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.
私は昨夜これに取り組み、上記を実装するコードでブランチを作成しました。 このために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にアップグレードできず、補間後にメタをSEPARATEオブジェクトとして取得できる場合、v3はほとんどの既存のユーザーにとって初心者ではありません。 レベル、メッセージ、メタを1つの大きなオブジェクトに混ぜるのが良い考えだと誰もが思った理由がわかりません。 それは紛争に熟している。 info [Symbol.for( 'splat)]も、補間値とメタを混合するため、信頼性がありません。 メタセパレートが必要です。
そのため、format.splat()を使用すると、情報にメタオブジェクトが追加されることに気付きましたが、補間も使用した場合に限ります。 補間を使用しない場合、メタは情報オブジェクトに混合されるだけです。
また、補間とメタを使用する場合、format.simple()はメタをv2のような{METAOBJ}ではなく{meta:{METAOBJ}}として出力します。
最も参考になるコメント
そのため、format.splat()を使用すると、情報にメタオブジェクトが追加されることに気付きましたが、補間も使用した場合に限ります。 補間を使用しない場合、メタは情報オブジェクトに混合されるだけです。
また、補間とメタを使用する場合、format.simple()はメタをv2のような{METAOBJ}ではなく{meta:{METAOBJ}}として出力します。