Apacheのログの表示形式を設定する方法 〜調べてみた編〜

Webサービスを開発しているとだいたいのケースでApacheが使われるかと思うのですが、その際にどんなログを表示・取得しておくかは、開発時・サービス運用時にとても大切になります。
Apacheには主に、 **アクセスログ** と **エラーログ** があり、特にアクセスログは設定の自由度が高く、出したい情報を自由に設定出来る。
httpd.confにて設定出来る。

```apache
<VirtualHost *>
  ServerName hoge.fuga.ar
  LogLevel notice
  ErrorLog  "|/usr/local/sbin/cronolog /apache/logs/project_name/error_projectname_log.%Y-%m-%d"
  LogFormat "%h - - %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined
  CustomLog "/apache/logs/project_name/access_projectname_log.%Y-%m-%d" combined
<!-- 以下省略 -->
```

## エラーログ

```apache
  ErrorLog  "|/usr/local/sbin/cronolog /apache/logs/project_name/error_projectname_log.%Y-%m-%d"
```

エラーログの設定で必要になる[ディレクティブ](http://www.javadrive.jp/servlet/jsp_directive/index1.html)は、「ErrorLog」と「LogLevel」の2つ.

- ErrorLogディレクティブはログファイルの位置と名称を指定
- LogLevelディレクティブは記録するログのレベルを指定

|レベル|記録される内容|
|:--------:|:--------:|
|emerg|動作不能な状況、Emergency|
|alert|修正しなければ（部分的に）動作できない問題|
|crit|上記に該当しない動作上の問題、Critical|
|error|存在しないファイルへのアクセスなど各種エラー|
|warn|設定のミスなどが考えられる場合、警告、Warning|
|notice|起動停止や設定変更された場合など|
|info|あらゆる情報（プロセスの起動や停止など）|
|debug|Apache関連のデバッグに必要な情報|

```apache
LogLevel notice
```

と指定すると、noticeから上、emerg〜noticeの情報が記録される。
一般的には以下な感じで指定されるらしい。私は常に warn だった。
- 運用状態のサーバーでは **notice** か **warn** 
- テスト状態であれば、 **info** か **debug**

↑のErrorLogの指定では、日単位でログをファイルを作って[Logrotation](http://www.adminweb.jp/apache/log/index6.html)している。

```apache
ErrorLog syslog
```

また↑の様に、Linuxの機能を使って、syslogに出すことも出来る

## アクセスログ

### 書き方

```apache
LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common
```

LogFormatとCustomLogディレクティブの2つのディレクティブを設定する。
- LogFormatで、記録する書式とその書式の名前を設定

```apache
LogFormat "%t" time
```

=> **書式の名前が「time」で、記録するのはアクセス時刻「%t」** 


- CustomLogでこの書式のログを記録するファイルを指定

```apache
CustomLog /usr/local/apache/logs/time_log time
```

=> **『書式名「time」のログを「time_log」というファイル名で記録する』**

### 値の意味

| 設定値 | 意味 |
|:-----------:|:------------:|
|%a|アクセス元のIPアドレス|
|%A|サーバ(Apache)のIPアドレス|
|%B|送信されたバイト数、データ転送量(ヘッダーは含まず)|
|%b|送信されたバイト数、データ転送量(ヘッダーは含まず)。0バイトの時は「-｣|
|%f|リクエストされたファイル名|
|%h|リモートホスト名|
|%H|リクエストのプロトコル名|
|%l|クライアントの識別子|
|%m|リクエストのメソッド名|
|%q|リクエストに含まれるクエリー文字列。空白以外は「?」が付く。|
|%r|リクエストの最初の行の値|
|%s|レスポンスステータス|
|%>S|最後のレスポンスのステータス|
|%t|時刻|
|%T|処理にかかった時間|
|%u|認証ユーザー名|
|%U|リクエストのURLパス|
|%v|リクエストに対するバーチャルホスト名|
|%V|UseCanonicalNameによるサーバ名|
|%X|接続ステータス|
|%{クッキー名}C|リクエストに含まれるクッキーの値|
|%{環境変数名}e|環境変数名の値|
|%{ヘッダー名}i|リクエストに含まれるヘッダー名の値|
|%{ヘッダー名}o|レスポンスに含まれるヘッダー名の値|
|%{メモ}n	|モジュールから渡されるメモの値|
|%{フォーマット}t|フォーマットされた時刻|

* %>Sのように、>が%とアルファベットの間に入ると、内部リダイレクトされた後の、最終結果が出力される 

* {}で囲まれた項目について
 * 「%{ヘッダー名}i」 :  ヘッダーからヘッダー名に指定した値だけを取り出して記録。
 * =>「%{User-Agent}i」: と記述した場合にはヘッダーの中の「User-Agent」の値を保存。


### 条件付け

```apache
SetEnvIf Request_URI \.pdf$ pdf-files
```

↑これは、 **『リクエストのURIにpdfという拡張子が含まれている場合に環境変数pdf-filesを設定』** を意味していて、 **PDFへアクセスしたログだけが取れる** ようです。

```apache
CustomLog /usr/local/apache/logs/outer_log common env!=internal
```

↑これは、社内外のアクセスを分ける際に利用できる書き方。環境変数で条件分けをしているということです。

### 代表的な書き方

```apache
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
```

↑httpd.confの中に記載されている例

### 参考

[本家サイト Apacheログのモジュールについて](http://httpd.apache.org/docs/2.2/mod/mod_log_config.html)
[本家サイト Apacheログ概要](http://httpd.apache.org/docs/2.2/ja/logs.html)
[日本語サイト ApacheLogFormatの説明](http://www.adminweb.jp/apache/log/index2.html)
[Apacheのログ概要](http://www.atmarkit.co.jp/ait/articles/0202/16/news001.html)