问题描述
我一直在阅读 W3C Trace Context 规范,但仅通过查看请求中的标头,我无法弄清楚如何获得跨度之间的子关系。
假设我正确理解 processing model,第一个服务生成一个 traceparent
,而后续服务替换 #border {
background-image: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' rx='20' ry='20' stroke='%2350535AFF' stroke-width='2' stroke-dasharray='4%2c 8' stroke-dashoffset='81' stroke-linecap='round'/%3e%3c/svg%3e");
border-radius: 20px;
height: 80px;
line-height: 80px;
font-size: $sama-font-size-3;
color: mat-color($mat-sama-gray,58);
text-align: center;
cursor: pointer;
}
中的 parentId
以用于下游请求。
因此服务 A 生成一个 traceparent
并向服务 B 发送请求:
traceparent
服务 B 收到请求,每次更改 host: service-b
traceparent: 00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01
时都会向服务 C 和服务 D 发出两个下游请求:
parentId
host: service-c
traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
最后我的请求中有三个 host: service-d
traceparent: 00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01
traceparent
很容易看出它们都属于跟踪 00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01
00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01
,但我如何找出它们之间的父子关系?
我最初的想法是这是使用 0af7651916cd43dd8448eb211c80319c
完成的,但规范指出:
tracestate 使用由一组名称/值对表示的供应商特定数据扩展了 traceparent。在 tracestate 中存储信息是可选的。
解决方法
如您之前所说,tracestate
字段仅负责传播特定于供应商的数据。此外,traceparent
本身并没有携带足够的上下游关系信息。跟踪上下文解决了三个问题:为单个跟踪提供唯一标识符,提供一种商定的机制来转发特定于供应商的跟踪数据 (tracestate
),并提供中介、平台和硬件提供商可以支持的行业标准.如果您想建立上游-下游(或父-子)关系,您将需要当前跨度范围的 traceparent
以及上游的 traceparent
。看一下c#中的一个例子.NET 5
:
using System;
using System.Diagnostics;
var upstreamActivity = new Activity("Upstream");
upstreamActivity.Start();
Console.WriteLine(upstreamActivity.OperationName);
Console.WriteLine("traceparent: {0}",upstreamActivity.Id);
Console.WriteLine("upstream traceparent: {0}",upstreamActivity.ParentId);
CallChildActivity();
upstreamActivity.Stop();
void CallChildActivity()
{
var downstreamActivity = new Activity("Downstream Dependency");
downstreamActivity.Start();
Console.WriteLine(downstreamActivity.OperationName);
Console.WriteLine("traceparent: {0}",downstreamActivity.Id);
Console.WriteLine("upstream traceparent: {0}",downstreamActivity.ParentId);
downstreamActivity.Stop();
}
stdout
将显示如下内容:
Upstream
traceparent: 00-192400a99d30ee459dce14655b09bc41-587841dea0e59b47-00
upstream traceparent:
Downstream Dependency
traceparent: 00-192400a99d30ee459dce14655b09bc41-d95c56215cddd74c-00
upstream traceparent: 00-192400a99d30ee459dce14655b09bc41-587841dea0e59b47-00
第一个 traceparent
的上游 Activity
是空的,这意味着:这是整个跟踪的第一个活动。另一方面,第二种方法有一个非空的ParentId
,所以这是上游活动的标识。请注意,术语 ParentId
与 w3c 规范的 parent-id
不同,在 .NET 5
中它代表上游标识。除此之外,parent-id
字段在 span-id
中称为 .NET 5
。
这与 stack trace
的概念相同,您需要两个 ID 来建立父子关系(我在此 article 中写过)。如果您使用的是与 System.Diagnostics
不同的框架、中间件或库,并且它不提供上游 traceparent
,请记住,您需要在它到达的那一刻存储它新的跨度范围。换句话说,在 parent-id/span-id traceparent
的更新之前。