Winston: ロギング関数に耇数のパラメヌタを枡すず、期埅どおりに動䜜したせん

䜜成日 2018幎08月06日  Â·  43コメント  Â·  ゜ヌス: winstonjs/winston

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

  • _ winstonバヌゞョン_

    • [] winston@2

    • [x] winston@3

  • _ node -v出力_ v8.11.3
  • _オペレヌティングシステム_macOS
  • _蚀語_フロヌES6 / 7

䜕が問題ですか


3.xxの堎合

const winston = require('winston')

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

logger.info('test log', 'with a second parameter')

出力

{"level":"info","message":"test log"}

2.xxの堎合

const winston = require('winston')

const logger = new winston.Logger({
    transports: [new winston.transports.Console()]
})

logger.info('test log', 'with a second parameter')

出力

info: test log with a second parameter

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


次のように出力されたす。

{"level":"info","message":"test log with a second parameter"}
important

最も参考になるコメント

これは私たちにずっお倧きな倉革です。 意図的なものである堎合は、 https//github.com/winstonjs/winston/blob/master/UPGRADE-3.0.mdで詳しく説明する必芁があり

党おのコメント43件

私は今日同じ問題に遭遇したした。 アップグレヌドドキュメントにもそのような䟋があるので、これはバグだず思いたす

logger.info('transaction ok', { creditCard: 123456789012345 });

珟圚、これを回避するために、winstonに枡される前に匕数を解析する関数を䜜成できたす。

@ mulligan121わかりたしたが、コヌドベヌス内のすべおのログステヌトメントを眮き換えたくありたせん...

@indexzeroこれはあなたのレヌダヌの䞋にありたすか これは倧きな倉化だず思いたす。 すべおのログ゚ントリを倉曎する必芁があるため、実際には2.xから3.xに移動できたせん。

䞀時的な回避策

const wrapper = ( original ) => {
    return (...args) => original(args.join(" "));
};

winstonLogger.error = wrapper(winstonLogger.error);
winstonLogger.warn = wrapper(winstonLogger.warn);
winstonLogger.info = wrapper(winstonLogger.info);
winstonLogger.verbose = wrapper(winstonLogger.verbose);
winstonLogger.debug = wrapper(winstonLogger.debug);
winstonLogger.silly = wrapper(winstonLogger.silly);

これは私たちにずっお倧きな倉革です。 意図的なものである堎合は、 https//github.com/winstonjs/winston/blob/master/UPGRADE-3.0.mdで詳しく説明する必芁があり

したがっお、さらに調査した結果、耇数の匕数を出力するには、スプラットフォヌマッタが必芁であるこずがわかりたした。 これは匕数の補間぀たり、sなどが含たれおいるもののためだけだず思いたしたが、 logger.info("something", value)を実行するためだけに必芁なようです。

しかし、これは私にずっおはただ少し奇劙です-JSON圢匏を䜿甚しおいなくおも、出力に「メタ」キヌを持぀JSONのようなものが衚瀺されたす。

logger.info('Test: %s', 1, 2, 3, 4);

生産

info: Test: 1 {"meta":[2,3,4]}

䟋の䟋でさえ、それが蚀うこずを生み出したせん

https://github.com/winstonjs/winston/blob/master/examples/interpolation.js#L20 -L21

info: test message first, second {"meta":{"number":123}}

私はこれらの線に沿った䜕かを䜿甚しおそれを解決したした

const { version } = require('../package');

const { createLogger, format, transports } = require('winston');
const { combine, timestamp, colorize, label, printf, align } = format;
const { SPLAT } = require('triple-beam');
const { isObject } = require('lodash');

function formatObject(param) {
  if (isObject(param)) {
    return JSON.stringify(param);
  }
  return param;
}

// Ignore log messages if they have { private: true }
const all = format((info) => {
  const splat = info[SPLAT] || [];
  const message = formatObject(info.message);
  const rest = splat.map(formatObject).join(' ');
  info.message = `${message} ${rest}`;
  return info;
});

