Log client errors as Debug (#12262)

This commit is contained in:
Stephen Halter 2019-07-18 15:43:56 -07:00 committed by GitHub
parent 771989b71d
commit 9c19577d49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 41 additions and 34 deletions

View File

@ -571,6 +571,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{
Log.RequestProcessingError(ConnectionId, ex);
}
catch (ConnectionAbortedException ex)
{
Log.RequestProcessingError(ConnectionId, ex);
}
catch (Exception ex)
{
Log.LogWarning(0, ex, CoreStrings.RequestProcessingEndError);

View File

@ -244,6 +244,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
Log.RequestProcessingError(ConnectionId, ex);
error = ex;
}
catch (ConnectionAbortedException ex)
{
Log.RequestProcessingError(ConnectionId, ex);
error = ex;
}
catch (Http2ConnectionErrorException ex)
{
Log.Http2ConnectionError(ConnectionId, ex);

View File

@ -37,13 +37,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
LoggerMessage.Define(LogLevel.Debug, new EventId(16, nameof(NotAllConnectionsClosedGracefully)), "Some connections failed to close gracefully during server shutdown.");
private static readonly Action<ILogger, string, string, Exception> _connectionBadRequest =
LoggerMessage.Define<string, string>(LogLevel.Information, new EventId(17, nameof(ConnectionBadRequest)), @"Connection id ""{ConnectionId}"" bad request data: ""{message}""");
LoggerMessage.Define<string, string>(LogLevel.Debug, new EventId(17, nameof(ConnectionBadRequest)), @"Connection id ""{ConnectionId}"" bad request data: ""{message}""");
private static readonly Action<ILogger, string, long, Exception> _connectionHeadResponseBodyWrite =
LoggerMessage.Define<string, long>(LogLevel.Debug, new EventId(18, nameof(ConnectionHeadResponseBodyWrite)), @"Connection id ""{ConnectionId}"" write of ""{count}"" body bytes to non-body HEAD response.");
private static readonly Action<ILogger, string, Exception> _requestProcessingError =
LoggerMessage.Define<string>(LogLevel.Information, new EventId(20, nameof(RequestProcessingError)), @"Connection id ""{ConnectionId}"" request processing ended abnormally.");
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(20, nameof(RequestProcessingError)), @"Connection id ""{ConnectionId}"" request processing ended abnormally.");
private static readonly Action<ILogger, Exception> _notAllConnectionsAborted =
LoggerMessage.Define(LogLevel.Debug, new EventId(21, nameof(NotAllConnectionsAborted)), "Some connections failed to abort during server shutdown.");
@ -64,19 +64,19 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
LoggerMessage.Define<string, string>(LogLevel.Debug, new EventId(26, nameof(RequestBodyDone)), @"Connection id ""{ConnectionId}"", Request id ""{TraceIdentifier}"": done reading request body.");
private static readonly Action<ILogger, string, string, double, Exception> _requestBodyMinimumDataRateNotSatisfied =
LoggerMessage.Define<string, string, double>(LogLevel.Information, new EventId(27, nameof(RequestBodyMinimumDataRateNotSatisfied)), @"Connection id ""{ConnectionId}"", Request id ""{TraceIdentifier}"": the request timed out because it was not sent by the client at a minimum of {Rate} bytes/second.");
LoggerMessage.Define<string, string, double>(LogLevel.Debug, new EventId(27, nameof(RequestBodyMinimumDataRateNotSatisfied)), @"Connection id ""{ConnectionId}"", Request id ""{TraceIdentifier}"": the request timed out because it was not sent by the client at a minimum of {Rate} bytes/second.");
private static readonly Action<ILogger, string, string, Exception> _responseMinimumDataRateNotSatisfied =
LoggerMessage.Define<string, string>(LogLevel.Information, new EventId(28, nameof(ResponseMinimumDataRateNotSatisfied)), @"Connection id ""{ConnectionId}"", Request id ""{TraceIdentifier}"": the connection was closed because the response was not read by the client at the specified minimum data rate.");
LoggerMessage.Define<string, string>(LogLevel.Debug, new EventId(28, nameof(ResponseMinimumDataRateNotSatisfied)), @"Connection id ""{ConnectionId}"", Request id ""{TraceIdentifier}"": the connection was closed because the response was not read by the client at the specified minimum data rate.");
private static readonly Action<ILogger, string, Exception> _http2ConnectionError =
LoggerMessage.Define<string>(LogLevel.Information, new EventId(29, nameof(Http2ConnectionError)), @"Connection id ""{ConnectionId}"": HTTP/2 connection error.");
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(29, nameof(Http2ConnectionError)), @"Connection id ""{ConnectionId}"": HTTP/2 connection error.");
private static readonly Action<ILogger, string, Exception> _http2StreamError =
LoggerMessage.Define<string>(LogLevel.Information, new EventId(30, nameof(Http2StreamError)), @"Connection id ""{ConnectionId}"": HTTP/2 stream error.");
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(30, nameof(Http2StreamError)), @"Connection id ""{ConnectionId}"": HTTP/2 stream error.");
private static readonly Action<ILogger, string, int, Exception> _hpackDecodingError =
LoggerMessage.Define<string, int>(LogLevel.Information, new EventId(31, nameof(HPackDecodingError)), @"Connection id ""{ConnectionId}"": HPACK decoding error while decoding headers for stream ID {StreamId}.");
LoggerMessage.Define<string, int>(LogLevel.Debug, new EventId(31, nameof(HPackDecodingError)), @"Connection id ""{ConnectionId}"": HPACK decoding error while decoding headers for stream ID {StreamId}.");
private static readonly Action<ILogger, string, string, Exception> _requestBodyNotEntirelyRead =
LoggerMessage.Define<string, string>(LogLevel.Information, new EventId(32, nameof(RequestBodyNotEntirelyRead)), @"Connection id ""{ConnectionId}"", Request id ""{TraceIdentifier}"": the application completed without reading the entire request body.");

