stefafafan の fa は3つです

"すてにゃん" こと id:stefafafan のブログです

Mackerelのサービスメトリックを簡単に投稿するためのGitHub Actionsを作った

このエントリは Mackerel Advent Calendar 2022 および GitHub Actions Advent Calendar 202220日目の記事です。*1
今回はMackerelのサービスメトリックを投稿するためのGitHub Actionsを新規で作ったのでその紹介をします。

GitHub Actions経由でメトリクスを簡単にMackerelに投稿したい

弊社ではよくメトリクスをMackerelに投稿しています。事例としては以下のようなものがあります。

  • 定期的にコードの行数を数えてMackerelに投稿する
  • TODOコメントの数を数えてMackerelに投稿する
  • ビルド時間を計測してMackerelに投稿する
  • PageSpeed Insightsの計測結果をMackerelに投稿する

Mackerelのサービスメトリックとして投稿するにはAPIキーを用意し、以下のドキュメントに従ってPOSTするだけで簡単にできます。GitHub Actions上で素朴に実装するならばリクエストを手作りしてからcurlでPOSTする、とかになるでしょうか。 mkr をインストールして実行するというやり方もあるかもしれません。
mackerel.io

既存のGitHub Actions

既存のGitHub Actionsがいくつかあるのでそれらを使うことはできます。

yutailang0119/action-mackerel-api

github.com

yutailang0119/action-mackerel-api を使う場合は以下のような記述でサービスメトリックを投稿することができます。

- uses: yutailang0119/action-mackerel-api@v3
  with:
    api-key: ${{ secrets.MACKEREL_APIKEY }}
    http-method: POST
    path: services/${{ secrets.MACKEREL_SERVICENAME }}/tsdb
    body: |
      [
        {
          "name": "foo-metric.count",
          "time": 1670747231,
          "value": 12345.678
        }
      ]

紹介記事:
yutailang0119.hatenablog.com

susisu/setup-mkr

github.com

susisu/setup-mkrGitHub Actions上で簡単に mkr をセットアップするためのActionです。 mkr throw を使えばサービスメトリックの投稿ができます。

- uses: susisu/setup-mkr@v1
- run: echo "foo-metric.count 12345.678 $(date +%s)" | mkr throw --service ${{ secrets.MACKEREL_SERVICENAME }} 
  env:
    MACKEREL_APIKEY: ${{ secrets.MACKEREL_APIKEY }}

なおGitHub ActionsのRunnerとしてUbuntu等で動かしている場合は普通にmkrをインストールする形でも問題ないです。

紹介記事:
susisu.hatenablog.com

自分のユースケースでの気になり

上記のようなActionsでやりたいことは実現できますが、自分の場合サービスメトリック以外の機能をGitHub Actionsで使うケースが少ないのでちょっとオーバーキルだと感じました。

yutailang0119/action-mackerel-api はREADMEを見る限り色々なAPIを網羅的に対応するような薄いラッパーで、mkr に関しては強力だけどサービスメトリックへのPOSTのためだけにこれをインストールするほどでもないなとも。

あとは単純に自分でもCustomなGitHub Actionsを作ってみるという経験がほしかったというのもあります(これが一番大きい)。

stefafafan/post-mackerel-metrics の紹介

ということで作りました。

github.com

サービスメトリックを投稿したい場合は以下のような使い勝手になります。

uses: stefafafan/post-mackerel-metrics@v1
with:
  api-key: ${{ secrets.MACKEREL_APIKEY }}
  service-name: ${{ secrets.MACKEREL_SERVICENAME }}
  metric-name: 'foo-metric.count'
  metric-value: 12345.678

推しポイントとしては以下のような点があります。

  • mkr のダウンロードは不要なので軽量で素早い
  • APIの仕様やmkrの使い方など詳細を知らなくても使えるシンプルさ
    • JSONの組み立てなども不要なのでMackerelに投稿するために凡ミスで四苦八苦することが少ないはず
  • 投稿日時は内部で現在時刻を指定してくれるのでGitHub Actions上で $(date +%s) のようなことをやる必要がない

また、複数のサービスメトリックを同時に投稿したい場合は metrics という input で Multiline String をサポートしているので以下のように指定して投稿できるようにしてあります。

uses: stefafafan/post-mackerel-metrics@v1
with:
  api-key: ${{ secrets.MACKEREL_APIKEY }}
  service-name: ${{ secrets.MACKEREL_SERVICENAME }}
  metrics: |
    foo-metric.count  12345.678 1670747999
    foo-metric.count2 7777.777  1670747999

上記の形式はMackerelのプラグインmkr throw するときのフォーマットに揃えてあるので馴染み深い形になっていると思います*2。Actionの内部実装としては \s+ 区切りでパースしてあるのでタブ文字でもスペースでも複数スペース連続していても問題なく利用できる形にしてあります。また、最後のタイムスタンプも省略して現在日時を内部で採用してもらうという使い方もできます。

