<?php
namespace Sentry\Laravel\Features;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Console\Events as ConsoleEvents;
use Sentry\Breadcrumb;
use Sentry\Laravel\Integration;
use Sentry\State\Scope;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Input\InputInterface;
class ConsoleIntegration extends Feature
{
private const FEATURE_KEY = 'command_info';
public function isApplicable(): bool
{
return true;
}
public function onBoot(Dispatcher $events): void
{
$events->listen(ConsoleEvents\CommandStarting::class, [$this, 'commandStarting']);
$events->listen(ConsoleEvents\CommandFinished::class, [$this, 'commandFinished']);
}
public function commandStarting(ConsoleEvents\CommandStarting $event): void
{
if (!$event->command) {
return;
}
Integration::configureScope(static function (Scope $scope) use ($event): void {
$scope->setTag('command', $event->command);
});
if ($this->isBreadcrumbFeatureEnabled(self::FEATURE_KEY)) {
Integration::addBreadcrumb(new Breadcrumb(
Breadcrumb::LEVEL_INFO,
Breadcrumb::TYPE_DEFAULT,
'artisan.command',
'Starting Artisan command: ' . $event->command,
[
'input' => $this->extractConsoleCommandInput($event->input),
]
));
}
}
public function commandFinished(ConsoleEvents\CommandFinished $event): void
{
if ($this->isBreadcrumbFeatureEnabled(self::FEATURE_KEY)) {
Integration::addBreadcrumb(new Breadcrumb(
Breadcrumb::LEVEL_INFO,
Breadcrumb::TYPE_DEFAULT,
'artisan.command',
'Finished Artisan command: ' . $event->command,
[
'exit' => $event->exitCode,
'input' => $this->extractConsoleCommandInput($event->input),
]
));
}
// Flush any and all events that were possibly generated by the command
Integration::flushEvents();
Integration::configureScope(static function (Scope $scope): void {
$scope->removeTag('command');
});
}
/**
* Extract the command input arguments if possible.
*
* @param \Symfony\Component\Console\Input\InputInterface|null $input
*
* @return string|null
*/
private function extractConsoleCommandInput(?InputInterface $input): ?string
{
if ($input instanceof ArgvInput) {
return (string)$input;
}
return null;
}
}