Blame | Letzte Änderung | Log anzeigen | RSS feed
<?phpnamespace Spatie\LaravelIgnition;use Illuminate\Contracts\Debug\ExceptionHandler;use Illuminate\Foundation\Application;use Illuminate\Support\Facades\Log;use Illuminate\Support\ServiceProvider;use Illuminate\View\ViewException;use Laravel\Octane\Events\RequestReceived;use Laravel\Octane\Events\RequestTerminated;use Laravel\Octane\Events\TaskReceived;use Laravel\Octane\Events\TickReceived;use Monolog\Logger;use Spatie\FlareClient\Flare;use Spatie\FlareClient\FlareMiddleware\AddSolutions;use Spatie\Ignition\Config\FileConfigManager;use Spatie\Ignition\Config\IgnitionConfig;use Spatie\Ignition\Contracts\ConfigManager;use Spatie\Ignition\Contracts\SolutionProviderRepository as SolutionProviderRepositoryContract;use Spatie\Ignition\Ignition;use Spatie\LaravelIgnition\Commands\SolutionMakeCommand;use Spatie\LaravelIgnition\Commands\SolutionProviderMakeCommand;use Spatie\LaravelIgnition\Commands\TestCommand;use Spatie\LaravelIgnition\ContextProviders\LaravelContextProviderDetector;use Spatie\LaravelIgnition\Exceptions\InvalidConfig;use Spatie\LaravelIgnition\FlareMiddleware\AddJobs;use Spatie\LaravelIgnition\FlareMiddleware\AddLogs;use Spatie\LaravelIgnition\FlareMiddleware\AddQueries;use Spatie\LaravelIgnition\Recorders\DumpRecorder\DumpRecorder;use Spatie\LaravelIgnition\Recorders\JobRecorder\JobRecorder;use Spatie\LaravelIgnition\Recorders\LogRecorder\LogRecorder;use Spatie\LaravelIgnition\Recorders\QueryRecorder\QueryRecorder;use Spatie\LaravelIgnition\Renderers\IgnitionExceptionRenderer;use Spatie\LaravelIgnition\Renderers\IgnitionWhoopsHandler;use Spatie\LaravelIgnition\Solutions\SolutionProviders\SolutionProviderRepository;use Spatie\LaravelIgnition\Support\FlareLogHandler;use Spatie\LaravelIgnition\Support\SentReports;use Spatie\LaravelIgnition\Views\ViewExceptionMapper;class IgnitionServiceProvider extends ServiceProvider{public function register(): void{$this->registerConfig();$this->registerFlare();$this->registerIgnition();$this->registerRenderer();$this->registerRecorders();$this->registerLogHandler();}public function boot(){if ($this->app->runningInConsole()) {$this->registerCommands();$this->publishConfigs();}$this->registerRoutes();$this->configureTinker();$this->configureOctane();$this->registerViewExceptionMapper();$this->startRecorders();$this->configureQueue();}protected function registerConfig(): void{$this->mergeConfigFrom(__DIR__ . '/../config/flare.php', 'flare');$this->mergeConfigFrom(__DIR__ . '/../config/ignition.php', 'ignition');}protected function registerCommands(): void{if ($this->app['config']->get('flare.key')) {$this->commands([TestCommand::class,]);}if ($this->app['config']->get('ignition.register_commands')) {$this->commands([SolutionMakeCommand::class,SolutionProviderMakeCommand::class,]);}}protected function publishConfigs(): void{$this->publishes([__DIR__ . '/../config/ignition.php' => config_path('ignition.php'),], 'ignition-config');$this->publishes([__DIR__ . '/../config/flare.php' => config_path('flare.php'),], 'flare-config');}protected function registerRenderer(): void{if (interface_exists('Whoops\Handler\HandlerInterface')) {$this->app->bind('Whoops\Handler\HandlerInterface',fn (Application $app) => $app->make(IgnitionWhoopsHandler::class));}if (interface_exists('Illuminate\Contracts\Foundation\ExceptionRenderer')) {$this->app->bind('Illuminate\Contracts\Foundation\ExceptionRenderer',fn (Application $app) => $app->make(IgnitionExceptionRenderer::class));}}protected function registerFlare(): void{$this->app->singleton(Flare::class, function () {return Flare::make()->setApiToken(config('flare.key') ?? '')->setBaseUrl(config('flare.base_url', 'https://flareapp.io/api'))->applicationPath(base_path())->setStage(app()->environment())->setContextProviderDetector(new LaravelContextProviderDetector())->registerMiddleware($this->getFlareMiddleware())->registerMiddleware(new AddSolutions(new SolutionProviderRepository($this->getSolutionProviders())));});$this->app->singleton(SentReports::class);}protected function registerIgnition(): void{$this->app->singleton(ConfigManager::class,fn () => new FileConfigManager(config('ignition.settings_file_path', '')));$ignitionConfig = (new IgnitionConfig())->merge(config('ignition', []))->loadConfigFile();$solutionProviders = $this->getSolutionProviders();$solutionProviderRepository = new SolutionProviderRepository($solutionProviders);$this->app->singleton(IgnitionConfig::class, fn () => $ignitionConfig);$this->app->singleton(SolutionProviderRepositoryContract::class, fn () => $solutionProviderRepository);$this->app->singleton(Ignition::class,fn () => (new Ignition())->applicationPath(base_path()));}protected function registerRecorders(): void{$this->app->singleton(DumpRecorder::class);$this->app->singleton(LogRecorder::class, function (Application $app): LogRecorder {return new LogRecorder($app,config()->get('flare.flare_middleware.' . AddLogs::class . '.maximum_number_of_collected_logs'));});$this->app->singleton(QueryRecorder::class,function (Application $app): QueryRecorder {return new QueryRecorder($app,config('flare.flare_middleware.' . AddQueries::class . '.report_query_bindings', true),config('flare.flare_middleware.' . AddQueries::class . '.maximum_number_of_collected_queries', 200));});$this->app->singleton(JobRecorder::class, function (Application $app): JobRecorder {return new JobRecorder($app,config('flare.flare_middleware.' . AddJobs::class . '.max_chained_job_reporting_depth', 5));});}public function configureTinker(): void{if (! $this->app->runningInConsole()) {if (isset($_SERVER['argv']) && ['artisan', 'tinker'] === $_SERVER['argv']) {app(Flare::class)->sendReportsImmediately();}}}protected function configureOctane(): void{if (isset($_SERVER['LARAVEL_OCTANE'])) {$this->setupOctane();}}protected function registerViewExceptionMapper(): void{$handler = $this->app->make(ExceptionHandler::class);if (! method_exists($handler, 'map')) {return;}$handler->map(function (ViewException $viewException) {return $this->app->make(ViewExceptionMapper::class)->map($viewException);});}protected function registerRoutes(): void{$this->loadRoutesFrom(realpath(__DIR__ . '/ignition-routes.php'));}protected function registerLogHandler(): void{$this->app->singleton('flare.logger', function ($app) {$handler = new FlareLogHandler($app->make(Flare::class),$app->make(SentReports::class),);$logLevelString = config('logging.channels.flare.level', 'error');$logLevel = $this->getLogLevel($logLevelString);$handler->setMinimumReportLogLevel($logLevel);return tap(new Logger('Flare'),fn (Logger $logger) => $logger->pushHandler($handler));});Log::extend('flare', fn ($app) => $app['flare.logger']);}protected function startRecorders(): void{foreach ($this->app->config['ignition.recorders'] ?? [] as $recorder) {$this->app->make($recorder)->start();}}protected function configureQueue(): void{if (! $this->app->bound('queue')) {return;}$queue = $this->app->get('queue');// Reset before executing a queue job to make sure the job's log/query/dump recorders are empty.// When using a sync queue this also reports the queued reports from previous exceptions.$queue->before(function () {$this->resetFlareAndLaravelIgnition();app(Flare::class)->sendReportsImmediately();});// Send queued reports (and reset) after executing a queue job.$queue->after(function () {$this->resetFlareAndLaravelIgnition();});// Note: the $queue->looping() event can't be used because it's not triggered on Vapor}protected function getLogLevel(string $logLevelString): int{$logLevel = Logger::getLevels()[strtoupper($logLevelString)] ?? null;if (! $logLevel) {throw InvalidConfig::invalidLogLevel($logLevelString);}return $logLevel;}protected function getFlareMiddleware(): array{return collect(config('flare.flare_middleware'))->map(function ($value, $key) {if (is_string($key)) {$middlewareClass = $key;$parameters = $value ?? [];} else {$middlewareClass = $value;$parameters = [];}return new $middlewareClass(...array_values($parameters));})->values()->toArray();}protected function getSolutionProviders(): array{return collect(config('ignition.solution_providers'))->reject(fn (string $class) => in_array($class, config('ignition.ignored_solution_providers')))->toArray();}protected function setupOctane(): void{$this->app['events']->listen(RequestReceived::class, function () {$this->resetFlareAndLaravelIgnition();});$this->app['events']->listen(TaskReceived::class, function () {$this->resetFlareAndLaravelIgnition();});$this->app['events']->listen(TickReceived::class, function () {$this->resetFlareAndLaravelIgnition();});$this->app['events']->listen(RequestTerminated::class, function () {$this->resetFlareAndLaravelIgnition();});}protected function resetFlareAndLaravelIgnition(): void{$this->app->get(SentReports::class)->clear();$this->app->get(Ignition::class)->reset();if (config('flare.flare_middleware.' . AddLogs::class)) {$this->app->make(LogRecorder::class)->reset();}if (config('flare.flare_middleware.' . AddQueries::class)) {$this->app->make(QueryRecorder::class)->reset();}if (config('flare.flare_middleware.' . AddJobs::class)) {$this->app->make(JobRecorder::class)->reset();}$this->app->make(DumpRecorder::class)->reset();}}