dotnet / dotnet/extensions

[API Proposal]: AddHttpLatencyTelemetry for incoming HTTP request logs

Open
#7,729 0 comments 1 reaction 1 assignee Claimed by @EasyL0ver View on GitHub
api-ready-for-review area-telemetry
Dominant language
C#
Stars
3.2k
Forks
894
Avg merge
1d 12h
Merged PRs (30d)
23

Description

### Background and motivation

Server applications already collect a rich per-request latency breakdown through
the request latency telemetry services (`AddRequestLatencyTelemetry`,
`AddRequestCheckpoint`): named checkpoints marking stages of the pipeline,
measures, tags, and a total duration, all captured in the request's
`ILatencyContext`. Today that breakdown lives only in the latency exporters; it
is not attached to the request's own HTTP log entry.

`AddHttpLatencyTelemetry` closes that gap. It registers an `IHttpLogEnricher`
that reads the completed `ILatencyContext` for each incoming request and attaches
its latency breakdown to that request's HTTP log as a single `LatencyInfo` tag.
This lets an operator open one request log line and immediately see where the
time went - which checkpoints fired, the measured values, and the total duration -
without correlating across a separate latency signal.

Value:

- **Single-line diagnosis.** The latency breakdown travels with the request log,
so slow requests are explained in place rather than by joining two telemetry
streams on a request id.
- **Uses data already collected.** It consumes the existing `ILatencyContext`;
no new measurement cost, only projection of that data onto the log.
- **Completes the incoming/outgoing pair.** The outgoing-request counterpart,
`HttpClientLatencyTelemetryExtensions.AddHttpClientLatencyTelemetry`, already
exists for `HttpClient` calls. This is its incoming-request equivalent, so a
service can carry consistent latency enrichment on both sides.

The surface is intentionally minimal: one additive extension method on
`IServiceCollection`, no options type and no new public abstractions. Enrichment
targets and formatting are handled internally by the enricher, so there is no
configuration surface to lock down.

### API Proposal

```csharp
namespace Microsoft.Extensions.DependencyInjection;

///
/// Extensions for enriching incoming HTTP request logs with latency telemetry.
///
public static class HttpLatencyTelemetryServiceCollectionExtensions
{
///
/// Adds an enricher that appends latency information from the request's latency
/// context to incoming HTTP request logs.
///
/// The to add to.
/// The value of .
/// is .
public static IServiceCollection AddHttpLatencyTelemetry(this IServiceCollection services);
}
```

The enricher writes one tag per enriched request:

- Key: `LatencyInfo` (matching the outgoing-request enricher's tag key).
- Value: a compact, ordered projection of the `ILatencyContext` - data version,
originating client application name, then the request's tags, checkpoints
(with elapsed milliseconds), measures, and total duration.

### API Usage

```csharp
var builder = WebApplication.CreateBuilder(args);

// Collect the per-request latency breakdown.
builder.Services.AddRequestLatencyTelemetry();
builder.Services.AddRequestCheckpoint();

// Attach that breakdown to each incoming request's HTTP log.
builder.Services.AddHttpLatencyTelemetry();

var app = builder.Build();
app.UseRequestLatencyTelemetry();
```

A slow request's log line then carries a `LatencyInfo` tag describing where the
time was spent, so it can be diagnosed directly from the request log.

### Alternative Designs

_No response_

### Risks

The surface is a single additive extension method, so the commitment is small.
The main constraint is the `LatencyInfo` tag value format: once consumers parse
it, its layout is effectively part of the contract even though it is a string.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.