Google App EngineのアクセスログをAWStatsで集計するまで

Jpostalの公開サーバ、jpostal-1006.appspot.comのアクセスログをAWStatsで集計しました。App Engine特有のawstas.conf設定やアクセスログ整形について説明します。

アクセスログ集計解析ソフトとは

アクセスログ集計解析ソフトって何?

アクセスログ集計解析ソフトとは、「月、日、曜日、ページ別、OS別、ブラウザ別」に、「訪問者数、htmlページだけのアクセス数、画像やcssを含む全アクセス数、転送量」を集計して、表やグラフで表示します。

AWStats、analog、webalizerの3つが有名ね

Google Analyticsとは何が違うのかな?

Google Analyticsはブラウザ側アクセスを集計します。Cookieで訪問者を追跡するので、訪問者数が正確です。

アクセスログ集計解析ソフトは、サーバ側アクセスを集計します。アクセス元IPアドレスで訪問者を追跡します。すると、数日後に再訪したとき、IPアドレスが変わっていると、新たな訪問者としてカウントされます。

Google Analyticsを仕込んでいないときや、仕込めないときも、アクセスログを集計します。

また、アクセスログを集計しないと、クローラやボットからのアクセスがわからないことも多いです。

AWStatsとは

AWStats - Open Source Log File Analyzer for advanced statistics (GNU GPL)
AWStats Official Web Site - Compile and generate advanced graphical web, ftp or mail statistics with a logfile analysis ...

AWStats(エーダブリュースタッツ)の名前の由来は、Advanced Web Statisticsです。Perlで開発されているので、Windows、Mac OS X、Linuxで同じzipパッケージを使えます。

AWStatsは、2つの処理と3つのファイルに注目すると、仕組みを理解しやすいです。

集計処理は、cronやJenkinsで定期処理するよ

設定ファイル(awstats.conf)、アクセスログ

集計処理

月別の集計結果ファイル

表示処理は、ブラウザで、/cgi-bin/awstats.plにアクセスしたときね

月別の集計結果ファイル

表示処理

webブラウザ

ファイル説明
awstats.conf設定ファイル
access_logアクセスログ
awstats042020.txt月別の集計結果

ディレクトリ構成

今回のディレクトリ構成です。awstats本体は、別の場所、Dockerコンテナ内にあります。

$ tree -L 2
.
├── awstats
│   ├── awstats.conf
│   ├── logs/
│   └── results/
└── jpostal_log.docker
     └── docker-compose.yml

DockerHub

https://hub.docker.com/r/pabra/awstats

AWStatsをインストール済みのDockerイメージを使います。

docker-compose.yml

version: '2'

services:
  web:
    tty: true
    container_name: awstats.jpostal_log.docker
    image: pabra/awstats
    ports:
      - 3000:80
    volumes:
      - ../awstats/logs:/var/local/log:ro
      - ../awstats/results:/var/lib/awstats
    environment:
      - TZ:"Asia/Tokyo"
    restart: always
Code language: YAML (yaml)

container_name
好みに編集してください。このままでもいいです。

ports
好みに編集してください。このままでもいいです。

restart: always
次回、PC起動時に、このDockerコンテナも自動起動します。

