Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
5893eaa
feat(tracing): enhance span management with improved error handling a…
huangdijia Sep 22, 2025
50087a8
refactor(span): update trace method parameter type hint for improved …
huangdijia Sep 22, 2025
fff7472
refactor(span): improve trace method to enhance scope handling and er…
huangdijia Sep 22, 2025
aa57540
fix(listener): ensure all spans are flushed before command exits
huangdijia Sep 23, 2025
c00a83a
refactor(listener): remove unnecessary sleep to ensure spans are flus…
huangdijia Sep 23, 2025
5b1f685
refactor(aspect): set priority to PHP_INT_MAX in constructor for impr…
huangdijia Sep 23, 2025
efb335c
refactor(coroutine-aspect): remove commented SentrySdk class referenc…
huangdijia Sep 23, 2025
db81938
fix(coroutine-aspect): add missing SentrySdk import for exception han…
huangdijia Sep 23, 2025
367f2d5
fix(aspect): uncomment SentrySdk class reference in keys array for pr…
huangdijia Sep 23, 2025
4052232
fix(span-starter): reorder parameters in withScope closure for consis…
huangdijia Sep 23, 2025
0df83f4
fix(span-starter): set current span in scope for child span tracking
huangdijia Sep 23, 2025
6fe1ad7
fix(event-handle-listener): refactor Redis span handling to use trace…
huangdijia Sep 23, 2025
7aebe51
fix(grpc-aspect): refactor tracing logic to use trace method and impr…
huangdijia Sep 23, 2025
121fbcb
fix(cache-aspect): refactor process method to enhance error handling …
huangdijia Sep 23, 2025
c40c068
fix(async-queue-job-message-aspect): refactor process method to impro…
huangdijia Sep 23, 2025
74bee6b
fix(amqp-producer-aspect): refactor message publishing to enhance tra…
huangdijia Sep 23, 2025
d179312
fix(coordinator-aspect): refactor process method to enhance tracing a…
huangdijia Sep 23, 2025
27f754a
fix(coroutine-aspect): refactor span handling to improve error tracki…
huangdijia Sep 23, 2025
fd749a7
fix(db-aspect): refactor process method to enhance tracing and error …
huangdijia Sep 23, 2025
33eb62d
fix(db-aspect): remove redundant variable assignment for operation
huangdijia Sep 23, 2025
fb2c661
fix(db-aspect): remove unused SentrySdk check to streamline process m…
huangdijia Sep 23, 2025
e135854
fix(elasticsearch-aspect): refactor process method to improve tracing…
huangdijia Sep 23, 2025
34f0dd6
fix(aspect): refactor tracing logic to improve error handling and str…
huangdijia Sep 23, 2025
ee03a02
fix(redis-aspect): refactor process method to enhance tracing and err…
huangdijia Sep 23, 2025
95d5a6b
fix(aspect): refactor tracing data structure for Kafka, Redis, and RP…
huangdijia Sep 23, 2025
0ed7db8
fix(aspect): update span context reference in GuzzleHttpClientAspect …
huangdijia Sep 23, 2025
96a9a8c
fix(aspect): refactor TraceAnnotationAspect to improve span handling …
huangdijia Sep 23, 2025
c1d83d3
fix(aspect): refactor EventHandleListener to enhance span handling an…
huangdijia Sep 23, 2025
30214a6
fix(aspect): ensure span is finished correctly in EventHandleListener
huangdijia Sep 23, 2025
3f175aa
fix(aspect): refactor GuzzleHttpClientAspect to improve span handling…
huangdijia Sep 23, 2025
596eae1
fix(aspect): refactor CoroutineAspect to improve span handling and en…
huangdijia Sep 23, 2025
34ff81f
Add comments to clarify coroutine tracing logic
huangdijia Sep 23, 2025
17b07b0
fix(dependencies): update sentry/sentry to version ^4.16.0
huangdijia Sep 23, 2025
c7e4d80
fix(aspect): add null check for span in AmqpProducerAspect to prevent…
huangdijia Sep 23, 2025
86a056d
fix(aspect): cast Elasticsearch result to string before setting as sp…
huangdijia Sep 23, 2025
070aa0d
fix(aspect): cast arguments to string in ElasticsearchAspect for prop…
huangdijia Sep 23, 2025
6bbd4b5
fix(aspect): add error handling and cleanup for RPC tracing in RpcAspect
huangdijia Sep 23, 2025
64b1a7c
fix(aspect): simplify tracing span check in GuzzleHttpClientAspect
huangdijia Sep 23, 2025
153a5f4
fix(aspect): add exception message to span tags in GuzzleHttpClientAs…
huangdijia Sep 23, 2025
38a04fe
fix(aspect): refactor HTTP status handling in GuzzleHttpClientAspect …
huangdijia Sep 23, 2025
5d3ebb8
fix(aspect): inject RPC context data and tracing carrier into span in…
huangdijia Sep 23, 2025
4196333
fix(aspect): ensure span is valid before setting RPC result data in R…
huangdijia Sep 23, 2025
2be7de2
fix(aspect): move exception message to span data in CoroutineAspect, …
huangdijia Sep 23, 2025
d066d83
fix(aspect): rename transaction variable to coTransaction for clarity…
huangdijia Sep 23, 2025
5ae1159
fix(span): add detailed description for trace method in SpanStarter t…
huangdijia Sep 23, 2025
6abe2ae
fix(span): enhance error handling and tracing in trace method of Span…
huangdijia Sep 23, 2025
81b4ff8
fix(span): set start timestamp in trace method of SpanStarter trait i…
huangdijia Sep 23, 2025
143ea06
fix(span): correct condition for enabling tracing extra tag in trace …
huangdijia Sep 23, 2025
29e5df6
fix(span): simplify tracing extra tag condition in trace method of Sp…
huangdijia Sep 23, 2025
403e64c
fix(span): ensure span is valid before setting data and status in Eve…
huangdijia Sep 24, 2025
4eadf40
fix(EventHandleListener): change private methods to protected for bet…
huangdijia Sep 24, 2025
0e50466
fix(CoroutineAspect, EventHandleListener, SpanStarter): refactor to u…
huangdijia Sep 24, 2025
a8c52e1
feat(Carrier, EventHandleListener, SpanStarter): implement Carrier ut…
huangdijia Sep 24, 2025
f2d735a
fix(SpanStarter): remove duplicate startTransaction method implementa…
huangdijia Sep 24, 2025
147ddce
Remove sampled check from trace ID header logic
huangdijia Sep 24, 2025
efb2f74
fix(EventHandleListener): simplify span validation logic and remove c…
huangdijia Sep 24, 2025
fb9957e
fix(EventHandleListener): add carrier initialization for improved tra…
huangdijia Sep 24, 2025
6062168
fix(EventHandleListener): streamline span creation logic in process m…
huangdijia Sep 24, 2025
08ec1dd
fix(EventHandleListener): refactor error handling and transaction man…
huangdijia Sep 24, 2025
0660dc8
fix(EventHandleListener): add return type annotation for parseRoute m…
huangdijia Sep 24, 2025
56ca181
fix(EventHandleListener): optimize span data setting and simplify tra…
huangdijia Sep 24, 2025
38c248d
Refactor trace ID handling in EventHandleListener
huangdijia Sep 24, 2025
fcecc17
fix(EventHandleListener): simplify trace ID handling in process method
huangdijia Sep 24, 2025
ffaae4b
fix(EventHandleListener, AmqpProducerAspect, AsyncQueueJobMessageAspe…
huangdijia Sep 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"psr/http-factory-implementation": "*",
"psy/psysh": "^0.10.0 || ^0.11.0",
"ramsey/uuid": "^4.7",
"sentry/sentry": "^4.15.0",
"sentry/sentry": "^4.16.0",
"symfony/console": "^5.3 || ^6.0 || ^7.0",
"symfony/http-foundation": "^5.3 || ^6.0 || ^7.0",
"symfony/polyfill-php84": "^1.33",
Expand Down
2 changes: 1 addition & 1 deletion src/sentry/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"hyperf/http-server": "~3.1.0",
"hyperf/support": "~3.1.0",
"hyperf/tappable": "~3.1.0",
"sentry/sentry": "^4.15.0",
"sentry/sentry": "^4.16.0",
"symfony/polyfill-php85": "^1.33"
},
"suggest": {
Expand Down
7 changes: 6 additions & 1 deletion src/sentry/src/Aspect/CoroutineAspect.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ class CoroutineAspect extends AbstractAspect
\Psr\Http\Message\ServerRequestInterface::class,
];

