Winston: [3.0.0]゚ラヌオブゞェクトが解析たたは出力されない

䜜成日 2018幎05月29日  Â·  68コメント  Â·  ゜ヌス: winstonjs/winston

あなたの環境に぀いお教えおください

  • _ winstonバヌゞョン_
  • _ node -v出力_v8.11.1
  • _オペレヌティングシステム_Windows、macOS、たたはLinuxmacOS
  • _Language_すべお| TypeScript XX | ES6 / 7 | ES5 | Dartすべお

䜕が問題ですか

ノヌドErrorオブゞェクトをログに蚘録するず、空のメッセヌゞが衚瀺されたす。

䟋

const winston = require('winston');
const { createLogger, format, transports } = winston;

const logger = createLogger({
  transports: [
    new transports.Console()
  ]
});

let err = new Error('this is a test');
logger.log({level: 'error', message: err});

結果の出力

% node test.js
{"level":"error","message":{}}

たた

logger.error(new Error('hello'))

結果

{"level":"error"}

代わりに䜕が起こるず思いたすか

メッセヌゞキヌには、少なくずも゚ラヌメッセヌゞが含たれおいるず思いたす。 カスタムフォヌマッタを詊しおみるず、 infoも゚ラヌオブゞェクトが含たれおいないため、どこかで削陀する必芁がありたすか

その他の情報

私がどのように手助けできるか教えおください-PRをフリックしお幞せですが、 [email protected]呚りの道がただわかりたせん

bug important

最も参考になるコメント

いいえ、これはロギングラむブラリには受け入れられたせん。
メンテナは、カスタムのprintf圢匏ず非json圢匏を定矩し、logger.error "something"、errやloggerなどを䜿甚しお゚ラヌをログに蚘録できる、゚ラヌをログに蚘録する方法が瀺されおいるドキュメントに、よく匷調された䟋を配眮するだけです。 .errorerr
りィンストンは玠晎らしいようでしたが、この問題は信じられないほど受け入れられたせん

党おのコメント68件

これに぀いおはテストカバレッゞがありたすが、明らかにもっず必芁です。 裏で䜕が起こっおいるのか

  1. ErrorむンスタンスはobjectModeストリヌムパむプチェヌンに沿っお枡されたす
  2. Loggerのデフォルトの圢匏はjson  logform json圢匏コヌドをlogform 
  3. messageずstackのプロパティError原因である非可算JSON.stringify 1には期埅しおいないこずを出力に䜕か。
console.log(JSON.stringify(new Error('lol nothing here')));
// '{}'

蚭蚈の芳点から、 winston@3は、パフォヌマンスを向䞊させるために、たさにこの皮の問題に察しおformatsを導入したした。 パフォヌマンスに぀いお蚀えば、興味深いこずに、 pinoはここで䜕か面癜いこずをしたす。 おそらく、解決策は、デフォルトのjson圢匏でasJsonに䌌たものを実装するこずです。

誰かが簡単な回避策を探しおいるなら、今のずころロガヌのフォヌマットにenumerateErrorFormatを含めるこずができたす。 来週の3.0.0前たたは3.0.1盎埌にこれを修正できるこずを願っおいたす。

const winston = require('../');
const { createLogger, format, transports } = winston;

const enumerateErrorFormat = format(info => {
  if (info.message instanceof Error) {
    info.message = Object.assign({
      message: info.message.message,
      stack: info.message.stack
    }, info.message);
  }

  if (info instanceof Error) {
    return Object.assign({
      message: info.message,
      stack: info.stack
    }, info);
  }

  return info;
});

const logger = createLogger({
  format: format.combine(
    enumerateErrorFormat(),
    format.json()
  ),
  transports: [
    new transports.Console()
  ]
});

// Error as message
console.log('Run FIRST test...');
logger.log({ level: 'error', message: new Error('FIRST test error') });

// Error as info (one argument)
console.log('\nRun SECOND test...');
const err = new Error('SECOND test error');
err.level = 'info';
logger.info(err);

// Error as info (two arguments);
console.log('\nRun THIRD test...');
logger.log('info', new Error('THIRD test error'));

@indexzero 、私はあなたの回避策に埓おうずしたしたが、それは機胜しおいたせん。 なぜなのかご存知ですか

フォヌマッタヌ
`` ` javascript const level = settings.debug ? 'debug' : 'info'; const printFormat = winston.format.printf(info => $ {info.timestamp}-$ {info.level}$ {info.message}`;
const enumerateErrorFormat = winston.formatinfo => {
ifinfo.message instanceof Error{
info.message = Object.assign{
メッセヌゞinfo.message.message、
スタックinfo.message.stack、
}、info.message;
}
ifinfo instanceof Error{
Object.assign{を返す
メッセヌゞinfo.message、
スタックinfo.stack、
}、情報;
}
情報を返す;
};

const consoleLogger = winston.createLogger{
レベル、
フォヌマットwinston.format.timestamp、
トランスポヌト[
new winston.transports.Console{
フォヌマットwinston.format.combine
winston.format.colorize、
enumerateErrorFormat、
printFormat、
、
}、
]、
};
Code: javascript
{を詊しおください
//コヌドスロヌ゚ラヌ
} catcherr{
logger.errorerr;
}
Output:
2018-06-28T211725.140Z-゚ラヌ未定矩
Info object: javascript
{レベル '\ u001b [31merror \ u001b [39m'、タむムスタンプ '2018-06-28T211725.140Z'、[蚘号レベル] '゚ラヌ'}
「」
゚ラヌログのメッセヌゞ属性はどこにありたすか

@sandrocsimasロガヌを機胜させるには、ロガヌのデフォルトのフォヌマッタヌにenumerateErrorFormat関数を指定する必芁があるこずに気づきたした。

フォヌマッタヌ

const consoleLogger = winston.createLogger({
  level,
  format: winston.format.combine(
    winston.format.timestamp(),
    enumerateErrorFormat()
  ),
  transports: [
    new winston.transports.Console({
      format: winston.format.combine(
        winston.format.colorize(),
        printFormat,
      ),
    }),
  ],
});

なぜなのかただわからない

@sandrocsimasず同じバグが発生しおいるず思いたす。

これが私のロガヌ蚭定です

logger.js

const winston = require('winston');
const {configure, format} = winston;
const {combine, colorize, timestamp, printf} = format;

const enumerateErrorFormat = format(info => {
  if (info.message instanceof Error) {
    info.message = Object.assign({
      message: info.message.message,
      stack: info.message.stack
    }, info.message);
  }

  if (info instanceof Error) {
    return Object.assign({
      message: info.message,
      stack: info.stack
    }, info);
  }

  return info;
});

const myConsoleFormat = printf(info => {
  console.log('** Info Object: **');
  console.log(info);
  console.log('** Winston Output: **');
  return `${info.level}: ${info.message}`;
});

winston.configure({
  transports: [
    new winston.transports.Console({
      format: combine(
        colorize(),
        enumerateErrorFormat(),
        myConsoleFormat
      ),
    })
  ]
});

このコヌドブロックでテストするず、次のようになりたす。

テストA

const logger = require('winston');
try {
  throw(new Error());
} catch (err) {
  logger.error(err);
}

new Error()メッセヌゞ倀が含たれおいない堎合、次の出力が埗られたす。

出力A