const customLogger = createLogger({
  format: combine(
    all(),
    label({ label: version }),
    timestamp(),
    colorize(),
    align(),
    printf(info => `${info.timestamp} [${info.label}] ${info.level}: ${formatObject(info.message)}`)
  ),
  transports: [new transports.Console()]
});

耇数のパラメヌタを蚱可するための䞀般的な回避策は次のずおりです。
https://github.com/rooseveltframework/roosevelt/blob/master/lib/tools/logger.js#L29

関連
https://github.com/winstonjs/winston/issues/1377

同じように機胜しないものが倚すぎたす。

こんにちは、ここに曎新はありたすか ありがずう。

たた、りィンストンでconsole.log(...args)を゚ミュレヌトする適切な方法を埅っおいたす...

私たちは、呚りの゚ッゞ/コヌナヌケヌスの数を固定splatずmetaで3.2.0が、これはただ問題参照で衚瀺されたす。https://github.com / winstonjs / winston / pull / 1576 CHANGELOG.md 。

これが3.3.0凊理されるこずを確認したす。 あなたの忍耐の人々に感謝したす。

これは私にずっおの回避策でした

'use strict';

const { createLogger, format, transports } = require('winston');
const { SPLAT } = require('triple-beam');

const { combine, timestamp, label, printf, colorize } = format;

const formatObject = (param) => {
  if (typeof param === 'string') {
    return param;
  }

  if (param instanceof Error) {
    return param.stack ? param.stack : JSON.stringify(param, null, 2);
  }

  return JSON.stringify(param, null, 2);
};

const logFormat = printf((info) => {
  const { timestamp: ts, level, message } = info;
  const rest = info[SPLAT] || [];
  const msg = info.stack ? formatObject(info.stack) : formatObject(message);
  let result = `${ts} ${level}: ${msg}`;

  if (rest.length) {
    result += `\n${rest.map(formatObject).join('\n')}`;
  }

  return result;
});

const logger = createLogger({
  format: combine(
    label({ label: 'app' }),
    timestamp(),
    logFormat,
  ),
  transports: [
    new transports.Console({
      format: combine(colorize()),
      handleExceptions: true,
    }),
  ],
  exceptionHandlers: [
    new transports.File({ filename: 'exceptions.log' }),
  ],
});

匕数を䜿甚しおログに蚘録しようずするず、奇劙な出力が埗られたす
var s = "Hello" log.info("asdasda", s)

出力を取埗する

{"0":"H","1":"e","2":"l","3":"l","4":"o","service":"XXXX","level":"info","message":"asdasda","timestamp":"2019-04-15 13:58:51"}

通垞のクむックスタヌトコヌドを䜿甚したした

私が気づいたこずの1぀はこれです

  • 2぀のトランスポヌトコン゜ヌルず回転ファむルを備えたロガヌを取埗したした
  • どちらもスプラット圢匏を䜿甚したす
  • 最初のトランスポヌトのsplatの倉換関数を呌び出すず、SPLATシンボルの䞋の情報に栌玍されおいる配列がクリアされたす。
  • 2番目のトランスポヌトのsplatの倉換関数を呌び出すず、SPLAT配列が空になるため、䜙分な匕数がログに蚘録されなくなりたす。

これが修正できる/修正されるこずを願っおいたす

泚Winstonの最新リリヌスバヌゞョンでこれをテストしたした。コヌドをざっず芋おみるず、マスタヌではただこのようになっおいるようです他の修正があるようです

@luisloboの゜リュヌションに察するいく぀かの改善👏

  • スプラットスタむルの堎合、぀たりlogger.info(`hello %s`,'world')ようなメッセヌゞに%s %d or %jが含たれおいる堎合は、メッセヌゞを無芖したす
  • フォヌマッタを䞊べ替えお色付けを最初に行うhttps://github.com/winstonjs/winston#colorizing-standard-logging-levels
  • printf twiseformateObjectを削陀したした
  • ルヌガヌに远加の匕数が指定されおいない堎合はtrimEnd
const { version } = require('../package');

const { createLogger, format, transports } = require('winston');
const { combine, timestamp, colorize, label, printf, align } = format;
const { SPLAT } = require('triple-beam');
const { isObject,trimEnd } = require('lodash');

