Python: OpenTelemetryでHit and Blowの処理をトレース
PR

Python: OpenTelemetryでHit and Blowの処理をトレース

Hit and Blowを分散トレーシング ソフトウェア
記事内に広告が含まれています。
スポンサーリンク

プログラムを組んでいると、「遅いな?でもどこが?」ということが起きてきます。「推測するな、測定せよ」という言葉の通り、ちゃんと遅い部分を見つけだしてから対処する必要があります。

ネットワーク経由でAPI呼び出しをしていたりするので、プロファイラーではなく分散トレーシングの方がいいでしょう。自分の処理はシロだったりすることもあります。

今回、Hit and Blowに分散トレーシングを組み込んでみました。ネットワーク経由の処理はないので、ちょっとオーバースペックかもしれませんが、練習ということで。

スポンサーリンク
スポンサーリンク

AWS X-Rayも分散トレーシング

以前、やっていました。

今回はOpenTelemetryを使います。「APIとか、ベンダーニュートラルだったらアプリ直さずにトレースのサービス切りかえられるよね?」ってことなのかと。

分散トレーシングで出てくる基礎知識や単語は、このスライドがまとまっています。

スポンサーリンク

Jaegerでトレースデータを見る

先に出口、データを見る部分をどうするか、決めてしまいます。
お試しなのでX-RayやCloud Traceといった有料サービスはパス。手元のPCで簡単に動かせるものを…ということで、Jaeger All in Oneを使います。コンテナ1個でOK。

OpenTelemetry?Jaeger?混乱しそうですが、JaegerはOpenTelemetryの情報を受け付けます。
ですので、プログラムのトレース情報をOpenTelemetryで取得して、その情報をJaeger All in Oneに送るようにします。そうすれば、どのタイミングでどんな順番で処理しているのか、わかりやすくグラフ表示されます。

All in Oneの公式サイトにオプションが載っていますが、今回はOpenTelemetryの情報を受け付けられるようにするので、

docker run -d --name jaeger \
  -e COLLECTOR_OTLP_ENABLED=true \
  -p 5778:5778 \
  -p 16686:16686 \
  -p 4317:4317 \
  -p 4318:4318 \
  -p 14269:14269 \
  jaegertracing/all-in-one:1.38

として立ち上げます。 http://localhost:16686/ にアクセスすると、Jaegerの画面が出てきます。

スポンサーリンク

Auto Instrumentationsで半自動的にOpenTelemetryを導入

Auto Instrumentationsはおすすめの導入方法らしいです。が、ライブラリにパッチを当てるので、サポートしていないライブラリとか、自分で書いたコードの部分とかは見れないです。見れないというか、呼び出しを別のスパンに分けることができないです。

今回はお試しなので、Auto Instrumentationsで導入してみます。

Flaskアプリケーションの起動方法

Flaskアプリケーションの起動方法にもお作法があるようで、flask runとして起動しないと、トレースできないようです。

ということで、既にDocker化していたコードに対する差分がこれ。Dockerfileの修正の他、OpenTelemetry関連のライブラリをrequirements.txtに追加しています。

diff --git a/Dockerfile b/Dockerfile 
index 20cb606..a3b9199 100644 
--- a/Dockerfile 
+++ b/Dockerfile 
@@ -2,7 +2,10 @@ FROM python:3.10-slim 
 COPY templates/ /app/templates/ 
 COPY main.py requirements.txt /app/ 
-RUN pip install -r /app/requirements.txt 
+RUN pip install -r /app/requirements.txt && \^M 
+    opentelemetry-bootstrap -a install^M 
 EXPOSE 5000 
-CMD ["python3", "/app/main.py"] 
+ENV FLASK_APP app.main.py^M 
+CMD opentelemetry-instrument --traces_exporter otlp --metrics_exporter console \^M 
+    --service_name hit-and-blow --exporter_otlp_protocol grpc flask run --host=0.0.0.0^M 
diff --git a/requirements.txt b/requirements.txt 
index 946ad91..7448eaa 100644 
--- a/requirements.txt 
+++ b/requirements.txt 
@@ -1 +1,3 @@ 
 Flask==2.1.0 
+opentelemetry-distro 
+opentelemetry-exporter-otlp

Pythonのアプリケーション(main.py)には変更がないのがポイントですね。DockerfileのCMDの部分はsh経由で起動することになってしまうので、要改善ではあるのですが、力尽きました。
コード全体はGitHubにあります。

これでbuildして、起動する時はこんな感じ。

docker run -p 5000:5000 -e OTEL_EXPORTER_OTLP_ENDPOINT=http://172.17.0.2:4317 -e OTEL_EXPORTER_OTLP_TRACE_INSECURE=true hit-and-blow_otel

172.17.0.2はJaeger All in Oneのコンテナに割り当てられたIPアドレスです。環境によってIPアドレスが異なる可能性があるので、コンテナ起動時に環境変数として渡しています。

トレースする

Hit and Blowで少し遊んでからJagerの画面を見ると、トレースがでています。※serviceからhit and blowを選んでください。

jinja2の処理時間が長いように見えますが、そもそも全体の処理時間が短いので気にしなくてよいでしょう。

内部の処理をスパンとして切り出したいのであれば、自分でOpenTrace用のコードを追加する必要があります。このページが参考になります。

OpenTelemetryの中立性とポータビリティ

分散トレーシングを行おうとすると、スパンの設定など、本来なすべき処理以外のコードがアプリケーションに入ってしまいます。これがベンダー依存だと、ベンダーを変更するためにアプリケーションを変更するという、嬉しくない事態が発生します。

OpenTelemetryを使用することで、こういったことを大幅に減少できるのではないでしょうか。トレーシングだけでなく、メトリクスやロギングについても期待しています。

スポンサーリンク
ソフトウェア
スポンサーリンク
タイトルとURLをコピーしました