Fastlyを使ってオリジンレスでログを収集する

# この記事の内容について

FastlyのBlogポスト [Beacon termination at the edge](https://www.fastly.com/blog/beacon-termination-edge/) で紹介されているように、Fastlyの特徴のひとつであるリアルタイムログストリーミング機能を利用して、たくさんの端末からのログを収集するためのプラットフォームとしてFastlyを利用することが出来ます。

この記事では、オリジンレスでログを収集するための設定を作成する手順をご紹介します。

```
特に記載がない限り本記事の記載内容はデフォルト設定での挙動となります。
```

作業のおおまかな流れとしては以下のようになります。
Step 1: サービスの作成
Step 2: ログ配信設定の作成
Step 3: カスタムレスポンスの作成
Step 4: サービスの有効化

それでは順番に手順を確認して見ましょう。

## Step 1: サービスの作成
Fastlyのコントロールパネル( https://manage.fastly.com/ )にログインし、**Configure**タブを選択し、**CREATE SERVICE**をクリックして下さい。

![Fastly: Configure (demo.a24fkd.com) 2017-04-14 12-22-40.png](https://qiita-image-store.s3.amazonaws.com/0/128569/7bc82ef3-7f01-d149-aab4-ebe95dd3409f.png)

### Domain, Origin(backend)の設定
CREATE SERVICEをクリックすると以下のような画面が表示されます。
![Fastly: Configure 2017-11-27 15-22-27.png](https://qiita-image-store.s3.amazonaws.com/0/128569/41c9476c-e093-3c11-ac5f-c46b6908661b.png)

**Name**: このサービスの名称になります。サービスを識別可能な名前を英数字で入力して下さい
**Domain**: ログの送付先となるドメインを入力して下さい
**Address**: backend(いわゆるオリジンサーバー)のドメイン、またはIPアドレスを入力します。完全にログ収集が目的のサービスで、すべてのリクエストにFastlyが生成するレスポンスを返却する場合はアクセスが出来ないダミーの情報でも構いません。
**Enable TLS**: オリジンとの接続でTLSを利用するかどうかを指定します。サンプルの設定ではダミーのオリジンで、実際にオリジンとの通信は発生しませんので**No**で問題ありません。

**Create** ボタンをクリックするとサービスの作成が完了します。


## Step 2: ログ配信設定の作成
正しくサービスが作成されると、以下のようにVersion.1が表示されているはずです。このバージョンはすでにActiveで編集が出来ないようにLockされているので、Cloneして編集可能なバージョンを作成します。

![Fastly: Configure (Log aggregation service) 2017-11-27 15-31-54.png](https://qiita-image-store.s3.amazonaws.com/0/128569/2ff846e6-3784-bf15-8b07-6a770069d6ec.png)

Cloneするには画面右上の**Configuration**をクリックして、表示されるメニューから**Clone active**を選択して下さい。

サービスのVersion.2が生成されます。ログの配信設定を作成するためには左側のメニューから**Logging**をクリックして下さい。以下のような画面が表示されます。

![Fastly: Configure (Log aggregation service) 2017-11-27 15-35-20.png](https://qiita-image-store.s3.amazonaws.com/0/128569/3acbb41c-d2a1-1dec-8c7f-93e70ee82fc1.png)
*ダミーのオリジン情報を登録している場合、警告メッセージが表示されますが問題ありません*

表示されたログのエンドポイントの中から、ログを送信したいエンドポイントを選択してログの配信設定を作成して下さい。
ログエンドポイントはどこでも構いませんが、送信するログの数に耐えうるエンドポイントである必要があります。ログのエンドポイントでも受け付けたトラフィックに応じて課金が発生するものもあるので注意して下さい。

具体的な設定手順は[リモートログストリーミングの設定](https://docs.fastly.com/ja/guides/streaming-logs/setting-up-remote-log-streaming)や、Qiita内にもFastlyのログ設定に関する記事がありますのでそちらを参照にして下さい。

ログを取得する条件やログフォーマットも自由に設定可能です。必要に応じてログフォーマットを変更して下さい。
ログビーコンの収集目的であれば、POST BODYやクエリストリング、リクエストヘッダなどを取得したいケースが多いかと思いますが、それらの情報をログに追加したい場合は**Log format** に以下のような内容をを追加することで取得することが出来ます。

指定したリクエストヘッダの値: `%{req.http.X_special}V` <- この場合は X_specialヘッダーの値を取得します
ポストボディの内容: `%{req.postbody}V`
クエリストリング全体: `%{req.url.qs}V`
指定したクエリストリングのValue: `%{if(req.url.qs ~ "^.*key=([^&]*)", re.group.1, "none")}V` <- この場合は keyパラメータのValueのみを取得します
指定したクエリストリングのKeyとValue: `%{if(req.url.qs ~ "^.*(key=[^&]*)", re.group.1, "none")}V` <- この場合は keyパラメータとValueを取得します


## Step 3: カスタムレスポンスの作成

続いて、リクエストを受信時にクライアントに返却するカスタムレスポンスを作成します。

左側のメニューから**Content**を選択し、**Create Your First Response**をクリックして下さい。

![Fastly: Configure (Log aggregation service) 2017-11-27 16-10-04.png](https://qiita-image-store.s3.amazonaws.com/0/128569/2f971f8c-ba11-d871-aabe-ccb9f2361125.png)

以下の**Create a synthetic response**画面が表示されます。
![Fastly: Configure (Log aggregation service) 2017-11-27 16-11-22.png](https://qiita-image-store.s3.amazonaws.com/0/128569/102729ff-2589-460c-5ed0-d49372e2d8f9.png)
**Name**: この設定の名称です。適当な名前を入力して下さい。
**Status**: 返却するレスポンスステータスです。ここでは「204 No Content」を選択します。
MIME Type, Response は通常空欄でも問題ありません。

上記の内容で**Create**をクリックして下さい。


## Step 4: サービスの有効化

![Fastly: Configure (Log aggregation service) 2017-11-27 16-19-47.png](https://qiita-image-store.s3.amazonaws.com/0/128569/51b8a825-2c25-453d-e32e-5cf38e0315ce.png)

上記の設定が完了したら、画面右上の**Activate**ボタンをクリックして下さい。

この設定の挙動を改めて簡単に説明すると
・すべてのリクエストに無条件で「204 No Content」 レスポンスを返却します。
・すべてのリクエストに対して、指定したログエンドポイントに指定した内容を含むログを送信します。
・オリジンサーバーへのアクセスは発生しないので、オリジンサーバーはダミーでも問題ありません。

## 動作確認と注意事項
それでは以下のLog formatでログを取得した場合の結果を確認してみたいと思います。以下のcURLコマンドはクエリストリング付きのPOSTリクエストをドメインに対して送っています。

```
curl -svo /dev/null "http://log.xxxxxx.com?aaa=bbb&key=query_value&ccc=ddd" -H "X_special:header_value" -d '{"key":"post_value"}'
> POST /?aaa=bbb&key=query_value&ccc=ddd HTTP/1.1
> Host: log.xxxxxx.com
> User-Agent: curl/7.52.1
> X_special:header_value

< HTTP/1.1 204 No Content
```

正しく204 No Content レスポンスが返却されています。

それでは、このサービスのログフォーマットと、リクエストで発生したログを確認してみます。


```ruby:ログフォーマット
%h %l %u %t "%r" %>s %b %{req.postbody}V %{req.url.qs}V %{req.http.X_special}V %{if(req.url.qs ~ "^.*key=([^&]*)", re.group.1, "none")}V %{if(req.url.qs ~ "^.*(key=[^&]*)", re.group.1, "none2")}V
```

```ruby:出力されたログ
122.208.204.58 "-" "-" [27/Nov/2017:10:11:22 +0000] "POST /?aaa=bbb&key=query_value&ccc=ddd HTTP/1.1" 204 "-" {"key":"post_value"} aaa=bbb&key=query_value&ccc=ddd header_value query_value  key=query_value
```


ログフォーマットではクエリストリングとPOST BODYをログに含めるように設定されています。出力されたログでは指定したデータが正しく取得されていることが確認できます。

このようにFastlyのログストリーミング機能、カスタムレスポンス機能を活用することで、簡単にオリジンレスでログの収集プラットフォームを作成することが出来ます。
ログの送り先はBigQueryでもGCSでもS3でもどこでも大丈夫です。使い慣れた分析プラットフォームに直接送信することが可能です。

CDNというと、名前の通りコンテンツ配信のためのプラットフォームというイメージがあると思いますが、Fastlyではアイデア次第でこのように通常のCDNとは異なるユースケースにも利用することが出来ます。


## 注意事項
Fastlyのログ取得目的で利用する場合は、以下のような点に注意して下さい。

* Fastly側ではお客様のログをディスクなどに保存はしていません。そのため、ログの受取先のサービスやネットワークの問題などでログの配信に失敗した場合も、Fastly側から失われたログを再送することは出来ません。
* Fastly でログに記録可能なPOST BODYのサイズは最大2KB となっています。2KBを超えるPOST BODYはログに記録されません。


なお、少量のトラフィックに対して大量のリクエストが突然発生すると、Fastly ネットワークチームに DDoS トラフィックと誤認識される恐れがあります。本記事でご紹介したログの収集目的のような実装を大規模なトラフィックが想定されるプロダクション環境に実装される場合、念のため事前に japan@fastly.com までご連絡下さい。