Golangでmackerelのメトリック（グラフ）を作るプラグインを書いてみよう

# (1) 環境
開発環境：Mac
実行環境：CentOS6サーバ

# (2) まずは開発環境を整えましょう。Goインストール例

```bash
[mac]
### go install
$ sudo brew install go --cross-compile-all

### PATHを通す
$ vim /etc/profile
export PATH=$PATH:/usr/local/opt/go/libexec/bin
export GOPATH=$HOME/go

### 読み込む
$ source /etc/profile

### golint入れて構文チェックをさせる
$ go get -u github.com/golang/lint/golint
 
### atom入れると開発しやすいです。
### とりあえずこれくらいパッケージ入れとけば大丈夫かと。私の他のスターはこれ。　https://atom.io/users/sioncojp/stars
linter-golint
godef
atom-runner
go-plus
```

# (3) 今回は/ パーティションのディスクの使用率を取ってくるプラグインを書きます

```bash
### df -Pの実行
$ df -P
Filesystem         1024-blocks      Used Available Capacity マウント位置
/dev/mapper/VolGroup00-lv_root 279349272 188646616  76512476      72% /
tmpfs                 16436140         0  16436140       0% /dev/shm
/dev/sda1               198337     55219    132878      30% /boot

```

dfの/ パーディション使用率を取ってくるプラグインを書きます。goで書いた理由は、

* <a href="https://github.com/mackerelio/go-mackerel-plugin" target=_blank>go-mackerel-plugin</a>にそって作ると、メトリクスが綺麗に表示できるし、x軸の値もいじれるから。
* <a href="https://github.com/mackerelio/mackerel-agent-plugins" target=_blank>mackerel-agent-plugins</a>もGoで書かれてるし、mackerel pluginがアップデートされても、nagios pluginの使い回しより互換性は保たれるだろう。

# (4) まずはGoで書いてみる（test.goを作ってみる）

```go:test.go
package main
import (
    "bufio"
    "fmt"
    "os"
    "os/exec"
    "regexp"
    "strconv"
)
func main() {
    cmd := exec.Command("df", "-P")
    // 抽出する文字列。()でくくられてる部分が抽出される。
    // /dev/mapper/VolGroup00-lv_root  567182456 151718832 386652360  29% /
    // dfを打って、29%と/パーティション名をマッチさせる。正規表現はperlのやつを参考にすると良いです
    re := regexp.MustCompile(`^[^\s]+\s+\d+\s+\d+\s+\d+\s+\d+%\s+(\/)$`)
    // 標準出力をstdout変数にぶち込む
    stdout, err := cmd.StdoutPipe()
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    // コマンド実行
    cmd.Start()
    //あらかじめ行数が事前にわかるなら、makeで初期capacityを指定してメモリ確保する
    lines := make([]string, 0, 10)
    // stdoutの結果を1行ずつ読んでいく
    scanner := bufio.NewScanner(stdout)
    for scanner.Scan() {
        lines = append(lines, scanner.Text())
        if err := scanner.Err(); err != nil {
            fmt.Println(err)
            os.Exit(1)
        }
    }
    // float型に変更するために宣言しておく
    var used float64
    // 1行ずつ読んでいったものから、ディスクの使用率を抽出する
    for _, line := range lines {
        // 正規表現で書いた部分を探してもらい、mに打ち込む
        m := re.FindStringSubmatch(line)
        // 文字列がマッチした場合のみの
        if len(m) != 0 {
            // stringからint型に変換する。また使用率はマッチした1番目のカッコ
            used, _ = strconv.ParseFloat(m[1], 64)
            fmt.Println("/ :", used)
        }
    }
}
```

# (5) コンパイルして実行してみる
```bash
[mac]
$ cd $HOME/go/src/my/
### CentOSのx86系で実行するので、それ用にコンパイル
$ GOOS=linux GOARCH=amd64 go build -o build/mackerel-plugin-disk-used mackerel-plugin-disk-used.go
### 物理サーバにrsync
$ sudo rsync -av build/test 192.168.0.1:/var/tmp/
 
[192.168.0.1]
### 実行テスト
$ /var/tmp/test
/ : 72
# それっぽい値が返ってきた！
```

# (6) mackerelでメトリック（グラフ）にするためのプラグインを書いてみる（mackerel-plugin-disk-usedを作る）

出力はこうなれば良い
{metric名}\t{metric値}\t{epoch秒}

Go pluginを書くときのソースコードの構造はこんな感じです。

　① メトリック定義の記述
　② プラグインの挙動を決める変数の定義
　③ メトリックの取得
　④ メトリック定義の取得
　⑤ main()関数

長いので、gitのほうをご覧ください。説明も書いております。
https://github.com/sioncojp/mackerel_plugins/blob/master/mackerel-plugin-disk-used/disk_used.go

# (7) コンパイルして実行してみる

```bash
[mac]
$ cd $HOME/go/src/my/
### CentOSのx86系で実行するので、それ用にコンパイル
$ GOOS=linux GOARCH=amd64 go build -o build/mackerel-plugin-disk-used mackerel-plugin-disk-used.go
### 物理サーバにrsync
$ sudo rsync -av build/mackerel-plugin-disk-used 192.168.0.1:/var/tmp/

[192.168.0.1]
### 実行テスト
$ /var/tmp/disk_used
disk.used./ 72  1437975211
# {metric名}\t{metric値}\t{epoch秒}で返ってきた！
```

# (8) 必要であればpull reqを出しましょう
https://github.com/sioncojp/mackerel_plugins/tree/master/mackerel-plugin-disk-used
私はこんな感じの構造です
build.shを叩けば、build/にコンパイル後のファイルが出来るようにすると楽チンです。
（.gitignoreでbuild/をするのを忘れないように）

# (9) 実際のサーバに適用してみる

```bash
[192.168.0.1]
### 読み込ませるconfファイルを作ります
# mackerel-agentはsudo権限で実行してくれますので、コマンド部分にsudoは不要。
# [plugin.metrics.disk_used]　の名前は、.が２個区切りじゃないとダメ。
# checks：閾値判定のみ。metrics：グラフと閾値判定。
$ vim /etc/mackerel-agent/conf.d/hoge.conf
[plugin.metrics.disk_used]
command = '/var/tmp/mackerel-plugin-disk-used'

### mackerel-agentリスタート。PATHを正式に通すためserviceコマンドでやる。
$ sudo service mackerel-agent restart
 
### 問題がないかログを見ましょう
$ tail -f /var/log/mackerel-agent.log
```

# (10) mackerel.ioにログインして、メトリックスが表示されてるか確認しましょう

* 1分間隔で表示されます。

![スクリーンショット 2015-07-27 17.06.46.png](https://qiita-image-store.s3.amazonaws.com/0/29405/2962726b-771c-4851-c817-e95a9f8a253f.png)

# (11) グラフを削除するときは

* 対象の*.confを修正してmackerel-agent restart。これでデータの取得はしなくなります。
* その後、グラフのsetting→グラフの削除をしないと、グラフ自体は消えません。