Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 0 additions & 1 deletion src/Aspect/GuzzleClientAspect.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@ private function onRejected(?SpanScope $scope, RequestInterface $request, float
[
ServerAttributes::SERVER_ADDRESS => $request->getUri()->getHost(),
HttpAttributes::HTTP_REQUEST_METHOD => $request->getMethod(),
HttpAttributes::HTTP_RESPONSE_STATUS_CODE => 0,
ErrorAttributes::ERROR_TYPE => get_class($throwable),
UrlIncubatingAttributes::URL_TEMPLATE => Uri::sanitize(
$request->getUri()->getPath(),
Expand Down
22 changes: 14 additions & 8 deletions src/Aspect/MongoAspect.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@

use Hyperf\Di\Aop\ProceedingJoinPoint;
use Hyperf\OpenTelemetry\Support\MetricBoundaries;
use Hyperf\Stringable\Str;
use OpenTelemetry\API\Trace\SpanKind;
use OpenTelemetry\API\Trace\StatusCode;
use OpenTelemetry\SemConv\Attributes\DbAttributes;
use OpenTelemetry\SemConv\Attributes\ErrorAttributes;
use OpenTelemetry\SemConv\Incubating\Attributes\DbIncubatingAttributes;
Expand Down Expand Up @@ -40,8 +38,9 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint)

$method = $proceedingJoinPoint->methodName;

$operation = Str::upper($method);
$operation = $method;
$collection = $this->getCollectionName($proceedingJoinPoint);
$namespace = $this->getNamespace($proceedingJoinPoint);
$driver = DbIncubatingAttributes::DB_SYSTEM_NAME_VALUE_MONGODB;

$scope = null;
Expand All @@ -50,22 +49,19 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint)

if ($this->isTracingEnabled) {
$scope = $this->instrumentation->startSpan(
name: "{$driver} {$operation} {$collection}",
name: "{$operation} {$collection}",
spanKind: SpanKind::KIND_CLIENT,
attributes: [
DbAttributes::DB_SYSTEM_NAME => $driver,
DbAttributes::DB_COLLECTION_NAME => $collection,
DbAttributes::DB_OPERATION_NAME => $operation,
'db.system' => $driver,
'db.operation' => $operation,
'db.collection' => $collection,
...($namespace !== null ? [DbAttributes::DB_NAMESPACE => $namespace] : []),
],
);
}

try {
$result = $proceedingJoinPoint->process();
$scope?->setStatus(StatusCode::STATUS_OK);
} catch (Throwable $e) {
$scope?->recordException($e);

Expand Down Expand Up @@ -113,4 +109,14 @@ private function getCollectionName(ProceedingJoinPoint $proceedingJoinPoint): st

return $property->getValue($collection);
}

private function getNamespace(ProceedingJoinPoint $proceedingJoinPoint): ?string
{
try {
$property = new ReflectionProperty('Hyperf\GoTask\MongoClient\Collection', 'database');
return $property->getValue($proceedingJoinPoint->getInstance());
} catch (Throwable) {
return null;
}
}
}
8 changes: 1 addition & 7 deletions src/Aspect/RedisAspect.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
use Hyperf\OpenTelemetry\Support\MetricBoundaries;
use Hyperf\Stringable\Str;
use OpenTelemetry\API\Trace\SpanKind;
use OpenTelemetry\API\Trace\StatusCode;
use OpenTelemetry\SemConv\Attributes\DbAttributes;
use OpenTelemetry\SemConv\Attributes\ErrorAttributes;
use OpenTelemetry\SemConv\Incubating\Attributes\DbIncubatingAttributes;
Expand Down Expand Up @@ -43,23 +42,18 @@ public function process(ProceedingJoinPoint $proceedingJoinPoint)

if ($this->isTracingEnabled) {
$scope = $this->instrumentation->startSpan(
name: 'Redis ' . Str::upper($command),
name: Str::upper($command),
spanKind: SpanKind::KIND_CLIENT,
attributes: [
DbAttributes::DB_SYSTEM_NAME => DbIncubatingAttributes::DB_SYSTEM_NAME_VALUE_REDIS,
DbAttributes::DB_OPERATION_NAME => Str::upper($command),
DbAttributes::DB_QUERY_TEXT => Str::limit($commandFull, 512),
'db.system' => DbIncubatingAttributes::DB_SYSTEM_NAME_VALUE_REDIS,
'db.operation.pool' => Str::upper($command),
'redis.pool' => $poolName,
]
);
}

