Repository navigation
Fix ArgumentNullException in per-request log buffering at the end of a request - #7811
evgenyfedorov2 merged 8 commits into
Conversation
โฆa request PerRequestLogBufferManager read HttpContext.RequestServices without checking it for null. ASP.NET Core disposes the request services, after which RequestServices returns null, before it logs "Request finished" and clears IHttpContextAccessor.HttpContext. TryEnqueue now uses the global buffer in that case, and Flush skips the per-request buffer and still flushes the global buffer. Fixes #7806 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Keep the test that reproduces the reported scenario ("Request finished"
logged after the request services have been disposed) and remove the unit
tests that used an HttpContext without request services.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
๐ Good job! The coverage increased ๐
Full code coverage report: https://dev.azure.com/dnceng-public/public/_build/results?buildId=1624770&view=codecoverage-tab |
Replace the IServiceProvider? locals with ?. on HttpContext.RequestServices. TryEnqueue already falls back to the global buffer when there's no per-request buffer, and Flush still flushes the global buffer. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Use Assert.Contains on FakeLogCollector.GetLogsAsync instead of a loop, and remove the status code check, which the bug doesn't affect. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Replace the end-to-end test with a test of PerRequestLogBufferManager: a record logged while HttpContext.RequestServices is null is held by the global buffer and written when PerRequestLogBuffer is flushed. The test covers both TryEnqueue and Flush. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Copilot review overview
๐ข Approval recommended
The focused null handling matches the reported lifecycle behavior and is adequately covered by a regression test.
Review effort: Balanced
Findings: None
What changed in this PR
Fixes per-request log buffering when request services have already been disposed.
Changes:
- Falls back to the global buffer when
RequestServicesis null. - Adds regression coverage for logging and flushing.
| File | Description |
|---|---|
PerRequestLogBufferManager.cs |
Safely handles null request services. |
PerRequestLogBufferManagerTests.cs |
Verifies global-buffer fallback behavior. |
๐ก Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
๐ Good job! The coverage increased ๐
Full code coverage report: https://dev.azure.com/dnceng-public/public/_build/results?buildId=1624977&view=codecoverage-tab |
#7811 fixed the exception the filter avoided. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Fixes #7806
Problem
As reported in #7806, with per-request log buffering (
AddPerIncomingRequestBuffer) and Information level enabled forMicrosoft.AspNetCore.Hosting.Diagnostics,ILogger.LogthrowsArgumentNullException: Value cannot be null. (Parameter 'provider')when ASP.NET Core logs "Request finished" (event id 2) at the end of a request.Root cause
ASP.NET Core disposes the request's service scope in a response
OnCompletedcallback, after whichHttpContext.RequestServicesreturnsnull, and then logs "Request finished" inHostingApplication.DisposeContextwhileIHttpContextAccessor.HttpContextstill returns the request'sHttpContext.PerRequestLogBufferManager.TryEnqueueandFlushonly checkedHttpContextfornull, so they passed thenullRequestServicestoGetService<T>(), which throws.ExtendedLoggercallsTryEnqueueoutside itstry/catch, so the exception escapesILogger.Log.Fix
In
PerRequestLogBufferManager:TryEnqueueuses the global buffer whenHttpContextor itsRequestServicesisnull, the same way it already handled anullHttpContext.Flushskips the per-request buffer whenRequestServicesisnulland still flushes the global buffer.