ConnectionInterface aligns seamlessly with Laravel’s middleware, service container, and dependency injection paradigms. This enables non-invasive profiling without modifying Rowcast’s core or Laravel’s query layer, reducing architectural friction.QueryProfileStore interface allows for custom storage backends (e.g., database, Redis, or even third-party services like Datadog). This is a best practice for scalability and integration with existing observability stacks, though it requires upfront design for production-grade implementations.Connection with ConnectionProfiler.QueryProfileStore (default: in-memory).slowQueryThresholdMs).$this->app->singleton(AsceticSoft\Rowcast\ConnectionInterface::class, function ($app) {
$inner = $app->make(AsceticSoft\Rowcast\Connection::class);
$profiler = new RowcastProfiler(
new DatabaseQueryProfileStore(),
new DefaultParameterSanitizer(),
slowQueryThresholdMs: 50.0
);
return new ConnectionProfiler($inner, $profiler);
});
ConnectionInterface.DefaultParameterSanitizer strips sensitive data but may also mask useful debug information (e.g., table/column names in dynamic queries). Mitigation: Customize sanitization rules or log raw SQL separately for debugging.InMemoryQueryProfileStore is not persistent or thread-safe. Production use requires a custom store, adding complexity. Mitigation: Provide a database-backed store as part of the integration.DefaultParameterSanitizer sufficient, or does the project need custom sanitization rules?ConnectionInterface decorator is fully compatible with Laravel’s service container, middleware, and database layers. It can be seamlessly injected into existing Rowcast-based applications without disrupting workflows.ConnectionInterface), the package integrates without friction with Laravel’s underlying infrastructure.QueryProfileStore backends can feed data to Prometheus, Datadog, or New Relic.InMemoryQueryProfileStore for testing.$this->app->bind(
AsceticSoft\Rowcast\ConnectionInterface::class,
function ($app) {
$inner = $app->make(AsceticSoft\Rowcast\Connection::class);
$profiler = new RowcastProfiler(
new DatabaseQueryProfileStore(), // Custom store
new CustomParameterSanitizer(), // Project-specific rules
slowQueryThresholdMs: 100.0,
maxQueries: 1000
);
return new ConnectionProfiler($inner, $profiler);
}
);
class DatabaseQueryProfileStore implements QueryProfileStore {
public function addProfile(QueryProfile $profile) {
DB::table('query_profiles')->insert([
'sql' => $profile->sql,
'duration_ms' => $profile->durationMs,
'parameters' => json_encode($profile->parameters),
'created_at' => now(),
'context' => request()->header('X-Request-ID'), // Correlate with traces
]);
}
public function getProfiles(): array {
return DB::table('query_profiles')
->orderBy('created_at', 'desc')
->limit(1000)
->get()
->map(fn ($record) => new QueryProfile(
$record->sql,
$record->duration_ms,
json_decode($record->parameters, true)
));
}
}
Telescope::channel('rowcast-queries', function () {
return DatabaseQueryProfileStore::getProfiles();
});
$profiler->setSlowQueryCallback(function (QueryProfile $profile) {
How can I help you explore Laravel packages today?