View File

@ -46,9 +46,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.PipeW
private TaskCompletionSource<FlushResult> _currentFlushTcs;
private bool _bufferedWritePending;
// We're trusting the Http2FrameWriter and Http1OutputProducer to not call into the PipeWriter after calling Abort() or Complete()
// If an abort occurs while a flush is in progress, we clean up after the flush completes, and don't flush again.
// We're trusting the Http2FrameWriter and Http1OutputProducer to not call into the PipeWriter after calling Abort() or Complete().
// If an Abort() is called while a flush is in progress, we clean up after the next flush completes, and don't flush again.
private bool _aborted;
// If an Complete() is called while a flush is in progress, we clean up after the flush loop completes, and call Complete() on the inner PipeWriter.
private Exception _completeException;
public ConcurrentPipeWriter(PipeWriter innerPipeWriter, MemoryPool<byte> pool, object sync)
@ -123,7 +124,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.PipeW
return flushTask;
}
// Use a TCS instead of something resettable so it can be awaited by multiple awaiters.
// Use a TCS instead of something custom so it can be awaited by multiple awaiters.
_currentFlushTcs = new TaskCompletionSource<FlushResult>(TaskCreationOptions.RunContinuationsAsynchronously);
var result = new ValueTask<FlushResult>(_currentFlushTcs.Task);
@ -153,7 +154,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.PipeW
if (flushResult.IsCanceled)
{
// Complete anyone currently awaiting a flush since CancelPendingFlush() was called
// Complete anyone currently awaiting a flush with the canceled FlushResult since CancelPendingFlush() was called.
_currentFlushTcs.SetResult(flushResult);
// Reset _currentFlushTcs, so we don't enter passthrough mode while we're still flushing.
_currentFlushTcs = new TaskCompletionSource<FlushResult>(TaskCreationOptions.RunContinuationsAsynchronously);
@ -176,18 +177,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.PipeW
public override void CancelPendingFlush()
{
// We propagate IsCanceled when we do multiple flushes in a loop. If FlushResult.IsCanceled is true with more data pending to flush,
// _currentFlushTcs with canceled flush task, but rekick the FlushAsync loop.
// FlushAsyncAwaited never ignores a canceled FlushResult.
_innerPipeWriter.CancelPendingFlush();
}
// To return all the segments without completing the inner pipe, call Abort().
public override void Complete(Exception exception = null)
{
// We store the complete exception or s sentinel exception instance in a field if a flush was ongoing.
// We call the inner Complete() method after the flush loop ended.
// To simply ensure everything gets returned after the PipeWriter is left in some unknown state (say GetMemory() was
// called but not Advance(), or there's a flush pending), but you don't want to complete the inner pipe, just call Abort().
// Store the exception or sentinel in a field so that if a flush is ongoing, we call the
// inner Complete() method with the correct exception or lack thereof once the flush loop ends.
_completeException = exception ?? _successfullyCompletedSentinel;
if (_currentFlushTcs == null)

View File

@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
// ConnectionWriteCallback: Reserved: 12
private static readonly Action<ILogger, string, Exception> _connectionError =
LoggerMessage.Define<string>(LogLevel.Information, new EventId(14, nameof(ConnectionError)), @"Connection id ""{ConnectionId}"" communication error.");
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(14, nameof(ConnectionError)), @"Connection id ""{ConnectionId}"" communication error.");
private static readonly Action<ILogger, string, Exception> _connectionReset =
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(19, nameof(ConnectionReset)), @"Connection id ""{ConnectionId}"" reset.");

View File

@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.Internal
// ConnectionWriteCallback: Reserved: 12
private static readonly Action<ILogger, string, Exception> _connectionError =
LoggerMessage.Define<string>(LogLevel.Information, new EventId(14, nameof(ConnectionError)), @"Connection id ""{ConnectionId}"" communication error.");
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(14, nameof(ConnectionError)), @"Connection id ""{ConnectionId}"" communication error.");
private static readonly Action<ILogger, string, Exception> _connectionReset =
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(19, nameof(ConnectionReset)), @"Connection id ""{ConnectionId}"" reset.");

View File

