diff --git a/config/sentry.php b/config/sentry.php index 6476e31b..4fe68262 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -67,6 +67,9 @@ // Capture SQL queries as spans 'sql_queries' => env('SENTRY_TRACE_SQL_QUERIES_ENABLED', true), + // Capture SQL query bindings (parameters) in SQL query spans + 'sql_bindings' => env('SENTRY_TRACE_SQL_BINDINGS_ENABLED', false), + // Capture where the SQL query originated from on the SQL query spans 'sql_origin' => env('SENTRY_TRACE_SQL_ORIGIN_ENABLED', true), diff --git a/src/Sentry/Laravel/Tracing/EventHandler.php b/src/Sentry/Laravel/Tracing/EventHandler.php index b184ca82..aeb47814 100644 --- a/src/Sentry/Laravel/Tracing/EventHandler.php +++ b/src/Sentry/Laravel/Tracing/EventHandler.php @@ -41,6 +41,13 @@ class EventHandler */ private $traceSqlQueries; + /** + * Indicates if we should add query bindings to query spans. + * + * @var bool + */ + private $traceSqlBindings; + /** * Indicates if we should we add SQL query origin data to query spans. * @@ -82,6 +89,7 @@ class EventHandler public function __construct(array $config) { $this->traceSqlQueries = ($config['sql_queries'] ?? true) === true; + $this->traceSqlBindings = ($config['sql_bindings'] ?? true) === true; $this->traceSqlQueryOrigins = ($config['sql_origin'] ?? true) === true; $this->traceQueueJobs = ($config['queue_jobs'] ?? false) === true; @@ -166,6 +174,12 @@ protected function queryExecutedHandler(DatabaseEvents\QueryExecuted $query): vo $context->setStartTimestamp(microtime(true) - $query->time / 1000); $context->setEndTimestamp($context->getStartTimestamp() + $query->time / 1000); + if ($this->traceSqlBindings) { + $context->setData(array_merge($context->getData(), [ + 'db.sql.bindings' => $query->bindings + ])); + } + if ($this->traceSqlQueryOrigins) { $queryOrigin = $this->resolveQueryOriginFromBacktrace(); diff --git a/test/Sentry/Features/DatabaseIntegrationTest.php b/test/Sentry/Features/DatabaseIntegrationTest.php index 3c32aec0..64504bae 100644 --- a/test/Sentry/Features/DatabaseIntegrationTest.php +++ b/test/Sentry/Features/DatabaseIntegrationTest.php @@ -85,11 +85,41 @@ public function testSpanIsCreatedForSqliteConnectionQuery(): void $this->assertNull($span->getData()['server.port']); } - private function executeQueryAndRetrieveSpan(string $query): Span + public function testSqlBindingsAreRecordedWhenEnabled(): void + { + $this->resetApplicationWithConfig([ + 'sentry.tracing.sql_bindings' => true, + ]); + + $span = $this->executeQueryAndRetrieveSpan( + $query = 'SELECT %', + $bindings = ['1'] + ); + + $this->assertEquals($query, $span->getDescription()); + $this->assertEquals($bindings, $span->getData()['db.sql.bindings']); + } + + public function testSqlBindingsAreRecordedWhenDisabled(): void + { + $this->resetApplicationWithConfig([ + 'sentry.tracing.sql_bindings' => false, + ]); + + $span = $this->executeQueryAndRetrieveSpan( + $query = 'SELECT %', + ['1'] + ); + + $this->assertEquals($query, $span->getDescription()); + $this->assertFalse(isset($span->getData()['db.sql.bindings'])); + } + + private function executeQueryAndRetrieveSpan(string $query, array $bindings = []): Span { $transaction = $this->startTransaction(); - $this->dispatchLaravelEvent(new QueryExecuted($query, [], 123, DB::connection())); + $this->dispatchLaravelEvent(new QueryExecuted($query, $bindings, 123, DB::connection())); $spans = $transaction->getSpanRecorder()->getSpans(); diff --git a/test/Sentry/Tracing/EventHandlerTest.php b/test/Sentry/Tracing/EventHandlerTest.php index 9c41e340..db4ceb31 100644 --- a/test/Sentry/Tracing/EventHandlerTest.php +++ b/test/Sentry/Tracing/EventHandlerTest.php @@ -3,9 +3,8 @@ namespace Sentry\Laravel\Tests\Tracing; use ReflectionClass; -use Sentry\Laravel\Tests\TestCase; -use Sentry\Laravel\Tracing\BacktraceHelper; use RuntimeException; +use Sentry\Laravel\Tests\TestCase; use Sentry\Laravel\Tracing\EventHandler; class EventHandlerTest extends TestCase