** Info Object: **
{ message: 
   { message: '',
     stack: 'Error\n    at Object.<anonymous> (app.js:21:9)\n    at Module._compile (module.js:652:30)\n    at Object.Module._extensions..js (module.js:663:10)\n    at Module.load (module.js:565:32)\n    at tryModuleLoad (module.js:505:12)\n    at Function.Module._load (module.js:497:3)\n    at Module.require (module.js:596:17)\n    at require (internal/module.js:11:18)\n    at Object.<anonymous> (server.js:11:13)\n    at Module._compile (module.js:652:30)' },
  level: '\u001b[31merror\u001b[39m',
  [Symbol(level)]: 'error',
  [Symbol(message)]: '{"message":{},"level":"error"}' }
** Winston Output: **
error: [object Object]

error: [object Object]はたさに私が期埅したものです

ただし、このコヌドブロックでテストするず、次のようになりたす。

テストB

const logger = require('winston');
try {
  throw(new Error('This causes error: undefined'));
} catch (err) {
  logger.error(err);
}

new Error()メッセヌゞ倀が含たれおいる堎合、次の出力が埗られたす。

出力B

** Info Object: **
{ level: '\u001b[31merror\u001b[39m',
  [Symbol(level)]: 'error',
  [Symbol(message)]: '{"level":"error"}' }
** Winston Output: **
error: undefined

ご芧のずおり、 @ sandrocsimasず同じerror: undefinedを取埗したす。 error: [object Object]を手に入れるず思っおいたした

このコヌドブロックを詊しおみるず、次のこずに泚意しおください。

テストC

const logger = require('winston');
try {
  throw(new Error('This should work'));
} catch (err) {
  logger.log({level: 'error', message: err});
}

logger.log代わりにlogger.errorを䜿甚するず、䞊蚘の出力Aず同じ出力が埗られたす。

私は同じ問題を抱えおいたす。 私はりィンストンが初めおです。 @indexzero゜リュヌションを詊し

@ nvtuan305 、 たしたか、それずも少し線集したしたか もしそうなら、サンプルコヌドを提䟛できたすか 圌のコヌドは、 logger.log({level: ____, message: err});を䜿甚しおいる堎合は機胜するはずです。 logger.info 、 logger.error 、たたはその他のlogger.<level>おいる堎合は機胜したせん。 。 これは䞊蚘で指定したバグであり、今埌のリリヌスで修正されるはずです。

私は䜕かが足りないのでしょうか、それずもconsole.log / error / warnから簡単に埗られるのず同じ出力を埗るのは完党な頭痛の皮たたは䞍可胜でさえありたすかですか

try {
   // ...
  throw new Error('foo');
} catch (e) {
  console.error('Caught error:', e);  // convenient, informative
  logger.error('Caught error:', e);  // nope, the second parameter is something else (couldn't find docs)
  logger.error(`Caught error: ${e}`);  // stack lost
  logger.error(`Caught error: ${JSON.stringify(e)}`);  // Caught error: {}
}

ず同じ出力を取埗するための同等のりィンストンコヌドは䜕ですか
console.error('Caught error:', error); 

たた、ロガヌオブゞェクトのコンビニ゚ンスメ゜ッドによっお取埗されるパラメヌタヌのドキュメントはどこにありたすか

@dandv

logger.error('Caught error:', e);

console.log()ずは異なり、りィンストンのlogger.<level>(message)はメッセヌゞず呌ばれるパラメヌタを1぀だけ取るため、これは機胜したせん。 そのメッセヌゞパラメヌタはオブゞェクトたたは文字列のいずれかです私が間違っおいる堎合は誰かが私を修正したすが、それは私の理解です。

logger.log({level: <level>, message: <message>})も䜿甚できるこずに泚意しおください。 これらの2぀の関数の詳现に぀いおは、ドキュメントのこの郚分を読むこずをお勧めしたすログレベルのWinstonDocs 。 ロギングレベルの䜿甚を必ずお読みください

logger.error(`Caught error: ${e}`);

なぜこれがスタックを出力しないのかを明確に蚀うこずはできたせんが、これがりィンストンの問題ではないこずは知っおいたす。 console.log(`Caught error: ${e}`)を詊しおみるず、スタックも含たれおいたせん。 私はテンプレヌトリテラルをあたり䜿甚しおいないので、テンプレヌトリテラルがオブゞェクトでうたく機胜しないか、javascriptのconsole.logがオブゞェクトを゚ラヌオブゞェクトずしお認識し、メッセヌゞプロパティのみを出力したす。 それが私の䞀番の掚枬です。

logger.error(`Caught error: ${JSON.stringify(e)}`)

これは、このバグスレッドの栞心になりたす。 たず、JavaScriptに関する技術的な詳现を理解する必芁がありたす。 console.log(`Caught error: ${JSON.stringify(e)}`)を詊しおみるず、同じ出力Caught error: {}も埗られるこずに泚意しおください。 @indexzeroが説明したように

messageずstack特性にError原因ずなる非列挙されおいるJSON.stringify出力に1が期埅しおいないこずを䜕かを。

基本的に、 messageプロパティずstackプロパティは列挙できないため、 JSON.stringifyはこれらのプロパティをスキップし、空のオブゞェクト{}たす。 列挙可胜性をよりよく理解するには、この列挙可胜性ずプロパティの所有暩を読むこずをお勧めし

幞いなこずに、winston 3.0の蚭蚈方法winstonチヌムぞの小道具により、@ indexzeroが提䟛したこの回避策がありたす。 説明を手䌝いたす。 たず、次の関数を䜜成したす。

const enumerateErrorFormat = format(info => {
  if (info.message instanceof Error) {
    info.message = Object.assign({
      message: info.message.message,
      stack: info.message.stack
    }, info.message);
  }

  if (info instanceof Error) {
    return Object.assign({
      message: info.message,
      stack: info.stack
    }, info);
  }

  return info;
});

ドキュメントStreams、objectMode、およびinfoオブゞェクトから、infoオブゞェクトにはinfo.levelずinfo.message 2぀のプロパティがありたす。 そのinfo.messageそれはあなたが枡されたすべおの堎合、゚ラヌオブゞェクトであるプロパティ。我々は新しいオブゞェクトを䜜成だからmessage.stackずmessage.message ず考えおError.stackずError.message が列挙可胜になり、その゚ラヌオブゞェクトにアタッチされる可胜性のある他のプロパティが含たれたす。

次に、䞊蚘のenumerateErrorFormat()関数を䜿甚するこのロガヌを䜜成したす。

const logger = createLogger({
  format: format.combine(
    enumerateErrorFormat(),
    format.json()
  ),
  transports: [
    new transports.Console()
  ]
});

これは、枡したmessageを受け取り、それが゚ラヌオブゞェクトであるかどうかを確認したす。 そうであれば、列挙の問題を修正したす。 次に、メッセヌゞをformat.jsonに枡したす。これにより、オブゞェクト゚ラヌかどうかが文字列化されたす。 それがオブゞェクトでない堎合、それは文字列であり、 format.json Effectivleyは䜕もしたせん、そしおあなたは家に垰りたせん

それでも、゚ラヌオブゞェクトは䞀般的にログに蚘録されるため、そのenumerateErrorFormatを䜜成する必芁がない堎合は䟿利です。 私が理解しおいるように、winstonチヌムは、埌のバヌゞョンでリリヌスされる修正に取り組んでいたす。

いく぀かの最埌のメモ。 これは、メッセヌゞが゚ラヌオブゞェクトであるlogger.log({level: <level>, message: <message>})を䜿甚する堎合にのみ機胜したす。 䟋

try {
  throw(new Error('This should work'));
} catch (err) {
  logger.log({level: 'error', message: err});
}

䞊蚘の他の投皿で説明したように、winstonにはこのコヌドが機胜しない別のバグがありたす。

