traceway-setup について
traceway-setupは、コードを変更する前にアプリケーション構成を分析し、Tracewayの可観測性設定を計画するスキルです。プロジェクト境界の確認後に連携を進め、認証情報の安全な取り扱いを重視します。
主な機能
- 01コンポーネント、デプロイ、既存監視の分析
- 02Tracewayのプロジェクト構成案の提示と確認
- 03バックエンド、ブラウザー、モバイル向け連携の計画
- 04トークン取り扱いの安全対策
- 05設定後の連携検証
活用シーン
- 01新規アプリケーションのTracewayプロジェクト設計
- 02複数サービスの監視範囲の整理
- 03認証情報を保護しながら監視を導入
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ tracewayapp/ traceway --skill traceway-setupインストール後、Claude Code で/traceway-setupを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
android.mdkubernetes.mdios.mdflutter.mddashboard-project-setup.mdfrontend-js.mdai-agent.mddata-model.md詳細
Traceway のセットアップ
まずアプリケーションを分析し、Traceway のプロジェクト構成についてユーザーと合意します。次にダッシュボードでその構成を作成できるよう支援し、その後で初めて統合と検証を行います。
運用上の取り決め
- 認証情報を求めたりコードを変更したりする前に、調査してください。
- 検出した内容、すでにトラッキングされているもの、本番環境の各コンポーネントが Traceway にどのようにデータを送信すべきかを説明してください。
- 提案するプロジェクト構成を提示し、実装前にユーザーの確認を待ってください。
- 認証情報には扱いの異なる 2 種類があります。
- セットアップトークン(
tws_で始まるもの)は組織単位で有効で、有効期限は 6 時間です。セットアップ計画の提案にのみ使用でき、ユーザーが Traceway のウェブサイトで計画を承認するまでは何も作成されません。チャット上での受け渡しを想定しているため、ユーザーに貼り付けてもらって構いません。 - プロジェクト取り込みトークンとアップロードトークンは長期間有効です。値を表示したり、チャットへの貼り付けをユーザーに求めたり、コミットしたりしてはいけません。ステップ 3 の適用スクリプト(または
tracewayCLI)が承認済みの計画の取り込みトークンを環境変数ファイルに書き込む場合は、出力から変数名とステータスだけを読み取り、値は読み取らないでください。
- セットアップトークン(
- ファイルや環境変数で見つかったトークンの値を表示してはいけません。値が存在することと、それを保持する変数名だけを報告してください。
- トークンや接続文字列の値を埋め込んだものをコミットしてはいけません。
呼び出し形式
| 呼び出しに含まれるもの | 手順 |
|---|---|
| プロジェクト取り込みトークン + URL | 単一コンポーネントの場合はファストパス。それ以外はステップ 1~2 の後、既存プロジェクトに対して統合 |
セットアップトークン(tws_)+ URL | ステップ 1~2 の後、「計画ファイルの作成」(3b)からステップ 3 を実施 |
| トークンなし | ステップ 1~2 の後、最初からステップ 3 を実施 |
すべてのバックエンドは OpenTelemetry と統合します。 言語やウェブフレームワークごとに異なるバックエンド経路があるわけではありません。Go、Node、Python、PHP、Java、.NET、Ruby など、あらゆるバックエンドが OTLP/HTTP で <instance>/api/otel/* にエクスポートします。Traceway プロジェクトはフレームワーク OpenTelemetry を選択して作成します。これはダッシュボードのフレームワーク選択欄にある唯一のバックエンドオプションです。ネイティブの Traceway Go SDK は、ユーザーが明示的に希望した場合にのみ使用する例外です。
ファストパス
以下の条件をすべて満たす場合は、ステップ 2 と 3 を省略し、統合手順に進んでください。
- リポジトリにデプロイ可能なコンポーネントがちょうど 1 つあり、
- ユーザーがインスタンス URL とプロジェクト取り込みトークンを提示している(または環境にすでに存在する)。プロジェクト作成用の
tws_セットアップトークンではないこと。 - そのトークンのプロジェクトが、該当するコンポーネントにすでに対応している。
計装方法を判断するため、ステップ 1 は必ず実行してください。「プロジェクト構成の提案と確認」は、確認の 1 行(「これは Go API です。OpenTelemetry 経由で既存の <name> プロジェクトにデータを送信します」)にまとめ、プロジェクト作成手順は完全に省略してください。プロジェクト構成の提案と作成の全手順は、デプロイ可能なコンポーネントが複数あるリポジトリ、またはプロジェクトがまだ存在しない場合にのみ必要です。単一サービスに対して、トークンを提示したユーザーにプロジェクト構成の確認を強いてはいけません。
ステップ 1:アーキテクチャを分析する
変更を加える前に、デプロイ対象と、すでに計装されているものを把握してください。
- フレームワークと言語:
package.json、go.mod、composer.json、requirements.txt/pyproject.toml、pubspec.yaml、build.gradle(.kts)、Package.swift、*.xcodeproj/*.xcworkspace、Podfile、およびソースファイルの拡張子から検出します。iOS/Apple を対象とする場合は、ソースが Swift か Objective-C かを確認します。この選択によって「フロントエンドとモバイル」で使う方法が決まります(Swift ではネイティブ SDK を使い、Objective-C のみの場合は該当する SDK がないため、OTel にフォールバックします)。 - デプロイ可能なコンポーネントとエントリーポイント:API、SSR サーバー、ブラウザーアプリ、ワーカー、スケジューラー、CLI、モバイルアプリケーションを一覧にします。コードの構成は証拠として扱いますが、デプロイされている証明とはみなしません。作業中にデプロイ先も確認します。Kubernetes マニフェスト、Helm チャート、Kustomize オーバーレイ、
Dockerfileと compose ファイルの組み合わせ、または cloud-init/Ansible/Terraform が該当します。デプロイ先によって、ステップ 8 のホストメトリクスの方法が決まります。 - 既存のオブザーバビリティ:OpenTelemetry の設定、Traceway SDK、Sentry、Datadog、New Relic、Honeycomb、ログエクスポーター、トレーシングミドルウェア、ソースマップまたはシンボルのアップロード手順、オブザーバビリティ関連の環境変数名を探します。Traceway が各連携を置き換えるのか、共存するのか、拡張するのかを説明します。検出した認証情報の値は絶対に表示しないでください。
- JS メタフレームワーク(Next.js、SvelteKit、Remix、Nuxt)の本番環境での役割:フルスタックだと決めつけないでください。
- フロントエンドのみであることを示す兆候:
next.config.*のoutput: 'export'(静的エクスポートのため、本番環境にサーバーがありません);API ルート(app/api/**/route.*、pages/api/*)がない、またはごく単純なものしかない;'use server'を使ったサーバーアクションがない;ブラウザーから外部 API に接続するrewrites/プロキシ設定、またはNEXT_PUBLIC_API_URLのような環境変数;このリポジトリ、別のリポジトリ、または別の言語で構成された独立したバックエンドサービス;デプロイ設定での静的ホスティング(S3/CloudFront、GitHub Pages、out/を配信する nginx)。 - サーバーであることを示す兆候:実際のロジックを持つ API ルート、
'use server'を使ったサーバーアクション、サーバーコードからインポートされるデータベースクライアント、独自のデータレイヤーからデータを読み取る SSR、デプロイ設定におけるnext startまたはスタンドアロン出力。 - 混在または不明確な場合:アプリケーションのデプロイ方法と、本番環境で追跡する価値のある処理をフレームワークサーバーが担っているかを確認します。 フロントエンドのみとは、フロントエンド SDK を使ってブラウザー側のみを統合し、フレームワークのサーバー側には OTel を追加したり、その他の方法で計装したりしないことを意味します。別個のバックエンドは独立したコンポーネントであり、専用の Traceway プロジェクトを持ちます。
- フロントエンドのみであることを示す兆候:
- バックグラウンド処理:cron ジョブ、キューコンシューマー、スケジューラー、CLI コマンド、長時間実行されるワーカーを探します。ライブラリがすでに
CONSUMERスパンを出力しているかどうかを記録します。 - AI/LLM の使用状況:依存関係に
openai、@anthropic-ai/sdk、anthropic、langchain/@langchain/*、ai(Vercel AI SDK)、litellm、google-generativeai、cohere、openrouter、およびエージェントフレームワーク(langgraph、crewai、autogen/ag2、pydantic-ai、@openai/agents、@mastra/*、llamaindex/llama-index、semantic-kernel)が含まれているかを確認します。次に、これは単発の LLM 呼び出しではなく会話型プロダクト(チャットボット、アシスタント、エージェント)かどうかを判断します。LLM に接続するチャットまたはストリーミングチャットのルート(/chat、/completions、SSE または WebSocket ハンドラー)、メッセージ履歴の永続化(messages/conversationsテーブルまたはスレッド ID)、モデルに渡されるツール/関数呼び出しの定義、または上記のエージェントフレームワークを探します。会話型またはツール呼び出し型の場合は、AI 統合を提案する前に、このスキルディレクトリにあるai-agent.mdを読みます。 - ブラウザービルドとリリースフロー:バンドラー、出力ディレクトリ、ソースマップの設定、デプロイパイプライン、既存のアーティファクトアップロードを特定します。
- モバイルビルドとリリースフロー:Flutter が難読化されているか、Android で R8/minification を使用しているか、iOS で dSYM が生成されるか、複数のプラットフォームディレクトリがひとつのクロスプラットフォームプロダクトなのか、個別にリリースされるアプリなのかを確認します。
- デプロイとホストメトリクス:Dockerfile、Compose、Kubernetes、Helm、Terraform、Ansible、cloud-init、PaaS の設定、CI/CD を調査します。バックエンドが Traceway OTel Agent を適用できるホストで実行されているかを判断します。
質問する前に、調査結果を提示してください。
| コンポーネント | リポジトリ内の根拠 | 本番環境での役割 | 現在のトラッキング | 提案する Traceway プロジェクト | 統合方法 | 必要な認証情報 |
|---|---|---|---|---|---|---|
apps/api | Go モジュール + Gin のルート | バックエンド API | OTel / なし / ベンダー製 | Product Backend | OTel | 実行時トークン |
apps/web | Svelte + Vite | ブラウザーアプリ | 既存 SDK / なし | Product Web | Traceway Svelte SDK | 実行時トークン + アップロードトークン |
実際のパスと調査結果を記載します。未解決のデプロイに関する前提は、明示してください。
ステップ 2:プロジェクトマップを提案して確認する
次のデフォルトの境界を説明します。
| アプリケーションの境界 | Traceway プロジェクト | 含まれるもの |
|---|---|---|
| バックエンドシステム | フレームワークが OpenTelemetry のプロジェクトを 1 つ | API エンドポイント、子スパン、イシュー、バックグラウンドタスク、AI トレース、ログ、アプリケーション/ランタイムのメトリクス、ホストメトリクス。API、ワーカー、スケジューラー、ホストエージェントはプロジェクトトークンを共有し、安定した service.name の値で区別します。 |
| ブラウザーフロントエンド | デプロイされたブラウザーアプリケーションごとに 1 つの個別プロジェクトを作成し、React、Svelte、Vue.js、jQuery のいずれかを使用 | ブラウザーのエラー、Web Vitals、セッションリプレイ、分散トレースとの関連付け、ソースマップ、ブラウザーのリリースメタデータ。 |
| モバイルアプリ | 個別にリリースされるアプリケーションごとに 1 つの個別プロジェクトを作成し、Flutter、React Native、Android、iOS のいずれかを使用 | モバイルのエラー/クラッシュ、対応している場合はリプレイ、ビルドシンボルまたはマッピング。Android と iOS を対象とする単一の Flutter 製品には、通常 1 つのプロジェクトを使用します。個別のネイティブアプリには、それぞれ別のプロジェクトを使用します。 |
| フルスタック JS アプリ | サーバーを本番環境で実行する場合は 2 つのプロジェクト | サーバー側の処理は OpenTelemetry のバックエンドプロジェクトに、ブラウザー側の処理はブラウザープロジェクトに送ります。 |
ダッシュボードのフレームワーク選択欄にある選択肢は、次の 9 つのみです。すべてのバックエンド向けの OpenTelemetry、ブラウザー向けの React/Svelte/Vue.js/jQuery、モバイル向けの Flutter/React Native/Android/iOS です。Gin、Django、Laravel、Next.js、Remix は選択肢にありませんが、追加する必要もありません。Next.js または Remix のブラウザープロジェクトでは React を選び、サーバー側では他のバックエンドと同じように OpenTelemetry を選びます。バックエンド固有のセットアップはプロジェクトの Connection ページにあり、プロジェクト作成後に言語と Web フレームワークを指定します。
デフォルトでは、バックエンドのプロセスごとにプロジェクトを作成しないでください。API、ワーカー、AI 呼び出し、サーバーメトリクスをまとめることで、運用上のコンテキストと分散トレースを維持できます。バックエンドプロジェクトを分割するのは、製品、所有者、アクセス制御、コンプライアンス、データ分離に関する実際の境界がある場合に限ります。
リポジトリから安全に判断できない事項のみ、ユーザーに確認します。
- 検出されたコンポーネントのうち、デプロイされ、追跡対象とするものはどれですか?
- Traceway Cloud とセルフホストのどちらを使用しますか?また、プロジェクトの所有者とする組織はどれですか?
- 提案した名前とプロジェクトの境界でよろしいですか?
- バックエンドは VM/ホスト、Kubernetes、サーバーレス/PaaS のどれで実行されますか?ホストメトリクスを収集しますか?
- モバイルのディレクトリは、1 つのクロスプラットフォーム製品を表していますか?それとも、個別にリリースされるアプリを表していますか?
確認済みの各行について、ステップ 3 のプランファイルに必要な次の項目も確定します。
- フレームワークの値:9 つのうちの 1 つです。
opentelemetry、react、svelte、vuejs、jquery、flutter、react-native、android、ios。 - env の設定:認証情報を格納する未追跡の env ファイル(
envFile)と、その中で使用する名前(envVar)を指定します。ブラウザーの値には、上記の認証情報の命名規則に従って、VITE_/PUBLIC_/NEXT_PUBLIC_などの公開用プレフィックスを使用します。コード内で接続文字列を組み立てる場合、または値を OTLP Authorization ヘッダーに渡す場合、envFormatはtokenです。SDK の初期化時に変数から<token>@<instance>/api/report形式の文字列全体を読み込む場合、envFormatはconnectionStringです。 - デプロイ先への設定:ステップ 1 のデプロイ分析に基づき、コンポーネントのデプロイ方法により認証情報をリポジトリにハードコードできない場合は、プラットフォーム名と正確なコマンドまたは UI のパスを含む
deploymentブロックを追加します。値にはプレースホルダー<token>をそのまま使用してください。承認後にウェブサイトが実際の値に置き換えるため、プランに実際のトークンを記載しないでください。認証情報が通常ビルド設定に保存されるモバイルプロジェクトでは、通常deploymentブロックを追加し、envFileは指定しません。
ユーザーがこのマップを確認するまで、コードを変更しないでください。
ステップ 3:プロジェクトを作成する
標準的な手順では、確認済みのマップをセットアップ計画として送信し、ユーザーが Traceway のウェブサイト上で内容を確認して承認します。その後、短い curl スクリプトで生成されたインジェストトークンを環境ファイルに書き込みます。curl と jq 以外にインストールするものはありません。適切にマッピング済みの既存の Traceway プロジェクトは再利用できます(計画では名前でプロジェクトを照合するため、既存の名前を指定すると重複せず再利用されます)。
3a. セットアップトークンを取得する(呼び出し時にトークンが渡されている場合はスキップ)
アカウントの状態に応じて分岐します。リポジトリと会話から判断できない場合に限り、確認してください。
- Traceway アカウントがある場合:「
<instance>/setupを開いてください(Traceway Cloud:https://cloud.tracewayapp.com/setup)。求められたらログインしてください。ページにtws_で始まるセットアップトークンが表示されます。ここに貼り付けて、ページは開いたままにしてください。」トークンの有効期限は6時間です。ページには「Generate New Token」ボタンがあります。 - まだアカウントがない場合:「
<instance>/registerを開いてください(Traceway Cloud:https://cloud.tracewayapp.com/register)。ステップ1でアカウントと組織を作成します。ステップ2では「AI」を選択したままにしてください。`tws_` で始まるセットアップトークンが表示されます。ここに貼り付けて、ページは開いたままにしてください。提案がそのページに表示され、承認できます。承認すると、プロジェクトがすぐに表示されます。」
この手順では、ウェブ UI でプロジェクトを作成させないでください。また、トークンなしで先に進まないでください。
3b. 計画ファイルを書き込む
確認済みのマップから、プロジェクトごとに1つのエントリーを含む traceway-setup-plan.json を書き込みます。
{
"projects": [
{"name": "Product Backend", "framework": "opentelemetry",
"envFile": "backend/.env", "envVar": "TRACEWAY_BACKEND_TOKEN"},
{"name": "Product Web", "framework": "svelte",
"envFile": "frontend/.env", "envVar": "PUBLIC_TRACEWAY_WEB_CONNECTION_STRING",
"envFormat": "connectionString",
"deployment": {"platform": "Vercel",
"instructions": "vercel env add PUBLIC_TRACEWAY_WEB_CONNECTION_STRING production\n# paste: <token>"}}
]
}
ルール:framework はステップ2の9つの値のいずれかにします。すべての envFile は追跡対象外である必要があります(作成し、最初に Git の無視対象であることを確認してください)。envVar は認証情報の命名ルールに従います。deployment.instructions では、実際の値ではなく、リテラルの <token> プレースホルダーを使用します。
3c. 計画を送信して承認を待つ(curl)
このステップでは curl と jq を直接使用してください。ここでは traceway CLI をインストールしないでください。この手順では何もインストールしません。(setup apply を利用できる新しいバージョンの CLI がすでにある場合に限り、printf '%s' "$TRACEWAY_SETUP_TOKEN" | traceway setup apply --url "$TRACEWAY_URL" --plan traceway-setup-plan.json --token-stdin を同等のワンステップ手順として使用できます。)jq が利用できず、インストールもできない場合は、手動の代替手順(3e)を使用してください。
最初に認証情報をエクスポートします。セットアップトークンはチャットを経由しても問題ありません。
export TRACEWAY_URL="<instance>" # no trailing slash
export TRACEWAY_SETUP_TOKEN="tws_..."
トークンを検証し、組織を表示します(この応答に含まれるのはプロジェクト名のみなので、安全に表示できます)。
curl -s -w '\nHTTP %{http_code}\n' -H "Authorization: Bearer $TRACEWAY_SETUP_TOKEN" \
"$TRACEWAY_URL/api/setup/session"
計画をドラフトとして送信します。
curl -s -w '\nHTTP %{http_code}\n' -X PUT \
-H "Authorization: Bearer $TRACEWAY_SETUP_TOKEN" -H 'Content-Type: application/json' \
--data-binary @traceway-setup-plan.json "$TRACEWAY_URL/api/setup/plan"
200 {"status":"pending"} はドラフトが送信されたことを意味します。ユーザーに「開いている Traceway のページで提案を確認し、Approve Setup を押してください。」と伝えてください。422 は検証メッセージです。計画を修正して再送信してください。401 はトークンが無効か期限切れであることを意味します。<instance>/setup から新しいトークンを取得するようユーザーに依頼してください。
次に、以下のスクリプトを使って決定を待ちます。決定応答にはインジェストトークンが含まれるため、このスクリプトを使用します。値が API から環境ファイルへ直接流れ、標準出力、コンテキスト、チャットには決して出ないようにしてください。traceway-setup-wait.sh という名前で、以下の内容を一字一句そのまま書き込み、sh traceway-setup-wait.sh を実行してください。GET /api/setup/plan を直接取得してはならず、書き込まれた環境ファイルを読み取ってもいけません。
#!/bin/sh
# Waits for the setup decision, then writes each ingest token into the env
# file named by the plan. Prints statuses and variable names only.
set -eu
PLAN=${1:-traceway-setup-plan.json}
AUTH="Authorization: Bearer ${TRACEWAY_SETUP_TOKEN:?}"
URL=${TRACEWAY_URL:?}
deadline=$(($(date +%s) + 1800))
while :; do
resp=$(curl -s -H "$AUTH" "$URL/api/setup/plan")
status=$(printf '%s' "$resp" | jq -r '.status // "error"')
case "$status" in
approved) break ;;
rejected)
echo "rejected: $(printf '%s' "$resp" | jq -r '.reason // "(no reason given)"')"
exit 2 ;;
pending|none) ;;
*) echo "unexpected response, the setup token may have expired"; exit 1 ;;
esac
if [ "$(date +%s)" -ge "$deadline" ]; then
echo "timed out waiting for approval; rerun when the user is ready"
exit 3
fi
sleep 3
done
i=0
n=$(jq '.projects | length' "$PLAN")
while [ "$i" -lt "$n" ]; do
name=$(jq -r ".projects[$i].name" "$PLAN")
envfile=$(jq -r ".projects[$i].envFile // empty" "$PLAN")
envvar=$(jq -r ".projects[$i].envVar // empty" "$PLAN")
format=$(jq -r ".projects[$i].envFormat // \"token\"" "$PLAN")
pstatus=$(printf '%s' "$resp" | jq -r --arg n "$name" \
'[.projects[] | select(.name == $n)][0].status // "missing"')
if [ "$pstatus" = missing ]; then
echo "$name: missing from the approved plan"
i=$((i + 1)); continue
fi
if [ -n "$envfile" ] && [ -n "$envvar" ]; then
value=$(printf '%s' "$resp" | jq -r --arg n "$name" --arg f "$format" \
'[.projects[] | select(.name == $n)][0]
| if $f == "connectionString"
then .token + "@" + (.backendUrl | sub("/+$"; "")) + "/api/report"
else .token end')
dir=$(dirname "$envfile"); mkdir -p "$dir"
tmp=$(mktemp "$dir/.tmp-env-XXXXXX")
{ [ -f "$envfile" ] && grep -v "^${envvar}=" "$envfile" > "$tmp"; } || true
printf '%s=%s\n' "$envvar" "$value" >> "$tmp"
mv "$tmp" "$envfile"
echo "$name: $pstatus, wrote $envvar to $envfile"
else
echo "$name: $pstatus"
fi
i=$((i + 1))
done
echo "done: deployment credentials, if any, are shown on the Traceway page the user has open"
環境ファイルは mktemp によってモード 0600 で作成されます。失敗時の対応:
- 拒否(終了コード 2):スクリプトにユーザーの拒否理由が表示されます。ユーザーとマップを修正し、計画ファイルを更新して再送信し(新しい PUT で保留中のドラフトが置き換えられます)、待機スクリプトを再実行してください。承認済みのプロジェクトは名前で照合され、重複して作成されることはありません。
- トークンの期限切れまたは無効(401/終了コード 1):
<instance>/setupから新しいトークンを取得するようユーザーに依頼し、再エクスポートして再送信し、再実行してください。 - タイムアウト(終了コード 3):ユーザーの準備ができたら、再送信して再実行してください。問題ありません。
適用が成功したら、計画ファイルと traceway-setup-wait.sh を削除してください。機密情報は含まれていませんが、セットアップ時の不要なファイルです。
3d. デプロイ認証情報を確認して設定する
承認されると、Traceway のページに完了メッセージが表示され、新しいプロジェクトのダッシュボードに移動します。このダッシュボードは、プロジェクトが作成されたことの確認も兼ねています。deployment ブロックがある各プロジェクトについて、ページにはまず、正確なコマンドと実際の認証情報の値を示す 次のステップ パネルが表示されます。プロジェクトがあるアカウントではセットアップページに再度アクセスできないため、先に進む前に、そこでの作業を完了できるようユーザーを案内してください。これらの値をチャットで伝えてはいけません。後で値が必要になった場合は、各プロジェクトのダッシュボードにある「接続」ページでトークンを確認できます。
3e. 手動での代替手順
ユーザーがクリック操作を希望する場合、curl または jq が利用できない場合、あるいは適用に繰り返し失敗する場合は、dashboard-project-setup.md に従ってください。ユーザーがダッシュボード UI で各プロジェクトを作成し、トークンを環境ファイルまたはシークレットストアに直接設定します。この方法では、従来のルールが全面的に適用されます。インジェストトークンをチャット経由でやり取りしてはいけません。
アップロードトークンは、どの方法でも手動で設定します。アップローダーは固定の変数名を読み取るためです。 traceway-sourcemaps は TRACEWAY_SOURCEMAP_TOKEN を読み取り、dart run traceway:upload_symbols と iOS の dSYM スクリプトは TRACEWAY_UPLOAD_TOKEN を読み取ります(3つすべてが TRACEWAY_URL も読み取ります)。CI シークレットにその名前を正確に付けるか、コンポーネントごとのシークレット名を維持して、明示的に渡してください。
traceway-sourcemaps --url "$TRACEWAY_URL" --token "$TRACEWAY_WEB_UPLOAD_TOKEN" --directory ./dist
TRACEWAY_WEB_UPLOAD_TOKEN のような名前を独自に作り、--token なしでアップローダーを呼び出すと、セットアップ時ではなくリリース時に失敗します。そのため、CI ステップで選択を明示してください。アップロードトークンは、ダッシュボードの 接続 -> ソースマップ または シンボルのアップロード から、プロジェクトごとに生成できます。
統合パス
プロジェクトの種類に応じてパスを選び、プロジェクトの種類は「アーキテクチャの分析」の調査結果に基づいて判断してください。フレームワーク名だけで判断してはいけません(Next.js のリポジトリは、フルスタックアプリの場合も、別のバックエンドのフロントエンドだけの場合もあります)。各パスはフレームワークごとに任意で選べるものではありません。Traceway がデータを受信するよう設計された方法です。
| プロジェクトの種類 | パス |
|---|---|
| バックエンド(言語を問わない) | OpenTelemetry を使用し、OTLP/HTTP で <instance>/api/otel/v1/* にエクスポートします。Go も必ずこの方法を使用します。 |
| フロントエンド(ブラウザー SPA、または本番環境でフロントエンドのみを実行する JS メタフレームワーク) | Traceway の @tracewayapp/<framework> SDK + バンドラープラグイン + ソースマップのアップロード(下記の「フロントエンドとモバイル」を参照)。 |
| フルスタック JS(「アーキテクチャの分析」に従い、本番環境で実際に API/SSR を提供する Next.js、SvelteKit、Remix) | 両方の側を、それぞれ別の Traceway プロジェクトとして統合します。サーバー側は OpenTelemetry、ブラウザー側はフロントエンド SDK を使用します。 |
| モバイル(Flutter、React Native、Android、ネイティブ Swift iOS) | Traceway のプラットフォーム SDK を使用します。OTel は使用しません。唯一の例外は、Swift 以外の iOS/Apple アプリにネイティブ SDK がない場合です。この場合は OTel ライブラリ(例:Honeycomb)を使用し、バックエンドと同様に Traceway にエクスポートします(「フロントエンドとモバイル」を参照)。 |
すべてのバックエンド統合が満たすべきルールと、各スパンがどのように変換されるかを示す表は、適用方法とともにステップ 4 に記載されています。
ステップ 4:バックエンドの OTel セットアップ
どの言語でも手順は同じです。
- 対象言語の OpenTelemetry SDK に加え、Web フレームワークとデータベースクライアント用の自動計装をインストールします。
- プロジェクトトークンを Bearer ヘッダーとして指定し、OTLP/HTTP エクスポーターの送信先を Traceway に設定します。
- リソースに
service.name(Traceway ではサーバー名になります)とservice.version(リリースの比較が可能になります)を設定します。 - 何よりも先に、エンドポイントのグルーピングを検証します。
譲れない3つのルール
- エンドポイントには必ずパラメーター化された値を設定してください。
http.routeにはルートパターン(/api/users/:id)を設定し、具体的なURLは設定しないでください。Traceway は値をそのまま使用しますが、/で始まる場合に限ります。app_user_showのようなルート名は、値がない場合と同様に破棄されます。使用できるルートがない場合はurl.pathにフォールバックし、Endpoints ページに一意のURLごとの行が大量に表示されます。 - バックグラウンド処理には必ず
SpanKind.CONSUMERを使用してください。 デフォルトのINTERNAL種別で、HTTP 属性のないルートスパンは、何も通知されず破棄されます(記録された例外は引き続き Issues に表示されますが、タスク実行自体は失われます)。 - エクスポーターには OpenTelemetry プロジェクトのトークンを必ず使用してください。 ブラウザプロジェクト(フレームワークが React、Svelte、Vue.js、jQuery、React Native)のトークンで OTLP が送信されると、Traceway は Issues のみを保持し、すべてのエンドポイント、タスク、子スパン、AI トレースを破棄します。「エラーは表示されるが、Endpoints ページが空」という症状が現れます。原因は、ほとんどの場合、2つのプロジェクトのトークンを取り違えていることです。
Traceway がスパンを分類する方法
ルールは以下の順序で評価され、最初に一致したものが適用されます。
| # | スパン | 条件 | 分類先 |
|---|---|---|---|
| 1 | すべてのスパン | SpanKind = INTERNAL かつ exception.* 属性を含む | Issue。 HTTP 属性や gen_ai.* 属性があっても、昇格されません。子スパンには通常のスパン行が残り、ルートスパンには Issue のみが表示されます |
| 2 | ルートスパン、または親スパンが同じエクスポートバッチに含まれていないスパン | SpanKind = SERVER、または HTTP 属性を持つ INTERNAL | エンドポイント |
| 3 | すべてのスパン | SpanKind = CONSUMER | タスク |
| 4 | ルートスパン | console.command 属性を持つ INTERNAL | タスク(CLI コマンド) |
| 5 | すべてのスパン | gen_ai.* 属性を含む | AI トレース |
| 6 | ルート以外のスパン | 親スパン ID を持つ | スパン(子) |
| 7 | ルートスパン | 上記のいずれにも一致しない | 破棄(記録された例外はリンクされずに Issue になります) |
順序は固定されているため、gen_ai.* を持つ CONSUMER スパンはタスクになり、gen_ai.* を持つ SERVER リクエストスパンはエンドポイントになります。モデル呼び出しは専用の子スパンに配置してください(手順6)。
スパンの種別に関係しないルールが、さらに2つあります。
- いずれかのスパンに
exceptionイベント、またはexception.*属性があると、スパン自体の分類にかかわらず Issue が生成されます。 - 実際のルートに一致せず(
http.routeがない、または/、/*のようなキャッチオールの場合)404 を返すエンドポイントは、文字列どおりUNMATCHEDに名前が変更されるため、ボットのスキャンや入力ミスによるURLは1つの行にまとめられます。実際に一致したルートが404を返す場合は、そのルート名が維持されます。
正確なルール、エンドポイントの命名、メトリクスの変換、その他の注意点については、このスキルのディレクトリにある data-model.md を参照してください。これが正式なリファレンスです。
エクスポーターの設定
SDK が標準の環境変数に対応している場合は、そちらを優先してください。言語を問わず同じように機能します。
OTEL_SERVICE_NAME=my-service
OTEL_RESOURCE_ATTRIBUTES=service.version=1.2.3 # there is no OTEL_SERVICE_VERSION variable
OTEL_EXPORTER_OTLP_ENDPOINT=https://<instance>/api/otel
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf # required, several SDKs default to gRPC
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <project-token>"
OTEL_TRACES_EXPORTER=otlp
OTEL_METRICS_EXPORTER=otlp
OTEL_LOGS_EXPORTER=otlp
このうち2行は、設定しなくてもエラーが表面化しないため、特に重要です。
OTEL_EXPORTER_OTLP_PROTOCOLは省略できません。 設定しない場合、Python SDK と Java エージェントはotlpを gRPC として解決しますが、Traceway には gRPC リスナーがありません。アプリは起動し、トラフィックを処理して、終了コード 0 で終了します。警告も出力されず、エクスポートはすべて失われます。(値が異なる例外は PHP で、http/jsonが必要です。)OTEL_SERVICE_VERSIONはありません。service.versionが Traceway に届くのは、OTEL_RESOURCE_ATTRIBUTESを通じてのみです。これがないと、すべてのエンドポイント行の App Version が空になり、リリース比較も機能しません。
SDK はエンドポイントに /v1/traces、/v1/metrics、/v1/logs を自動で追加するため、ベース URL のみを設定してください。OTEL_EXPORTER_OTLP_ENDPOINT にシグナルのパス全体を設定すると、/v1/traces/v1/traces になります。また、シグナル固有の変数(OTEL_EXPORTER_OTLP_TRACES_ENDPOINT)は、何も追加されずにそのまま使用されます。コード内で設定する場合の完全な URL は https://<instance>/api/otel/v1/traces(および /v1/metrics、/v1/logs)で、ヘッダーは Authorization: Bearer <project-token> です。
ステップ3の適用スクリプトが環境変数ファイルを書き込んだ場合、プランの変数にはすでにローカルの実値が設定されているため、それらの名前をそのままエクスポーターに設定し(例:Authorization=Bearer ${TRACEWAY_BACKEND_TOKEN})、すぐにライブ検証を実行してください。スクリプトが書き込むのは各プロジェクトのプラン変数1つだけです。インスタンス URL 用の TRACEWAY_URL など、インテグレーションが読み取る関連変数は、今のうちに同じ環境変数ファイルに追加してください。手動で設定する場合は、先にユーザーが変数を設定します。
制約:OTLP/HTTP のみ(protobuf または JSON)。OTLP/gRPC はサポートされておらず、ポート 4317 にリスナーはありません。Content-Encoding: gzip は使用できます。解凍後の本文サイズ上限は 10 MB で、上限を超えるバッチは 413 と {"error":"request body exceeds the 10MB limit"} を返して、全体が拒否されます。一部だけ取り込まれることはありません。トークンが誤っているか指定されていない場合は 401 が返され、それ以外のパスには 404 が返されます。これらはすべてアプリケーションからは見えません。多くの SDK はエクスポーターの失敗をデバッグレベルでしかログに記録しないため、データが届かない場合は、まず SDK 自体の診断ログを有効にしてください。
Node.js の例
npm install @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node \
@opentelemetry/instrumentation @opentelemetry/api @opentelemetry/sdk-metrics \
@opentelemetry/exporter-trace-otlp-http @opentelemetry/exporter-metrics-otlp-http
推移的にインストールされる場合でも、@opentelemetry/api は自分で宣言してください。hoisting に依存すると、pnpm の厳格な node_modules や Yarn PnP で問題が発生します。
プロジェクトのルートに instrumentation.mjs を作成し、アプリの前に読み込んでください:node --import ./instrumentation.mjs server.js。拡張子には .mjs を使用してください。import 構文を含む .js ファイルは、ほとんどのプロジェクトで現在も使われている CommonJS プロジェクトでは読み込みに失敗します。
import { register } from "node:module";
register("@opentelemetry/instrumentation/hook.mjs", import.meta.url);
import { NodeSDK } from "@opentelemetry/sdk-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
import { PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
const url = process.env.TRACEWAY_URL;
const headers = { Authorization: `Bearer ${process.env.TRACEWAY_BACKEND_TOKEN}` };
const sdk = new NodeSDK({
serviceName: process.env.OTEL_SERVICE_NAME ?? "my-service",
traceExporter: new OTLPTraceExporter({ url: `${url}/api/otel/v1/traces`, headers }),
metricReaders: [
new PeriodicExportingMetricReader({
exporter: new OTLPMetricExporter({ url: `${url}/api/otel/v1/metrics`, headers }),
exportIntervalMillis: 30_000,
}),
],
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
このコードのうち、特に重要な点は3つあります。
- 2行の
registerは ESM ローダーフックをインストールします。 これらがない場合、ESM アプリ("type": "module"、import express from "express")では HTTP スパンは取得できますが、http.routeは取得できず、URL ごとに別のエンドポイント行になります。CommonJS アプリ(require("express"))はフックがなくてもパッチが適用されます。また、この行は CommonJS では何も問題を起こさないため、どちらの場合も残してください。 serviceNameは Traceway の Server Name になります。省略すると、すべてのスパンでunknown_service:nodeが報告されます。リリース比較を行う場合は、OTEL_RESOURCE_ATTRIBUTES=service.version=1.2.3も設定してください。metricReadersはリストです。 旧式の単数形オプションmetricReaderは非推奨です。
自動計装は、Express のルート(http.route を設定)、ステータスコード、エラー、データベースクライアント(pg、mysql2、mongodb、ioredis)を対象とします。SQLite と独自のビジネスロジックには、手動で tracer.startActiveSpan() の子スパンを作成する必要があります。
Next.js サーバーの例外
Next.js では、上記の汎用 instrumentation.mjs プリロード、node --import、または NODE_OPTIONS を使用しないでください。Next.js は、一致した http.route を持つ独自の受信リクエストルートスパンを作成します。汎用の Node HTTP 計装をプリロードすると、リテラル URL を名前にした競合するルートが作成されるため、/api/users/1 と /api/users/2 が別々のエンドポイントになります。
Next.js サーバーでは、最小限の instrumentation.ts フックを作成し、SDK は別の instrumentation.node.ts に配置してください。Next.js はこのフックを Node と Edge の両方用にコンパイルします。ランタイムガードの後に動的な import() 呼び出しを行う場合でも、フックで OTel パッケージを直接インポートすると、開発時の Edge コンパイルで Node の組み込みモジュールが解決され、失敗することがあります。ラッパーでは Node モジュールのみを条件付きでインポートする必要があります。
export async function register() {
if (process.env.NEXT_RUNTIME === "nodejs") {
await import("./instrumentation.node");
}
}
Node 専用のすべてのインポートと SDK の起動処理は、隣接するモジュールに配置してください。
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
import { resourceFromAttributes } from "@opentelemetry/resources";
import { BatchLogRecordProcessor } from "@opentelemetry/sdk-logs";
import { PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
import { NodeSDK } from "@opentelemetry/sdk-node";
(Error as unknown as { prepareStackTrace?: unknown }).prepareStackTrace = undefined;
const instance = process.env.TRACEWAY_URL!.replace(/\/+$/, "");
const base = `${instance}/api/otel`;
const headers = { Authorization: `Bearer ${process.env.TRACEWAY_BACKEND_TOKEN}` };
new NodeSDK({
resource: resourceFromAttributes({
"service.name": process.env.OTEL_SERVICE_NAME ?? "nextjs-server",
"service.version": process.env.APP_VERSION ?? "development",
}),
traceExporter: new OTLPTraceExporter({ url: `${base}/v1/traces`, headers }),
metricReaders: [
new PeriodicExportingMetricReader({
exporter: new OTLPMetricExporter({ url: `${base}/v1/metrics`, headers }),
exportIntervalMillis: 30_000,
}),
],
logRecordProcessors: [
new BatchLogRecordProcessor({
exporter: new OTLPLogExporter({ url: `${base}/v1/logs`, headers }),
}),
],
instrumentations: [getNodeAutoInstrumentations()],
}).start();
汎用の Node 依存関係に加えて、ログエクスポーターと SDK パッケージをインストールしてください:@opentelemetry/exporter-logs-otlp-http、@opentelemetry/sdk-logs、@opentelemetry/api-logs、および @opentelemetry/resources。Next.js 15 より前のバージョンでは、experimental.instrumentationHook: true も必要です。セットアップと検証の詳細:https://docs.tracewayapp.com/client/otel/nextjs
instrumentation.node.ts で Error.prepareStackTrace をリセットすると、Node がソースマップを適用できるようになり、サーバーの Issue が圧縮された Next のチャンクを指したままになるのを防げます。本番環境では NODE_OPTIONS=--enable-source-maps を指定して起動し、ビルドで .next/server/**/*.js.map が出力されるようにする必要もあります。サーバーのスタックが読みやすいと決めつけず、両方を確認してください。webpack ビルドでソースマップが省略される場合は、next.config に experimental: { serverSourceMaps: true } を追加してください。また、計装レジストリがバンドルされたり、オプションのトランスポートについて警告が出たりしないよう、@opentelemetry/auto-instrumentations-node を serverExternalPackages に記載してください。
言語別の注意事項
- Go:フレームワークの OTel ミドルウェアを使用してください。
go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin、github.com/riandyrn/otelchi(コミュニティパッケージです。また、生の URL が報告されるのを防ぐため、otelchi.WithChiRoutes(r)を渡してください)、github.com/gofiber/contrib/otelfiber/v2。これらはいずれも、一致したルートパターンからhttp.routeを設定します。エクスポーター:otlptracehttp.WithEndpointURL(...)+WithHeaders。Go 固有の注意点が 2 つあります。-
プロパゲーターを設定する。 Go のグローバルプロパゲーターはデフォルトでは何もしないため、
traceparentが送信も読み取りもされず、サービス間のトレースが関連付けられません。otel.SetTracerProvider(tp)の直後に、次の 1 行を追加します。otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator( propagation.TraceContext{}, propagation.Baggage{}, )) -
標準ライブラリの
net/httpはルートを報告しない。otelhttpはr.Patternからルートを読み取ります。ServeMuxがこの値を設定するのは照合後だけなので、通常の最上位のotelhttp.NewHandler(mux, "server")ではhttp.routeがまったく記録されず、URL ごとに別のエンドポイント行が作成されます。登録する各ハンドラーをラップして、スパンの開始を mux の内側に置く方法があります。mux.Handle("GET /api/users/{id}", otelhttp.NewHandler(usersHandler, "users"))または、最上位のラップを 1 つだけ使い、ルートを自分で設定する方法があります。
// インポート:strings、go.opentelemetry.io/otel/trace、 // semconv "go.opentelemetry.io/otel/semconv/v1.26.0" func withRoute(mux *http.ServeMux) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if _, pattern := mux.Handler(r); pattern != "" { if i := strings.IndexByte(pattern, '/'); i >= 0 { route := pattern[i:] // "GET " プレフィックスを削除。http.route は "/" で始まる必要があります trace.SpanFromContext(r.Context()).SetAttributes(semconv.HTTPRoute(route)) } } mux.ServeHTTP(w, r) }) } handler := otelhttp.NewHandler(withRoute(mux), "server")
-
- Python:
pip install opentelemetry-distro opentelemetry-exporter-otlpを実行し、次にopentelemetry-bootstrap -a installを実行します。その後、上記の環境変数を設定して、opentelemetry-instrumentを付けてアプリを実行します(opentelemetry-instrument uvicorn app:app、opentelemetry-instrument gunicorn wsgi:app、opentelemetry-instrument python worker.py)。このプレフィックスなしでサーバーを起動すると、何も送信されません。FastAPIとFlaskの計装は、アプリケーションコードを一切変更せず、各フレームワーク独自の構文(GET /users/{user_id}、GET /orders/<order_id>)でhttp.routeを正しく設定します。また、どちらのフレームワークも未処理の例外に対してすでに500を返すため、追加作業なしでエンドポイントのステータスとIssueが一致します。FastAPI 0.142.0以降では、次の箇条書きで説明する組み込みテレメトリーがデフォルトです。この方法を引き続き使う場合は、必ずFastAPI(telemetry={"auto_configure": False})としてアプリを構築してください。そうしないとFastAPIが2つ目のエクスポーターを追加し、すべてのスパンがTracewayに二重に届きます。Python固有の注意点は3つあります。-
ログには変数を2つ追加する必要があります。
OTEL_LOGS_EXPORTER=otlpを設定すると、OTelハンドラーがルートロガーに取り付けられます。ルートロガーのレベルはデフォルトでWARNINGなので、すべてのlogger.info(...)がブリッジに届く前にフィルタリングされ、WARN以上だけがTracewayに届きます。また、ハンドラーを取り付けるとルートハンドラーのリストが置き換えられるため、アプリ独自のレコードが標準出力に表示されなくなります。次の両方を追加してください。OTEL_PYTHON_LOG_CORRELATION=true # コンソール出力を復元し、otelTraceID/otelSpanIDを付与します OTEL_PYTHON_LOG_LEVEL=info # 上の行と併せて設定した場合にのみ読み込まれますOTEL_PYTHON_LOG_LEVELだけを設定しても何も起こりません。OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=trueは設定しないでください。現在のバージョンではブリッジはすでに有効になっており、この変数を設定するとSDKの非推奨ハンドラーに切り替わります。 -
メトリクスの送信には1分かかります。
OTEL_METRIC_EXPORT_INTERVALのSDKデフォルト値は60000 msなので、パイプラインが正しくても確認中は空に見えます。検証中はOTEL_METRIC_EXPORT_INTERVAL=10000を設定してください。 -
Djangoでは追加で2つ必要です:
DJANGO_SETTINGS_MODULEをエクスポートしないと、opentelemetry-instrumentはDjangoの起動に失敗します。また、Djangoガイドに記載されているルートミドルウェアを追加してください。opentelemetry-instrumentation-djangoはhttp.routeとしてDjango独自のパターン(api/users/<int:user_id>/)を報告しますが、先頭に/がないため破棄されるからです。 ガイド:https://docs.tracewayapp.com/client/otel/python と https://docs.tracewayapp.com/client/otel/django
-
- FastAPI 0.142.0 以降:デフォルトでは FastAPI の組み込みテレメトリーを使用してください(https://fastapi.tiangolo.com/advanced/opentelemetry/)。ロックファイルまたは
pip show fastapiでインストール済みのバージョンを確認してください。0.142.0 未満には組み込みテレメトリーがないため、上記の汎用 Python の方法を使用してください。この機能を利用するためだけに FastAPI を更新するかどうかは、ユーザーの判断に委ねられます。組み込みの方法ではエージェントは不要で、opentelemetry-instrumentのプレフィックスも必要ありません。-
fastapi[standard](または、アプリで standard extra を使用しない場合はfastapi[opentelemetry])をインストールします。通常のfastapiに含まれるのはopentelemetry-apiのみなので、起動時に FastAPI は警告FastAPI automatic telemetry configuration failed: Automatic OpenTelemetry export requires fastapi[opentelemetry] or fastapi[standard]...を出力し、何もエクスポートしません。 -
「Exporter configuration」に記載されている環境変数ブロックを、プロセスの環境に設定します。FastAPI はライフスパンの起動時にこれを読み取り、トレース、メトリクス、ログ用の OTLP/HTTP エクスポーターを構成します。エクスポーターは
OTEL_EXPORTER_OTLP_HEADERSを、リソースはOTEL_SERVICE_NAMEとOTEL_RESOURCE_ATTRIBUTESをそれぞれ読み取ります。対応しているプロトコルはhttp/protobufのみです。それ以外のプロトコルを指定すると、FastAPI automatic telemetry configuration failedがログに出力され、アプリは何もエクスポートしません。 -
通常どおりサーバーを起動します(
fastapi run、uvicorn app:app、gunicorn -k uvicorn.workers.UvicornWorker app:app)。 -
例外ハンドラーを追加してください。追加しないと Issues に何も表示されません。 組み込みテレメトリーは、リクエストスパンをステータス
500とerror.typeを持つERRORとして記録しますが、例外はログレコード(http.server.request.exception)としてのみ送信し、スパンにはexceptionイベントを記録しません。Traceway はスパンの例外イベントから Issues を作成するため、エンドポイントの失敗行は表示されても、Issues ページは空になります。リクエストスパンに例外を記録してください。from fastapi import Request from fastapi.responses import JSONResponse from opentelemetry import trace from opentelemetry.trace import Status, StatusCode @app.exception_handler(Exception) async def record_unhandled_exception(request: Request, exc: Exception): span = trace.get_current_span() span.record_exception(exc) span.set_status(Status(StatusCode.ERROR, str(exc))) return JSONResponse({"detail": "Internal Server Error"}, status_code=500)HTTPExceptionと検証エラーにはそれぞれ独自のハンドラーが適用されるため、404 や 422 は Issue として記録されません。 対象範囲:SERVER スパン(FastAPI 構文のhttp.route(GET /users/{user_id}))、ステータスコード、fastapi.dependencies/fastapi.endpoint/fastapi.serializationの子スパン、traceparentの伝播、HTTP サーバーメトリクス、FastAPI 独自の例外ログとバリデーションログをカバーします。データベースクエリ、送信 HTTP 呼び出し、アプリ独自のlogging呼び出しはカバーしません。それらも必要な場合(データベースを使うほとんどのアプリでは必要になります)は、汎用の Python 用パス(opentelemetry-instrument)を使い、FastAPI のエクスポートを無効にしてください:FastAPI(telemetry={"auto_configure": False})。opentelemetry-instrumentの下でauto_configureを有効のままにすると、FastAPI はエージェントのプロバイダーに 2 つ目のエクスポーターを追加するため、すべてのスパンが 2 回送信されます。(FastAPI は contrib ミドルウェアを検出して独自のスパンの作成を停止するため、リクエストスパンが二重に作成されることはなく、エクスポートだけが重複します。)このトレードオフは黙って選択せず、セットアップ計画に明記してください。
-
- PHP:Laravel では
composer require keepsuit/laravel-opentelemetry open-telemetry/exporter-otlp php-http/guzzle7-adapterを、Symfony ではcomposer require traceway/opentelemetry-symfony open-telemetry/exporter-otlp php-http/guzzle7-adapterを使います(標準の Symfony 自動計装ではhttp.routeがルートの NAME に設定され、Traceway はこれを破棄します。data-model.mdを参照してください)。PHP では、上記のブロックの隣に通常の環境変数としてOTEL_PHP_AUTOLOAD_ENABLEDを設定しても認識されません。Laravel では追加設定は不要です。keepsuit サービスプロバイダーが SDK を起動します。Symfony では、config/packages/open_telemetry.yamlのopen_telemetry.sdk.autoload_enabled: true、または php-fpm、Dockerfile、Apache で設定する実際のプロセス環境変数を使って SDK を起動します。OTEL_PHP_AUTOLOAD_ENABLEDを.envに設定しないでください。Dotenv が Composer の autoload 後にこの値を読み込むため、バンドルが SDK の起動をスキップし、すべてのシグナルが通知なく no-op になります。PHP ではOTEL_EXPORTER_OTLP_PROTOCOL=http/jsonが推奨されますが、http/protobufも動作します。ただしext-protobufがない場合は低速になります。- Symfony ワーカー:
messenger:consumeは絶対に計装しないでください。 バンドルではすでに除外されています。traces.console.excluded_commandsのデフォルト値は['messenger:consume', 'messenger:consume-messages']です。また、このキーは prototyped array node なので、config/packages/open_telemetry.yamlで設定すると、デフォルトへの追加ではなく、デフォルトが置き換えられます。理由を問わずこの設定を上書きする場合は、両方の項目を必ず再指定してください。コンシューマーは無限ループで実行されるため、コマンドスパンが終了せず、エクスポートもされず、ワーカーの稼働中はすべての子スパンを取り込みます。コマンドを除外しても、その内部の処理が記録されなくなるわけではありません。Messenger ミドルウェアは引き続きメッセージごとに 1 つの CONSUMER スパンを出力し、これらが Traceway でタスクになります。bin/console debug:config open_telemetry traces.consoleで実際に解決された設定を確認してください。
- Symfony ワーカー:
- Java/.NET/その他:標準の OTel エージェントまたは SDK は、上記の環境変数でそのまま動作します。
- フレームワークごとの詳細なドキュメント:https://docs.tracewayapp.com/client/otel
エンドポイントのグループ化を確認する(最初に実施)
パラメーター化されたルートに異なる ID を使って数回アクセスし、Traceway の Endpoints ページを確認してください。ID ごとに 1 行ずつではなく、1 行(GET /api/users/:id)だけ表示される必要があります。生の ID が表示される場合、計装で http.route が設定されていません。先に修正してから続行してください。最後の手段として、照合されたルートパターンを把握しているミドルウェアで手動設定してください(値は / で始まる必要があり、そうでなければ破棄されます):
import { trace } from "@opentelemetry/api";
trace.getActiveSpan()?.setAttribute("http.route", matchedRoutePattern);
エラー
スローされたエラーを例外イベントとして記録すると、Issues に表示されます。自動計装では未捕捉エラーが処理されます。捕捉して処理するエラーについては、次のようにします。
import { trace, SpanStatusCode } from "@opentelemetry/api";
const span = trace.getActiveSpan();
span?.recordException(error);
span?.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
(Go の場合:span.RecordError(err, trace.WithStackTrace(true))。スタックトレースオプションによって exception.stacktrace 属性が生成されます。)
例外が発生した場合は HTTP 500 を返してください。 リクエストで例外がスローされたりパニックが発生したりした場合は、500 を返し、スパンのステータスを ERROR に設定する必要があります。200/2xx にフォールスルーさせないでください。よくある落とし穴は、例外を報告してもレスポンスライターのデフォルトである 200 を維持する recover/panic ミドルウェアです。この場合、Traceway はエンドポイントのトランザクションを成功として記録するため、Issues が埋まっていく一方で Endpoints ページは正常に見えます。また、例外は失敗したリクエスト(分散トレーシングを使っている場合は、そのリクエストを引き起こしたフロントエンドの呼び出し)と関連付けられない孤立したイベントになります。「例外を記録した」場合は、必ず「500 を返し、スパンのステータスを ERROR に設定する」ことも合わせて行ってください。バグではない本来のクライアントエラー(検証エラー 422、認証エラー 401、見つからない場合の 404)は、実際の 4xx ステータスを維持し、そもそも例外として記録しないでください。
Go では、同じ落とし穴がより顕著に現れます。otelgin は c.Next() の返却後にのみステータスを記録しますが、パニックの巻き戻し中はそこに到達しません。そのため、未回復のパニックが発生すると、Gin 自身のリカバリーによってクライアントに 500 が返されていても、エンドポイントの行にステータス 0 が記録され、Issue にはタイトルが付くもののスタックトレースはありません。リカバリーミドルウェアを otelgin.Middleware の後に登録して、サーバースパン内で実行されるようにします。
// imports: fmt, net/http, go.opentelemetry.io/otel/codes, go.opentelemetry.io/otel/trace
func otelRecovery() gin.HandlerFunc {
return func(c *gin.Context) {
defer func() {
if r := recover(); r != nil {
err, ok := r.(error)
if !ok {
err = fmt.Errorf("%v", r)
}
span := trace.SpanFromContext(c.Request.Context())
span.RecordError(err, trace.WithStackTrace(true))
span.SetStatus(codes.Error, err.Error())
c.AbortWithStatus(http.StatusInternalServerError)
}
}()
c.Next()
}
}
router.Use(otelgin.Middleware(serviceName))
router.Use(otelRecovery())
ログ
OTEL_LOGS_EXPORTER=otlp で設定されるのはエクスポーターのみです。Logs ページを空のままにしないためには、トレースとメトリクスが正常に見えていても、アプリケーション独自のログ呼び出しにブリッジが必要です。
- Node:
@opentelemetry/winston-transport、または Pino や Bunyan の計装を追加して、各レコードにtrace_idとspan_idが設定されるようにします。 - Python、PHP、Java、.NET:
opentelemetry-instrumentと言語エージェントが、標準ロガーを自動的にブリッジします。FastAPI の組み込みテレメトリーは例外で、FastAPI 自身のレコードのみをエクスポートします。そのため、アプリのlogging出力を Traceway に送る場合は、opentelemetry-instrumentを使います。 - Go:
otlploghttp.WithEndpointURL(...)を使ってsdklog.LoggerProviderを構築し、global.SetLoggerProvider(lp)で登録してからdefer lp.Shutdown(ctx)を呼び出します。そうしないと、終了時に最後のバッチが失われます。
リクエストのコンテキストから出力してください(Gin では c.Request.Context()、net/http では r.Context()、Node ではアクティブなコンテキストを使います)。バックグラウンドコンテキストから出力された行にはトレース ID が含まれず、関連するエンドポイントから開くことができません。Traceway は severity_text(または severity_number から導出した値)、本文、service.name、トレース ID とスパン ID を読み取ります。
Go では OpenTelemetry を使用
Traceway 専用の Go SDK はありません。廃止されており、Go では他のバックエンドと同様に opentelemetry-go を使って計装します。go get go.opentelemetry.io/otel/sdk go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp を実行し、上のブロックと同じ環境変数を設定してください。ホストの CPU とメモリは、アプリではなく Traceway OTel Agent から取得します(「Deployment and Server Metrics」を参照)。
ステップ 5:バックグラウンドタスク(境界とラベル付け)
「アーキテクチャを分析する」でバックグラウンド処理が見つかった場合は、タスクとして計装します。ルールは次のとおりです。
- 境界:1 つのタスクは、バックグラウンド処理の単位を 1 回実行したものです。 cron ジョブ全体の 1 回の実行が 1 つのタスクです。キューのメッセージまたはジョブ 1 件が 1 つのタスクです。CLI コマンドの呼び出し 1 回が 1 つのタスクです。1 回の実行内の項目ごとの処理(バッチ内の各メール、インポート内の各行など)はタスクスパンの子スパンであり、個別の
CONSUMERスパンにはしません。 - 二重にラップしないでください。 ライブラリの自動計装がすでに
CONSUMERスパンを出力している場合(Kafka、RabbitMQ、Symfony Messenger のコンシューマーなど)、さらにラップするとタスクのエントリーが重複します。 - ラベル付け:スパン名がタスク名であり、グループ化キーです。
cleanup-expired-sessionsやprocess-email-queueのような安定した識別子を使います。ジョブ ID、タイムスタンプ、ユーザー ID を名前に含めないでください。名前が異なるたびに、別のタスクグループになります。動的なコンテキスト(ジョブ ID、バッチサイズなど)はスパン属性に設定します。タスク詳細ページに表示され、グループ化には影響しません。 - 種別は
CONSUMERにする必要があります。 デフォルトのSpanKind.INTERNALを使ったルートスパンは、警告なく破棄されます。「cron ジョブが表示されない」という最も一般的な原因です。CLI コマンドは、代わりにconsole.command属性を持つルートINTERNALスパンにすることもできます(Laravel/Symfony のコンソール計装ではこの方式が使われます)。
import { trace, SpanKind, SpanStatusCode } from "@opentelemetry/api";
const tracer = trace.getTracer("my-app");
async function runScheduledJob() {
await tracer.startActiveSpan(
"cleanup-expired-sessions",
{ kind: SpanKind.CONSUMER },
async (span) => {
try {
await doWork();
span.setStatus({ code: SpanStatusCode.OK });
} catch (error) {
const err = error instanceof Error ? error : new Error(String(error));
span.recordException(err);
span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });
throw error;
} finally {
span.end();
}
}
);
}
(Go の場合:tracer.Start(ctx, "cleanup-expired-sessions", trace.WithSpanKind(trace.SpanKindConsumer))。)
Step 6: AI トレース
「アーキテクチャを分析」で AI/LLM 依存関係が見つかった場合は、モデル呼び出しを計装します。スパンに gen_ai.* 属性が少なくとも 1 つ含まれ、かつそれ以前の分類ルールに該当しない場合、そのスパンは AI トレース になります。実際には、HTTP ルートスパンに gen_ai.* を付けない(エンドポイントになります)、CONSUMER スパンに付けない(タスクになります)、そしてモデル呼び出し専用の子スパンを作り、INTERNAL ではなく SpanKind.CLIENT を指定します。これにより、失敗した呼び出しで exception.* 属性が記録された場合でも、AI トレースが生成されます。呼び出しはリクエストまたはタスク内で行われるため、その子スパンはトレース ID によってエンドポイントまたはタスクに関連付けられます。
境界:モデル呼び出しごとに 1 スパン(プロバイダー API リクエスト 1 件につき、AI トレースの行が 1 件)。複数ステップのエージェント実行は、安定した trace.name を共有する複数のスパンになります(タスク名と同じ命名ルールに従い、ID やタイムスタンプは含めません)。ストリーミングの場合は、ストリームが完了した時点でスパンを終了します。
会話型の製品ですか? 「アーキテクチャを分析」でチャットボット、アシスタント、またはツール呼び出し型エージェントが検出された場合は、以下の表で終わらせず、このスキルディレクトリにある ai-agent.md に従ってください。ここでは、gen_ai.conversation.id(複数ターンのグループ化)、user.id に設定する値(安定したエンドカスタマー ID。セッション ID は使用しません)、ツール呼び出しのペイロード形式、サブエージェントについて説明しています。これらがないと、「ユーザー」タブは空のままで、「会話」タブにはリクエストごとに使い捨ての単一ターン会話が表示されます。Traceway が OTel トレース ID にフォールバックするためです。何も表示されないよりも悪い状態です。機能が動作しているように見えてしまいます。
Traceway が読み取る属性(すべて省略可能です。利用できるものを設定してください):
| 属性 | 意味 |
|---|---|
gen_ai.request.model / gen_ai.response.model | 要求されたモデル/応答に使用されたモデル |
gen_ai.system または gen_ai.provider.name | プロバイダー(openai、anthropic など) |
gen_ai.operation.name | オペレーション(chat、embeddings など) |
gen_ai.usage.input_tokens / .output_tokens / .total_tokens | トークン数 |
gen_ai.usage.input_tokens.cached / gen_ai.usage.output_tokens.reasoning | キャッシュ済みトークン/推論トークン |
gen_ai.usage.input_cost / .output_cost / .total_cost | 料金を計算した場合のコスト |
trace.name | エージェント/ワークフローのグループ名 |
gen_ai.conversation.id | 複数ターンの会話のグループ化(session.id、次に OTel トレース ID にフォールバック) |
user.id | エンドユーザーの帰属情報:安定した顧客 ID(アカウント ID、テナント ID、またはメールアドレス)。そのユーザーのすべての会話で同じ値を使用します |
gen_ai.response.finish_reason | 生成が終了した理由 |
gen_ai.prompt / gen_ai.completion | 会話の内容。トレース詳細ページに表示されます(内容をアプリ外に出してはいけない場合は省略してください) |
gen_ai.prompt/gen_ai.completion がない場合、会話の内容は trace.input/trace.output(または span.input/span.output)からも読み取られます。また、total_tokens/total_cost がない場合は、入力値と出力値から計算されます。トークン数は整数属性、コストは倍精度浮動小数点数または整数の属性である必要があります。文字列として送信された数値は、エクスポート時にエラーなしで暗黙に破棄され、0 として保存されます。
import { SpanKind } from "@opentelemetry/api";
return tracer.startActiveSpan("chat-completion", { kind: SpanKind.CLIENT }, async (span) => {
const response = await openai.chat.completions.create({ model: "gpt-4o", messages });
span.setAttributes({
"gen_ai.system": "openai",
"gen_ai.request.model": "gpt-4o",
"gen_ai.usage.input_tokens": response.usage?.prompt_tokens ?? 0,
"gen_ai.usage.output_tokens": response.usage?.completion_tokens ?? 0,
"trace.name": "support-agent",
});
span.end();
return response;
});
OpenRouter ユーザー向けのゼロコード方式:OpenRouter Settings -> Observability で、OpenTelemetry Collector の送信先を追加し、https://<instance>/api/otel/v1/traces を指定します。ヘッダーは {"Authorization": "Bearer <project-token>"} です。ドキュメント:https://docs.tracewayapp.com/client/openrouter
Step 7: フロントエンドとモバイル
フロントエンドとモバイルのプロジェクトでは OTel を使用せず、Traceway SDK を使用して、接続文字列 <project-token>@https://<instance>/api/report で /api/report にレポートを送信します。
ブラウザー(React/Vue/Svelte/jQuery/プレーンな JS):以下の 3 つすべてを設定してください。
- SDK:
npm install @tracewayapp/react(または、プレーンな JS の場合はvue、svelte、jquery、frontend)を実行し、接続文字列を使って初期化します(React の場合は、アプリを<TracewayProvider connectionString="...">でラップします)。エラー、ウェブバイタル、セッションリプレイを記録します。 - バンドラープラグイン:
npm install -D @tracewayapp/bundler-pluginを実行し、@tracewayapp/bundler-plugin/viteのtracewayDebugIds()(または/rollup、あるいは/webpackのTracewayDebugIdsWebpackPlugin)を、ソースマップを有効にした状態(build.sourcemap: true/devtool: "source-map")でバンドラーの設定に追加します。 - ソースマップのアップロード:
npm install -D @tracewayapp/sourcemap-uploadを実行し、ビルド後の処理または CI のステップとしてtraceway-sourcemaps --url <instance> --token <source-map-upload-token> --directory ./distを実行します(環境変数:TRACEWAY_URL、TRACEWAY_SOURCEMAP_TOKEN)。アップロードトークンはブラウザープロジェクトから取得し、CI のシークレットとして管理します。決してコミットしないでください。
フレームワークごとの初期化コード(プレーン JS、React、Vue、Svelte/SvelteKit、jQuery)、共通 SDK オプション、エラーフィルタリング、カスタム属性、分散トレーシング、デバッグ ID とソースマップの完全なパイプラインについては、このスキルディレクトリにある frontend-js.md をお読みください。オンラインドキュメント:https://docs.tracewayapp.com/client/react(または vue、svelte、jquery、js-sdk)。
フルスタック JS(Next.js、SvelteKit、Remix):「アーキテクチャを分析する」で、本番環境でフレームワークのサーバーが実際にアプリを配信していると確認できた場合に限ります。フロントエンドのみのデプロイでは上記のブラウザー側の設定だけを行い、バックエンドが別にある場合は「バックエンド OTel セットアップ」に従います。実際にフルスタックの場合は、確認済みの 2 つのプロジェクトの下で両側を統合します。サーバー側はバックエンドプロジェクトのトークンを使って「バックエンド OTel セットアップ」に従い、ブラウザー側はフロントエンドプロジェクトのトークンを使って上記の 3 つの設定を行います。Next.js では特に、上記の「Next.js サーバーの例外」にある instrumentation.ts フレームワークフックを使ってください。汎用の Node プリロードは決して適用しないでください。
Next.js のブラウザービルドでは、現在 @tracewayapp/bundler-plugin にあるのは webpack のエントリーポイントであり、Turbopack 用のものはありません。productionBrowserSourceMaps: true を設定し、TracewayDebugIdsWebpackPlugin は !isServer && !dev の場合に限って追加します(このプラグインは本番環境専用であり、Next.js の開発用ソースマップモードに置き換わるものであってはなりません)。また、本番ビルドでは next build --webpack を実行するようにしてください(Next.js 16 ではデフォルトが Turbopack であり、そのままではこのプラグインが無視されます)。ビルド後、クライアントの .js ファイルに //# debugId= が含まれ、対応する .js.map ファイルに debugId が含まれていることを確認してから、React プロジェクトのソースマップアップロードトークンを使って .next/static/chunks をアップロードします。
モバイルでは、必ずプラットフォーム SDK を使い、OTel は使わないでください。
- Flutter:
flutter pub add tracewayを実行し、Traceway.run(connectionString: '<token>@https://<instance>/api/report', child: MyApp())を呼び出します。次に、リリースビルドが難読化されているか(--obfuscate --split-debug-info)を確認します。難読化されている場合、本番環境のクラッシュスタックトレースは難読化された状態で届き、ビルドの.symbolsファイルをアップロードするまで判読できません。そのため、モバイルプロジェクトのアップロードトークンを使用して、シンボルのアップロードを設定してください。オプション、プラットフォーム権限、ナビゲーターオブザーバー、画面録画、プライバシーマスキング、難読化の確認とシンボルのアップロード、Flutter Webに関する注意事項については、このスキルディレクトリのflutter.mdをお読みください。ドキュメント:https://docs.tracewayapp.com/client/flutter - React Native:
npm install @tracewayapp/react-nativeを実行し、アプリをTracewayProviderでラップします。ドキュメント:https://docs.tracewayapp.com/client/react-native - Android(ネイティブ Kotlin/Java):Maven Centralから
implementation("com.tracewayapp:traceway:1.0.1")を追加し、Application.onCreate()からTraceway.init(application = this, connectionString = "<token>@https://<instance>/api/report", options = TracewayOptions(version = "1.0.0"))を呼び出します(マニフェストにApplicationクラスを登録してください。権限エントリは不要です。AARのマニフェストがINTERNETとACCESS_NETWORK_STATEを宣言しており、マージ時に統合されます)。すべてのスレッドで発生する未捕捉のJava/Kotlin例外と、手動のTraceway.captureException(...)をキャプチャします。エラーとクラッシュのみを対象とし、セッションリプレイには対応していません。リリースビルドではR8が実行されるため、本番環境のクラッシュはクラス名が変更され、行番号が書き換えられた状態で届きます。ビルドのmapping.txtをアップロードするまで判読できません。com.tracewayapp.symbolsGradleプラグイン(バージョン"1.0.1"。mavenCentral()から解決)を適用してください。このプラグインによりBuildConfig.TRACEWAY_PROGUARD_UUIDが注入され、モバイルプロジェクトのアップロードトークンを使ってマッピングがアップロードされます。各クラッシュを対応するマッピングに紐付けるため、そのUUIDをTracewayOptions(proguardUuid = ...)に渡してください。初期化コード、オプション、マニフェスト、Gradleプラグインの設定全般については、このスキルディレクトリのandroid.mdをお読みください。ドキュメント:https://docs.tracewayapp.com/client/android - iOS / Swift(ネイティブSwiftUIまたはUIKit):Swift Package Managerを使用してTraceway iOS SDK(
https://github.com/tracewayapp/traceway-ios.git)を追加し、できるだけ早い段階でTraceway.start(connectionString: "<token>@https://<instance>/api/report", options: TracewayOptions(version: "1.0.0"))を呼び出します。未捕捉のNSExceptionと致命的シグナルをキャプチャします(致命的クラッシュは次回起動時にアップロードされます)。手動のTraceway.capture(...)にも対応しています。エラーとクラッシュのみを報告し、セッションリプレイには対応していません。リリース時のクラッシュはアドレスのみの状態で届くため、ビルドのdSYMをアップロードする設定をモバイルプロジェクトのアップロードトークンを使って行ってください。初期化コード、オプション、デバッガーに関する注意事項、dSYMのアップロードについては、このスキルディレクトリのios.mdをお読みください。アプリがSwiftアプリではない場合(Objective-Cのみ、TracewayモバイルSDKを使用しないクロスプラットフォームスタック、またはOpenTelemetryに標準化しているチーム)は、ネイティブSDKはありません。HoneycombなどのOTelディストリビューションを使用し、エクスポーターの送信先を<instance>/api/otelに設定して、Authorization: Bearer <project-token>ヘッダーを指定してください。バックエンドと同じ方法です(「Backend OTel Setup」を参照)。Swift以外の方法についてもios.mdに記載されています。
Step 8: デプロイとサーバーメトリクス
「プロジェクトマップの提案と確認」で確定したデプロイ方法とホストメトリクスの選択を使用してください。未確定のままの場合は、デプロイ設定を変更する前に確認してください。
- このプロジェクトはどのようにデプロイされていますか? VM 上の Docker/VM またはベアメタルに直接/Kubernetes/サーバーレスまたは PaaS。
- サーバー(ホスト)メトリクスを Traceway で追跡しますか? アプリを実行しているマシンの CPU、メモリ、ディスク、ファイルシステム、ネットワーク。
| デプロイ方法 | ホストメトリクスを希望するか | 対応内容 |
|---|---|---|
| VM 上の Docker、または VM/ホストに直接デプロイ | はい | ホストに Traceway OTel Agent をインストールします(以下を参照)。Docker でのデプロイではこれがデフォルトです。エージェントはコンテナ内ではなく、ホストにインストールします。 |
| Kubernetes | どちらでも | ホストサービスであるエージェントは使用しません。このスキルディレクトリにある kubernetes.md の 2 つのコレクターワークロードをデプロイします。ノードメトリクス、Pod メトリクス、コンテナログ用の DaemonSet と、クラスターの状態およびイベント用のレプリカ数 1 の Deployment です。プロセス内のアプリメトリクスは、引き続き「バックエンドの OTel セットアップ」の OTLP メトリクスエクスポーター経由で送信されます。 |
| サーバーレス/PaaS | どちらでも | インストール先となるホストがないため、スキップします。 |
| その他すべて | いいえ | スキップします。 |
Kubernetes の場合は、ここで作業を止め、このスキルディレクトリにある kubernetes.md を読んでください。動作を左右する 4 つの項目(ノードごとの service.name、デフォルトで無効になっている 3 つの *.utilization メトリクス、k8s.cluster.name、root_path: /hostfs)は見落としやすく、どれか 1 つでも誤ると、もっともらしく見えても有用なデータを何も報告しない設定になってしまいます。
エージェントは、60 秒ごとにホストメトリクスをスクレイピングする、事前設定済みの小型 OTel Collector です。API、ワーカー、タスク、AI トレースと同じバックエンドプロジェクトトークンを必ず使用してください。ホストにインストールします(Linux の systemd/macOS の launchd。Windows 用の PowerShell インストーラーもあります)。
curl -fsSL https://install.tracewayapp.com/install.sh | \
TRACEWAY_TOKEN=<project-token> \
TRACEWAY_ENDPOINT=https://<instance>/api/otel \
TRACEWAY_SERVICE_NAME=<host-label, e.g. api-prod-eu-1> \
bash
TRACEWAY_ENDPOINTは/api/otelで終わる必要があり、セルフホストインスタンスでは必須です。Traceway Cloud の場合に限り、省略できます。- 任意の設定:
TRACEWAY_LOG_PATHS(ログとして追跡する glob をカンマ区切りで指定)、TRACEWAY_PROCESS_NAMES(プロセスごとのメトリクス)。 - インストーラーを再実行すると既存環境をそのままアップグレードするため、プロビジョニングスクリプトにコマンドを残しても安全です。
- リポジトリにホストのプロビジョニングまたはデプロイスクリプト(cloud-init、Ansible、Terraform の
user_data、deploy.sh)がある場合は、シークレットからトークンを参照する形でコマンドを追加してください。ない場合は、入力済みのワンライナーを運用担当者に渡してください。リポジトリは変更しないでください。
メトリクスは約 60 秒以内に、ホストメトリクス名(system.cpu.utilization、system.memory.usage など)で届きます。ホストは TRACEWAY_SERVICE_NAME に由来する server_name タグで識別されます。host.name、host.id、host.arch、os.type、クラウドリージョンなどのリソースメタデータも保持されますが、これらが正式な識別情報の代わりになることはありません。ホストを区別できるよう、ホストごとに異なる TRACEWAY_SERVICE_NAME を設定してください。組織の概要ではこれらのホストメトリクスを直接認識しますが、従来の Go SDK の CPU/メモリウィジェットでは、SDK 固有の正確なメトリクス名が引き続き使用されます。メトリクス一式を確認するには、OTelemetry Server Agent ダッシュボードテンプレートをインストールしてください。Cmd K でコマンドパレットを開いて検索すると、system.cpu.utilization、system.memory.*、system.filesystem.*、system.disk.*、system.network.* に接続済みのダッシュボードがインストールされます。テンプレートで扱われない項目は、カスタムウィジェットで補えます。エージェントのリポジトリ:https://github.com/tracewayapp/traceway-otel-agent
Step 9: 検証
以下に示す各ダッシュボードページは <instance>/<page> にあります:/endpoints、/issues、/tasks、/ai-traces、/logs、/dashboards。いずれかを確認する前に、時間範囲を直近 15 分に設定してください。プロジェクトごとに個別に検証し、最後にプロジェクトとコンポーネントの対応表をまとめてください。
CLI が計画を適用した時点で、ローカルの env ファイルには実際の値が設定されているため、先送りせずにローカルでの検証を実行してください。デプロイ環境の検証は、ユーザーがウェブサイトの Next Steps パネルを完了した後にのみ行います。その検証に合格するために、そこで設定されている必要がある変数を改めて示してください。
- バックエンドプロジェクト
curl <app>/api/users/1を実行し、続けて/2、/3を実行してから、/endpointsを開きます。ステータスコードがゼロ以外の行は、GET /api/users/:idの1行だけである必要があります。3行表示される場合は、http.routeが設定されていません。他を確認する前に修正してください。- 壊れているように見えても問題ではない結果が2つあります。どのルートにも一致しないURLへのリクエストは、入力したURLではなく
UNMATCHEDとして届きます。また、プロジェクトで「drop healthy healthchecks」が有効になっている場合、成功した/healthリクエストは取り込み時に破棄されるため、スモークテストにヘルスチェックルートは使わないでください。 - ハンドリング済み例外またはテスト例外を発生させてから、
/issuesを開きます。例外がエンドポイントまたはタスクのコンテキストとともに一覧表示され、そのリクエストのエンドポイント行にはステータス 500 が表示されます。 - エンドポイント行を1つ開きます。データベースクエリと送信HTTPコールが子スパンとして表示されます。
- 各バックグラウンドジョブを1回ずつ実行してから、
/tasksを開きます。ジョブごとに1行表示され、IDやタイムスタンプを含まない安定した名前になっている必要があります。 - ログが接続されている場合は、リクエスト内で INFO と ERROR の行を1つずつ出力してから、
/logsを開きます。どちらも、そのエンドポイントと同じトレースIDを持ちます。 - 「AI Traces」が適用されている場合は、モデル呼び出しを1回行ってから、
/ai-tracesを開きます。利用可能な場合、モデル、トークン数、コストとともに呼び出しが一覧表示されます。 /dashboardsを開き、アプリケーション/ランタイムのメトリクスが届いていることを確認します。OTel Agent がインストールされている場合、ホストメトリクスは約60秒以内に同じバックエンドプロジェクトに届き、各ホストにはそれぞれ固有のserver_nameタグが付きます。- ホストまたは Kubernetes のメトリクスを設定した場合は、
/organizationを開きます。すべてのホストとノードが、CPU、メモリ、ディスクの情報とともに、それぞれ独立したインスタンス行として表示されます。Kubernetes ノードはクラスターごとにグループ化されます。複数表示されるはずの場所に1行だけ表示される場合は、service.nameがマシンごとに異なっていません。リングが空の場合は、*.utilizationメトリクスが有効になっていません。
- ブラウザープロジェクト
- テスト用のブラウザーエラーを発生させ、それがバックエンドプロジェクトではなく、このプロジェクトに表示されることを確認します。
- 一致するソースマップとバンドルをアップロードした後、スタックトレースが元のソースファイルと行に解決されることを確認します。
- 分散トレーシングを設定した場合は、ブラウザーのイシューまたはリクエストがバックエンドのトレースにリンクされることを確認します。
- 各モバイルプロジェクト
- プラットフォームの安全なテスト用エラーまたはクラッシュのフローを実行し、一致するモバイルプロジェクトにのみ表示されることを確認します。
- 難読化された Flutter、minify された Android、または Release iOS ビルドの場合は、一致するシンボル、R8 マッピング、または dSYM によって本番環境のスタックトレースが解決されることを確認します。
- 認証情報とトポロジーの監査
- ブラウザーとモバイルのインテグレーションでバックエンドトークンを使用していないこと、および OTLP エクスポーターでブラウザープロジェクトのトークンを使用していないことを確認します(Step 4 のルール 3)。
- ユーザーが分離境界を承認していない限り、API、ワーカー、スケジューラー、AI 呼び出し、ホストメトリクスがバックエンドプロジェクトを使用していることを確認します。
- ローカル、デプロイ、または CI の変数がまだ設定されていないために実行できなかった検証があれば報告します。
tracewayCLI がインストールされている場合は、traceway loginを実行し、traceway projects use <project-id>でバックエンドプロジェクトを選択するか、各呼び出しで--project <project-id>を渡してから、次を実行します。
タスクと AI トレースにはtraceway endpoints list --since 15m traceway exceptions list --since 15m traceway logs query --since 15m traceway metrics query --name system.cpu.utilization --since 15mlistサブコマンドがなく、show <id>のみを利用できます。そのため、ダッシュボードの/tasksと/ai-tracesでこの2つを確認してください。- ユーザーにテスト方法を案内します。 自分での検証後、ユーザー自身が接続の動作を確認できるよう、具体的な手順を最後に伝えます。ユーザーのアプリに対してコピー&ペーストで実行できる操作を2~3個示し、それぞれの操作が表示される Traceway のページも併記します。たとえば、実際のパラメーター付きエンドポイントに数回アクセスすると(
curl <their-app>/api/users/1、/2、/3)、数秒以内に/endpointsに1行で表示されます。アプリのエラー経路または意図的なテスト例外を発生させると、失敗したリクエストにリンクされた状態で/issuesに表示されます。また、バックグラウンドジョブを実行するか、1つ実行されるまで待つと、/tasksに表示されます。ユーザーの実際のルートとコマンドを使い、ダッシュボードの時間選択を過去15分に設定するよう伝えます。また、承認後、正しいプロジェクトのダッシュボードがすでに開いていることも伝えてください。