diff --git a/src/Aspect/CoroutineAspect.php b/src/Aspect/CoroutineAspect.php new file mode 100644 index 0000000..31a27d6 --- /dev/null +++ b/src/Aspect/CoroutineAspect.php @@ -0,0 +1,65 @@ +arguments['keys']['callable']; + $root = TracerContext::getRoot(); + + $proceedingJoinPoint->arguments['keys']['callable'] = function () use ($callable, $root) { + try { + if ($root instanceof Span) { + /** @var Tracer $tracer */ + $tracer = make(Tracer::class); + TracerContext::setTracer($tracer); + $child = $tracer->startSpan('coroutine', [ + 'child_of' => $root->getContext(), + ]); + $child->setTag('coroutine.id', Co::id()); + TracerContext::setRoot($child); + Co::defer(function () use ($child, $tracer) { + $child->finish(); + $tracer->flush(); + }); + } + + $callable(); + } catch (Throwable $e) { + if (isset($child)) { + $child->setTag('error', true); + $child->log(['message', $e->getMessage(), 'code' => $e->getCode(), 'stacktrace' => $e->getTraceAsString()]); + } + + throw $e; + } + }; + + return $proceedingJoinPoint->process(); + } +} diff --git a/src/Middleware/TraceMiddleware.php b/src/Middleware/TraceMiddleware.php index fe1a319..7b2c8f8 100644 --- a/src/Middleware/TraceMiddleware.php +++ b/src/Middleware/TraceMiddleware.php @@ -52,6 +52,11 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface }); try { $response = $handler->handle($request); + /** @var \ZipkinOpenTracing\SpanContext $spanContent */ + $spanContent = $span->getContext(); + /** @var \Zipkin\Propagation\TraceContext $traceContext */ + $traceContext = $spanContent->getContext(); + $response = $response->withHeader('Trace-Id', $traceContext->getTraceId()); $span->setTag($this->spanTagManager->get('response', 'status_code'), $response->getStatusCode()); } catch (Throwable $exception) { $this->switchManager->isEnable('exception') && $this->appendExceptionToSpan($span, $exception); diff --git a/src/SpanStarter.php b/src/SpanStarter.php index 8138ec7..599c9b4 100644 --- a/src/SpanStarter.php +++ b/src/SpanStarter.php @@ -32,16 +32,17 @@ protected function startSpan( array $option = [], string $kind = SPAN_KIND_RPC_SERVER ): Span { - $root = Context::get('tracer.root'); + $root = TracerContext::getRoot(); + $tracer = TracerContext::getTracer() ?: $this->tracer; if (! $root instanceof Span) { $container = ApplicationContext::getContainer(); $request = RequestContext::getOrNull(); if (! $request instanceof ServerRequestInterface) { - // If the request object is absent, we are probably in a commandline context. + // If the request object is absent, we are probably in a commandLine context. // Throwing an exception is unnecessary. - $root = $this->tracer->startSpan($name, $option); + $root = $tracer->startSpan($name, $option); $root->setTag(SPAN_KIND, $kind); - Context::set('tracer.root', $root); + TracerContext::setRoot($root); return $root; } $carrier = array_map(function ($header) { @@ -54,17 +55,17 @@ protected function startSpan( } } // Extracts the context from the HTTP headers. - $spanContext = $this->tracer->extract(TEXT_MAP, $carrier); + $spanContext = $tracer->extract(TEXT_MAP, $carrier); if ($spanContext) { $option['child_of'] = $spanContext; } - $root = $this->tracer->startSpan($name, $option); + $root = $tracer->startSpan($name, $option); $root->setTag(SPAN_KIND, $kind); - Context::set('tracer.root', $root); + TracerContext::setRoot($root); return $root; } $option['child_of'] = $root->getContext(); - $child = $this->tracer->startSpan($name, $option); + $child = $tracer->startSpan($name, $option); $child->setTag(SPAN_KIND, $kind); return $child; } diff --git a/src/TracerContext.php b/src/TracerContext.php new file mode 100644 index 0000000..0263d7f --- /dev/null +++ b/src/TracerContext.php @@ -0,0 +1,43 @@ +