From 11389ed9f28c3bef2b7104cb43ad5bbe9a216c1e Mon Sep 17 00:00:00 2001 From: Tim MacDonald Date: Thu, 9 Jun 2022 16:22:55 +1000 Subject: [PATCH 1/6] allow handling query duration limit per connection --- src/Illuminate/Database/Connection.php | 73 +++++++ src/Illuminate/Queue/QueueServiceProvider.php | 7 + tests/Database/QueryDurationThresholdTest.php | 179 ++++++++++++++++++ 3 files changed, 259 insertions(+) create mode 100644 tests/Database/QueryDurationThresholdTest.php diff --git a/src/Illuminate/Database/Connection.php b/src/Illuminate/Database/Connection.php index af2a18b97a14..2e9fc33d65bf 100755 --- a/src/Illuminate/Database/Connection.php +++ b/src/Illuminate/Database/Connection.php @@ -2,6 +2,7 @@ namespace Illuminate\Database; +use Carbon\CarbonInterval; use Closure; use DateTimeInterface; use Doctrine\DBAL\Connection as DoctrineConnection; @@ -157,6 +158,20 @@ class Connection implements ConnectionInterface */ protected $loggingQueries = false; + /** + * The duration of all run queries in milliseconds. + * + * @var float + */ + protected $totalQueryDuration = 0.0; + + /** + * Query duration handlers. + * + * @var array + */ + protected $queryDurationHandlers = []; + /** * Indicates if the connection is in a "dry run". * @@ -755,6 +770,8 @@ protected function runQueryCallback($query, $bindings, Closure $callback) */ public function logQuery($query, $bindings, $time = null) { + $this->totalQueryDuration += $time ?? 0.0; + $this->event(new QueryExecuted($query, $bindings, $time, $this)); if ($this->loggingQueries) { @@ -773,6 +790,62 @@ protected function getElapsedTime($start) return round((microtime(true) - $start) * 1000, 2); } + /** + * Handle exceeding query duration threshold. + * + * @param \Carbon\CarbonInterval|float|int $threshold + * @param callable $handler + * @return void + */ + public function handleExceedingQueryDuration($threshold, $handler) + { + $threshold = $threshold instanceof CarbonInterval + ? $threshold->totalMilliseconds + : $threshold; + + $this->queryDurationHandlers[] = [ + 'not_yet_run' => true, + 'handler' => $handler, + ]; + + $key = count($this->queryDurationHandlers) - 1; + + $this->listen(function ($event) use ($threshold, $handler, $key) { + if ($this->queryDurationHandlers[$key]['not_yet_run'] && $this->totalQueryDuration() > $threshold) { + $handler($this); + + $this->queryDurationHandlers[$key]['not_yet_run'] = false; + } + }); + } + + public function restoreAlreadyRunQueryDurationHandlers() + { + foreach ($this->queryDurationHandlers as $key => $queryDurationHandler) { + $this->queryDurationHandlers[$key]['not_yet_run'] = true; + } + } + + /** + * Get the duration of all run queries in milliseconds. + * + * @return float + */ + public function totalQueryDuration() + { + return $this->totalQueryDuration; + } + + /** + * Reset the duration of all run queries. + * + * @return void + */ + public function resetTotalQueryDuration() + { + $this->totalQueryDuration = 0.0; + } + /** * Handle a query exception. * diff --git a/src/Illuminate/Queue/QueueServiceProvider.php b/src/Illuminate/Queue/QueueServiceProvider.php index 937af81ee988..740a63b2217b 100755 --- a/src/Illuminate/Queue/QueueServiceProvider.php +++ b/src/Illuminate/Queue/QueueServiceProvider.php @@ -200,6 +200,13 @@ protected function registerWorker() $app['log']->withoutContext(); } + if (method_exists($app['db'], 'getConnections')) { + foreach ($app['db']->getConnections() as $connection) { + $connection->resetTotalQueryDuration(); + $connection->restoreAlreadyRunQueryDurationHandlers(); + } + } + return $app->forgetScopedInstances(); }; diff --git a/tests/Database/QueryDurationThresholdTest.php b/tests/Database/QueryDurationThresholdTest.php new file mode 100644 index 000000000000..4f6386c52e91 --- /dev/null +++ b/tests/Database/QueryDurationThresholdTest.php @@ -0,0 +1,179 @@ +setEventDispatcher(new Dispatcher()); + $called = 0; + $connection->handleExceedingQueryDuration(CarbonInterval::milliseconds(1.1), function () use (&$called) { + $called++; + }); + + $connection->logQuery('xxxx', [], 1.0); + $connection->logQuery('xxxx', [], 0.1); + $this->assertSame(0, $called); + + $connection->logQuery('xxxx', [], 0.1); + $this->assertSame(1, $called); + } + + public function testItIsOnlyCalledOnce() + { + $connection = new Connection(new PDO('sqlite::memory:')); + $connection->setEventDispatcher(new Dispatcher()); + $called = 0; + $connection->handleExceedingQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { + $called++; + }); + + $connection->logQuery('xxxx', [], 1); + $connection->logQuery('xxxx', [], 1); + $connection->logQuery('xxxx', [], 1); + + $this->assertSame(1, $called); + } + + public function testItCanSpecifyMultipleHandlersWithTheSameIntervals() + { + $connection = new Connection(new PDO('sqlite::memory:')); + $connection->setEventDispatcher(new Dispatcher()); + $called = []; + $connection->handleExceedingQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { + $called['a'] = true; + }); + $connection->handleExceedingQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { + $called['b'] = true; + }); + + $connection->logQuery('xxxx', [], 1); + $connection->logQuery('xxxx', [], 1); + + $this->assertSame([ + 'a' => true, + 'b' => true, + ], $called); + } + + public function testItCanSpecifyMultipleHandlersWithDifferentIntervals() + { + $connection = new Connection(new PDO('sqlite::memory:')); + $connection->setEventDispatcher(new Dispatcher()); + $called = []; + $connection->handleExceedingQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { + $called['a'] = true; + }); + $connection->handleExceedingQueryDuration(CarbonInterval::milliseconds(2), function () use (&$called) { + $called['b'] = true; + }); + + $connection->logQuery('xxxx', [], 1); + $connection->logQuery('xxxx', [], 1); + $this->assertSame([ + 'a' => true, + ], $called); + + $connection->logQuery('xxxx', [], 1); + $this->assertSame([ + 'a' => true, + 'b' => true, + ], $called); + } + + public function testItHasAccessToConnectionInHandler() + { + $connection = new Connection(new PDO('sqlite::memory:'), '', '', ['name' => 'expected-name']); + $connection->setEventDispatcher(new Dispatcher()); + $name = null; + $connection->handleExceedingQueryDuration(CarbonInterval::milliseconds(1), function ($connection) use (&$name) { + $name = $connection->getName(); + }); + + $connection->logQuery('xxxx', [], 1); + $connection->logQuery('xxxx', [], 1); + + $this->assertSame('expected-name', $name); + } + + public function testItHasSpecifyThresholdWithFloat() + { + $connection = new Connection(new PDO('sqlite::memory:')); + $connection->setEventDispatcher(new Dispatcher()); + $called = false; + $connection->handleExceedingQueryDuration(1.1, function () use (&$called) { + $called = true; + }); + + $connection->logQuery('xxxx', [], 1.1); + $this->assertFalse($called); + + $connection->logQuery('xxxx', [], 0.1); + $this->assertTrue($called); + } + + public function testItHasSpecifyThresholdWithInt() + { + $connection = new Connection(new PDO('sqlite::memory:')); + $connection->setEventDispatcher(new Dispatcher()); + $called = false; + $connection->handleExceedingQueryDuration(2, function () use (&$called) { + $called = true; + }); + + $connection->logQuery('xxxx', [], 1.1); + $this->assertFalse($called); + + $connection->logQuery('xxxx', [], 1.0); + $this->assertTrue($called); + } + + public function testItCanResetTotalQueryDuration() + { + $connection = new Connection(new PDO('sqlite::memory:')); + $connection->setEventDispatcher(new Dispatcher()); + + $connection->logQuery('xxxx', [], 1.1); + $this->assertSame(1.1, $connection->totalQueryDuration()); + $connection->logQuery('xxxx', [], 1.1); + $this->assertSame(2.2, $connection->totalQueryDuration()); + + $connection->resetTotalQueryDuration(); + $this->assertSame(0.0, $connection->totalQueryDuration()); + } + + public function testItCanRestoreAlreadyRunHandlers() + { + $connection = new Connection(new PDO('sqlite::memory:')); + $connection->setEventDispatcher(new Dispatcher()); + $called = 0; + $connection->handleExceedingQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { + $called++; + }); + + $connection->logQuery('xxxx', [], 1); + $connection->logQuery('xxxx', [], 1); + $connection->logQuery('xxxx', [], 1); + $this->assertSame(1, $called); + + $connection->restoreAlreadyRunQueryDurationHandlers(); + $connection->logQuery('xxxx', [], 1); + $connection->logQuery('xxxx', [], 1); + $connection->logQuery('xxxx', [], 1); + $this->assertSame(2, $called); + + $connection->restoreAlreadyRunQueryDurationHandlers(); + $connection->logQuery('xxxx', [], 1); + $connection->logQuery('xxxx', [], 1); + $connection->logQuery('xxxx', [], 1); + $this->assertSame(3, $called); + } +} From 0455d3ee86f0845919c7e9825f6480f424e9d719 Mon Sep 17 00:00:00 2001 From: Tim MacDonald Date: Tue, 14 Jun 2022 11:38:31 +1000 Subject: [PATCH 2/6] add docblocks --- src/Illuminate/Database/Connection.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Illuminate/Database/Connection.php b/src/Illuminate/Database/Connection.php index 2e9fc33d65bf..dc5466bb4d11 100755 --- a/src/Illuminate/Database/Connection.php +++ b/src/Illuminate/Database/Connection.php @@ -819,6 +819,11 @@ public function handleExceedingQueryDuration($threshold, $handler) }); } + /** + * Restore all the query duration handlers that have already run. + * + * @return void + */ public function restoreAlreadyRunQueryDurationHandlers() { foreach ($this->queryDurationHandlers as $key => $queryDurationHandler) { From 8d45ebed92313464e66c04a40a57e7e8eafff5f5 Mon Sep 17 00:00:00 2001 From: Tim MacDonald Date: Tue, 14 Jun 2022 12:21:32 +1000 Subject: [PATCH 3/6] improve naming --- src/Illuminate/Database/Connection.php | 2 +- tests/Database/QueryDurationThresholdTest.php | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Illuminate/Database/Connection.php b/src/Illuminate/Database/Connection.php index dc5466bb4d11..6a36daf3d34b 100755 --- a/src/Illuminate/Database/Connection.php +++ b/src/Illuminate/Database/Connection.php @@ -797,7 +797,7 @@ protected function getElapsedTime($start) * @param callable $handler * @return void */ - public function handleExceedingQueryDuration($threshold, $handler) + public function handleExceedingCumulativeQueryDuration($threshold, $handler) { $threshold = $threshold instanceof CarbonInterval ? $threshold->totalMilliseconds diff --git a/tests/Database/QueryDurationThresholdTest.php b/tests/Database/QueryDurationThresholdTest.php index 4f6386c52e91..e11ee02f6d23 100644 --- a/tests/Database/QueryDurationThresholdTest.php +++ b/tests/Database/QueryDurationThresholdTest.php @@ -15,7 +15,7 @@ public function testItCanHandleReachingADurationThresholdInTheDb() $connection = new Connection(new PDO('sqlite::memory:')); $connection->setEventDispatcher(new Dispatcher()); $called = 0; - $connection->handleExceedingQueryDuration(CarbonInterval::milliseconds(1.1), function () use (&$called) { + $connection->handleExceedingCumulativeQueryDuration(CarbonInterval::milliseconds(1.1), function () use (&$called) { $called++; }); @@ -32,7 +32,7 @@ public function testItIsOnlyCalledOnce() $connection = new Connection(new PDO('sqlite::memory:')); $connection->setEventDispatcher(new Dispatcher()); $called = 0; - $connection->handleExceedingQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { + $connection->handleExceedingCumulativeQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { $called++; }); @@ -48,10 +48,10 @@ public function testItCanSpecifyMultipleHandlersWithTheSameIntervals() $connection = new Connection(new PDO('sqlite::memory:')); $connection->setEventDispatcher(new Dispatcher()); $called = []; - $connection->handleExceedingQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { + $connection->handleExceedingCumulativeQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { $called['a'] = true; }); - $connection->handleExceedingQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { + $connection->handleExceedingCumulativeQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { $called['b'] = true; }); @@ -69,10 +69,10 @@ public function testItCanSpecifyMultipleHandlersWithDifferentIntervals() $connection = new Connection(new PDO('sqlite::memory:')); $connection->setEventDispatcher(new Dispatcher()); $called = []; - $connection->handleExceedingQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { + $connection->handleExceedingCumulativeQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { $called['a'] = true; }); - $connection->handleExceedingQueryDuration(CarbonInterval::milliseconds(2), function () use (&$called) { + $connection->handleExceedingCumulativeQueryDuration(CarbonInterval::milliseconds(2), function () use (&$called) { $called['b'] = true; }); @@ -94,7 +94,7 @@ public function testItHasAccessToConnectionInHandler() $connection = new Connection(new PDO('sqlite::memory:'), '', '', ['name' => 'expected-name']); $connection->setEventDispatcher(new Dispatcher()); $name = null; - $connection->handleExceedingQueryDuration(CarbonInterval::milliseconds(1), function ($connection) use (&$name) { + $connection->handleExceedingCumulativeQueryDuration(CarbonInterval::milliseconds(1), function ($connection) use (&$name) { $name = $connection->getName(); }); @@ -109,7 +109,7 @@ public function testItHasSpecifyThresholdWithFloat() $connection = new Connection(new PDO('sqlite::memory:')); $connection->setEventDispatcher(new Dispatcher()); $called = false; - $connection->handleExceedingQueryDuration(1.1, function () use (&$called) { + $connection->handleExceedingCumulativeQueryDuration(1.1, function () use (&$called) { $called = true; }); @@ -125,7 +125,7 @@ public function testItHasSpecifyThresholdWithInt() $connection = new Connection(new PDO('sqlite::memory:')); $connection->setEventDispatcher(new Dispatcher()); $called = false; - $connection->handleExceedingQueryDuration(2, function () use (&$called) { + $connection->handleExceedingCumulativeQueryDuration(2, function () use (&$called) { $called = true; }); @@ -155,7 +155,7 @@ public function testItCanRestoreAlreadyRunHandlers() $connection = new Connection(new PDO('sqlite::memory:')); $connection->setEventDispatcher(new Dispatcher()); $called = 0; - $connection->handleExceedingQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { + $connection->handleExceedingCumulativeQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { $called++; }); From e1208fa3b88f005ebe928357947dec42c6c4d796 Mon Sep 17 00:00:00 2001 From: Tim MacDonald Date: Tue, 14 Jun 2022 12:32:22 +1000 Subject: [PATCH 4/6] ensure handler can trace all previous queries when logging is active --- src/Illuminate/Database/Connection.php | 2 +- tests/Database/QueryDurationThresholdTest.php | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Connection.php b/src/Illuminate/Database/Connection.php index 6a36daf3d34b..daf46a761bac 100755 --- a/src/Illuminate/Database/Connection.php +++ b/src/Illuminate/Database/Connection.php @@ -812,7 +812,7 @@ public function handleExceedingCumulativeQueryDuration($threshold, $handler) $this->listen(function ($event) use ($threshold, $handler, $key) { if ($this->queryDurationHandlers[$key]['not_yet_run'] && $this->totalQueryDuration() > $threshold) { - $handler($this); + $handler($this, $event); $this->queryDurationHandlers[$key]['not_yet_run'] = false; } diff --git a/tests/Database/QueryDurationThresholdTest.php b/tests/Database/QueryDurationThresholdTest.php index e11ee02f6d23..002d820ea87d 100644 --- a/tests/Database/QueryDurationThresholdTest.php +++ b/tests/Database/QueryDurationThresholdTest.php @@ -5,6 +5,7 @@ use Carbon\CarbonInterval; use Illuminate\Database\Connection; use Illuminate\Events\Dispatcher; +use Illuminate\Support\Arr; use PDO; use PHPUnit\Framework\TestCase; @@ -176,4 +177,26 @@ public function testItCanRestoreAlreadyRunHandlers() $connection->logQuery('xxxx', [], 1); $this->assertSame(3, $called); } + + public function testItCanAccessAllQueriesWhenQueryLoggingIsActive() + { + $connection = new Connection(new PDO('sqlite::memory:')); + $connection->setEventDispatcher(new Dispatcher()); + $connection->enableQueryLog(); + $queries = []; + $connection->handleExceedingCumulativeQueryDuration(CarbonInterval::milliseconds(2), function ($connection, $event) use (&$queries) { + $queries = Arr::pluck($connection->getQueryLog(), 'query'); + $queries[] = $event->sql; + }); + + $connection->logQuery('foo', [], 1); + $connection->logQuery('bar', [], 1); + $connection->logQuery('baz', [], 1); + + $this->assertSame([ + 'foo', + 'bar', + 'baz', + ], $queries); + } } From 0f38d8ec4620388f8aebdf3722ce5b9ad072af99 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Wed, 15 Jun 2022 08:35:38 -1000 Subject: [PATCH 5/6] formatting --- src/Illuminate/Database/Connection.php | 16 ++++++++-------- src/Illuminate/Queue/QueueServiceProvider.php | 2 +- tests/Database/QueryDurationThresholdTest.php | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Illuminate/Database/Connection.php b/src/Illuminate/Database/Connection.php index daf46a761bac..147f4150beb9 100755 --- a/src/Illuminate/Database/Connection.php +++ b/src/Illuminate/Database/Connection.php @@ -159,14 +159,14 @@ class Connection implements ConnectionInterface protected $loggingQueries = false; /** - * The duration of all run queries in milliseconds. + * The duration of all executed queries in milliseconds. * * @var float */ protected $totalQueryDuration = 0.0; /** - * Query duration handlers. + * All of the registered query duration handlers. * * @var array */ @@ -804,30 +804,30 @@ public function handleExceedingCumulativeQueryDuration($threshold, $handler) : $threshold; $this->queryDurationHandlers[] = [ - 'not_yet_run' => true, + 'has_run' => false, 'handler' => $handler, ]; $key = count($this->queryDurationHandlers) - 1; $this->listen(function ($event) use ($threshold, $handler, $key) { - if ($this->queryDurationHandlers[$key]['not_yet_run'] && $this->totalQueryDuration() > $threshold) { + if (! $this->queryDurationHandlers[$key]['has_run'] && $this->totalQueryDuration() > $threshold) { $handler($this, $event); - $this->queryDurationHandlers[$key]['not_yet_run'] = false; + $this->queryDurationHandlers[$key]['has_run'] = true; } }); } /** - * Restore all the query duration handlers that have already run. + * Allow all the query duration handlers to run again, even if they have already run. * * @return void */ - public function restoreAlreadyRunQueryDurationHandlers() + public function allowQueryDurationHandlersToRunAgain() { foreach ($this->queryDurationHandlers as $key => $queryDurationHandler) { - $this->queryDurationHandlers[$key]['not_yet_run'] = true; + $this->queryDurationHandlers[$key]['has_run'] = false; } } diff --git a/src/Illuminate/Queue/QueueServiceProvider.php b/src/Illuminate/Queue/QueueServiceProvider.php index 740a63b2217b..861ccb979102 100755 --- a/src/Illuminate/Queue/QueueServiceProvider.php +++ b/src/Illuminate/Queue/QueueServiceProvider.php @@ -203,7 +203,7 @@ protected function registerWorker() if (method_exists($app['db'], 'getConnections')) { foreach ($app['db']->getConnections() as $connection) { $connection->resetTotalQueryDuration(); - $connection->restoreAlreadyRunQueryDurationHandlers(); + $connection->allowQueryDurationHandlersToRunAgain(); } } diff --git a/tests/Database/QueryDurationThresholdTest.php b/tests/Database/QueryDurationThresholdTest.php index 002d820ea87d..a1471919e6ec 100644 --- a/tests/Database/QueryDurationThresholdTest.php +++ b/tests/Database/QueryDurationThresholdTest.php @@ -165,13 +165,13 @@ public function testItCanRestoreAlreadyRunHandlers() $connection->logQuery('xxxx', [], 1); $this->assertSame(1, $called); - $connection->restoreAlreadyRunQueryDurationHandlers(); + $connection->allowQueryDurationHandlersToRunAgain(); $connection->logQuery('xxxx', [], 1); $connection->logQuery('xxxx', [], 1); $connection->logQuery('xxxx', [], 1); $this->assertSame(2, $called); - $connection->restoreAlreadyRunQueryDurationHandlers(); + $connection->allowQueryDurationHandlersToRunAgain(); $connection->logQuery('xxxx', [], 1); $connection->logQuery('xxxx', [], 1); $connection->logQuery('xxxx', [], 1); From 9b15a1d2c18c9758c042eb23c0299345366f3efc Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Tue, 21 Jun 2022 09:34:00 -0500 Subject: [PATCH 6/6] method rename --- src/Illuminate/Database/Connection.php | 12 ++++-- tests/Database/QueryDurationThresholdTest.php | 38 +++++++++++++------ 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/src/Illuminate/Database/Connection.php b/src/Illuminate/Database/Connection.php index 147f4150beb9..d28250bf0fe7 100755 --- a/src/Illuminate/Database/Connection.php +++ b/src/Illuminate/Database/Connection.php @@ -20,6 +20,7 @@ use Illuminate\Database\Query\Processors\Processor; use Illuminate\Database\Schema\Builder as SchemaBuilder; use Illuminate\Support\Arr; +use Illuminate\Support\InteractsWithTime; use Illuminate\Support\Traits\Macroable; use PDO; use PDOStatement; @@ -30,6 +31,7 @@ class Connection implements ConnectionInterface use DetectsConcurrencyErrors, DetectsLostConnections, Concerns\ManagesTransactions, + InteractsWithTime, Macroable; /** @@ -791,14 +793,18 @@ protected function getElapsedTime($start) } /** - * Handle exceeding query duration threshold. + * Register a callback to be invoked when the connection queries for longer than a given amount of time. * - * @param \Carbon\CarbonInterval|float|int $threshold + * @param \DateTimeInterface|\Carbon\CarbonInterval|float|int $threshold * @param callable $handler * @return void */ - public function handleExceedingCumulativeQueryDuration($threshold, $handler) + public function whenQueryingForLongerThan($threshold, $handler) { + $threshold = $threshold instanceof DateTimeInterface + ? $this->secondsUntil($threshold) * 1000 + : $threshold; + $threshold = $threshold instanceof CarbonInterval ? $threshold->totalMilliseconds : $threshold; diff --git a/tests/Database/QueryDurationThresholdTest.php b/tests/Database/QueryDurationThresholdTest.php index a1471919e6ec..06fb996c974a 100644 --- a/tests/Database/QueryDurationThresholdTest.php +++ b/tests/Database/QueryDurationThresholdTest.php @@ -16,7 +16,7 @@ public function testItCanHandleReachingADurationThresholdInTheDb() $connection = new Connection(new PDO('sqlite::memory:')); $connection->setEventDispatcher(new Dispatcher()); $called = 0; - $connection->handleExceedingCumulativeQueryDuration(CarbonInterval::milliseconds(1.1), function () use (&$called) { + $connection->whenQueryingForLongerThan(CarbonInterval::milliseconds(1.1), function () use (&$called) { $called++; }); @@ -33,7 +33,23 @@ public function testItIsOnlyCalledOnce() $connection = new Connection(new PDO('sqlite::memory:')); $connection->setEventDispatcher(new Dispatcher()); $called = 0; - $connection->handleExceedingCumulativeQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { + $connection->whenQueryingForLongerThan(CarbonInterval::milliseconds(1), function () use (&$called) { + $called++; + }); + + $connection->logQuery('xxxx', [], 1); + $connection->logQuery('xxxx', [], 1); + $connection->logQuery('xxxx', [], 1); + + $this->assertSame(1, $called); + } + + public function testItIsOnlyCalledOnceWhenGivenDateTime() + { + $connection = new Connection(new PDO('sqlite::memory:')); + $connection->setEventDispatcher(new Dispatcher()); + $called = 0; + $connection->whenQueryingForLongerThan(now()->addMilliseconds(1), function () use (&$called) { $called++; }); @@ -49,10 +65,10 @@ public function testItCanSpecifyMultipleHandlersWithTheSameIntervals() $connection = new Connection(new PDO('sqlite::memory:')); $connection->setEventDispatcher(new Dispatcher()); $called = []; - $connection->handleExceedingCumulativeQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { + $connection->whenQueryingForLongerThan(CarbonInterval::milliseconds(1), function () use (&$called) { $called['a'] = true; }); - $connection->handleExceedingCumulativeQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { + $connection->whenQueryingForLongerThan(CarbonInterval::milliseconds(1), function () use (&$called) { $called['b'] = true; }); @@ -70,10 +86,10 @@ public function testItCanSpecifyMultipleHandlersWithDifferentIntervals() $connection = new Connection(new PDO('sqlite::memory:')); $connection->setEventDispatcher(new Dispatcher()); $called = []; - $connection->handleExceedingCumulativeQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { + $connection->whenQueryingForLongerThan(CarbonInterval::milliseconds(1), function () use (&$called) { $called['a'] = true; }); - $connection->handleExceedingCumulativeQueryDuration(CarbonInterval::milliseconds(2), function () use (&$called) { + $connection->whenQueryingForLongerThan(CarbonInterval::milliseconds(2), function () use (&$called) { $called['b'] = true; }); @@ -95,7 +111,7 @@ public function testItHasAccessToConnectionInHandler() $connection = new Connection(new PDO('sqlite::memory:'), '', '', ['name' => 'expected-name']); $connection->setEventDispatcher(new Dispatcher()); $name = null; - $connection->handleExceedingCumulativeQueryDuration(CarbonInterval::milliseconds(1), function ($connection) use (&$name) { + $connection->whenQueryingForLongerThan(CarbonInterval::milliseconds(1), function ($connection) use (&$name) { $name = $connection->getName(); }); @@ -110,7 +126,7 @@ public function testItHasSpecifyThresholdWithFloat() $connection = new Connection(new PDO('sqlite::memory:')); $connection->setEventDispatcher(new Dispatcher()); $called = false; - $connection->handleExceedingCumulativeQueryDuration(1.1, function () use (&$called) { + $connection->whenQueryingForLongerThan(1.1, function () use (&$called) { $called = true; }); @@ -126,7 +142,7 @@ public function testItHasSpecifyThresholdWithInt() $connection = new Connection(new PDO('sqlite::memory:')); $connection->setEventDispatcher(new Dispatcher()); $called = false; - $connection->handleExceedingCumulativeQueryDuration(2, function () use (&$called) { + $connection->whenQueryingForLongerThan(2, function () use (&$called) { $called = true; }); @@ -156,7 +172,7 @@ public function testItCanRestoreAlreadyRunHandlers() $connection = new Connection(new PDO('sqlite::memory:')); $connection->setEventDispatcher(new Dispatcher()); $called = 0; - $connection->handleExceedingCumulativeQueryDuration(CarbonInterval::milliseconds(1), function () use (&$called) { + $connection->whenQueryingForLongerThan(CarbonInterval::milliseconds(1), function () use (&$called) { $called++; }); @@ -184,7 +200,7 @@ public function testItCanAccessAllQueriesWhenQueryLoggingIsActive() $connection->setEventDispatcher(new Dispatcher()); $connection->enableQueryLog(); $queries = []; - $connection->handleExceedingCumulativeQueryDuration(CarbonInterval::milliseconds(2), function ($connection, $event) use (&$queries) { + $connection->whenQueryingForLongerThan(CarbonInterval::milliseconds(2), function ($connection, $event) use (&$queries) { $queries = Arr::pluck($connection->getQueryLog(), 'query'); $queries[] = $event->sql; });