-
Notifications
You must be signed in to change notification settings - Fork 161
Expand file tree
/
Copy pathNLogRequestLoggingOptions.cs
More file actions
143 lines (130 loc) · 5.41 KB
/
Copy pathNLogRequestLoggingOptions.cs
File metadata and controls
143 lines (130 loc) · 5.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using NLog.Web.Internal;
namespace NLog.Web
{
/// <summary>
/// Options configuration for <see cref="NLogRequestLoggingMiddleware"/>
/// </summary>
public sealed class NLogRequestLoggingOptions
{
internal static readonly NLogRequestLoggingOptions Default = new NLogRequestLoggingOptions();
/// <summary>
/// Initializes a new instance of the <see cref="NLogRequestLoggingOptions" /> class.
/// </summary>
public NLogRequestLoggingOptions()
{
ShouldLogRequest = ShouldLogRequestDefault;
}
/// <summary>
/// Logger-name used for logging http-requests
/// </summary>
/// <remarks>Default: <c>NLogRequestLogging</c></remarks>
public string LoggerName { get; set; } = "NLogRequestLogging";
/// <summary>
/// Get or set duration time in milliseconds, before a HttpRequest is seen as slow (Logged as warning)
/// </summary>
/// <remarks>Default: 300 milliseconds</remarks>
public int DurationThresholdMs { get => (int)_durationThresholdMs.TotalMilliseconds; set => _durationThresholdMs = TimeSpan.FromMilliseconds(value); }
private TimeSpan _durationThresholdMs = TimeSpan.FromMilliseconds(300);
/// <summary>
/// Gets or sets request-paths where LogLevel should be reduced (Logged as debug)
/// </summary>
/// <remarks>
/// Example '/healthcheck'
/// </remarks>
public ISet<string> ExcludeRequestPaths { get; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
/// <summary>
/// Mapper from HttpContext status to LogLevel
/// </summary>
public Func<HttpContext, Exception?, Microsoft.Extensions.Logging.LogLevel> ShouldLogRequest { get; set; }
private Microsoft.Extensions.Logging.LogLevel ShouldLogRequestDefault(HttpContext httpContext, Exception? exception)
{
if (exception is null)
{
var statusCode = httpContext.Response?.StatusCode ?? 0;
if (statusCode < 100 || (statusCode >= 400 && statusCode < 600))
{
return Microsoft.Extensions.Logging.LogLevel.Warning;
}
else if (IsExcludedHttpRequest(httpContext))
{
return Microsoft.Extensions.Logging.LogLevel.Debug;
}
else if (IsSlowHttpRequest())
{
return Microsoft.Extensions.Logging.LogLevel.Warning;
}
else
{
return Microsoft.Extensions.Logging.LogLevel.Information;
}
}
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 - only warn if the server was slow
return IsSlowHttpRequest()
? Microsoft.Extensions.Logging.LogLevel.Warning
: Microsoft.Extensions.Logging.LogLevel.Information;
}
}
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)
{
if (currentActivity.StartTimeUtc > DateTime.MinValue)
activityStartTime = currentActivity.StartTimeUtc;
currentActivity = currentActivity.Parent;
}
if (activityStartTime > DateTime.MinValue)
{
var currentDuration = DateTime.UtcNow - activityStartTime;
if (currentDuration > _durationThresholdMs)
{
return true;
}
}
#endif
return false;
}
private bool IsExcludedHttpRequest(HttpContext httpContext)
{
if (ExcludeRequestPaths.Count > 0)
{
var requestPath = httpContext.TryGetFeature<IHttpRequestFeature>()?.Path;
if (requestPath is null || string.IsNullOrEmpty(requestPath))
{
requestPath = httpContext.Request?.Path;
if (requestPath is null || string.IsNullOrEmpty(requestPath))
{
return false;
}
}
return ExcludeRequestPaths.Contains(requestPath);
}
return false;
}
}
}