try {
$result = $proceedingJoinPoint->process();

$scope?->setStatus(StatusCode::STATUS_OK);
} catch (Throwable $e) {
$scope?->recordException($e);

Expand Down
6 changes: 2 additions & 4 deletions src/Listener/DbQueryExecutedListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ protected function onQueryExecuted(QueryExecuted $event): void
$operation = Str::upper(Str::before($event->sql, ' '));
$table = $this->extractTableName($sql);
$driver = $this->getDriverName($event);
$spanName = $table ? "{$driver} {$operation} {$table}" : "{$driver} {$operation}";
$spanName = $table ? "{$operation} {$table}" : $operation;

if ($this->isTracingEnabled) {
$scope = $this->instrumentation->startSpan(
Expand All @@ -67,11 +67,9 @@ protected function onQueryExecuted(QueryExecuted $event): void
DbAttributes::DB_NAMESPACE => $event->connection->getDatabaseName(),
DbAttributes::DB_OPERATION_NAME => Str::upper($operation),
DbAttributes::DB_QUERY_TEXT => $sql,
DbAttributes::DB_QUERY_SUMMARY => $table ? "{$operation} {$table}" : $operation,
ServerAttributes::SERVER_ADDRESS => $event->connection->getConfig('host'),
ServerAttributes::SERVER_PORT => $event->connection->getConfig('port'),
'db.system' => $driver,
'db.operation' => Str::upper($operation),
'db.sql.table' => $table,
],
startTimestamp: $this->calculateQueryStartTime($nowInNs, $event->time)
);
Expand Down
2 changes: 1 addition & 1 deletion src/Middleware/TraceMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
$context = $this->instrumentation->propagator()->extract($request->getHeaders());

$scope = $this->instrumentation->startSpan(
name: Uri::sanitize($path, $this->config->get('open-telemetry.traces.uri_mask', [])),
name: $request->getMethod() . ' ' . Uri::sanitize($path, $this->config->get('open-telemetry.traces.uri_mask', [])),
spanKind: SpanKind::KIND_SERVER,
attributes: [
HttpAttributes::HTTP_REQUEST_METHOD => $request->getMethod(),
Expand Down
1 change: 0 additions & 1 deletion tests/Unit/Aspect/GuzzleClientAspectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,6 @@ public function testProcessWithRejectedRequest(): void
ServerAttributes::SERVER_ADDRESS => 'api.example.com',
UrlIncubatingAttributes::URL_TEMPLATE => '/v1/users',
HttpAttributes::HTTP_REQUEST_METHOD => 'POST',
HttpAttributes::HTTP_RESPONSE_STATUS_CODE => 0,
ErrorAttributes::ERROR_TYPE => $exception::class,
]
);
Expand Down
29 changes: 9 additions & 20 deletions tests/Unit/Aspect/MongoAspectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
use OpenTelemetry\API\Metrics\HistogramInterface;
use OpenTelemetry\API\Metrics\MeterInterface;
use OpenTelemetry\API\Trace\SpanKind;
use OpenTelemetry\API\Trace\StatusCode;
use OpenTelemetry\SemConv\Attributes\DbAttributes;
use OpenTelemetry\SemConv\Attributes\ErrorAttributes;
use OpenTelemetry\SemConv\Incubating\Attributes\DbIncubatingAttributes;
Expand Down Expand Up @@ -145,23 +144,16 @@ public function testProcess(): void
->expects($this->once())
->method('startSpan')
->with(
$this->equalTo('mongodb FIND users'),
$this->equalTo('find users'),
$this->equalTo(SpanKind::KIND_CLIENT),
$this->equalTo([
DbAttributes::DB_SYSTEM_NAME => DbIncubatingAttributes::DB_SYSTEM_NAME_VALUE_MONGODB,
DbAttributes::DB_COLLECTION_NAME => 'users',
DbAttributes::DB_OPERATION_NAME => 'FIND',
'db.system' => DbIncubatingAttributes::DB_SYSTEM_NAME_VALUE_MONGODB,
'db.operation' => 'FIND',
'db.collection' => 'users',
DbAttributes::DB_OPERATION_NAME => 'find',
])
Comment on lines 149 to 153
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new getNamespace() method and the conditional inclusion of DB_NAMESPACE attribute lack test coverage. The mock Collection class in the test setup (lines 62-68) only defines a 'collection' property, not a 'database' property. This means getNamespace() will always return null in the current tests, and the happy path where DB_NAMESPACE is successfully extracted and included in span attributes is not verified.

Consider adding a test case that:

  1. Creates a mock Collection with both 'collection' and 'database' properties
  2. Verifies that DB_NAMESPACE is included in the span attributes when successfully extracted
  3. Ensures the existing test continues to verify the behavior when 'database' property is not available

Copilot uses AI. Check for mistakes.
)
->willReturn($this->spanScope);

$this->spanScope->expects($this->once())
->method('setStatus')
->with(StatusCode::STATUS_OK);

$this->spanScope->expects($this->once())->method('end');

$this->meter->expects($this->once())
Expand All @@ -182,7 +174,7 @@ public function testProcess(): void
$this->isType('float'),
$this->equalTo([
DbAttributes::DB_SYSTEM_NAME => DbIncubatingAttributes::DB_SYSTEM_NAME_VALUE_MONGODB,
DbAttributes::DB_OPERATION_NAME => 'FIND',
DbAttributes::DB_OPERATION_NAME => 'find',
])
);

