- 重要な情報
- はじめに
- 用語集
- ガイド
- エージェント
- インテグレーション
- OpenTelemetry
- 開発者
- API
- CoScreen
- アプリ内
- Service Management
- インフラストラクチャー
- アプリケーションパフォーマンス
- 継続的インテグレーション
- ログ管理
- セキュリティ
- UX モニタリング
- 管理
このチュートリアルでは、コンテナにインストールされたサンプル Python アプリケーションでトレースを有効にするための手順を説明します。このシナリオでは、Datadog Agent はコンテナにもインストールされています。
ホスト上のアプリケーションと Agent、ホスト上のコンテナと Agent のアプリケーション、他の言語で書かれたアプリケーションなど、その他のシナリオについては、その他のトレース有効化のチュートリアルを参照してください。
Python の一般的なトレース設定ドキュメントについては、Python アプリケーションのトレースを参照してください。
このチュートリアルのコードサンプルは、GitHub の github.com/Datadog/apm-tutorial-python にあります。まずは、このリポジトリを複製してください。
git clone https://github.com/DataDog/apm-tutorial-python.git
このリポジトリには、Docker コンテナ内で実行できるようにあらかじめ構成されたマルチサービスの Python アプリケーションが含まれています。サンプルアプリは、データの追加や変更を行うための REST API を備えた基本的なノートアプリです。
以下を実行することでアプリケーションのコンテナを構築します。
docker-compose -f docker/containers/exercise/docker-compose.yaml build notes_app
コンテナを起動します。
docker-compose -f docker/containers/exercise/docker-compose.yaml up db notes_app
ターミナルに次のような出力が表示されたら、アプリケーションの使用準備は完了です。
notes | * Debug mode: on
notes | INFO:werkzeug:WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
notes | * Running on all addresses (0.0.0.0)
notes | * Running on http://127.0.0.1:8080
notes | * Running on http://192.168.32.3:8080
notes | INFO:werkzeug:Press CTRL+C to quit
notes | INFO:werkzeug: * Restarting with stat
notes | WARNING:werkzeug: * Debugger is active!
notes | INFO:werkzeug: * Debugger PIN: 143-375-699
また、docker ps
コマンドで実行中のコンテナを表示することで、実行されていることを確認することができます。
別のターミナルを開いて、アプリを行使するために API リクエストを送信します。ノートアプリケーションは、別のコンテナで実行されている Postgres データベースにデータを保存する REST API です。これにいくつかのコマンドを送信します。
curl -X GET 'localhost:8080/notes'
{}
curl -X POST 'localhost:8080/notes?desc=hello'
(1, hello)
curl -X GET 'localhost:8080/notes?id=1'
(1, hello)
curl -X GET 'localhost:8080/notes'
{”1”, "hello"}
curl -X PUT 'localhost:8080/notes?id=1&desc=UpdatedNote'
(1, UpdatedNote)
curl -X DELETE 'localhost:8080/notes?id=1'
Deleted
アプリケーションの実行を確認したら、それを停止して、トレースを有効にします。
コンテナを停止します。
docker-compose -f docker/containers/exercise/docker-compose.yaml down
コンテナを削除します。
docker-compose -f docker/containers/exercise/docker-compose.yaml rm
Python アプリケーションが動作するようになったので、トレースを有効にするための構成を行います。
Python トレーシングパッケージをプロジェクトに追加します。ファイル apm-tutorial-python/requirements.txt
を開き、ddtrace
がなければ追加してください。
flask==2.2.2
psycopg2-binary==2.9.3
requests==2.28.1
ddtrace
ノートアプリケーションの Dockerfile (docker/containers/exercise/Dockerfile.notes
) 内で、アプリケーションを起動する CMD 行を変更し、ddtrace
パッケージを使用するようにしてください。
# Run the application with Datadog
CMD ["ddtrace-run", "python", "-m", "notes_app.app"]
これにより、アプリケーションは自動的に Datadog のサービスにインスツルメンテーションされます。
異なるバージョンやデプロイ環境間でトレースされたサービスを識別する統合サービスタグを適用することで、Datadog 内で相関が取れるようになり、検索やフィルターに利用できるようになります。統合サービスタグ付けに使用する環境変数は、DD_SERVICE
、DD_ENV
、DD_VERSION
の 3 つです。Dockerfile に以下の環境変数を追加します。
ENV DD_SERVICE="notes"
ENV DD_ENV="dev"
ENV DD_VERSION="0.1.0"
統合サービスタグに対応する Docker ラベルを追加します。これにより、アプリケーションが実行されると、Docker のメトリクスも取得できるようになります。
LABEL com.datadoghq.tags.service="notes"
LABEL com.datadoghq.tags.env="dev"
LABEL com.datadoghq.tags.version="0.1.0"
正しく設定されているか確認するために、サンプルリポジトリのソリューションファイル docker/containers/solution/Dockerfile.notes
で提供されている Dockerfile ファイルと比較してみてください。
docker/containers/exercise/docker-compose.yaml
ファイルのサービスセクションに Datadog Agent を追加します。
Agent の構成を追加し、自分の Datadog API キーとサイトを指定します。
datadog:
container_name: dd-agent
image: "gcr.io/datadoghq/agent:latest"
environment:
- DD_API_KEY=<DD_API_KEY>
- DD_SITE=datadoghq.com # Default. Change to eu.datadoghq.com, us3.datadoghq.com, us5.datadoghq.com as appropriate for your org
- DD_APM_ENABLED=true # Enable APM
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /proc/:/host/proc/:ro
- /sys/fs/cgroup/:/host/sys/fs/cgroup:ro
環境変数 DD_AGENT_HOST
を追加し、監視したいコードを持つ各コンテナ (この場合は notes_app
コンテナ) のセクションに、Agent コンテナのホスト名を指定します。
environment:
- DD_AGENT_HOST=datadog
正しく設定されているか確認するために、サンプルリポジトリのソリューションファイル docker/containers/solution/docker-compose.yaml
で提供されている docker-compose.yaml
ファイルと比較してみてください。
トレーシングライブラリがインストールされたので、アプリケーションを再起動し、トレースの受信を開始します。以下のコマンドを実行します。
docker-compose -f docker/containers/exercise/docker-compose.yaml build notes_app
docker-compose -f docker/containers/exercise/docker-compose.yaml up db datadog notes_app
Agent が動作しているかどうかは、ターミナルで連続出力を観察するか、Datadog のイベントエクスプローラーを開いて Agent の開始イベントを確認することで分かります。
アプリケーションを起動した状態で、いくつかの curl リクエストを送信します。
curl -X POST 'localhost:8080/notes?desc=hello'
(1, hello)
curl -X GET 'localhost:8080/notes?id=1'
(1, hello)
curl -X PUT 'localhost:8080/notes?id=1&desc=UpdatedNote'
(1, UpdatedNote)
curl -X DELETE 'localhost:8080/notes?id=1'
Deleted
しばらく待って、Datadog の APM > Traces にアクセスすると、API 呼び出しに対応するトレースの一覧が表示されます。
もし、数分待ってもトレースが表示されない場合は、Traces Search フィールドのフィルターをクリアしてください (使用していない ENV
などの環境変数にフィルターをかけている場合があります)。
Traces ページで、POST /notes
トレースをクリックすると、各スパンにかかった時間や、あるスパンが完了する前に他のスパンが発生したことを示すフレームグラフが表示されます。グラフの上部にあるバーは、前の画面で選択したスパンです (この場合、ノートアプリケーションへの最初のエントリポイントです)。
バーの幅は、それが完了するまでにかかった時間を示します。低い深さのバーは、高い深さのバーの寿命の間に完了するスパンを表します。
POST
トレースのフレームグラフは次のようになります。
GET /notes
トレースは次のようになります。
自動インスツルメンテーションは便利ですが、より細かいスパンが欲しい場合もあります。Datadog の Python DD Trace API では、アノテーションやコードを使用してコード内のスパンを指定することができます。
次のステップでは、コードにアノテーションを追加して、いくつかのサンプルメソッドをトレースする方法を説明します。
notes_app/notes_helper.py
を開きます。
以下のインポートを追加します。
from ddtrace import tracer
NotesHelper
クラスの中に、notes_helper
というトレーサーラッパーを追加して、notes_helper.long_running_process
メソッドがどのように動作するかを確認できるようにします。
class NotesHelper:
@tracer.wrap(service="notes_helper")
def long_running_process(self):
time.sleep(.3)
logging.info("Hello from the long running process")
self.__private_method_1()
さて、トレーサーは自動的にリソースにラップされている関数名、この場合は long_running_process
をラベル付けしています。
以下を実行してコンテナを再構築します。
docker-compose -f docker/containers/exercise/docker-compose.yaml build notes_app
docker-compose -f docker/containers/exercise/docker-compose.yaml up db datadog notes_app
いくつかの HTTP リクエスト、特にいくつかの GET
リクエストを再送します。
トレースエクスプローラーで、新しい GET
リクエストの 1 つをクリックすると、次のようなフレームグラフが表示されます。
get_notes
関数にカスタムトレースが追加され、スタックトレースがより詳細になったことに注意してください。
詳しくは、カスタムインストルメンテーションをご覧ください。
単一のアプリケーションをトレースすることは素晴らしいスタートですが、トレースの本当の価値は、リクエストがサービスを通じてどのように流れるかを見ることです。これは、_分散型トレーシング_と呼ばれています。
サンプルプロジェクトには calendar_app
という 2 番目のアプリケーションが含まれており、呼び出されるたびにランダムな日付を返します。Notes アプリケーションの POST
エンドポイントには、add_date
という名前の 2 つ目のクエリパラメーターがあります。このパラメータが y
に設定されると、Notes はカレンダーアプリケーションを呼び出して、ノートに追加する日付を取得します。
Dockerfile の起動コマンドに dd_trace
を追加して、カレンダーアプリをトレース用に構成します。docker/containers/exercise/Dockerfile.calendar
を開き、CMD 行を以下のように更新します。
CMD ["ddtrace-run", "python", "-m", "calendar_app.app"]
ノートアプリと同様に、統合サービスタグを適用します。Dockerfile.calendar
ファイルに、以下の環境変数を追加します。
ENV DD_SERVICE="calendar"
ENV DD_ENV="dev"
ENV DD_VERSION="0.1.0"
再び、統合サービスタグに対応する Docker ラベルを追加します。これにより、アプリケーションが実行されると、Docker のメトリクスも取得できるようになります。
LABEL com.datadoghq.tags.service="calendar"
LABEL com.datadoghq.tags.env="dev"
LABEL com.datadoghq.tags.version="0.1.0"
Agent コンテナのホスト名である DD_AGENT_HOST
をカレンダーアプリのコンテナに追加し、トレースを正しい場所に送信します。docker/containers/exercise/docker-compose.yaml
を開き、calendar_app
セクションに以下の行を追加してください。
environment:
- DD_AGENT_HOST=datadog
正しく設定されているか確認するために、サンプルリポジトリの docker/containers/solution
ディレクトリで提供されている Dockerfile と docker-config.yaml
ファイルと比較してみてください。
コンテナを再起動し、マルチサービスアプリケーションを構築します。まず、実行中のコンテナをすべて停止します。
docker-compose -f docker/containers/exercise/docker-compose.yaml down
その後、以下のコマンドを実行して起動します。
docker-compose -f docker/containers/exercise/docker-compose.yaml build
docker-compose -f docker/containers/exercise/docker-compose.yaml up
add_date
パラメーターを指定して、POST リクエストを送信します。
curl -X POST 'localhost:8080/notes?desc=hello_again&add_date=y'
(2, hello_again with date 2022-11-06)
トレースエクスプローラーで、この最新のトレースをクリックすると、2 つのサービス間の分散型トレーシングが表示されます。
コードを使って、カスタムのインスツルメンテーションを追加することができます。例えば、カレンダサービスをさらにインスツルメンテーションして、トレースを見やすくしたいとします。
notes_app/notes_logic.py
を開きます。
以下のインポートを追加します。
from ddtrace import tracer
try
ブロックの内部、28 行目あたりに、次の with
ステートメントを追加してください。
with tracer.trace(name="notes_helper", service="notes_helper", resource="another_process") as span:
その結果、こうなりました。
def create_note(self, desc, add_date=None):
if (add_date):
if (add_date.lower() == "y"):
try:
with tracer.trace(name="notes_helper", service="notes_helper", resource="another_process") as span:
self.nh.another_process()
note_date = requests.get(f"http://localhost:9090/calendar")
note_date = note_date.text
desc = desc + " with date " + note_date
print(desc)
except Exception as e:
print(e)
raise IOError("Cannot reach calendar service.")
note = Note(description=desc, id=None)
note.id = self.db.create_note(note)
コンテナを再構築します。
docker-compose -f docker/containers/exercise/docker-compose.yaml build notes_app
docker-compose -f docker/containers/exercise/docker-compose.yaml up
引数 add_date
を指定して、より多くの HTTP リクエスト、特に POST
リクエストを送信します。
トレースエクスプローラーで、これらの新しい POST
トレースをクリックすると、複数のサービスにわたるカスタムトレースが表示されます。
notes_helper.another_process
というラベルが付けられていることに注意してください。もし、期待通りのトレースが受信できない場合は、Python パッケージの ddtrace
でデバッグモードを設定してください。詳しくはデバッグモードの有効化を読んでください。