volumes
アクセスログをホスト側の ../awstats/logs/* の位置に保存すると、Dockerコンテナからは、/var/local/log/* の位置に見えます。
集計結果ファイルは、Dockerコンテナは、/va/lib/awstats/* の位置に保存します。ホスト側からは ../awstats/results/* の位置に見えます。

Docker内ホスト側説明
/var/local/log/*../awstats/logs/*アクセスログ
/var/lib/awstats/*../awstats/results/*結果ファイル

docker-composeで起動してください。

$ cd jpostal_log.docker
$ sudo docker-compose up -dCode language: Bash (bash)

webブラウザでhttp://localhost:3000 にアクセスすると、AWStatsの画面が表示されるはずです。

まだ集計していないから、アクセス数はゼロで表示されるよ

awstats.conf

編集するために、Dockerコンテナのawstats.confを取り出します。Dockerコンテナ内の/etc/awstats/awstats.conf にあるので、ホストから見える位置 /var/lib/awstats/ にコピーします。

$ container_name=awstats.jpostal_log.docker
$ sudo docker exec $container_name cp  /etc/awstats/awstats.conf  /var/lib/awstats/Code language: Bash (bash)

ホストでは awstats/results/ の位置に見えます。書き込み権限がないので、chmod か chown してください。

$ sudo chmod a+w ../awstats/results/awstats.confCode language: Bash (bash)

awstats.confの設定項目は多いから、めまいがしそうだよ。

ほとんどの項目はそのままよ。

SiteDomain

AWStats画面の左上のサイト名に反映されます。

156行目付近です。

SiteDomain="jpostal-1006.appspot.com"Code language: Bash (bash)

TimeZone

アクセスログの日時に「-0700」とある場合、アクセスログのタイムゾーンは -7 です。

これを日本時間の +9 で表示したいんですね。

そこで、-7 と +9 の差、+16 を設定します。

1408行目付近です。先頭に "#" があったら削除してください。

LoadPlugin="timezone +16"Code language: Bash (bash)

ValidHTTPCodes

デフォルトでは、status codeが200、304だけが集計対象です。

200は、正常なレスポンス

304は、If-Modified-Sinceでリクエストされたけど、コンテンツは更新されていないときだね。ブラウザはブラウザ内キャッシュから表示したんだね。

これで集計したところ、全リクエストの約75%がstatus code 204で、集計対象から除外されていました。

204は、No Contentってあるけど、304と同じ?

似ているけど、違うわ。
204は、エッジキャッシュから配信されたのね。

http://google-app-engine.75637.x6.nabble.com/http-204-status-on-static-files-td3587.html

ここでは、エッジキャッシュを含めたアクセス数を集計したいので、204も集計対象に含めることにします。

617行目付近のValidHTTPCodesを編集します。

ValidHTTPCodes="200 204 304"Code language: Bash (bash)

NotPageList

Jpostalはjsとjsonしかないので、PVとして集計されません。そこで、NotPageListから js を除外しました。

601行目付近のNotPageListを編集します。

NotPageList="css class gif jpg jpeg png bmp ico rss xml swf eot woff woff2"Code language: Bash (bash)

awstats.confをDockerコンテナにコピーするのを忘れないでね

この状態の awstats.conf を Dockerコンテナの /etc/awstats/ へコピーします。Dockerコンテナが再起動すると、/etc/awstats/awstats.conf は初期状態に戻ってしまうので、再起動したらコピーしてください。

$ sudo docker exec awstats.jpostal_log.docker cp  /var/lib/awstats/awstats.conf  /etc/awstats/Code language: Bash (bash)

アクセスログの整形

この状態で集計してみました。

$ container_name=awstats.jpostal_log.docker
$ logfile=/var/local/log/2020-04-07-01-15-49.log

$ sudo docker exec $container_name /usr/lib/awstats/cgi-bin/awstats.pl -update -config=default -LogFile="$logfile"

Create/Update database for config "/etc/awstats/awstats.conf" by AWStats version 7.7 (build 20180105)
From data in log file "/var/local/log/2020-04-07-01-15-49.log"...
Phase 1 : First bypass old records, searching new record...
Direct access to last remembered record is out of file.
So searching it from beginning of log file...
Phase 2 : Now process new records (Flush history on disk after 20000 hosts)...
Jumped lines in file: 0
Parsed lines in file: 354231
 Found 0 dropped records,
 Found 0 comments,
 Found 0 blank records,
 Found 319026 corrupted records,
 Found 0 old records,
 Found 35205 new qualified records.Code language: Bash (bash)

corrupted recordsが31万もあるけど、なんだろう?

35万行のうち、新規追加されたのは3万行だけです。31万行は「corrupted records」となってしまいました。全体の90%です。

「corrupted records」とは、awstats.confのLogFormatでパースできなかった不正な行です。LogFormatは、いわゆるCombined Log Formatです。

LogFormat="%host %other %logname %time1 %methodurl %code %bytesd %refererquot %uaquot"Code language: Bash (bash)

どんなサーバのログでも1%ぐらいは「corrupted records」になるそうですが、90%は多すぎます。

アクセスログを調べてみると、リファラーがあるときは「"https://www.google.com"」のようにダブルクォート囲みでした。リファラーがないときはダブルクォートのない「-」でした。

試しに数行のアクセスログを作り、リファラーを「"-"」に編集しました。集計してみると、その行は集計されて「new qualified records.」にカウントされました。

つまり、AWStatsのLogFormatの%refererquotは、「"-"」を想定していて、「-」は不正扱いするようです。

App Engineのアクセスログの書式がおかしいってこと?

それともAWStatsのバグ?

どちらも考えにくいわ。
でもそれらしいawstatasの設定オプションは見つからないし、
9割のリクエストを集計できるような、いい方法はないかしら

集計前に、アクセスログのリファラーの「-」を「"-"」に置換してしまいましょう。

ここでは、sedコマンドを使いました。

adjust_logformat.sh

#!/bin/bash -uex
# HTTP/1.1" 204 6430 - "Mozil...
# HTTP/1.1" 204 6430 "-" "Mozil...

src=$1
dst=$2

cat  $src \
  | sed -e "s/\(HTTP\/[0-9]\+[.][0-9]\+\" [0-9]\+ [0-9]\+\) - /\1 \"-\" /g" \
  >$dst
Code language: Bash (bash)

次のように使います。

$ ./adjust_logformat.sh  awstats/logs/2020-04-07-01-15-49.log  awstats/logs/2020-04-07-01-15-49.log.tmpCode language: Bash (bash)

集計処理

awstats/results/awstats*.txt を削除して、集計しなおします。

$ container_name=awstats.jpostal_log.docker
$ logfile=/var/local/log/2020-04-07-01-15-49.log.tmp

$ cd jpostal_log.docker
$ sudo docker exec $container_name /usr/lib/awstats/cgi-bin/awstats.pl -update -config=default -LogFile="$logfile"

Create/Update database for config "/etc/awstats/awstats.conf" by AWStats version 7.7 (build 20180105)
From data in log file "/var/local/log/2020-04-07-01-15-49.log.tmp"...
Phase 1 : First bypass old records, searching new record...
Searching new records from beginning of log file...
Phase 2 : Now process new records (Flush history on disk after 20000 hosts)...
Flush history file on disk (unique hosts reach flush limit of 20000)
Jumped lines in file: 0
Parsed lines in file: 354231
 Found 0 dropped records,
 Found 0 comments,
 Found 0 blank records,
 Found 234 corrupted records,
 Found 0 old records,
 Found 353997 new qualified records.
Code language: JavaScript (javascript)

ほぼ全ての行を集計できました。まだ234行が不正な書式で集計できませんでしたが、これぐらいは許容範囲とします。

集計済みのログファイルは削除していいのかな?

何回でもやり直せるから、とっておいたほうがいいわよ。
gzipで圧縮して、アーカイブ用のディレクトリに移動しておいて。

タイトルとURLをコピーしました