gpt4 book ai didi

c# - 在旧 ASP.NET 4.8 中读取和传播 TraceId

转载 作者:行者123 更新时间:2023-12-04 09:45:06 24 4
gpt4 key购买 nike

我正在维护几个用 ASP.NET 4.8(完整框架)和 ASP.NET Core 编写的应用程序。

.NET Core 实现 https://www.w3.org/TR/trace-context/这样我就可以看到我的日志(我使用 Serilog 进行结构化日志记录),其中包含 ParentId、SpanId 以及最重要的 TraceId。

有没有办法在旧的 ASP.NET 4.8 应用程序中读取和传播 TraceId?

我的应用程序之间正在执行大量请求,这将极大地改善调试体验。不幸的是,大多数请求源自旧的 ASP.NET 4.8 应用程序,并转到较新的 .NET Core 应用程序。

理想情况下,我希望达到与 ASP.NET Core 应用程序相同的状态 - 如果 Request-Id 来自 HTTP header ,则使用它并将其填充到 ParentId 和 TraceId 中,并基于此生成 SpanId。此外,它还会进一步传播到源自 .NET Core 应用程序的其他 HTTP 请求。

谢谢!

最佳答案

好的,我自己解决了。

首先需要添加System.Diagnostics.DiagnosticSource金 block 包。

然后,创建 ActivityManager类:

public static class ActivityManager
{
public static void StartActivity()
{
if (Activity.Current == null)
{
var activity = new Activity("Default Activity");

string parentIdFromHeaders = HttpContext.Current?.Request.Headers[GetRequestIdHeaderName()];
if (!string.IsNullOrEmpty(parentIdFromHeaders))
{
activity.SetParentId(parentIdFromHeaders);
}

activity.Start();
Activity.Current = activity;

// Sometimes I had issues with Activity.Current being empty even though I set it
// So just to be sure, I add it also to HttpContext Items.
HttpContext.Current?.Items.Add("Activity", activity);
}
}

public static void StopActivity()
{
GetActivity()?.Stop();
}

public static Activity GetActivity()
{
Activity activity = Activity.Current ?? (Activity)HttpContext.Current.Items["Activity"];
return activity;
}

public static string GetRequestIdHeaderName()
{
return "Request-Id";
}

public static string GetRequestId()
{
Activity activity = GetActivity();

if (activity != null)
{
string activityId = activity.Id;
return activityId;
}

// For the rare cases when something happens and activity is not set
// Try to read Request-Id first, if none, then create new GUID
return HttpContext.Current?.Request.Headers.Get(GetRequestIdHeaderName())
?? Guid.NewGuid().ToString().Replace("-", "");
}
}

并配置Global.asax.cs处理程序

protected void Application_Start()
{
Activity.DefaultIdFormat = ActivityIdFormat.Hierarchical;
}

protected void Application_BeginRequest()
{
ActivityManager.StartActivity();
}

protected void Application_EndRequest()
{
ActivityManager.StopActivity();
}

现在所有传入请求都会创建新的 Activity并正确设置其 ParentId .

添加SpanId , TraceIdParentId为了记录上下文,我创建了自定义日志丰富器:

public class TraceLogEnricher : ILogEventEnricher
{
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
Activity activity = ActivityManager.GetActivity();

if (activity != null)
{
string parentId = activity.ParentId;
string rootId = activity.RootId;
string activityId = activity.Id;

logEvent.AddPropertyIfAbsent(new LogEventProperty("SpanId", new ScalarValue(activityId)));
logEvent.AddPropertyIfAbsent(new LogEventProperty("ParentId", new ScalarValue(parentId)));
logEvent.AddPropertyIfAbsent(new LogEventProperty("TraceId", new ScalarValue(rootId))); }
}
}

并将其添加到 Serilog 配置中 .Enrich.With<TraceLogEnricher>() .

最后一步是配置传出请求。在 HttpClient使用DefaultRequestHeaders 。 (为了更方便,也可以在 IHttpClientFactory 配置中进行配置)。

var requestId = ActivityManager.GetRequestId();
client.DefaultRequestHeaders.Add("Request-Id", requestId);

如果使用 WebServices,最好添加 Request-Id header 也适用于 Web 服务请求。为此,请覆盖 GetWebRequest Web 服务客户端的方法。 (这些通常生成为分部类,因此请在您自己的分部类文件中覆盖它)。

protected override WebRequest GetWebRequest(Uri uri)
{
var request = base.GetWebRequest(uri);

request.Headers.Add("Request-Id", ActivityManager.GetRequestId());

return request;
}

关于c# - 在旧 ASP.NET 4.8 中读取和传播 TraceId,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62167181/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com