まるまるこふこふ

数々の次元が崩壊し、全ての生命が塵と化すのを見てきた。私ほどの闇の心の持ち主でも、そこには何の喜びも無かった。

ログ出力ライブラリ node-bunyan

この記事はNode.js Advent Calendar その2 の5日目の記事です。

express のアプリケーションログ

express でアプリケーションログを出力したい。

express-generator などで express アプリを作ると、最初から morgan
使われていますが、これはアクセスログを保存するもので、
アプリケーションログを出力するものではありません。

有名ドコロを探ってみたところ、log4jsbunyan があるみたいなので、 bunyan 使います。

バニヤンと読むみたいです。ぶーにゃんって読んでました。ぶーにゃんかわいいよぶーにゃん。

インストール

npm install bunyan

インストールしましょう。インストールすると bunyan コマンドという
ログをいい感じに見やすくするツールもついてきます。これは後述します。

Introduction

$ cat hi.js
var bunyan = require('bunyan');
var log = bunyan.createLogger({name: 'myapp'});
log.info('hi');
log.warn({lang: 'fr'}, 'au revoir');

こんな感じのスクリプトを書いて実行します。 name にはアプリの名前をお好きに書いてあげてください。

$ node hi.js
{"name":"myapp","hostname":"banana.local","pid":40161,"level":30,"msg":"hi","time":"2013-01-04T18:46:23.851Z","v":0}
{"name":"myapp","hostname":"banana.local","pid":40161,"level":40,"lang":"fr","msg":"au revoir","time":"2013-01-04T18:46:23.853Z","v":0}

実行するとこんな感じのログが標準出力されます。bunyan は
JSONフォーマットでログ出力してくれるので
fluentd などでログを扱いやすいのが特徴です。

level というのはエラーレベルのことですね。bunyan には下記6つのAPIでログを出力することが
でき、それぞれ危険度に応じて level が設定されており、それが出力されております。

var bunyan = require('bunyan');
var log = bunyan.createLogger({name: 'myapp'});

log.trace('trace log'); // level 10
log.debug('debug log'); // level 20
log.info('info log'); // level 30
log.warn('warn log'); // level 40
log.error('error log'); // level 50
log.fatal('fatal log'); // level 60

bunyan コマンド

JSONフォーマットはコンピュータには扱いやすいですが、人間が読むことには適していません。 先ほどご紹介した bunyan コマンドを使うと、見やすい形に整形してくれます。

$ node hi.js | ./bin/bunyan
[2013-01-04T19:01:18.241Z]  INFO: myapp/40208 on banana.local: hi
[2013-01-04T19:01:18.242Z]  WARN: myapp/40208 on banana.local: au revoir (lang=fr)

標準出力からJSONフォーマットのログの内容を受けて、標準出力に整形後のログを
吐き出します。

※実際にはカラーリングされてて、より読みやすいです。

ログの出力設定

bunyan はデフォルトでは info 以上のログを標準出力に吐くようになってます。

// デフォルトの設定
var log = bunyan.createLogger({
    name: 'myapp',
    stream: process.stdout,
    level: 'info'
});

こんな感じで出力先をファイルにすることができます。

var log = bunyan.createLogger({
  name: 'myapp',
  streams: [
    {
      level: 'error',
      path: '/var/tmp/myapp-error.log'
    }
  ]
});

配列になってることからも分かる通り、出力先を複数設定することも可能です。

// info以上 -> 標準出力
// error以上 -> myapp-error.logに出力
var log = bunyan.createLogger({
  name: 'myapp',
  streams: [
    {
      level: 'info',
      stream: process.stdout
    },
    {
      level: 'error',
      path: '/var/tmp/myapp-error.log'
    }
  ]
});

ログファイルのローテーション

ログ・ファイルのローテーションはLinux の logratate を使っても良いのですが、
bunyan は自前でログローテション機能も持ってます。

var log = bunyan.createLogger({
    name: 'foo',
    streams: [{
        type: 'rotating-file',
        path: '/var/log/foo.log',
        period: '1d',
        count: 3
    }]
});

これで

/var/log/foo.log # 今日のログ
/var/log/foo.log.0 # 前日のログ
/var/log/foo.log.1 # 前々日のログ
/var/log/foo.log.2 # 前々々日のログ

と 1日ごとに 3つのログをローテーションしてくれます(それ以降の数のログは削除されます)

src

var log = bunyan.createLogger({src: true, ...});

createLogger 時に src: trueを設定すると、

{
  "name": "src-example",
  "hostname": "banana.local",
  "pid": 123,
  "component": "wuzzle",
  "level": 4,
  "msg": "This wuzzle is woosey.",
  "time": "2012-02-06T04:19:35.605Z",
  "src": {
    "file": "/Users/trentm/tm/node-bunyan/examples/src.js",
    "line": 20,
    "func": "Wuzzle.woos"
  },
  "v": 0
}

とより詳細な情報を吐いてくれます。開発環境で実行する時は true にしておくといいかも。

終わり

GithubREADME にもっとたくさんいいこと書いてあるよ!