Skip to content

Add HTTP request latency log enricher (experimental) - #7602

Merged
EasyL0ver merged 8 commits into
dotnet:mainfrom
EasyL0ver:users/pkudlacik/perfpanel-http-latency-enricher
Jul 15, 2026
Merged

Add HTTP request latency log enricher (experimental)#7602
EasyL0ver merged 8 commits into
dotnet:mainfrom
EasyL0ver:users/pkudlacik/perfpanel-http-latency-enricher

Conversation

@EasyL0ver

@EasyL0ver EasyL0ver commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Completes the open-sourcing of the incoming-request latency log enricher that was originally intended for public release but was orphaned. Migrates it from the R9 SDK into Microsoft.AspNetCore.Diagnostics.Middleware.

Changes

  • Public API: AddHttpLatencyTelemetry() extension method (registered via AddHttpLogEnricher) in Microsoft.Extensions.DependencyInjection namespace.
  • Internal: HttpLatencyLogEnricher reads ILatencyContext from request services and emits a latencyInfo tag with checkpoints, measures, tags, and total duration.
  • API status: Marked [Experimental(EXTEXP0013)] on both class and method, consistent with precedent (sibling HttpClientLatencyLogEnricher).

Design notes

  • Tag-key casing: uses lowercase latencyInfo, while sibling client enricher uses uppercase LatencyInfo. This inconsistency should be addressed at API review.

Precedent