public function __construct()
{
$this->priority = PHP_INT_MAX - 1;
}

public function process(ProceedingJoinPoint $proceedingJoinPoint)
{
$callable = $proceedingJoinPoint->arguments['keys']['callable'];
Expand All @@ -40,7 +45,7 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint)
$current = Co::getContextFor();

foreach ($keys as $key) {
if (isset($from[$key])) {
if (isset($from[$key]) && ! isset($current[$key])) {
$current[$key] = $from[$key];
}
}
Expand Down
75 changes: 39 additions & 36 deletions src/sentry/src/Tracing/Aspect/AmqpProducerAspect.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
use FriendsOfHyperf\Sentry\Util\Carrier;
use Hyperf\Amqp\Annotation\Producer;
use Hyperf\Amqp\Message\ProducerMessage;
use Hyperf\Coroutine\Coroutine;
use Hyperf\Di\Annotation\AnnotationCollector;
use Hyperf\Di\Aop\AbstractAspect;
use Hyperf\Di\Aop\ProceedingJoinPoint;
use PhpAmqpLib\Wire\AMQPTable;

use function Hyperf\Tappable\tap;
use Sentry\State\Scope;
use Sentry\Tracing\SpanContext;

/**
* @property array{application_headers?:AMQPTable} $properties
Expand Down Expand Up @@ -60,16 +61,6 @@ protected function handleProduceMessage(ProceedingJoinPoint $proceedingJoinPoint
return $proceedingJoinPoint->process();
}

$span = $this->startSpan(
op: 'queue.publish',
description: sprintf('%s::%s()', $proceedingJoinPoint->className, $proceedingJoinPoint->methodName),
origin: 'auto.amqp'
);

if (! $span) {
return $proceedingJoinPoint->process();
}

$routingKey = $producerMessage->getRoutingKey();
$exchange = $producerMessage->getExchange();
$poolName = $producerMessage->getPoolName();
Expand All @@ -87,30 +78,42 @@ protected function handleProduceMessage(ProceedingJoinPoint $proceedingJoinPoint
$messageId = uniqid('amqp_', true);
$destinationName = implode(', ', (array) $routingKey);
$bodySize = strlen($producerMessage->payload());
$span->setData([
'messaging.system' => 'amqp',
'messaging.operation' => 'publish',
'messaging.message.id' => $messageId,
'messaging.message.body.size' => $bodySize,
'messaging.destination.name' => $destinationName,
// for amqp
'messaging.amqp.message.type' => $producerMessage->getTypeString(),
'messaging.amqp.message.routing_key' => $routingKey,
'messaging.amqp.message.exchange' => $exchange,
'messaging.amqp.message.pool_name' => $poolName,
]);
$carrier = Carrier::fromSpan($span)->with([
'publish_time' => microtime(true),
'message_id' => $messageId,
'destination_name' => $destinationName,
'body_size' => $bodySize,
]);

(function () use ($carrier) {
$this->properties['application_headers'] ??= new AMQPTable();
$this->properties['application_headers']->set(Constants::TRACE_CARRIER, $carrier->toJson());
})->call($producerMessage);

return tap($proceedingJoinPoint->process(), fn () => $span->finish());
return $this->trace(
function (Scope $scope) use ($proceedingJoinPoint, $producerMessage, $messageId, $destinationName, $bodySize) {
$span = $scope->getSpan();
if ($span) {
$carrier = Carrier::fromSpan($span)->with([
'publish_time' => microtime(true),
'message_id' => $messageId,
'destination_name' => $destinationName,
'body_size' => $bodySize,
]);
(function () use ($carrier) {
$this->properties['application_headers'] ??= new AMQPTable();
$this->properties['application_headers']->set(Constants::TRACE_CARRIER, $carrier->toJson());
})->call($producerMessage);
}

return $proceedingJoinPoint->process();
},
SpanContext::make()
->setOp('queue.publish')
->setDescription(sprintf('%s::%s()', $proceedingJoinPoint->className, $proceedingJoinPoint->methodName))
->setOrigin('auto.amqp')
->setData([
'coroutine.id' => Coroutine::id(),
'messaging.system' => 'amqp',
'messaging.operation' => 'publish',
'messaging.message.id' => $messageId,
'messaging.message.body.size' => $bodySize,
'messaging.destination.name' => $destinationName,
// for amqp
'messaging.amqp.message.type' => $producerMessage->getTypeString(),
'messaging.amqp.message.routing_key' => $routingKey,
'messaging.amqp.message.exchange' => $exchange,
'messaging.amqp.message.pool_name' => $poolName,
])
);
}
}
76 changes: 39 additions & 37 deletions src/sentry/src/Tracing/Aspect/AsyncQueueJobMessageAspect.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
use FriendsOfHyperf\Sentry\Util\Carrier;
use Hyperf\AsyncQueue\Driver\RedisDriver;
use Hyperf\Context\Context;
use Hyperf\Coroutine\Coroutine;
use Hyperf\Di\Aop\AbstractAspect;
use Hyperf\Di\Aop\ProceedingJoinPoint;
use Sentry\State\Scope;
use Sentry\Tracing\SpanContext;

use function Hyperf\Support\with;

Expand Down Expand Up @@ -73,46 +76,45 @@ public function handlePush(ProceedingJoinPoint $proceedingJoinPoint)
{
/** @var \Hyperf\AsyncQueue\JobInterface $job */
$job = $proceedingJoinPoint->arguments['keys']['job'] ?? null;
$span = $this->startSpan(
op: 'queue.publish',
description: $job::class,
origin: 'auto.queue'
);

if (! $span) {
return $proceedingJoinPoint->process();
/** @var \Hyperf\AsyncQueue\Driver\Driver $driver */
$driver = $proceedingJoinPoint->getInstance();
$messageId = method_exists($job, 'getId') ? $job->getId() : uniqid('async_queue_', true);
$destinationName = Context::get('sentry.messaging.destination.name', 'default');
$bodySize = (fn ($job) => strlen($this->packer->pack($job)))->call($driver, $job);
$data = [
'coroutine.id' => Coroutine::id(),
'messaging.system' => 'async_queue',
'messaging.operation' => 'publish',
'messaging.message.id' => $messageId,
'messaging.message.body.size' => $bodySize,
'messaging.destination.name' => $destinationName,
];

if ($driver instanceof RedisDriver) {
$data = array_merge($data, $this->buildSpanDataOfRedisDriver($driver));
}

try {
/** @var \Hyperf\AsyncQueue\Driver\Driver $driver */
$driver = $proceedingJoinPoint->getInstance();
$messageId = method_exists($job, 'getId') ? $job->getId() : uniqid('async_queue_', true);
$destinationName = Context::get('sentry.messaging.destination.name', 'default');
$bodySize = (fn ($job) => strlen($this->packer->pack($job)))->call($driver, $job);
$span->setData([
'messaging.system' => 'async_queue',
'messaging.operation' => 'publish',
'messaging.message.id' => $messageId,
'messaging.message.body.size' => $bodySize,
'messaging.destination.name' => $destinationName,
]);
if ($driver instanceof RedisDriver) {
$span->setData($this->buildSpanDataOfRedisDriver($driver));
}

$carrier = Carrier::fromSpan($span)->with([
'publish_time' => microtime(true),
'message_id' => $messageId,
'destination_name' => $destinationName,
'body_size' => $bodySize,
]);

Context::set(Constants::TRACE_CARRIER, $carrier);

return $proceedingJoinPoint->process();
} finally {
$span->finish();
}
return $this->trace(
function (Scope $scope) use ($proceedingJoinPoint, $messageId, $destinationName, $bodySize) {
$span = $scope->getSpan();
$carrier = Carrier::fromSpan($span)->with([
'publish_time' => microtime(true),
'message_id' => $messageId,
'destination_name' => $destinationName,
'body_size' => $bodySize,
]);

Context::set(Constants::TRACE_CARRIER, $carrier);

return $proceedingJoinPoint->process();
},
SpanContext::make()
->setOp('queue.publish')
->setDescription($job::class)
->setOrigin('auto.queue')
->setData($data)
);
}

protected function buildSpanDataOfRedisDriver(RedisDriver $driver): array
Expand Down
111 changes: 55 additions & 56 deletions src/sentry/src/Tracing/Aspect/CacheAspect.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@

use FriendsOfHyperf\Sentry\Switcher;
use FriendsOfHyperf\Sentry\Tracing\SpanStarter;
use Hyperf\Coroutine\Coroutine;
use Hyperf\Di\Aop\AbstractAspect;
use Hyperf\Di\Aop\ProceedingJoinPoint;
use Sentry\SentrySdk;
use Sentry\State\Scope;
use Sentry\Tracing\SpanContext;

use function Hyperf\Tappable\tap;

Expand Down Expand Up @@ -47,63 +49,60 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint)
return $proceedingJoinPoint->process();
}

