yii-sentry icon indicating copy to clipboard operation
yii-sentry copied to clipboard

Support crontab monitoring

Open samdark opened this issue 9 months ago • 1 comments

Could be implemented as a base command like the following:

use DateTime;
use Sentry\CheckInStatus;
use Sentry\MonitorConfig;
use Sentry\MonitorSchedule;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Stopwatch\Stopwatch;
use Throwable;

use function Sentry\captureCheckIn;

abstract class SentryMonitoredCommand extends Command
{
    private ?string $checkinId = null;
    private Stopwatch $stopwatch;

    protected function initialize(InputInterface $input, OutputInterface $output): void
    {
        $this->stopwatch = new Stopwatch();
        $this->stopwatch->start($this->getName());

        // read comand schedule from crontab file where command name is $this->getName()
        
        $cronSchedule = ...;

        $monitorConfig = null;
        if ($cronEntry !== null) {
            $currentTimezone = (new DateTime())->getTimezone()->getName();

            $monitorSchedule = MonitorSchedule::crontab($cronSchedule);
            $monitorConfig = new MonitorConfig($monitorSchedule, timezone: $currentTimezone);
        }

        $this->checkinId = captureCheckIn(
            slug: $this->getName(),
            status: CheckInStatus::inProgress(),
            monitorConfig: $monitorConfig,
        );
    }

    public function run(InputInterface $input, OutputInterface $output): int
    {
        try {
            $exitCode = parent::run($input, $output);
        } catch (Throwable $t) {
            $this->reportFail();
            throw $t;
        }

        if ($exitCode === self::SUCCESS) {
            $this->reportSuccess();
        } else {
            $this->reportFail();
        }

        return $exitCode;
    }

    private function reportSuccess(): void
    {
        $event = $this->stopwatch->stop($this->getName());

        captureCheckIn(
            slug: $this->getName(),
            status: CheckInStatus::ok(),
            duration: $event->getDuration() * 0.001,
            checkInId: $this->checkinId,
        );
    }

    private function reportFail(): void
    {
        $event = $this->stopwatch->stop($this->getName());

        captureCheckIn(
            slug: $this->getName(),
            status: CheckInStatus::error(),
            duration: $event->getDuration() * 0.001,
            checkInId: $this->checkinId,
        );
    }
}

Alternatively, the same could be done via events.

samdark avatar Mar 12 '25 22:03 samdark

Good example. I think in the future it could be a separate package for monitoring: periodic checks, poling messages, working with local "agents"/"exporters"

xepozz avatar Mar 13 '25 07:03 xepozz