addDatabaseQuery does not increase queries count
We have converted a legacy project to Laravel and still have many vanilla DB fetches.
We created a wrapper above PDOStatement to log all queries, excluding those made by Laravel's query builder. This works well, but I noticed that the total query count is incorrect. It only counts when the Laravel query event is triggered, but not when calling clock()->addDatabaseQuery as described in the docs.
Is there a way to increase the count? Instead of using addDatabaseQuery, I tried manually triggering the Laravel query event, but then I cannot pass options like trace skipping.
Any advice on how to properly increase the count?
Hey, it would totally make sense if the addDatabaseQuery helper incremented query counts, I'll look into adding it for the next release.
As a workaround for now, you can increment the database queries yourself in your own wrapper like this:
$request = clock()->request();
// Increment the total query count
$request->databaseQueriesCount++;
// Increment query count of a particular type
$request->databaseSelects++;
$request->databaseInserts++;
$request->databaseUpdates++;
$request->databaseDeletes++;
$request->databaseOthers++;
Thanks for the workaround.
Its a littly hacky but does the job. Here to share my code, which tracks all PDO executes:
<?php
namespace App\Database;
use PDOStatement;
use Clockwork\Helpers\{ Serializer, StackTrace };
class TrackPDOStatement extends PDOStatement
{
protected function __construct()
{
}
public function execute($params = null): bool
{
return $this->trackSql(fn() => parent::execute($params), $this->queryString, $params ?? [], 2);
}
private function trackSql(callable $callback, string $query, array $bindings, int $tracesSkip = 0)
{
if (str_starts_with(strtolower(trim($query)), 'set ')) {
return $callback();
}
$trace = (new Serializer(['tracesSkip' => $tracesSkip]))->trace(StackTrace::get());
$containsQueryBuilder = false;
foreach ($trace as $traceStep) {
if (isset($traceStep['call']) && str_contains($traceStep['call'], 'Illuminate\Database\Query\Builder')) {
$containsQueryBuilder = true;
break;
}
}
$time = microtime(true);
$result = $callback();
$executionTime = (microtime(true) - $time) * 1000;
// Add the database query only if "Illuminate\Database\Query\Builder" is not in the call stack
if (!$containsQueryBuilder) {
clock()->addDatabaseQuery($query, $bindings, $executionTime, ['trace' => $trace, 'model' => 'PDO', 'connection' => 'mysql']);
// See https://github.com/itsgoingd/clockwork/issues/703#issuecomment-2177763487
// Maybe fixed in future
$request = clock()->request();
$sql = ltrim($query);
$request->databaseQueriesCount++;
if (preg_match('/^select\b/i', $sql)) {
$request->databaseSelects++;
} elseif (preg_match('/^insert\b/i', $sql)) {
$request->databaseInserts++;
} elseif (preg_match('/^update\b/i', $sql)) {
$request->databaseUpdates++;
} elseif (preg_match('/^delete\b/i', $sql)) {
$request->databaseDeletes++;
} else {
$request->databaseOthers++;
}
}
return $result;
}
}
in laravel i just add to DatabaseProvider
class DatabaseProvider extends ServiceProvider
{
public function register(): void
{
if ($this->app->environment('local')) {
config()->set('database.connections.mysql.options.' . PDO::ATTR_STATEMENT_CLASS, [TrackPDOStatement::class, []]);
}
}
}
This is now implemented in master (https://github.com/itsgoingd/clockwork/commit/bbcefdf1e32540e9a2de5fbd1eacbb77d3f50bda) and will be released in Clockwork 5.3.