Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[9.x] Allow handling cumulative query duration limit per DB connection #42744

Merged
merged 6 commits into from
Jun 21, 2022
Merged
Changes from 1 commit
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
Prev Previous commit
method rename
taylorotwell committed Jun 21, 2022
commit 9b15a1d2c18c9758c042eb23c0299345366f3efc
12 changes: 9 additions & 3 deletions src/Illuminate/Database/Connection.php
Original file line number Diff line number Diff line change
@@ -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;
38 changes: 27 additions & 11 deletions tests/Database/QueryDurationThresholdTest.php
Original file line number Diff line number Diff line change
@@ -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;
});