Zabbix ローレベルディスカバリ（LLD）の拡張①


 [Zabbix ローレベルディスカバリ（LLD）の拡張①](http://qiita.com/usiusi/items/51e8478cb080412958a4)
 [Zabbix ローレベルディスカバリ（LLD）の拡張②](http://qiita.com/usiusi/items/d616b7c0d51a926ca4a0)
 [Zabbix ローレベルディスカバリ（LLD）の拡張③](http://qiita.com/usiusi/items/0972da38984a82e43e74)
 [Zabbix ローレベルディスカバリ（LLD）の拡張④](http://qiita.com/usiusi360/items/8d44fd6b975b2db40ded)
 [Zabbix ローレベルディスカバリ（LLD）の拡張⑤](http://qiita.com/usiusi360/items/4664b10426bb6d993e1d)

# はじめに
Zabbix v2.0からローレベルディスカバリ機能(LLD)が使用出来る様になりました。
しかし、v2.4でもデフォルトで用意されているLLDアイテムキーは４種類しかありません。
LLDは使い方次第で、ホスト毎の差異を埋めてくれる便利な機能です。
LLDアイテムキーを拡張し、様々なデータのアイテム登録を自動化することが出来ます。

#### LLDで使えるアイテムキー(v2.4現在)
* net.if.discovery　since 2.0
* vfs.fs.discovery　since 2.0
* system.cpu.discovery　since 2.4
* snmp.discovery　since 2.0

#### LLDの拡張方法
独自のLDDアイテムキーを作る場合は、標準出力で以下のような形式のJSONデータを出力するようにします。
標準出力で表示するだけなので、シェルスクリプトでも作成可能です。

```lang:LLD-jsonデータの例
{
     "data":[
                { "{#NAME_A1}":"valueA1","{#NAME_A2}":"valueA2", ～～～～},
                { "{#NAME_B1}":"valueB1","{#NAME_B2}":"valueB2", ～～～～ },
                { "{#NAME_C1}":"valueC1","{#NAME_C2}":"valueX2", ～～～～ },
　　　　　　　　　　　　　　　　　　　　　　　　　～～～～
                { "{#NAME_X1}":"valueX1","{#NAME_X2}":"valueX2", ～～～～ }
     ]
}
```


# LLDの拡張例
## ディスクデバイス名
ディスクデバイス名（例：hda,sdaなど）を返します。
アイテムキーのvfs.dev.read、vfs.dev.write、system.swap.in、system.swap.out等と組み合わせるとデバイス別のI/O量取得を自動登録できます。

#### zabbix_agnetd.conf(エージェント側)での設定
　　UserParameter=vfs.dev.discovery,/etc/zabbix/zabbix_discovery/vfs.dev.discovery.sh

#### WebGUIでの設定

|ディスカバリルール | |
|:-----------|------------:|
|名前   |ディスクデバイスのディスカバリ |
|タイプ |Zabbixエージェント |
|キー   |vfs.dev.discovery |

|アイテムのプロトタイプ | |
|:-----------|------------:|
|名前   |ディスク読取平均回数[{#DEVNAME}] |
|タイプ |Zabbixエージェント |
|キー   |vfs.dev.read[{#DEVNAME},ops,avg1] |

```bash:vfs.dev.discovery.sh
#!/bin/bash
OS_CHK=`uname`
case "${OS_CHK}" in
   "Linux")
            LIST=`cat /proc/partitions | awk '{print $4}' | tail -n +3` ;;
   "SunOS")
            LIST=`iostat -x | awk '{print $1}' | tail +3` ;;
   *)
            echo "ZBX_NOTSUPPORTED"
            exit 1 ;;
esac

if [ "${LIST}" = "" ] ;then
    echo "ZBX_NOTSUPPORTED"
    exit 1
fi
 
echo "{"
echo "	\"data\":["
FIRST=1
for VER in ${LIST}
do
   if [ ${FIRST} -eq 1 ] ; then
      echo ""
      FIRST=0
   else
      echo ","
   fi
   echo -e -n "\t\t{ \"{#DEVNAME}\":\"${VER}\" }"
done
echo ""
echo "	]"
echo "}"
```

```lang:出力結果
# zabbix_get -s 192.168.0.1 -k vfs.dev.discovery
{
        "data":[

                { "{#DEVNAME}":"hda" },
                { "{#DEVNAME}":"hda1" },
                { "{#DEVNAME}":"hda2" },
                { "{#DEVNAME}":"hda3" },
                { "{#DEVNAME}":"vda" },
                { "{#DEVNAME}":"vda1" },
                { "{#DEVNAME}":"dm-0" }
        ]
}
```

##CPU使用率の高いプロセス（TopX）
実行中プロセスの中で、CPU使用率の高い順にX番目までのプロセスIDとプロセス名を返します。
リソースの使用率が高いプロセスを継続して取得することで、リソース逼迫障害時の切り分けに役立ちます。

#### zabbix_agnetd.conf(エージェント側)での設定
　　UserParameter=proc.cpu.discovery[*],/etc/zabbix/zabbix_discovery/proc.cpu.discovery.sh $1

#### WebGUIでの設定

|ディスカバリルール | |
|:-----------|------------:|
|名前   |プロセス別CPU使用率のディスカバリ |
|タイプ |Zabbixエージェント |
|キー   |proc.cpu.discovery[5] |

|アイテムのプロトタイプ | |
|:-----------|------------:|
|名前   |プロセス別CPU使用率[{#PROC_NAME}/{#PROC_ID}] |
|タイプ |Zabbixエージェント |
|キー   |proc.cpu.util[{#PROC_ID}] |

　 ※アイテム登録
　　標準ではプロセス毎にCPU使用率を取得するアイテムが用意されていないため、UserParameterかsystem.runで独自アイテムを作成する必要があります。

```lang:zabbix_agnetd.conf
　　UserParameter=proc.cpu.util[*],pidstat -u -p $1 | sed -e '1,3d' |  awk '{print $$6}'
```



##### 注意
　pidstatコマンドを使用するためsysstatがインストールされている必要があります。
　CentOS5系の標準リポジトリにあるsysstatは古く、sysstat8.0から追加されたpidstatコマンドが使えません。
　ちなみにpsコマンドを使わない理由は、[こちらのページ](http://d.hatena.ne.jp/ikeas/20091130/1259595249)参照

```bash:proc.cpu.discovery.sh
#!/bin/bash
# description
#  $1 : Showing Top N

TOP_line=$1

if [ "${TOP_line}" = "" ] ;then
    echo "NO ARGUMENT"
    echo "Must be specified head line."
    exit 1
fi

LIST=`pidstat -u | sed -e '1,3d' | awk '{print $6, $2, $8}' | sort -nr | head -${TOP_line}`

if [ "${LIST}" = "" ] ;then
    echo "ZBX_NOTSUPPORTED"
    exit 1
fi
 
echo "{"
echo "	\"data\":["
IFS=$'\n'
FIRST=1
for VER in ${LIST}
do
   PROC_NAME=`echo ${VER} | awk '{print $3}'`
   PROC_ID=`echo ${VER} | awk '{print $2}'`
   if [ ${FIRST} -eq 1 ] ; then
      echo ""
      FIRST=0
   else
      echo ","
   fi
   echo -e -n "\t\t{ \"{#PROC_NAME}\":\"${PROC_NAME}\",\"{#PROC_ID}\":\"${PROC_ID}\" }"
done
echo ""
echo "	]"
echo "}"
```

```lang:実行結果
# zabbix_get -s 192.168.0.1 -k "proc.cpu.discovery[5]"
{
        "data":[

                { "{#PROC_NAME}":"mysqld","{#PROC_ID}":"15183" },
                { "{#PROC_NAME}":"httpd","{#PROC_ID}":"20864" },
                { "{#PROC_NAME}":"httpd","{#PROC_ID}":"18337" },
                { "{#PROC_NAME}":"httpd","{#PROC_ID}":"18450" },
                { "{#PROC_NAME}":"httpd","{#PROC_ID}":"18449" }
        ]
}
```

##メモリ使用量の多いプロセス（TopX）
実行中プロセスの中で、メモリ使用率の多い順にX番目までのプロセスIDとプロセス名を返します。
proc.memと組み合わせて、プロセス毎のメモリ使用量の変化を追跡することが出来ます。

#### zabbix_agnetd.conf(エージェント側)での設定
　UserParameter=proc.mem.rss.discovery[*],/etc/zabbix/zabbix_discovery/proc.mem.discovery.sh 0 $1

　UserParameter=proc.mem.vsz.discovery[*],/etc/zabbix/zabbix_discovery/proc.mem.discovery.sh 1 $1

```
　　///// 第1引数
　　　物理メモリ使用量(RSS) : 0
　　　仮想メモリ使用量(VSZ) : 1
　　///// 第2引数
　　　上位Nまで表示（実際の数値はアイテムのプロトタイプのアイテム側で指定）
```

#### WebGUIでの設定

|ディスカバリルール | |
|:-----------|------------:|
|名前   |プロセス別メモリ使用量(RSS)のディスカバリ |
|タイプ |Zabbixエージェント |
|キー   |proc.mem.rss.discovery[5] |

|アイテムのプロトタイプ | |
|:-----------|------------:|
|名前   |プロセス別メモリ使用量(RSS)[{#PROC_NAME}] |
|タイプ |Zabbixエージェント |
|キー   |proc.mem[,,max,{#PROC_NAME}]  |


```bash:proc.mem.discovery.sh
#!/bin/bash
# description
#  $1 
#    RSS : 0
#    VSZ : 1
#  $2
#    Showing Top N

case "$1" in
   "0")
            MEM_TYPE=rss ;;
   "1")
            MEM_TYPE=vsz ;;
   *)
            echo "ZBX_NOTSUPPORTED"
            exit 1 ;;
esac

TOP_line=$2
if [ "${TOP_line}" = "" ] ;then
    echo "NO ARGUMENT"
    echo "Must be specified head line."
    exit 1
fi

LIST=`ps -eo ${MEM_TYPE},pid,comm | grep -v "PID COMMAND" | sort -nr | head -${TOP_line}`

if [ "${LIST}" = "" ] ;then
    echo "ZBX_NOTSUPPORTED"
    exit 1
fi
 
echo "{"
echo "	\"data\":["
IFS=$'\n'
FIRST=1
for VER in ${LIST}
do
   PROC_SIZE=`echo ${VER} | awk '{print $1}'`
   PROC_ID=`echo ${VER} | awk '{print $2}'`
   PROC_NAME=`echo ${VER} | awk '{print $3}'`

   if [ ${FIRST} -eq 1 ] ; then
      echo ""
      FIRST=0
   else
      echo ","
   fi

   echo -e -n "\t\t{ \"{#PROC_SIZE}\":\"${PROC_SIZE}\",\"{#PROC_NAME}\":\"${PROC_NAME}\",\"{#PROC_ID}\":\"${PROC_ID}\" }"

done
echo ""
echo "	]"
echo "}"
```

```lang:出力結果(RSS)_Top5

# zabbix_get -s 192.168.0.1 -k "proc.mem.rss.discovery[5]"
{
        "data":[
                { "{#PROC_SIZE}":"1759076","{#PROC_NAME}":"mysqld","{#PROC_ID}":"15183" },
                { "{#PROC_SIZE}":"34196","{#PROC_NAME}":"httpd","{#PROC_ID}":"18443" },
                { "{#PROC_SIZE}":"33844","{#PROC_NAME}":"httpd","{#PROC_ID}":"18450" },
                { "{#PROC_SIZE}":"33488","{#PROC_NAME}":"httpd","{#PROC_ID}":"18445" },
                { "{#PROC_SIZE}":"33244","{#PROC_NAME}":"httpd","{#PROC_ID}":"18448" }
        ]
}
```