diff --git a/README.md b/README.md index bf7154cc..590cd0ec 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,9 @@ return array( // capture release as git sha // 'release' => trim(exec('git log --pretty="%h" -n1 HEAD')), + + // Capture bindings on SQL queries + 'breadcrumbs.sql_bindings' => true, ); ``` diff --git a/examples/laravel-4.2/app/config/packages/sentry/sentry-laravel/config.php b/examples/laravel-4.2/app/config/packages/sentry/sentry-laravel/config.php index a1e66d5b..a4ee886e 100644 --- a/examples/laravel-4.2/app/config/packages/sentry/sentry-laravel/config.php +++ b/examples/laravel-4.2/app/config/packages/sentry/sentry-laravel/config.php @@ -5,4 +5,7 @@ // capture release as git sha // 'release' => trim(exec('git log --pretty="%h" -n1 HEAD')), + + // Capture bindings on SQL queries + 'breadcrumbs.sql_bindings' => false, ); diff --git a/examples/laravel-4.2/app/routes.php b/examples/laravel-4.2/app/routes.php index 4c6942bc..b8057e49 100644 --- a/examples/laravel-4.2/app/routes.php +++ b/examples/laravel-4.2/app/routes.php @@ -7,13 +7,14 @@ | | Here is where you can register all of the routes for an application. | It's a breeze. Simply tell Laravel the URIs it should respond to -| and give it the Closure to execute when that URI is requested. +| and give it the controller to call when that URI is requested. | */ function verifyCredentials() { Log::info('Verifying credentials'); + $user = DB::table('migrations')->where('migration', 'a migration')->first(); throw new Exception('No credentials passed!'); } diff --git a/examples/laravel-5.1/config/app.php b/examples/laravel-5.1/config/app.php index 71032d93..8eafeb01 100644 --- a/examples/laravel-5.1/config/app.php +++ b/examples/laravel-5.1/config/app.php @@ -78,7 +78,7 @@ | */ - 'key' => env('APP_KEY', 'SomeRandomString'), + 'key' => env('APP_KEY', 'xlhF31NeOlibJcoOW9tvZg7TkHcAZI3a'), 'cipher' => 'AES-256-CBC', diff --git a/examples/laravel-5.1/config/sentry.php b/examples/laravel-5.1/config/sentry.php index 4866441c..6424ea8b 100644 --- a/examples/laravel-5.1/config/sentry.php +++ b/examples/laravel-5.1/config/sentry.php @@ -1,8 +1,11 @@ env('SENTRY_DSN'), + 'dsn' => env('SENTRY_DSN', 'https://e9ebbd88548a441288393c457ec90441:399aaee02d454e2ca91351f29bdc3a07@sentry.io/3235'), // capture release as git sha // 'release' => trim(exec('git log --pretty="%h" -n1 HEAD')), + + // Capture bindings on SQL queries + 'breadcrumbs.sql_bindings' => true, ); diff --git a/examples/laravel-5.2/app/Http/routes.php b/examples/laravel-5.2/app/Http/routes.php index 7c59fc89..ae1b05e6 100644 --- a/examples/laravel-5.2/app/Http/routes.php +++ b/examples/laravel-5.2/app/Http/routes.php @@ -14,6 +14,7 @@ function verifyCredentials() { Log::info('Verifying credentials'); + $user = DB::table('users')->where('name', 'John')->first(); throw new Exception('No credentials passed!'); } diff --git a/examples/laravel-5.2/config/app.php b/examples/laravel-5.2/config/app.php index 9b8805c7..07a133f3 100644 --- a/examples/laravel-5.2/config/app.php +++ b/examples/laravel-5.2/config/app.php @@ -91,7 +91,7 @@ | */ - 'key' => env('APP_KEY'), + 'key' => env('APP_KEY', 'xlhF31NeOlibJcoOW9tvZg7TkHcAZI3a'), 'cipher' => 'AES-256-CBC', diff --git a/examples/laravel-5.2/config/sentry.php b/examples/laravel-5.2/config/sentry.php index 4866441c..2d44cb00 100644 --- a/examples/laravel-5.2/config/sentry.php +++ b/examples/laravel-5.2/config/sentry.php @@ -1,8 +1,11 @@ env('SENTRY_DSN'), + 'dsn' => env('SENTRY_DSN', 'https://e9ebbd88548a441288393c457ec90441:399aaee02d454e2ca91351f29bdc3a07@sentry.io/3235'), // capture release as git sha // 'release' => trim(exec('git log --pretty="%h" -n1 HEAD')), + + // Capture bindings on SQL queries + 'breadcrumbs.sql_bindings' => false, ); diff --git a/examples/lumen-5.2/app/Http/routes.php b/examples/lumen-5.2/app/Http/routes.php index ee3650cc..353d9763 100644 --- a/examples/lumen-5.2/app/Http/routes.php +++ b/examples/lumen-5.2/app/Http/routes.php @@ -11,7 +11,22 @@ | */ +function verifyCredentials() +{ + Log::info('Verifying credentials'); + $user = DB::table('migrations')->where('migration', 'a migration')->first(); + throw new Exception('No credentials passed!'); +} + + +function authenticateUser() +{ + Log::info('Authenticating the current user'); + verifyCredentials(); +} + + $app->get('/', function () use ($app) { Log::info('Rendering a page thats about to error'); - throw new Exception('An unhandled exception'); + authenticateUser(); }); diff --git a/examples/lumen-5.2/bootstrap/app.php b/examples/lumen-5.2/bootstrap/app.php index b0fe4198..b8814968 100644 --- a/examples/lumen-5.2/bootstrap/app.php +++ b/examples/lumen-5.2/bootstrap/app.php @@ -23,7 +23,7 @@ realpath(__DIR__.'/../') ); -// $app->withFacades(); +$app->withFacades(); // $app->withEloquent(); diff --git a/examples/lumen-5.2/config/sentry.php b/examples/lumen-5.2/config/sentry.php index d6ad110e..24416c78 100644 --- a/examples/lumen-5.2/config/sentry.php +++ b/examples/lumen-5.2/config/sentry.php @@ -2,4 +2,7 @@ return array( 'dsn' => 'https://e9ebbd88548a441288393c457ec90441:399aaee02d454e2ca91351f29bdc3a07@app.getsentry.com/3235', + + // Capture bindings on SQL queries + 'breadcrumbs.sql_bindings' => false, ); diff --git a/src/Sentry/SentryLaravel/SentryLaravelEventHandler.php b/src/Sentry/SentryLaravel/SentryLaravelEventHandler.php new file mode 100644 index 00000000..a8df5860 --- /dev/null +++ b/src/Sentry/SentryLaravel/SentryLaravelEventHandler.php @@ -0,0 +1,75 @@ +client = $client; + $this->sqlBindings = ( + isset($config['breadcrumbs.sql_bindings']) + ? $config['breadcrumbs.sql_bindings'] + : true + ); + } + + public function subscribe(Dispatcher $events) + { + $this->events = $events; + $events->listen('*', [$this, 'onWildcardEvent']); + } + + public function onWildcardEvent() + { + $name = $this->events->firing(); + $args = func_get_args(); + $data = null; + $level = 'info'; + if ($name === 'Illuminate\Database\Events\QueryExecuted') { + $name = 'sql.query'; + $message = $args[0]->sql; + $data = array( + 'connectionName' => $args[0]->connectionName, + ); + if ($this->sqlBindings) { + $bindings = $args[0]->bindings; + if (!empty($bindings)) { + $data['bindings'] = $bindings; + } + } + } elseif ($name === 'illuminate.query') { + // $args = array(sql, bindings, ...) + $name = 'sql.query'; + $message = $args[0]; + $data = array( + 'connectionName' => $args[3], + ); + if ($this->sqlBindings) { + $bindings = $args[1]; + if (!empty($bindings)) { + $data['bindings'] = $bindings; + } + } + } elseif ($name === 'illuminate.log') { + $name = 'log.' . $args[0]; + $level = $args[0]; + $message = $args[1]; + if (!empty($args[2])) { + $data = array('params' => $args[2]); + } + } else { + return; + } + $this->client->breadcrumbs->record(array( + 'message' => $message, + 'category' => $name, + 'data' => $data, + 'level' => $level, + )); + } +} diff --git a/src/Sentry/SentryLaravel/SentryLaravelServiceProvider.php b/src/Sentry/SentryLaravel/SentryLaravelServiceProvider.php index 670b5193..abbcb3bc 100644 --- a/src/Sentry/SentryLaravel/SentryLaravelServiceProvider.php +++ b/src/Sentry/SentryLaravel/SentryLaravelServiceProvider.php @@ -21,6 +21,8 @@ class SentryLaravelServiceProvider extends ServiceProvider */ public function boot() { + parent::boot(); + $app = $this->app; // Laravel 4.x compatibility @@ -35,23 +37,21 @@ public function boot() $app['sentry']->captureException($e); }); - $this->bindLogger($app['sentry']); + $this->bindEvents($app); } else { // the default configuration file $this->publishes(array( __DIR__ . '/config.php' => config_path('sentry.php'), ), 'config'); - $this->bindLogger(app('sentry')); + $this->bindEvents($app); } } - public function bindLogger($client) + protected function bindEvents($app) { - $handler = new \Raven_Breadcrumbs_MonologHandler($client); - - $logger = Log::getMonolog(); - $logger->pushHandler($handler); + $handler = new SentryLaravelEventHandler($app['sentry'], $app['sentry.config']); + $handler->subscribe($app->events); } /** @@ -61,7 +61,7 @@ public function bindLogger($client) */ public function register() { - $this->app->singleton('sentry', function ($app) { + $this->app->singleton('sentry.config', function ($app) { // sentry::config is Laravel 4.x $user_config = $app['config']['sentry'] ?: $app['config']['sentry::config']; @@ -70,6 +70,12 @@ public function register() $user_config = []; } + return $user_config; + }); + + $this->app->singleton('sentry', function ($app) { + $user_config = $app['sentry.config']; + $client = SentryLaravel::getClient(array_merge(array( 'environment' => $app->environment(), 'prefixes' => array(base_path()), diff --git a/src/Sentry/SentryLaravel/SentryLumenServiceProvider.php b/src/Sentry/SentryLaravel/SentryLumenServiceProvider.php index 3ccee80a..5c5e0428 100644 --- a/src/Sentry/SentryLaravel/SentryLumenServiceProvider.php +++ b/src/Sentry/SentryLaravel/SentryLumenServiceProvider.php @@ -21,6 +21,13 @@ class SentryLumenServiceProvider extends ServiceProvider public function boot() { $this->app->configure('sentry'); + $this->bindEvents($this->app); + } + + protected function bindEvents($app) + { + $handler = new SentryLaravelEventHandler($app['sentry'], $app['sentry.config']); + $handler->subscribe($app->events); } /** @@ -30,7 +37,7 @@ public function boot() */ public function register() { - $this->app->singleton('sentry', function ($app) { + $this->app->singleton('sentry.config', function ($app) { $user_config = $app['config']['sentry']; // Make sure we don't crash when we did not publish the config file @@ -38,6 +45,12 @@ public function register() $user_config = []; } + return $user_config; + }); + + $this->app->singleton('sentry', function ($app) { + $user_config = $app['sentry.config']; + $client = SentryLaravel::getClient(array_merge(array( 'environment' => $app->environment(), 'prefixes' => array(base_path()), diff --git a/src/Sentry/SentryLaravel/config.php b/src/Sentry/SentryLaravel/config.php index 4866441c..1f03c883 100644 --- a/src/Sentry/SentryLaravel/config.php +++ b/src/Sentry/SentryLaravel/config.php @@ -5,4 +5,7 @@ // capture release as git sha // 'release' => trim(exec('git log --pretty="%h" -n1 HEAD')), + + // Capture bindings on SQL queries + 'breadcrumbs.sql_bindings' => true, );