逆に使えないユースケースとしては、サービスメトリックの投稿に特化しているので、他のAPIであれこれしたい場合は yutailang0119/action-mackerel-apimkr を使ってください。

実際に活用している事例

リポジトリにもWorkflowの例を載せていますが、以下のような記述をすれば簡単にコードの行数をMackerelに投稿することができます。

name: Count and Post lines of Code to Mackerel

on:
  push:
    branches:
      - main

jobs:
  count-and-post:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
      
      - id: count-lines
        name: count lines of TypeScript code
        run: |
          lines=$(find src/ -name '*.ts' -print0 | xargs -0 cat | wc -l | tr -d ' ')
          echo "lines=${lines}" >> $GITHUB_OUTPUT
      
      - name: Post to Mackerel
        uses: stefafafan/post-mackerel-metrics@v1
        with:
          api-key: ${{ secrets.MACKEREL_APIKEY }}
          service-name: ${{ secrets.MACKEREL_SERVICENAME }}
          metric-name: 'lines.typescript'
          metric-value: ${{ steps.count-lines.outputs.lines }}
Mackerelにサービスメトリックが投稿されている様子

Mackerelのサービスメトリックへの投稿が面倒そうと思って敬遠している方がもしいれば参考にしてもらえれば幸いです。

テクニック紹介: 他のStepからMultiline Stringの受け渡し

例えばGitHub Actionsの他のStepで計算した複数の値を1つずつOutputとして出力するのではなく、まとめてMultiline Stringとして受け渡したくなるかもしれません。こちらについても紹介しておきます。

Bashで色々やっている場合はdelimiterを指定しつつ $GITHUB_OUTPUT に出力するということをやることになります。以下の例ではActions上で直接メトリックの結果をechoしてありますが、これをたとえば実行可能なshell scriptとして用意しておいてActions内ではそれを実行して $GITHUB_OUTPUT に出力するだけ、みたいに実現することもできそうです。

- id: multiline-output
  run: |
    delimiter="$(openssl rand -hex 8)"
    echo "metrics<<${delimiter}" >> $GITHUB_OUTPUT

    echo "multiline.metric1 12345 $(date +%s)" >> $GITHUB_OUTPUT
    echo "multiline.metric2 67890 $(date +%s)" >> $GITHUB_OUTPUT

    echo "${delimiter}" >> $GITHUB_OUTPUT

- name: Post to Mackerel
  uses: stefafafan/post-mackerel-metrics@v1
  with:
    api-key: ${{ secrets.MACKEREL_APIKEY }}
    service-name: ${{ secrets.MACKEREL_SERVICENAME }}
    metrics: ${{ steps.multiline-output.outputs.metrics }}

参考ドキュメント

actions/github-script を使いたい場合は core.setOutput を利用して受け渡しすることができます。

- id: multiline-output
  uses: actions/github-script@v6
  with:
    result-encoding: string
    script: |
      const metrics = `
        multiline.metric1 12345
        multiline.metric2 67890
        multiline.metric3 77777
      `;
      core.setOutput('metrics', metrics);

- name: Post to Mackerel
  uses: stefafafan/post-mackerel-metrics@v1
  with:
    api-key: ${{ secrets.MACKEREL_APIKEY }}
    service-name: ${{ secrets.MACKEREL_SERVICENAME }}
    metrics: ${{ steps.multiline-output.outputs.metrics }}

GitHub APIであれこれした後にまとめてサービスメトリックとして投稿したい場合はこういう風にMultiline StringをOutputして利用すると良いでしょう。

初めて作ったGitHub Actionについての感想や困りなど

今回CustomなGitHub Actionを作るにあたって参考にしたのは主に以下のドキュメントです。

またリポジトリについては TypeScript Action を作るためのテンプレートリポジトリがあったので以下のテンプレートを利用しました。

テンプレートがあるのは初めて作る上でとても助かりました。構成やCIの整備などに迷うことなく既にある雛形に自分のコードを追加する形で作れました。脆弱性検知をしてくれるCodeQLのActionが最初から組み込まれているのも良いですね。

一方でこのテンプレートで利用しているライブラリの依存が更新されていないという点が気になりで、実装を始める前にDependabotを有効化したらそれだけで9つのPull Requestが開かれて体験が悪かったです。気になったので最初はひたすらバージョンを上げていました。

Dependabotによって開かれたPull Request一覧

バージョンといえばJavaScript Actionが使うNode.jsのバージョンも現状 v12 か v16 固定というポイントもちょっとイマイチでした。この記事を書いてる段階では Node.js v18 が Active LTS なのでそれを最初から指定したかったですがそうは行かないようでした。しょうがないですね。
github.com

何はともあれサクッと自分がほしいと思ったCustomなGitHub Actionを作れたので満足しています。

終わりに

この記事は Mackerel Advent Calendar 2022 および GitHub Actions Advent Calendar 2022 の記事でした。

Mackerel Advent Calendar 明日は id:buty4649 さんの予定です。GitHub Actions Advent Calendarは @taptappun さんの予定です。お楽しみに!