これは、なにをしたくて書いたもの?
Grafana Tempoにトレースシグナルを送信しようとPythonで簡単なアプリケーションを作成したら、
OpenTelemetry計装ライブラリーの導入方法でちょっと苦労したのでちゃんと見てみようということで…。
Grafana Tempo 2.8+MinIO+GrafanaをUbuntu Linux 24.04 LTSにインストールして、トレースデータを見てみる - CLOVER🍀
特にuvと組み合わせた時にハマったので…。
OpenTelemetryのPython APIとSDK
OpenTelemetryのPython APIとSDKに関するドキュメントはこちらです。
一方で、ゼロコード計装と呼ばれるものについてのドキュメントはこちらです。
Python zero-code instrumentation | OpenTelemetry
基本的にはゼロコード計装に焦点を当てていこうと思います。
まず、Getting Startedの計装のインストールですが、opentelemetry-distroというパッケージをインストールして
opentelemetry-bootstrap -a installコマンドを実行しています。
$ pip install opentelemetry-distro $ opentelemetry-bootstrap -a install
Getting Started / Instrumentation
これ、なんでしょうね?
このページではFlaskに対する計装ライブラリーの話をしているようですが、これでFlaskの計装ライブラリーがインストール
されると書かれています。
This will install Flask instrumentation.
そして、アプリケーションはopentelemetry-instrumentコマンド経由で実行するようです。
$ opentelemetry-instrument \
--traces_exporter console \
--metrics_exporter console \
--logs_exporter console \
--service_name dice-server \
flask run -p 8080
OpenTelemetry Protocolで送信する場合は、opentelemetry-exporter-otlpというライブラリーが必要になります。
$ pip install opentelemetry-exporter-otlp
Getting Started / Send telemetry to an OpenTelemetry Collector
まあ、これはいいでしょう、と。
各ライブラリー向けには、opentelemetry-instrumentation-[ライブラリー名]で計装ライブラリーがあります。
$ pip install opentelemetry-instrumentation-{instrumented-library}
Using instrumentation libraries / Setup
計装ライブラリーはこちらですね。
https://github.com/open-telemetry/opentelemetry-python-contrib/tree/v0.57b0/instrumentation
ドキュメントはこちらになるようです。
OpenTelemetry-Python-Contrib — OpenTelemetry Python Contrib documentation
よくわからないのがこのあたりですね。
$ pip install opentelemetry-distro $ opentelemetry-bootstrap -a install
OpenTelemetry Distroを見てみる
opentelemetry-distroはユーザーがよく使うオプションの一部を自動設定するものだそうです。
In order to make using OpenTelemetry and auto-instrumentation as quick as possible without sacrificing flexibility, OpenTelemetry distros provide a mechanism to automatically configure some of the more common options for users.
OpenTelemetry Distro | OpenTelemetry
ソースコードを見たところでは、こういうところでしょうか…?
# pylint: disable=no-self-use
def _configure(self, **kwargs):
os.environ.setdefault(OTEL_TRACES_EXPORTER, "otlp")
os.environ.setdefault(OTEL_METRICS_EXPORTER, "otlp")
os.environ.setdefault(OTEL_LOGS_EXPORTER, "otlp")
os.environ.setdefault(OTEL_EXPORTER_OTLP_PROTOCOL, "grpc")
実際に使うのはこちらのようなので、このスクリプトを見てみましょう。
$ opentelemetry-bootstrap -a install
こういう環境で
$ python3 --version Python 3.12.3 $ pip3 --version pip 24.0 from /usr/lib/python3/dist-packages/pip (python 3.12)
仮想環境を作成してインストール。
$ python3 -m venv .venv $ . .venv/bin/activate $ pip3 install opentelemetry-distro $ pip3 list Package Version ---------------------------------- ------- importlib_metadata 8.7.0 opentelemetry-api 1.36.0 opentelemetry-distro 0.57b0 opentelemetry-instrumentation 0.57b0 opentelemetry-sdk 1.36.0 opentelemetry-semantic-conventions 0.57b0 packaging 25.0 pip 24.0 typing_extensions 4.14.1 wrapt 1.17.2 zipp 3.23.0
スクリプトの中身はこんな感じでした。
$ cat $(which opentelemetry-bootstrap)
#!/path/to/.venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from opentelemetry.instrumentation.bootstrap import run
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(run())
つまり、こちらですね。
どうやらinstallとrequirementsというアクションがあるようです。これが-aで指定しているアクションですね。
デフォルトはrequirementsのようです。
試しにFastAPIをインストールしてみましょう。
$ pip3 install 'fastapi[standard]'
opentelemetry-bootstrapコマンドを実行すると、こういう結果になります。
$ opentelemetry-bootstrap opentelemetry-instrumentation-asyncio==0.57b0 opentelemetry-instrumentation-dbapi==0.57b0 opentelemetry-instrumentation-logging==0.57b0 opentelemetry-instrumentation-sqlite3==0.57b0 opentelemetry-instrumentation-threading==0.57b0 opentelemetry-instrumentation-urllib==0.57b0 opentelemetry-instrumentation-wsgi==0.57b0 opentelemetry-instrumentation-click==0.57b0 opentelemetry-instrumentation-fastapi==0.57b0 opentelemetry-instrumentation-httpx==0.57b0 opentelemetry-instrumentation-jinja2==0.57b0 opentelemetry-instrumentation-starlette==0.57b0 opentelemetry-instrumentation-tortoiseorm==0.57b0 opentelemetry-instrumentation-urllib3==0.57b0
現在のpipでインストールしているライブラリーから、必要な計装ライブラリーを選んでいるようです。
ちなみに、こちらでも同じです。
$ opentelemetry-bootstrap -a requirements
なので、この結果をインストールするのがこちらのスクリプト、というわけですね。
$ opentelemetry-bootstrap -a install
プロジェクトにインストールされているライブラリーの確認は、こちらのスクリプト経由で
Pythonの標準ライブラリーで参照しているようです。
importlib.metadata -- パッケージメタデータへのアクセス — Python 3.12.12 ドキュメント
opentelemetry-instrumentコマンドは?
それから、アプリケーションを起動する時にはopentelemetry-instrumentコマンド経由になっていましたね。
$ opentelemetry-instrument \
--traces_exporter console \
--metrics_exporter console \
--logs_exporter console \
--service_name dice-server \
flask run -p 8080
これはなんでしょう?
OpenTelemetry Distroをインストールすると使えるようになっているので、確認してみます。
$ cat $(which opentelemetry-instrument)
#!/path/to/.venv/bin/python3
# -*- coding: utf-8 -*-
import re
import sys
from opentelemetry.instrumentation.auto_instrumentation import run
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(run())
実体はこのスクリプトのようですね。
スクリプトではrun関数を呼び出しているだけですが、実際のセットアップはinitialize関数で行われます。
initialize関数がどうやって呼び出されるかというと、以下のスクリプトですね。
これはこちらの仕組みを利用しているようです。
site --- サイト固有の設定フック — Python 3.12.12 ドキュメント
なんとなく、ここまでの流れはわかった感じです。
uvとの組み合わせ
ところでuvでハマったということを書きましたが、ドキュメントにトラブルシュートの方法が載っているくらいです。
Troubleshooting Python automatic instrumentation issues / Installation issues / Bootstrap using uv
少し試してみましょう。uvでFastAPIとopentelemetry-distroをインストール。
$ uv add 'fastapi[standard]' $ uv add opentelemetry-distro
そしてopentelemetry-bootstrap -a installを実行すると、pip installに失敗することになります。
$ uv run opentelemetry-bootstrap -a install /path/to/.venv/bin/python3: No module named pip Command '['/path/to/.venv/bin/python3', '-m', 'pip', 'install', '-U', '--upgrade-strategy', 'only-if-needed', 'opentelemetry-instrumentation-asyncio==0.57b0']' returned non-zero exit status 1. /path/to/.venv/bin/python3: No module named pip Command '['/path/to/.venv/bin/python3', '-m', 'pip', 'install', '-U', '--upgrade-strategy', 'only-if-needed', 'opentelemetry-instrumentation-dbapi==0.57b0']' returned non-zero exit status 1. /path/to/.venv/bin/python3: No module named pip Command '['/path/to/.venv/bin/python3', '-m', 'pip', 'install', '-U', '--upgrade-strategy', 'only-if-needed', 'opentelemetry-instrumentation-logging==0.57b0']' returned non-zero exit status 1. /path/to/.venv/bin/python3: No module named pip Command '['/path/to/.venv/bin/python3', '-m', 'pip', 'install', '-U', '--upgrade-strategy', 'only-if-needed', 'opentelemetry-instrumentation-sqlite3==0.57b0']' returned non-zero exit status 1. /path/to/.venv/bin/python3: No module named pip Command '['/path/to/.venv/bin/python3', '-m', 'pip', 'install', '-U', '--upgrade-strategy', 'only-if-needed', 'opentelemetry-instrumentation-threading==0.57b0']' returned non-zero exit status 1. /path/to/.venv/bin/python3: No module named pip Command '['/path/to/.venv/bin/python3', '-m', 'pip', 'install', '-U', '--upgrade-strategy', 'only-if-needed', 'opentelemetry-instrumentation-urllib==0.57b0']' returned non-zero exit status 1. /path/to/.venv/bin/python3: No module named pip Command '['/path/to/.venv/bin/python3', '-m', 'pip', 'install', '-U', '--upgrade-strategy', 'only-if-needed', 'opentelemetry-instrumentation-wsgi==0.57b0']' returned non-zero exit status 1. /path/to/.venv/bin/python3: No module named pip Command '['/path/to/.venv/bin/python3', '-m', 'pip', 'install', '-U', '--upgrade-strategy', 'only-if-needed', 'opentelemetry-instrumentation-click==0.57b0']' returned non-zero exit status 1. /path/to/.venv/bin/python3: No module named pip Command '['/path/to/.venv/bin/python3', '-m', 'pip', 'install', '-U', '--upgrade-strategy', 'only-if-needed', 'opentelemetry-instrumentation-fastapi==0.57b0']' returned non-zero exit status 1. /path/to/.venv/bin/python3: No module named pip Command '['/path/to/.venv/bin/python3', '-m', 'pip', 'install', '-U', '--upgrade-strategy', 'only-if-needed', 'opentelemetry-instrumentation-httpx==0.57b0']' returned non-zero exit status 1. /path/to/.venv/bin/python3: No module named pip Command '['/path/to/.venv/bin/python3', '-m', 'pip', 'install', '-U', '--upgrade-strategy', 'only-if-needed', 'opentelemetry-instrumentation-jinja2==0.57b0']' returned non-zero exit status 1. /path/to/.venv/bin/python3: No module named pip Command '['/path/to/.venv/bin/python3', '-m', 'pip', 'install', '-U', '--upgrade-strategy', 'only-if-needed', 'opentelemetry-instrumentation-starlette==0.57b0']' returned non-zero exit status 1. /path/to/.venv/bin/python3: No module named pip Command '['/path/to/.venv/bin/python3', '-m', 'pip', 'install', '-U', '--upgrade-strategy', 'only-if-needed', 'opentelemetry-instrumentation-tortoiseorm==0.57b0']' returned non-zero exit status 1. /path/to/.venv/bin/python3: No module named pip Command '['/path/to/.venv/bin/python3', '-m', 'pip', 'install', '-U', '--upgrade-strategy', 'only-if-needed', 'opentelemetry-instrumentation-urllib3==0.57b0']' returned non-zero exit status 1. /path/to/.venv/bin/python3: No module named pip
よって、回避方法としてはこうしていたわけですね。
$ uv run opentelemetry-bootstrap -a requirements | uv pip install --requirement -
ただ、これだとpyproject.tomlでの管理からは外れるんですよね…。uv.lockにも載りません。
なので、注意事項としてライブラリーを更新した場合は計装ライブラリーを再インストール、つまり回避方法に記載されている
コマンドを実行することが書かれています。
Please note that you have to reinstall the auto instrumentation every time you run uv sync or update existing packages. It is therefore recommended to make the installation part of your build pipeline.
どうなんでしょうね、以下のコマンドではダメなのでしょうか?
$ uv run opentelemetry-bootstrap -a requirements | xargs uv add
uvで管理すること自体がダメなのかがよくわかりません。
もとのissueを見ると、インストールが失敗するだけのようですが…?
それでは、だいたい確認できたので少し動かしてみましょう。
お題
FastAPIを使った簡単なアプリケーションにOpenTelemetry計装ライブラリーを組み込んで、メトリクスを送信してみます。
こういう感じにしましょう。
flowchart LR
A["FastAPI"] -- OTLP over http/protobuf --> B["OpenTelemetry Collector"]
B -- Remote Write --> C["Prometheus"]
ソースコードはこちらにしましょう。
OpenTelemetry FastAPI Instrumentation — OpenTelemetry Python Contrib documentation
またpipとuvの2種類で試してみます。
環境
今回の環境はこちらです。
$ python3 --version Python 3.12.3 $ pip3 --version pip 24.0 from /usr/lib/python3/dist-packages/pip (python 3.12) $ uv --version uv 0.8.8
OpenTelemetry Collector Contrib。172.18.0.2で動作しているものとします。
$ otelcol-contrib --version otelcol-contrib version 0.131.1
Prometheus。172.18.0.3で動作しているものとします。
$ ./prometheus --version prometheus, version 3.5.0 (branch: HEAD, revision: 8be3a9560fbdd18a94dedec4b747c35178177202) build user: root@4451b64cb451 build date: 20250714-16:15:23 go version: go1.24.5 platform: linux/amd64 tags: netgo,builtinassets
またPrometheusはリモート書き込みを有効にして起動しているものとします。
$ ./prometheus --web.enable-remote-write-receiver
準備
OpenTelemetry Collector Contribの設定。
/etc/otelcol-contrib/config.yaml
receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 processors: batch: exporters: prometheusremotewrite: endpoint: "http://172.18.0.3:9090/api/v1/write" resource_to_telemetry_conversion: enabled: true service: pipelines: metrics: receivers: [otlp] processors: [batch] exporters: [prometheusremotewrite]
Prometheusの設定。
prometheus.yml
global: scrape_interval: 15s evaluation_interval: 15s scrape_configs:
Prometheusはスクレイピング対象なしです。
pipで試す
最初はpipで試してみます。
$ mkdir instrument-fastapi-pip $ cd instrument-fastapi-pip $ python3 -m venv .venv $ . .venv/bin/activate
FastAPIとOpenTelemetry Distro、Exporterのインストール。
$ pip3 install 'fastapi[standard]' $ pip3 install opentelemetry-distro opentelemetry-exporter-otlp
計装ライブラリーをインストール。
$ opentelemetry-bootstrap -a install
インストールされたライブラリーの一覧。
$ pip3 list Package Version ----------------------------------------- -------- annotated-types 0.7.0 anyio 4.10.0 asgiref 3.9.1 certifi 2025.8.3 charset-normalizer 3.4.3 click 8.2.1 dnspython 2.7.0 email_validator 2.2.0 fastapi 0.116.1 fastapi-cli 0.0.8 fastapi-cloud-cli 0.1.5 googleapis-common-protos 1.70.0 grpcio 1.74.0 h11 0.16.0 httpcore 1.0.9 httptools 0.6.4 httpx 0.28.1 idna 3.10 importlib_metadata 8.7.0 Jinja2 3.1.6 markdown-it-py 3.0.0 MarkupSafe 3.0.2 mdurl 0.1.2 opentelemetry-api 1.36.0 opentelemetry-distro 0.57b0 opentelemetry-exporter-otlp 1.36.0 opentelemetry-exporter-otlp-proto-common 1.36.0 opentelemetry-exporter-otlp-proto-grpc 1.36.0 opentelemetry-exporter-otlp-proto-http 1.36.0 opentelemetry-instrumentation 0.57b0 opentelemetry-instrumentation-asgi 0.57b0 opentelemetry-instrumentation-asyncio 0.57b0 opentelemetry-instrumentation-click 0.57b0 opentelemetry-instrumentation-dbapi 0.57b0 opentelemetry-instrumentation-fastapi 0.57b0 opentelemetry-instrumentation-grpc 0.57b0 opentelemetry-instrumentation-httpx 0.57b0 opentelemetry-instrumentation-jinja2 0.57b0 opentelemetry-instrumentation-logging 0.57b0 opentelemetry-instrumentation-requests 0.57b0 opentelemetry-instrumentation-sqlite3 0.57b0 opentelemetry-instrumentation-starlette 0.57b0 opentelemetry-instrumentation-threading 0.57b0 opentelemetry-instrumentation-tortoiseorm 0.57b0 opentelemetry-instrumentation-urllib 0.57b0 opentelemetry-instrumentation-urllib3 0.57b0 opentelemetry-instrumentation-wsgi 0.57b0 opentelemetry-proto 1.36.0 opentelemetry-sdk 1.36.0 opentelemetry-semantic-conventions 0.57b0 opentelemetry-util-http 0.57b0 packaging 25.0 pip 24.0 protobuf 6.31.1 pydantic 2.11.7 pydantic_core 2.33.2 Pygments 2.19.2 python-dotenv 1.1.1 python-multipart 0.0.20 PyYAML 6.0.2 requests 2.32.4 rich 14.1.0 rich-toolkit 0.14.9 rignore 0.6.4 sentry-sdk 2.34.1 shellingham 1.5.4 sniffio 1.3.1 starlette 0.47.2 typer 0.16.0 typing_extensions 4.14.1 typing-inspection 0.4.1 urllib3 2.5.0 uvicorn 0.35.0 uvloop 0.21.0 watchfiles 1.1.0 websockets 15.0.1 wrapt 1.17.2 zipp 3.23.0
スクリプトを作成。
app.py
import fastapi from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor app = fastapi.FastAPI() @app.get("/foobar") async def foobar(): return {"message": "hello world"} FastAPIInstrumentor.instrument_app(app)
※ opentelemetry-instrument経由で使うのであれば、FastAPIInstrumentorは使わなくてもよかったです…
Pythonアプリケーションに対して、opentelemetry-instrumentを使わずにOpenTelemetryのゼロ計装を行う - CLOVER🍀
起動して
$ fastapi run app.py
動作確認。
$ curl localhost:8000/foobar
{"message":"hello world"}
OKですね。
OpenTelemetryに関する環境変数を設定。
$ export OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true $ export OTEL_TRACES_EXPORTER=none $ export OTEL_METRICS_EXPORTER=otlp $ export OTEL_LOGS_EXPORTER=none $ export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://172.18.0.2:4318/v1/metrics $ export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http/protobuf $ export OTEL_SERVICE_NAME=app
opentelemetry-instrument越しに起動。
$ opentelemetry-instrument fastapi run app.py
あとはリクエストを送り続けて
$ curl localhost:8000/foobar
{"message":"hello world"}
Prometheus側を見ると、メトリクスが送信されていることが確認できます。

