LIFULL Creators Blog

「株式会社LIFULL(ライフル)」の社員によるブログです。

退屈な監視はPrometheusにやらせよう――アプリケーションエンジニアのためのcustom metrics入門

f:id:LIFULL-shimay:20220216154315p:plain

エンジニアの島です。AI戦略室でバックエンドシステムの開発をしています。

本記事ではPrometheusを利用して、独自のメトリクスを計測することで監視を効率よく行えることを紹介します。

背景

チームで作っているもの

LIFULLのAIチームでは、いくつかの機械学習プロダクトを本番運用しています。

2022年2月にAIホームズくんᴮᴱᵀᴬをリリースしました!(SPサイトのみです)

20220216150710 https://www.homes.co.jp/ai-homeskun/

また、3D間取りも2021年にリリースしています。

20220216150725 https://www.homes.co.jp/3dmadori/

その他には、LIFULL HOME'Sのレコメンド機能でも機械学習を活用しています。

https://www.homes.co.jp/chintai/tokyo/list/

それ以外の開発プロジェクトもいくつか進行中です!

社内共通基盤の活用

これらのプロダクトは社内共通基盤チームが開発したKEELという、 In-house PaaSとして各種機能を提供するKubernetesベースのアプリケーション実行基盤で動いています。

www.lifull.blog

KEELチームが開発しているコードジェネレータ(keelctl)によって、Production Readyなアラートが自動的に設定されます。

例えば下記が監視され、しきい値を検知すると通知されます。

  • サクセスレート低下
  • レスポンスタイム
  • CPU・メモリ使用量

www.lifull.blog

success rateやresponse timeなどの基本的な指標は、ダッシュボードで閲覧できます。また、それらの通知も生成されるため、基本的な指標の悪化に気付けます。

そしてKEELチームが運用するPrometheus,AlertManager,Grafanaといったソフトウェアからアラートの受け取り、収集したメトリクスを確認できます。

www.lifull.blog

アプリケーション開発者はこの仕組みを活用しながら、 DevOpsの考え方に従い、自分たちでアプリケーション固有のエラー対応や監視を行うことが出来ます。

開発したプロダクトが増えていくにつれ、運用コストも増えていくため、自動化できるところは自動化したいモチベーションがあります。

効果的な監視で得られるもの

問題の予兆に気付けるようになる

監視の恩恵としてここが一番大きいです。

本番サーバが突然落ちて、それにより割り込み対応や残業を余儀なくされるというのは、開発者体験として最悪ですよね。

バグの早期発見により対応コストが劇的に下がるのと同様、障害対応も早期解決・顕在化前の解決が最も効率的です。

適切に監視をすることで、サービス利用者への価値提供を継続できるだけでなく、あなたや同僚の時間を守る事にもつながります。



問題の原因特定につながる

custom metricsを作成することの恩恵はこちらになります。

問題が発生したときに、手がかりがないと調査から始めないといけません。

custom metricsが手がかりとなれば、問題を迅速に切り分けることができます。

仮に問題がなかったとしても、「問題はそこではない」という貴重な情報が得られます。

結果的に初動が早くなり、問題を迅速に解決できるでしょう。



時系列での傾向を把握できる

こちらはメトリクス値を蓄積することの恩恵になります。

通知を設定しなかったとしても、蓄積したデータを調べることで、システムの長期的な傾向を知ることができます。

  • リリースしてから、サーバのメモリは増加していないか
  • 依存サービスのタイムアウトは一時的なのか周期的なのか
  • catchして握りつぶしている例外の数は規定内に収まっているか
  • 機械学習スコアの傾向に変わりはないか

さまざまな情報を知ることで、サービス開発・運用に役立てることができます。

Prometheusとは

一言でいうとシステム状態の収集・可視化と監視ができるOSSです。

prometheus.io

元はCNCF(Cloud Native Computing Foundation)プロジェクトとして始まりました。

今ではAWSマネージドサービスも出ており、監視標準と言って良いでしょう。

aws.amazon.com

思想

Zen of Prometheusが分かりやすいので紹介します。(非公式サイトですが)

https://the-zen-of-prometheus.netlify.app/

3行でまとめると、

  • メトリクス取得は安価に行えるので、どんどん取得しよう。
  • ログを取ったり、可視化をしたりするのであれば、そのメトリクスを計測してアラートさせるように作っておこう。
  • やっかいな問題へと深刻化する前に、すぐ気付いて早期対処しよう。

といったところでしょうか

メトリクスの公開

Prometheus公式にて、いくつかのプログラミング言語用のライブラリがサポートされています。 こちらを利用するだけで、簡単に実装できます。

github.com

PythonのFastAPIフレームワークであれば、例えば以下のように記載するだけでデフォルトのメトリクスを公開できます。

import prometheus_client

...

@app.get('/my_prometheus_metrics')
def prometheus_metrics():
    return fastapi.responses.PlainTextResponse(
        prometheus_client.generate_latest()
    )



