.NET HTTP の統合
Telemetry は、ネイティブ .NET SDK を公開しません。アプリケーション所有の HTTP API を使用します。 HttpClient または IHttpClientFactory ASP.NET Core サービス、ワーカー、またはスケジュールされたジョブで構造化イベントの取り込みが必要な場合の構成。
アプリケーションは、接続の再利用、タイムアウト、再試行、シリアル化、キャンセル、および可観測性の障害が顧客のワークフローに影響を与えるかどうかを引き続き担当します。
名前付きクライアントを構成する
builder.Services.AddHttpClient("telemetry", client =>
{
client.BaseAddress = new Uri("https://api.telemetry.sh");
client.Timeout = TimeSpan.FromSeconds(3);
});
builder.Services.AddHttpClient("telemetry-query", client =>
{
client.BaseAddress = new Uri("https://api.telemetry.sh");
client.Timeout = TimeSpan.FromSeconds(15);
});
クライアントを解決する IHttpClientFactory 新しいものを構築するのではなく、 HttpClient あらゆるイベントに。 Telemetry キーをサービスの既存のシークレット マネージャーに保存し、ランタイムが取り込みとクエリの両方をサポートする場合は、取り込み専用キーと読み取り専用キーを別々にを使用します。
1 つの構造化イベントを送信する
アプリケーションの最終的な結果がわかったら、型指定されホワイトリストに登録されたペイロードを構築します。
using System.Net.Http.Json;
using System.Text.Json;
var payload = new
{
table = "api_request_completed",
data = new
{
event_id = eventId,
route_template = routeTemplate,
method = requestMethod,
status_code = completedStatusCode,
status = completedStatusCode < 400 ? "success" : "error",
latency_ms = elapsed.TotalMilliseconds,
request_id = requestId,
release
}
};
try
{
using var request = new HttpRequestMessage(HttpMethod.Post, "/log")
{
Content = JsonContent.Create(payload)
};
request.Headers.TryAddWithoutValidation("Authorization", telemetryApiKey);
var client = httpClientFactory.CreateClient("telemetry");
using var response = await client.SendAsync(request, cancellationToken);
if (!response.IsSuccessStatusCode)
{
RecordTelemetryDeliveryFailure("telemetry_delivery_rejected");
}
}
catch (OperationCanceledException)
{
RecordTelemetryDeliveryFailure("telemetry_delivery_cancelled");
}
catch (Exception error) when (error is HttpRequestException
or JsonException or NotSupportedException
or ArgumentException or InvalidOperationException)
{
RecordTelemetryDeliveryFailure("telemetry_delivery_failed");
}
static void RecordTelemetryDeliveryFailure(string reason)
{
// Diagnostics must not replace the already completed application result.
try { Console.Error.WriteLine(reason); }
catch { }
}
この例は処理の完了後に実行し、実際のルートテンプレート、メソッド、HTTP ステータスを渡してください。送信失敗が処理結果を置き換えることはありません。キャンセルトークンはキャンセル状態のままです。送信は一回だけで、応答本文を記録せず、保存も保証しません。SQL で到達を確認してください。
ルート テンプレート、安定した内部識別子、および制御されたエラー カテゴリを使用します。ヘッダー、Cookie、資格情報、リクエスト本文、バインドされた SQL 値、スタック トレース、プロンプト、生成されたコンテンツ、または制限のない例外メッセージをシリアル化しないでください。
SQLを実行します
より長い、個別に制限されたクエリ期限と読み取りスコープのキーを使用します。
以下では独立した telemetry-query クライアントを使います。タイムアウトは15秒で、取り込み用は3秒のままです。呼び出し元のキャンセル期限が短い場合はそちらが優先されます。共有クライアントでリクエストを開始した後にタイムアウトを変更しないでください。
var queryPayload = new
{
query = """
SELECT route_template, COUNT(*) AS requests
FROM api_request_completed
WHERE timestamp_utc >= now() - INTERVAL '24 hours'
GROUP BY route_template
ORDER BY requests DESC
"""
};
using var queryRequest = new HttpRequestMessage(HttpMethod.Post, "/query")
{
Content = JsonContent.Create(queryPayload)
};
queryRequest.Headers.TryAddWithoutValidation(
"Authorization",
telemetryReadApiKey
);
var queryClient = httpClientFactory.CreateClient("telemetry-query");
using var queryResponse = await queryClient.SendAsync(
queryRequest,
queryCancellationToken
);
HTTPのステータスと応答を確認してください status, data、そして key_order フィールド。空の結果は有効な結果であり、トランスポート エラーとして扱うべきではありません。
失敗と再試行のポリシー
接続エラーなどの限定された一時的なエラーのみを再試行します。 429, 502, 503、そして 504。 ジッター付き指数バックオフを適用し、合計経過時間に上限を設け、リクエストのキャンセルを尊重して、同じ event_id。未変更のスキーマ エラーまたは不正な資格情報を再試行しないでください。
通常の製品分析では、テレメトリの配信が失敗したために、成功した顧客操作をエラーにしないでください。耐久性が必要な請求イベントや承認された監査イベントの場合は、ビジネス トランザクションで送信トレイ レコードをコミットし、バックグラウンド ワーカーから配信します。
統合を確認する
既知の成功、失敗、再試行、キャンセル、タイムアウト フィクスチャを送信し、最近の行を検査します。
SELECT timestamp_utc, event_id, route_template, method, status_code, status, latency_ms
FROM api_request_completed
ORDER BY timestamp_utc DESC
LIMIT 20;
論理結果ごとに 1 つのターミナル行、安定したフィールド タイプ、予期される単位、UTC タイムスタンプ、および機密コンテンツの有無を確認します。本番ボリュームでパスを有効にする前に、Telemetry タイムアウトと正常なワーカー シャットダウンを実行します。
続けて、 .NET と Serilog の統合, ログ API, レート制限とエラー、そして バッチ処理とシャットダウン.