I am wanting to create a correlation-id to help analyze logs, but I am wanting to generate a single correlation-id per user "session". I.e. one single correlation id from the start to the end of the application (regardless of the operations performed on the web mvc). I was reading up on how to do this using a middleware in .net. I attempted to implement this in my project, however when I start the application and perform certain operations (homescreen -> 2nd page view -> 3rd page view -> final page view) it will create a new correlation-id for each view. Is there a way to generate one single correlation-id that will be for all the operations performed (home view, 2nd page view, 3rd page view, and final page view)?
Startup.cs:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseMiddleware<CorrelationIdMiddleware>();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(x => x
.AllowAnyMethod()
.AllowAnyHeader()
.SetIsOriginAllowed(origin => true) // allow any origin
.AllowCredentials()); // allow credentials
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
CorrelationIdContext.cs:
public class CorrelationIdContext
{
private static readonly AsyncLocal<string> _correlationId = new AsyncLocal<string>();
public static void SetCorrelationId(string correlationId)
{
if (string.IsNullOrWhiteSpace(correlationId))
{
throw new ArgumentException("Correlation Id cannot be null or empty", nameof(correlationId));
}
if (!string.IsNullOrWhiteSpace(_correlationId.Value))
{
throw new InvalidOperationException("Correlation Id is already set for the context");
}
_correlationId.Value = correlationId;
}
public static string GetCorrelationId()
{
return _correlationId.Value;
}
}
CorrelationIdMiddleware.cs:
public class CorrelationIdMiddleware
{
private readonly RequestDelegate _next;
public CorrelationIdMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
context.Request.Headers.TryGetValue("correlation-id", out var correlationIds);
var correlationId = correlationIds.FirstOrDefault() ?? Guid.NewGuid().ToString();
CorrelationIdContext.SetCorrelationId(correlationId);
// Serilog
using (LogContext.PushProperty("correlation-id", correlationId))
{
await _next.Invoke(context);
}
}
}
and in my controllers I just have a simple logger i.e._logger.Log(LogLevel.Information, "First page...");
I noticed when debugging in the CorrelationIdMiddleware.cs file, when it hits the line:
var correlationId = correlationIds.FirstOrDefault() ?? Guid.NewGuid().ToString(); it will create a new correlationID even though one already exists. Is there a way to generate one single correlationId for an entire user session (start to end of application)?
context.Request.Headers.TryGetValue("correlation-id", out var correlationIds); value after the first correlationId is created:

