計算アイテムの紹介と知っておくと得するTips

この記事は [Zabbix Advent Calendar 2015](http://qiita.com/advent-calendar/2015/zabbix) の14日目の記事です。
計算アイテムの初歩とあわせて、Zabbix上級者にも知っておいて欲しいTipsを1つご紹介します。


# 計算アイテムの概要

計算アイテム(Calculated Items)とは、設定された計算式によって、他のアイテムから新たな値を生成することができるアイテムタイプです。
Zabbix 1.8.1 からサポートされています。

[ドキュメント](https://www.zabbix.com/documentation/2.2/jp/manual/config/items/itemtypes/calculated)にも利用例がいくつか掲載されていますが、
次のような用途が多いとおもいます。

- 複数のアイテムを使って新たな値を導出したい
    - e.g.) トラフィックの inbound と outbound を合算したもの

- 直近の一定期間の統計的な値を知りたい
    - e.g.) 過去1時間のトラフィックの平均

- 過去のある時点との比較結果を知りたい
    - e.g.) 1週間前の同じ時刻のトラフィックとの差

計算式には四則演算と[トリガー関数](https://www.zabbix.com/documentation/2.2/jp/manual/appendix/triggers/functions)が利用できますので、
組み合わせによってとても柔軟な設定が可能です。

ここでは、最新の値を得る関数である`last(<key>)`を用いたシンプルな設定例をみてみましょう。

## 設定例: メモリの利用状況をグラフにしたい

あなたはいま、Linuxホストのメモリ利用状況について、`free` コマンドで得られるような値をもとに、搭載メモリ量を合計値とする積算グラフを作りたいと考えています。

調べてみるとZabbixエージェントには、メモリの情報を取得するアイテムキー `vm.memory.size[xxx]` が用意されていることがわかりました。

これを用いてメモリの情報を取得し、以下の様なグラフを作成してみました。

![chart1.png](https://qiita-image-store.s3.amazonaws.com/0/103907/7b9b5762-4a90-efca-2d62-65d3563ea65c.png)

さて、上記のグラフは一見正しい値を示しているように見えますが、このホストには約1.0GBのメモリしか搭載されていません。
しかし、このグラフでは合計が約1.3GB弱として表示されています。

実は `free` コマンドで `used` として表示される値と、`vm.memory.size[used]` の値は一致していないため、
知らずに利用すると上記のグラフのような問題が発生してしまいます。
※参考: [vm.memory.sizeパラメータ](https://www.zabbix.com/documentation/2.2/jp/manual/appendix/items/vm.memory.size_params)

加えて、残念ながら他の `vm.memory.size[xxx]` のどれを利用しても、目的の値は得られそうにありません。

しかたがないので、計算アイテムを用いて値を導出してみましょう。

## 計算アイテムの設定方法

まずは何はともあれアイテム設定画面を開き、
_アイテムタイプ:計算_ を選択します。

![calculated_items.png](https://qiita-image-store.s3.amazonaws.com/0/103907/2306785b-fefb-2dfc-7b62-c1e081af1d36.png)

_アイテムタイプ:計算_ を選択すると、
_式_ を入力する欄が現れますので、こちらに計算式を入力します。

![calculated_item.png](https://qiita-image-store.s3.amazonaws.com/0/103907/84db75d7-7754-f4e1-d18f-5df2ad5cc43f.png)

今回のケースでは次のような式になります。
(式には改行が含まれていても構いません。)

```
last(vm.memory.size[total])-
last(vm.memory.size[available])
```

上記の式の `last()` は、カッコ内に指定されたキーをもつアイテムの最新の値を得る関数です。
ほかにも、`avg()` や `min()`、`max()` などの[トリガー関数](https://www.zabbix.com/documentation/2.2/jp/manual/appendix/triggers/functions)を利用することもできます。

なお、式のなかで指定されるキーをもつアイテムは、
別途あらかじめ作成しておく必要がありますので、ご留意下さい。
(上記でいう`vm.memory.size[total]`や`vm.memory.size[available]`)

式以外の設定項目は、他のアイテムタイプの設定方法とおなじです。

![calculated.png](https://qiita-image-store.s3.amazonaws.com/0/103907/8a3b2347-c7b5-9c30-b1c5-69e1d664bd53.png)

## 確認

それでは作成した計算アイテムを用いて、
もう一度先ほどのグラフを確認してみましょう。

![chart2.png](https://qiita-image-store.s3.amazonaws.com/0/103907/ed24e9a9-5592-b995-8fa6-ef402146fb25.png)

どうやら今度は正しそうですね。

これでおわってしまっても良いのですが、
この計算アイテムにはまだ問題点が潜んでいます。

# 計算の元となるアイテムの状態による問題

計算アイテムには、計算の元となるアイテムが必要となりますが、
さて、ここで、障害が起きたときの挙動を想定してみましょう。

たとえば先ほどのメモリの例で、監視対象のホストのZabbixエージェントが停止してしまった場合、どうなるでしょうか。

以下はZabbixエージェントが停止した状態を再現したものですが、
計算アイテムで求めている部分だけグラフ上に残ってしまっています。

![nodata_ng.png](https://qiita-image-store.s3.amazonaws.com/0/103907/f7907c63-6e97-f9d9-71f4-cb072bc4b715.png)

`last()`関数は、_"最後に取得した値"_ を返す関数なので、
計算元のアイテムの値が更新されなくなったとしても、常に _"直近の"_ 値を返してしまい、上記のようにみえるのです。

これはちょっと気持ちが悪いですね。

## 元のアイテムの取得状態を反映する

上記のような状態を発生させたくない場合には、障害時には計算アイテムの値が更新されないよう、制御する必要があります。
しかしながら、いちいち手動で対応するのはナンセンスです。

そこで「取得不可」状態を発生させることで、
自動的に値の更新を止める方法を紹介します。

## 自動的に取得不可にする方法

まず、計算元のアイテムが更新されていないことは、
`nodata()`関数で検知できます。

`nodata()` 関数は2つの引数をとり、
第1引数がアイテムキー、第2引数に秒数を指定します。

第2引数は秒数を示し、指定された秒数の間
対象のキーにデータの更新がなかった場合、
関数の戻り値が `真(=1)` となります。

次に、計算アイテムを「取得不可」にする方法ですが、
取得不可になる場合のひとつに「ゼロ除算」があることに注目して下さい。

※参考: [計算アイテム](https://www.zabbix.com/documentation/2.2/jp/manual/config/items/itemtypes/calculated)
> 計算アイテムは、以下のケースでは取得不可になる場合があります：
> 1. 参照アイテムが見つからない
> 2. 関数を計算するためのデータがない
> 3. ゼロ除算
> 4. 使用している構文が正しくない
    
つまり、次の式のようなかたちで `nodata(key,t)` を用いることで、意図的に「ゼロ除算」を発生させ、
計算アイテムを「取得不可」にすることができるのです。

```
(1/(1-nodata(vm.memory.size[available],90)))*
(last(vm.memory.size[total])-
last(vm.memory.size[available]))
```

![calculated+nodata.png](https://qiita-image-store.s3.amazonaws.com/0/103907/0ea31de3-62ad-9101-db3b-3120ffd863c7.png)

これで、(更新間隔のぶんだけわずかに差は残るものの) 障害等で計算元の値が取得できない場合には、
値を記録しない計算アイテムを作成できました。

![nodata_ok.png](https://qiita-image-store.s3.amazonaws.com/0/103907/6de2b013-a6bb-d0d2-a118-17dad7a90875.png)

是非つかってみてください。

## 補足

いちど取得不可になったアイテムは、一定の期間を経て再度の取得が試みられます。
この期間は Zabbix の Web画面から設定可能です。

メインメニューから "管理"
→ "一般設定"
→ ドロップダウンから"その他"
→ "取得不可アイテムの更新間隔(秒)"
![settings.png](https://qiita-image-store.s3.amazonaws.com/0/103907/994fe028-ea44-170f-54fb-827c45b45529.png)

デフォルト値では 600秒(10分) となっていますので、
今回ご紹介した「自動的に取得不可にする」方法を用いる場合は、
計算アイテムの更新間隔にあわせて、より短く設定したほうがよいでしょう。

-----

明日は winebarrel さんです。
よろしくお願いします。