Winston: Winston์€ ์˜ˆ์™ธ์—์„œ ํฌ์ฐฉ๋œ ์˜ค๋ฅ˜๋ฅผ ๊ธฐ๋ก/๋ถ„์„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์— ๋งŒ๋“  2020๋…„ 03์›” 04์ผ  ยท  3์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: winstonjs/winston

๊ท€ํ•˜์˜ ํ™˜๊ฒฝ์— ๋Œ€ํ•ด ์•Œ๋ ค์ฃผ์‹ญ์‹œ์˜ค.

  • _ winston ๋ฒ„์ „?_ 3.2.1

    • [ ] winston@2

    • [x] winston@3

  • _ node -v ์ถœ๋ ฅ:_ v12.8.1
  • _์šด์˜ ์ฒด์ œ?_(Windows, macOS ๋˜๋Š” Linux) Windows
  • _์–ธ์–ด?_ (์ „์ฒด | TypeScript XX | ES6/7 | ES5 | Dart) ES6

๋ฌธ์ œ๊ฐ€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

Winston์€ ์˜ˆ์™ธ๋ฅผ ๊ธฐ๋กํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™๊ณ  ์˜ค๋ฅ˜ ๊ฐœ์ฒด๋ฅผ ์ œ๋Œ€๋กœ ๊ตฌ๋ฌธ ๋ถ„์„ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

const logger = winston.createLogger({
    level: 'info',
    format: winston.format.combine(winston.format.timestamp(), winston.format.json()),
    transports: [
        new winston.transports.File({
            filename: `./logs/error-${momentLogger.unix()}.log`,
            level: 'error'
        }),
        new winston.transports.File({
            filename: `./logs/debug-${momentLogger.unix()}.log`,
            level: 'debug'
        }),
        new winston.transports.File({
            filename: `./logs/combined-${momentLogger.unix()}.log`
        }),
        new winston.transports.Console({
            format: winston.format.simple()
        })
    ]
});

try {
    logger.debug(folderIdRegex.exec(event.link)[1]);
} catch (ex) {
    console.log(ex); // Correctly prints
    logger.info(ex); // Undefined
    logger.debug(ex); // Undefined
    logger.error(ex); // Undefined
}

VSCode ๋””๋ฒ„๊ฑฐ๋ฅผ ์‚ฌ์šฉํ•œ ์ถ”๊ฐ€ ๋””๋ฒ„๊น…

// Output
TypeError: Cannot read property '1' of null
    at .....google-sheets-scraping-testing.js:188:51
    at processTicksAndRejections (internal/process/task_queues.js:85:5)
info: undefined {"timestamp":"2020-03-04T19:58:36.251Z"}
error: undefined {"timestamp":"2020-03-04T19:58:36.251Z"}

// Here I started using the built-in debug terminal
ex // Input into debug console
> TypeError: Cannot read property '1' of null // Result of ex
logger.log(ex) // Input into debug console
info: undefined {"timestamp":"2020-03-04T20:11:13.924Z"} // Result of logger.log(ex)
> DerivedLogger {_readableState: ReadableState, readable: true, _events: Object, _eventsCount: 3, _maxListeners: undefined, โ€ฆ}  // Result of logger.log(ex)

๊ทธ ๋Œ€์‹  ์–ด๋–ค ์ผ์ด ์ผ์–ด๋‚˜๊ธฐ๋ฅผ ๊ธฐ๋Œ€ํ•˜์‹ญ๋‹ˆ๊นŒ?

Winston์ด try...catch ๋ธ”๋ก์—์„œ catch๋œ ์˜ค๋ฅ˜๋ฅผ ๊ธฐ๋กํ•  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•ฉ๋‹ˆ๋‹ค. ex.message ๋Œ€์‹  ex ๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ์ œ๋Œ€๋กœ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค. ex ๋Š” catch ๋ธ”๋ก ์ „์ฒด์— ๊ฑธ์ณ ์ •์˜๋˜์–ด ์žˆ์ง€๋งŒ Winston์€ ์–ด๋–ค ์ด์œ ๋กœ ์ด๋ฅผ ๊ตฌ๋ฌธ ๋ถ„์„ํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ธฐํƒ€ ์ •๋ณด

๋˜ํ•œ catch ๋ธ”๋ก ๋‚ด์—์„œ return ex ํ•˜๊ณ  ๋‹ค๋ฅธ catch ๋ธ”๋ก ๋‚ด์—์„œ ๋ชจ๋“  ๊ฒƒ์„ ๋‘˜๋Ÿฌ์‹ธ๋ฉด ์ œ๋Œ€๋กœ ์ถœ๋ ฅ๋˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด ๋น„์ •์ƒ์ ์ธ ๋™์ž‘์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ด๊ฒƒ์ด Winston์˜ ๋ฒ„๊ทธ๋ผ๋Š” ๊ฒƒ์„ ๊นจ๋‹ซ๊ธฐ ์ „์— ๋‚ด๊ฐ€ Discord์— ์ž‘์„ฑํ•œ ์ง€์› ๊ฒŒ์‹œ๋ฌผ ์˜ ์š”์ง€๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š” .

