From 969be806032789039a5d0c55125eaebe3cd7316e Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Thu, 4 Sep 2025 14:04:54 +0800 Subject: [PATCH 1/3] feat(tracing): comprehensive improvements to tracing aspects and listeners - Enhanced multiple tracing aspects with better data collection - Improved span creation and management across various components - Updated listeners for better tracing coverage - Optimized tracing data structure and performance --- .../src/Tracing/Aspect/AmqpProducerAspect.php | 7 +-- .../Aspect/AsyncQueueJobMessageAspect.php | 7 +-- src/sentry/src/Tracing/Aspect/CacheAspect.php | 5 ++- .../src/Tracing/Aspect/CoordinatorAspect.php | 27 ++++++------ .../src/Tracing/Aspect/CoroutineAspect.php | 39 +++++++++-------- src/sentry/src/Tracing/Aspect/DbAspect.php | 37 +++++++++------- .../Tracing/Aspect/ElasticsearchAspect.php | 33 ++++++++------ src/sentry/src/Tracing/Aspect/GrpcAspect.php | 27 +++++++----- .../Tracing/Aspect/GuzzleHttpClientAspect.php | 18 +++++--- .../Tracing/Aspect/KafkaProducerAspect.php | 10 +++-- src/sentry/src/Tracing/Aspect/RedisAspect.php | 26 ++++++----- src/sentry/src/Tracing/Aspect/RpcAspect.php | 15 +++++-- .../Tracing/Aspect/TraceAnnotationAspect.php | 23 +++++----- .../Tracing/Listener/TracingAmqpListener.php | 3 +- .../Listener/TracingAsyncQueueListener.php | 3 +- .../Listener/TracingCommandListener.php | 5 +-- .../Listener/TracingCrontabListener.php | 5 +-- .../Listener/TracingDbQueryListener.php | 8 ++-- .../Tracing/Listener/TracingKafkaListener.php | 5 +-- .../Tracing/Listener/TracingRedisListener.php | 9 ++-- .../Listener/TracingRequestListener.php | 15 ++++--- src/sentry/src/Tracing/SpanStarter.php | 43 +++++++++++-------- 22 files changed, 215 insertions(+), 155 deletions(-) diff --git a/src/sentry/src/Tracing/Aspect/AmqpProducerAspect.php b/src/sentry/src/Tracing/Aspect/AmqpProducerAspect.php index ff8d12c1b..ef2d83ff0 100644 --- a/src/sentry/src/Tracing/Aspect/AmqpProducerAspect.php +++ b/src/sentry/src/Tracing/Aspect/AmqpProducerAspect.php @@ -61,8 +61,9 @@ protected function handleProduceMessage(ProceedingJoinPoint $proceedingJoinPoint } $span = $this->startSpan( - 'queue.publish', - sprintf('%s::%s()', $proceedingJoinPoint->className, $proceedingJoinPoint->methodName) + op: 'queue.publish', + description: sprintf('%s::%s()', $proceedingJoinPoint->className, $proceedingJoinPoint->methodName), + origin: 'auto.amqp' ); if (! $span) { @@ -110,6 +111,6 @@ protected function handleProduceMessage(ProceedingJoinPoint $proceedingJoinPoint $this->properties['application_headers']->set(Constants::TRACE_CARRIER, $carrier->toJson()); })->call($producerMessage); - return tap($proceedingJoinPoint->process(), fn () => $span->setOrigin('auto.amqp')->finish()); + return tap($proceedingJoinPoint->process(), fn () => $span->finish()); } } diff --git a/src/sentry/src/Tracing/Aspect/AsyncQueueJobMessageAspect.php b/src/sentry/src/Tracing/Aspect/AsyncQueueJobMessageAspect.php index 1fc0fe588..607510527 100644 --- a/src/sentry/src/Tracing/Aspect/AsyncQueueJobMessageAspect.php +++ b/src/sentry/src/Tracing/Aspect/AsyncQueueJobMessageAspect.php @@ -71,8 +71,9 @@ public function handlePush(ProceedingJoinPoint $proceedingJoinPoint) { $job = $proceedingJoinPoint->arguments['keys']['job'] ?? null; $span = $this->startSpan( - 'queue.publish', - $job::class + op: 'queue.publish', + description: $job::class, + origin: 'auto.queue' ); if (! $span) { @@ -109,7 +110,7 @@ public function handlePush(ProceedingJoinPoint $proceedingJoinPoint) return $proceedingJoinPoint->process(); } finally { - $span->setOrigin('auto.queue')->finish(); + $span->finish(); } } diff --git a/src/sentry/src/Tracing/Aspect/CacheAspect.php b/src/sentry/src/Tracing/Aspect/CacheAspect.php index 8d399045e..76f553301 100644 --- a/src/sentry/src/Tracing/Aspect/CacheAspect.php +++ b/src/sentry/src/Tracing/Aspect/CacheAspect.php @@ -72,8 +72,9 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) $span = $this->startSpan( op: $op, description: implode(', ', $keys), + origin: 'auto.cache', asParent: true - )->setData([ + )?->setData([ 'cache.key' => $keys, 'cache.ttl' => $arguments['ttl'] ?? null, 'item_size' => match (true) { @@ -95,7 +96,7 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) ], default => [], }; - $span->setOrigin('auto.cache')->setData($data)->finish(); + $span?->setData($data)->finish(); }); } finally { SentrySdk::getCurrentHub()->setSpan($parent); diff --git a/src/sentry/src/Tracing/Aspect/CoordinatorAspect.php b/src/sentry/src/Tracing/Aspect/CoordinatorAspect.php index c4e0d06e0..13b8b111f 100644 --- a/src/sentry/src/Tracing/Aspect/CoordinatorAspect.php +++ b/src/sentry/src/Tracing/Aspect/CoordinatorAspect.php @@ -42,26 +42,29 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) ]; $span = $this->startSpan( - sprintf('%s.%s', strtolower(class_basename($proceedingJoinPoint->className)), $proceedingJoinPoint->methodName), - sprintf('%s::%s(%s)', $proceedingJoinPoint->className, $proceedingJoinPoint->methodName, $timeout), - ); + op: sprintf('%s.%s', strtolower(class_basename($proceedingJoinPoint->className)), $proceedingJoinPoint->methodName), + description: sprintf('%s::%s(%s)', $proceedingJoinPoint->className, $proceedingJoinPoint->methodName, $timeout), + origin: 'auto.coordinator', + )?->setData($data); try { return $proceedingJoinPoint->process(); } catch (Throwable $exception) { - $span?->setStatus(SpanStatus::internalError()); - $span?->setTags([ - 'error' => true, - 'exception.class' => $exception::class, - 'exception.message' => $exception->getMessage(), - 'exception.code' => $exception->getCode(), - ]); + $span?->setStatus(SpanStatus::internalError()) + ->setTags([ + 'error' => true, + 'exception.class' => $exception::class, + 'exception.message' => $exception->getMessage(), + 'exception.code' => $exception->getCode(), + ]); if ($this->switcher->isTracingExtraTagEnable('exception.stack_trace')) { - $data['exception.stack_trace'] = (string) $exception; + $span?->setData([ + 'exception.stack_trace' => (string) $exception, + ]); } throw $exception; } finally { - $span?->setOrigin('auto.coordinator')->setData($data)->finish(microtime(true)); + $span?->finish(microtime(true)); } } } diff --git a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php index 36ef72986..4eba1167f 100644 --- a/src/sentry/src/Tracing/Aspect/CoroutineAspect.php +++ b/src/sentry/src/Tracing/Aspect/CoroutineAspect.php @@ -50,7 +50,11 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) } $callable = $proceedingJoinPoint->arguments['keys']['callable']; - $parent = $this->startSpan('coroutine.create', $callingOnFunction); + $parent = $this->startSpan( + op: 'coroutine.create', + description: $callingOnFunction, + origin: 'auto.coroutine', + )?->setOrigin('auto.coroutine'); if (! $parent) { return $proceedingJoinPoint->process(); @@ -62,42 +66,43 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) $proceedingJoinPoint->arguments['keys']['callable'] = function () use ($callable, $parent, $callingOnFunction) { $transaction = $this->startCoroutineTransaction( - $parent, + parent: $parent, name: 'coroutine', op: 'coroutine.execute', description: $callingOnFunction, - ); + origin: 'auto.coroutine', + )->setData([ + 'coroutine.id' => Co::id(), + ]); defer(function () use ($transaction) { SentrySdk::getCurrentHub()->setSpan($transaction); $transaction->finish(); }); - $data = [ - 'coroutine.id' => Co::id(), - ]; - try { $callable(); } catch (Throwable $exception) { - $transaction->setStatus(SpanStatus::internalError()); - $transaction->setTags([ - 'error' => true, - 'exception.class' => $exception::class, - 'exception.message' => $exception->getMessage(), - 'exception.code' => $exception->getCode(), - ]); + $transaction->setStatus(SpanStatus::internalError()) + ->setTags([ + 'error' => true, + 'exception.class' => $exception::class, + 'exception.message' => $exception->getMessage(), + 'exception.code' => $exception->getCode(), + ]); if ($this->switcher->isTracingExtraTagEnable('exception.stack_trace')) { - $data['exception.stack_trace'] = (string) $exception; + $transaction->setData([ + 'exception.stack_trace' => (string) $exception, + ]); } throw $exception; } finally { - $transaction->setOrigin('auto.coroutine')->setData($data); + // ... } }; - $parent->setOrigin('auto.coroutine')->finish(); + $parent->finish(); return $proceedingJoinPoint->process(); } diff --git a/src/sentry/src/Tracing/Aspect/DbAspect.php b/src/sentry/src/Tracing/Aspect/DbAspect.php index 174959601..dbb7dd08a 100644 --- a/src/sentry/src/Tracing/Aspect/DbAspect.php +++ b/src/sentry/src/Tracing/Aspect/DbAspect.php @@ -76,12 +76,11 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) // $operation ? $operation . ' ' : '', // implode('.', array_filter([$database, $table])) // ); - $op = 'db.sql.query'; - $description = $sql; - - // Already check in the previous context - /** @var \Sentry\Tracing\Span $span */ - $span = $this->startSpan($op, $description); + $span = $this->startSpan( + op: 'db.sql.query', + description: $sql, + origin: 'auto.db', + ); $data = [ 'coroutine.id' => Coroutine::id(), @@ -103,26 +102,32 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) $data['db.parameter.' . $key] = $value; } + $span?->setData($data); + try { $result = $proceedingJoinPoint->process(); if ($this->switcher->isTracingExtraTagEnable('db.result')) { - $data['db.result'] = json_encode($result, JSON_UNESCAPED_UNICODE); + $span?->setData([ + 'db.result' => json_encode($result, JSON_UNESCAPED_UNICODE), + ]); } } catch (Throwable $exception) { - $span->setStatus(SpanStatus::internalError()); - $span->setTags([ - 'error' => true, - 'exception.class' => $exception::class, - 'exception.message' => $exception->getMessage(), - 'exception.code' => $exception->getCode(), - ]); + $span?->setStatus(SpanStatus::internalError()) + ->setTags([ + 'error' => true, + 'exception.class' => $exception::class, + 'exception.message' => $exception->getMessage(), + 'exception.code' => $exception->getCode(), + ]); if ($this->switcher->isTracingExtraTagEnable('exception.stack_trace')) { - $data['exception.stack_trace'] = (string) $exception; + $span?->setData([ + 'exception.stack_trace' => (string) $exception, + ]); } throw $exception; } finally { - $span->setOrigin('auto.db')->setData($data)->finish(); + $span?->finish(); } return $result; diff --git a/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php b/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php index 7e844e6b3..a157d9f65 100644 --- a/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php +++ b/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php @@ -62,10 +62,11 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) return $proceedingJoinPoint->process(); } - // TODO 规则: opeate dbName.tableName + // TODO 规则: operate dbName.tableName $span = $this->startSpan( - 'db.elasticserach', - sprintf('%s::%s()', $proceedingJoinPoint->className, $proceedingJoinPoint->methodName), + op: 'db.elasticsearch', + description: sprintf('%s::%s()', $proceedingJoinPoint->className, $proceedingJoinPoint->methodName), + origin: 'auto.elasticsearch', ); if (! $span) { @@ -83,26 +84,32 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) 'arguments' => json_encode($proceedingJoinPoint->arguments['keys'], JSON_UNESCAPED_UNICODE), ]; + $span->setData($data); + try { $result = $proceedingJoinPoint->process(); if ($this->switcher->isTracingExtraTagEnable('elasticsearch.result')) { - $data['elasticsearch.result'] = json_encode($result, JSON_UNESCAPED_UNICODE); + $span->setData([ + 'elasticsearch.result' => json_encode($result, JSON_UNESCAPED_UNICODE), + ]); } } catch (Throwable $exception) { - $span->setStatus(SpanStatus::internalError()); - $span->setTags([ - 'error' => true, - 'exception.class' => $exception::class, - 'exception.message' => $exception->getMessage(), - 'exception.code' => $exception->getCode(), - ]); + $span->setStatus(SpanStatus::internalError()) + ->setTags([ + 'error' => true, + 'exception.class' => $exception::class, + 'exception.message' => $exception->getMessage(), + 'exception.code' => $exception->getCode(), + ]); if ($this->switcher->isTracingExtraTagEnable('exception.stack_trace')) { - $data['exception.stack_trace'] = (string) $exception; + $span->setData([ + 'exception.stack_trace' => (string) $exception, + ]); } throw $exception; } finally { - $span->setOrigin('auto.elasticsearch')->setData($data)->finish(); + $span->finish(); } return $result; diff --git a/src/sentry/src/Tracing/Aspect/GrpcAspect.php b/src/sentry/src/Tracing/Aspect/GrpcAspect.php index 9dce0f50a..b2eeecac9 100644 --- a/src/sentry/src/Tracing/Aspect/GrpcAspect.php +++ b/src/sentry/src/Tracing/Aspect/GrpcAspect.php @@ -56,7 +56,11 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) ]; $proceedingJoinPoint->arguments['keys']['options'] = $options; - $span = $this->startSpan('grpc.client', $method); + $span = $this->startSpan( + op: 'grpc.client', + description: $method, + origin: 'auto.grpc', + )?->setData($data); try { $result = $proceedingJoinPoint->process(); @@ -64,16 +68,18 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) if (! $span) { return $result; } + [$message, $code, $response] = $result; + if ($response instanceof Http2Response) { - $data += [ + $span->setData([ 'response.status' => $code, 'response.reason' => $message, 'response.headers' => $response->headers, - ]; - if ($this->switcher->isTracingExtraTagEnable('response.body')) { - $data['response.body'] = $response->data; - } + ]); + $this->switcher->isTracingExtraTagEnable('response.body') && $span->setData([ + 'response.body' => $response->data, + ]); } } catch (Throwable $exception) { $span?->setStatus(SpanStatus::internalError()) @@ -83,14 +89,15 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) 'exception.message' => $exception->getMessage(), 'exception.code' => $exception->getCode(), ]); - if ($this->switcher->isTracingExtraTagEnable('exception.stack_trace')) { - $data['exception.stack_trace'] = (string) $exception; - } + $this->switcher->isTracingExtraTagEnable('exception.stack_trace') && $span?->setData([ + 'exception.stack_trace' => (string) $exception, + ]); throw $exception; } finally { - $span?->setOrigin('auto.grpc')->setData($data)->finish(); + $span?->finish(); } + return $result; } } diff --git a/src/sentry/src/Tracing/Aspect/GuzzleHttpClientAspect.php b/src/sentry/src/Tracing/Aspect/GuzzleHttpClientAspect.php index 761f93e15..bfe9ffdf0 100644 --- a/src/sentry/src/Tracing/Aspect/GuzzleHttpClientAspect.php +++ b/src/sentry/src/Tracing/Aspect/GuzzleHttpClientAspect.php @@ -71,7 +71,11 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) } // Inject trace context && Start span - $span = $this->startSpan('http.client', $request->getMethod() . ' ' . (string) $request->getUri()); + $span = $this->startSpan( + op: 'http.client', + description: $request->getMethod() . ' ' . (string) $request->getUri(), + origin: 'auto.http.client', + ); $options['headers'] = array_replace($options['headers'] ?? [], [ 'sentry-trace' => $span->toTraceparent(), 'baggage' => $span->toBaggage(), @@ -122,11 +126,11 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) } if ($response->getStatusCode() >= 400 && $response->getStatusCode() < 600) { - $span->setStatus(SpanStatus::internalError()); - $span->setTags([ - 'error' => true, - 'response.reason' => $response->getReasonPhrase(), - ]); + $span->setStatus(SpanStatus::internalError()) + ->setTags([ + 'error' => true, + 'response.reason' => $response->getReasonPhrase(), + ]); } } @@ -144,7 +148,7 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) } } - $span->setOrigin('auto.http.client')->setData($data)->finish(); + $span->setData($data)->finish(); if (is_callable($onStats)) { ($onStats)($stats); diff --git a/src/sentry/src/Tracing/Aspect/KafkaProducerAspect.php b/src/sentry/src/Tracing/Aspect/KafkaProducerAspect.php index d57de7fb1..5327ad6fa 100644 --- a/src/sentry/src/Tracing/Aspect/KafkaProducerAspect.php +++ b/src/sentry/src/Tracing/Aspect/KafkaProducerAspect.php @@ -58,7 +58,8 @@ protected function sendAsync(ProceedingJoinPoint $proceedingJoinPoint) { $span = $this->startSpan( 'queue.publish', - sprintf('%s::%s()', $proceedingJoinPoint->className, $proceedingJoinPoint->methodName) + sprintf('%s::%s()', $proceedingJoinPoint->className, $proceedingJoinPoint->methodName), + origin: 'auto.kafka' ); if (! $span) { @@ -90,7 +91,7 @@ protected function sendAsync(ProceedingJoinPoint $proceedingJoinPoint) ->setValue($carrier->toJson()); $proceedingJoinPoint->arguments['keys']['headers'] = $headers; - return tap($proceedingJoinPoint->process(), fn () => $span->setOrigin('auto.kafka')->finish()); + return tap($proceedingJoinPoint->process(), fn () => $span->finish()); } protected function sendBatchAsync(ProceedingJoinPoint $proceedingJoinPoint) @@ -99,7 +100,8 @@ protected function sendBatchAsync(ProceedingJoinPoint $proceedingJoinPoint) $messages = $proceedingJoinPoint->arguments['keys']['messages'] ?? []; $span = $this->startSpan( 'kafka.send_batch', - sprintf('%s::%s', $proceedingJoinPoint->className, $proceedingJoinPoint->methodName) + sprintf('%s::%s', $proceedingJoinPoint->className, $proceedingJoinPoint->methodName), + origin: 'auto.kafka' ); if (! $span) { @@ -119,6 +121,6 @@ protected function sendBatchAsync(ProceedingJoinPoint $proceedingJoinPoint) })->call($message); } - return tap($proceedingJoinPoint->process(), fn () => $span->setOrigin('auto.kafka')->finish()); + return tap($proceedingJoinPoint->process(), fn () => $span->finish()); } } diff --git a/src/sentry/src/Tracing/Aspect/RedisAspect.php b/src/sentry/src/Tracing/Aspect/RedisAspect.php index 52837ea47..6e5fef170 100644 --- a/src/sentry/src/Tracing/Aspect/RedisAspect.php +++ b/src/sentry/src/Tracing/Aspect/RedisAspect.php @@ -84,7 +84,11 @@ class_exists(CommandExecuted::class) strtoupper($arguments['name'] ?? ''), is_array($key) ? implode(',', $key) : $key ); - $span = $this->startSpan($op, $description); + $span = $this->startSpan( + op: $op, + description: $description, + origin: 'auto.cache.redis', + )?->setData($data); try { $result = $proceedingJoinPoint->process(); @@ -94,23 +98,23 @@ class_exists(CommandExecuted::class) } if ($this->switcher->isTracingExtraTagEnable('redis.result')) { - $data['redis.result'] = $result; + $span->setData(['redis.result' => $result]); } } catch (Throwable $exception) { - $span->setStatus(SpanStatus::internalError()); - $span->setTags([ - 'error' => true, - 'exception.class' => $exception::class, - 'exception.message' => $exception->getMessage(), - 'exception.code' => $exception->getCode(), - ]); if ($this->switcher->isTracingExtraTagEnable('exception.stack_trace')) { - $data['exception.stack_trace'] = (string) $exception; + $span->setData(['exception.stack_trace' => (string) $exception]); } + $span->setStatus(SpanStatus::internalError()) + ->setTags([ + 'error' => true, + 'exception.class' => $exception::class, + 'exception.message' => $exception->getMessage(), + 'exception.code' => $exception->getCode(), + ]); throw $exception; } finally { - $span->setOrigin('auto.cache.redis')->setData($data)->finish(); + $span->finish(); } return $result; diff --git a/src/sentry/src/Tracing/Aspect/RpcAspect.php b/src/sentry/src/Tracing/Aspect/RpcAspect.php index 6e0cc17ba..de4a37c5d 100644 --- a/src/sentry/src/Tracing/Aspect/RpcAspect.php +++ b/src/sentry/src/Tracing/Aspect/RpcAspect.php @@ -81,7 +81,11 @@ private function handleGenerateRpcPath(ProceedingJoinPoint $proceedingJoinPoint) // $package.$service/$path $op = sprintf('%s.%s/%s', $package, $service, $path); - $span = $this->startSpan($op, $path); + $span = $this->startSpan( + op: $op, + description: $path, + origin: 'auto.rpc', + ); if (! $span) { return $path; @@ -94,11 +98,14 @@ private function handleGenerateRpcPath(ProceedingJoinPoint $proceedingJoinPoint) 'rpc.service' => $service, ]; + $span->setData($data); + Context::set(static::DATA, $data); // @deprecated since v3.1, will be removed in v3.2 - Context::set(static::SPAN, $span->setData($data)); + Context::set(static::SPAN, $span); if ($this->container->has(Rpc\Context::class)) { - $this->container->get(Rpc\Context::class)->set(Constants::TRACE_CARRIER, Carrier::fromSpan($span)->toJson()); + $this->container->get(Rpc\Context::class) + ->set(Constants::TRACE_CARRIER, Carrier::fromSpan($span)->toJson()); } return $path; @@ -140,7 +147,7 @@ private function handleSend(ProceedingJoinPoint $proceedingJoinPoint) throw $exception; } finally { - $span?->setOrigin('auto.rpc')->setData($data)->finish(); + $span?->setData($data)->finish(); Context::destroy(static::SPAN); Context::destroy(static::DATA); diff --git a/src/sentry/src/Tracing/Aspect/TraceAnnotationAspect.php b/src/sentry/src/Tracing/Aspect/TraceAnnotationAspect.php index dd72bac33..45a57430b 100644 --- a/src/sentry/src/Tracing/Aspect/TraceAnnotationAspect.php +++ b/src/sentry/src/Tracing/Aspect/TraceAnnotationAspect.php @@ -56,13 +56,13 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) } $span = $this->startSpan( - $annotation->op ?? 'method', - $annotation->description ?? sprintf( + op: $annotation->op ?? 'method', + description: $annotation->description ?? sprintf( '%s::%s()', $proceedingJoinPoint->className, $methodName ), - true + asParent: true ); try { @@ -76,20 +76,19 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) $data['annotation.result'] = $result; } } catch (Throwable $exception) { - $span->setStatus(SpanStatus::internalError()); - $span->setTags([ - 'error' => true, - 'exception.class' => $exception::class, - 'exception.message' => $exception->getMessage(), - 'exception.code' => $exception->getCode(), - ]); + $span->setStatus(SpanStatus::internalError()) + ->setTags([ + 'error' => true, + 'exception.class' => $exception::class, + 'exception.message' => $exception->getMessage(), + 'exception.code' => $exception->getCode(), + ]); if ($this->switcher->isTracingExtraTagEnable('exception.stack_trace')) { $data['exception.stack_trace'] = (string) $exception; } throw $exception; } finally { - $span->setData($data); - $span->finish(microtime(true)); + $span->setData($data)->finish(microtime(true)); // Reset root span SentrySdk::getCurrentHub()->setSpan($parent); diff --git a/src/sentry/src/Tracing/Listener/TracingAmqpListener.php b/src/sentry/src/Tracing/Listener/TracingAmqpListener.php index 4e6947f1f..edc102107 100644 --- a/src/sentry/src/Tracing/Listener/TracingAmqpListener.php +++ b/src/sentry/src/Tracing/Listener/TracingAmqpListener.php @@ -83,6 +83,7 @@ protected function startTransaction(BeforeConsume $event): void name: $message::class, op: 'queue.process', description: $message::class, + origin: 'auto.amqp', source: TransactionSource::custom() )->setStartTimestamp(microtime(true)); } @@ -132,7 +133,7 @@ protected function finishTransaction(AfterConsume|FailToConsume $event): void } } - $transaction->setOrigin('auto.amqp')->setData($data)->setTags($tags); + $transaction->setData($data)->setTags($tags); SentrySdk::getCurrentHub()->setSpan($transaction); diff --git a/src/sentry/src/Tracing/Listener/TracingAsyncQueueListener.php b/src/sentry/src/Tracing/Listener/TracingAsyncQueueListener.php index b6dd6e1f4..127a32d96 100644 --- a/src/sentry/src/Tracing/Listener/TracingAsyncQueueListener.php +++ b/src/sentry/src/Tracing/Listener/TracingAsyncQueueListener.php @@ -74,6 +74,7 @@ protected function startTransaction(BeforeHandle $event): void name: $job::class, op: 'queue.process', description: 'async_queue: ' . $job::class, + origin: 'auto.async_queue', source: TransactionSource::custom() )->setStartTimestamp(microtime(true)); } @@ -113,7 +114,7 @@ protected function finishTransaction(AfterHandle|RetryHandle|FailedHandle $event } } - $transaction->setOrigin('auto.queue')->setData($data)->setTags($tags); + $transaction->setData($data)->setTags($tags); SentrySdk::getCurrentHub()->setSpan($transaction); diff --git a/src/sentry/src/Tracing/Listener/TracingCommandListener.php b/src/sentry/src/Tracing/Listener/TracingCommandListener.php index 9ecb47bf2..3d6b5f516 100644 --- a/src/sentry/src/Tracing/Listener/TracingCommandListener.php +++ b/src/sentry/src/Tracing/Listener/TracingCommandListener.php @@ -78,6 +78,7 @@ protected function startTransaction(BeforeHandle $event): void name: $command->getName() ?: '', op: 'console.command', description: $command->getDescription(), + origin: 'auto.command', source: TransactionSource::custom() ); } @@ -114,9 +115,7 @@ protected function finishTransaction(AfterExecute $event): void } } - $transaction - ->setOrigin('auto.command') - ->setStatus($exitCode == SymfonyCommand::SUCCESS ? SpanStatus::ok() : SpanStatus::internalError()) + $transaction->setStatus($exitCode == SymfonyCommand::SUCCESS ? SpanStatus::ok() : SpanStatus::internalError()) ->setData($data) ->setTags($tags); diff --git a/src/sentry/src/Tracing/Listener/TracingCrontabListener.php b/src/sentry/src/Tracing/Listener/TracingCrontabListener.php index 2361e3adc..7d305ea2d 100644 --- a/src/sentry/src/Tracing/Listener/TracingCrontabListener.php +++ b/src/sentry/src/Tracing/Listener/TracingCrontabListener.php @@ -62,6 +62,7 @@ protected function startTransaction(BeforeExecute $event): void name: $crontab->getName() ?: '', op: 'crontab.run', description: $crontab->getMemo(), + origin: 'auto.crontab', source: TransactionSource::task() ); } @@ -97,9 +98,7 @@ protected function finishTransaction(AfterExecute|FailToExecute $event): void } } - $transaction->setOrigin('auto.crontab') - ->setData($data) - ->setTags($tags); + $transaction->setData($data)->setTags($tags); SentrySdk::getCurrentHub()->setSpan($transaction); diff --git a/src/sentry/src/Tracing/Listener/TracingDbQueryListener.php b/src/sentry/src/Tracing/Listener/TracingDbQueryListener.php index 75d19d9a0..453e84efb 100644 --- a/src/sentry/src/Tracing/Listener/TracingDbQueryListener.php +++ b/src/sentry/src/Tracing/Listener/TracingDbQueryListener.php @@ -105,9 +105,11 @@ protected function queryExecutedHandler(object $event): void $description = $event->sql; // Already check in the previous context - $this->startSpan($op, $description) - ->setOrigin('auto.db') - ->setData($data) + $this->startSpan( + op: $op, + description: $description, + origin: 'auto.db' + )?->setData($data) ->setStartTimestamp($startTimestamp) ->finish($startTimestamp + $event->time / 1000); } diff --git a/src/sentry/src/Tracing/Listener/TracingKafkaListener.php b/src/sentry/src/Tracing/Listener/TracingKafkaListener.php index 03c895418..1733de7f9 100644 --- a/src/sentry/src/Tracing/Listener/TracingKafkaListener.php +++ b/src/sentry/src/Tracing/Listener/TracingKafkaListener.php @@ -81,6 +81,7 @@ protected function startTransaction(BeforeConsume $event): void name: $consumer->getTopic() . ' process', op: 'queue.process', description: $consumer::class, + origin: 'auto.kafka', source: TransactionSource::custom() )->setStartTimestamp(microtime(true)); } @@ -124,9 +125,7 @@ protected function finishTransaction(AfterConsume|FailToConsume $event): void } } - $transaction->setOrigin('auto.kafka') - ->setData($data) - ->setTags($tags); + $transaction->setData($data)->setTags($tags); SentrySdk::getCurrentHub()->setSpan($transaction); diff --git a/src/sentry/src/Tracing/Listener/TracingRedisListener.php b/src/sentry/src/Tracing/Listener/TracingRedisListener.php index 0d7c1d528..bbd09190a 100644 --- a/src/sentry/src/Tracing/Listener/TracingRedisListener.php +++ b/src/sentry/src/Tracing/Listener/TracingRedisListener.php @@ -70,7 +70,11 @@ public function process(object $event): void // rule: operation db.table $op = 'db.redis'; - $span = $this->startSpan($op, $redisStatement); + $span = $this->startSpan( + op: $op, + description: $redisStatement, + origin: 'auto.cache.redis', + ); if (! $span) { return; @@ -93,8 +97,7 @@ public function process(object $event): void } } - $span->setOrigin('auto.cache.redis') - ->setData($data) + $span->setData($data) ->finish(); } } diff --git a/src/sentry/src/Tracing/Listener/TracingRequestListener.php b/src/sentry/src/Tracing/Listener/TracingRequestListener.php index 3ff3c77c9..ff5f99d7d 100644 --- a/src/sentry/src/Tracing/Listener/TracingRequestListener.php +++ b/src/sentry/src/Tracing/Listener/TracingRequestListener.php @@ -100,10 +100,11 @@ private function startTransaction(RequestReceived|RpcRequestReceived $event): vo // Get sentry-trace and baggage $transaction = $this->startRequestTransaction( - $request, + request: $request, name: $name, op: sprintf('%s.server', $serverName), description: sprintf('%s %s', $method, $path), + origin: 'auto.request', source: $source, ); @@ -126,13 +127,17 @@ private function startTransaction(RequestReceived|RpcRequestReceived $event): vo $data['rpc.context'] = $this->container->get(RpcContext::class)->getData(); } - $transaction->setOrigin('auto.request')->setData($data); + $transaction->setData($data); - $span = $this->startSpan('request.received', 'request.received', true); + $span = $this->startSpan( + op: 'request.received', + description: 'request.received', + origin: 'auto.request.received', + asParent: true + ); defer(function () use ($transaction, $span) { - $span?->setOrigin('auto.request') - ->finish(); + $span?->finish(); SentrySdk::getCurrentHub()->setSpan($transaction); diff --git a/src/sentry/src/Tracing/SpanStarter.php b/src/sentry/src/Tracing/SpanStarter.php index 05d48d603..64034f15f 100644 --- a/src/sentry/src/Tracing/SpanStarter.php +++ b/src/sentry/src/Tracing/SpanStarter.php @@ -29,23 +29,25 @@ trait SpanStarter { - protected function startSpan(?string $op = null, ?string $description = null, bool $asParent = false): ?Span - { + protected function startSpan( + ?string $op = null, + ?string $description = null, + ?string $origin = null, + bool $asParent = false + ): ?Span { if (! $parent = SentrySdk::getCurrentHub()->getSpan()) { return null; } - $span = $parent->startChild(new SpanContext()); - $span->setOp($op); - $span->setDescription($description); - $span->setStatus(SpanStatus::ok()); - $span->setStartTimestamp(microtime(true)); - - if ($asParent) { - SentrySdk::getCurrentHub()->setSpan($span); - } - - return $span; + return tap( + $parent->startChild(new SpanContext()) + ->setOp($op) + ->setDescription($description) + ->setOrigin($origin) + ->setStatus(SpanStatus::ok()) + ->setStartTimestamp(microtime(true)), + fn (Span $span) => $asParent && SentrySdk::getCurrentHub()->setSpan($span) + ); } protected function startRequestTransaction(ServerRequestInterface $request, ...$options): Transaction @@ -85,24 +87,27 @@ protected function continueTrace(string $sentryTrace = '', string $baggage = '', ); $context = continueTrace($sentryTrace, $baggage); - if (isset($options['name'])) { + if (isset($options['name']) && is_string($options['name'])) { $context->setName($options['name']); } - if (isset($options['op'])) { + if (isset($options['op']) && is_string($options['op'])) { $context->setOp($options['op']); } - if (isset($options['description'])) { + if (isset($options['description']) && is_string($options['description'])) { $context->setDescription($options['description']); } + if (isset($options['origin']) && is_string($options['origin'])) { + $context->setOrigin($options['origin']); + } if (isset($options['source']) && $options['source'] instanceof TransactionSource) { $context->setSource($options['source']); } else { $context->setSource(TransactionSource::custom()); } - $transaction = $hub->startTransaction($context); - $transaction->setStartTimestamp(microtime(true)); - $transaction->setStatus(SpanStatus::ok()); + $transaction = $hub->startTransaction($context) + ->setStartTimestamp(microtime(true)) + ->setStatus(SpanStatus::ok()); $hub->setSpan($transaction); From 5e9b748b93b39253d737ed2372c46e9c5d904431 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Thu, 4 Sep 2025 15:18:04 +0800 Subject: [PATCH 2/3] fix(tracing): add type hint for job variable in handlePush method --- src/sentry/src/Tracing/Aspect/AsyncQueueJobMessageAspect.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sentry/src/Tracing/Aspect/AsyncQueueJobMessageAspect.php b/src/sentry/src/Tracing/Aspect/AsyncQueueJobMessageAspect.php index 607510527..eaf9defbd 100644 --- a/src/sentry/src/Tracing/Aspect/AsyncQueueJobMessageAspect.php +++ b/src/sentry/src/Tracing/Aspect/AsyncQueueJobMessageAspect.php @@ -69,6 +69,7 @@ public function handleGet(ProceedingJoinPoint $proceedingJoinPoint) public function handlePush(ProceedingJoinPoint $proceedingJoinPoint) { + /** @var \Hyperf\AsyncQueue\JobInterface $job */ $job = $proceedingJoinPoint->arguments['keys']['job'] ?? null; $span = $this->startSpan( op: 'queue.publish', From e0cb5eff97c3f059f3b8714ca9db26d1d3d9d7b6 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Thu, 4 Sep 2025 15:22:13 +0800 Subject: [PATCH 3/3] fix(tracing): add null safety checks for span status and finish methods in RedisAspect --- src/sentry/src/Tracing/Aspect/RedisAspect.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sentry/src/Tracing/Aspect/RedisAspect.php b/src/sentry/src/Tracing/Aspect/RedisAspect.php index 6e5fef170..e8037037f 100644 --- a/src/sentry/src/Tracing/Aspect/RedisAspect.php +++ b/src/sentry/src/Tracing/Aspect/RedisAspect.php @@ -104,7 +104,7 @@ class_exists(CommandExecuted::class) if ($this->switcher->isTracingExtraTagEnable('exception.stack_trace')) { $span->setData(['exception.stack_trace' => (string) $exception]); } - $span->setStatus(SpanStatus::internalError()) + $span?->setStatus(SpanStatus::internalError()) ->setTags([ 'error' => true, 'exception.class' => $exception::class, @@ -114,7 +114,7 @@ class_exists(CommandExecuted::class) throw $exception; } finally { - $span->finish(); + $span?->finish(); } return $result;