Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/NLog.Web.AspNetCore/NLogRequestLoggingMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ private bool LogHttpRequest(HttpContext httpContext, Exception? exception)
_logger.Log(logLevel, 0, null, "HttpRequest Completed");
break;
case Microsoft.Extensions.Logging.LogLevel.Warning:
var statusCode = httpContext.Response?.StatusCode ?? 0;
if (statusCode < 100 || (statusCode >= 400 && statusCode < 600))
_logger.Log(logLevel, 0, null, "HttpRequest Failure");
else
_logger.Log(logLevel, 0, null, "HttpRequest Completed");
break;
case Microsoft.Extensions.Logging.LogLevel.Error:
case Microsoft.Extensions.Logging.LogLevel.Critical:
_logger.Log(logLevel, 0, null, "HttpRequest Failure");
Expand Down
20 changes: 20 additions & 0 deletions src/NLog.Web.AspNetCore/NLogRequestLoggingOptions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using NLog.Web.Internal;
Expand Down Expand Up @@ -69,13 +70,32 @@ private Microsoft.Extensions.Logging.LogLevel ShouldLogRequestDefault(HttpContex
}
else
{
if (exception is OperationCanceledException || (exception is AggregateException aggregateException && aggregateException.InnerException is OperationCanceledException))
{
var statusCode = httpContext.Response?.StatusCode ?? 0;
if (statusCode == StatusCodes.Status408RequestTimeout
#if NET8_0_OR_GREATER
|| statusCode == StatusCodes.Status499ClientClosedRequest
#else
|| statusCode == 499
#endif
|| httpContext.RequestAborted.IsCancellationRequested
)
{
// Client canceled the request - not server side error, but maybe server is responding slow
return Microsoft.Extensions.Logging.LogLevel.Warning;
}
}
return Microsoft.Extensions.Logging.LogLevel.Error;
}
}

private bool IsSlowHttpRequest()
{
#if NETCOREAPP3_0_OR_GREATER
if (_durationThresholdMs == TimeSpan.Zero)
return false;

var currentActivity = System.Diagnostics.Activity.Current;
var activityStartTime = DateTime.MinValue;
while (currentActivity != null)
Expand Down
19 changes: 12 additions & 7 deletions src/NLog.Web.AspNetCore/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,25 @@ Supported platforms:
- ASP.NET Core 6, 7, 8, 9 and 10
- ASP.NET Core 2, .NET Standard 2.0 and .NET 4.6.2+

Registration of NLog.Web.AspNetCore in the NLog.config file:
Register NLog as logging provider:
```csharp
builder.Logging.ClearProviders();
builder.Host.UseNLog();
```

If logging is needed before the host building, then one can use fluent setup:
```csharp
var logger = NLog.LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
```

Alternative include NLog.Web.AspNetCore extension in the NLog.config file:

```xml
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
```

Registration of NLog.Web.AspNetCore can also be performed with fluent setup:

```csharp
NLog.LogManager.Setup().LoadConfigurationFromAppSettings();
```

Useful Links:

- [Home Page](https://nlog-project.org/)
Expand Down
3 changes: 3 additions & 0 deletions src/NLog.Web/NLogRequestLoggingModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ private bool IsSlowHttpRequest(HttpContext? httpContext)
if (httpContext is null)
return false;

if (_durationThresholdMs == TimeSpan.Zero)
return false;

var timestamp = httpContext.Timestamp;
if (timestamp > DateTime.MinValue)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,44 @@ public void HttpRequestFailedTest()
Assert.Equal("Warn|HttpRequest Failure", testTarget.Logs[0]);
}

[Fact]
public void HttpRequestAbortedTest()
{
// Arrange
DefaultHttpContext defaultContext = new DefaultHttpContext();
defaultContext.Response.Body = new MemoryStream();
defaultContext.Request.Path = "/";

var testTarget = new NLog.Targets.MemoryTarget() { Layout = "${level}|${message}" };
var nlogFactory = new LogFactory().Setup().LoadConfiguration(builder =>
{
builder.ForLogger().WriteTo(testTarget);
}).LogFactory;
var loggerFactory = new NLogLoggerFactory(new NLogLoggerProvider(new NLogProviderOptions(), nlogFactory));

var middlewareInstance = new NLogRequestLoggingMiddleware(next: (innerHttpContext) =>
{
innerHttpContext.Response.StatusCode = StatusCodes.Status408RequestTimeout;
throw new OperationCanceledException();
}, loggerFactory: loggerFactory);

// Act
Assert.Throws<OperationCanceledException>(() =>
{
try
{
middlewareInstance.Invoke(defaultContext).GetAwaiter().GetResult();
}
catch
{
// Assert
Assert.Single(testTarget.Logs);
Assert.Equal("Warn|HttpRequest Exception", testTarget.Logs[0]);
throw;
}
});
}

[Fact]
public void HttpRequestExceptionFilterTest()
{
Expand Down