-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathCorrelationIdEnricher.cs
More file actions
128 lines (111 loc) · 4.28 KB
/
CorrelationIdEnricher.cs
File metadata and controls
128 lines (111 loc) · 4.28 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
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Serilog.Core;
using Serilog.Events;
namespace Serilog.Enrichers;
/// <inheritdoc />
public class CorrelationIdEnricher : ILogEventEnricher
{
private const string CorrelationIdItemKey = "Serilog_CorrelationId";
private const string PropertyName = "CorrelationId";
private readonly bool _addCorrelationIdToResponse;
private readonly bool _addValueIfHeaderAbsence;
private readonly IHttpContextAccessor _contextAccessor;
private readonly string _headerKey;
/// <summary>
/// Initializes a new instance of the <see cref="CorrelationIdEnricher" /> class.
/// </summary>
/// <param name="headerKey">
/// The header key used to retrieve the correlation ID from the HTTP request or response headers.
/// </param>
/// <param name="addValueIfHeaderAbsence">
/// Determines whether to add a new correlation ID value if the header is absent.
/// </param>
/// <param name="addCorrelationIdToResponse">
/// Determines whether to add correlation ID value to <see cref="HttpContext.Response" /> header collection.
/// </param>
public CorrelationIdEnricher(
string headerKey,
bool addValueIfHeaderAbsence,
bool addCorrelationIdToResponse)
: this(
headerKey,
addValueIfHeaderAbsence,
addCorrelationIdToResponse,
new HttpContextAccessor())
{
}
internal CorrelationIdEnricher(
string headerKey,
bool addValueIfHeaderAbsence,
bool addCorrelationIdToResponse,
IHttpContextAccessor contextAccessor)
{
_headerKey = headerKey;
_addValueIfHeaderAbsence = addValueIfHeaderAbsence;
_addCorrelationIdToResponse = addCorrelationIdToResponse;
_contextAccessor = contextAccessor;
}
/// <inheritdoc />
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
HttpContext httpContext = _contextAccessor.HttpContext;
if (httpContext == null) return;
if (httpContext.Items.TryGetValue(CorrelationIdItemKey, out object value) &&
value is LogEventProperty logEventProperty)
{
logEvent.AddPropertyIfAbsent(logEventProperty);
// Ensure the string value is also available if not already stored
if (!httpContext.Items.ContainsKey(Constants.CorrelationIdValueKey))
{
string correlationIdValue = ((ScalarValue)logEventProperty.Value).Value as string;
httpContext.Items.Add(Constants.CorrelationIdValueKey, correlationIdValue);
}
return;
}
string correlationId = PrepareCorrelationId(httpContext);
AddCorrelationIdToResponse(httpContext, correlationId);
LogEventProperty correlationIdProperty = new(PropertyName, new ScalarValue(correlationId));
logEvent.AddOrUpdateProperty(correlationIdProperty);
httpContext.Items.Add(CorrelationIdItemKey, correlationIdProperty);
httpContext.Items.Add(Constants.CorrelationIdValueKey, correlationId);
}
private void AddCorrelationIdToResponse(HttpContext httpContext, in string correlationId)
{
if (_addCorrelationIdToResponse
&& !httpContext.Response.Headers.ContainsKey(_headerKey))
{
httpContext.Response.Headers[_headerKey] = correlationId;
}
}
private string PrepareCorrelationId(HttpContext httpContext)
{
StringValues requestHeader = httpContext.Request.Headers[_headerKey];
string returnValue;
if (!string.IsNullOrWhiteSpace(requestHeader))
{
returnValue = requestHeader;
}
else
{
StringValues responseHeader = httpContext.Response.Headers[_headerKey];
if (!string.IsNullOrWhiteSpace(responseHeader))
{
returnValue = responseHeader;
}
else
{
if (_addValueIfHeaderAbsence)
{
returnValue = Guid.NewGuid().ToString();
}
else
{
returnValue = null;
}
}
}
return returnValue;
}
}