laravel-db-query-sniffer maintained by andriichuk
Laravel DB Query Sniffer: SQL Query and Redis Logger
Laravel DB Query Sniffer is a Laravel SQL query logger and Redis command logger for local API debugging. Log Eloquent, query builder, and raw SQL queries to rotating files with request IDs, execution timings, and optional slow-query filters.
Capture queries from JSON APIs, mobile clients, Postman, browser requests, console commands, and queue jobs. No dashboard, migrations, or additional database tables are required.
What you can debug
- SQL query logging: inspect executed SQL, bound values, connection names, and execution times.
- Laravel API debugging: group queries by request ID, HTTP method, and URL path.
- Redis command logging: inspect commands and sanitized parameters alongside SQL logs.
- Slow query logging: record only SQL queries or Redis commands that meet a configurable duration threshold.
Requirements
- PHP 8.3 or later, with
mbstring. - Laravel 12 or 13.
Install the Laravel query logger
composer require andriichuk/laravel-db-query-sniffer --dev
The service provider is auto-discovered. Logging is restricted to the local environment by default. When LOG_DB_QUERIES is absent, the enable switch follows APP_DEBUG. Set it explicitly to control capture:
LOG_DB_QUERIES=true
DB_QUERY_LOG_ENABLED=true
REDIS_COMMAND_LOG_ENABLED=false
SQL query logging is enabled by default when the master switch allows capture. Redis command logging is opt-in: set REDIS_COMMAND_LOG_ENABLED=true to enable it. Both switches still respect the master switch and allowed environments.
The package supplies db and redis daily log channels with two-day retention when those channels do not already exist. Existing application channels are preserved. Files are written under storage/logs/db-YYYY-MM-DD.log and storage/logs/redis-YYYY-MM-DD.log.
Configuration publishing is optional:
php artisan vendor:publish --tag=db-query-sniffer-config
Debug SQL queries from Laravel API requests
SQL and Redis events are captured server-side, independently of the response format or client. Global middleware adds these fields while handling an HTTP request:
request_id: a generated identifier shared by that request's query records.request_method: the HTTP method.request_path: the URL path, excluding query parameters.
The response includes X-Query-Sniffer-Request-Id, allowing you to find its records in the logs. IDs are generated by the server; incoming headers are not trusted or reused. Set request_context to false to disable both correlation and the response header.
{
"query": "select * from users where id = 7",
"time": "1.24ms",
"duration_ms": 1.24,
"connection": "mysql",
"request_id": "31de9d5984414e1ca7282caa3ca0c6c1",
"request_method": "GET",
"request_path": "/api/users/7"
}
Context is cleared when middleware exits, including exception paths. Console commands and asynchronous queue jobs are logged without HTTP fields. Queries during application bootstrap, request termination, or streamed response callbacks are still captured but may not have HTTP context.
Log slow SQL queries and Redis commands
Every successfully executed Laravel SQL query is logged by default when capture is enabled. Redis commands are recorded after opting in with REDIS_COMMAND_LOG_ENABLED=true. To focus on slow database queries, set database.slow_only to true in the published configuration and choose a database.slow_ms threshold in milliseconds. Use redis.slow_only and redis.slow_ms independently for slow Redis commands.
SQL and Redis logging configuration
| Key | Default | Purpose |
|---|---|---|
enabled |
LOG_DB_QUERIES, falling back to APP_DEBUG |
Master switch |
environments |
['local'] |
Allowed environments; ['*'] allows all |
request_context |
true |
HTTP correlation fields and response header |
database.enabled |
true |
Capture SQL queries; override with DB_QUERY_LOG_ENABLED |
database.channel |
db |
Override with DB_QUERY_LOG_CHANNEL |
database.message |
SQL Query: |
Log message |
database.include_connection |
true |
Include the connection name |
database.slow_only |
false |
Capture every query unless enabled |
database.slow_ms |
100 |
Inclusive minimum duration when slow_only is enabled |
redis.enabled |
false |
Capture Redis commands; opt in with REDIS_COMMAND_LOG_ENABLED |
redis.channel |
redis |
Override with REDIS_COMMAND_LOG_CHANNEL |
redis.message |
Redis Command: |
Log message |
redis.slow_only |
false |
Capture every command unless enabled |
redis.slow_ms |
100 |
Inclusive minimum duration when slow_only is enabled |
bindings.max_string_length |
null |
Limit text in fallback bindings and Redis parameters |
bindings.binary_as_base64 |
true |
Include binary bytes as base64, or a size placeholder when disabled |
Both SQL and Redis records include the original time string and a numeric duration_ms field. Custom channel names must exist in config/logging.php. To use an existing logger, set the channel override to its name.
Reliability and scope
- SQL capture uses Laravel's
QueryExecutedevent. It records successfully executed statements through Laravel connections, including Eloquent, the query builder, and rawDBqueries. Direct PDO calls, other applications' queries, and failed statements are outside its scope. - Redis capture enables Laravel's command events. Direct calls to a Redis client that bypass Laravel's connection are outside its scope.
- When raw SQL interpolation fails, the package logs the statement and sanitized bindings instead. NUL-containing and invalid UTF-8 strings are encoded for JSON-safe logging.
- Queries issued by a log handler are deliberately excluded to prevent recursive logging. Handler failures go to PHP's error log without failing the application query.
- Raw SQL and Redis parameters can contain application data. This is a local development tool, and binary encoding is not redaction. Text truncation applies to fallback bindings and Redis parameters, not interpolated SQL or base64 binary values.
Replacing inline listeners
Remove the application's old SQL and Redis listeners and their binding sanitizer after installing this package, otherwise queries will be logged twice. Keep any application log channel configuration you want to preserve. If you previously published the package configuration, update its database.enabled and redis.enabled entries to use the new environment switches; an existing published configuration overrides package defaults. The LOG_DB_QUERIES environment switch continues to work; the old logging.log_db_queries configuration entry is no longer used.
Development
composer install
composer check
composer check runs Pint, maximum-level PHPStan without a baseline, and the test suite. CI checks Linux and Windows, PHP 8.3 through 8.5, and Laravel 12 and 13 using compatible Pest/Testbench versions. A separate coverage job enforces at least 95% source line coverage.
composer test-coverage -- --min=95
Coverage requires PCOV or Xdebug. See CONTRIBUTING for contribution guidelines and CHANGELOG for releases.
License
MIT. See LICENSE.