web-dev-qa-db-ja.com

Winstonがエラーの詳細を表示しない

私はロギングにwinstonを使用しており、ほとんどの場合それはうまく機能しますが、例外がある場合は、詳細を出力しません。

winstonを構成するためのコードは次のとおりです。

_// Create logger
const logger = winston.createLogger()

// Create timestamp format
const tsFormat = () => (new Date()).toLocaleTimeString()

// Attach transports based on app mode
if (process.env.APP_MODE === 'production') {
  // Log to file
  logger.add(new (winston.transports.DailyRotateFile)({
    filename: path.join(__dirname, '../logs/errors-%DATE%.log'),
    datePattern: 'YYYY-MM-DD-HH',
    zippedArchive: true,
    format: winston.format.json(),
    handleExceptions: true
  }))
} else {
  // Log to the console
  logger.add(new (winston.transports.Console)({
    timestamp: tsFormat,
    colorize: true,
    handleExceptions: true
  }))
}

module.exports = logger
_

私はExpressも使用しており、エラー処理ミドルウェアには次のコードがあります。

_const logger = require('../config/winston')
function (err, req, res, next) {
    console.log(err)
    logger.error(err)
    res.status(500).send({ error: 'Please try again later.' })
}
_

問題は、エラーが発生すると、すべてのwinstonログが次のようになることです。

{"レベル": "エラー"}

古き良きconsole.log()が表示されている間:

_TypeError: Cannot read property 'filename' of undefined
    at router.post (/Users/balazsvincze/Desktop/testapi/app/routes/upload.js:16:33)
    at Layer.handle [as handle_request] (/Users/de/Desktop/testapi/node_modules/express/lib/router/layer.js:95:5)
    at next (/Users/balazsvincze/Desktop/testapi/node_modules/express/lib/router/route.js:137:13)
    at Immediate.<anonymous> (/Users/balazsvincze/Desktop/testapi/node_modules/multer/lib/make-middleware.js:53:37)
    at runCallback (timers.js:814:20)
    at tryOnImmediate (timers.js:768:5)
    at processImmediate [as _immediateCallback] (timers.js:745:5)
_

スタックトレースを含めて、このようなものをwinstonに記録するにはどうすればよいですか?

どうもありがとう!

編集: logger.error(err)の行をlogger.error(err.message)に変更すると、少なくとも次のようになります。

{"メッセージ": "未定義のプロパティ 'ファイル名'を読み取れません"、 "レベル": "エラー"}

それでも私が求めているものからはかなりかけ離れています。

12
Balázs Vincze

すばやく汚い方法は、ログを記録することですerr.stack

logger.error(err.stack);

より複雑な方法は、特にErrorインスタンスに対して カスタム形式 を実装することです。 このGithubの問題 にそれを実装する方法のコード例があります。

2
robertklep

フォーマットを使用します。

const { combine, timestamp, label, printf } = winston.format;
const myFormat = printf(info => {
    if(info instanceof Error) {
        return `${info.timestamp} [${info.label}] ${info.level}: ${info.message} ${info.stack}`;
    }
    return `${info.timestamp} [${info.label}] ${info.level}: ${info.message}`;
});
winston.createLogger({
    level: "info",
    format: combine(
        winston.format.splat(),
        label({ label: filename}),
        timestamp(),
        myFormat,
    ),
    transports: [
    //
    // - Write to all logs with level `info` and below to `combined.log`
    // - Write all logs error (and below) to `error.log`.
    //
        new winston.transports.File({ filename: path.join(os.tmpdir(), "test", "test.log"), level: "info" }),
    ],
});
1
Gary Shan

あなたが欠けているのは_winston.createLogger_のformat.errors({ stack: true })です。

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

詳細は this GitHub thread を参照してください。

これが発生している理由は、_.stack_などの興味深いErrorオブジェクトプロパティが列挙できないためです。 _console.error_などの一部の関数は、それらのパラメーターがErrorインスタンスであるかどうかをチェックし、_winston.<log-level>_や_JSON.stringify_などの列挙できないプロパティをすべて無視します。

_> console.error(new Error('foo'))
Error: foo
    at repl:1:15
    at Script.runInThisContext (vm.js:124:20)
    ...(abbr)

> JSON.stringify(new Error('foo'))
'{}'
_

とは言っても、エラーロガーが基本的にエラーを無視するのはひどいユーザビリティです...これに時間をかけすぎただけです。

1
jtpeterson