サードパーティプラグインインストール機能を使ってみる

Mackerelのプラグイン機能、非常に便利ですね。
[mackerel-agent-plguins](https://github.com/mackerelio/mackerel-agent-plugins)、[go-check-plugins](https://github.com/mackerelio/go-check-plugins)ともに様々活用させていただいています。

活用しているプラグインには以下の様なものがありました。

- mackerel-agent-plugins
  - mackerel-plugin-apache2
  - mackerel-plugin-docker
  - mackerel-plugin-jvm
  - mackerel-plugin-memcached
  - mackerel-plugin-mysql
  - mackerel-plugin-nginx
  - mackerel-plugin-postgres
- go-check-plugins
  - check-http
  - check-log
  - check-procs
  - check-tcp

そしてMackerelの良いところは自分でプラグインを作成、利用できるところです。
私も自分でいくつかプラグインを作成して利用しています。

そんな私待望の[サードパーティプラグインインストール機能](https://mackerel.io/ja/blog/entry/feature/20171116)が先日発表されました。

この機能が登場するまでは、ビルド済みのバイナリをどこかにおき、Mackerel設定時に配布する、またはMackerelをインストールする環境にGoをインストールしておき、毎回ビルドをする必要がありました。
私の利用環境では、Mackerel設定用のAnsibleのリポジトリ内にビルド済みのバイナリを入れて配布していたため、リポジトリが肥大化したり、バイナリがいつのタイミングでビルドされたものかわからない問題がありました。

今回は、サードパーティプラグインインストール機能を利用するまでの一連の流れを実際にプラグイン実装からやってみたいと思います。

## まずはプラグインの実装
肝心のプラグインの題材ですが、実際に以前から活用していて公開していなかったものを公開する形で行います。
先日Songmuさんが[紹介していた](https://mackerel.io/ja/blog/entry/advent-calendar2017/day9-mackerel-plugin-accesslog)`mackerel-plugin-accesslog`を少し改造したものです。

記事でも紹介されていた、fluentdを用いた集計方法を以前から活用しており、`mackerel-plugin-accesslog`を利用すればもっと便利になると思っていたのですが、私の環境ではLTSVのフォーマットが対応しておらず利用することが出来ませんでした。

プラグインの実装としては、記事でも解説がある通り[ltsv.org](http://ltsv.org/)に則って`reqtime`や`status`のKeyが入ったログである必要があるのですが、私の環境では異なるフォーマットを利用していました。
Mackerel以外のログを活用するものの依存を考えたときにフォーマットを変えることは難しかったため、Keyを選択できるようにしたかったのですが、`mackerel-plugin-accesslog`の実装上難しそうであったため、本家へのPull Requestと言う形ではなく自前で改造という形をとっていました。

それがこちら[mackerel-plugin-ltsv-accesslog](https://github.com/nashiox/mackerel-plugin-ltsv-accesslog)です。

## GitHub Releasesへリリース
プラグインの実装が終わったら`mkr plugin install`が可能な状態を作る必要があります。
`<release_tag>`に`<repo>_<GOOS>_<GOARCH>.zip`という命名規則に従って、ビルドした生成物を配置するだけです。

### プラグインをビルドする
プラグインのビルドには、クロスコンパイルが簡単にできる[goxc](https://github.com/laher/goxc)を利用します。

```bash
### インストール
$ go get github.com/laher/goxc

### クロスコンパイル
$ goxc
```

サンプルとして公開されている[mackerel-plugin-sample](https://github.com/mackerelio/mackerel-plugin-sample/blob/master/.goxc.json)にgoxcのビルド設定があるため、このまま拝借します。

下記ファイルをリポジトリ直下に配置します。
こうすることで、Linux、Mac、Windowsの32bit、64bit環境で動作するバイナリがプラグインとして期待されている`<repo>_<GOOS>_<GOARCH>.zip`の命名規則で生成されます。

```json:.goxc.json
{
    "ArtifactsDest": "dist",
    "Tasks": [
        "clean-destination",
        "xc",
        "archive-zip",
        "rmbin"
    ],
    "TaskSettings": {
        "archive-zip": {
            "include-top-level-dir": "windows darwin linux",
            "platforms": "windows darwin linux"
        }
    },
    "Arch": "386 amd64",
    "Os": "linux darwin windows",
    "ConfigVersion": "0.9"
}
```

### 成果物を自動でリリースする
せっかくなのでGitHubにPushされたら自動でテスト->ビルド->リリースされるように設定します。
CIにはCircleCI、GitHub Releasesへのリリースは[ghr](https://github.com/tcnksm/ghr)を利用します。

GitHubのリポジトリとCircleCIを連携させたあとは、リポジトリ内に`.circleci/config.yml`を作成してPushするだけです。

```yaml:config.yml
version: 2
jobs:
  test:
    working_directory: /go/src/github.com/nashiox/mackerel-plugin-ltsv-accesslog
    docker:
      - image: golang:1.9
    steps:
      - checkout
      - run:
          name: "Install Build Dependencies"
          command: |
              make builddep
      - run:
          name: "Run Test"
          command: make test

  deploy:
    working_directory: /go/src/github.com/nashiox/mackerel-plugin-ltsv-accesslog
    docker:
      - image: golang:1.9
    steps:
      - checkout
      - run:
          name: "Install Build Dependencies"
          command: make builddep
      - run:
          name: "Cross Compile"
          command: make cross
      - run:
          name: "Deploy"
          command: make deploy

workflows:
  version: 2
  test_and_deploy:
    jobs:
      - test
      - deploy:
          requires:
            - test
          filters:
            branches:
              only: master
```

テストやビルド、デプロイに必要なコマンドは`Makefile`にすべて任せています。
CircleCI 2.0の`workflows`の機能を使って`test`は全てのブランチで、`deploy`はmasterブランチにPushされたときのみ実行されるようにしています。

ここまで来たら後はGitHubにPushをするだけです。
masterブランチにPushが行われると以下のようにタグが来られ、プラグインのリリース完了です。
![ 2017-12-11 3.01.17.png](https://qiita-image-store.s3.amazonaws.com/0/91270/5b6012e5-7d01-7736-075a-9931657a74b2.png)

## 設定
あとは実際に監視の設定をするだけです。
インストールは以下のように`<GitHubのリポジトリ>@<タグ>`の規則で指定します。

```bash
$ mkr plugin install nashiox/mackerel-plugin-ltsv-accesslog@v0.0.1
```

設定は以下のように記載します。

```
[plugin.metrics.accesslog]
command = "/path/to/mackerel-plugin-ltsv-accesslog -request-time-key=reqtime -status-key=status /path/to/access.log"
```

このプラグインは前述の通り、リクエストタイムとステータスコードのKeyをオプションで指定できるようになっています。
ログフォーマットの自由度がぐんと上がるので個人的にはすごく便利だと思っています。

## [オプション] plugin-registryにPull Requestを出す
作成したプラグインを他のユーザーが見つけやすくするためには、[公式のプラグインレジストリ](https://github.com/mackerelio/plugin-registry)にPull Requestを出すことになります。

`plugins/`配下に`<プラグイン名>.json`ファイルを以下のような内容で作成します。

```json
{
    "source": "nashiox/mackerel-plugin-ltsv-accesslog",
    "description": "LTSV Accesslog custom metrics plugin"
}
```

あとはPull Requestを出して、マージされれば完了です。

## まとめ
今回はサードパーティプラグインインストール機能の利用を実際にプラグインの作成からリリースまで行ってみました。
今まではプラグインインストールの手間を省くためにはmackerel-agent-plguins等にマージして貰う必要があり、ハードルが高かったですが、自作のプラグインインストール機能が公式に提供されたことによって、プラグイン作成のハードルがさらに下がったと思います。
まだいくつか公開していない自作プラグインがあるので徐々にこちらの方式に寄せていきたいと思っています。

余談ですが、今回作成・公開したプラグインをplugin-registryにPull Requestを出すところまで実施しましたが、オリジナルのmackerel-plugin-accesslogに似すぎているという理由でマージされませんでした。
ユーザの目につきやすくする方法が絶たれたので、ぜひみなさん認知度アップにご協力お願いいたします。