その上で設定したパス/my_prometheus_metricsにアクセスすると、計測しているメトリクスを次のようなプレーンテキストで取得できます。

# HELP process_start_time_seconds Start time of the process since unix epoch in seconds.
# TYPE process_start_time_seconds gauge
process_start_time_seconds 1.64446715949e+09
# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
# TYPE process_cpu_seconds_total counter
process_cpu_seconds_total 260.51

custom metricsをプログラム側で追加すると、このプレーンテキストに行が追加されていくことになります。

Prometheusが設定したエンドポイントをポーリングし、メトリクスを読み込みます。したがって追加されたcustom metricsも連携することができます。

custom metricsを追加しよう

利用方法もPrometheusのライブラリ側に書いてあるので、非常に親切です。

たとえば下記のように記載するとタイムアウトがどれくらい起きているかのメトリクスを追加できます。

※異なるアプリケーション間でのメトリクス名を明確に区別するために、プレフィックスを付けています。

PREFIX = 'your_awesome_app'
TIMEOUT_REDIS_COUNTER = prometheus_client.Counter(f'{PREFIX}_timeout_redis_counter', 'redis timeout counts')
try:
    # some redis execution
    ...
except redis.exceptions.TimeoutError:
    my_prometheus.TIMEOUT_REDIS_COUNTER.inc()



Prometheusで監視しよう

PrometheusではPromQLという記法で条件式を表現できます。

例えば下記のように割合を表現できます。入力から機械学習モデルのイレギュラー値の割合を、モデルに渡さない除外データの数を除外して計算しています。

これにより「有効データのうち、モデルが値を返せている割合」を監視できます。

(sum(increase(your_awesome_app_zero_score{app="your-awesome-app"}[10m])) - sum(increase(your_awesome_app_exclude{app="your-awesome-app"}[10m])))
/ (sum(increase(your_awesome_app_input_records{app="your-awesome-app"}[10m])) - sum(increase(your_awesome_app_exclude{app="your-awesome-app"}[10m]))) < 0.0025

このPromQLによる検知がPrometheusのAlertmanagerに渡され、事前に設定した通知設定でSlackに通知されます。

custom metricsで計測すると嬉しいもの

以下のように外部IOや、アプリケーションの内部状態を計測しています。

外部IOに関して

複数の外部IOに接続して、レスポンス低下が起こっている場合に、どこで問題が起きているかが特定できて便利です。

response time(histogramを利用)やnetwork timeout数を計測しています。

分散トレーシングに関してはJaegerが得意なので、そちらで可視化しても良いです。

Prometheusで取得することで、PromQLで他メトリクスと同じように扱えたり、アラート通知が行えたりとメリットがあるのでこちらで計測しています。



内部状態に関して

注視しておきたい値を計測しておくと、時系列で追えるので便利です。

外部起因ではないアプリケーションのエラーの数

単純なsuccess rateだと外部起因エラーと内部起因エラーが交じるため、分離して監視しています。

今の所、安定して値を返せています。このような安定した数値は手動確認だと見なくなる傾向があるため、自動監視の恩恵が大きいです。

有効データのうち、モデルが値を返せている割合

単純なsuccess rateだと異常値は0点スコアとして200 OKで返すため、このメトリクスを監視しています。

監視することでモデルや入力データの異常に気付くことができます。

こちらも同様に普段発生しないため、自動監視に任せています。

機械学習モデルのスコア(histogramを利用)

GrafanaでPromQLを記述し、Prometheusのメトリクスを可視化できます。

f:id:LIFULL-shimay:20220216184330p:plain
機械学習スコアの推移

こちらは問題が発生した場合の調査用に計測しています。

※スコア自体は、相対的な順序が正しければそれでよく、絶対的な数値で正常・異常を測ることができないと判断しています。

機械学習スコアの比率は、細かなブレはありますが長期で見て変動ないことを確認できます。

※年末年始に不動産会社がお休みのタイミングのみ微減しており、これは新鮮な物件広告の供給が途絶えていたためと考えられます。

モデルの継続的な品質担保は別の方法で行う必要があり、ABテストによるサイトのCTRやCVRを目視しています。

※これはPrometheusで監視していませんが、サイトパフォーマンスのデータは別系統で集計されているためです。 Google Analyticsで計測されたものを、Data Studioのダッシュボードに表示しています。

そのほか

こういうメトリクスを計測すると良いというものがあれば、ぜひブコメなどで教えてください!

終わりに

Prometheusのcustom metricsを計測して通知すると、監視を効率よく行えることを紹介しました。

問題がやっかいなものになる前に、早めの対処で良いサービスを提供していきましょう!

最後に宣伝

このようにバックエンドサービスの開発から共通基盤開発まで、さまざまな職種を募集しています!よろしければぜひこちらのページもご覧ください!

hrmos.co

カジュアル面談もお待ちしております!ぜひぜひどうぞ!

hrmos.co