エンドツーエンドの SaaS 可観測性デモ
このデモでは、合成 SaaS ワークフロー イベントの決定論的なセットを Telemetry に送信し、SQL でクエリを返します。信頼性、製品の成果、バックグラウンド作業、AI コストを結び付けながら、一度に検査できるように意図的に十分に小さいものになっています。
このサンプルでは、運用トラフィックや顧客データは使用されません。すべてのランにはユニークな特徴があります run_id、そのため、そのクエリは作成した行を分離できます。
デモが証明するもの
1 つの広範なイベント契約で、いくつかの質問に答えることができます。
- ワークフローは完了しましたか?
- どのステップが失敗したか、または再試行されましたか?
- 各ステップにどれくらい時間がかかりましたか?
- ワークフローによって生じた AI コストはどれくらいと見積もられますか?
- どのアカウント プランとリリースが影響を受けましたか?
コードはパブリック HTTP エンドポイントを直接使用するため、イベント、API リクエスト、SQL 結果の間にフレームワークや SDK 抽象化はありません。
前提条件
Node.js 20 以降と Telemetry API キーが必要です。サンプルを実行するシェル内でのみキーをエクスポートします。
export TELEMETRY_API_KEY="YOUR_API_KEY"
リポジトリには実行可能なソースも保存されます。 examples/saas-observability-demo。完全なプログラムを以下に示します。そのため、データ コントラクトとクエリはこのページに表示されたままになります。
完全なプログラム
これを名前を付けて保存 demo.mjs:
import { randomUUID } from "node:crypto";
const apiKey = process.env.TELEMETRY_API_KEY;
if (!apiKey) {
throw new Error("TELEMETRY_API_KEY is required to run this demo");
}
const apiOrigin = process.env.TELEMETRY_API_ORIGIN || "https://api.telemetry.sh";
const runId = randomUUID();
const table = "saas_observability_demo";
const base = {
run_id: runId,
account_id: "synthetic_acme",
plan: "growth",
release: "demo-2026.07",
region: "us-west",
};
const events = [
{
...base,
event_name: "checkout_started",
workflow: "subscription_checkout",
step: "checkout",
outcome: "started",
duration_ms: 18,
retry_count: 0,
estimated_cost_usd: 0,
},
{
...base,
event_name: "payment_authorized",
workflow: "subscription_checkout",
step: "payment",
outcome: "success",
duration_ms: 284,
retry_count: 0,
estimated_cost_usd: 0,
},
{
...base,
event_name: "invoice_job_completed",
workflow: "subscription_checkout",
step: "invoice_job",
outcome: "success",
duration_ms: 618,
retry_count: 1,
estimated_cost_usd: 0,
},
{
...base,
event_name: "welcome_email_completed",
workflow: "subscription_checkout",
step: "welcome_email",
outcome: "failed",
duration_ms: 910,
retry_count: 2,
error_type: "provider_timeout",
estimated_cost_usd: 0,
},
{
...base,
event_name: "ai_summary_completed",
workflow: "subscription_checkout",
step: "ai_summary",
outcome: "success",
duration_ms: 742,
retry_count: 0,
model: "configured-demo-model",
input_tokens: 820,
output_tokens: 146,
estimated_cost_usd: 0.0042,
},
];
const ingestResponse = await fetch(`${apiOrigin}/log`, {
method: "POST",
headers: {
Authorization: apiKey,
"Content-Type": "application/json",
},
body: JSON.stringify({ table, data: events }),
});
if (!ingestResponse.ok) {
throw new Error(
`Ingest failed: ${ingestResponse.status} ${await ingestResponse.text()}`
);
}
const sql = `
SELECT
workflow,
COUNT(*) AS event_count,
SUM(CASE WHEN outcome = 'failed' THEN 1 ELSE 0 END) AS failed_steps,
SUM(retry_count) AS retries,
SUM(estimated_cost_usd) AS estimated_cost_usd,
MAX(duration_ms) AS slowest_step_ms
FROM ${table}
WHERE run_id = '${runId}'
GROUP BY workflow
ORDER BY workflow
`;
const queryResponse = await fetch(`${apiOrigin}/query`, {
method: "POST",
headers: {
Authorization: apiKey,
"Content-Type": "application/json",
},
body: JSON.stringify({ query: sql, realtime: true, json: true }),
});
if (!queryResponse.ok) {
throw new Error(
`Query failed: ${queryResponse.status} ${await queryResponse.text()}`
);
}
const result = await queryResponse.json();
console.log(JSON.stringify({ run_id: runId, rows: result.data }, null, 2));
実行してください:
node demo.mjs
期待される形状は 1 つの概要行です。
{
"run_id": "generated-for-this-run",
"rows": [
{
"workflow": "subscription_checkout",
"event_count": 5,
"failed_steps": 1,
"retries": 3,
"estimated_cost_usd": 0.0042,
"slowest_step_ms": 910
}
]
}
JSON 応答の正確な数値エンコーディングは、クエリ結果のシリアル化によって異なる場合があります。形と意味を契約として扱います。
生のタイムラインを検査する
集計により、ワークフローに失敗したステップが 1 つあったことがわかります。相関タイムラインにより、失敗したステップとその周囲で何が起こったかがわかります。
SELECT
timestamp_utc,
event_name,
step,
outcome,
duration_ms,
retry_count,
error_type
FROM saas_observability_demo
WHERE run_id = 'PASTE_RUN_ID'
ORDER BY timestamp_utc ASC;
の run_id ワークフロー相関識別子のように機能します。実際のアプリケーションでは、ワークフロー境界で作成された安定した識別子を使用し、それを API ハンドラー、キュー ペイロード、ジョブ、Webhook、および AI 呼び出しを通じて渡します。
同じコントラクトから 3 つのビューを構築する
信頼性
失敗したステップと最大期間をグラフ化します。 release または region。最小ボリュームとチームから期待される応答を定義した後でのみアラートを送信します。
製品の完成
予想される終了イベントに到達した個別のワークフロー ID をカウントします。 1 つのワークフローで複数のステップを実行できる場合は、完了したワークフローとして行をカウントしません。
コストと価値
合計 estimated_cost_usd AI ステップを結合または関連付けて、アクティベーション、受け入れられた出力、またはワークフローの正常な完了などの後の結果に関連付けます。バージョン化された構成でモデルの価格を維持し、見積もりをプロバイダーの請求書と照合します。
生産上の変更点
デモでは抽象化よりも可視性を重視しています。本番環境の実装では次のことを行う必要があります。
- デモンストレーション配列ではなく、実際の操作境界でイベントを作成します。
- 制限付きスキーマを使用し、ルート、エラー、計画、およびリリースの値を正規化します。
- 信頼できない入力を SQL に補間することを避けます。
- API キーをサーバー側の秘密ストアに保持します。
- 永続的な障害を隠すことなく、イベントをバッチまたはバッファーします。
- 保存と削除の要件を定義する。
- プロデューサが独立して進化するときにスキーマのバージョンを記録します。
- イベント配信自体が失敗しているかどうかを測定します。
使用する 構造化されたロギング 計装用、 可観測性のための SQL 解析モデルの場合、 接続済み SQL ラボ 視覚的な結果を備えた大規模な 6 テーブル データセットの場合。