创建跨追踪的链接
了解如何使用 OpenTelemetry .NET 创建跨追踪的链接
本指南将介绍如何在 OpenTelemetry .NET 中创建跨追踪的链接,这在扇出操作、批处理处理或关联不同追踪中的相关活动时非常有用。
什么是追踪链接?
在 OpenTelemetry 中,链接允许您在 span(或 .NET 中的 activity)之间建立关联,这些 span 是相关的,但可能没有直接的父子关系。这在分布式系统中尤其有用,您需要关联可能属于不同追踪的多个操作。
使用链接的常见场景包括:
- 扇出操作:当单个请求触发多个并行操作时
- 批量处理:当多个传入请求在单个批次中进行处理时
- 异步处理:当操作在不同追踪中异步处理时
- 跨服务关联:当连接不同服务中的相关操作时
创建现有活动的链接
以下示例演示了如何创建新的根活动,并链接到现有活动。
using System.Diagnostics;
using OpenTelemetry;
using OpenTelemetry.Trace;
// Create an activity source
var activitySource = new ActivitySource("MyCompany.MyApplication");
// Configure OpenTelemetry
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSource("MyCompany.MyApplication")
.AddConsoleExporter()
.Build();
// Start a parent activity
using (var orchestratingActivity = activitySource.StartActivity("OrchestratingActivity"))
{
orchestratingActivity?.SetTag("operation", "main-process");
// Fan out to multiple operations with linked activities
await DoFanoutAsync(activitySource, 3);
// Continue with the original activity
using (var nestedActivity = activitySource.StartActivity("WrapUp"))
{
nestedActivity?.SetTag("status", "completed");
}
}
// Method that creates new root activities with links
async Task DoFanoutAsync(ActivitySource source, int operationCount)
{
// Store the current activity to restore it later
var previous = Activity.Current;
// Get the context of the current activity for linking
var activityContext = Activity.Current!.Context;
var links = new List<ActivityLink>
{
new ActivityLink(activityContext),
};
var tasks = new List<Task>();
// Create multiple new root activities that link to the original activity
for (int i = 0; i < operationCount; i++)
{
int operationIndex = i;
var task = Task.Run(() =>
{
// Set the current activity to null to create a new root activity
Activity.Current = null;
// Create a new root activity with a link to the original activity
using var newRootActivity = source.StartActivity(
ActivityKind.Internal,
name: $"FannedOutActivity {operationIndex + 1}",
links: links);
// Perform work for this operation...
});
tasks.Add(task);
}
// Wait for all fanned-out operations to complete
await Task.WhenAll(tasks);
// Restore the original activity context
Activity.Current = previous;
}
理解输出
运行此代码后,您将在输出中看到多个活动。
- 一个追踪用于
OrchestratingActivity(原始活动) - 多个独立的追踪,每个
FannedOutActivity一个 - 每个
FannedOutActivity都链接到OrchestratingActivity
输出将类似于:
Activity.TraceId: 5ce4d8ad4926ecdd0084681f46fa38d9
Activity.SpanId: 8f9e9441f0789f6e
Activity.TraceFlags: Recorded
Activity.ActivitySourceName: MyCompany.MyApplication
Activity.DisplayName: FannedOutActivity 1
Activity.Kind: Internal
Activity.StartTime: 2023-10-17T01:24:40.4957326Z
Activity.Duration: 00:00:00.0008656
Activity.Links:
2890476acefb53b93af64a0d91939051 16b83c1517629363
请注意,此活动具有:
- 新的追踪 ID(
5ce4d8ad4926ecdd0084681f46fa38d9) - 链接到原始活动的追踪和 span ID(
2890476acefb53b93af64a0d91939051 16b83c1517629363)
何时使用链接
考虑在以下场景中使用链接:
高基数操作:当单个操作会生成数千个 span 时,创建具有链接的独立追踪可以使可视化和分析更易于管理。
并行处理:当并行处理项目时,您希望独立跟踪每个项目的处理,同时保持与原始请求的连接。
异步工作流:当操作异步发生并且可能不在同一追踪生命周期内完成时。
使用链接的权衡
虽然链接提供了灵活性,但也有一些需要考虑的地方:
- 多个追踪:您将拥有多个相关的追踪,而不是一个连贯的追踪。
- 可视化复杂性:某些可观测性工具可能对可视化链接追踪的支持有限。
- 分析复杂性:跨链接追踪分析数据需要更复杂的查询。
最佳实践
- 使用有意义的活动名称:选择清晰的名称,表明每个链接活动的用途。
- 添加上下文标签:包含有助于识别活动为何链接的标签。
- 恢复原始上下文:在创建链接活动后,始终恢复原始的
Activity.Current。 - 谨慎使用:仅在必要时创建新的根活动,以避免碎片化您的追踪数据。