Expand All @@ -205,7 +197,6 @@ public function testProcessWithDifferentMethods(): void
$instrumentation->method('meter')->willReturn($this->meter);

$spanScope = $this->createMock(SpanScope::class);
$spanScope->expects($this->once())->method('setStatus');
$spanScope->expects($this->once())->method('end');

$aspect = new MongoAspect(
Expand All @@ -218,16 +209,14 @@ public function testProcessWithDifferentMethods(): void
$proceedingJoinPoint->methodName = $method;
$proceedingJoinPoint->method('getInstance')->willReturn($this->mongoCollection);

$expectedOperation = strtoupper($method);

$instrumentation
->expects($this->once())
->method('startSpan')
->with(
$this->equalTo("mongodb {$expectedOperation} users"),
$this->equalTo("{$method} users"),
$this->anything(),
$this->callback(function ($attributes) use ($expectedOperation) {
return $attributes[DbAttributes::DB_OPERATION_NAME] === $expectedOperation;
$this->callback(function ($attributes) use ($method) {
return $attributes[DbAttributes::DB_OPERATION_NAME] === $method;
})
)
->willReturn($spanScope);
Expand All @@ -253,7 +242,7 @@ public function testProcessWithException(): void
$this->instrumentation
->expects($this->once())
->method('startSpan')
->with('mongodb INSERTONE users')
->with('insertOne users')
->willReturn($this->spanScope);

$this->meter->expects($this->once())
Expand All @@ -275,7 +264,7 @@ public function testProcessWithException(): void
[
ErrorAttributes::ERROR_TYPE => Exception::class,
DbAttributes::DB_SYSTEM_NAME => DbIncubatingAttributes::DB_SYSTEM_NAME_VALUE_MONGODB,
DbAttributes::DB_OPERATION_NAME => 'INSERTONE',
DbAttributes::DB_OPERATION_NAME => 'insertOne',
]
);

Expand Down Expand Up @@ -318,7 +307,7 @@ public function testProcessWithDifferentCollectionName(): void
->expects($this->once())
->method('startSpan')
->with(
$this->equalTo('mongodb FIND orders'),
$this->equalTo('find orders'),
$this->anything(),
$this->callback(function ($attributes) {
return $attributes[DbAttributes::DB_COLLECTION_NAME] === 'orders';
Expand Down
20 changes: 3 additions & 17 deletions tests/Unit/Aspect/RedisAspectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
use OpenTelemetry\API\Metrics\HistogramInterface;
use OpenTelemetry\API\Metrics\MeterInterface;
use OpenTelemetry\API\Trace\SpanKind;
use OpenTelemetry\API\Trace\StatusCode;
use OpenTelemetry\SemConv\Attributes\DbAttributes;
use OpenTelemetry\SemConv\Attributes\ErrorAttributes;
use OpenTelemetry\SemConv\Incubating\Attributes\DbIncubatingAttributes;
Expand Down Expand Up @@ -101,23 +100,16 @@ public function testProcess(): void
->expects($this->once())
->method('startSpan')
->with(
$this->equalTo('Redis GET'),
$this->equalTo('GET'),
$this->equalTo(SpanKind::KIND_CLIENT),
[
DbAttributes::DB_SYSTEM_NAME => DbIncubatingAttributes::DB_SYSTEM_NAME_VALUE_REDIS,
DbAttributes::DB_OPERATION_NAME => 'GET',
DbAttributes::DB_QUERY_TEXT => 'get user:123',
'db.system' => DbIncubatingAttributes::DB_SYSTEM_NAME_VALUE_REDIS,
'db.operation.pool' => 'GET',
'redis.pool' => 'default',
]
)
->willReturn($this->spanScope);

$this->spanScope->expects($this->once())
->method('setStatus')
->with(StatusCode::STATUS_OK);

$this->spanScope->expects($this->once())->method('end');

// Metric
Expand Down Expand Up @@ -178,15 +170,12 @@ public function testProcessWithException(): void
->expects($this->once())
->method('startSpan')
->with(
$this->equalTo('Redis SET'),
$this->equalTo('SET'),
$this->equalTo(SpanKind::KIND_CLIENT),
[
DbAttributes::DB_SYSTEM_NAME => DbIncubatingAttributes::DB_SYSTEM_NAME_VALUE_REDIS,
DbAttributes::DB_OPERATION_NAME => 'SET',
DbAttributes::DB_QUERY_TEXT => 'set user:123 data EX 3600',
'db.system' => DbIncubatingAttributes::DB_SYSTEM_NAME_VALUE_REDIS,
'db.operation.pool' => 'SET',
'redis.pool' => 'semaphore',
]
)
->willReturn($this->spanScope);
Expand Down Expand Up @@ -257,15 +246,12 @@ public function testProcessWithComplexArguments(): void
->expects($this->once())
->method('startSpan')
->with(
$this->equalTo('Redis HMSET'),
$this->equalTo('HMSET'),
$this->equalTo(SpanKind::KIND_CLIENT),
[
DbAttributes::DB_SYSTEM_NAME => DbIncubatingAttributes::DB_SYSTEM_NAME_VALUE_REDIS,
DbAttributes::DB_OPERATION_NAME => 'HMSET',
DbAttributes::DB_QUERY_TEXT => 'hmset user:123 John 30 São Paulo',
'db.system' => DbIncubatingAttributes::DB_SYSTEM_NAME_VALUE_REDIS,
'redis.pool' => 'default',
'db.operation.pool' => 'HMSET',
]
)
->willReturn($this->spanScope);
Expand Down
14 changes: 5 additions & 9 deletions tests/Unit/Listener/DbQueryExecutedListenerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,19 +124,17 @@ public function testProcess(): void
->expects($this->once())
->method('startSpan')
->with(
$this->equalTo('postgresql SELECT users'),
$this->equalTo('SELECT users'),
$this->equalTo(SpanKind::KIND_CLIENT),
[
DbAttributes::DB_SYSTEM_NAME => DbAttributes::DB_SYSTEM_NAME_VALUE_POSTGRESQL,
DbAttributes::DB_COLLECTION_NAME => 'users',
DbAttributes::DB_NAMESPACE => 'testdb',
DbAttributes::DB_OPERATION_NAME => 'SELECT',
DbAttributes::DB_QUERY_TEXT => $sql,
DbAttributes::DB_QUERY_SUMMARY => 'SELECT users',
ServerAttributes::SERVER_ADDRESS => 'localhost',
ServerAttributes::SERVER_PORT => 8000,
'db.system' => DbAttributes::DB_SYSTEM_NAME_VALUE_POSTGRESQL,
'db.operation' => 'SELECT',
'db.sql.table' => 'users',
],
$this->isType('int')
)
Expand Down Expand Up @@ -196,19 +194,17 @@ public function testProcessWithBindingEnabled(): void
->expects($this->once())
->method('startSpan')
->with(
$this->equalTo('mysql SELECT users'),
$this->equalTo('SELECT users'),
$this->equalTo(SpanKind::KIND_CLIENT),
[
DbAttributes::DB_SYSTEM_NAME => DbAttributes::DB_SYSTEM_NAME_VALUE_MYSQL,
DbAttributes::DB_COLLECTION_NAME => 'users',
DbAttributes::DB_NAMESPACE => 'testdb',
DbAttributes::DB_OPERATION_NAME => 'SELECT',
DbAttributes::DB_QUERY_TEXT => 'SELECT id, name FROM users WHERE active = \'1\'',
DbAttributes::DB_QUERY_SUMMARY => 'SELECT users',
ServerAttributes::SERVER_ADDRESS => 'localhost',
ServerAttributes::SERVER_PORT => 8000,
'db.system' => DbAttributes::DB_SYSTEM_NAME_VALUE_MYSQL,
'db.operation' => 'SELECT',
'db.sql.table' => 'users',
],
$this->isType('int')
)
Expand Down Expand Up @@ -265,7 +261,7 @@ public function testProcessWithException(): void
->expects($this->once())
->method('startSpan')
->with(
$this->equalTo('microsoft.sql_server SELECT users')
$this->equalTo('SELECT users')
)
->willReturn($spanScope);

Expand Down
4 changes: 2 additions & 2 deletions tests/Unit/Middleware/TraceMiddlewareTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public function testProcessWithSuccessfulRequest(): void
$this->instrumentation->expects($this->once())
->method('startSpan')
->with(
'/users/{number}',
'GET /users/{number}',
SpanKind::KIND_SERVER,
[
HttpAttributes::HTTP_REQUEST_METHOD => 'GET',
Expand Down Expand Up @@ -204,7 +204,7 @@ public function testProcessWithUriMaskAndSuccessRequest(): void
$this->instrumentation->expects($this->once())
->method('startSpan')
->with(
'/users/{identifier}',
'GET /users/{identifier}',
SpanKind::KIND_SERVER,
[
HttpAttributes::HTTP_REQUEST_METHOD => 'GET',
Expand Down