mcpField
O
otel-onboarding-style

otel-onboarding-style

github.com/superloglabsクラウド・DevOps13373 回インストール21 週間前に更新
リポジトリ

otel-onboarding-style について

サービスへの計装に関する OpenTelemetry 導入規約を定めるスキルです。シグナル、リソース属性、エラー、HTTP フレームワーク、LLM プロバイダーを扱い、一貫したテレメトリー設定を案内します。

主な機能

  1. 01ネイティブ OpenTelemetry API の指針
  2. 02リソースと環境属性
  3. 03トレース、ログ、メトリクスの実践
  4. 04HTTP とエラーの計装
  5. 05LLM プロバイダーのテレメトリー指針

活用シーン

  1. 01サービスのテレメトリー設定
  2. 02操作単位の RED シグナル構築
  3. 03トレース相関付き構造化ログの追加
  4. 04対応する LLM プロバイダーの計装

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/superloglabs/skills --skill otel-onboarding-style

インストール後、Claude Code で/otel-onboarding-styleを入力して読み込まれたか確認します。

詳細

OTel オンボーディングのスタイル

OpenTelemetry のネイティブ API を使用してください。ヘルパー API を独自に作成しないでください。

TypeScript/JavaScript では、範囲を限定したビジネススパンに公開済みの @superlog/otel-helpers の withSpan ヘルパーを使用し、まだ package.json に含まれていない場合は @superlog/otel-helpers を追加してください。パッケージをインストールできる場合は、これが必須です。withSpan は、関数全体を tracer.startActiveSpan(...) と try / catch / finally に展開する代わりに使用することを想定しています。OpenInference/プロバイダーの計装で直接監視できるプロバイダー SDK の呼び出しをヘルパーでラップしないでください。

次のようにします:

const tracer = trace.getTracer("mugline.api");
const meter = metrics.getMeter("mugline.api");
const ordersSubmitted = meter.createCounter("orders.submitted");

await withSpan("order.submit", async (span) => {
  span.setAttributes({
    "tenant.id": tenantId,
    "order.id": orderId,
    outcome: "success",
  });
  ordersSubmitted.add(1, { "tenant.id": tenantId, outcome: "success" });
}, { tracer });

次のようにはしないでください:

await sendSuperlogSpan(...);
recordCounter(...);
withTelemetry(...);

命名

  • ファイル名/関数名はプロバイダーに依存しないものにします:telemetry.ts、observability.ts、 initTelemetry()、initObservability()。
  • Superlog という語は、エンドポイント/キーの設定コメントまたは PR の指示にのみ使用します。
  • スパン名は慣例に従い、カーディナリティを低くします:checkout.process、voice.session、llm.generate_copy。
  • プロバイダーのトランスポート名より、意味が分かる製品操作のスパン名を優先します。 通常、llm.anthropic.messages.create よりも llm.generate_copy や llm.voice_response のほうが有用です。

エンドポイントと公開トークン

エンドポイントと Superlog の公開インジェストトークンは、ブートストラップのソースコードに直接記述してください。トークンは sl_public_ で始まり、プロジェクト単位でスコープされ、書き込み専用です。PostHog のプロジェクトトークンや Sentry DSN と同様に、ブラウザー/モバイル/サーバーのソースコードに含めても安全なものとして設計されています。

SUPERLOG_ENDPOINT = "https://intake.superlog.sh"
SUPERLOG_PUBLIC_TOKEN = "sl_public_…"

SUPERLOG_API_KEY や SUPERLOG_INTAKE_URL のような従来の名前を、ドキュメントやコメント内のプレースホルダーテキストとしても独自に作成しないでください。ペアリングが完了するまでは、生成された sl_public_ トークンをソースコードで使用してください。サインアップインテントのフローでユーザーのプロジェクトに紐付けられるまでは、インジェストで拒否される場合があります。

エクスポーターのコンストラクターの endpoint / headers オプションを使い、インラインの値を SDK に明示的に渡してください。暗黙的な OTEL 環境変数の読み取りによって Superlog を設定しないでください。このスキルで回避する主なオンボーディング失敗の原因は、環境変数の欠落です。

トークンは x-api-key ヘッダーに指定します。インジェストで受け付けられるのは x-api-key: <token> または Authorization: Bearer <token>(リテラルの Bearer 接頭辞が必須)のみです。x-api-key を優先してください。トークンが有効でも、それ以外のヘッダー名を使用すると、リクエストはすべて 401 を返します。これは環境変数の欠落に次いで、2 番目に多いオンボーディング失敗の原因です。ヘッダー名を一か所にまとめるため、1 行のヘルパーを定義してください:

function superlogHeaders(token: string): Record<string, string> {
  return { "x-api-key": token };
}
def superlog_headers(token: str) -> dict[str, str]:
    return {"x-api-key": token}

リポジトリ内の複数の経路からテレメトリーの初期化を呼び出せる場合は、プロバイダー/エクスポーターの設定をガードし、インポート、テスト、再読み込み、フレームワークのコールバックが繰り返されても、プロセッサーやログハンドラーが重複して登録されないようにしてください。エントリーポイントが 1 つで、正常に起動するアプリなら、シンプルに保ってください。