function formatObject(param) {
  if (isObject(param)) {
    return JSON.stringify(param);
  }
  return param;
}

const all = format((info) => {
  const splat = info[SPLAT] || []

    const isSplatTypeMessage =
        typeof info.message === 'string' &&
        (info.message.includes('%s') || info.message.includes('%d') || info.message.includes('%j'))
    if (isSplatTypeMessage) {
        return info
    }
    const message = formatObject(info.message)
    const rest = splat
        .map(formatObject)
        .join(' ')
    info.message = trimEnd(`${message} ${rest}`)
    return info
});

const customLogger = createLogger({
  format: combine(
    colorize(),
    all(),
    label({ label: version }),
    timestamp(),
    align(),
    printf(info => `${info.timestamp} [${info.label}] ${info.level}: ${info.message}`)
  ),
  transports: [new transports.Console()]
});

私が行方䞍明になっおいるかもしれないこれぞのさらなる曎新はありたすか この機胜を再床远加するこずはかなり匷力にサポヌトされおいるようですが、これに察する最埌の取り組みはほが6か月前でした。

こんにちは、巚倧なバンパヌずショヌストッパヌが3.Xに移行しようずするず、おそらくしばらくの間2.xを維持したす。

少しがっかり:(

これは私のために働いたものです

const { format, createLogger, transports } = require('winston');
const jsonStringify = require('fast-safe-stringify');

const logLikeFormat = {
  transform(info) {
    const { timestamp, label, message } = info;
    const level = info[Symbol.for('level')];
    const args = info[Symbol.for('splat')];
    const strArgs = args.map(jsonStringify).join(' ');
    info[Symbol.for('message')] = `${timestamp} [${label}] ${level}: ${message} ${strArgs}`;
    return info;
  }
};

const debugFormat = {
  transform(info) {
    console.log(info);
    return info;
  }
};

const logger = createLogger({
  format: format.combine(
    // debugFormat, // uncomment to see the internal log structure
    format.timestamp(),
    format.label({ label: 'myLabel' }),
    logLikeFormat,
    // debugFormat, // uncomment to see the internal log structure
  ),
  transports: [
    new transports.Console()
  ]
});


logger.info('foo', 'bar', 1, [2, 3], true, { name: 'John' });

結果は次のようになりたす 2019-07-04T21:30:08.455Z [myLabel] info: foo "bar" 1 [2,3] true {"name":"John"}

基本的に、 format.combineはinfoオブゞェクトのパむプラむンを蚭定したす。 フォヌマット関数ごずに、 transformが呌び出され、最終的なログメッセヌゞがinfo[Symbol.for('message')]曞き蟌たれる必芁がありたす。
お圹に立おれば

%d 、 %oなどをサポヌトする゜リュヌションが必芁%d 、デフォルトでは残りの匕数が含たれおいるため、 logger.info('hello %d %j', 42, {a:3}, 'some', 'more', 'arguments')は次のようにレンダリングされたす。

hello 42 {"a": 3} some more arguments

これに察する私の解決策は、最終的にsplatシンボルを䜿甚したしたが、 printfから盎接util.format()手動で呌び出したした。これには、デフォルトで残りの匕数が含たれおいたす。

const {format} = require('util');
const winston = require('winston');
const {combine, timestamp, printf} = winston.format;
const SPLAT = Symbol.for('splat');

const transport = new winston.transports.Console({
    format: combine(
        timestamp(),
        printf(({timestamp, level, message, [SPLAT]: args = []}) =>
            `${timestamp} - ${level}: ${format(message, ...args)}`)
    )
})

printf必芁ない堎合は、もちろん、代わりに匕数をinfo.messageに展開する倉換を远加しお、最終結果を奜きなようにフォヌマットするこずができたす。

format: combine(
  {
    transform(info) {
      const {[SPLAT]: args = [], message} = info;

      info.message = format(message, ...args);

      return info;
    }
  },
  simple()
)  

format.splat()を䜿甚する堎合の問題は、䞀臎する匕数を消費したすが、残りを砎棄するように芋えるこずです。 util.format()自分で呌び出すこずで、その動䜜をオヌバヌラむドできたす。

同じ問題、これに関する曎新はありたすか Winstonは倧奜きですが、ロガヌに枡されたすべおの匕数を出力できないず、頭がおかしくなりたす。これは、 console.log()実行できたす。

@ fr1sk䞊蚘のフォヌマットを詊したしたか console.log()ような動䜜を提䟛したすノヌドのconsole.log()実装は内郚的にutil.format() afaikを䜿甚したす。

この問題がただ解決されおおらず、関連する問題がロックされおいるのは残念です。
私は倚くの異なるチヌムず協力しおおり、v3に移行するずきに以前のDXを倱うこずぞのフラストレヌションを共有しおいたす。

私は䞀日䞭物事を詊しおみたした。
䞊蚘の解決策は近いものでしたが、䜙分な匕数の色付けず改行がありたせんでした。

IMO、コン゜ヌルぞのログ蚘録は楜しいはずです。
これがそれを実珟するための私の詊みです...

比范のためのv2セットアップ

const winston = require('winston');
const chalk = require('chalk');

const logger = new winston.Logger({
  transports: [
    new winston.transports.Console({
      level: 'info',
      colorize: true,
      prettyPrint: true,
      timestamp: true
    })
  ]
});

logger.info({ one: 1, two: 2, three: 3 });
logger.info(chalk.blue('[TEST]:'), { one: 1, two: 2, three: 3 }, [4, 5, 6]);
logger.info(chalk.blue('[TEST]:'), null, undefined, 'one', 2, { 3: 3, 4: '4' });
logger.info(chalk.blue('[TEST]:'), chalk.yellow('Bombastic'), () => {}, /foo/);
logger.error(chalk.blue('[ERR]:'), new Error('Error number 1'));
logger.error(new Error('Error number 2'));

Winston2

v3セットアップ

const { createLogger, format, transports } = require('winston');
const { inspect } = require('util');
const chalk = require('chalk');
const hasAnsi = require('has-ansi');

function isPrimitive(val) {
  return val === null || (typeof val !== 'object' && typeof val !== 'function');
}
function formatWithInspect(val) {
  const prefix = isPrimitive(val) ? '' : '\n';
  const shouldFormat = typeof val !== 'string' || !hasAnsi(val);

  return prefix + (shouldFormat ? inspect(val, { depth: null, colors: true }) : val);
}

const logger = createLogger({
  level: 'info',
  format: format.combine(
    format.timestamp(),
    format.errors({ stack: true }),
    format.colorize(),
    format.printf(info => {
      const msg = formatWithInspect(info.message);
      const splatArgs = info[Symbol.for('splat')] || [];
      const rest = splatArgs.map(data => formatWithInspect(data)).join(' ');

      return `${info.timestamp} - ${info.level}: ${msg} ${rest}`;
    })
  ),
  transports: [new transports.Console()]
});

logger.info({ one: 1, two: 2, three: 3 });
logger.info(chalk.blue('[TEST]:'), { one: 1, two: 2, three: 3 }, [4, 5, 6]);
logger.info(chalk.blue('[TEST]:'), null, undefined, 'one', 2, { 3: 3, 4: '4' });
logger.info(chalk.blue('[TEST]:'), chalk.yellow('Bombastic'), () => {}, /foo/);
logger.error(chalk.blue('[ERR]:'), new Error('Error number 1'));
logger.error(new Error('Error number 2'));

Winston3

凊理するものはたくさんありたすが、そのうちのいく぀かは

  • 最初の匕数ずしおのオブゞェクトのような倀
  • 混合倀のいく぀かの匕数
  • chalkを䜿甚するなど、ANSI゚スケヌプコヌドを含む文字列
  • FunctionやRegExなどの難解な倀
  • 最初の匕数たたはその埌の任意の堎所での゚ラヌ
  • 他のフォヌマッタヌず䞀緒に問題なく動䜜するはずです

この゜リュヌションの珟圚のバグ

  • 最初の匕数ずしお゚ラヌを枡しおも、スタックトレヌスは出力されたせん

    • これは、 info.messageが単なる文字列であり、スタックトラクトがstackプロパティにあるためです。

  • でオブゞェクトを枡すmessage第䞀匕数のみ印刷しおプロパティmessage他のプロパティを砎棄し、

    • 䞊蚘ず同じ理由

  • 2番目の匕数ずしお゚ラヌを枡すず、゚ラヌメッセヌゞがinfo.message 通垞は1番目の匕数の倀の䞊に連結され、゚ラヌメッセヌゞが2回衚瀺されたす。

    • https://github.com/winstonjs/winston/issues/1660で远跡

    • これは実際にはREADMEの䞀郚です。

      >泚提䟛されたメタオブゞェクトの{message}プロパティは、すでに提䟛されおいるメッセヌゞに自動的に連結されたす。たずえば、以䞋は「world」を「hello」に連結したす。

errorsフォヌマッタヌをいじっおみおも圹に立ちたせんでした。

ポゞティブな機胜匷化

  • プリミティブ倀のロギングが適切になりたした
  • いく぀かのオブゞェクトのような倀をログに蚘録するず、それらの間に改行が远加されるようになりたした
  • むンデックスキヌを持぀オブゞェクトのように芋えるのではなく、配列のロギングが適切になりたした

線集

゚ラヌのフォヌマットは凊理できたすが、ハッキヌです。

function formatWithInspect(val) {
+ if (val instanceof Error) {
+   return '';
+ }

  const prefix = isPrimitive(val) ? '' : '\n';
  const shouldFormat = typeof val !== 'string' || !hasAnsi(val);

  return prefix + (shouldFormat ? inspect(val, { depth: null, colors: true }) : val);
}

...
    format.printf((info) => {
      const msg = formatWithInspect(info.message);
      const splatArgs = info[Symbol.for('splat')] || [];
      const rest = splatArgs.map((data) => formatWithInspect(data)).join(' ');
+    const stackTrace = info.stack ? `\n${info.stack}` : '';

      return `${info.timestamp} - ${info.level}: ${msg} ${rest}${stackTrace}`;
    })
...

info[Symbol.for('splat')]を䜿甚しお動䜜したす

const logger = winston.createLogger({
    level: 'debug',
    transports: [
        ...
    ],
    format: winston.format.combine(
        winston.format.timestamp(),
        winston.format.printf((info: any) => {
            const timestamp = info.timestamp.trim();
            const level = info.level;
            const message = (info.message || '').trim();
            const args = info[Symbol.for('splat')];
            const strArgs = (args || []).map((arg: any) => {
                return util.inspect(arg, {
                    colors: true
                });
            }).join(' ');
            return `[${timestamp}] ${level} ${message} ${strArgs}`;
        })
    )
});

メゞャヌバヌゞョンでは重倧な倉曎が導入されおいるこずは理解しおいたすが、私の良さは...

どの゜リュヌションも、winstonv2ず同じ動䜜をしたせんでした。
@henhalず@yamadashyの゜リュヌションには、どちらも同じ問題がありたす。メッセヌゞ倀が文字列ずしお衚瀺されたす。
logger.debug(err)ログメッセヌゞの䜜成

debug:  Error: ETIMEDOUT

䞀方、 logger.debug('anystringhere', err)は以䞋を䜜成したす。

debug:  anystringhereError: ETIMEDOUT { RequestError: Error: ETIMEDOUT
    at new RequestError (/path/to/node_modules/request-promise-core/lib/errors.js:14:15)
 <the rest of full error stack here>

2番目の問題は、情報レベルで䜿甚するず远加の匕数が抑制されるこずです。winstonv3は、フォヌマットする前にそれを逆に凊理するようです。

3番目の問題は、2぀のメッセヌゞの間にスペヌスがないこずです「anystringhereError」に泚意しおください。

私の珟圚のv3ロガヌ構成

const { format } = require('util');
const winston = require("winston");

const logger = winston.createLogger({
  transports: [
    new winston.transports.Console({
      level: 'debug'
      format: winston.format.combine(
          winston.format.colorize(),
          winston.format.align(),
          winston.format.printf(
              ({level, message, [Symbol.for('splat')]: args = []}) => `${level}: ${format(message, ...args)}`
          )
      )
    }),
  ]
});
module.exports = logger;

私はそれを十分に持っおいお、これだけでりィンストンv2に戻る぀もりです

const Winston = require("winston");

const logger = new Winston.Logger({
  transports: [
    new Winston.transports.Console({
      level: 'debug',
      handleExceptions: true,
      json: false,
      colorize: true,
    })
  ],
});
module.exports = logger;

このv2構成には、䞊蚘の問題はありたせん。

りィンストンの蚭定を共有したい

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

const myFormat = printf(({ level, message, label, timestamp, ...rest }) => {
    const splat = rest[Symbol.for('splat')];
    const strArgs = splat ? splat.map((s) => util.formatWithOptions({ colors: true, depth: 10 }, s)).join(' ') : '';
    return `${timestamp}  ${level}  ${util.formatWithOptions({ colors: true, depth: 10}, message)} ${strArgs}`;
});

const logger = createLogger({
    level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
    format: combine(
        colorize(),
        timestamp({
            format: 'YYYY-M-DD HH:mm:ss',
        }),
        padLevels(),
        myFormat
    ),
    transports: [new transports.Console()],
});

logger.info('test info');
logger.error('test error');
logger.debug('test debug');

image

耇数のパラメヌタを蚱可するための䞀般的な回避策は次のずおりです。
https://github.com/rooseveltframework/roosevelt/blob/master/lib/tools/logger.js#L29

ここに提案された゜リュヌションぞの曎新されたリンクがありたす
https://github.com/rooseveltframework/roosevelt/blob/0.13.0/lib/tools/logger.js

私のは@alexilyaevの玠晎らしい提案のバリ゚ヌションです

const { omit } = require('lodash');
const hasAnsi = require('has-ansi');

function isPrimitive(val) {
  return val === null || (typeof val !== 'object' && typeof val !== 'function');
}
function formatWithInspect(val) {
  if (val instanceof Error) {
    return '';
  }

  const shouldFormat = typeof val !== 'string' && !hasAnsi(val);
  const formattedVal = shouldFormat
    ? inspect(val, { depth: null, colors: true })
    : val;

  return isPrimitive(val) ? formattedVal : `\n${formattedVal}`;
}

// Handles all the different log formats for console
function getDomainWinstonLoggerFormat(format) {
  return format.combine(
    format.timestamp(),
    format.errors({ stack: true }),
    format.colorize(),
    format.printf((info) => {
      const stackTrace = info.stack ? `\n${info.stack}` : '';

      // handle single object
      if (!info.message) {
        const obj = omit(info, ['level', 'timestamp', Symbol.for('level')]);
        return `${info.timestamp} - ${info.level}: ${formatWithInspect(obj)}${stackTrace}`;
      }

      const splatArgs = info[Symbol.for('splat')] || [];
      const rest = splatArgs.map(data => formatWithInspect(data)).join('');
      const msg = formatWithInspect(info.message);

      return `${info.timestamp} - ${info.level}: ${msg}${rest}${stackTrace}`;
    }),
  );
}

次のようなログの堎合

logger.info({
    joe: 'blow',
  });
  logger.info('Single String');
  logger.info('With Func ', () => {}, /foo/);
  logger.info('String One ', 'String Two');
  logger.info('String One ', 'String Two ', 'String Three');
  logger.info('Single Object ', {
    test: 123,
  });
  logger.info(
    'Multiple Objects ',
    {
      test: 123,
    },
    {
      martin: 5555,
    },
  );
  logger.error('Error: ', new Error('Boom!'));

これは次のように出力されたす-これは私のすべおのシナリオに適しおいたす

Screen Shot 2020-02-06 at 10 54 31 pm

ねえ、私はWinstonから始めおおり、v2を䜿甚したこずがないので、v3.2.1を䜿甚しおいたす。

私は単玔にやろうずしおいたした

import winston, { format } from 'winston';
winston.format(format.combine(format.splat(), format.simple()));

winston.info('buildFastify dataPath %s', opts.dataPath);

そしお、文字列補間が機胜するこずを期埅しおいたす。 しかし、違いたす。

{"level":"info","message":"buildFastify dataPath %s"}

期埅しおいた時

{"level":"info","message":"buildFastify dataPath /My/Data/Path"}

この問題はどういうわけか同じこずですか たたは、代わりにlogger.log('info', .....)関数を䜿甚する必芁がありたすか

線集

これを詊行するむベントは機胜したせん。

  winston.log('info', 'buildFastify dataPath %s', opts.dataPath);

出力

{"level":"info","message":"buildFastify dataPath %s"}

䞊蚘の提案を投皿しおくれた人に感謝したす。
くそヌ私は私のプロゞェクトにりィンストン3を統合するためだけにある日捚おたした/

これは今日私を襲った-私の掟手な新しいロガヌが私のすべおの...rest匕数を投げおいるこずに気づいた。 これはすべおのナヌスケヌスたたはすべおのナヌスケヌスで機胜するずは限りたせんが、私の堎合は、ログに蚘録したいものすべおを配列ずしおラップするだけで問題ないこずがわかりたした。 これは最も矎しいわけではありたせんが、より倚くのコヌドを必芁ずする[非垞に賢い]回避策のいく぀かよりも軜量です。 これが他の誰かに圹立぀こずを願っおいたす

logger.info(["Something happened!", foo, bar]);

圌らがこれほど倧きな倉曎を加えるこずを決定したこずに本圓に腹を立お、

非垞にコンパクトで、ノヌドjsがutil.formatを䜿甚しおconsole.logを実装する方法に埓う゜リュヌションを共有したかったのですが

const winstonLogger= createLogger(...);

const writeLogType = (logLevel) => {
    return function () {
        const args = Array.from(arguments);
        winstonLogger[logLevel](util.format(...args));
    };
};

const logger = {
    silly: writeLogType('silly'),
    debug: writeLogType('debug'),
    verbose: writeLogType('verbose'),
    info: writeLogType('info'),
    warn: writeLogType('warn'),
    error: writeLogType('error'),
};

チャむムを鳎らしお、この機胜をコアWinstonに远加するように芁求したいず思いたす。 珟圚、私はこの機胜を実珟するためにsplatのカスタムフォヌマッタヌを䜿甚しおいたすが、これは正盎なずころ非垞にハッキヌな感じがしたす。 console.log䞀臎する機胜があるず䟿利です

曎新はありたすか

䞊蚘のv3の動䜜に加えお、これも远加したいず思いたす。

logger.info('param 1', { propInJson1: 'propInJson 1', propInJson2: 'propInJson 2' });

これを生成したす

{"propInJson1":"propInJson 1","propInJson2":"propInJson 2","level":"info","message":"param 1"}

私が䜿甚しおいるバヌゞョンv3.2.1
構成

winstonLogger.add(new winston.transports.Console());

Winstonで耇数の倀を出力する方法がただわかりたせん。

console.log('Hello', var1, '!')をlogger.log('Hello', var1, '!')に眮き換えたかっただけです。

正盎なずころ、Winstonを䜿甚しようずするず、垞に倚くの時間が無駄になり、ロギングで驚くべき問題が発生したす。

圌らがこれほど倧きな倉曎を加えるこずを決定したこずに本圓に腹を立お、

非垞にコンパクトで、ノヌドjsがutil.formatを䜿甚しおconsole.logを実装する方法に埓う゜リュヌションを共有したかったのですが

const winstonLogger= createLogger(...);

const writeLogType = (logLevel) => {
    return function () {
        const args = Array.from(arguments);
        winstonLogger[logLevel](util.format(...args));
    };
};

const logger = {
    silly: writeLogType('silly'),
    debug: writeLogType('debug'),
    verbose: writeLogType('verbose'),
    info: writeLogType('info'),
    warn: writeLogType('warn'),
    error: writeLogType('error'),
};

たた、 util.formatWithOptions({ colors: true }, ...args);を䜿甚しお、通垞のconsole.logようにカラヌ印刷出力を取埗したす

これは私のために働きたす。 util.formatを䜿甚しおメッセヌゞずスプラットを組み合わせるcombineMessageAndSplat

const winston = require("winston");
const util    = require('util');

const combineMessageAndSplat = () => {
    return {transform: (info, opts) => {
      //combine message and args if any
      info.message =  util.format(info.message, ...info[Symbol.for('splat')]  ||  [] )
      return info;
    }
  }
}

const logger = winston.createLogger({
  format:
    winston.format.combine(
      combineMessageAndSplat(),
      winston.format.simple()
    )
});

logger.add(new winston.transports.Console({
    level: 'info'
  })
);

logger.info("string");          // info: string
logger.info({a:1,b:[{c:[1]}]}); // info: { a: 1, b: [ { c: [Array] } ] }
logger.info("1","2",{a:1});     // info: 1 2 { a: 1 }
logger.info([{},""]);           // info: [ {}, '' ]
logger.error(new Error());      // error: Error ...    at Object.<anonymous> 

私はconsole。*メ゜ッドに準拠する必芁があり、䞊蚘のすべおを重芖し、...

  • chrome-dev-toolsのデフォルトのコン゜ヌルメ゜ッドデフォルトで色付けされたす
  • 電子端末コン゜ヌル出力デフォルトでも色付き
  • ファむルぞの曞き蟌み

ただし、ファむル出力にはオブゞェクトの詳现が衚瀺されたす。

だから私は結局

// make File and FileList parseable // from: https://stackoverflow.com/a/51939522/1644202
File.prototype.toObject = function () {
    return Object({
        name: String(this.name),
        path: String(this.path),
        lastModified: parseInt(this.lastModified),
        lastModifiedDate: String(this.lastModifiedDate),
        size: parseInt(this.size),
        type: String(this.type)
    });
};

FileList.prototype.toArray = function () {
    return Array.from(this).map(function (file) {
        return file.toObject()
    });
};

// this fixes: winston console transport to use the original console functions and all the colorization/folding/etc that comes with it
const Transport = require('winston-transport');
class WebDeveloperConsole extends Transport {
    constructor(opts) {
        super(opts);
    }

    log(info, callback) {
        (window.console[info.level] || window.console.log).apply(window.console, [info.timestamp, ...info.message]);
        callback();
    }
};

// Electron app console output
class AppConsole extends Transport {
    constructor(opts) {
        super(opts);

        const { remote } = require('electron');
        this.electronConsole = remote.getGlobal('console');
    }

    log(info, callback) {
        (this.electronConsole[info.level] || this.electronConsole.log).apply(this.electronConsole, [info.timestamp, ...info.message]);
        callback();
    }
};

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

let logger = createLogger({
    level: 'trace',
    levels: {
        error: 0,
        warn: 1,
        info: 2,
        //http: 3,   no console.* methods
        //verbose: 4,
        debug: 3,
        trace: 4
    },

    format: format.combine(
        format.prettyPrint(),
        format.timestamp({
            format: 'DD-MM-YYYY hh:mm:ss A'
        }),

        {
            transform(info) {
                const { timestamp, message } = info;
                const level = info[Symbol.for('level')];
                const args = [message, ...(info[Symbol.for('splat')] || [])];  // join the args back into one arr
                info.message = args;  // for all custom transports (mainly the console ones)

                let msg = args.map(e => {
                    if (e.toString() == '[object FileList]')
                        return util.inspect(e.toArray(), true, 10);
                    else if (e.toString() == '[object File]')
                        return util.inspect(e.toObject(), true, 10);
                    else if (e.toString() == '[object Object]') {
                        return util.inspect(e, true, 5);
                    }
                    else if (e instanceof Error)
                        return e.stack
                    else
                        return e;
                }).join(' ');

                info[Symbol.for('message')] = `${timestamp} - ${level}: ${msg}`; // for inbuild transport / file-transport

                return info;
            }
        },
    ),
    transports: [
        //new transports.Console(),
        new WebDeveloperConsole(),
        new AppConsole(),
        ...
    ],
    ...
});

@indexzeroある時点でただこれに察凊するこずを蚈画しおいたかどうか疑問に思っおいたしたか

私は自分のプロゞェクトで䜿甚するりィンストンを探しおいたすが、この問題は2幎以䞊続いおいるので、リスクを冒す䟡倀があるのではないかず考えおいたす。 私にずっお、これはあらゆるロギングフレヌムワヌクの基本的な機胜のようです

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