๋˜ํ•œ ์ด ์˜ค๋ฅ˜๋Š” ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž๊ฐ€ #1758์—์„œ ์ง€๋‚œ ํ•œ ๋‹ฌ ๋™์•ˆ ๊ฒช์—ˆ๋˜ ๋ฌธ์ œ๋„ ์ˆ˜๋ฐ˜ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

๋‚˜๋Š” ์ด๊ฒƒ์ด ํ˜•์‹์„ ์ ์šฉํ•  ๋•Œ winston ๋กœ๊ฑฐ์™€ ์ „์†ก ์‚ฌ์ด์˜ ์ผ๊ด€์„ฑ ์—†๋Š” ๋™์ž‘ ๋•Œ๋ฌธ์ผ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. winston-transport์—์„œ TransportStream _write ํ•จ์ˆ˜์˜ ์ผ๋ถ€๋Š” ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

transformed = this.format.transform(Object.assign({}, info), this.format.options);

winston/logger.js์˜ ๊ด€๋ จ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

this.push(this.format.transform(info, this.format.options));

๋‹ค์Œ์€ ๋ฌธ์ œ์˜ ๋‹จ์ˆœํ™”๋œ ์žฌํ˜„์ž…๋‹ˆ๋‹ค.

const winston = require('winston');

// First logger uses a format configured on logger
const logger1 = winston.createLogger({
  level: 'info',
  transports: new winston.transports.Console(),
  format: winston.format.simple()
});


// Second logger uses a format configured on transport
const logger2 = winston.createLogger({
  level: 'info',
  transports: new winston.transports.Console({
    format: winston.format.simple()
  })
});

logger1.info(new Error('err message'));   // logs expected 'err message'
logger2.info(new Error('err message'));   // logs 'undefined'

์–ด๋–ค ํ–‰๋™์„ ์„ ํ˜ธํ•ด์•ผ ํ•˜๋Š”์ง€ ๋ช…ํ™•ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  3 ๋Œ“๊ธ€

๋‚˜๋Š” ์ด๊ฒƒ์ด ํ˜•์‹์„ ์ ์šฉํ•  ๋•Œ winston ๋กœ๊ฑฐ์™€ ์ „์†ก ์‚ฌ์ด์˜ ์ผ๊ด€์„ฑ ์—†๋Š” ๋™์ž‘ ๋•Œ๋ฌธ์ผ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. winston-transport์—์„œ TransportStream _write ํ•จ์ˆ˜์˜ ์ผ๋ถ€๋Š” ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

transformed = this.format.transform(Object.assign({}, info), this.format.options);

winston/logger.js์˜ ๊ด€๋ จ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

this.push(this.format.transform(info, this.format.options));

๋‹ค์Œ์€ ๋ฌธ์ œ์˜ ๋‹จ์ˆœํ™”๋œ ์žฌํ˜„์ž…๋‹ˆ๋‹ค.

const winston = require('winston');

// First logger uses a format configured on logger
const logger1 = winston.createLogger({
  level: 'info',
  transports: new winston.transports.Console(),
  format: winston.format.simple()
});


// Second logger uses a format configured on transport
const logger2 = winston.createLogger({
  level: 'info',
  transports: new winston.transports.Console({
    format: winston.format.simple()
  })
});

logger1.info(new Error('err message'));   // logs expected 'err message'
logger2.info(new Error('err message'));   // logs 'undefined'

์–ด๋–ค ํ–‰๋™์„ ์„ ํ˜ธํ•ด์•ผ ํ•˜๋Š”์ง€ ๋ช…ํ™•ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

winston์ด ์ผ๋ถ€ ๊ฐœ์ฒด๋ฅผ ์ œ๋Œ€๋กœ ๊ธฐ๋กํ•˜์ง€ ์•Š๊ณ  [object Object] ์ธ์‡„ํ•˜๋Š” ๋ฐ˜๋ฉด ๋‹ค๋ฅธ ๊ฐœ์ฒด๋Š” ๋ฌธ์ œ ์—†์ด ์ธ์‡„ํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ ๋™์ผํ•œ ๊ฒฝ์šฐ์ธ์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

@jleverenz
๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค, ์ข‹์€ ๋ฐœ๊ฒฌ! https://github.com/winstonjs/winston/issues/1758 ๊ณผ ๋™์ผํ•œ ๋‚ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ๊ฐ„๋‹จํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• ์„ ์ œ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