Follows the pattern established by @rainsxng (#6783) and @mariamgerges (#7380) for other migration enrichers. Baseline JSON, attribute placement, test porting all consistent with that precedent.

Microsoft Reviewers: Open in CodeFlow

Migrates the incoming-request latency log enricher from the R9 SDK into
Microsoft.AspNetCore.Diagnostics.Middleware. Adds the public
AddHttpLatencyTelemetry() extension (registered via AddHttpLogEnricher) and
the internal HttpLatencyLogEnricher that emits a latencyInfo tag with
checkpoints, measures, tags and total duration on incoming HTTP request logs.

The new API ships behind [Experimental] (EXTEXP0013) on both the class and the
method, mirroring the sibling HttpClientLatency enricher. Tests are faithfully
ported from the R9 suite (golden-string serialization plus null/edge cases).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@EasyL0ver
EasyL0ver requested a review from a team as a code owner July 1, 2026 08:42
Pawel Kudlacik and others added 2 commits July 1, 2026 11:21
Removes PerfPanel branding from MockLatencyData helper class and renames the
property to better reflect its purpose as serialized latency data.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The MockLatencyData class was nested in HttpLatencyLogEnricherTests. Extract it to a dedicated file following extensions repo convention (e.g., CustomHttpLogEnricher.cs, TestHttpLogEnricher.cs) for better test organization.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an incoming HTTP request latency log enricher to Microsoft.AspNetCore.Diagnostics.Middleware, exposing a new experimental DI extension (AddHttpLatencyTelemetry) and wiring up serialization of ILatencyContext.LatencyData into HTTP log enrichment output.

Changes:

  • Introduces AddHttpLatencyTelemetry() (experimental) to register the incoming-request latency log enricher.
  • Adds HttpLatencyLogEnricher that reads ILatencyContext from request services and emits a serialized latency payload.
  • Ports/creates tests and updates the library README and API baseline JSON.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
test/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware.Tests/Latency/Internal/MockLatencyData.cs Adds a test helper that builds deterministic LatencyData + expected serialized string.
test/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware.Tests/Latency/Internal/HttpLatencyLogEnricherTests.cs Adds unit tests for the new incoming-request log enricher behavior.
test/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware.Tests/Latency/HttpLatencyTelemetryExtensionsTests.cs Adds DI registration tests for AddHttpLatencyTelemetry.
src/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware/README.md Documents how to register the new enricher.
src/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware/Microsoft.AspNetCore.Diagnostics.Middleware.json Adds the new experimental public API to the baseline.
src/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware/Latency/Internal/HttpLatencyLogEnricher.cs Implements the incoming-request latency enrichment + serialization format.
src/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware/Latency/HttpLatencyTelemetryExtensions.cs Adds the experimental DI extension method for registering the enricher.

Comment thread src/Libraries/Microsoft.AspNetCore.Diagnostics.Middleware/README.md
System.Globalization and System.Linq became unnecessary when MockLatencyData was extracted to a separate file.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@EasyL0ver

Copy link
Copy Markdown
Contributor Author

@dotnet-policy-service agree company="Microsoft"

1 similar comment
@EasyL0ver

Copy link
Copy Markdown
Contributor Author

@dotnet-policy-service agree company="Microsoft"

@EasyL0ver

Copy link
Copy Markdown
Contributor Author

Thanks — noted the automated suggestions. These behaviors were intentionally preserved to maintain parity with the original production implementation:

  • StringBuilder pool: uses the factory-created pool pattern to match production behavior.
  • Header serialization: header StringValues are appended as-is to preserve the existing log schema.
  • Null behaviour: tests/assertions mirror the original implementation (NullReferenceException on null context).
  • Tag key casing: kept "latencyInfo" to avoid changing the log schema; recommend API review to standardize if desired.

If maintainers prefer these changes, I can follow up with a targeted PR. Parity diffs can be provided on request (internal review only).

Pawel Kudlacik and others added 4 commits July 8, 2026 11:44
…ant AddHttpLoggingRedaction() from example

Make test helper properties get-only to communicate immutability. Remove redundant AddHttpLoggingRedaction() from README example because AddHttpLatencyTelemetry already wires the logging plumbing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Rename the incoming enricher's log dimension key from lowercase 'latencyInfo' to 'LatencyInfo' to match the logging-dimension naming convention established in dotnet#4545 and used by the sibling HttpClientLatencyLogEnricher. Updated test assertions accordingly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Use PoolFactory.SharedStringBuilderPool (static) instead of a per-instance pool.
- Append only the first client-application header value instead of the whole StringValues.

Both match the established pattern in the sibling outgoing-request enricher.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The null-context and without-latency-context tests set up HeaderDictionary and HttpRequest mocks that were never exercised. Remove the dead setup for clarity.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-comment-bot

Copy link
Copy Markdown
Collaborator

‼️ Found issues ‼️

Project Coverage Type Expected Actual
Microsoft.Extensions.Diagnostics.Testing Line 99 98.65 🔻
Microsoft.Extensions.Telemetry Line 93 91.95 🔻
Microsoft.Extensions.AI Line 89 88.62 🔻
Microsoft.Extensions.AI Branch 89 88.57 🔻
Microsoft.Extensions.AI.OpenAI Line 75 62.89 🔻
Microsoft.Extensions.AI.OpenAI Branch 75 50.41 🔻
Microsoft.Extensions.DataIngestion.MarkItDown Line 75 4.46 🔻
Microsoft.Extensions.DataIngestion.MarkItDown Branch 75 0 🔻
Microsoft.Extensions.Diagnostics.ResourceMonitoring Line 99 96.03 🔻
Microsoft.Extensions.Diagnostics.ResourceMonitoring Branch 99 94.39 🔻
Microsoft.Extensions.Diagnostics.ResourceMonitoring.Kubernetes Line 99 97.73 🔻
Microsoft.Extensions.ServiceDiscovery.Dns Line 75 71.61 🔻
Microsoft.Extensions.ServiceDiscovery.Abstractions Line 75 42.11 🔻
Microsoft.Extensions.ServiceDiscovery.Abstractions Branch 75 42.86 🔻
Microsoft.Extensions.ServiceDiscovery Line 75 67.96 🔻
Microsoft.Extensions.ServiceDiscovery Branch 75 71.43 🔻
Microsoft.Extensions.ServiceDiscovery.Yarp Line 75 73.85 🔻
Microsoft.Extensions.ServiceDiscovery.Yarp Branch 75 70 🔻
Microsoft.Extensions.VectorData.Abstractions Line 75 37.39 🔻
Microsoft.Extensions.VectorData.Abstractions Branch 75 22.73 🔻

🎉 Good job! The coverage increased 🎉
Update MinCodeCoverage in the project files.

Project Expected Actual
Microsoft.Gen.BuildMetadata 97 100
Microsoft.Gen.MetadataExtractor 57 73
Microsoft.Gen.MetricsReports 67 69
Microsoft.Extensions.AI.Abstractions 82 85
Microsoft.Extensions.AI.Evaluation.NLP 0 78
Microsoft.Extensions.Caching.Hybrid 82 84
Microsoft.Extensions.DataIngestion 75 89
Microsoft.Extensions.DataIngestion.Markdig 75 90
Microsoft.Extensions.Http.Resilience 97 100

Full code coverage report: https://dev.azure.com/dnceng-public/public/_build/results?buildId=1499794&view=codecoverage-tab

@EasyL0ver
EasyL0ver merged commit b3a34f1 into dotnet:main Jul 15, 2026
5 checks passed
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#if NET8_0_OR_GREATER

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is it not going to work on .NET Framework?

/// Extensions for enriching incoming HTTP request logs with latency telemetry.
/// </summary>
[Experimental(diagnosticId: DiagnosticIds.Experiments.HttpLogging, UrlFormat = DiagnosticIds.UrlFormat)]
public static class HttpLatencyTelemetryExtensions

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public static class HttpLatencyTelemetryExtensions
public static class HttpLatencyTelemetryServiceCollectionExtensions

EasyL0ver added a commit that referenced this pull request Jul 20, 2026
…uard (#7645)

Rename HttpLatencyTelemetryExtensions and drop redundant TFM guard

Address post-merge review feedback on #7602:
- Rename HttpLatencyTelemetryExtensions to
  HttpLatencyTelemetryServiceCollectionExtensions to match the
  *ServiceCollectionExtensions naming convention used by sibling
  extension classes (RequestLatencyTelemetryServiceCollectionExtensions,
  HttpLoggingServiceCollectionExtensions).
- Remove the always-true #if NET8_0_OR_GREATER guard from the enricher
  and its extensions. The project only targets net8.0+, so the guard
  never excluded any target framework.


Copilot-Session: d705cd71-1bda-4572-88e7-0bbfda83c3d6

Co-authored-by: Pawel Kudlacik <pkudlacik@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants