主要实现思路是生成并管理Trace ID和Span ID,记录请求的关键数据,并将这些数据保存到日志或数据库中供分析
基本思路
-
生成 Trace ID 和 Span ID:在每次请求开始时生成唯一的 Trace ID 和 Span ID,并在子调用中生成新的 Span ID。
-
Trace ID:用于标识整个请求链,通常每个请求(比如一次HTTP请求)会生成一个唯一的Trace ID。无论这个请求经过多少服务、多少个子操作,整个链路的所有操作都共享同一个Trace ID。因此,通过Trace ID,可以把一次请求的所有操作串联起来,形成完整的调用链。
-
Span ID:用于标识单个操作或子调用。每个Span代表一次具体的调用或操作,并记录该操作的开始和结束时间、持续时间、相关信息等。每个Span都有独立的Span ID,因此在同一个Trace中,不同的操作或子调用会有各自的Span ID。
-
-
记录调用开始和结束时间:在每个调用中记录开始时间和结束时间,计算出响应时间。
-
保存追踪数据:将追踪数据保存到文件或数据库中,以便后续分析。
-
输出和分析:可以使用简单的日志文件格式或数据库查询工具来分析链路追踪数据。
Trace ID和Span ID是链路追踪的核心,用于区分和识别一次请求的全链路。可以使用uniqid或random_bytes来生成ID。
注意: 额外的记录且频繁的记录会增加额外的开销,现实远比理论复杂,很多时候合适当前项目的实现才是最好的实现。
class Span {
public $traceId;
public $spanId;
public $parentId;
public $operationName;
public $startTime;
public $endTime;
public function __construct($traceId, $spanId, $parentId = null, $operationName = '') {
$this->traceId = $traceId;
$this->spanId = $spanId;
$this->parentId = $parentId;
$this->operationName = $operationName;
$this->startTime = microtime(true);
}
public function end() {
$this->endTime = microtime(true);
}
public function getDuration() {
return $this->endTime - $this->startTime;
}
public function toArray() {
return [
'trace_id' => $this->traceId,
'span_id' => $this->spanId,
'parent_id' => $this->parentId,
'operation_name' => $this->operationName,
'start_time' => $this->startTime,
'end_time' => $this->endTime,
'duration' => $this->getDuration(),
];
}
}