[Fastly] backendのhealth状態(req.backend.healthy)を監視する方法 (version 2, 全POPでのhealth状態取得)

### 前回までのあらすじ
少し前になりますが、下記のような記事を書きました。

- [[Fastly] 登録されている各backendのhealth状態(req.backend.healthy)を監視する方法](https://qiita.com/jrsyo/items/fbc2e5d0d195e8bea182)

上記方法の問題は、リクエストを発行したclientに最も近いPOPのhealth状態しか取得できないことでした。
では全拠点POPでのbackendのhealth状態をまとめて取得・監視する方法は無いのでしょうか？

## Fastlyの `/content/edge_check` APIを使う
Fastlyには色んなAPIがありますが、あまり知られていないAPIの1つに、`/content/edge_check` があります。

- [Fastly API | Content](https://docs.fastly.com/api/tools#content)

これは、Fastlyの管理画面でも使える `Check cache` と同じですが、APIの方が確認できる情報量が少し多いです。
<img width="1589" alt="Screen Shot 2018-02-21 at 17.15.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/19942/a638512d-12c2-9c9d-8322-bcbd2e9fa535.png">


このAPIが何をしてくれるかと言うと、通常は引数にURLを渡すことで全てのPOPに対してそのURLがキャッシュされているかどうかをチェックし、その結果をJSONで返してくれます。

例えば、APIの出力は下記のようになります。下記はサンプルなので1POP分だけの出力を切り取っていますが、POPの数だけこれが続きます。

```json
[
  {
    "hash": "a6fa75cf5b77f61527421aaaa4ddcd50",
    "pop": "fjr-ae",
    "response_time": 0.399193,
    "server": "cache-fjr7922",
    "request": {
      "headers": {
        "User-Agent": "Fastly/cache-check",
        "Fastly-Debug": 1,
        "Host": "<name>.global.ssl.fastly.net"
      },
      "method": null,
      "url": null
    },
    "response": {
      "headers": {
        "Server": "Varnish",
        "Retry-After": "0",
        "Content-Length": "191",
        "Content-Type": "application/json",
        "Accept-Ranges": "bytes",
        "Date": "Wed, 21 Feb 2018 07:51:53 GMT",
        "Via": "1.1 varnish",
        "Connection": "close",
        "Fastly-Debug-Path": "(D cache-fjr7922-FJR 1519199513)",
        "Fastly-Debug-TTL": "(M cache-fjr7922-FJR - - -)",
        "Fastly-Debug-Digest": "96be48cccb522690d0b6bb55e427bf366e7160213ef4c953ae240b66d1a5d100",
        "X-Served-By": "cache-fjr7922-FJR",
        "X-Cache": "MISS",
        "X-Cache-Hits": "0"
      },
      "status": 200
    }
  },
  
  #↑の配列がPOPの数だけこの後に続きます。
```

ポイントは、このAPIで確認できるのはそのURLにリクエストを投げた時の`レスポンスヘッダ`と`ステータスコード`だけで、bodyの内容は確認できないということです。
つまり、前回作った`synthetic`レスポンスによるJSONはこれでは確認できません。

### `synthetic`レスポンスを工夫する

ではどうするか、おそらく一番簡単なのは、JSONにも出力していた`req.backend.healthy` をレスポンスヘッダに含める方法です。そうすることで、このAPIのレスポンスヘッダに`health`状態を出力させることができます。

前回の記事を前提にお話すると、`vcl_error`のコードに1行だけ付け加えればOKです。`vcl_recv`のコードは前回のままで問題ありません。

- `vcl_error`

```c
if (obj.status == 610) {
  synthetic "{" LF
      {"  "timestamp": ""} now {"","} LF
      {"  "req.backend": ""} req.backend {"","} LF
      {"  "req.backend.healthy": "} req.backend.healthy LF
      "}"
  ;
  set obj.status = 200;
  set obj.response = "OK";

  # ヘッダにbodyへのJSON同様に `req.backend.healthy` を出力する
  set obj.http.X-Backend-Healthy = req.backend.healthy;
  set obj.http.Content-Type = "application/json";
  return (deliver);
}
```

### APIへリクエストを投げる

`${hostname}`: Fastlyのサービスに登録しているドメイン
`${backend_name}`: backend名
`${your_fastly_token}`: API token

```bash
$ curl https://api.fastly.com/content/edge_check?url=${hostname}/api/status?backend=${backend_name} -H 'Fastly-Key: ${your_fastly_token}'
```

これを叩くとJSONがババーっと返ってくると思います。

```json
[
  {
    "hash": "a6fa75cf5b77f61527421aaaa4ddcd50",
    "pop": "fjr-ae",
    "response_time": 0.399193,
    "server": "cache-fjr7922",
    "request": {
      "headers": {
        "User-Agent": "Fastly/cache-check",
        "Fastly-Debug": 1,
        "Host": "<name>.global.ssl.fastly.net"
      },
      "method": null,
      "url": null
    },
    "response": {
      "headers": {
        "Server": "Varnish",
        "Retry-After": "0",
        "Content-Length": "191",
        #↓これ↓
        "X-Backend-Healthy": "1",
        "Content-Type": "application/json",
        "Accept-Ranges": "bytes",
        "Date": "Wed, 21 Feb 2018 07:51:53 GMT",
        "Via": "1.1 varnish",
        "Connection": "close",
        "Fastly-Debug-Path": "(D cache-fjr7922-FJR 1519199513)",
        "Fastly-Debug-TTL": "(M cache-fjr7922-FJR - - -)",
        "Fastly-Debug-Digest": "96be48cccb522690d0b6bb55e427bf366e7160213ef4c953ae240b66d1a5d100",
        "X-Served-By": "cache-fjr7922-FJR",
        "X-Cache": "MISS",
        "X-Cache-Hits": "0"
      },
      "status": 200
    }
  },
  
  #↑の配列がPOPの数だけこの後に続きます。
```

出力は上記のようになるはずです。
`"X-Backend-Healthy": "1",` という部分が今回追加したレスポンスヘッダです。0=unhealthy, 1=healthy です。

これを頑張ってパースしてPOPごとのヘッダに切り分ければ、各POPでのbackendのhealth状態をこのAPIによって取得することができます。