Code
·
54 lines
·
2038 bytes
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
54using Microsoft.AspNetCore.Http.Features;
using Microsoft.Net.Http.Headers;
using Serilog.Core;
using Serilog.Events;
namespace SeriLoog.Extensions;
/// <summary>
/// Enriches every log event with request context, but only when one actually
/// exists (i.e. we're inside an HTTP request). Background work, startup logs
/// and anything logged outside a request simply won't get these properties.
/// </summary>
public sealed class HttpContextEnricher : ILogEventEnricher
{
private readonly IHttpContextAccessor _httpContextAccessor;
public HttpContextEnricher(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
var context = _httpContextAccessor.HttpContext;
if (context is null)
return;
var request = context.Request;
var ip = context.Connection.RemoteIpAddress?.ToString() ?? "unknown";
var forwarded = request.Headers["X-Forwarded-For"].FirstOrDefault();
if (!string.IsNullOrEmpty(forwarded))
{
ip = forwarded.Split(',').First().Trim();
}
var sessionId = context.Features.Get<ISessionFeature>() is not null
? context.Session.Id
: string.Empty;
Set(logEvent, propertyFactory, "ClientIp", ip);
Set(logEvent, propertyFactory, "RequestUrl", $"{request.Scheme}://{request.Host}{request.Path}{request.QueryString}");
Set(logEvent, propertyFactory, "TraceId", context.TraceIdentifier);
Set(logEvent, propertyFactory, "Referer", request.Headers[HeaderNames.Referer].FirstOrDefault() ?? string.Empty);
Set(logEvent, propertyFactory, "UserAgent", request.Headers[HeaderNames.UserAgent].FirstOrDefault() ?? string.Empty);
Set(logEvent, propertyFactory, "SessionId", sessionId);
Set(logEvent, propertyFactory, "User", context.User?.Identity?.Name ?? "anonymous");
}
private static void Set(LogEvent logEvent, ILogEventPropertyFactory propertyFactory, string name, string value)
{
logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty(name, value));
}
}