これは ドリコム Advent Calendar 2019の5日目です。
4日目は よもぎ さんによる、( ᐛ )デザイナー運用大反省会 です。

こんにちは。
ドリコムでエンジニアをしているhataです。本ブログの運営なんかもお手伝いさせていただいてます。
今回は、本ブログのKPIを測るために行なったことについて執筆させていただきます。

はじめに

本記事は、アクセスログを利用しサイトPV数を取得するまでのhow to記事となります。
同じことをしようとしてる方々の参考になれば良いなと思い、書き残しています。

なぜ自前?

我々は今まで、本ブログのPV取得にWordPressのプラグインや無料のwebサイト分析ツールを利用してきました。
これらのツールはある期間のPVを測る上で何の問題もありませんでした。

しかしある日、「このブログを見ている人のうち、社内の人はどれくらいいるのだろう」ということを思い調べようとしましたが、当時利用していたツールでは取得ができなかったり、明らかにおかしな値が出たりしていました。

これはもどかしい。
データがあるはずなのに取得できないことに悲しみを感じました。

そこで、今後このような柔軟な調査が可能にするべく、自前で作ってしまおうとやっちゃいました。


以下、詳細になります。

登場人物

  • Nginx
  • td-agent
  • AWS S3
  • AWS Athena

最終目標

社内の人がどれくらい本ブログの閲覧されているか確認すること
(Athenaで調べたい情報をクエリで投げれる環境ができること)

やったこと

  1. Nginxのログフォーマット変更
  2. AWS S3のバケット作成
  3. td-agent導入と設定更新
  4. AWS Athenaのセッティング
  5. 目標のクエリ文を実行

1. Nginxのログフォーマット変更

出力ログの形式を/etc/nginx/conf.d/format.combined2.confに記述し読み込むように反映する。
今回は json 形式が扱いやすかったので取得したい情報を json で記述。

# サーバーに接続
ssh xxx.xxx.xx.xxx

# 出力したい形に編集
vi /etc/nginx/conf.d/format.combined2.conf

# format.combined2.confの中
# $request_time prefixed version of `combined` format
log_format combined2 '{"request_time": "$request_time",'
  '"remote_addr": "$remote_addr",'
  '"remote_user": "$remote_user",'
  '"time_local": "$time_local",'
  '"request": "$request",'
  '"status": "$status",'
  '"body_bytes_sent": "$body_bytes_sent",'
  '"http_referer": "$http_referer",'
  '"http_user_agent": "$http_user_agent",'
  '"uri": "$request_uri",'
  '"http_x_forwarded_for": "$http_x_forwarded_for"}';


# 設定したフォーマットを読み込むように
vi /etc/nginx/nginx.conf

# /etc/nginx/nginx.confの中
include /etc/nginx/global.conf;

http {
    server_tokens off;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;

    # この行を追加
    access_log /var/log/nginx/access.log combined2;
}

# 設定の反映
/etc/init.d/nginx configtest
/etc/init.d/nginx restart

2. AWS S3のバケット作成

名前を決め、リージョンを最寄りのものにし、あとはデフォルトで作成。
外部からアクセスするための credentials.csv をダウンロードし保存しておくことを忘れずに。
詳しくはこちら

3. td-agent導入と設定更新

2. で立てた S3 のバケットにログを送信する。

# サーバーに接続
ssh xxx.xxx.xx.xxx

# td-agent導入
yum install td-agent -y

# どのログをどこに送信するか記述
vim /etc/td-agent/td-agent.conf

# /etc/td-agent/td-agent.confの中
## File input
## read apache logs continuously and tags td.apache.access
<source>
  type tail
  format json
  path /var/log/nginx/access.log
  tag s3.nginx.access
</source>
## File output
# S3
<match s3.*.*>
  type s3
  format json
  aws_key_id XXXXXXXXXXXXXXXX # credential.csv参照
  aws_sec_key XXXXXXXXXXXXXXXX # credential.csv参照
  s3_bucket tid-xxx-01 # 設定したbucket名
  s3_region ap-northeast-1 # 設定したリージョン
  time_slice_format %Y%m%d%H%M
  path tid/nginx/access/ # バケットの出力先ディレクトリ
  buffer_path /var/log/td-agent/buffer/s3
  time_slice_wait 20s
</match>

# 設定の反映
/etc/init.d/td-agent configtest
/etc/init.d/td-agent restart

4. AWS Athenaのセッティング

Athena からどの S3 バケットに対してクエリを投げるのかを定義する。
Athena のクエリ入力部に以下を入力し実行。

# 接続するdatabaseをつくる
CREATE EXTERNAL TABLE IF NOT EXISTS tid_prod.access_logs (
  `request_time` string,
  `remote_addr` string,
  `remote_user` string,
  `time_local` string,
  `request` string,
  `status` string,
  `body_bytes_sent` string,
  `http_referer` string,
  `http_user_agent` string,
  `uri` string,
  `http_x_forwarded_for` string
)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
WITH SERDEPROPERTIES (
  'serialization.format' = '1'
) LOCATION 's3://xxxxxxxxxx/tid/nginx/access/'
TBLPROPERTIES ('has_encrypted_data'='false');

5. 目標のクエリ文を実行

特定記事に対するアクセス数を Athena でクエリ文を実行し確認する。

# 社内からのアクセス
SELECT count(*) FROM access_logs WHERE (uri = '/new-business-development/') AND (status = '200') AND (http_x_forwarded_for = 'xxx.xxx.xx.xxx');

# 社外からのアクセス
SELECT count(*) FROM access_logs WHERE (uri = '/new-business-development/') AND (status = '200') AND NOT (http_x_forwarded_for = 'xxx.xxx.xx.xxx');

とれた!!

最後に

無事、目標達成をすることができました。
本記事がどなたかのお役に立てることができれば大変嬉しく思います。

明日は 髙寺昂大 さんの記事です。

ドリコムでは一緒に働くメンバーを募集しています! 募集一覧はコチラを御覧ください!