Pythonの自動計装に関する問題のトラブルシューティング

インストールに関する問題

Python パッケージのインストール失敗

Pythonパッケージのインストールには gccgcc-c++ が必要で、CentOSのようなスリムバージョンのLinuxを使用している場合はインストールする必要があるかもしれません。

yum -y install python3-devel
yum -y install gcc-c++
apt install -y python3-dev
apt install -y build-essential
apk add python3-dev
apk add build-base

uv を使ったブートストラップ

uvパッケージマネージャを使用しているときに opentelemetry-bootstrap -a install を実行すると、依存関係の設定がエラーになったり、予期しない結果になったりすることがあります。

かわりに、OpenTelemetry 要件を動的に生成し、uv を使ってインストールできます。

まず、適切なパッケージをインストール(またはプロジェクトファイルに追加して uv sync を実行)します。

uv pip install opentelemetry-distro opentelemetry-exporter-otlp

これで、自動計装をインストールできます。

uv run opentelemetry-bootstrap -a requirements | uv pip install --requirement -

最後に、 uv run を使用してアプリケーションを起動します(エージェントの設定を参照してください)。

uv run opentelemetry-instrument python myapp.py

uv sync を実行したり、既存のパッケージを更新したりするたびに、自動計装を再インストールする必要があることに注意してください。 そのため、ビルドパイプラインの一部としてインストールを行うことを推奨します。

計装の問題

リローダによる Flask デバッグモードが計装を壊す

デバッグモードは、Flaskアプリで次のように有効にできます。

if __name__ == "__main__":
    app.run(port=8082, debug=True)

デバッグモードはリローダを有効にするため、計装を中断させることがあります。 デバッグモードが有効なときに計装を実行するには、 use_reloader オプションを False に設定します。

if __name__ == "__main__":
    app.run(port=8082, debug=True, use_reloader=False)

プリフォークサーバーの問題

複数のワーカーを持つGunicornのようなプリフォークサーバーは、次のように実行できます。

gunicorn myapp.main:app --workers 4

ただし、複数の --workers を指定すると、自動計装を適用した場合にメトリクスの生成が壊れる可能性があります。 これは、ワーカー/子プロセスの作成であるフォークが、バックグラウンドスレッドとOpenTelemetry SDKの主要なコンポーネントが想定しているロックとの間に、各子プロセス間で不整合を生じさせるためです。 具体的には、PeriodicExportingMetricReader は、データをエクスポーターに定期的にフラッシュするための独自のスレッドを生成します。 イシュー#2767 および #3307 も参照してください。 フォーク後、各子プロセスは実際には実行されていないメモリ内のスレッドオブジェクトを探し、元のロックは各子プロセスでアンロックされない可能性があります。 Python issue 6721 で説明されているフォークとデッドロックも参照してください。

回避策

OpenTelemetryでプリフォークサーバーを使用するためのいくつかの回避策があります。 次の表は、複数のワーカーでプリフォークされた、さまざまな自動計装Webサーバーゲートウェイスタックによるシグナルエクスポートの現在のサポートをまとめています。 詳細とオプションについては、以下を参照してください。

複数ワーカーのスタックトレースメトリクスログ
Uvicornxx
Gunicornxx
Gunicorn + UvicornWorkerxxx
GunicornとUvicornWorkerでデプロイ

複数のワーカーを持つサーバーを自動計装するには、非同期サーバーゲートウェイインターフェース(ASGI)アプリ(FastAPI、Starletteなど)の場合、uvicorn.workers.UvicornWorker を使ったGunicornによるデプロイが推奨されます。 UvicornWorkerクラスは、バックグラウンドプロセスとスレッドを保持しながらフォークを処理するように特別に設計されています。 例を挙げましょう。

opentelemetry-instrument gunicorn \
  --workers 4 \
  --worker-class uvicorn.workers.UvicornWorker \
  --bind 0.0.0.0:8000 \
  myapp.main:app
プログラム自動計装の使用

opentelemetry-instrument のかわりに、サーバーフォーク後のワーカープロセス内でプログラム自動計装を使用してOpenTelemetryを初期化します。 例を挙げましょう。

from opentelemetry.instrumentation.auto_instrumentation import initialize
initialize()

from your_app import app

FastAPIを使用している場合、計装がパッチされる方法により、FastAPI をインポートする前に initialize() を呼び出す必要があることに注意してください。 例を挙げましょう。

from opentelemetry.instrumentation.auto_instrumentation import initialize
initialize()

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}

その後、次のコマンドでサーバーを実行します。

uvicorn main:app --workers 2
PrometheusでOTLPを直接使用

OTLP メトリクスを直接受信するために、Prometheus の最新バージョンの使用を検討してください。 PeriodicExportingMetricReader とプロセスごとに1つのOTLPワーカーを設定して、Prometheusサーバーにプッシュします。 フォークでの PrometheusMetricReader の使用は推奨しません。 イシュー#3747 を参照してください。

単一ワーカーの使用

または、ゼロコード計装でプリフォークで単一ワーカーを使用します。

opentelemetry-instrument gunicorn your_app:app --workers 1

接続性の問題

gRPCコネクティビティ

Python gRPC接続の問題をデバッグするには、以下のgRPCデバッグ環境変数を設定します。

export GRPC_VERBOSITY=debug
export GRPC_TRACE=http,call_error,connectivity_state
opentelemetry-instrument python YOUR_APP.py