koudenpaのブログ

趣味のブログです。株式会社はてなでWebアプリケーションエンジニアをやっています。職業柄IT関連の記事が多いと思います。

Mackerelエージェントから他のサービスに投稿したい Vol.2

前回のあらすじ。

あるオープンソースCLIアプリケーションソフトウェアでやりたいことがある場合には、大体以下ようなことを上から順に試すと思う。

  1. Readmeを読む
  2. help コマンドを叩く
  3. ソースコードを読み込む
  4. とりあえずガチャガチャ実装を直す

下からやってしまいました。 Goのプログラムをビルドしてみるという他の目的があったとはいえ、あんまりな段取りだったと反省しました。

さて、Mackerelエージェントをビルドできるようになったので、次は以下のようなことを試していきたい。

  • 設定項目を追加する
  • 追加した設定項目を動作に反映する

設定項目を追加する

設定ファイルの形式はTOMLだということは知っていて、何かしらのライブラリで読み込んでいるのだろうと思っていた。

実際その通りで、設定用の構造体にメンバを追加したらいい感じに読み込まれた。

設定項目を追加する · 7474/mackerel-agent@88623e4 · GitHub

f:id:koudenpa:20180425221935p:plain

大昔は設定ファイルの読み込み処理を独自に書いたりしたものだけれど、今どきは簡単で良い。

追加した設定項目を動作に反映する

追加した設定を動作に反映していく。

元々は、大きな設定差分毎にAPI呼び出し用のインタフェースを実装していこうと思っていたのだけれど、MackerelエージェントはAPIクライアントをインタフェースではなく構造体で取り廻しているようなので無理筋だった。 (多分。Goは入門本を斜め読みした程度なので、実体を取り廻していてもいい感じに多様性を持たせられるのかもしれない)

APIクライアント構造体と、そこに生えているメソッドをゴリゴリ修正して行く形で追加変更していくことにした。

追加した設定項目を動作に反映する · 7474/mackerel-agent@1ed3258 · GitHub

apikey = "xxx"
apibase = "https://mackerel-dash-stub.azurewebsites.net"
verbose = true

# Custom Config
APIClientType = "custom-http"
CustomHTTPHeaders = { x-functions-key = "b64==", foo = "bar" }

上記のような設定をして実行。

> mackerel-agent.exe
2018/04/25 22:24:02 main.go:171: INFO <main> Starting mackerel-agent version:0.54.1, rev:, apibase:https://mackerel-dash-stub.azurewebsites.net
2018/04/25 22:24:02 main.go:172: INFO <main> APIClientType:custom-http
2018/04/25 22:24:02 command.go:649: DEBUG <command> NewCustomHttpClient
2018/04/25 22:24:02 command.go:659: DEBUG <command> headers x-functions-key: b64==
2018/04/25 22:24:02 command.go:659: DEBUG <command> headers foo: bar
2018/04/25 22:24:09 command.go:739: INFO <command> Start: apibase = https://mackerel-dash-stub.azurewebsites.net, hostName = , hostID = xxx
2018/04/25 22:24:09 command.go:199: DEBUG <command> wait 4 seconds before initial posting.
2018/04/25 22:24:09 command.go:597: DEBUG <command> Updating host specs...
2018/04/25 22:24:09 memory.go:43: DEBUG <metrics.memory> memory : map[~~]
2018/04/25 22:24:09 filesystem.go:45: DEBUG <metrics.filesystem> map[~~]
2018/04/25 22:24:09 processor_queue_length.go:61: DEBUG <metrics.processor_queue_length> processor_queue_length: map["processor_queue_length":%!q(float64=0)]
2018/04/25 22:24:09 cpuusage.go:76: DEBUG <cpu.user.percentage> cpuusage: map["cpu.user.percentage":%!q(float64=0) "cpu.system.percentage":%!q(float64=0) "cpu.idle.percentage":%!q(float64=0)]
2018/04/25 22:24:15 api.go:306: DEBUG <api> PUT /api/v0/hosts/xxx {"name":"DESKTOP-xxx","meta":{~~}
2018/04/25 22:24:15 api.go:319: DEBUG <api> PUT /api/v0/hosts/xxx status="200 OK"

どうやら、想定通りにヘッダが設定されたリクエストが行われているようだ。

MackerelサービスAPIスタブ

前回雑に作成したMackerelのAPIスタブをローカルマシン上で実行していたが、本命はAzure Functions上での実行である。

Functionsは様々なトリガーで実行できるが、HTTPリクエストをトリガーとする場合の認証は特定のクエリパラメータないしHTTPヘッダにキーを送出することで行う。

Azure Functions における HTTP と Webhook のバインド | Microsoft Docs

キーは、上記のように code という名前のクエリ文字列変数に含めることも、x-functions-key HTTP ヘッダーに含めることもできます。 キーの値には、関数のために定義されている任意の関数キーまたは任意のホスト キーを指定できます。

先にHTTPヘッダを設定できるようにしたのはそのためだ。

これでHTTPでリクエストを受け付け、HTTPヘッダ内容を見てクライアント認証する形のサービスへの投稿は過不足なく設定できるようになった。

遊び

改造エージェントは想定通りに動作していることを確認するために、投稿されたメトリックをチャート表示した。

f:id:koudenpa:20180426011835p:plain

Teat Chart ← Blobストレージに適当なHTMLを置いて、Functionsの方のCORS設定をした。

はっきり言ってエージェントの改造よりこの『遊び』やAPIのスタブ作りの方が何倍も時間がかかっている。

が、まぁ、そういうもん。

Mackerelというサービスの価値の過半はそちらの方にあるわけだし、一朝一夕でクローン出来たらそれで商売するわ。


次は何をするか、HTTPクライアントを拡張して証明書認証できるようにするか、さっさとMQTTクライアントに手を出すか、少し迷っている。

どちらもAWS IoTをターゲットとしているので、最終的にはどちらも試そうかなぁ、と思っている。