Go言語でZabbixサーバーからヒストリをとってくる

Go言語でZabbixサーバーにあるアイテムのヒストリをとって表示するコードを書いてみた。
今回は1番わかりやすいlocal time(時刻)のヒストリを取り出すことにした。

##用意するもの
https://github.com/rday/zabbix
デバッグ用のアイテム

##はじめにすること
Zabbixサーバーに接続しバージョンを表示する。

```go:main.go
	api, err := zabbix.NewAPI("http://[ホストのIP]/api_jsonrpc.php", "name", "password")
	if err != nil {
		fmt.Println(err)
		return
	}

	versionresult, err := api.Version()
	if err != nil {
		fmt.Println(err)
	}

	fmt.Println(versionresult)
```
これで、バージョンが返ってくれば正常に動作していることが分かる。


次にログインをする。

```go:main.go
	_, err = api.Login()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("Connected to API")
```
ログインに成功すればConnected to APIが表示される。ここからZabbix APIの機能が使える。


##ソースコード
さっそく指定したアイテムのヒストリをとりたいところだけど、どうやらHistory.getではアイテムキーやアイテム名で指定できないみたいだったので、Item.getで欲しいItemのIDをとってきてそれを使ってヒストリも取ってくることにした。
先ず、Item.getでアイテムをキーで指定して取ってくる。今回gitHubで拾ってきたコードにItemを操作する機能が追加されていなかったため自分で追加した。一応、取りたいアイテムがどれなのかアイテム名などから見ておく必要があるみたい。

```go:main.go

type ZabbixItem struct{
	Itemid string `json:"itemid"`
    //データ確認用
	Hostid string `json:"hostid"`
	Name string `json:"name"`
}

func getItem(api *zabbix.API) ([]ZabbixItem, error){
	params := make(map[string]interface{}, 0)
	filter := make(map[string]interface{}, 0)

	params["output"] = "extend"
	params["filter"] = filter    //フィルターにマッチしたもののみ取り出す
	filter["key_"] = "system.localtime"    //アイテムキー
	filter["name"] = "name"    //アイテム名

	response, err := api.ZabbixRequest("item.get", params)    //ここでAPIの機能を指定できる
	if err != nil {
		return nil, err
	}

	if response.Error.Code != 0 {
		return nil, err
	}

	res, err := json.Marshal(response.Result)

	var ret []ZabbixItem
	err = json.Unmarshal(res, &ret)	
    if err != nil {
		return nil, err
	}

	if len(res) > 0{
		return ret, nil
	}else{
		return nil, &zabbix.ZabbixError{0, "", "Cannot get the Item"}
	}
}
```

次にヒストリを取得する関数を用意する。

```go:main.go
	func getHistory(api *zabbix.API, itemid string)(){
	params := make(map[string]interface{}, 0)

	params["output"] = "extend"
	params["history"] = 3    //整数値が返ってくる
	params["itemids"] = itemid   //先ほど取得したitemidを指定
	params["sortfield"] = "clock"    //時間でソート
	params["sortorder"] = "DESC"    //降順
	params["time_till"] = time.Now().Unix()    //現在時刻までのデータを取得する
	res, err := api.History("get", params)    
	if err != nil{
		fmt.Println(err)
	}


	if len(res) > 0{
		      for _, item:= range res{
			        t, _ := strconv.ParseInt(item.Value,10 ,64)    //stringからint64へ変換
		            fmt.Println(time.Unix(t, 0))    //timestampからtime型へ変換し標準出力
		      }
	     }else{
		    fmt.Println(&zabbix.ZabbixError{0, "", "Cannot get the History"})    
	     }
     }
```

こちらはvoid型の関数なので関数を呼び出すだけで取得したデータをすべて表示してくれる。
 あとはmain関数で一連の処理をまとめるだけ。

```go:main.go
func main(){
    //zabbixサーバーへ接続
	api, err := zabbix.NewAPI("http://[ホストのIP]/zabbix/api_jsonrpc.php", "name", "password")
	if err != nil {
		fmt.Println(err)
		return
	}
    //バージョンの取得
	versionresult, err := api.Version()
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(versionresult)

    //ログイン
	_, err = api.Login()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("Connected to API")

    //アイテムIDの取得
	item, err := getItem(api)
	if err != nil{
		fmt.Println(err)
	}

    //ヒストリの取得、表示
	getHistory(api, item[0].Itemid)

    //ログアウト
	_, err = api.Logout()
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("Logged out")
}
```

今回は、急ぎで作ったこともありgitHubからコードを借りてAPIを利用したが、仕組みとしてはhttpclientでJSONデータをzabbixにPOSTし、JSONデータを受け取るだけでなので理解しやすいと思う。JSON-RPC便利やな…
とりあえずヒストリの取得はできたので、今度はhttpclientでPOSTする処理から自分で書きたい。

https://www.zabbix.com/documentation/2.2/manual/api
こちらにAPIの機能一覧が載ってるので、他の機能が使いたいという方は参照して下さい。