Zabbix 4.0でlivedoor 天気情報を取得してダッシュボードに表示する

## はじめに

(2020/08/17 追記)
livedoor 天気情報のAPIが終了してしまったため、別手段で同等の監視を行う [Zabbix 5.0でYahoo!天気の天気情報を取得してダッシュボードに表示する](https://qiita.com/mandoi/items/f8df51af0e7207e687c6) を書きました。
(2020/08/17 追記ここまで)

Webページのデータを監視しようとすると、以前のバージョンのZabbixでは外部スクリプトで色々頑張る必要がありましたが、Zabbix 4.0では監視タイプに「HTTPエージェント」が追加され、指定したURLからレスポンスを直接監視データとして受け取ることが可能になりました。

Zabbix 4.0の新機能「HTTPエージェント」とZabbix 3.4から追加されている機能「保存前処理」「依存アイテム」を組み合わせておこなったことを、メモとして残しておこうと思います。  
今回、監視しようとしたのは、**livedoor 天気情報**の[お天気Webサービス](http://weather.livedoor.com/weather_hacks/webservice)で提供される、特定の地域の天気と気温情報です。RESTで利用できるので、まさにHTTPエージェントタイプの監視アイテムで遊ぶのにはピッタリです。  
こういうことをしようと思うと、以前は外部スクリプトでcurlを呼び出してWebページを開いてから、さらにjqで加工してZabbixへ渡すなんていう面倒なことをしていたんですが、これをスマートに監視できるようになったのはありがたいですね。

## 環境情報

CentOS 7.6.1810 (x86_64) + Zabbix 4.0.5

## [準備] お天気Webサービスで取得したい地域のIDを調べる

まず、お天気Webサービスで取得したい地域のIDを確認しておきます。

地域のIDだけを一覧化した情報がないので、[RSSフィード一覧](http://weather.livedoor.com/weather_hacks/rss_feed_list)のリンク先URLからIDを調べるのが手っ取り早いようです。例えば**東京**を取り出す場合ですと、リンク先URLが`http://weather.livedoor.com/forecast/rss/area/130010.xml`なので、`130010`が東京を示すIDになります。

ここから先は、東京(地域のIDは`130010`)をサンプルに監視アイテムを作成していきます。

## [Zabbix] 監視設定をおこなう

### 監視ホストを作成

今回は地域のID単位でホストを作ることにします。以下のサンプルでは、IDをホスト名にして、表示名に区別しやすい別名をつけています。

| 設定項目 | 設定値 | 説明 |
|--:|:--|:--|
| ホスト名 | 130010 | 地域のIDを指定する |
| 表示名 | weather(東京) | 識別しやすい任意の表示名を指定する |
| グループ | xxxxx | 任意のグループを選択する |
| 有効 | ✔︎ | このホストを有効にする |

上記以外の設定は変更しません。

### 監視アイテムを作成

お天気WebサービスのRESTで返されるJSONは以下のような構造になっています。

```json
{
  "pinpointLocations": [
(snip)
  ],
  "link": "http://weather.livedoor.com/area/forecast/130010",
  "forecasts": [
    {
      "dateLabel": "今日",
      "telop": "曇り",
      "date": "2019-03-27",
      "temperature": {
        "min": null,
        "max": null
      },
      "image": {
        "width": 50,
        "url": "http://weather.livedoor.com/img/icon/8.gif",
        "title": "曇り",
        "height": 31
      }
    },
    {
      "dateLabel": "明日",
      "telop": "曇り",
      "date": "2019-03-28",
      "temperature": {
        "min": {
          "celsius": "12",
          "fahrenheit": "53.6"
        },
        "max": {
          "celsius": "18",
          "fahrenheit": "64.4"
        }
      },
      "image": {
        "width": 50,
        "url": "http://weather.livedoor.com/img/icon/8.gif",
        "title": "曇り",
        "height": 31
      }
    },
(snip)
  }
}
```

ここから必要なオブジェクト ーー 最低気温`.forecasts[].temprature.min`, 最高気温`.forecasts[].temprature.max`, 天気の画像`.forecasts[].image.url` ーー を取り出し、監視データとして保存します。この監視アイテムは、 **`.forecasts[]`を保存するための親アイテム** と **親アイテムから「最低気温」「最高気温」「天気の画像」に細分化して保存するための依存アイテム** を作るという方針とします。

以下のサンプルは「今日」の天気のアイテムですが、加えて「明日」や「明後日」のアイテムを作る場合は、それぞれ別のアイテムを作って、`.body.forecasts[]`配列から2番目又は3番目のオブジェクトを取り出す必要があります。

### アイテム(1) - 親アイテム

以下のアイテムを作り、今日の天気に関する要素をまとめて保存します。

| 設定項目 | 設定値 | 説明 |
|--:|:--|:--|
|名前|w_today|任意の名前を指定する|
|タイプ|HTTPエージェント||
|キー|w_today|任意のキー名を指定する|
|URL|http://weather.livedoor.com/forecast/webservice/json/v1|RESTのベースURLを指定する|
|クエリフィールド|名前⇒ city<br/>値⇒ {HOST.HOST} |名前はcityで固定<br/>値はホスト名を参照するマクロを使用する |
|JSONへの変換|✔︎||
|データ型|テキスト||
|監視間隔|4h|更新頻度が低いのであまり間隔を短くしても意味がない|
|ヒストリの保存期間|7d|とりあえず7日保存|
|アプリケーション|Weather|任意のアプリケーション名を指定もしくは作成する|
| 有効 | ✔︎ | このアイテムを有効にする |

不要な要素を取り除いて保存するため、「保存前処理」も設定します。

| 設定項目 | 名前 |パラメータ | 説明 |
|--:|:--|:--|:--|
|保存前処理の設定|JSON Path|$.body.forecasts[0] |「今日」は.body.forecasts[]の1番目のオブジェクトなので **0** にする<br/>「明日」の天気の場合は **1** 、「明後日」の場合は **2** にする|

### アイテム(2) - 最低気温

| 設定項目 | 設定値 | 説明 |
|--:|:--|:--|
|名前|w_today_min|任意の名前を指定する|
|タイプ|依存アイテム||
|キー|w_today_min|任意のキー名を指定する|
|マスターアイテム|w_today|(1)のアイテムを指定する|
|データ型|整数|整数値を返す<br/>ただし、時間帯によりnullを返し、アイテムのステータスは「取得不可」になる|
|ヒストリの保存期間|1d||
|トレンドの保存期間|7d||
|アプリケーション|Weather|任意のアプリケーション名を指定もしくは作成する|
| 有効 | ✔︎ | このアイテムを有効にする |

親アイテムから最低気温だけを保存するため、「保存前処理」も設定します。

| 設定項目 | 名前 |パラメータ | 説明 |
|--:|:--|:--|:--|
|保存前処理の設定|JSON Path|$.temperature.min.celsius ||

### アイテム(3) - 最高気温

| 設定項目 | 設定値 | 説明 |
|--:|:--|:--|
|名前|w_today_max|任意の名前を指定する|
|タイプ|依存アイテム||
|キー|w_today_max|任意のキー名を指定する|
|マスターアイテム|w_today|(1)のアイテムを指定する|
|データ型|整数|整数値を返す<br/>ただし、時間帯によりnullを返し、アイテムのステータスは「取得不可」になる|
|ヒストリの保存期間|1d||
|トレンドの保存期間|7d||
|アプリケーション|Weather|任意のアプリケーション名を指定もしくは作成する|
| 有効 | ✔︎ | このアイテムを有効にする |

親アイテムから最高気温だけを保存するため、「保存前処理」も設定します。

| 設定項目 | 名前 |パラメータ | 説明 |
|--:|:--|:--|:--|
|保存前処理の設定|JSON Path|$.temperature.max.celsius ||

### アイテム(4) - 天気の画像

| 設定項目 | 設定値 | 説明 |
|--:|:--|:--|
|名前|w_today_image|任意の名前を指定する|
|タイプ|依存アイテム||
|キー|w_today_image|任意のキー名を指定する|
|マスターアイテム|w_today|(1)のアイテムを指定する|
|データ型|テキスト||
|ヒストリの保存期間|7d||
|アプリケーション|Weather|任意のアプリケーション名を指定もしくは作成する|
| 有効 | ✔︎ | このアイテムを有効にする |

親アイテムから画像のURLをimgタグに変換して保存するため、「保存前処理」も設定します。

| 設定項目 | 名前 |パラメータ | 説明 |
|--:|:--|:--|:--|
|保存前処理の設定|JSON Path|$.temperature.image.url ||
||正規表現|パターン⇒ ^(.*)$<br/>出力⇒ \<img src="\1" width="35" height="21" /\> |JSON Pathでimage.urlを取り出し、続けて正規表現のマッチ部分(全体)をimgタグに埋め込む<br/>JSON Pathは使わず最初から正規表現だけでもいいが... |

と、ここまでで「今日」の天気情報を取得する監視アイテムができあがりました。  
「明日」や「明後日」も作る場合は、アイテム名やJSON Pathで参照するオブジェクトを調整しつつ作ってください。

## [Zabbix] お天気監視ダッシュボードを作る

### ダッシュボードにウィジェットを追加する

ダッシュボードに移動して、右上の ![ダッシュボードを変更](https://qiita-image-store.s3.amazonaws.com/0/208817/3bf011a6-dd48-c51b-9ed1-8e319990e6c9.jpeg) から ![ウィジェットの追加](https://qiita-image-store.s3.amazonaws.com/0/208817/81aee8dc-f214-bc30-7c66-dba66f6f6cc7.jpeg) をします。

### (1) 今日の天気ウィジェット

今日の天気はimgタグを貼り付けたいので、プレーンテキストタイプのウィジェットにします。  
プレーンテキストタイプのウィジェットで**HTMLをテキストとして表示**を有効にすると、表示するヒストリをHTMLのタグとして解釈してくれるようになります。つまり、imgタグによる画像表示が可能となるわけです。

| 設定項目 | 設定値 | 説明 |
|--:|:--|:--|
|タイプ|プレーンテキスト||
|名前|今日の天気|任意のウィジェット名|
|リフレッシュ間隔|15分|もしくは「リフレッシュなし」でもいい|
|アイテム|(先に作成した「天気の画像」の監視アイテム)||
|アイテム名の位置|上||
|表示する行数|5|ダッシュボードに表示させたい行数を指定する|
|HTMLをテキストとして表示|✔︎||

### (2) 今日の気温ウィジェット

最高気温と最低気温は、まとめてひとつのウィジェットにします。

| 設定項目 | 設定値 | 説明 |
|--:|:--|:--|
|タイプ|グラフ||
|名前|今日の気温|任意のウィジェット名|
|リフレッシュ間隔|15分|もしくは「リフレッシュなし」でもいい|
|データセット|ホストパターン⇒ 130010<br/>アイテムパターン⇒ w_today_min, w_today_max|東京のIDのホストを選択|
|基本色|80CBC4|お好みで|
|欠損データ|接続する||
|グラフの形式|棒グラフ|お好みで|
|アイテム名の位置|上||
|表示する行数|5|ダッシュボードに表示させたい行数を指定する|

### お天気監視ダッシュボード完成

配置したいウィジェットを並べ終えたら ![変更を保存](https://qiita-image-store.s3.amazonaws.com/0/208817/de5f1933-4ce1-4673-020b-f751f3ad1700.jpeg) すると…これで、お天気監視ダッシュボードの完成です!

![お天気監視ダッシュボード](https://qiita-image-store.s3.amazonaws.com/0/208817/77e5ad01-eb0d-0b70-1f35-2429fb20d307.jpeg)

# おわりに

しょうもないことに保存前処理をなんとかして使いたい感がある監視設定でしたが、いろいろ遊んでみると新しい使い方が見えてきそうで楽しいですね。
Zabbix 4.2では保存前処理にJavaScriptを書けるようになるらしいので、JavaScriptによる処理を加えることでさらにいろいろ広がるような気もします!