uvで試す
次はuvで試してみましょう。
$ uv init --vcs none instrument-fastapi-uv $ cd instrument-fastapi-uv
ライブラリーをインストール。
$ uv add 'fastapi[standard]' $ uv add opentelemetry-exporter-otlp $ uv add --dev opentelemetry-distro
opentelemetry-distroは、開発用パッケージではないのかなと思います。
※違ったかもしれません…
計装ライブラリーをインストールしてみましょう。
$ uv run opentelemetry-bootstrap -a requirements | xargs uv add
pyproject.tomlはこうなりました。
pyproject.toml
[project] name = "instrument-fastapi-uv" version = "0.1.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.12" dependencies = [ "fastapi[standard]>=0.116.1", "opentelemetry-exporter-otlp>=1.36.0", "opentelemetry-instrumentation-asyncio==0.57b0", "opentelemetry-instrumentation-click==0.57b0", "opentelemetry-instrumentation-dbapi==0.57b0", "opentelemetry-instrumentation-fastapi==0.57b0", "opentelemetry-instrumentation-grpc==0.57b0", "opentelemetry-instrumentation-httpx==0.57b0", "opentelemetry-instrumentation-jinja2==0.57b0", "opentelemetry-instrumentation-logging==0.57b0", "opentelemetry-instrumentation-requests==0.57b0", "opentelemetry-instrumentation-sqlite3==0.57b0", "opentelemetry-instrumentation-starlette==0.57b0", "opentelemetry-instrumentation-threading==0.57b0", "opentelemetry-instrumentation-tortoiseorm==0.57b0", "opentelemetry-instrumentation-urllib==0.57b0", "opentelemetry-instrumentation-urllib3==0.57b0", "opentelemetry-instrumentation-wsgi==0.57b0", ] [dependency-groups] dev = [ "opentelemetry-distro>=0.57b0", ]
インストールされたライブラリーの一覧。
$ uv pip list Package Version ----------------------------------------- -------- annotated-types 0.7.0 anyio 4.10.0 asgiref 3.9.1 certifi 2025.8.3 charset-normalizer 3.4.3 click 8.2.1 dnspython 2.7.0 email-validator 2.2.0 fastapi 0.116.1 fastapi-cli 0.0.8 fastapi-cloud-cli 0.1.5 googleapis-common-protos 1.70.0 grpcio 1.74.0 h11 0.16.0 httpcore 1.0.9 httptools 0.6.4 httpx 0.28.1 idna 3.10 importlib-metadata 8.7.0 jinja2 3.1.6 markdown-it-py 3.0.0 markupsafe 3.0.2 mdurl 0.1.2 opentelemetry-api 1.36.0 opentelemetry-distro 0.57b0 opentelemetry-exporter-otlp 1.36.0 opentelemetry-exporter-otlp-proto-common 1.36.0 opentelemetry-exporter-otlp-proto-grpc 1.36.0 opentelemetry-exporter-otlp-proto-http 1.36.0 opentelemetry-instrumentation 0.57b0 opentelemetry-instrumentation-asgi 0.57b0 opentelemetry-instrumentation-asyncio 0.57b0 opentelemetry-instrumentation-click 0.57b0 opentelemetry-instrumentation-dbapi 0.57b0 opentelemetry-instrumentation-fastapi 0.57b0 opentelemetry-instrumentation-grpc 0.57b0 opentelemetry-instrumentation-httpx 0.57b0 opentelemetry-instrumentation-jinja2 0.57b0 opentelemetry-instrumentation-logging 0.57b0 opentelemetry-instrumentation-requests 0.57b0 opentelemetry-instrumentation-sqlite3 0.57b0 opentelemetry-instrumentation-starlette 0.57b0 opentelemetry-instrumentation-threading 0.57b0 opentelemetry-instrumentation-tortoiseorm 0.57b0 opentelemetry-instrumentation-urllib 0.57b0 opentelemetry-instrumentation-urllib3 0.57b0 opentelemetry-instrumentation-wsgi 0.57b0 opentelemetry-proto 1.36.0 opentelemetry-sdk 1.36.0 opentelemetry-semantic-conventions 0.57b0 opentelemetry-util-http 0.57b0 packaging 25.0 protobuf 6.31.1 pydantic 2.11.7 pydantic-core 2.33.2 pygments 2.19.2 python-dotenv 1.1.1 python-multipart 0.0.20 pyyaml 6.0.2 requests 2.32.4 rich 14.1.0 rich-toolkit 0.14.9 rignore 0.6.4 sentry-sdk 2.34.1 shellingham 1.5.4 sniffio 1.3.1 starlette 0.47.2 typer 0.16.0 typing-extensions 4.14.1 typing-inspection 0.4.1 urllib3 2.5.0 uvicorn 0.35.0 uvloop 0.21.0 watchfiles 1.1.0 websockets 15.0.1 wrapt 1.17.2 zipp 3.23.0
スクリプトは、ファイル名が変わりました…。
main.py
import fastapi from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor app = fastapi.FastAPI() @app.get("/foobar") async def foobar(): return {"message": "hello world"} FastAPIInstrumentor.instrument_app(app)
※ opentelemetry-instrument経由で使うのであれば、FastAPIInstrumentorは使わなくてもよかったです…
Pythonアプリケーションに対して、opentelemetry-instrumentを使わずにOpenTelemetryのゼロ計装を行う - CLOVER🍀
あとは環境変数を設定して
$ export OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true $ export OTEL_TRACES_EXPORTER=none $ export OTEL_METRICS_EXPORTER=otlp $ export OTEL_LOGS_EXPORTER=none $ export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://172.18.0.2:4318/v1/metrics $ export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http/protobuf $ export OTEL_SERVICE_NAME=app
opentelemetry-instrument越しに起動。
$ uv run opentelemetry-instrument fastapi run main.py
リクエストを送り続けて
$ curl localhost:8000/foobar
{"message":"hello world"}
Prometheusで確認。

OKですね。
おわりに
PythonのOpenTelemetry計装ライブラリーの導入方法がよくわからなかったので、pipとuvを使ってFastAPIで試してみました。
OpenTelemetryの計装ライブラリーは前にJavaとNode.jsを見たのですが、PythonはPythonでだいぶ雰囲気が違いますね…。
最初はよくわからなかったのですが、ひとつひとつ紐解くとやっていることがなんとなくわかった気がします。それから、
知らないPythonの標準ライブラリーもいろいろと出てきましたし。
どちらにしても、これでPythonでOpenTelemetryの計装ライブラリーを扱えそうです。