我目前正在使用
.NET 6.0 isolated
函数和 HTTP trigger
。
因为活动未填充,我添加了一个中间件,该中间件基于 W3C
traceparent
标头创建活动。
我基于 MS docs 的期望是,使用 Application Insights 时,
operation_ParentId
将直接与完成日志记录的 ParentSpanId
的 Activity
相关。
但这不是我所看到的。我看到的是以下
traceparent = 00-3abe9f15e940badc5f1521e6eb1eb411-bfd30439c918c783-00
ParentId
等于 00-3abe9f15e940badc5f1521e6eb1eb411-bfd30439c918c783-00
。 ParentSpanId
等于 bfd30439c918c783
using var requestActivity = new Activity(context.FunctionDefinition.Name);
requestActivity.SetParentId(traceParent);
requestActivity.Start();
_logger.LogInformation("Invoking '{Name}'", context.FunctionDefinition.Name);
OperationId
等于 WC3 跟踪 ID 3abe9f15e940badc5f1521e6eb1eb411
,正如预期的那样。然而,operation_ParentId
是我以前从未见过的跨度。它既不是 requestActivity.SpanId
也不是 requestActivity.ParentSpanId
。发生了什么我不明白的事情? Application Insights 在记录时是否不使用活动的
Activity
?
我的应用程序配置
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults(worker =>
{
worker.UseMiddleware<TracingMiddleware>();
})
.ConfigureServices(collection =>
{
})
.ConfigureLogging(x=>x.AddApplicationInsights())
.Build();
host.Run();
我的中间件功能
public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
{
using var requestActivity = new Activity(context.FunctionDefinition.Name);
SetParentId(context, requestActivity);
requestActivity.Start();
_logger.LogInformation("Invoking '{Name}'", context.FunctionDefinition.Name);
var t = Activity.Current;
System.Console.WriteLine();
System.Console.WriteLine($"Activity.TraceId: {t.TraceId}");
System.Console.WriteLine($"Activity.ParentId: {t.ParentId}");
System.Console.WriteLine($"Activity.SpanId: {t.SpanId}");
await next(context);
var statusCode = (context.Items != null)
? context.GetHttpResponseData()?.StatusCode
: System.Net.HttpStatusCode.OK;
_logger.LogInformation(
"Executed '{Name}', Result {Result}, Duration = {Duration}ms",
context.FunctionDefinition.Name,
statusCode,
(DateTime.UtcNow - requestActivity.StartTimeUtc).TotalMilliseconds);
requestActivity.Stop();
}
更新 首先,在我看来,Application Insights 对于隔离功能来说仍然没有完全正常运行。有些值可能会丢失(例如操作名称),但只需很少的工作,使用 Application Insights SDK 您仍然可以一致地添加它。
与HTTP跨度的差异相关:在进行调用(例如HTTP调用)时,库可以启动新的子活动。这就是为什么您可以获得与预期不同的父跨度。协调自动传递跟踪信息时使用的类是
DistributedContextPropagator
。我首先根据这篇文章对其进行了一些更改,以消除子活动创建的额外层。
但是,最终我们恢复了这一点,因为 Application Insights 更喜欢您保留尽可能多的默认值。获得应用程序见解(例如应用程序地图)的良好概述比使其在我查询的跟踪语句中完美对齐更重要。
根据 MS-Doc,操作 ID 等于 TraceId。而Operation_parent Id 是Trace-ID 和Parent-ID 的组合。格式有 .
字段的格式为operation_ParentId
,其中<trace-id>.<parent-id>
和trace-id
都是 从请求中传递的跟踪标头中获取。parent-id
我注意到它实际上并不相同。我已经厌倦了许多可能的方法。我最终得到 The operation-ID is not equal to the Trace-ID and the Operation-parent-ID is not equal to < Trace-ID>.< Parent-ID>.
在我的中间件中,我添加了当前上下文,如下所示
ILogger logger = context.GetLogger<MyCustomMiddleware>();
//logger.LogInformation("From function: {message}", message);
using var requestActivity = new Activity(context.FunctionDefinition.Name);
//t.SetParentId(context, requestActivity);
requestActivity.Start();
logger.LogInformation("Invoking '{Name}'", context.FunctionDefinition.Name);
//requestActivity.SetParentId(Convert.ToString(requestActivity.RootId));
requestActivity.SetParentId(requestActivity.TraceId,requestActivity.SpanId,ActivityTraceFlags.None);
var t = Activity.Current;
//Activity.SetParentId(context, requestActivity,);
//t.SetParentId(context, requestActivity)
logger.LogInformation($"Activity.TraceId: {t.TraceId}");
logger.LogInformation($"Activity.ParentId: {t.ParentId}");
logger.LogInformation($"Activity.SpanId: {t.SpanId}");
logger.LogInformation($"Activity.Id: {t.Id}");
logger.LogInformation($"Activity.ParentSpanId: {t.ParentSpanId}");
logger.LogInformation($"Activity.RootId: {t.RootId}");
logger.LogInformation($"Activity.Parent: {t.Parent}");
我得到的结果。
请参阅此处了解我的解决方法之一,其中包含更多详细信息。