feat(shared-web): add shared swagger and tracing utilities

This commit is contained in:
2025-11-22 21:20:49 +08:00
parent b9d4a06f61
commit b587e8c1e1
22 changed files with 1058 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using TakeoutSaaS.Shared.Abstractions.Diagnostics;
namespace TakeoutSaaS.Shared.Web.Middleware;
/// <summary>
/// 统一 TraceId/CorrelationId贯穿日志与响应。
/// </summary>
public sealed class CorrelationIdMiddleware
{
private const string TraceHeader = "X-Trace-Id";
private const string RequestHeader = "X-Request-Id";
private readonly RequestDelegate _next;
private readonly ILogger<CorrelationIdMiddleware> _logger;
public CorrelationIdMiddleware(RequestDelegate next, ILogger<CorrelationIdMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
var traceId = ResolveTraceId(context);
context.TraceIdentifier = traceId;
TraceContext.TraceId = traceId;
context.Response.OnStarting(() =>
{
context.Response.Headers[TraceHeader] = traceId;
return Task.CompletedTask;
});
using (_logger.BeginScope(new Dictionary<string, object>
{
["TraceId"] = traceId
}))
{
try
{
await _next(context);
}
finally
{
TraceContext.Clear();
}
}
}
private static string ResolveTraceId(HttpContext context)
{
if (TryGetHeader(context, TraceHeader, out var traceId))
{
return traceId;
}
if (TryGetHeader(context, RequestHeader, out var requestId))
{
return requestId;
}
return Guid.NewGuid().ToString("N");
}
private static bool TryGetHeader(HttpContext context, string headerName, out string value)
{
if (context.Request.Headers.TryGetValue(headerName, out var values))
{
var headerValue = values.ToString();
if (!string.IsNullOrWhiteSpace(headerValue))
{
value = headerValue;
return true;
}
}
value = string.Empty;
return false;
}
}