Telemetry
Browse docs

Use this doc with your coding agent

Open a focused prompt pack for Claude Code, Codex, Cursor, or another coding agent, then adapt it to the workflow covered here.

On this page
  1. Configure a named client
  2. Send one structured event
  3. Run SQL
  4. Failure and retry policy
  5. Verify the integration

.NET HTTP Integration

Telemetry does not publish a native .NET SDK. Use the HTTP API through an application-owned HttpClient or IHttpClientFactory configuration when an ASP.NET Core service, worker, or scheduled job needs structured event ingestion.

The application remains responsible for connection reuse, timeouts, retries, serialization, cancellation, and whether an observability failure may affect the customer workflow.

Configure a named client

builder.Services.AddHttpClient("telemetry", client =>
{
    client.BaseAddress = new Uri("https://api.telemetry.sh");
    client.Timeout = TimeSpan.FromSeconds(3);
});

Resolve the client from IHttpClientFactory instead of constructing a new HttpClient for every event. Store the Telemetry key in the service's existing secret manager and use separate write- and read-scoped keys where the runtime supports both ingestion and querying.

Send one structured event

Build a typed, allowlisted payload after the final application outcome is known:

using System.Net.Http.Json;

var payload = new
{
    table = "api_request_completed",
    data = new
    {
        event_id = eventId,
        route_template = "/api/projects/:id",
        method = "POST",
        status_code = 201,
        status = "success",
        latency_ms = elapsed.TotalMilliseconds,
        request_id = requestId,
        release
    }
};

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)
{
    RecordDeliveryFailure((int)response.StatusCode, eventId);
}

Use route templates, stable internal identifiers, and controlled error categories. Do not serialize headers, cookies, credentials, request bodies, bound SQL values, stack traces, prompts, generated content, or unrestricted exception messages.

Run SQL

Use a longer, separately bounded query deadline and a read-scoped key:

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
);

using var queryResponse = await client.SendAsync(
    queryRequest,
    queryCancellationToken
);

Check the HTTP status and the response status, data, and key_order fields. An empty result is a valid result and should not be treated as a transport error.

Failure and retry policy

Retry only bounded transient failures such as connection errors, 429, 502, 503, and 504. Apply exponential backoff with jitter, cap total elapsed time, respect request cancellation, and reuse the same event_id. Do not retry an unchanged schema error or bad credential.

For normal product analytics, do not turn a successful customer operation into an error because telemetry delivery failed. For billing or approved audit events that require durability, commit an outbox record with the business transaction and deliver it from a background worker.

Verify the integration

Send known success, failure, retry, cancellation, and timeout fixtures, then inspect recent rows:

SELECT timestamp_utc, event_id, route_template, status, latency_ms, error_type
FROM api_request_completed
ORDER BY timestamp_utc DESC
LIMIT 20;

Confirm one terminal row per logical outcome, stable field types, expected units, UTC timestamps, and the absence of sensitive content. Exercise a Telemetry timeout and graceful worker shutdown before enabling the path at production volume.

Continue with the .NET and Serilog integration, Log API, rate limits and errors, and batching and shutdown.

Related product capability

Capture stable event names, typed fields, and privacy-reviewed context.

Ownership and technical references

The Telemetry editorial team owns this explanation; the product team reviews behavior, examples, and boundaries.

Review the editorial standard