PHP code example of easyswoole / trace
1. Go to this page and download the library: Download easyswoole/trace library . Choose the download type require .
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
easyswoole / trace example snippets
asySwoole\Trace\Trace;
use EasySwoole\Trace\Utility;
$trace = new Trace('http-request', params: [
'method' => 'GET',
'uri' => '/users/10001',
]);
$controller = $trace->next('UserController::profile');
$service = $controller->next('UserService::profile', [
'user_id' => 10001,
]);
$orders = $service->parallel('order-service');
$coupons = $service->parallel('coupon-service');
$orders->endCall();
$coupons->endCall();
$service->endCall();
$controller->endCall();
$trace->endCall();
echo Utility::toTree($trace), PHP_EOL;
$controller = $trace->next('controller');
$service = $controller->next('service');
$database = $service->next('database');
$trace->next('first');
$trace->next('second'); // LogicException
$serviceA = $point->parallel('service-a');
$serviceB = $point->parallel('service-b');
$serviceC = $point->parallel('service-c');
$next = $point->next('next-call');
$parallel1 = $point->parallel('parallel-1');
$parallel2 = $point->parallel('parallel-2');
use EasySwoole\Trace\TraceStatus;
TraceStatus::Running;
TraceStatus::Success;
TraceStatus::Exception;
TraceStatus::Timeout;
TraceStatus::Abandoned;
$point->endCall();
// 等价于:
$point->endCall(TraceStatus::Success);
try {
callRemoteService();
$point->endCall();
} catch (Throwable $error) {
$point->fail($error);
throw $error;
}
$point->timeout('deadline exceeded');
$parallel1 = $point->parallel('service-1');
$parallel2 = $point->parallel('service-2');
$parallel1->endCall();
// parallel2 没有正常结束。
$point->endCall(); // parallel2 自动变为 abandoned
$point = $trace->next('query-user', [
'user_id' => 10001,
'filters' => [
'status' => 'active',
],
]);
$point->setParams([
'user_id' => 10002,
]);
$params = $point->params();
$paramsJson = json_encode(
$span->params,
JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR,
);
$trace->traceId();
$point->spanId();
$point->parentSpanId();
$trace = new Trace(
name: 'incoming-request',
traceId: $incomingTraceId,
parentSpanId: $incomingSpanId,
);
/**
* @return null|array{trace_id: string, parent_span_id: string, flags: string}
*/
function parseTraceparent(?string $header): ?array
{
if ($header === null) {
return null;
}
$header = strtolower(trim($header));
if (!preg_match(
'/^00-([0-9a-f]{32})-([0-9a-f]{16})-([0-9a-f]{2})$/',
$header,
$matches,
)) {
return null;
}
// W3C 不允许全零 Trace ID 或 Span ID。
if (trim($matches[1], '0') === '' || trim($matches[2], '0') === '') {
return null;
}
return [
'trace_id' => $matches[1],
'parent_span_id' => $matches[2],
'flags' => $matches[3],
];
}
function buildTraceparent(
string $traceId,
string $parentSpanId,
string $flags = '01',
): string {
return sprintf('00-%s-%s-%s', $traceId, $parentSpanId, $flags);
}
use EasySwoole\Trace\Trace;
$incoming = parseTraceparent(
$request->getHeaderLine('traceparent'),
);
if ($incoming === null) {
$trace = new Trace('user-service.request', params: [
'method' => $request->getMethod(),
'route' => '/users/{id}',
]);
$traceFlags = '01';
} else {
$trace = new Trace(
name: 'user-service.request',
traceId: $incoming['trace_id'],
parentSpanId: $incoming['parent_span_id'],
params: [
'method' => $request->getMethod(),
'route' => '/users/{id}',
],
);
$traceFlags = $incoming['flags'];
}
$controller = $trace->next('UserController::profile');
$orderRequest = $controller->parallel('HTTP GET order-service', [
'method' => 'GET',
'host' => 'order-service',
'route' => '/orders',
]);
$headers = [
'traceparent' => buildTraceparent(
$trace->traceId(),
$orderRequest->spanId(),
$traceFlags,
),
];
try {
$response = $httpClient->get(
'http://order-service/orders?user_id=10001',
headers: $headers,
);
if ($response->getStatusCode() >= 500) {
$orderRequest->fail(
new RuntimeException('order-service returned 5xx'),
);
} else {
$orderRequest->endCall();
}
} catch (Throwable $error) {
$orderRequest->fail($error);
throw $error;
}
$incoming = parseTraceparent(
$request->getHeaderLine('traceparent'),
);
$trace = $incoming === null
? new Trace('order-service.request')
: new Trace(
name: 'order-service.request',
traceId: $incoming['trace_id'],
parentSpanId: $incoming['parent_span_id'],
);
$controller = $trace->next('OrderController::list');
$database = $controller->next('query-orders', [
'user_id' => 10001,
]);
try {
$orders = queryOrders(10001);
$database->endCall();
$controller->endCall();
$trace->endCall();
} catch (Throwable $error) {
$database->fail($error);
$controller->fail($error);
$trace->fail($error);
throw $error;
}
use EasySwoole\Trace\Bean\SpanBean;
$span = $point->toSpanBean();
/** @var SpanBean[] $spans */
$spans = $trace->spans();
$current = $point->spans(onlySelf: true);
$row = $span->toArray();
if (!$trace->isPersisted()) {
$repository->insertMany($trace->spans());
$trace->markPersisted();
}
use EasySwoole\Trace\TracePoint;
$trace->setAutoPersist(
static function (TracePoint $point) use ($repository): void {
$repository->insertMany(
$point->spans(onlySelf: true),
);
},
);
// 在外层入库前先建立一个仍处于运行状态的协程范围。
$asyncScope = $trace->parallel('async-scope');
// 外层先批量写入当前已经存在的节点。
$repository->insertMany($trace->spans());
$trace->markPersisted();
// 内部协程之后创建的新节点默认是未持久化状态,
// 并且已经继承 auto-persist callback。
$latePoint = $asyncScope->next('late-coroutine');
$point->persistIfNeeded();
$didPersist = $point->persistIfNeeded();
use EasySwoole\Trace\Bean\SpanBean;
use EasySwoole\Trace\Utility;
$rows = $repository->findByTraceId(
'4b0b2f5d54bb61e080ecce28ded4bc6a',
);
$beans = array_map(
static fn (array $row): SpanBean => SpanBean::fromArray($row),
$rows,
);
$trace = Utility::restoreFromBeans($beans);
echo Utility::toTree($trace), PHP_EOL;
$tree = $trace->toArray();
echo json_encode(
$trace,
JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR,
);
$point->next($name, $params); // 创建唯一串行后继节点
$point->parallel($name, $params); // 创建并行节点
$point->endCall(); // 成功结束
$point->fail($throwable); // 异常结束
$point->timeout($message); // 超时结束
$point->setParams($params); // 替换节点参数
$point->params(); // 获取参数
$point->status(); // 获取 TraceStatus
$point->children(); // 获取直接子节点
$point->toSpanBean(); // 转换当前节点
$point->spans(); // 当前节点及所有后代 Bean
$point->spans(onlySelf: true); // 仅当前节点 Bean
$point->toArray(); // 树形数组
$point->setAutoPersist($callback); // 设置自动补写回调
$point->persistIfNeeded(); // 主动执行补写
$point->isPersisted(); // 是否已持久化
$point->markPersisted(); // 标记已持久化
Utility::restoreFromBeans($beans); // 从 Bean 恢复调用树
Utility::toTree($trace); // 输出文本调用树
text
traceparent: 00-4b0b2f5d54bb61e080ecce28ded4bc6a-00f067aa0ba902b7-01