我正在尝试拥有一个 azure 函数(.net core 6 隔离),我想在其中连接到应用程序洞察力和用户 W3C traceparent 作为我的关联方法。
我已经安装了 System.Diagnostics.DiagnosticSource (7.0.1)、Microsoft.Azure.Functions.Worker.ApplicationInsights (1.0.0-preview) 并将所需的代码添加到我的 program.cs
.ConfigureFunctionsWorkerDefaults(builder =>
{
builder.AddApplicationInsights()
.AddApplicationInsightsLogger();
})
虽然我看到 Activity.Id 确实包含一个 traceparent 格式字符串,但如果我发送一个 traceparent 标头,活动不会获取它,因此,我在应用程序洞察中看不到它。此外,响应不会发送回 traceparent 标头......
然后我被迫创建一个中间件来尝试这个,我很想知道这是否是实现目标的正确方法,记住这只适用于 http 触发器(更喜欢适用于所有触发器的东西)
public class TraceparentMiddleware : IFunctionsWorkerMiddleware
{
private const string TraceParentPattern = "^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$";
public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
{
try
{
if (await TrySetActivityId(context))
await next(context);
else
{
var req = await context.GetHttpRequestDataAsync();
var res = req!.CreateResponse(HttpStatusCode.BadRequest);
await res.WriteStringAsync("Invalid traceparent format.");
context.GetInvocationResult().Value = res;
}
SetTraceparentHeader(context);
}
catch
{
SetTraceparentHeader(context);
throw; //because I don't know where the app insights code to log the exceptions happens.
}
}
private static async Task<bool> TrySetActivityId(FunctionContext context)
{
var request = await context.GetHttpRequestDataAsync();
if (request?.Headers?.TryGetValues("traceparent", out var values) ?? false && !string.IsNullOrWhiteSpace(values?.FirstOrDefault()))
{
var regex = new Regex(TraceParentPattern, RegexOptions.IgnoreCase);
if (regex.IsMatch(values.FirstOrDefault()))
Activity.Current.GetType()
.GetField("_id", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
.SetValue(Activity.Current, values.FirstOrDefault());
else
return false;
}
return true;
}
private void SetTraceparentHeader(FunctionContext context)
{
var response = context.GetHttpResponseData();
if (!response?.Headers?.Contains("traceparent") ?? false)
response.Headers.Add("traceparent", Activity.Current.Id);
}
}
如您所见...我什至被迫使用反射来设置 Activity.Current.Id,我想避免这种情况。