You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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
namespaceMicrosoft.Extensions.DependencyInjection;/// <summary>/// Extensions for enriching incoming HTTP request logs with latency telemetry./// </summary>publicstaticclassHttpLatencyTelemetryServiceCollectionExtensions{/// <summary>/// Adds an enricher that appends latency information from the request's latency/// context to incoming HTTP request logs./// </summary>/// <param name="services">The <see cref="IServiceCollection"/> to add to.</param>/// <returns>The value of <paramref name="services"/>.</returns>/// <exception cref="System.ArgumentNullException"><paramref name="services"/> is <see langword="null"/>.</exception>publicstaticIServiceCollectionAddHttpLatencyTelemetry(thisIServiceCollectionservices);}
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
varbuilder=WebApplication.CreateBuilder(args);// Register the latency context and collect the per-request latency breakdown.builder.Services.AddLatencyContext();builder.Services.AddRequestLatencyTelemetry();builder.Services.AddRequestCheckpoint();// Attach that breakdown to each incoming request's HTTP log.builder.Services.AddHttpLatencyTelemetry();varapp=builder.Build();app.UseRequestCheckpoint();app.UseHttpLogging();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.
Example enriched log
For a request from client webfrontend carrying one tag, two checkpoints, and
one measure, the enricher attaches a single tag whose value is a compact,
positional string:
Read positionally, the nine comma-separated sections are:
#
Section
Value
1
data version
v1.0
2
client application name
webfrontend
3
tag names
region/
4
tag values
westus/
5
checkpoint names
eltexm/eltltf/
6
checkpoint elapsed ms
12/47/
7
measure names
dbCalls/
8
measure values
3/
9
total duration ms
51
Within a section, list items are separated by / (each item followed by a
trailing /), and a / occurring inside an item is escaped to _.
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.
Notes for API review
Not self-contained. Registers only the enricher; caller wires AddLatencyContext + AddRequestLatencyTelemetry + AddRequestCheckpoint, matching the stable outgoing twin.
No-op if ILatencyContext is missing (singleton enricher, resolves per request, never throws on the log path).
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; itis not attached to the request's own HTTP log entry.
AddHttpLatencyTelemetrycloses that gap. It registers anIHttpLogEnricherthat reads the completed
ILatencyContextfor each incoming request and attachesits latency breakdown to that request's HTTP log as a single
LatencyInfotag.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:
so slow requests are explained in place rather than by joining two telemetry
streams on a request id.
ILatencyContext;no new measurement cost, only projection of that data onto the log.
HttpClientLatencyTelemetryExtensions.AddHttpClientLatencyTelemetry, alreadyexists for
HttpClientcalls. This is its incoming-request equivalent, so aservice 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. Enrichmenttargets and formatting are handled internally by the enricher, so there is no
configuration surface to lock down.
API Proposal
The enricher writes one tag per enriched request:
LatencyInfo(matching the outgoing-request enricher's tag key).ILatencyContext- data version,originating client application name, then the request's tags, checkpoints
(with elapsed milliseconds), measures, and total duration.
API Usage
A slow request's log line then carries a
LatencyInfotag describing where thetime was spent, so it can be diagnosed directly from the request log.
Example enriched log
For a request from client
webfrontendcarrying one tag, two checkpoints, andone measure, the enricher attaches a single tag whose value is a compact,
positional string:
Read positionally, the nine comma-separated sections are:
v1.0webfrontendregion/westus/eltexm/eltltf/12/47/dbCalls/3/51Within a section, list items are separated by
/(each item followed by atrailing
/), and a/occurring inside an item is escaped to_.Alternative Designs
No response
Risks
The surface is a single additive extension method, so the commitment is small.
The main constraint is the
LatencyInfotag value format: once consumers parseit, its layout is effectively part of the contract even though it is a string.
Notes for API review
AddLatencyContext+AddRequestLatencyTelemetry+AddRequestCheckpoint, matching the stable outgoing twin.ILatencyContextis missing (singleton enricher, resolves per request, never throws on the log path).,and the client-name field are unescaped, so a comma in the client name corrupts the positional value. Low severity, shared with the twin, tracked in Outgoing HttpClient LatencyInfo enricher value has incomplete escaping #7757.