expressというかnodeというか・・でログを取る（log4js編）


アクセスログをとるだけなら[morgan](https://github.com/expressjs/morgan)とかの方が簡単そうですが、とりあえず馴染みのあるlog4jsを利用してみます。

## 準備と注意点

### 準備

```bash
npm install log4js
```

### 注意点

現在のlog4jsはver2.x系で2017年5月に2.xになった模様。
ネット上の情報のほとんどが1.xで書かれたもので、動作しないことが多いので注意。
[本家サイト](https://github.com/log4js-node/log4js-node)などを見て対応する必要あり。

## とりあえず利用してみる

### 一番簡単な実装

一番簡単な実装は下記。

```js
var log4js = require('log4js');
var logger = log4js.getLogger();

logger.level = "debug"; //これがないと表示されない
logger.debug("hoge hoge");
```

ログがコンソールに出力される。でも、このレベルならconsole.log()で事足ります。

### ファイルに出力したい

というわけで、ファイルに出力したいのですが、とたんに記述増えます。
どうやら、2.xからカテゴリーの追加が変更・必須になって手間が増えたようです。

>カテゴリは配列でappendersを取るので、複数の指定も可能。
>また、getLogger()では、appenderじゃなくて、categories名を指定するのがポイントです。

```js
var log4js = require('log4js');

//config
log4js.configure({
    appenders: {
        system: {type: 'file', filename: 'system.log'}
    },
    categories: {
        default: {appenders:['system'], level: 'debug'}
    }
});

var systemLogger = log4js.getLogger(); //getLogger('default')と同義

systemLogger.debug("hoge");
```

実行するとsystem.logが作成され、下記が出力される。

```system.log
[2018-04-11T06:18:14.965] [DEBUG] default - hoge
```



### expressのアクセスログを取りたいが、システムログとはファイルを分けたい

```js
var log4js = require('log4js');

//config
log4js.configure({
    appenders: {
        system: {type: 'file', filename: 'system.log'},
        access: {type: 'file', filename: 'access.log'} //追加
    },
    categories: {
        default: {appenders:['system'], level: 'debug'},
        web: {appenders: ['access'], level: 'info'} //追加
    }
});



//logger
var systemLogger = log4js.getLogger(); 
var accessLogger = log4js.getLogger('web'); //追加

//express
var express = require('express');
var app = express();
//bind access log
app.use(log4js.connectLogger(accessLogger));

//root
app.get('/', function(req, res) {
    res.send("hello logger");
});

//listen
app.listen(3000, function(req, res){
    console.log("app listen on 3000 port.")
});

//system log
systemLogger.info("Express start");
```

#### system.log

実行するとsystem.logにはexpressのstartが表示される。

```
[2018-04-11T06:29:47.603] [INFO] default - Express start

```

#### access.log

access.log側にはexpressへのアクセスログが表示される。

```
[2018-04-11T06:29:58.258] [INFO] web - ::1 - - "GET / HTTP/1.1" 304 - "" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
[2018-04-11T06:30:04.137] [INFO] web - ::1 - - "GET /?hoge=hoge HTTP/1.1" 200 12 "" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
```

### ログタイプの指定

fileの場合はローテーションなどを気にする必要がありますが、サイズ指定や日別分割もできます。

#### 日別指定

例えばWebのサクセスログなどは日別にしたいものです。例えばappendersの指定を下記のようにします。

```js
access: { type: 'dateFile', filename: 'access.log', pattern: '-yyyy-MM-dd' }
```

#### サイズやバックアップ数の指定

```js
system: { type: 'file', filename: 'system.log', maxLogSize: 10485760, numBackups: 3 },
```

#### コンソールに出力

下記のようにすればコンソールに出力されます。

```js
system: { type: 'console' }
```

### 設定ファイルを外部ファイル化したい

下記のようにすれば外部ファイルから設定を読み込めます。

#### 読込

```js
log4js.configure('./log4js.config.json');
```

#### 設定ファイル

ただJSON化すると、パラメータを""で囲む必要があるので、最初から外部ファイルで記述したほうが手間がないかもしれません。

>もちろんjsをimportしてオブジェクトのまま利用するのもありですが。

```js:log4j.config.json
{
    "appenders": {
        "system": {"type": "file", "filename": "system.log"},
        "access": {"type": "file", "filename": "access.log"}
    },
    "categories": {
        "default": {"appenders":["system"], "level": "debug"},
        "web": {"appenders": ["access"], "level": "info"}
    }
}
```