From 72534ea0281f60d55a740bbc0f9735906450b274 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Sat, 15 Mar 2025 12:50:49 +0800 Subject: [PATCH 1/2] Improved redis tracing --- src/sentry/src/Tracing/Aspect/RedisAspect.php | 3 +- .../Tracing/Listener/TracingRedisListener.php | 3 +- src/sentry/src/Util/RedisCommand.php | 42 ++++++++++++ tests/Sentry/RedisCommandTest.php | 68 +++++++++++++++++++ 4 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 src/sentry/src/Util/RedisCommand.php create mode 100644 tests/Sentry/RedisCommandTest.php diff --git a/src/sentry/src/Tracing/Aspect/RedisAspect.php b/src/sentry/src/Tracing/Aspect/RedisAspect.php index a619b78a7..d23098914 100644 --- a/src/sentry/src/Tracing/Aspect/RedisAspect.php +++ b/src/sentry/src/Tracing/Aspect/RedisAspect.php @@ -13,6 +13,7 @@ use FriendsOfHyperf\Sentry\Switcher; use FriendsOfHyperf\Sentry\Tracing\SpanStarter; +use FriendsOfHyperf\Sentry\Util\RedisCommand; use Hyperf\Coroutine\Coroutine; use Hyperf\Di\Aop\AbstractAspect; use Hyperf\Di\Aop\ProceedingJoinPoint; @@ -65,7 +66,7 @@ class_exists(CommandExecuted::class) 'db.redis.connection' => $poolName, 'db.redis.database_index' => $config['db'] ?? 0, 'db.redis.parameters' => $arguments['arguments'], - // 'db.statement' => strtoupper($arguments['name']) . implode(' ', $arguments['arguments']), + 'db.statement' => (new RedisCommand($arguments['name'], $arguments['arguments']))->__toString(), 'db.redis.pool.name' => $poolName, 'db.redis.pool.max' => $pool->getOption()->getMaxConnections(), 'db.redis.pool.max_idle_time' => $pool->getOption()->getMaxIdleTime(), diff --git a/src/sentry/src/Tracing/Listener/TracingRedisListener.php b/src/sentry/src/Tracing/Listener/TracingRedisListener.php index e19b7a6bb..cc4d3cd84 100644 --- a/src/sentry/src/Tracing/Listener/TracingRedisListener.php +++ b/src/sentry/src/Tracing/Listener/TracingRedisListener.php @@ -13,6 +13,7 @@ use FriendsOfHyperf\Sentry\Switcher; use FriendsOfHyperf\Sentry\Tracing\SpanStarter; +use FriendsOfHyperf\Sentry\Util\RedisCommand; use Hyperf\Contract\ConfigInterface; use Hyperf\Coroutine\Coroutine; use Hyperf\Event\Contract\ListenerInterface; @@ -58,7 +59,7 @@ public function process(object $event): void 'db.redis.connection' => $event->connectionName, 'db.redis.database_index' => $config['db'] ?? 0, 'db.redis.parameters' => $event->parameters, - 'db.statement' => implode(' ', [$event->parameters[0] ?? '', $event->parameters[1] ?? '']), // @todo optimize + 'db.statement' => (new RedisCommand($event->command, $event->parameters))->__toString(), 'db.redis.pool.name' => $event->connectionName, 'db.redis.pool.max' => $pool->getOption()->getMaxConnections(), 'db.redis.pool.max_idle_time' => $pool->getOption()->getMaxIdleTime(), diff --git a/src/sentry/src/Util/RedisCommand.php b/src/sentry/src/Util/RedisCommand.php new file mode 100644 index 000000000..4525a0e33 --- /dev/null +++ b/src/sentry/src/Util/RedisCommand.php @@ -0,0 +1,42 @@ +parameters)->map(function ($parameter) { + if (is_array($parameter)) { + return collect($parameter)->map(function ($value, $key) { + if (is_array($value)) { + return sprintf('%s %s', $key, json_encode($value)); + } + + return is_int($key) ? $value : sprintf('%s %s', $key, $value); + })->implode(' '); + } + + return $parameter; + })->implode(' '); + + return sprintf('%s %s', $this->command, $parameters); + } +} diff --git a/tests/Sentry/RedisCommandTest.php b/tests/Sentry/RedisCommandTest.php new file mode 100644 index 000000000..d5a6f764c --- /dev/null +++ b/tests/Sentry/RedisCommandTest.php @@ -0,0 +1,68 @@ +toBe('GET key'); +}); + +test('redis command with multiple simple parameters', function () { + $command = new RedisCommand('MGET', ['key1', 'key2', 'key3']); + + expect((string) $command)->toBe('MGET key1 key2 key3'); +}); + +test('redis command with array parameter', function () { + $command = new RedisCommand('HMSET', ['user:1', ['name' => 'John', 'email' => 'john@example.com']]); + + expect((string) $command)->toBe('HMSET user:1 name John email john@example.com'); +}); + +test('redis command with nested array parameter', function () { + $command = new RedisCommand('HMSET', ['user:1', ['name' => 'John', 'data' => ['age' => 30, 'active' => true]]]); + + expect((string) $command)->toBe('HMSET user:1 name John data {"age":30,"active":true}'); +}); + +test('redis command with indexed array parameter', function () { + $command = new RedisCommand('LPUSH', ['list', ['item1', 'item2', 'item3']]); + + expect((string) $command)->toBe('LPUSH list item1 item2 item3'); +}); + +test('redis command with empty parameters', function () { + $command = new RedisCommand('PING'); + + expect((string) $command)->toBe('PING '); +}); + +test('redis command with mixed parameters', function () { + $command = new RedisCommand('ZADD', ['scores', 1, 'value1', 2, 'value2', ['extra' => 'data']]); + + expect((string) $command)->toBe('ZADD scores 1 value1 2 value2 extra data'); +}); + +test('redis command with SET NX option', function () { + $command = new RedisCommand('SET', ['key', 'value', 'NX']); + + expect((string) $command)->toBe('SET key value NX'); +}); + +test('redis command with SET EX option', function () { + $command = new RedisCommand('SET', ['key', 'value', 'EX', 60]); + + expect((string) $command)->toBe('SET key value EX 60'); +}); From b69a50afba4eceaf2a4268277ba56b22f69a0379 Mon Sep 17 00:00:00 2001 From: Deeka Wong <8337659+huangdijia@users.noreply.github.com> Date: Sat, 15 Mar 2025 12:54:15 +0800 Subject: [PATCH 2/2] Split format command --- src/sentry/src/Util/RedisCommand.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/sentry/src/Util/RedisCommand.php b/src/sentry/src/Util/RedisCommand.php index 4525a0e33..e46c92bcf 100644 --- a/src/sentry/src/Util/RedisCommand.php +++ b/src/sentry/src/Util/RedisCommand.php @@ -23,7 +23,12 @@ public function __construct(public string $command, public array $parameters = [ public function __toString(): string { - $parameters = collect($this->parameters)->map(function ($parameter) { + return $this->formatCommand($this->command, $this->parameters); + } + + protected function formatCommand(string $command, array $parameters): string + { + $parameters = collect($parameters)->map(function ($parameter) { if (is_array($parameter)) { return collect($parameter)->map(function ($value, $key) { if (is_array($value)) { @@ -37,6 +42,6 @@ public function __toString(): string return $parameter; })->implode(' '); - return sprintf('%s %s', $this->command, $parameters); + return sprintf('%s %s', $command, $parameters); } }