diff --git a/src/Sentry/Laravel/EventHandler.php b/src/Sentry/Laravel/EventHandler.php index e6c3add1..4b838453 100644 --- a/src/Sentry/Laravel/EventHandler.php +++ b/src/Sentry/Laravel/EventHandler.php @@ -239,7 +239,7 @@ protected function queryExecutedHandler(DatabaseEvents\QueryExecuted $query): vo Integration::addBreadcrumb(new Breadcrumb( Breadcrumb::LEVEL_INFO, Breadcrumb::TYPE_DEFAULT, - 'sql.query', + 'db.sql.query', $query->sql, $data )); @@ -287,12 +287,12 @@ protected function httpClientResponseReceivedHandler(HttpClientEvents\ResponseRe null, [ 'url' => $this->getPartialUri($fullUri), - 'method' => $event->request->method(), - 'status_code' => $event->response->status(), + 'http.request.method' => $event->request->method(), + 'http.response.status_code' => $event->response->status(), 'http.query' => $fullUri->getQuery(), 'http.fragment' => $fullUri->getFragment(), - 'request_body_size' => $event->request->toPsrRequest()->getBody()->getSize(), - 'response_body_size' => $event->response->toPsrResponse()->getBody()->getSize(), + 'http.request.body.size' => $event->request->toPsrRequest()->getBody()->getSize(), + 'http.response.body.size' => $event->response->toPsrResponse()->getBody()->getSize(), ] )); } @@ -312,10 +312,10 @@ protected function httpClientConnectionFailedHandler(HttpClientEvents\Connection null, [ 'url' => $this->getPartialUri($fullUri), - 'method' => $event->request->method(), + 'http.request.method' => $event->request->method(), 'http.query' => $fullUri->getQuery(), 'http.fragment' => $fullUri->getFragment(), - 'request_body_size' => $event->request->toPsrRequest()->getBody()->getSize(), + 'http.request.body.size' => $event->request->toPsrRequest()->getBody()->getSize(), ] )); } diff --git a/src/Sentry/Laravel/Tracing/EventHandler.php b/src/Sentry/Laravel/Tracing/EventHandler.php index 18855e41..128b4ace 100644 --- a/src/Sentry/Laravel/Tracing/EventHandler.php +++ b/src/Sentry/Laravel/Tracing/EventHandler.php @@ -182,6 +182,12 @@ protected function queryExecutedHandler(DatabaseEvents\QueryExecuted $query): vo $context = new SpanContext(); $context->setOp('db.sql.query'); $context->setDescription($query->sql); + $context->setData([ + 'db.name' => $query->connection->getDatabaseName(), + 'db.system' => $query->connection->getDriverName(), + 'server.address' => $query->connection->getConfig('host'), + 'server.port' => $query->connection->getConfig('port'), + ]); $context->setStartTimestamp(microtime(true) - $query->time / 1000); $context->setEndTimestamp($context->getStartTimestamp() + $query->time / 1000); @@ -189,7 +195,9 @@ protected function queryExecutedHandler(DatabaseEvents\QueryExecuted $query): vo $queryOrigin = $this->resolveQueryOriginFromBacktrace(); if ($queryOrigin !== null) { - $context->setData(['db.sql.origin' => $queryOrigin]); + $context->setData(array_merge($context->getData(), [ + 'db.sql.origin' => $queryOrigin + ])); } } @@ -302,7 +310,7 @@ protected function httpClientRequestSendingHandler(HttpClientEvents\RequestSendi $context->setDescription($event->request->method() . ' ' . $partialUri); $context->setData([ 'url' => $partialUri, - 'method' => $event->request->method(), + 'http.request.method' => $event->request->method(), 'http.query' => $fullUri->getQuery(), 'http.fragment' => $fullUri->getFragment(), ]); diff --git a/src/Sentry/Laravel/Tracing/Middleware.php b/src/Sentry/Laravel/Tracing/Middleware.php index f909ea07..117e2411 100644 --- a/src/Sentry/Laravel/Tracing/Middleware.php +++ b/src/Sentry/Laravel/Tracing/Middleware.php @@ -176,7 +176,7 @@ private function startTransaction(Request $request, HubInterface $sentry): void $context->setData([ 'url' => $requestPath, - 'method' => strtoupper($request->method()), + 'http.request.method' => strtoupper($request->method()), ]); $transaction = $sentry->startTransaction($context); diff --git a/test/Sentry/Features/DatabaseIntegrationTest.php b/test/Sentry/Features/DatabaseIntegrationTest.php new file mode 100644 index 00000000..cefd030d --- /dev/null +++ b/test/Sentry/Features/DatabaseIntegrationTest.php @@ -0,0 +1,106 @@ +set('database.default', 'mysql'); + $app['config']->set('database.connections.mysql', [ + 'driver' => 'mysql', + 'host' => 'host-mysql', + 'port' => 3306, + 'username' => 'user-mysql', + 'password' => 'password', + 'database' => 'db-mysql', + ]); + } + + protected function usesMySQLFromUrl($app): void + { + $app['config']->set('database.default', 'mysqlurl'); + $app['config']->set('database.connections.mysqlurl', [ + 'driver' => 'mysql', + 'url' => 'mysql://user-mysqlurl:password@host-mysqlurl:3307/db-mysqlurl', + ]); + } + + protected function usesInMemorySqlite($app): void + { + $app['config']->set('database.default', 'inmemory'); + $app['config']->set('database.connections.inmemory', [ + 'driver' => 'sqlite', + 'database' => ':memory:', + ]); + } + + /** + * @define-env usesMySQL + */ + public function testSpanIsCreatedForMySQLConnectionQuery(): void + { + $span = $this->executeQueryAndRetrieveSpan( + $query = 'SELECT "mysql"' + ); + + $this->assertEquals($query, $span->getDescription()); + $this->assertEquals('db.sql.query', $span->getOp()); + $this->assertEquals('host-mysql', $span->getData()['server.address']); + $this->assertEquals(3306, $span->getData()['server.port']); + } + + /** + * @define-env usesMySQLFromUrl + */ + public function testSpanIsCreatedForMySQLUrlConnectionQuery(): void + { + $span = $this->executeQueryAndRetrieveSpan( + $query = 'SELECT "mysqlurl"' + ); + + $this->assertEquals($query, $span->getDescription()); + $this->assertEquals('db.sql.query', $span->getOp()); + $this->assertEquals('host-mysqlurl', $span->getData()['server.address']); + $this->assertEquals(3307, $span->getData()['server.port']); + } + + /** + * @define-env usesInMemorySqlite + */ + public function testSpanIsCreatedForSqliteConnectionQuery(): void + { + $span = $this->executeQueryAndRetrieveSpan( + $query = 'SELECT "inmemory"' + ); + + $this->assertEquals($query, $span->getDescription()); + $this->assertEquals('db.sql.query', $span->getOp()); + $this->assertNull($span->getData()['server.address']); + $this->assertNull($span->getData()['server.port']); + } + + private function executeQueryAndRetrieveSpan(string $query): Span + { + $hub = $this->getHubFromContainer(); + + $transaction = $hub->startTransaction(new TransactionContext); + $transaction->initSpanRecorder(); + + $this->getCurrentScope()->setSpan($transaction); + + $this->dispatchLaravelEvent(new QueryExecuted($query, [], 123, DB::connection())); + + $spans = $transaction->getSpanRecorder()->getSpans(); + + $this->assertCount(2, $spans); + + return $spans[1]; + } +} diff --git a/test/Sentry/Features/HttpClientIntegrationTest.php b/test/Sentry/Features/HttpClientIntegrationTest.php index 2acb03b0..8e217b73 100644 --- a/test/Sentry/Features/HttpClientIntegrationTest.php +++ b/test/Sentry/Features/HttpClientIntegrationTest.php @@ -31,11 +31,11 @@ public function testHttpClientBreadcrumbIsRecordedForResponseReceivedEvent(): vo $metadata = $this->getLastBreadcrumb()->getMetadata(); - $this->assertEquals('GET', $metadata['method']); + $this->assertEquals('GET', $metadata['http.request.method']); $this->assertEquals('https://example.com', $metadata['url']); - $this->assertEquals(200, $metadata['status_code']); - $this->assertEquals(7, $metadata['request_body_size']); - $this->assertEquals(8, $metadata['response_body_size']); + $this->assertEquals(200, $metadata['http.response.status_code']); + $this->assertEquals(7, $metadata['http.request.body.size']); + $this->assertEquals(8, $metadata['http.response.body.size']); } public function testHttpClientBreadcrumbDoesntConsumeBodyStream(): void