try {
  throw(new Error('This will not work'));
} catch (err) {
  logger.error(err);
}

logger.error(err)を䜿甚するず、䜕らかの理由でinfo.messageプロパティが定矩されたせん。 うたくいけば、 @ indexzeroはこれを

@ SamuelMaddox17 @indexzeroありがずうございたす logger.log({level: 'error', message: err});を䜿っおみたしたが、うたくいきたした

これはlogger.errorなどで修正できたすか

logger.logを䜿甚するのは面倒で冗長です。特に、 logger.errorを䜿甚するず、耇数の匕数を簡単に远加できるためです。

ねえ、私はこれを調べおいたす。 @indexzero それでも、enumerateErrorFormat機胜をjsonフォヌマッタヌに远加するのが最善のアむデアだず思いたすか 私たちは別に気にする必芁がありたすかに぀いおの堎合はmetaあるErrorだけではなく、 object 私たちはたた、そのような堎合に察凊しおいない堎合、人々は文句を蚀うだろう掚枬しおいたす  たた、私はmasterを䜿甚しおいたすが、䞊蚘の@indexzero / @ SamuelMaddox17による゜リュヌションでは、 logger.error機胜しおいるようです。

const winston = require('winston');
const format = winston.format;

const enumerateErrorFormat = format(info => {
  if (info.message instanceof Error) {
    info.message = Object.assign({
      message: info.message.message,
      stack: info.message.stack
    }, info.message);
  }

  if (info instanceof Error) {
    return Object.assign({
      message: info.message,
      stack: info.stack
    }, info);
  }

  return info;
});

const logger = winston.createLogger({
  level: 'debug',
  format: format.combine(
    enumerateErrorFormat(),
    format.json()
  ),
  transports: [
    new winston.transports.Console(),
  ],
});

logger.error(new Error('whatever'));

さらに調査したずころ、䞊蚘で説明したlogger.error問題は、デフォルトのロガヌを䜿甚した堎合の問題にすぎないようです。 @DABH 、私はあなたのコヌドを詊したした、そしおそれは私のために働きたす、しかし私がそれをデフォルトのロガヌに切り替えるずき、それは働きたせん

const winston = require('winston');
const format = winston.format;

const enumerateErrorFormat = format(info => {
  if (info.message instanceof Error) {
    info.message = Object.assign({
      message: info.message.message,
      stack: info.message.stack
    }, info.message);
  }

  if (info instanceof Error) {
    return Object.assign({
      message: info.message,
      stack: info.stack
    }, info);
  }

  return info;
});

winston.configure({
  transports: [
    new winston.transports.Console({
      level: 'debug',
      format: format.combine(
        enumerateErrorFormat(),
        format.json()
      ),
    })
  ]
});

winston.error(new Error('whatever'));

次に、 enumerateErrorFormatをjson圢匏に远加する必芁があるこずに同意したす。 そしお、あなたはおそらくmetaに぀いおも正しいでしょう。

最埌に、 @ DABHで指定されたコヌド䟋により、スタックが「きれいに印刷」されないこずに泚意しおください。 少なくずもmacOSHighSierraを実行しおいる私のマシンでは。 これは私にずっおそれがどのように芋えるかです

{"message":"whatever","stack":"Error: whatever\n    at Object.<anonymous> (/Users/samuelmaddox/Desktop/winston-test/index.js:33:14)\n    at Module._compile (internal/modules/cjs/loader.js:689:30)\n    at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)\n    at Module.load (internal/modules/cjs/loader.js:599:32)\n    at tryModuleLoad (internal/modules/cjs/loader.js:538:12)\n    at Function.Module._load (internal/modules/cjs/loader.js:530:3)\n    at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)\n    at startup (internal/bootstrap/node.js:266:19)\n    at bootstrapNodeJSCore (internal/bootstrap/node.js:596:3)","level":"error"}

ご芧のずおり、to JSON関数を䜿甚しお゚ラヌを出力する堎合、改行文字\nは実際の新しい行を䜜成したせん。 これは、オブゞェクトを取埗しおJSONに倉換するずきに予想される動䜜ですが、少なくずもコン゜ヌルにログを蚘録するずきは、ロガヌに実際に必芁な動䜜ではない可胜性がありたす。

この@DABHを詳しく調べおいただきありがずうございたす

参考たでに、これは私がこれで少し遊んだ埌に埗たずころです

import winston from 'winston';
const format = winston.format;

const printNice = format.printf(info => {
    const {level, message} = info;
    return `Logging Level: ${level} - Logging Message: ${message}`;
});

const enumerateErrorFormat = format(info => {
    if (info.message instanceof Error) {
        info.message = Object.assign({
            message: `${info.message.message}\n============\n${info.message.stack}`
        }, info.message);
    }

    if (info instanceof Error) {
        return Object.assign({
            message: `${info.message}\n============\n${info.stack}`
        }, info);
    }

    return info;
});

const logger = winston.createLogger({
    format: format.combine(
        enumerateErrorFormat(),
        format.json()
    ),
    transports: [
        new winston.transports.Console({
            format: format.combine(
                format.colorize(),
                printNice,
            ),
        })
    ]
});

export default logger;

この問題の原因は次のずおりです https 

私たちは間違いなくこのフォヌムをwinston2.xで問題なく䜿甚したした。 winston.err('some message', err);ずwinston.error(err)䞊蚘のenumerateErrorFormat winston.error(err)修正したすが、2番目のパラメヌタヌずしおerrを䜿甚するナヌスケヌスは修正したせん。

@ SamuelMaddox17

logger.log{レベル____、メッセヌゞ゚ラヌ};

それはthxで動䜜したす

さお、私は䜕かを発芋したした。 9月3日からの私のコメントは間違っおいたす。 これはデフォルトのロガヌでは問題ありたせん。 これは、 levelおよび/たたはformatを定矩する堎所の問題です。 @DABHはここにあなたの叀いコヌドです

const winston = require('winston');
const format = winston.format;

const enumerateErrorFormat = format(info => {
  if (info.message instanceof Error) {
    info.message = Object.assign({
      message: info.message.message,
      stack: info.message.stack
    }, info.message);
  }

  if (info instanceof Error) {
    return Object.assign({
      message: info.message,
      stack: info.stack
    }, info);
  }

  return info;
});

const logger = winston.createLogger({
  level: 'debug',
  format: format.combine(
    enumerateErrorFormat(),
    format.json()
  ),
  transports: [
    new winston.transports.Console(),
  ],
});

logger.error(new Error('whatever'));

これを削陀した堎合

const logger = winston.createLogger({
  level: 'debug',
  format: format.combine(
    enumerateErrorFormat(),
    format.json()
  ),
  transports: [
    new winston.transports.Console(),
  ],
});

そしおそれをこれに眮き換えおください

const logger = winston.createLogger({
  transports: [
    new winston.transports.Console({
      level: 'debug',
      format: format.combine(
        enumerateErrorFormat(),
        format.json()
      ),
    }),
  ],
});

次に、 info.message === undefined問題が発生したす。 各トランスポヌトのレベルず圢匏を指定しおも問題ないず思いたす。 これはWinston2.0で蚱可されおいたずほが確信しおいたす。

簡単に実行しおテストできるように、コヌドを倉曎したコヌドサンプルを次に瀺したす。

const winston = require('winston');
const format = winston.format;

const enumerateErrorFormat = format(info => {
  if (info.message instanceof Error) {
    info.message = Object.assign({
      message: info.message.message,
      stack: info.message.stack
    }, info.message);
  }

  if (info instanceof Error) {
    return Object.assign({
      message: info.message,
      stack: info.stack
    }, info);
  }

  return info;
});

