diff --git a/src/State/Hub.php b/src/State/Hub.php index 152dec95a..02c0a3390 100644 --- a/src/State/Hub.php +++ b/src/State/Hub.php @@ -5,11 +5,14 @@ namespace Sentry\State; use Sentry\Breadcrumb; +use Sentry\CheckIn; +use Sentry\CheckInStatus; use Sentry\ClientInterface; use Sentry\Event; use Sentry\EventHint; use Sentry\EventId; use Sentry\Integration\IntegrationInterface; +use Sentry\MonitorConfig; use Sentry\Severity; use Sentry\Tracing\SamplingContext; use Sentry\Tracing\Span; @@ -169,6 +172,38 @@ public function captureLastError(?EventHint $hint = null): ?EventId return null; } + /** + * @param string $slug Identifier of the Monitor + * @param CheckInStatus $status The status of the check-in + * @param int|float|null $duration The duration of the check-in + * @param MonitorConfig|null $monitorConfig Configuration of the Monitor + * @param string|null $checkInId A check-in ID from the previous check-in + */ + public function captureCheckIn(string $slug, CheckInStatus $status, $duration = null, ?MonitorConfig $monitorConfig = null, ?string $checkInId = null): ?string + { + $client = $this->getClient(); + + if (null === $client) { + return null; + } + + $options = $client->getOptions(); + $event = Event::createCheckIn(); + $checkIn = new CheckIn( + $slug, + $status, + $checkInId, + $options->getRelease(), + $options->getEnvironment(), + $duration, + $monitorConfig + ); + $event->setCheckIn($checkIn); + $this->captureEvent($event); + + return $checkIn->getId(); + } + /** * {@inheritdoc} */ diff --git a/src/State/HubAdapter.php b/src/State/HubAdapter.php index eb3da1688..37f4b6395 100644 --- a/src/State/HubAdapter.php +++ b/src/State/HubAdapter.php @@ -5,11 +5,13 @@ namespace Sentry\State; use Sentry\Breadcrumb; +use Sentry\CheckInStatus; use Sentry\ClientInterface; use Sentry\Event; use Sentry\EventHint; use Sentry\EventId; use Sentry\Integration\IntegrationInterface; +use Sentry\MonitorConfig; use Sentry\SentrySdk; use Sentry\Severity; use Sentry\Tracing\Span; @@ -135,6 +137,18 @@ public function captureLastError(?EventHint $hint = null): ?EventId return SentrySdk::getCurrentHub()->captureLastError($hint); } + /** + * @param string $slug Identifier of the Monitor + * @param CheckInStatus $status The status of the check-in + * @param int|float|null $duration The duration of the check-in + * @param MonitorConfig|null $monitorConfig Configuration of the Monitor + * @param string|null $checkInId A check-in ID from the previous check-in + */ + public function captureCheckIn(string $slug, CheckInStatus $status, $duration = null, ?MonitorConfig $monitorConfig = null, ?string $checkInId = null): ?string + { + return SentrySdk::getCurrentHub()->captureCheckIn($slug, $status, $duration, $monitorConfig, $checkInId); + } + /** * {@inheritdoc} */ diff --git a/src/State/HubInterface.php b/src/State/HubInterface.php index 07ff16879..740686f3f 100644 --- a/src/State/HubInterface.php +++ b/src/State/HubInterface.php @@ -5,11 +5,13 @@ namespace Sentry\State; use Sentry\Breadcrumb; +use Sentry\CheckInStatus; use Sentry\ClientInterface; use Sentry\Event; use Sentry\EventHint; use Sentry\EventId; use Sentry\Integration\IntegrationInterface; +use Sentry\MonitorConfig; use Sentry\Severity; use Sentry\Tracing\SamplingContext; use Sentry\Tracing\Span; @@ -20,6 +22,8 @@ * This interface represent the class which is responsible for maintaining a * stack of pairs of clients and scopes. It is the main entry point to talk * with the Sentry client. + * + * @method string|null captureCheckIn(string $slug, CheckInStatus $status, $duration = null, ?MonitorConfig $upsertMonitorConfig = null, ?string $checkInId = null) Captures a check-in */ interface HubInterface { diff --git a/src/functions.php b/src/functions.php index 158c00b60..4956b1226 100644 --- a/src/functions.php +++ b/src/functions.php @@ -66,6 +66,20 @@ function captureLastError(?EventHint $hint = null): ?EventId return SentrySdk::getCurrentHub()->captureLastError($hint); } +/** + * Captures a check-in and sends it to Sentry. + * + * @param string $slug Identifier of the Monitor + * @param CheckInStatus $status The status of the check-in + * @param int|float|null $duration The duration of the check-in + * @param MonitorConfig|null $monitorConfig Configuration of the Monitor + * @param string|null $checkInId A check-in ID from the previous check-in + */ +function captureCheckIn(string $slug, CheckInStatus $status, $duration = null, ?MonitorConfig $monitorConfig = null, ?string $checkInId = null): ?string +{ + return SentrySdk::getCurrentHub()->captureCheckIn($slug, $status, $duration, $monitorConfig, $checkInId); +} + /** * Records a new breadcrumb which will be attached to future events. They * will be added to subsequent events to provide more context on user's diff --git a/tests/FunctionsTest.php b/tests/FunctionsTest.php index 473e052d9..a01b19104 100644 --- a/tests/FunctionsTest.php +++ b/tests/FunctionsTest.php @@ -8,10 +8,13 @@ use PHPUnit\Framework\TestCase; use RuntimeException; use Sentry\Breadcrumb; +use Sentry\CheckInStatus; use Sentry\ClientInterface; use Sentry\Event; use Sentry\EventHint; use Sentry\EventId; +use Sentry\MonitorConfig; +use Sentry\MonitorSchedule; use Sentry\Options; use Sentry\SentrySdk; use Sentry\Severity; @@ -25,7 +28,9 @@ use Sentry\Tracing\TraceId; use Sentry\Tracing\Transaction; use Sentry\Tracing\TransactionContext; +use Sentry\Util\SentryUid; use function Sentry\addBreadcrumb; +use function Sentry\captureCheckIn; use function Sentry\captureEvent; use function Sentry\captureException; use function Sentry\captureLastError; @@ -185,6 +190,38 @@ public static function captureLastErrorDataProvider(): \Generator ]; } + public function testCaptureCheckIn() + { + $hub = new Hub(); + $options = new Options([ + 'environment' => Event::DEFAULT_ENVIRONMENT, + 'release' => '1.1.8', + ]); + /** @var ClientInterface&MockObject $client */ + $client = $this->createMock(ClientInterface::class); + $client->expects($this->once()) + ->method('getOptions') + ->willReturn($options); + + $hub->bindClient($client); + SentrySdk::setCurrentHub($hub); + + $checkInId = SentryUid::generate(); + + $this->assertSame($checkInId, captureCheckIn( + 'test-crontab', + CheckInStatus::ok(), + 10, + new MonitorConfig( + MonitorSchedule::crontab('*/5 * * * *'), + 5, + 30, + 'UTC' + ), + $checkInId + )); + } + public function testAddBreadcrumb(): void { $breadcrumb = new Breadcrumb(Breadcrumb::LEVEL_ERROR, Breadcrumb::TYPE_ERROR, 'error_reporting'); diff --git a/tests/State/HubAdapterTest.php b/tests/State/HubAdapterTest.php index c876fca55..982cfa00e 100644 --- a/tests/State/HubAdapterTest.php +++ b/tests/State/HubAdapterTest.php @@ -4,21 +4,28 @@ namespace Sentry\Tests\State; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Sentry\Breadcrumb; +use Sentry\CheckInStatus; use Sentry\ClientInterface; use Sentry\Event; use Sentry\EventHint; use Sentry\EventId; use Sentry\Integration\IntegrationInterface; +use Sentry\MonitorConfig; +use Sentry\MonitorSchedule; +use Sentry\Options; use Sentry\SentrySdk; use Sentry\Severity; +use Sentry\State\Hub; use Sentry\State\HubAdapter; use Sentry\State\HubInterface; use Sentry\State\Scope; use Sentry\Tracing\Span; use Sentry\Tracing\Transaction; use Sentry\Tracing\TransactionContext; +use Sentry\Util\SentryUid; final class HubAdapterTest extends TestCase { @@ -255,6 +262,39 @@ public static function captureLastErrorDataProvider(): \Generator ]; } + public function testCaptureCheckIn() + { + $hub = new Hub(); + + $options = new Options([ + 'environment' => Event::DEFAULT_ENVIRONMENT, + 'release' => '1.1.8', + ]); + /** @var ClientInterface&MockObject $client */ + $client = $this->createMock(ClientInterface::class); + $client->expects($this->once()) + ->method('getOptions') + ->willReturn($options); + + $hub->bindClient($client); + SentrySdk::setCurrentHub($hub); + + $checkInId = SentryUid::generate(); + + $this->assertSame($checkInId, HubAdapter::getInstance()->captureCheckIn( + 'test-crontab', + CheckInStatus::ok(), + 10, + new MonitorConfig( + MonitorSchedule::crontab('*/5 * * * *'), + 5, + 30, + 'UTC' + ), + $checkInId + )); + } + public function testAddBreadcrumb(): void { $breadcrumb = new Breadcrumb(Breadcrumb::LEVEL_DEBUG, Breadcrumb::TYPE_ERROR, 'user'); diff --git a/tests/State/HubTest.php b/tests/State/HubTest.php index 3719d5864..d2b27e7e5 100644 --- a/tests/State/HubTest.php +++ b/tests/State/HubTest.php @@ -7,11 +7,14 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Sentry\Breadcrumb; +use Sentry\CheckInStatus; use Sentry\ClientInterface; use Sentry\Event; use Sentry\EventHint; use Sentry\EventId; use Sentry\Integration\IntegrationInterface; +use Sentry\MonitorConfig; +use Sentry\MonitorSchedule; use Sentry\Options; use Sentry\Severity; use Sentry\State\Hub; @@ -19,6 +22,7 @@ use Sentry\Tracing\PropagationContext; use Sentry\Tracing\SamplingContext; use Sentry\Tracing\TransactionContext; +use Sentry\Util\SentryUid; final class HubTest extends TestCase { @@ -390,6 +394,38 @@ public static function captureLastErrorDataProvider(): \Generator ]; } + public function testCaptureCheckIn() + { + $hub = new Hub(); + + $options = new Options([ + 'environment' => Event::DEFAULT_ENVIRONMENT, + 'release' => '1.1.8', + ]); + /** @var ClientInterface&MockObject $client */ + $client = $this->createMock(ClientInterface::class); + $client->expects($this->once()) + ->method('getOptions') + ->willReturn($options); + + $hub->bindClient($client); + + $checkInId = SentryUid::generate(); + + $this->assertSame($checkInId, $hub->captureCheckIn( + 'test-crontab', + CheckInStatus::ok(), + 10, + new MonitorConfig( + MonitorSchedule::crontab('*/5 * * * *'), + 5, + 30, + 'UTC' + ), + $checkInId + )); + } + public function testCaptureEvent(): void { $hub = new Hub();