値が利用可能な場合は、標準のリソース属性を含めてください: service.name、service.version、deployment.environment.name、および以下の VCS 属性。

環境のタグ付け

可能な限り、すべてのシグナルに実行環境のタグを付けてください。deployment.environment.name を OTel リソースに一度設定し、トレース、ログ、メトリクスに反映させることを優先してください。NODE_ENV、VERCEL_ENV、RAILWAY_ENVIRONMENT_NAME、FLY_APP_NAME/リリースメタデータ、ENVIRONMENT、APP_ENV、PYTHON_ENV など、既存のプラットフォーム環境変数から値を推定し、明らかな値は local、development、preview、staging、production のようなカーディナリティの低い名前に正規化してください。

実行環境/エクスポーターの経路で、すべての観測データにリソース属性を付与できない場合は、同じカーディナリティの低い環境値を、カスタムスパン属性、ログレコード、メトリクスのデータポイントに手動で追加してください。リポジトリに既定の規則がない限り、env、environment、app.environment などの別の属性名を作成しないでください。SDK が対応している場合は、常に deployment.environment.name を使用してください。

VCS リソース属性

計装対象のすべてのサービスについて、OTel リソースに vcs.repository.url.full を設定します。値には、リポジトリの正規の https URL(例:https://github.com/acme/api)を指定します。ユーザーがブラウザーに貼り付けるものと同じ URL であり、SSH URL やローカルの作業ツリーパスではありません。これは重要な属性です。Superlog がテレメトリーを信頼できる情報源に関連付けるために使用します。SDK の初期化時に service.name とともにこの文字列をハードコードしても問題ありません。ビルド環境でスラッグがすでに公開されている場合(例:VERCEL_GIT_REPO_OWNER と VERCEL_GIT_REPO_SLUG、RAILWAY_GIT_REPO_OWNER と RAILWAY_GIT_REPO_NAME)は、フォークや名称変更によるずれを避けるため、環境変数から読み取ることを優先してください。

また、可能な範囲で vcs.ref.head.revision(コミット SHA)も設定します。実行環境またはビルドプラットフォームがすでに注入している環境変数から読み取ってください。例:VERCEL_GIT_COMMIT_SHA、RAILWAY_GIT_COMMIT_SHA、GITHUB_SHA、SOURCE_COMMIT、GIT_COMMIT、HEROKU_SLUG_COMMIT など。実行中のプロセスから git をシェルで呼び出してはいけません。本番用イメージには git や作業ツリーがないことがよくあります。環境変数から取得できない場合は、この属性を省略してください。SHA の省略は問題ありませんが、URL の省略は認められません。

vcs.repository.url.full と vcs.ref.head.revision は、必ず名前をそのまま使用してください。これらは OTel のセマンティック規約で定められたキーです。git.repo や app.repo_url のような独自の属性を作らないでください。

シグナル

計装対象のすべてのサービスにおける基本目標は、ソフトウェアコンポーネントごとの RED(処理数、エラー数、処理時間)です。次の 2 点を満たす必要があります。

  • RED をサービスごとに集計できるよう、すべてのシグナルに service.name を設定します。
  • 個別の作業単位ごとに、カーディナリティの低い操作識別子(HTTP ルートテンプレート、キューハンドラー名、スケジュールジョブ名、RPC メソッドなど)を持つ、独自のスパン/メトリック系列を生成します。RED はサービス単位だけでなく、操作単位でも確認できる必要があります。

サービスの主要な処理(インバウンド HTTP リクエスト、キューハンドラー、スケジュールジョブ、バックグラウンドループなど)について、操作ごとにこれら 3 つの数値を生成する仕組みがなければ、オンボーディングは未完了です。

  • トレース:重要な操作には、関連属性を持つスパンが必要です。すべてのサービスで、インバウンドの作業単位ごとに少なくとも 1 つのスパンを生成してください。通常は HTTP/フレームワークの自動計装を使用し、そうでない場合は、リクエスト/ハンドラーのエントリーポイントを withSpan(または各言語の同等機能)で手動計装します。
  • ログ:構造化され、簡潔で、OTLP に転送され、トレース/スパンと関連付けられていること。
  • メトリクス:重要な操作について、カーディナリティの低いカウンター/ヒストグラムを用意すること。
  • テナント/組織/プロジェクトの情報は、利用可能な場合に含めてください。
  • リポジトリですでに上限のあるテナント相当の ID として扱われている場合を除き、メトリックのタグに生のユーザー ID やリクエスト ID を含めないでください。

HTTP とフレームワークの計装

各サービスに、その言語およびフレームワーク向けの標準的な OpenTelemetry HTTP/サーバー計装をインストールし(例:Node では @opentelemetry/instrumentation-http とフレームワーク用パッケージ、Python では opentelemetry-instrumentation-fastapi/-django/-flask など)、不足していれば package.json/pyproject.toml に追加してください。これにより http.server.request.duration、http.request.method、http.response.status_code が設定され、ルートごとのコードを書かなくても RED を計測できます。

サービスのフレームワークまたは実行環境に自動計装が用意されていない場合(カスタムサーバー、特殊な実行環境、非 HTTP トランスポートを使う RPC、バックグラウンドワーカーのループなど)は、エントリーポイントにスパンを手動で設定し、すべての作業単位で http.* または操作に適した属性とステータスを持つスパンが 1 つ生成されるようにしてください。サービスには「ビジネススパンしかない」という理由で、この手順を省略しないでください。それではサービスごとの RED を計測できません。

エラー

作業単位を表すすべてのスパンで、一貫して失敗を通知し、エラー数を算出できるようにしてください。

  • 例外を捕捉した場合は、span.recordException(err) と span.setStatus({ code: SpanStatusCode.ERROR, message })(または言語に応じた同等の処理)を呼び出してください。自動計装では通常、HTTP 5xx に対してこの処理が行われますが、処理済みのエラーや手動で設定したスパンには、引き続きこの処理が必要です。
  • ビジネススパンと対応するメトリクスのデータポイントに、"success" または "error" の outcome 属性を設定してください。これにより、ステータスコードを結合条件にせず、カーディナリティの低い単一のディメンションで RED を成功とエラーに分けられます。
  • 既知のエラークラスについては、error.type に短くカーディナリティの低い文字列(例:"timeout"、"validation"、"upstream_5xx")も設定してください。例外メッセージは値の範囲に上限がないため、使用しないでください。
  • withSpan コールバック内で例外を黙って握りつぶさないでください。記録した後に再スローして、外側のスパンと呼び出し元にも失敗が伝わるようにしてください。

LLM メトリクス

アプリが LLM を使用している場合は、まずモデル/プロバイダー/トークン/エラーのスパンをすでに取得しているプロバイダー計装がないか確認してください。JavaScript/TypeScript では、対応する SDK に @arizeai/openinference-instrumentation-anthropic などの OpenInference パッケージを優先してください。実際のプロバイダー呼び出しは、ネイティブな形式で読みやすく保ってください。

const response = await client.messages.create({
  model,
  max_tokens: 100,
  messages,
});

すべてのプロバイダー呼び出し箇所で、使用状況に関する質問に答えられるだけのテレメトリーを取得する必要があります。対応している場合は、モデル/プロバイダー/トークンのスパンをプロバイダー計装に任せてください。アプリケーションの各呼び出し箇所でこれらの属性を重複させたり、プロダクトのハンドラーにプロバイダーの料金表やコスト計算を含めたりしないでください。Superlog は、取得したプロバイダー/モデル/トークンのデータを使って、UI/クエリレイヤーで LLM の推定コストを一元的に計算します。

llmInputTokens.add(inputTokens, {
  "tenant.id": tenantId,
  "gen_ai.provider.name": "anthropic",
  "gen_ai.request.model": model,
  "app.gen_ai.use_case": "voice.initial_greeting",
  "app.gen_ai.call_site": "_callMugCopyLlm",
  outcome: "success",
});

プロバイダー計装でトークン使用量を取得できない場合に限り、加算可能な合計値にカウンターを使用してください。

  • llm.tokens.input
  • llm.tokens.output

トークンカウンターでは、unit="tokens" または SDK に応じた同等の設定を使用してください。OpenInference/プロバイダー計装ですでにトークン使用量を取得している場合は、単にそれを複製するためのトークンカウンターを追加しないでください。通常の LLM 呼び出しについて、llm.cost_usd やそれに相当するアプリ側のコストメトリクスを追加しないでください。コストは Superlog の一元管理された料金レイヤーで扱います。

レイテンシー/所要時間の分布にはヒストグラムを使用してください。

LLM のプロバイダー/モデル/トークン属性には、現在の gen_ai.* セマンティック規約スタイルの属性名を優先し、ユースケースや呼び出し箇所など、値の範囲が限定されたアプリケーションのディメンションには app.gen_ai.* を使用してください。リポジトリですでに標準化されている場合を除き、並行する llm.* 属性を独自に作成しないでください。

アプリに OpenAI、Anthropic、Google の呼び出し元がある場合は、3 つすべてを計装してください。

スモークテスト

リポジトリに適切な場所がある場合は、README、テストガイド、スクリプト、npm コマンド、pytest、またはリポジトリに含まれるコマンドのメモを使って、継続的に実行できるスモークテストの手順を追加してください。

スモークテストでは、OTel 環境変数を設定した状態での起動/インポートを明示的に確認し、プロバイダーの設定、エクスポーターの構築、ログのブリッジ、フレームワークの計装がエラーなく初期化されることを検証してください。その後、実用的な場合は、実際に計装されたスパン/ログ/メトリクス、または OTLP のエクスポート試行を実行してください。一般的なヘルスルートで確認できるのはサーバーが応答することだけです。追加した計装を通過する操作を優先してください。

コメント