@ -151,7 +151,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests
}
[Fact]
public async Task BadRequestLogsAreNotHigherThanInformation()
public async Task BadRequestLogsAreNotHigherThanDebug()
{
await using (var server = new TestServer(async context =>
{
@ -168,8 +168,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests
}
}
Assert.All(TestSink.Writes, w => Assert.InRange(w.LogLevel, LogLevel.Trace, LogLevel.Information));
Assert.Contains(TestSink.Writes, w => w.EventId.Id == 17 && w.LogLevel == LogLevel.Information);
Assert.All(TestSink.Writes, w => Assert.InRange(w.LogLevel, LogLevel.Trace, LogLevel.Debug));
Assert.Contains(TestSink.Writes, w => w.EventId.Id == 17);
}
[Fact]

View File

@ -3731,7 +3731,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
[Fact]
public void IOExceptionDuringFrameProcessingLoggedAsInfo()
public void IOExceptionDuringFrameProcessingIsNotLoggedHigherThanDebug()
{
CreateConnection();
@ -3740,9 +3740,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
Assert.Equal(TaskStatus.RanToCompletion, _connection.ProcessRequestsAsync(new DummyApplication(_noopApplication)).Status);
var logMessage = TestApplicationErrorLogger.Messages.Single(m => m.LogLevel >= LogLevel.Information);
Assert.All(TestApplicationErrorLogger.Messages, w => Assert.InRange(w.LogLevel, LogLevel.Trace, LogLevel.Debug));
var logMessage = TestApplicationErrorLogger.Messages.Single(m => m.EventId == 20);
Assert.Equal(LogLevel.Information, logMessage.LogLevel);
Assert.Equal("Connection id \"(null)\" request processing ended abnormally.", logMessage.Message);
Assert.Same(ioException, logMessage.Exception);
}

View File

@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
Assert.NotNull(transportConnection.AbortReason);
Assert.Equal(CoreStrings.ConnectionTimedBecauseResponseMininumDataRateNotSatisfied, transportConnection.AbortReason.Message);
Assert.Single(TestApplicationErrorLogger.Messages, w => w.EventId.Id == 28 && w.LogLevel == LogLevel.Information);
Assert.Single(TestApplicationErrorLogger.Messages, w => w.EventId.Id == 28 && w.LogLevel <= LogLevel.Debug);
}
}
}

View File

@ -431,7 +431,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests
Assert.NotNull(readException);
Assert.Contains(TestSink.Writes, w => w.EventId.Id == 17 && w.LogLevel == LogLevel.Information && w.Exception is BadHttpRequestException
Assert.Contains(TestSink.Writes, w => w.EventId.Id == 17 && w.LogLevel <= LogLevel.Debug && w.Exception is BadHttpRequestException
&& ((BadHttpRequestException)w.Exception).StatusCode == StatusCodes.Status400BadRequest);
}
@ -1750,7 +1750,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests
}
}
Assert.Contains(TestApplicationErrorLogger.Messages, w => w.EventId.Id == 17 && w.LogLevel == LogLevel.Information && w.Exception is BadHttpRequestException
Assert.Contains(TestApplicationErrorLogger.Messages, w => w.EventId.Id == 17 && w.LogLevel <= LogLevel.Debug && w.Exception is BadHttpRequestException
&& ((BadHttpRequestException)w.Exception).StatusCode == StatusCodes.Status400BadRequest);
}
@ -1802,7 +1802,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests
{
while (TestApplicationErrorLogger.Messages.TryDequeue(out var message))
{
if (message.EventId.Id == 17 && message.LogLevel == LogLevel.Information && message.Exception is BadHttpRequestException
if (message.EventId.Id == 17 && message.LogLevel <= LogLevel.Debug && message.Exception is BadHttpRequestException
&& ((BadHttpRequestException)message.Exception).StatusCode == StatusCodes.Status400BadRequest)
{
foundMessage = true;
@ -1863,7 +1863,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests
}
}
Assert.Contains(TestApplicationErrorLogger.Messages, w => w.EventId.Id == 17 && w.LogLevel == LogLevel.Information && w.Exception is BadHttpRequestException
Assert.Contains(TestApplicationErrorLogger.Messages, w => w.EventId.Id == 17 && w.LogLevel <= LogLevel.Debug && w.Exception is BadHttpRequestException
&& ((BadHttpRequestException)w.Exception).StatusCode == StatusCodes.Status400BadRequest);
}
@ -4118,13 +4118,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests
if (sendMalformedRequest)
{
Assert.Contains(testSink.Writes, w => w.EventId.Id == 17 && w.LogLevel == LogLevel.Information && w.Exception is BadHttpRequestException
Assert.Contains(testSink.Writes, w => w.EventId.Id == 17 && w.LogLevel <= LogLevel.Debug && w.Exception is BadHttpRequestException
&& ((BadHttpRequestException)w.Exception).StatusCode == StatusCodes.Status400BadRequest);
}
else
{
Assert.DoesNotContain(testSink.Writes, w => w.EventId.Id == 17 && w.LogLevel == LogLevel.Information && w.Exception is BadHttpRequestException
&& ((BadHttpRequestException)w.Exception).StatusCode == StatusCodes.Status400BadRequest);
Assert.DoesNotContain(testSink.Writes, w => w.EventId.Id == 17);
}
}