2018年10月6日土曜日

prometheus-client を使って独自の exporter を作成する方法

概要

前回 prometheus-client を使ってデフォルトのメトリックを自分のアプリに組み込む方法を紹介しました
今回はカスタム Exporter を作成して独自のメトリック情報も取得できるようにしてみます
なお、組み込むアプリは Rails アプリではなく Sinatra をベースにしたアプリになります

環境

  • macOS 10.14
  • ruby 2.5.1p57
  • prometheus-client 0.8.0

カスタム Controller の作成

まず Controller を作成します
Controller では独自で追加するメトリックのメタデータの登録を行います

  • vim helper/custom_controller.rb
require 'prometheus/client'

module Prometheus
  module Controller
    prometheus = Prometheus::Client.registry
    gauge = Prometheus::Client::Gauge.new(:online_flag, 'Check the flag whether it is online')
    prometheus.register(gauge)
  end
end

とりあえずこんな感じで作ります
Gauge は 1 or 0 のような二値を返却するときに使うタイプになります
新しく Gauge のオブジェクトを作成し引数にメトリック名と説明を与えます
あとは prometheus.register することで Controller を登録します

なおこの状態で config.ru から参照すると /metrics にメトリック名だけ表示することができます

require './helper/custom_controller'

カスタム Exporter の作成

次に Exporter を作成します
Exporter は実際にメトリックに出力するデータを操作する役割になります

  • vim helper/custom_exporter.rb
require 'prometheus/middleware/exporter'

module Prometheus
  module Middleware
    class CustomExporter < Prometheus::Middleware::Exporter

      def respond_with(format)
        guage = @registry.metrics.first
        guage.set({
          name: :my_site
        }, online?)
        super
      end

      def online?
        0
      end

    end
  end
end

まず Prometheus::Middleware::Exporter を継承します
そして respond_with を実装します
ここで先程登録したメトリック項目を @registry で参照できます
@registry には登録したメトリック情報がキュー配列で格納されています
先程登録したメトリック (:online_flag) は先頭に格納されるので .first で取得することができます
ちなみに今回の場合であれば配列は 4 つあり残り 3 つはデフォルトで Exporter に実装されているメトリックが入っています

あとはメトリックにラベルとコールバック用のメソッドを set します
ラベルはハッシュで好きな内容が登録できます
コールバック用のメソッドは実際にメトリックとして出力する内容を取得するメソッドになります
今回は単純に 0 を返却していますが実際はここに例えばサイトがオンラインであるかどうかチェックするロジックを記載します

Tips

もしデフォルトのメトリック情報を削除したい場合は Prometheus::Middleware::Exporter を継承しないで独自メトリック情報の文字列を返却する Exporter を作成する必要があります

@registry.metrics の配列から Prometheus::Client を削除しようとしても readonly なフィールドなので削除することはできません

config.ru から呼び出す

あとは Controller と Exporter を config.ru から参照するだけです

  • vim config.ru
require './helper/custom_controller'
require './helper/custom_exporter'
require 'prometheus/middleware/collector'
# require 'prometheus/middleware/exporter'

use Rack::Deflater
use Prometheus::Middleware::Collector
# use Prometheus::Middleware::Exporter
use Prometheus::Middleware::CustomExporter

Prometheus の部分だけ抜粋しています
Prometheus::Middleware::Exporter は作成したカスタム Exporter が継承しているので不要になります

またあとで気づいたのですが、デフォルトのメトリック情報を削除したいのであれば prometheus/middleware/collectorPrometheus::Middleware::Collector を削除すれば出なくなります

最後に

Ruby の prometheus-client を使って独自のメトリックを作成する方法を紹介しました
Controller でメトリックの項目を登録し、Exporter で登録したメトリックに対して実際に値を取得するロジックを実装する感じになります

今回 Exporter は Prometheus::Middleware::Exporter を継承して実装しました
おそらくこの方法が一番簡単な方法だとは思います
が、実はこの方法にこだわる必要は全くありません
というのも Prometheus は結局 exporter と HTTP で話しができてその出力結果がフォーマットに沿った text/plain であれば良いのです
なので、自分で erb を作成してそれを出力してもいいですし単純にフォーマットに沿ったテキストファイルを読み込んでそれを Sinatra で出力する感じでも全然問題ありません

今回の方法を使うと、その辺りのフォーマット関係を気にせず実装できるという感じになります
あとは Prometheus から exporter にアクセスがあったときに値の集計を行うコールバックが呼ばれるので無駄なメトリック取得のためのアクセスやコールを防ぐことができるというメリットもあります

参考サイト

0 件のコメント:

コメントを投稿