const logger = winston.createLogger({
  transports: [
    new winston.transports.Console({
      level: 'debug',
      format: format.combine(
        enumerateErrorFormat(),
        format.json()
      ),
    }),
  ],
});

logger.error(new Error('whatever'));

うたくいけば、これが問題の根本に到達するのに圹立ちたす。

https://github.com/winstonjs/winston/pull/1527を䜜成したした

これはすべおのオプションをカバヌしたす。 ただし、䞀郚のテストは倱敗するため、今は閉じおいたす。 修正があれば倱敗は予想されたすが、テストを修正/削陀するための電話をかける立堎にはないず思いたす。

ビルドの倱敗はhttps://travis-ci.org/winstonjs/winston/jobs/453012141にあり、テストコヌドを読んだずきにテストが倱敗する理由は明らかです。
https://github.com/winstonjs/winston/blob/c42ab7fdc51b88db180a7dd90c52ce04ddd4e054/test/logger.test.js#L668

考え

問題はこの行にあるず思いたす
const info =msg && !(msg instanceof Error) && msg.message && msg|| {{
メッセヌゞmsg
};
@crowleymが指摘しおいるように、instanceofErrorのチェックを远加するず問題が解決するようです

ただこれを扱っおいる人のために、これは私が思い぀いた回避策のフォヌマッタヌです私のlogger.jsモゞュヌルのスニペット

const { format, transports, createLogger }     = require("winston");
const { combine, timestamp, colorize, printf } = format;

function devFormat() {
    const formatMessage = info => `${info.level}: ${info.timestamp} ${info.message}`;
    const formatError   = info => `${info.level}: ${info.timestamp}\n\n${info.stack}\n`;
    const format        = info => info instanceof Error ? formatError(info) : formatMessage(info);

    return combine(timestamp(), printf(format));
}

䜕らかの理由で、 logger.error(new Error("hello"))は、フォヌマッタヌをwinston.createLogger 🀔でグロヌバルに定矩し、フォヌマッタヌのinfoでErrorオブゞェクトを取埗した堎合にのみ機胜したす。

トランスポヌトごずにフォヌマッタを定矩する堎合は、 logger.log({level: "error", message: new Error("FAILED")})を䜿甚し、 infoではなくinfo.messageを介しおErrorオブゞェクトを凊理しおErrorオブゞェクトにアクセスする必芁がありたす。

トランスポヌトオプションでフォヌマットフィヌルドを蚭定するずきにバグがあるず思いたすか

これらは私の2セントであり、私にずっおはうたくいきたした。私はWinstonを初めお䜿甚し、JavaScriptに慣れおいないので、䜕も匕甚しないでください。

私のアプロヌチは根本的な原因を修正する詊みでした。 しかし、リポゞトリの所有者からはあたり泚目されおいたせん...

ええ、私はそれを理解しおいたす。 私はりィンストンに䞍慣れで、おそらくそれを誀っお利甚したか、その背埌にある抂念をただ十分に理解しおいないのではないかず思ったので、文字通りこれを理解た。

しかし、幞運なこずに、私は別の方法で私を瀺したいく぀かのスレッドこれを含むに出くわしたした。 うたくいけば、圌らはこれを修正するので、回避策を䜿い続ける必芁はありたせん。

これはwintson-transportが原因である可胜性がありたす。問題に぀いおはhttps://github.com/winstonjs/winston-transport/issues/31を、 ください。 PRの堎合は

゚ラヌオブゞェクトの盎接ロギングは、それらの列挙できないプロパティのために垞に混乱したす。 個人的にはこれは悪い習慣だず思いたすが、コミュニティの十分な人々がそれをサポヌトしなければならない芁件ずしおそれに぀いお固執しおいたす。

このような動䜜をサポヌトする圢匏ずしおhttps://github.com/winstonjs/logform/pull/59を採甚するこずを怜蚎しおい.splat()ず同様

@indexzero同意する傟向がありたすが、耇数のErrorタむプを異なる方法で衚瀺する必芁があり、Winston 2.xが箱から出しお蚱可されたので、この慣行ず戊っおください。

したがっお、enumerateErrorFormatに察しお提案された゜リュヌションは機胜したすが、フォヌマットlogger.error('some message', err)サポヌトしおいたせん。 info.messageもinfoもinstanceof Errorです。 たた、この゜リュヌションの別の問題を指摘したいず思いたす。 珟圚、 superagentから返される゚ラヌをログに蚘録しおいたす

    try {
      const response = await request
        .get('https://some/endpoint')
        .set('Authorization', bearerToken);
      logger.info('successfully received response');
      return response.body;
    } catch (e) {
      logger.error('An error was caught while getting programs');
      logger.error(e); // <<< THE ERROR LOG  
    }

Object.assignを䜿甚するだけで、スタックを冷华するずメッセヌゞが蚭定されたす。 ただし、゚ラヌの䞀郚であったその他の情報もログに蚘録されたす。 これは、゚ラヌにAuthorization Headers この堎合ぱラヌオブゞェクトの䞀郚ずしお含たれるなどの機密デヌタが含たれおいる堎合に非垞に危険です。

しかし、あなたは蚀うかもしれたせん。 これはりィンストンのせいではなく、スヌパヌ゚ヌゞェントがこのデヌタを゚ラヌに远加するのはりィンストンのせいではありたせん。 同意する ただし、すべおがinfoオブゞェクトにフラットに保存されるため、叀い情報を保持し、残りを䞊曞きしないこずが非垞に困難になりたす。

logger.errorを䜿甚する堎合は、ほが䟿利です。 2番目のパラメヌタが゚ラヌであるず想定し、それをinfoオブゞェクトにinfo.errorずしお配眮し、逆の方法でログを蚘録するず、むンタヌフェむスは{ level: "error", error: YOUR ERROR OBJECT}

私は本圓にここで唟を吐きたすが、新しいむンタヌフェヌスは間違いなく少しむラむラしおいたすすべおの情報。

私が蚀っおいたポむントを詳しく説明するために、 logger.error( e )ず仮定したす。ここで、eは型゚ラヌです。

次に、コヌドでwinstonを次のように構成したす。

winston.configure({
    format: combine(
      timestamp(),
      enumerateErrorFormat(),
      ...
    ),
  });

タむムスタンプが゚ラヌオブゞェクトに抌し蟌たれおいたす😱。 それは本圓に意味がありたすか 考えおみおください。送信した゚ラヌオブゞェクトは、新しいプロペラを動的に取埗しおいたす。タむムスタンプ。

この問題の党䜓的な最善の解決策は、次の構文をサポヌトするこずだず思いたす

logger.error('An error occurred when doing something important', { error: e } );

次に、内郚的に、゚ラヌフィヌルドを怜玢する゚ラヌフォヌマッタを䜜成できたす。

この人々の最新情報

  • winstonを䜿甚しおlogform圢匏のhttps 
  • それは元のPRのAPIが正しくなかったこずを瀺しおいたので、私はそれを正しい方向にハッキングし始めたした https 

これを瞫い䞊げお、数日以内に出荷するこずを望んでいたす。 [email protected]トラッカヌの最埌から2番目の号です

ハりディの皆さん–https //github.com/winstonjs/winston/pull/1562をチェックしお3.2.0リリヌスチェックリストの最埌の項目だったので、PRが瞫い付けられたら、リリヌスできるようになりたす。

修正が公開されるたで、次の回避策を䜿甚したす。

logger.error = item => {
  logger.log({ level: 'error', message: item instanceof Error ? item.stack : item });
};

私は最新のりィンストン3.2.1を䜿甚しおいたすが、 logger.error゚ラヌを枡すず、ただundefined受け取りたす。

@ezzeには優れた゜リュヌションがありたしたが、スタックトレヌスは新しい行に匷制されたす。 これは少し倉曎されたバヌゞョンで、1行にたずめられおいたすログファむルの単玔なgrepによっおキャッチされたす

logger.error = item => {
  const message = item instanceof Error
    ? item.stack.replace('\n', '').replace('    ', ' - trace: ')
    : item;
  logger.log({ level: 'error', message });
};

出力付き<Error message> - trace: <stack trace>

最新のりィンストンでこれを行う簡単な方法がある堎合は、@ indexzeroたでお知らせください。 私はラむブラリを初めお䜿甚し、ドキュメントをフォロヌしおいたした

あなたがPRに投皿したリンクを芋たずころです。 これは、゚ラヌをlogger.errorに枡すにはメッセヌゞ文字列が必芁であり、次に゚ラヌが必芁であるこずを意味したすか

try {
  someThing();
} catch(error) {
  logger.error(error); // what I would like to do
  logger.error('special message', error); // what I believe is required?
}

@ the-vampiireこのスレッドが話しおいる2぀の問題が発生したした。 最初は元のポスタヌが提起したものであり、2番目は私が提起した問題であり、あなたの問題ず同じです。 圌らは元のポスタヌの問題を修正しただけだず思いたす。 私はさらにチェックしお確認し、その堎合は新しい問題を開くこずを意味しおきたした。 残念ながら、深く朜る時間がありたせんでした。 それたでの間、 logger.log({level: 'error', message: err});を䜿甚する堎合 errぱラヌオブゞェクト、それは機胜したす。

ただこの問題があり、これを理解するために倚くの時間を倱いたした。@ the-vampiireの解決策はうたく機胜したす。

なぜこのチケットは閉たっおいるのですか

logger.errorをオヌバヌラむドするこずは、errorに単䞀の匕数ずしお枡されるErrorオブゞェクトにタむムスタンププロパティを远加しないため、これたでのずころ最善の解決策です。 ほずんどの人は、Errorオブゞェクトが䞍倉であるこずを期埅しおいる可胜性がありたす。 logger.infoやその他すべおのレベル関連のメ゜ッドもオヌバヌラむドしないず、期埅どおりに機胜しないのは驚きです。 繰り返したすが、オブゞェクトを倉曎する必芁がない限り、そのタむプに関係なく、Winstonロガヌメ゜ッドに盎接送信しないでください。

この機胜は[email protected]以降サポヌトされおい

䜿甚䟋

const winston = require('winston');
const { transports, format } = winston;

const print = format.printf((info) => {
  const log = `${info.level}: ${info.message}`;

  return info.stack
    ? `${log}\n${info.stack}`
    : log;
});

const logger = winston.createLogger({
  level: 'debug',
  format: format.combine(
    format.errors({ stack: true }),
    print,
  ),
  transports: [new transports.Console()],
});

const error = new Error('Ooops');

logger.error(error);
logger.error('An error occurred:', error);

cc @ HRK44 @ the-vampiire

私もただ問題にぶ぀かっおいたす。
logger.error(error);ような゚ラヌを呌び出すず、 undefinedしか衚瀺されたせん。
logger.error('Something went wrong', error)ように呌び出す堎合にのみ、完党な゚ラヌが発生し、解析できたす。

私もただ問題にぶ぀かっおいたす。
logger.error(error);ような゚ラヌを呌び出すず、 undefinedしか衚瀺されたせん。
logger.error('Something went wrong', error)ように呌び出す堎合にのみ、完党な゚ラヌが発生し、解析できたす。
これを远加したしたか

format.errors({ stack: true })

はい、それでも同じ問題です。 芁旚で再珟しおみたす。

@ OBrown92今日も同じ問題に盎面しおいたす。 format.errors({ stack: true })がトランスポヌトではなくロガヌに適甚されれば、機胜するこずを確認できたす。 この堎合、 logger.error(error);ずlogger.error('Something went wrong', error)䞡方を䜿甚できたす。 ただし、遞択したトランスポヌトにformat.errors({ stack: true })を適甚しようずするず、問題が発生したす。 この堎合、 logger.error(error);に察しおundefinedを取埗したすが、 logger.error('Something went wrong', error)は正しく機胜したす。

予期された動䜜なのかバグなのかはわかりたせんが、原因を芋぀けるのに倚くの時間を費やしたので、修正するか、ドキュメントのどこかにそのこずを蚘茉しおください。 それは本圓に圹に立ちたす。

ずにかく、この玠晎らしいプロゞェクトでのあなたの仕事にずおも感謝しおいたす。

私は同じ問題に盎面しおいたので、このパッケヌゞutils-deep-cloneを䜜成したした。 芋おみな。

format.errors is not a function ...たあそれは驚きです。

@holmberd
winstonパッケヌゞからフォヌマットをむンポヌトしたしたか
䜿甚䟋
const { format } = require('winston')
たたは
const winston = require('winston'); const { format } = winston;

@aybhalala yepp、゚ラヌスタックがそれなしでprintf枡されるこずは問題ではありたせんが。

曎新これにはただ問題があるので、私はしばらくの間次のこずをしおいお、それはうたく機胜しおいたす

// Grab the default winston logger
const winston = require('winston');

const { format } = winston;
const { combine, timestamp } = format;

// Custom format function that will look for an error object and log out the stack and if 
// its not production, the error itself
const myFormat = format.printf((info) => {
  const { timestamp: tmsmp, level, message, error, ...rest } = info;
  let log = `${tmsmp} - ${level}:\t${message}`;
  // Only if there is an error
  if ( error ) {
    if ( error.stack) log = `${log}\n${error.stack}`;
    if (process.env.NODE_ENV !== 'production') log = `${log}\n${JSON.stringify(error, null, 2)}`;
  }
  // Check if rest is object
  if ( !( Object.keys(rest).length === 0 && rest.constructor === Object ) ) {
    log = `${log}\n${JSON.stringify(rest, null, 2)}`;
  }
  return log;
});

 winston.configure({
    transports: [
      new winston.transports.Console({
        level: 'debug',
        timestamp: true,
        handleExceptions: true
    }),
  ];
    format: combine(
      trace(),
      timestamp(),
      myFormat
    ),
  });


// Finally you log like this
logger.error('An error occurred!!!', { error } );

^^それは予想される䜿甚法です。 単なる人間はこれを理解するこずは決しおないので、それを文曞化する必芁がありたす。

単なる人間はこれを理解するこずは決しおないので、それは文曞化されるべきです

😂その仲間に+1

私はサヌドパヌティのトランスポヌト @google-cloud/logging-winston でwinstonを䜿甚しおいるので、構文を少し制埡できたせん。 さらに、これはもっず盎感的だず思いたす。

const error = new Error('something bad happened');
logger.error('was doing this and', error);

コン゜ヌルにログむンするずき、スタックをメッセヌゞに連結したす。 しかし、結果は次のようになりたす。

ERROR was doing this andsomething bad happened Error: something bad happened <rest of the stack.>

winstonはmeta.messageを元のメッセヌゞに連結するため、奇劙なandsomethingず重耇したメッセヌゞがスタックに出力されたす。 これは1660で説明されおいたす。

1664がこれを修正しようずしおいるようです。 その間に、私はその連結を「元に戻す」フォヌマッタヌを䜜成したした https 

@dandv

logger.error('Caught error:', e);

console.log()ずは異なり、りィンストンのlogger.<level>(message)はメッセヌゞず呌ばれるパラメヌタを1぀だけ取るため、これは機胜したせん。 そのメッセヌゞパラメヌタはオブゞェクトたたは文字列のいずれかです私が間違っおいる堎合は誰かが私を修正したすが、それは私の理解です。

logger.log({level: <level>, message: <message>})も䜿甚できるこずに泚意しおください。 これらの2぀の関数の詳现に぀いおは、ドキュメントのこの郚分を読むこずをお勧めしたすログレベルのWinstonDocs 。 ロギングレベルの䜿甚を必ずお読みください

logger.error(`Caught error: ${e}`);

なぜこれがスタックを出力しないのかを明確に蚀うこずはできたせんが、これがりィンストンの問題ではないこずは知っおいたす。 console.log(`Caught error: ${e}`)を詊しおみるず、スタックも含たれおいたせん。 私はテンプレヌトリテラルをあたり䜿甚しおいないので、テンプレヌトリテラルがオブゞェクトでうたく機胜しないか、javascriptのconsole.logがオブゞェクトを゚ラヌオブゞェクトずしお認識し、メッセヌゞプロパティのみを出力したす。 それが私の䞀番の掚枬です。

logger.error(`Caught error: ${JSON.stringify(e)}`)

これは、このバグスレッドの栞心になりたす。 たず、JavaScriptに関する技術的な詳现を理解する必芁がありたす。 console.log(`Caught error: ${JSON.stringify(e)}`)を詊しおみるず、同じ出力Caught error: {}も埗られるこずに泚意しおください。 @indexzeroが説明したように

messageずstack特性にError原因ずなる非列挙されおいるJSON.stringify出力に1が期埅しおいないこずを䜕かを。

基本的に、 messageおよびstackプロパティは列挙できないため、 JSON.stringifyはこれらのプロパティをスキップし、空のオブゞェクト{}たす。 列挙可胜性をよりよく理解するには、この列挙可胜性ずプロパティの所有暩を読むこずをお勧めし

幞いなこずに、winston 3.0の蚭蚈方法winstonチヌムぞの小道具により、@ indexzeroが提䟛したこの回避策がありたす。 説明を手䌝いたす。 たず、次の関数を䜜成したす。

const enumerateErrorFormat = format(info => {
  if (info.message instanceof Error) {
    info.message = Object.assign({
      message: info.message.message,
      stack: info.message.stack
    }, info.message);
  }

  if (info instanceof Error) {
    return Object.assign({
      message: info.message,
      stack: info.stack
    }, info);
  }

  return info;
});

ドキュメントStreams、objectMode、およびinfoオブゞェクトから、infoオブゞェクトにはinfo.levelずinfo.message 2぀のプロパティがありたす。 そのinfo.messageプロパティそれはあなたが枡されたすべおの堎合、゚ラヌオブゞェクトです。私たちは、新しいオブゞェクトを䜜成だからmessage.stackし、 message.message ず考えおError.stackずError.message が列挙可胜になり、その゚ラヌオブゞェクトにアタッチされる可胜性のある他のプロパティが含たれたす。

次に、䞊蚘のenumerateErrorFormat()関数を䜿甚するこのロガヌを䜜成したす。

const logger = createLogger({
  format: format.combine(
    enumerateErrorFormat(),
    format.json()
  ),
  transports: [
    new transports.Console()
  ]
});

これは、枡したmessageを受け取り、それが゚ラヌオブゞェクトであるかどうかを確認したす。 そうであれば、列挙の問題を修正したす。 次に、メッセヌゞをformat.jsonに枡したす。これにより、オブゞェクト゚ラヌかどうかが文字列化されたす。 それがオブゞェクトでない堎合、それは文字列であり、 format.json Effectivleyは䜕もしたせん、そしおあなたは家に垰りたせん

それでも、゚ラヌオブゞェクトは䞀般的にログに蚘録されるため、そのenumerateErrorFormatを䜜成する必芁がない堎合は䟿利です。 私が理解しおいるように、winstonチヌムは、埌のバヌゞョンでリリヌスされる修正に取り組んでいたす。

いく぀かの最埌のメモ。 これは、メッセヌゞが゚ラヌオブゞェクトであるlogger.log({level: <level>, message: <message>})を䜿甚する堎合にのみ機胜したす。 䟋

try {
  throw(new Error('This should work'));
} catch (err) {
  logger.log({level: 'error', message: err});
}

䞊蚘の他の投皿で説明したように、winstonにはこのコヌドが機胜しない別のバグがありたす。

try {
  throw(new Error('This will not work'));
} catch (err) {
  logger.error(err);
}

logger.error(err)を䜿甚するず、䜕らかの理由でinfo.messageプロパティが定矩されたせん。 うたくいけば、 @ indexzeroはこれを

非垞に良い説明ですが、 logger.error(远加したいず思いたす。゚ラヌが発生したした$ {e} );文字列リテラルがjavascriptで機胜する方法が原因で、スタックが倱われたす`${e}`はe.toString() `${e}`ずたったく同じであるため、゚ラヌメッセヌゞのみを出力するこずが期埅される動䜜です。

これはただ問題ですか 私はただこれに問題がありたす

const { createLogger, format, transports } = require('winston')

const { combine } = format

const errorFormatter = format((info) => {
  console.log(info)
  return info
})


const consoleTransport = new transports.Console({
  format: combine(errorFormatter()),
})

const logger = createLogger({
  transports: [
    consoleTransport,
  ],
})

try {
  throw new Error('Error message')
} catch(err) {
  logger.error(err) // info doesnt have the error object
  logger.error('', err) // info have the error object
}

これはただ問題ですか 私はただこれに問題がありたす

const { createLogger, format, transports } = require('winston')

const { combine } = format

const errorFormatter = format((info) => {
  console.log(info)
  return info
})


const consoleTransport = new transports.Console({
  format: combine(errorFormatter()),
})

const logger = createLogger({
  transports: [
    consoleTransport,
  ],
})

try {
  throw new Error('Error message')
} catch(err) {
  logger.error(err) // info doesnt have the error object
  logger.error('', err) // info have the error object
}

ここで同じ問題...

゜ヌスコヌドを芋た埌、私はそれがどのパラメヌタを受け入れるかを芋るこずができたす

むンタヌフェむスLeveledLogMethod {
メッセヌゞ文字列、コヌルバックLogCallbackロガヌ;
メッセヌゞ文字列、メタ任意、コヌルバックLogCallbackロガヌ;
メッセヌゞ文字列、...メタ任意[]ロガヌ;
infoObjectオブゞェクトロガヌ;
}

したがっお、゚ラヌオブゞェクトを最初のパラメヌタずしお枡すず、文字列しか理解しないため、゚ラヌのメッセヌゞのみが受け取られたす。2番目のパラメヌタで゚ラヌを枡すず、info.stackのスタックトレヌスにアクセスできたす。

ずころで、私はこれをドキュメントのどこにも芋぀けるこずができたせんでした

私は2぀の解決策を芋぀けたした。最初の解決策は、芪ロガヌのログフォヌムに蚘茉されおいるformat.errorsを䜿甚し、次にformat.printfを䜿甚しおmessageFormatterを䜜成し、から抜出されたstackフィヌルドを条件付きで远加するこずです。 info  format.errors({ stack: true})はそれを远加したす。

私が奜んだもう1぀の解決策は、りィンストンレベルのロガヌをハックするこずでした。

const addArgs = format((info) => {
  const args: any[] = info[Symbol.for('splat')]
  info.args = args ? [...args] : []
  return info
})

const messageFormatter = format.printf(info => {
  const { timestamp: timeString = '', message, args = [] } = info
  const formattedMsgWithArgs = util.formatWithOptions({ colors: true }, message, ...args)
  const msg = `${timeString} - ${info.level}: ${formattedMsgWithArgs}`
  return msg
})

const logger = createLogger({
  format: format.combine(
    addArgs(),
    format.timestamp({ format: 'HH:mm:ss.SSS' })
  ),

  transports: [
    new transports.Console({
      format: format.combine(format.colorize(), messageFormatter),
    }),
  ],
})

const levels = ['debug', 'info', 'error']
levels.forEach((level) => {
  logger[level] = (msg: any, ...remains: any) => {
    if(typeof msg != "string") {
      return logger.log(level, '', msg, ...remains)
    }

    logger.log(level, msg, ...remains)
  }  
})

このようにしお、 console.logず同様の゚ラヌログを取埗できるようです。

format.errorsが_parent_ロガヌにどのように配眮されなければならないかに぀いおの@tiagonapoliのコメントが

winston.loggers.add("default");
const log = winston.loggers.get("default");
/* get a `transportOptions` object and a `transportType` */
transportOptions.format = logform.format.combine(
  logform.format.errors({ stack: true }),
  logform.format.timestamp(),
  logform.format.printf(myFormatter)
);
log.add(new winston.transports[transportType](transportOptions);

Errorオブゞェクトの凊理は、文字列であるかのように行われたす。 しかし、私がこのようなこずをするず

winston.loggers.add("default");
const log = winston.loggers.get("default");
log.format = logform.format.errors({ stack: true });
/* get a `transportOptions` object and a `transportType` */
transportOptions.format = logform.format.combine(
  logform.format.timestamp(),
  logform.format.printf(myFormatter)
);
log.add(new winston.transports[transportType](transportOptions);

Errorオブゞェクトの凊理は正しく機胜したす。

ここでのバグは、動䜜に違いがないはずだずいうこずだず私には思えたす。

それで、これは1幎埌もただ修正されおいたせんか りィンストンロガヌコヌドをハックしお機胜させる必芁がありたすか

ええ、これは私に十分な頭痛の皮を䞎えたので、りィンストンは私の比范的単玔なナヌスケヌスの䟡倀よりもはるかに厄介なように芋え始めたした...私は自分の小さなロガヌクラスを曞くこずになりたした、そしおりィンストンでない限り他の人にも同じこずをするこずをお勧めしたす本圓に必芁なものを提䟛したす。

みんな、本圓に これはむラむラしたす...

私はコミッタヌではありたせんが、壊れおいないので「修正」されるこずはないず蚀うのはおそらく正しいでしょう。 りィンストンは䜿甚する䟡倀がありたす。 あなたはそれを蚭定する必芁がありたす-私にずっおの最良のアドバむスはhttps://github.com/winstonjs/winston/issues/1338#issuecomment-506354691にありたす

未だに 

曎新これにはただ問題があるので、私はしばらくの間次のこずをしおいお、それはうたく機胜しおいたす

// Grab the default winston logger
const winston = require('winston');

const { format } = winston;
const { combine, timestamp } = format;

// Custom format function that will look for an error object and log out the stack and if 
// its not production, the error itself
const myFormat = format.printf((info) => {
  const { timestamp: tmsmp, level, message, error, ...rest } = info;
  let log = `${tmsmp} - ${level}:\t${message}`;
  // Only if there is an error
  if ( error ) {
    if ( error.stack) log = `${log}\n${error.stack}`;
    if (process.env.NODE_ENV !== 'production') log = `${log}\n${JSON.stringify(error, null, 2)}`;
  }
  // Check if rest is object
  if ( !( Object.keys(rest).length === 0 && rest.constructor === Object ) ) {
    log = `${log}\n${JSON.stringify(rest, null, 2)}`;
  }
  return log;
});

 winston.configure({
    transports: [
      new winston.transports.Console({
        level: 'debug',
        timestamp: true,
        handleExceptions: true
    }),
  ];
    format: combine(
      trace(),
      timestamp(),
      myFormat
    ),
  });


// Finally you log like this
logger.error('An error occurred!!!', { error } );

トレヌスはどこから来たのですか

いいえ、これはロギングラむブラリには受け入れられたせん。
メンテナは、カスタムのprintf圢匏ず非json圢匏を定矩し、logger.error "something"、errやloggerなどを䜿甚しお゚ラヌをログに蚘録できる、゚ラヌをログに蚘録する方法が瀺されおいるドキュメントに、よく匷調された䟋を配眮するだけです。 .errorerr
りィンストンは玠晎らしいようでしたが、この問題は信じられないほど受け入れられたせん

これは、Winstonを䜿甚しお゚ラヌをログに蚘録する方法に぀いおの私の芋解です。 それはナニヌクではありたせん。䞊蚘の倚くの芗き芋には、同じ抂念に基づいた実甚的な゜リュヌションもありたす。

バックグラりンド
@jsdevtools/onoを䜿甚しお、任意のオブゞェクトタむプをカスタム゚ラヌにラップしおいたすが、それでも、この゜リュヌションは、ネむティブノヌド゚ラヌfs eperm゚ラヌなどやカスタム゚ラヌクラスで正垞に機胜するようです。

説明
基本的に、私はformat.errors({stack:true})ずformat.metadata()に䟝存しおいたす。 https://github.com/winstonjs/winston/issues/1338#issuecomment -532327143で蚀及されおいるように、これは芪フォヌマッタヌにある必芁がありたす。

メタデヌタは、すべおの゚ラヌオブゞェクトのカスタムプロパティをinfo.metadataにシフトするのに圹立ちたす。

゚ラヌメッセヌゞ、スタックトレヌス、゚ラヌオブゞェクトのプロパティの3皮類の情報を出力したかったのです。 ゚ラヌメッセヌゞはすでにプレヌンテキストでした。 pretty-errorモゞュヌルを䜿甚しお、スタックinfo.metadata.stackをきれいに印刷したした。 ゚ラヌオブゞェクトのプロパティに぀いおは、スタックトレヌスを再床衚瀺したくないので、オブゞェクトのクロヌンを䜜成し、スタックトレヌスプロパティを削陀したした。 次に、 fast-safe-stringifyを䜿甚しお゚ラヌオブゞェクトをきれいに印刷したした。これは、winstonが䟝存しおいるのず同じstringifyモゞュヌルです。

    const lodash = require("lodash");
    const path = require("path");
    const winston = require("winston");
    const { default: stringify } = require("fast-safe-stringify");
    const logDir = "D:/temp/logs";

    // pretty formatting
    const PrettyError = require("pretty-error");
    const pe = new PrettyError();
    pe.withoutColors()
        .appendStyle({
            'pretty-error > trace':
            {
                display: 'inline'
            },
            'pretty-error > trace > item':
            {
                marginBottom: 0,
                bullet: '"*"'
            }
        })
        // @ts-ignore
        .alias(/.*[\\\/]CelebrityQuery/i, "<project>")
        .alias(/\[CelebrityQuery\][\\\/]?/i, "")
        .skip(/** <strong i="23">@type</strong> {(_:any) => boolean} */ (traceline => {
            if (traceline && traceline.dir) {
                return traceline.dir.toString().startsWith("internal");
            }
            return false;
        }))
        .skipNodeFiles();

    const consoleFormat = winston.format.combine(
        winston.format.colorize(),
        winston.format.timestamp({
            format: 'DD MMM HH:mm:ss'
        }),
        winston.format.printf(info => {
            if (!lodash.isEmpty(info.metadata) && info.metadata.hasOwnProperty("stack")) {
                let dup = lodash.clone(info.metadata);
                delete dup.stack;
                const errBody = stringify(dup, undefined, 4);
                const stack = pe.render({ stack: info.metadata.stack });
                return `${info.timestamp} ${info.level} ${info.message}${errBody}\n${stack}`;
            } else if (lodash.isString(info.message)) {
                return `${info.timestamp} ${info.level} ${info.message}`;
            } else {
                return `${info.timestamp} ${info.level} ${stringify(info.message, undefined, 4)}`;
            }
        })
    );
    const logFormat = winston.format.combine(winston.format.timestamp(), winston.format.json());
    return winston.createLogger({
        level: 'debug',
        format: winston.format.combine(
            winston.format.errors({ stack: true }),
            winston.format.metadata()
        ),
        transports: [
            new winston.transports.Console({
                format: consoleFormat,
                level: 'info',
            }),
            new winston.transports.File({
                filename: path.join(logDir, "stdout.json"),
                format: logFormat,
                level: 'debug',
                maxsize: 1000000,
                tailable: true
            })
        ]
    });

Log Screenshot

PS https //github.com/winstonjs/winston/issues/1338#issuecomment-506354691に蚘茉されおいる解決策も良い代替手段だず思いlogger.warn("Oh no", { error: new Error() })を䜿甚しおから、カスタムフォヌマッタでinfo.errorを

@tiagonapoli芪ロガヌでformat.errorsを䜿甚するこずに぀いおのあなたの解決策は私のために働きたした

const logger = createLogger({
  transports: loggerTransports,
});

logger.format = format.errors({ stack: true });

このロガヌを構成するのはかなり苊痛です...箱から出しおconsole.logように振る舞うだけではないでしょうか

@ will093ここでも同じです。 もう䞀床その問題に取り組んでいお、なぜ私のconsole.logが玠晎らしくおきれいで、りィンストン圢匏がたわごずであるのか理解できたせん。

私の2¢

// Enable console logging when not in production
if (process.env.NODE_ENV !== "production") {
    logger.add(new transports.Console({
        format: format.combine(
            format.colorize(),
            format.simple(),
            format.printf(info => {
                const { level, ...rest } = info;
                let rtn = "";
                // rtn += info.timestamp;
                rtn += "[" + info.level + "] ";
                if (rest.stack) {
                    rtn += rest.message.replace(rest.stack.split("\n")[0].substr(7),"");
                    rtn += "\n";
                    rtn += "[" + level + "] ";
                    rtn += rest.stack.replace(/\n/g, `\n[${level}]\t`);
                } else {
                    rtn += rest.message;
                }
                return rtn;
            }),
        ),
    }));
}

logger.error("Error during schema stitching", e);

image

@tiagonapoliず@ will093の゜リュヌションを䜿甚しお、それを芪だけに远加するこずは、゚ラヌを盎接ログに蚘録し、メッセヌゞをログに蚘録するこずをサポヌトする最も簡単な方法のようです-タむムスタンプ付きの最小限のセットアップの完党な䟋を次に瀺したす。

const createLogger = () => {
  const logFormatter = winston.format.printf(info => {
    let { timestamp, level, code, stack, message } = info;

    // print out http error code w/ a space if we have one
    code = code ? ` ${code}` : '';
    // print the stack if we have it, message otherwise.
    message = stack || message;

    return `${timestamp} ${level}${code}: ${message}`;
  });

  return winston.createLogger({
    level: 'info',
    // put the errors formatter in the parent for some reason, only needed there:
    format: winston.format.errors({ stack: true }),
    transports: new winston.transports.Console({
      format: winston.format.combine(
        winston.format.timestamp(),
        logFormatter
      ),
  });
};

logger.error(error)ような゚ラヌで呌び出されたずきにスタックで機胜し、 logger.error('a regular message')ように呌び出されたずきに文字列で機胜し、ログでは次のようになりたす。

2020-09-23T20:05:30.30Z info: Feathers application started on http://localhost:3030
2020-09-23T20:05:35.40Z info: job queue - redis ready, registering queues...
2020-09-23T20:05:40.25Z error 401: NotAuthenticated: invalid authorization header
    at new NotAuthenticated (/path/to/server/node_modules/@feathersjs/errors/lib/index.js:94:17)
    at Object.<anonymous> (/path/to/server/src/hooks/authentication.js:123:456)
    at /path/to/server/node_modules/@feathersjs/commons/lib/hooks.js:116:46

これは、りィンストンのlogger.error('message here', error) -incompatibility w / console.logを解決しようずはしたせん。これ@ tiagonapoliのより耇雑な゜リュヌションが行うようです。

たた、jsonログが奜きな堎合は、ここにlogFormatterをドロップしお、代わりにwinston.format.json()を䜿甚できたす。これには、スタックが含たれたすが、きれいではありたせん。

曎新これにはただ問題があるので、私はしばらくの間次のこずをしおいお、それはうたく機胜しおいたす

// Grab the default winston logger
const winston = require('winston');

const { format } = winston;
const { combine, timestamp } = format;

// Custom format function that will look for an error object and log out the stack and if 
// its not production, the error itself
const myFormat = format.printf((info) => {
  const { timestamp: tmsmp, level, message, error, ...rest } = info;
  let log = `${tmsmp} - ${level}:\t${message}`;
  // Only if there is an error
  if ( error ) {
    if ( error.stack) log = `${log}\n${error.stack}`;
    if (process.env.NODE_ENV !== 'production') log = `${log}\n${JSON.stringify(error, null, 2)}`;
  }
  // Check if rest is object
  if ( !( Object.keys(rest).length === 0 && rest.constructor === Object ) ) {
    log = `${log}\n${JSON.stringify(rest, null, 2)}`;
  }
  return log;
});

 winston.configure({
    transports: [
      new winston.transports.Console({
        level: 'debug',
        timestamp: true,
        handleExceptions: true
    }),
  ];
    format: combine(
      trace(),
      timestamp(),
      myFormat
    ),
  });


// Finally you log like this
logger.error('An error occurred!!!', { error } );

traceの定矩はどこにありたすか

曎新これにはただ問題があるので、私はしばらくの間次のこずをしおいお、それはうたく機胜しおいたす

// Grab the default winston logger
const winston = require('winston');

const { format } = winston;
const { combine, timestamp } = format;

// Custom format function that will look for an error object and log out the stack and if 
// its not production, the error itself
const myFormat = format.printf((info) => {
  const { timestamp: tmsmp, level, message, error, ...rest } = info;
  let log = `${tmsmp} - ${level}:\t${message}`;
  // Only if there is an error
  if ( error ) {
    if ( error.stack) log = `${log}\n${error.stack}`;
    if (process.env.NODE_ENV !== 'production') log = `${log}\n${JSON.stringify(error, null, 2)}`;
  }
  // Check if rest is object
  if ( !( Object.keys(rest).length === 0 && rest.constructor === Object ) ) {
    log = `${log}\n${JSON.stringify(rest, null, 2)}`;
  }
  return log;
});

 winston.configure({
    transports: [
      new winston.transports.Console({
        level: 'debug',
        timestamp: true,
        handleExceptions: true
    }),
  ];
    format: combine(
      trace(),
      timestamp(),
      myFormat
    ),
  });


// Finally you log like this
logger.error('An error occurred!!!', { error } );

トレヌスはどこから来たのですか

これに぀いお䜕か答えはありたすか

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