ããã¯ããªã«ãããããŠæžãããã®ïŒ
Node.jsã§ã¢ããªã±ãŒã·ã§ã³ãæžãæã®ãã®ã³ã°ã©ã€ãã©ãªã¯ãã©ããããã®ãããã®ãã¡ãã£ãšæ°ã«ãªããŸããŠã
調ã¹ãæãã以äžã®ãããªãã®ãããããã§ãã
GitHub - winstonjs/winston: A logger for just about everything.
GitHub - trentm/node-bunyan: a simple and fast JSON logging module for node.js services
GitHub - log4js-node/log4js-node: A port of log4js to node.js
GitHub - npm/npmlog: The logger that npm uses
ä»åã¯ããã®äžã§ãstaræ°ãå€ãwinstonãè©ŠããŠã¿ãããšã«ããŸããã
winston
winstonã¯ãè€æ°ã®ãã©ã³ã¹ããŒãïŒåºåå ïŒããµããŒããããã®ã³ã°ã©ã€ãã©ãªã§ãã
GitHub - winstonjs/winston: A logger for just about everything.
ãã¬ãŒãäœæããæã«ã
- åºåå
- ãã°ãã©ãŒããã
- åºåãããã°ã¬ãã«
ãªã©ãèšå®ã§ããŸãããã«ããŽãªå¥ã«ãã¬ãŒãäœæããããããã©ã«ããã¬ãŒãèšå®ããããã§ããŸãã
Working with multiple Loggers in winston
ãã°ã®åºåå
ã«ã¯ããã«ãã€ã³ã§ã¯ã³ã³ãœãŒã«ããã¡ã€ã«ãHTTPãStreamãéžã¹ããã®ä»ã«ãã³ãã¥ããã£ãªã©ã§ãããããš
å®è£
ãããŠããããã§ãã
winston/transports.md at 3.2.1 · winstonjs/winston · GitHub
ãã©ãŒãããã«ã€ããŠã¯ãlogformã§ã®ãã®ãæ±ããããã§ãã
GitHub - winstonjs/logform: An mutable object format designed for chaining & objectMode streams
Logstashãã©ãŒããããšãããã£ããããŸãã
ãšãããããä»åã¯ç°¡åã«è©ŠããŠã¿ããšããŸãããã
ç°å¢
ä»åã®ç°å¢ã¯ããã¡ãã
$ node -v v10.15.3 $ npm -v 6.4.1
æºå
winstonã®ã€ã³ã¹ããŒã«ã
$ npm i winston
ã€ã³ã¹ããŒã«ãããwinstonã®ããŒãžã§ã³ã
"dependencies": { "winston": "^3.2.1" }
ä»åã¯ããã¡ãã䜿ã£ãŠãããããšæããŸãã
winstonã䜿ã£ãŠããããè©Šã
ããã§ã¯ãããããããã€ãç°¡åã«winstonã䜿ã£ãã³ãŒããæžããŠãããŸãããã
Getting Startedçãª
ãªã«ã¯ãšãããããŸãã¯åãããŠã¿ãŸãã
ãããªã³ãŒããçšæã
winston-example1.js
const winston = require('winston'); const logger = winston.createLogger({ level: 'info', format: winston.format.json(), // default transports: [ new winston.transports.Console() ] }); logger.debug('Debug Message'); logger.info('Info Message'); logger.warn('Warn Message'); logger.error('Error Message');
ãã°åºåå
ãã³ã³ãœãŒã«ãåºåãããã°ã¬ãã«ãinfo以äžã«ããã°ãã©ãŒããããJSONã«ããŸããããã°åºåå
ïŒTransportïŒã¯ã
æå®ããªããšãšã©ãŒã«ãªããŸãã
ãã¬ãŒã®ããã©ã«ãèšå®ã¯ä»¥äžã«èšèŒããããŸããããã°ãã©ãŒãããã¯JSONããã°åºåã¬ãã«ã¯info以äžã¿ããã§ãã
å®è¡ã
$ node winston-example1.js {"message":"Info Message","level":"info"} {"message":"Warn Message","level":"warn"} {"message":"Error Message","level":"error"}
ãã°åºåã¬ãã«ãinfo以äžãªã®ã§ãdebugã®ãã®ã¯åºåãããŠããŸãããããŸãããã°ãã©ãŒãããã¯JSONã§ãã
ã¡ãªã¿ã«ããã°ã¬ãã«ã®äžèŠ§ã¯ãã¡ãã
ä»åã¯debugãinfoãwarnãerrorãã䜿ã£ãŠããŸãããããã£ãšããããããããšãããããŸãã
ãã°ã«ã¿ã€ã ã¹ã¿ã³ããå ¥ããã¡ãã»ãŒãžããã©ãŒãããæå®ã§ããããã«ããŠã¿ã
å ã»ã©ã®ãã°ã«ã¯ãå®è¡æã®ã¿ã€ã ã¹ã¿ã³ãããããŸãããã§ããã°ãã¿ã€ã ã¹ã¿ã³ãã衚瀺ããããšããã§ãã
ãŸãããã°ã¡ãã»ãŒãžã«%sã®ãããªãã©ãŒãããæå®ãã§ãããããªã®ã§ããã¡ããåãããŠè©ŠããŠã¿ãŸããã
winston-example2.js
const winston = require('winston'); const format = winston.format; const logger = winston.createLogger({ level: 'info', format: format.combine( format.timestamp(), // timestampãåºåãã format.splat(), // String interpolation splat for %d %s-style messages. format.json() ), transports: [ new winston.transports.Console() ] }); logger.debug('Debug Message'); logger.info('Info Message'); logger.warn('Warn Message'); logger.error('Error Message'); logger.debug('%s %s', 'Debug','Message'); logger.info('%s %s', 'Info', 'Message'); logger.warn('%s %s', 'Warn', 'Message'); logger.error('%s %s', 'Error', 'Message');
ãã¡ãã¯ããã©ãŒããããcombineã§çµã¿åãããããšã§èšå®ããŠããŸãã
format: format.combine( format.timestamp(), // timestampãåºåãã format.splat(), // String interpolation splat for %d %s-style messages. format.json() ),
ãã®æå®ããé çªã倧äºã¿ããã§ãjsonã®åŸã«timestampãå ¥ããããããšãã¿ã€ã ã¹ã¿ã³ãã¯åºåãããŸããâŠã
詳现ã¯ãlogformãèŠãŠã¿ããšããã§ãããã
GitHub - winstonjs/logform: An mutable object format designed for chaining & objectMode streams
確èªã
$ node winston-example2.js {"message":"Info Message","level":"info","timestamp":"2019-05-21T14:21:17.627Z"} {"message":"Warn Message","level":"warn","timestamp":"2019-05-21T14:21:17.628Z"} {"message":"Error Message","level":"error","timestamp":"2019-05-21T14:21:17.628Z"} {"level":"info","message":"Info Message","timestamp":"2019-05-21T14:21:17.629Z"} {"level":"warn","message":"Warn Message","timestamp":"2019-05-21T14:21:17.629Z"} {"level":"error","message":"Error Message","timestamp":"2019-05-21T14:21:17.629Z"}
ã¿ã€ã ã¹ã¿ã³ãããã°ã«å ¥ãã%sã®éšåã眮æãããããã«ãªã£ãŠããŸãã
ãšããã§ãã¿ã€ã ãŸãŒã³ãUTCæã
ã¿ã€ã ã¹ã¿ã³ãã®ãã©ãŒããããå€ãããå Žåã¯ãtimestampã«formatã§æå®ããã°ããã¿ããã§ãã
ãã°ãã©ãŒãããã«ä»»æã®é ç®ãè¿œå ãã
ãã°ãã©ãŒãããã«ãä»»æã®é ç®ãè¿œå ããŠã¿ãŸããããèŠããã«ãã«ã¹ã¿ã ãã©ãŒãããã®äœãæ¹ã§ãã
ä»åã¯ããhostnameããšããé
ç®ã足ããŠã¿ãŸããã
winston-example3.js
const winston = require('winston'); const format = winston.format; const hostname = format((info, opts = {}) => { let value; if (!opts.hostname) { value = 'myhost'; } else { value = opts.hostname; } if (!opts.alias) { info.hostname = value; } else { info[opts.alias] = value; } return info; }); const logger = winston.createLogger({ level: 'info', format: format.combine( format.timestamp(), hostname(), // custom format format.json() ), transports: [ new winston.transports.Console() ] }); logger.debug('Debug Message'); logger.info('Info Message'); logger.warn('Warn Message'); logger.error('Error Message');
ãã©ãŒãããã¯ãformaté¢æ°ã§äœæããŸããä»åã¯ããã¹ãåïŒåºå®ã§ããïŒãå ¥ããããšã«ããŸããã
const hostname = format((info, opts = {}) => { let value; if (!opts.hostname) { value = 'myhost'; } else { value = opts.hostname; } if (!opts.alias) { info.hostname = value; } else { info[opts.alias] = value; } return info; });
ãã®é¢æ°ããformatãªãã·ã§ã³ã§æå®ããŸãã
format: format.combine(
format.timestamp(),
hostname(), // custom format
format.json()
),
確èªã
$ node winston-example3.js {"message":"Info Message","level":"info","timestamp":"2019-05-21T14:25:30.017Z","hostname":"myhost"} {"message":"Warn Message","level":"warn","timestamp":"2019-05-21T14:25:30.018Z","hostname":"myhost"} {"message":"Error Message","level":"error","timestamp":"2019-05-21T14:25:30.018Z","hostname":"myhost"}
ãhostnameããšããé ç®ãå¢ããŸãããã
ä»åã¯äœ¿ã£ãŠããŸãããããã®hostnameã«ãªãã·ã§ã³ãäžãããšãåäœã®ã«ã¹ã¿ãã€ãºãã§ããããã«ãªããŸãã以äžã®ã³ãŒãã§ã
infoã¯å®éã«åºåãããã°ã®æ
å ±ã§ãoptsã¯formatãäœæããæã®ãªãã·ã§ã³ã§ãã
const hostname = format((info, opts = {}) => { let value; if (!opts.hostname) { value = 'myhost'; } else { value = opts.hostname; } if (!opts.alias) { info.hostname = value; } else { info[opts.alias] = value; } return info; });
ãªãã·ã§ã³ã¯ããããªæãã§æå®ããŸãã
hostname({ alias: 'servername' }), // custom format
ãã°ãè€æ°ã®åºåå ã«åºåãã
åºåå ïŒTransportïŒãè€æ°æå®ããããšã§ããã°ãè€æ°ã®ã¿ãŒã²ããã«åºåããããšãã§ããŸãã
ããšãã°ãã³ã³ãœãŒã«ãšãã¡ã€ã«ã«åºåããå Žåã
winston-example4.js
const winston = require('winston'); const logger = winston.createLogger({ level: 'info', transports: [ new winston.transports.Console({ level: 'warn' }), new winston.transports.File({ filename: 'app.log', level: 'debug' }) ] }); logger.debug('Debug Message'); logger.info('Info Message'); logger.warn('Warn Message'); logger.error('Error Message');
åºåå ïŒTransportïŒåäœã§ãèšå®ãå€æŽããããšãã§ããŸãã
transports: [ new winston.transports.Console({ level: 'warn' }), new winston.transports.File({ filename: 'app.log', level: 'debug' }) ]
ä»åã¯ããã©ã«ãã®ãã°ã¬ãã«ã¯infoã«ããŠããŸãããã³ã³ãœãŒã«ã¯warnããã¡ã€ã«ã¯debugã«ããŠã¿ãŸããããŸãããã¡ã€ã«ã®æ¹ã®
åºåå
ã¯app.logãšããŸãã
確èªã
$ node winston-example4.js {"message":"Warn Message","level":"warn"} {"message":"Error Message","level":"error"}
ã³ã³ãœãŒã«ã«ã¯ãinfoãåºãªããªããŸããããã¡ã€ã«ã®ãã°ãèŠãŠã¿ãŸãããã
$ cat app.log {"message":"Debug Message","level":"debug"} {"message":"Info Message","level":"info"} {"message":"Warn Message","level":"warn"} {"message":"Error Message","level":"error"}
ãã¡ãã¯ãdebugã¬ãã«ãŸã§åºåãããŠããŸãã
Transportã¯ãä»ã«ããã€ãªãŒã§ããŒããŒã·ã§ã³ãããã®ã ã£ãããšããããããã®ã§ã確èªããŠã¿ããšããã§ãããã
winston/transports.md at 3.2.1 · winstonjs/winston · GitHub
CLIãã°ãã©ãŒãããã«ãã
ãããŸã§JSONãã©ãŒãããã§ãã°ãåºåããŠããŸãããããã£ãšCLIã£ãœããã°ã§ãåºåããŠã¿ããããªãšã
ãããªæãã®ãã©ãŒãããã§ã©ãã§ãããã
winston-example5.js
const winston = require('winston'); const format = winston.format; const logger = winston.createLogger({ level: 'info', format: format.combine( format.timestamp(), // timestampãåºåãã format.cli(), format.printf(info => `[${info.timestamp}] ${info.level} ${info.message}`) ), transports: [ new winston.transports.Console() ] }); logger.debug('Debug Message'); logger.info('Info Message'); logger.warn('Warn Message'); logger.error('Error Message');
ã¿ã€ã ã¹ã¿ã³ããå ¥ããCLIãã©ãŒãããã§ãè¿œå ããã¿ã€ã ã¹ã¿ã³ãã®äœçœ®ã¯printfã§æ±ºå®ããŸãã
確èªã
$ node winston-example5.js [2019-05-21T14:33:57.427Z] info Info Message [2019-05-21T14:33:57.428Z] warn Warn Message [2019-05-21T14:33:57.428Z] error Error Message
ãã°ã¬ãã«ã¯ãã«ã©ãŒã§åºåãããŸãã
CLIãã©ãŒãããã®æ£äœã¯ãcolorizeãpadLevelsãçµã¿åããããã®ã§ãã
ã«ã©ãŒè¡šç€ºããããããã°ãcliã®éšåãsimpleã«ãããšããã§ãããã
format: format.combine( format.timestamp(), // timestampãåºåãã format.simple(), format.printf(info => `[${info.timestamp}] ${info.level} ${info.message}`) ),
ãã°ã«Errorãåºåããã
ãã°åºåã®éã«ã¯ãtryãcatchããErrorãåºåããããããšãããã§ãããã
ãããŸãããã¥ã¡ã³ãã«ããã£ãœãããšãæžãããŠããªãã£ãã®ã§ãè©ŠããŠã¿ãŸããããããªæãã£ãœãã§ãã winston-example6.js
const winston = require('winston'); const logger = winston.createLogger({ transports: [ new winston.transports.Console() ] }); logger.error('error: ', new Error('Oops!!')); // OK logger.error(new Error('Oops!!')); // NG
2ã€ç®ã®ãã°åºåã¯ãNGäŸã§ãã
確èªã
$ node winston-example6.js {"level":"error","message":"error: Oops!!","stack":"Error: Oops!!\n at Object.<anonymous> (/path/to/winston-example6.js:9:25)\n at Module._compile (internal/modules/cjs/loader.js:701:30)\n at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)\n at Module.load (internal/modules/cjs/loader.js:600:32)\n at tryModuleLoad (internal/modules/cjs/loader.js:539:12)\n at Function.Module._load (internal/modules/cjs/loader.js:531:3)\n at Function.Module.runMain (internal/modules/cjs/loader.js:754:12)\n at startup (internal/bootstrap/node.js:283:19)\n at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)"} {"level":"error"}
ã²ãšã€ç®ã®ãã°ã¯ããããªæãã«åºåãããŠããŸãã
{"level":"error","message":"error: Oops!!","stack":"Error: Oops!!\n at Object.<anonymous> (/path/to/winston-example6.js:9:25)\n at Module._compile (internal/modules/cjs/loader.js:701:30)\n at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)\n at Module.load (internal/modules/cjs/loader.js:600:32)\n at tryModuleLoad (internal/modules/cjs/loader.js:539:12)\n at Function.Module._load (internal/modules/cjs/loader.js:531:3)\n at Function.Module.runMain (internal/modules/cjs/loader.js:754:12)\n at startup (internal/bootstrap/node.js:283:19)\n at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)"}
ããããèŠããšãæå®ããã¡ãã»ãŒãžã«ãããã«Errorã®ã¡ãã»ãŒãžãè¿œå ãããŠããŸããã
"message":"error: Oops!!"
ããã¯ããã®ãããã§è¡ãããŠããããã§ãã
https://github.com/winstonjs/winston/blob/3.2.1/lib/winston/logger.js#L241-L242
ãŸãã2ã€ç®ã®ãã°ã¯ãErrorã®æ å ±ããã¬ã€ã«ç¡èŠãããŠããŸãã
{"level":"error"}
ãšããããã§ãã¡ãã»ãŒãžãšã¯å¥ã«Errorãæå®ããŸããããšããããšã§ã
logger.error('error: ', new Error('Oops!!')); // OK
ãã®ä»
ã«ããŽãªãŒãšãã䟿å©ããªããšã¯æããŸãããä»åã¯ããããªããšã
Working with multiple Loggers in winston
ã¡ã¢ãšããŠã¯ãæžãçããŠããçšåºŠã«ããŠãããŸãã
ãšãããããåºæ¬çãªäœ¿ãæ¹ãšããŠã¯ãããªãšããã§ã¯ãªãã§ããããã