$parent = SentrySdk::getCurrentHub()->getSpan();
$method = $proceedingJoinPoint->methodName;
$op = match ($method) {
'set', 'setMultiple' => 'cache.put',
'get', 'fetch', 'getMultiple' => 'cache.get',
'delete', 'deleteMultiple' => 'cache.remove',
'clear' => 'cache.flush',
default => 'cache',
};

try {
$method = $proceedingJoinPoint->methodName;
$op = match ($method) {
'set', 'setMultiple' => 'cache.put',
'get', 'fetch', 'getMultiple' => 'cache.get',
'delete', 'deleteMultiple' => 'cache.remove',
'clear' => 'cache.flush',
default => 'cache',
};
$arguments = $proceedingJoinPoint->arguments['keys'] ?? [];

$arguments = $proceedingJoinPoint->arguments['keys'] ?? [];
/** @var string[] $keys */
$keys = match ($method) {
'set', 'get', 'delete' => [$arguments['key'] ?? 'unknown'],
'setMultiple' => array_keys($arguments['values'] ?? []),
'getMultiple', 'deleteMultiple' => $arguments['keys'] ?? [],
default => [],
};

/** @var string[] $keys */
$keys = match ($method) {
'set', 'get', 'delete' => [$arguments['key'] ?? 'unknown'],
'setMultiple' => array_keys($arguments['values'] ?? []),
'getMultiple', 'deleteMultiple' => $arguments['keys'] ?? [],
default => [],
};

$span = $this->startSpan(
op: $op,
description: implode(', ', $keys),
origin: 'auto.cache',
asParent: true
)?->setData([
'cache.key' => $keys,
'cache.ttl' => $arguments['ttl'] ?? null,
'item_size' => match (true) {
isset($arguments['value']) => strlen(json_encode($arguments['value'])),
isset($arguments['values']) && is_array($arguments['values']) => strlen(json_encode(array_values($arguments['values']))),
default => 0,
},
]);

return tap($proceedingJoinPoint->process(), function ($result) use ($span, $method) {
$data = match ($method) {
'get' => [
'cache.hit' => ! is_null($result),
'cache.item_size' => strlen((string) json_encode($result)),
],
'fetch' => [
'cache.hit' => ($result[0] ?? false) !== false,
'cache.item_size' => strlen((string) json_encode($result[1] ?? '')),
],
'getMultiple' => [
'cache.hit' => ! empty($result),
'cache.item_size' => strlen((string) json_encode(array_values((array) $result))),
],
default => [],
};
$span?->setData($data)->finish();
});
} finally {
SentrySdk::getCurrentHub()->setSpan($parent);
}
return $this->trace(
function (Scope $scope) use ($proceedingJoinPoint, $method) {
return tap($proceedingJoinPoint->process(), function ($result) use ($method, $scope) {
$data = match ($method) {
'get' => [
'cache.hit' => ! is_null($result),
'cache.item_size' => strlen((string) json_encode($result)),
],
'fetch' => [
'cache.hit' => ($result[0] ?? false) !== false,
'cache.item_size' => strlen((string) json_encode($result[1] ?? '')),
],
'getMultiple' => [
'cache.hit' => ! empty($result),
'cache.item_size' => strlen((string) json_encode(array_values((array) $result))),
],
default => [],
};
$scope->getSpan()?->setData($data);
});
},
SpanContext::make()
->setOp($op)
->setDescription(implode(', ', $keys))
->setOrigin('auto.cache')
->setData([
'coroutine.id' => Coroutine::id(),
'cache.key' => $keys,
'cache.ttl' => $arguments['ttl'] ?? null,
'item_size' => match (true) {
isset($arguments['value']) => strlen(json_encode($arguments['value'])),
isset($arguments['values']) && is_array($arguments['values']) => strlen(json_encode(array_values($arguments['values']))),
default => 0,
},
])
);
}
}
Loading