From 2784d4b6f42b6f90ef73e92248d96ec3e0102da5 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Thu, 20 Nov 2025 18:23:41 +0800 Subject: [PATCH 1/5] feat: add server address and HTTP method tracing for Elasticsearch operations This enhancement adds comprehensive server connection metadata to Elasticsearch spans, including server address, port, HTTP method, and full URL. It supports both legacy Elasticsearch\Client and modern Elastic\Elasticsearch\Client implementations. Changes: - Extract server address, port, and request method from Elasticsearch clients - Add support for both Elasticsearch client versions - Use tap() helper for cleaner result processing with side effects - Gracefully handle errors when extracting connection metadata - Remove TODO comments as the functionality is now implemented --- .../Tracing/Aspect/ElasticsearchAspect.php | 53 ++++++++++++++----- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php b/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php index 08177576a..c445bf762 100644 --- a/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php +++ b/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php @@ -16,8 +16,10 @@ use Hyperf\Di\Aop\ProceedingJoinPoint; use Sentry\State\Scope; use Sentry\Tracing\SpanContext; +use Throwable; use function FriendsOfHyperf\Sentry\trace; +use function Hyperf\Tappable\tap; class ElasticsearchAspect extends AbstractAspect { @@ -62,13 +64,45 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint) return trace( function (Scope $scope) use ($proceedingJoinPoint) { - $result = $proceedingJoinPoint->process(); - if ($this->feature->isTracingTagEnabled('elasticsearch.result')) { - $scope->getSpan()?->setData([ - 'elasticsearch.result' => (string) json_encode($result, JSON_UNESCAPED_UNICODE), - ]); - } - return $result; + return tap($proceedingJoinPoint->process(), function ($result) use ($scope, $proceedingJoinPoint) { + if ($this->feature->isTracingTagEnabled('elasticsearch.result')) { + $scope->getSpan()?->setData([ + 'elasticsearch.result' => (string) json_encode($result, JSON_UNESCAPED_UNICODE), + ]); + } + + try { + /** @var \Elasticsearch\Client|\Elastic\Elasticsearch\Client $client */ + $client = $proceedingJoinPoint->getInstance(); + $data = match ($client::class) { + 'Elasticsearch\Client' => (function ($client) { + $lastConnection = $client->transport->getLastConnection(); + $lastRequestInfo = $lastConnection->getLastRequestInfo(); + return [ + 'server.address' => $lastConnection->getHost(), + 'server.port' => $lastConnection->getPort(), + 'http.request.method' => $lastRequestInfo['request']['http_method'] ?? null, + 'url.full' => $lastRequestInfo['response']['effective_url'] ?? null, + ]; + })($client), + 'Elastic\Elasticsearch\Client' => (function ($client) { + /** @var \Elastic\Elasticsearch\Client $client */ + $transport = $client->getTransport(); + $lastRequest = $transport->getLastRequest(); + return [ + 'server.address' => $lastRequest->getUri()->getHost(), + 'server.port' => $lastRequest->getUri()->getPort(), + 'http.request.method' => $lastRequest->getMethod(), + 'url.full' => (fn ($request) => $this->getFullUrl($request))->call($transport, $lastRequest), + ]; + })($client), + default => [], + }; + $scope->getSpan()?->setData($data); + } catch (Throwable) { + // Ignore errors + } + }); }, SpanContext::make() ->setOp('db.query') @@ -78,11 +112,6 @@ function (Scope $scope) use ($proceedingJoinPoint) { 'db.system' => 'elasticsearch', 'db.operation.name' => $proceedingJoinPoint->methodName, 'arguments' => (string) json_encode($proceedingJoinPoint->arguments['keys'], JSON_UNESCAPED_UNICODE), - // TODO - // 'http.request.method' => '', - // 'url.full' => '', - // 'server.host' => '', - // 'server.port' => '', ]) ); } From acba8ac0e1566864308c969aeb879b9823a7558a Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Thu, 20 Nov 2025 18:30:14 +0800 Subject: [PATCH 2/5] fix: add PHPStan ignore rules for Elasticsearch\Client type errors --- phpstan.neon.dist | 10 +++++++++- src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php | 4 ++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index f0bc5e436..4c3f0bae0 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -40,4 +40,12 @@ parameters: - message: '#.* has invalid return type Elasticsearch\\Client.#' paths: - - src/telescope-elasticsearch/*/*.php \ No newline at end of file + - src/telescope-elasticsearch/*/*.php + - + message: '#unknown class Elasticsearch\\Client#' + paths: + - src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php + - + message: "#'Elasticsearch\\Client' is always false#" + paths: + - src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php \ No newline at end of file diff --git a/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php b/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php index c445bf762..1d52ad528 100644 --- a/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php +++ b/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php @@ -75,8 +75,8 @@ function (Scope $scope) use ($proceedingJoinPoint) { /** @var \Elasticsearch\Client|\Elastic\Elasticsearch\Client $client */ $client = $proceedingJoinPoint->getInstance(); $data = match ($client::class) { - 'Elasticsearch\Client' => (function ($client) { - $lastConnection = $client->transport->getLastConnection(); + 'Elasticsearch\Client' => (function ($client) { // @phpstan-ignore-line + $lastConnection = $client->transport->getLastConnection(); // @phpstan-ignore-line $lastRequestInfo = $lastConnection->getLastRequestInfo(); return [ 'server.address' => $lastConnection->getHost(), From a778cc1bb24ae66fd68641b7dcd8fd83bea9fbc5 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Thu, 20 Nov 2025 18:31:30 +0800 Subject: [PATCH 3/5] fix: remove obsolete PHPStan ignore rules for Elasticsearch\Client --- phpstan.neon.dist | 8 -------- 1 file changed, 8 deletions(-) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 4c3f0bae0..95b8279f3 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -41,11 +41,3 @@ parameters: message: '#.* has invalid return type Elasticsearch\\Client.#' paths: - src/telescope-elasticsearch/*/*.php - - - message: '#unknown class Elasticsearch\\Client#' - paths: - - src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php - - - message: "#'Elasticsearch\\Client' is always false#" - paths: - - src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php \ No newline at end of file From d64ee447a96540a84564f47276fe8fc650993465 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Thu, 20 Nov 2025 18:32:33 +0800 Subject: [PATCH 4/5] fix: remove redundant PHPStan ignore lines in ElasticsearchAspect --- src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php b/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php index 1d52ad528..d30448e56 100644 --- a/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php +++ b/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php @@ -72,11 +72,10 @@ function (Scope $scope) use ($proceedingJoinPoint) { } try { - /** @var \Elasticsearch\Client|\Elastic\Elasticsearch\Client $client */ $client = $proceedingJoinPoint->getInstance(); $data = match ($client::class) { - 'Elasticsearch\Client' => (function ($client) { // @phpstan-ignore-line - $lastConnection = $client->transport->getLastConnection(); // @phpstan-ignore-line + 'Elasticsearch\Client' => (function ($client) { // @phpstan-ignore-line + $lastConnection = $client->transport->getLastConnection(); $lastRequestInfo = $lastConnection->getLastRequestInfo(); return [ 'server.address' => $lastConnection->getHost(), @@ -85,7 +84,7 @@ function (Scope $scope) use ($proceedingJoinPoint) { 'url.full' => $lastRequestInfo['response']['effective_url'] ?? null, ]; })($client), - 'Elastic\Elasticsearch\Client' => (function ($client) { + 'Elastic\Elasticsearch\Client' => (function ($client) { // @phpstan-ignore-line /** @var \Elastic\Elasticsearch\Client $client */ $transport = $client->getTransport(); $lastRequest = $transport->getLastRequest(); From af87d8c816b755d88ed29fba5b23248a5ae2ef5b Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Thu, 20 Nov 2025 18:35:59 +0800 Subject: [PATCH 5/5] refactor: extract data retrieval logic for Elasticsearch v7 and v8 into separate methods --- .../Tracing/Aspect/ElasticsearchAspect.php | 49 +++++++++++-------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php b/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php index d30448e56..0910bba03 100644 --- a/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php +++ b/src/sentry/src/Tracing/Aspect/ElasticsearchAspect.php @@ -74,27 +74,8 @@ function (Scope $scope) use ($proceedingJoinPoint) { try { $client = $proceedingJoinPoint->getInstance(); $data = match ($client::class) { - 'Elasticsearch\Client' => (function ($client) { // @phpstan-ignore-line - $lastConnection = $client->transport->getLastConnection(); - $lastRequestInfo = $lastConnection->getLastRequestInfo(); - return [ - 'server.address' => $lastConnection->getHost(), - 'server.port' => $lastConnection->getPort(), - 'http.request.method' => $lastRequestInfo['request']['http_method'] ?? null, - 'url.full' => $lastRequestInfo['response']['effective_url'] ?? null, - ]; - })($client), - 'Elastic\Elasticsearch\Client' => (function ($client) { // @phpstan-ignore-line - /** @var \Elastic\Elasticsearch\Client $client */ - $transport = $client->getTransport(); - $lastRequest = $transport->getLastRequest(); - return [ - 'server.address' => $lastRequest->getUri()->getHost(), - 'server.port' => $lastRequest->getUri()->getPort(), - 'http.request.method' => $lastRequest->getMethod(), - 'url.full' => (fn ($request) => $this->getFullUrl($request))->call($transport, $lastRequest), - ]; - })($client), + 'Elasticsearch\Client' => $this->getV7Data($client), // @phpstan-ignore-line + 'Elastic\Elasticsearch\Client' => $this->getV8Data($client), // @phpstan-ignore-line default => [], }; $scope->getSpan()?->setData($data); @@ -114,4 +95,30 @@ function (Scope $scope) use ($proceedingJoinPoint) { ]) ); } + + protected function getV7Data($client): array + { + $lastConnection = $client->transport->getLastConnection(); + $lastRequestInfo = $lastConnection->getLastRequestInfo(); + + return [ + 'server.address' => $lastConnection->getHost(), + 'server.port' => $lastConnection->getPort(), + 'http.request.method' => $lastRequestInfo['request']['http_method'] ?? null, + 'url.full' => $lastRequestInfo['response']['effective_url'] ?? null, + ]; + } + + protected function getV8Data($client): array + { + $transport = $client->getTransport(); + $lastRequest = $transport->getLastRequest(); + + return [ + 'server.address' => $lastRequest->getUri()->getHost(), + 'server.port' => $lastRequest->getUri()->getPort(), + 'http.request.method' => $lastRequest->getMethod(), + 'url.full' => (fn ($request) => $this->getFullUrl($request))->call($transport, $lastRequest), + ]; + } }