web-chefs / db-lojack
Laravel 数据库查询记录器和调试助手。
Requires
- php: ~5.6|~7.0
- laravel/framework: 5.*
- symfony/stopwatch: >=3.4
Requires (Dev)
- doctrine/dbal: ^2.5
- phpunit/phpunit: ~5.7
- squizlabs/php_codesniffer: ^2.3
- web-chefs/laravel-app-spawn: ^1.0
This package is auto-updated.
Last update: 2024-09-11 17:20:05 UTC
README
支持基本参数替换的 Laravel 数据库查询记录器和调试助手。
特性
- 基本的查询绑定替换
- 中间件和监听器处理程序
- 在生产环境和预发布环境中隐藏安全信息
- 请求查询计数记录
- 记录网页和控制台查询
- DBLog 门面,便于开发者查询调试
- 可配置
- 默认文本记录器支持日志文件轮转,无需依赖其他包
版本
已验证为正常工作
- Laravel 5.3 在 PHP 5.6 上
- Laravel 5.4 在 PHP 5.6, 7.0 上
- Laravel 5.5 在 PHP 7.0, 7.1 上
- Laravel 5.6 在 PHP 7.1 上
安装
通过 Composer
$ composer require web-chefs/db-lojack
将服务提供者添加到 config/app.php
'providers' => [ // Other Service Providers WebChefs\DBLoJack\DBLoJackServiceProvider::class, ];
可选地添加 DB LoJack Facade
'aliases' => [ 'DBLog' => WebChefs\DBLoJack\Facades\DbLogger::class, ];
处理程序
有两种处理程序可用,各有优缺点。
中间件(默认)
使用 Laravel HTTP 内核中间件来启用数据库查询记录,并在请求结束时记录所有查询作为单个块。
优点
- 将所有查询记录为单个块,允许您跟踪特定请求的查询
- 记录每个查询的查询时间(毫秒)
缺点
- 不适用于控制台命令(请参阅事件监听器)
- 如果请求中执行了大量查询,Laravel 对查询数据的跟踪可能会消耗大量内存,中间件方法不适用于长时间运行的过程或请求
- 如果不是第一个中间件,一些查询可能会丢失,应将其设置为高于任何执行数据库调用的中间件
设置
将处理程序配置为 middleware
。
将中间件添加到 App\Http\Kernel
protected $middleware = [ \WebChefs\DBLoJack\Middleware\QueryLoggingMiddleware::class, ];
事件监听器
使用 Laravel 事件监听器数据库事件。无论配置如何,此方法在控制台/artisan 应用程序中使用。
优点
- 一次处理一个查询,因此更节省内存
- 记录所有查询,不受配置影响
缺点
- 不一致地记录查询时间,通常由 Laravel 提供
- 对于单个请求的多个查询,记录为单独的,使其更难以跟踪到特定请求
设置
将处理程序配置为 listener
。
开发者使用(门面)
# Get formated query builder query $query = DB::table('users')->where('id', 1); print DBLog::formatQuery($query); # Get formated model query $model = \App\User::where('id', 1); print DBLog::formatQuery($model); # Format raw sql and bindings print DBLog::formatSql($query->toSql(), $query->getBindings()); # Logs single query or model DBLog::logQuery($query); # Debug query using dd(); DBLog::debugQuery($query); # Check if enabled DBLog::isEnabled(); # Check if will log for specific handler DBLog::isLogging('middleware'); # Get configured handler DBLog::getHandler(); # Check if an object is queryable and loggable throwing an exception DBLog::isQueryable($query); # Check if an object is queryable and loggable returning a boolean DBLog::isQueryable($query, false);
日志
查询日志
查询日志将单个查询记录到每天轮转的文本文件中。
例如: storage/logs/db/db_query.console.2018-06-06.log
。
性能看门狗日志
一个 PerformanceWatchdog
类将收集统计信息和查询,如果达到或超过指标阈值,则写入日志。
汇总日志
记录每个请求的总计一行。
20180608 12:06:12: Time: 5ms, Version: 7.0.14, DB Queries: 8, Memory: 14 MiB, Request: "CLI: ./vendor/bin/phpunit"
20180608 12:07:35: Time: 10ms, Version: 7.0.14, DB Queries: 25, Memory: 35 MiB, Request: "https:///login"
详细日志
每个运行的查询的日志,包括每个查询的计数器和每个唯一路径到该查询的迷你堆栈跟踪。
START===========================================================================
Date: 20180608 12:06:12
Time: 54ms
Version: 7.0.14
Request: "CLI: ./vendor/bin/phpunit"
Memory Start: 10 MiB
Memory Current: 14 MiB
Memory Usage: 3.18 MiB
Memory Max Peak: 13.18 MiB
DB Queries: 8
--------------------------------------------------------------------------------
Usage Count: 2
Trace Count: 2
--------------------------------------------------------------------------------
select * from sqlite_master where type = 'table' and name = ?
--------------------------------------------------------------------------------
1) /var/www/site/vendor/WebChefs/DB-LoJack/src/PerformanceWatchdog.php(497): Illuminate\Support\Facades\Facade::__callStatic('simpleTrace', Array)
2) /var/www/site/vendor/WebChefs/DB-LoJack/src/DBLoJackServiceProvider.php(70): WebChefs\DBLoJack\PerformanceWatchdog->logQuery('select * from s...')
3) /var/www/site/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(348): WebChefs\DBLoJack\DBLoJackServiceProvider->WebChefs\DBLoJack\{closure}(Object(Illuminate\Database\Events\QueryExecuted))
4) /var/www/site/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(199): Illuminate\Events\Dispatcher->Illuminate\Events\{closure}('Illuminate\\Data...', Array)
5) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Connection.php(808): Illuminate\Events\Dispatcher->dispatch('Illuminate\\Data...')
6) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Connection.php(665): Illuminate\Database\Connection->event(Object(Illuminate\Database\Events\QueryExecuted))
7) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Connection.php(618): Illuminate\Database\Connection->logQuery('select * from s...', Array, 0.52)
8) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Connection.php(326): Illuminate\Database\Connection->run('select * from s...', Array, Object(Closure))
9) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Schema/Builder.php(72): Illuminate\Database\Connection->select('select * from s...', Array)
10) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Migrations/DatabaseMigrationRepository.php(154): Illuminate\Database\Schema\Builder->hasTable('migrations')
1) /var/www/site/vendor/WebChefs/DB-LoJack/src/PerformanceWatchdog.php(497): Illuminate\Support\Facades\Facade::__callStatic('simpleTrace', Array)
2) /var/www/site/vendor/WebChefs/DB-LoJack/src/DBLoJackServiceProvider.php(70): WebChefs\DBLoJack\PerformanceWatchdog->logQuery('select * from s...')
3) /var/www/site/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(348): WebChefs\DBLoJack\DBLoJackServiceProvider->WebChefs\DBLoJack\{closure}(Object(Illuminate\Database\Events\QueryExecuted))
4) /var/www/site/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(199): Illuminate\Events\Dispatcher->Illuminate\Events\{closure}('Illuminate\\Data...', Array)
5) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Connection.php(808): Illuminate\Events\Dispatcher->dispatch('Illuminate\\Data...')
6) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Connection.php(665): Illuminate\Database\Connection->event(Object(Illuminate\Database\Events\QueryExecuted))
7) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Connection.php(618): Illuminate\Database\Connection->logQuery('select * from s...', Array, 0.06)
8) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Connection.php(326): Illuminate\Database\Connection->run('select * from s...', Array, Object(Closure))
9) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Schema/Builder.php(72): Illuminate\Database\Connection->select('select * from s...', Array)
10) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Migrations/DatabaseMigrationRepository.php(154): Illuminate\Database\Schema\Builder->hasTable('migrations')
--------------------------------------------------------------------------------
Usage Count: 2
Trace Count: 2
--------------------------------------------------------------------------------
delete from "jobs" where "id" = ?
--------------------------------------------------------------------------------
1) /var/www/site/vendor/WebChefs/DB-LoJack/src/PerformanceWatchdog.php(497): Illuminate\Support\Facades\Facade::__callStatic('simpleTrace', Array)
2) /var/www/site/vendor/WebChefs/DB-LoJack/src/DBLoJackServiceProvider.php(70): WebChefs\DBLoJack\PerformanceWatchdog->logQuery('delete from "jo...')
3) /var/www/site/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(348): WebChefs\DBLoJack\DBLoJackServiceProvider->WebChefs\DBLoJack\{closure}(Object(Illuminate\Database\Events\QueryExecuted))
4) /var/www/site/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(199): Illuminate\Events\Dispatcher->Illuminate\Events\{closure}('Illuminate\\Data...', Array)
5) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Connection.php(808): Illuminate\Events\Dispatcher->dispatch('Illuminate\\Data...')
6) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Connection.php(665): Illuminate\Database\Connection->event(Object(Illuminate\Database\Events\QueryExecuted))
7) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Connection.php(618): Illuminate\Database\Connection->logQuery('delete from "jo...', Array, 0.05)
8) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Connection.php(477): Illuminate\Database\Connection->run('delete from "jo...', Array, Object(Closure))
9) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Connection.php(428): Illuminate\Database\Connection->affectingStatement('delete from "jo...', Array)
10) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php(2225): Illuminate\Database\Connection->delete('delete from "jo...', Array)
1) /var/www/site/vendor/WebChefs/DB-LoJack/src/PerformanceWatchdog.php(497): Illuminate\Support\Facades\Facade::__callStatic('simpleTrace', Array)
2) /var/www/site/vendor/WebChefs/DB-LoJack/src/DBLoJackServiceProvider.php(70): WebChefs\DBLoJack\PerformanceWatchdog->logQuery('delete from "jo...')
3) /var/www/site/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(348): WebChefs\DBLoJack\DBLoJackServiceProvider->WebChefs\DBLoJack\{closure}(Object(Illuminate\Database\Events\QueryExecuted))
4) /var/www/site/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(199): Illuminate\Events\Dispatcher->Illuminate\Events\{closure}('Illuminate\\Data...', Array)
5) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Connection.php(808): Illuminate\Events\Dispatcher->dispatch('Illuminate\\Data...')
6) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Connection.php(665): Illuminate\Database\Connection->event(Object(Illuminate\Database\Events\QueryExecuted))
7) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Connection.php(618): Illuminate\Database\Connection->logQuery('delete from "jo...', Array, 0.02)
8) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Connection.php(477): Illuminate\Database\Connection->run('delete from "jo...', Array, Object(Closure))
9) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Connection.php(428): Illuminate\Database\Connection->affectingStatement('delete from "jo...', Array)
10) /var/www/site/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php(2225): Illuminate\Database\Connection->delete('delete from "jo...', Array)
END=============================================================================
配置
要自定义配置,请发布 config/db-lojack.php
。
php artisan vendor:publish --provider="WebChefs\DBLoJack\DBLoJackServiceProvider" --tag="config"
默认配置
return [ /* |-------------------------------------------------------------------------- | Lo-Jack Query Log |-------------------------------------------------------------------------- | | To debug database queries by logging to a text file found in | storage/logs. We should avoid running this in production. | */ 'query_log' => [ // Enable query logging 'enabled' => env('APP_DEBUG', false) && env('APP_ENV', 'local') == 'local', // If enabled, when running in console the listener handler will be forced 'console_logging' => false, // Max files number of files to keep, logs are rotated daily 'max_files' => 10, // Type of handler to collect the query lots and action the log writer: // Options middleware or listener 'handler' => 'middleware', // Default logging location 'log_path' => storage_path('logs/db'), // Connections to log // Comma separated database connection names eg: mysql,pgsql,test // all = all configured connections 'connection' => 'all', /* |---------------------------------------------------------------------- | Log Formatters |---------------------------------------------------------------------- | | Available tokens: | | All | - :env = environment config variable at time | - :date = date and time the log was writen | - :connection = database connection | - :label = request label, URL for http requests, argv for console | - :handler = DBLoJack handler, middleware or listener | | Query Only | - :time = execution time of a query (not always available) | - :query = formatted query | | Boundary entires | - :boundary = boundary type, before or after | */ // String format for single query (listener) 'log_foramt_single' => '[:date] [:connection] [:env] :time ms ":query" ":label"', // String format for multiple queries being log at once (middleware) 'log_foramt_multi' => '[:connection] [:env] :time ms ":query"', // Log entries showing for grouping all the logs for single request // Leave empty or null to skip boundary 'log_before_boundary' => '---------BOUNDARY :boundary-:handler [:env]---------' . "\n[:date] :label", 'log_after_boundary' => '---------BOUNDARY :boundary---------', ], /* |-------------------------------------------------------------------------- | Lo-Jack Performance Watchdog |-------------------------------------------------------------------------- | | Implements a monitoring system were logs are generated if a configured | threshold is exceeded. | */ 'performance_watchdog' => [ // Default logging location 'log_path' => storage_path('logs/performance'), // Operating mode // - false = turns off all monitoring // - 'summary' = most light weight logs a single line per a request // - 'detailed' = logs debug details of every database query, good for development // - 'both' = log summary and detailed 'mode' => false, // Size of mini back trace used in detailed log. // Can be integer or false to not log traces 'trace' => 10, // The minimum number of times a queries should be run before logging. 'min_queries' => 2, // Threshold counters 'threshold' => [ 'time' => 1000, // request total time in ms 'queries' => 100, // total query count per request 'memory' => '35MB', // request max memory ], ], ];
安全性与信息泄露
通常,在生产环境中记录完整的数据库查询(具有实际参数/绑定)是一个非常糟糕的想法,因为这会导致将敏感信息(如用户名、密码和会话 ID)记录到通常安全性较低的位置,形式为应用程序日志。
因此,如果Laravel环境设置为生产
或测试
,查询将被记录,但不会替换绑定,查询将留下?
占位符。
贡献
所有代码提交将仅作为拉取请求进行评估和接受。如果您有任何问题或发现任何错误,请随时提出问题。
鸣谢
许可证
MIT许可证(MIT)。更多信息请参阅许可证文件。