diff --git a/src/CheckIn.php b/src/CheckIn.php index bcc0f3e28..7cc70e756 100644 --- a/src/CheckIn.php +++ b/src/CheckIn.php @@ -38,6 +38,11 @@ final class CheckIn */ private $duration; + /** + * @var \Sentry\MonitorConfig|null The monitor configuration + */ + private $monitorConfig; + /** * @param int|float|null $duration The duration of the check-in in seconds */ @@ -47,7 +52,8 @@ public function __construct( string $id = null, ?string $release = null, ?string $environment = null, - $duration = null + $duration = null, + ?MonitorConfig $monitorConfig = null ) { $this->setMonitorSlug($monitorSlug); $this->setStatus($status); @@ -56,6 +62,7 @@ public function __construct( $this->setRelease($release ?? ''); $this->setEnvironment($environment ?? Event::DEFAULT_ENVIRONMENT); $this->setDuration($duration); + $this->setMonitorConfig($monitorConfig); } public function getId(): string @@ -123,4 +130,14 @@ public function setDuration($duration): void { $this->duration = $duration; } + + public function getMonitorConfig(): ?MonitorConfig + { + return $this->monitorConfig; + } + + public function setMonitorConfig(?MonitorConfig $monitorConfig): void + { + $this->monitorConfig = $monitorConfig; + } } diff --git a/src/MonitorConfig.php b/src/MonitorConfig.php new file mode 100644 index 000000000..c03c82700 --- /dev/null +++ b/src/MonitorConfig.php @@ -0,0 +1,101 @@ +schedule = $schedule; + $this->checkinMargin = $checkinMargin; + $this->maxRuntime = $maxRuntime; + $this->timezone = $timezone; + } + + public function getSchedule(): MonitorSchedule + { + return $this->schedule; + } + + public function setSchedule(MonitorSchedule $schedule): self + { + $this->schedule = $schedule; + + return $this; + } + + public function getCheckinMargin(): ?int + { + return $this->checkinMargin; + } + + public function setCheckinMargin(?int $checkinMargin): self + { + $this->checkinMargin = $checkinMargin; + + return $this; + } + + public function getMaxRuntime(): ?int + { + return $this->maxRuntime; + } + + public function setMaxRuntime(?int $maxRuntime): self + { + $this->maxRuntime = $maxRuntime; + + return $this; + } + + public function getTimezone(): ?string + { + return $this->timezone; + } + + public function setTimezone(?string $timezone): self + { + $this->timezone = $timezone; + + return $this; + } + + /** + * @return array + */ + public function toArray(): array + { + return [ + 'schedule' => $this->schedule->toArray(), + 'checkin_margin' => $this->checkinMargin, + 'max_runtime' => $this->maxRuntime, + 'timezone' => $this->timezone, + ]; + } +} diff --git a/src/MonitorSchedule.php b/src/MonitorSchedule.php new file mode 100644 index 000000000..f9eee21fe --- /dev/null +++ b/src/MonitorSchedule.php @@ -0,0 +1,106 @@ +type = $type; + $this->value = $value; + $this->unit = $unit; + } + + public static function crontab(string $value): self + { + return new self(self::TYPE_CRONTAB, $value); + } + + public static function interval(int $value, MonitorScheduleUnit $unit): self + { + return new self(self::TYPE_INTERVAL, $value, $unit); + } + + public function getType(): string + { + return $this->type; + } + + public function setType(string $type): self + { + $this->type = $type; + + return $this; + } + + /** + * @return string|int + */ + public function getValue() + { + return $this->value; + } + + /** + * @param string|int $value + */ + public function setValue($value): self + { + $this->value = $value; + + return $this; + } + + public function getUnit(): ?MonitorScheduleUnit + { + return $this->unit; + } + + public function setUnit(?MonitorScheduleUnit $unit): self + { + $this->unit = $unit; + + return $this; + } + + /** + * @return array + */ + public function toArray(): array + { + return [ + 'type' => $this->type, + 'value' => $this->value, + 'unit' => (string) $this->unit, + ]; + } +} diff --git a/src/MonitorScheduleUnit.php b/src/MonitorScheduleUnit.php new file mode 100644 index 000000000..950d95ed8 --- /dev/null +++ b/src/MonitorScheduleUnit.php @@ -0,0 +1,67 @@ + A list of cached enum instances + */ + private static $instances = []; + + private function __construct(string $value) + { + $this->value = $value; + } + + public static function minute(): self + { + return self::getInstance('minute'); + } + + public static function hour(): self + { + return self::getInstance('hour'); + } + + public static function day(): self + { + return self::getInstance('day'); + } + + public static function week(): self + { + return self::getInstance('week'); + } + + public static function month(): self + { + return self::getInstance('month'); + } + + public static function year(): self + { + return self::getInstance('year'); + } + + public function __toString(): string + { + return $this->value; + } + + private static function getInstance(string $value): self + { + if (!isset(self::$instances[$value])) { + self::$instances[$value] = new self($value); + } + + return self::$instances[$value]; + } +} diff --git a/src/Serializer/PayloadSerializer.php b/src/Serializer/PayloadSerializer.php index 25ed8b299..7aec12421 100644 --- a/src/Serializer/PayloadSerializer.php +++ b/src/Serializer/PayloadSerializer.php @@ -86,6 +86,10 @@ private function serializeAsCheckInEvent(Event $event): string 'environment' => $checkIn->getEnvironment(), ]; + if (null !== $checkIn->getMonitorConfig()) { + $result['monitor_config'] = $checkIn->getMonitorConfig()->toArray(); + } + if (!empty($event->getContexts()['trace'])) { $result['contexts']['trace'] = $event->getContexts()['trace']; } diff --git a/tests/CheckInTest.php b/tests/CheckInTest.php index 4380ebd40..dbe191559 100644 --- a/tests/CheckInTest.php +++ b/tests/CheckInTest.php @@ -7,6 +7,8 @@ use PHPUnit\Framework\TestCase; use Sentry\CheckIn; use Sentry\CheckInStatus; +use Sentry\MonitorConfig; +use Sentry\MonitorSchedule; use Sentry\Util\SentryUid; final class CheckInTest extends TestCase @@ -54,6 +56,7 @@ public function gettersAndSettersDataProvider(): array ['getRelease', 'setRelease', '1.0.0'], ['getEnvironment', 'setEnvironment', 'dev'], ['getDuration', 'setDuration', 10], + ['getMonitorConfig', 'setMonitorConfig', new MonitorConfig(MonitorSchedule::crontab('* * * * *'))], ]; } } diff --git a/tests/MonitorConfigTest.php b/tests/MonitorConfigTest.php new file mode 100644 index 000000000..14ca7cea7 --- /dev/null +++ b/tests/MonitorConfigTest.php @@ -0,0 +1,51 @@ +assertEquals($monitorSchedule, $monitorConfig->getSchedule()); + $this->assertEquals(10, $monitorConfig->getCheckinMargin()); + $this->assertEquals(12, $monitorConfig->getMaxRuntime()); + $this->assertEquals('Europe/Amsterdam', $monitorConfig->getTimezone()); + } + + /** + * @dataProvider gettersAndSettersDataProvider + */ + public function testGettersAndSetters(string $getterMethod, string $setterMethod, $expectedData): void + { + $monitorConfig = new MonitorConfig( + MonitorSchedule::crontab('* * * * *') + ); + $monitorConfig->$setterMethod($expectedData); + + $this->assertEquals($expectedData, $monitorConfig->$getterMethod()); + } + + public function gettersAndSettersDataProvider(): array + { + return [ + ['getSchedule', 'setSchedule', MonitorSchedule::crontab('foo')], + ['getCheckinMargin', 'setCheckinMargin', 10], + ['getMaxRuntime', 'setMaxRuntime', 12], + ['getTimezone', 'setTimezone', 'Europe/Amsterdam'], + ]; + } +} diff --git a/tests/MonitorScheduleTest.php b/tests/MonitorScheduleTest.php new file mode 100644 index 000000000..d81d3da73 --- /dev/null +++ b/tests/MonitorScheduleTest.php @@ -0,0 +1,65 @@ +assertEquals(MonitorSchedule::TYPE_CRONTAB, $monitorSchedule->getType()); + $this->assertEquals('* * * * *', $monitorSchedule->getValue()); + $this->assertNull($monitorSchedule->getUnit()); + } + + public function testConvenienceCrontabConstructor(): void + { + $monitorSchedule = MonitorSchedule::crontab('* * * * *'); + + $this->assertEquals(MonitorSchedule::TYPE_CRONTAB, $monitorSchedule->getType()); + $this->assertEquals('* * * * *', $monitorSchedule->getValue()); + $this->assertNull($monitorSchedule->getUnit()); + } + + public function testConvenienceIntervalConstructor(): void + { + $monitorSchedule = MonitorSchedule::interval(10, MonitorScheduleUnit::minute()); + + $this->assertEquals(MonitorSchedule::TYPE_INTERVAL, $monitorSchedule->getType()); + $this->assertEquals(10, $monitorSchedule->getValue()); + $this->assertEquals(MonitorScheduleUnit::minute(), $monitorSchedule->getUnit()); + } + + /** + * @dataProvider gettersAndSettersDataProvider + */ + public function testGettersAndSetters(string $getterMethod, string $setterMethod, $expectedData): void + { + $monitorSchedule = new MonitorSchedule( + MonitorSchedule::TYPE_CRONTAB, + '* * * * *' + ); + $monitorSchedule->$setterMethod($expectedData); + + $this->assertEquals($expectedData, $monitorSchedule->$getterMethod()); + } + + public function gettersAndSettersDataProvider(): array + { + return [ + ['getType', 'setType', MonitorSchedule::TYPE_INTERVAL], + ['getValue', 'setValue', '* * * * *'], + ['getUnit', 'setUnit', MonitorScheduleUnit::hour()], + ]; + } +} diff --git a/tests/MonitorScheduleUnitTest.php b/tests/MonitorScheduleUnitTest.php new file mode 100644 index 000000000..eec63984a --- /dev/null +++ b/tests/MonitorScheduleUnitTest.php @@ -0,0 +1,53 @@ +assertSame('minute', (string) $monitorScheduleUnit); + } + + public function testHour(): void + { + $monitorScheduleUnit = MonitorScheduleUnit::hour(); + + $this->assertSame('hour', (string) $monitorScheduleUnit); + } + + public function testDay(): void + { + $monitorScheduleUnit = MonitorScheduleUnit::day(); + + $this->assertSame('day', (string) $monitorScheduleUnit); + } + + public function testWeek(): void + { + $monitorScheduleUnit = MonitorScheduleUnit::week(); + + $this->assertSame('week', (string) $monitorScheduleUnit); + } + + public function testMonth(): void + { + $monitorScheduleUnit = MonitorScheduleUnit::month(); + + $this->assertSame('month', (string) $monitorScheduleUnit); + } + + public function testYear(): void + { + $monitorScheduleUnit = MonitorScheduleUnit::year(); + + $this->assertSame('year', (string) $monitorScheduleUnit); + } +} diff --git a/tests/Serializer/PayloadSerializerTest.php b/tests/Serializer/PayloadSerializerTest.php index 29f591bfa..2e5f15402 100644 --- a/tests/Serializer/PayloadSerializerTest.php +++ b/tests/Serializer/PayloadSerializerTest.php @@ -17,6 +17,8 @@ use Sentry\ExceptionDataBag; use Sentry\ExceptionMechanism; use Sentry\Frame; +use Sentry\MonitorConfig; +use Sentry\MonitorSchedule; use Sentry\Options; use Sentry\Profiling\Profile; use Sentry\Serializer\PayloadSerializer; @@ -607,6 +609,40 @@ public function serializeAsJsonDataProvider(): iterable {"event_id":"fc9442f5aef34234bb22b9a615e30ccd","sent_at":"2020-08-18T22:47:15Z","dsn":"http:\/\/public@example.com\/sentry\/1","sdk":{"name":"sentry.php","version":"$sdkVersion"}} {"type":"check_in","content_type":"application\/json"} {"check_in_id":"$checkinId","monitor_slug":"my-monitor","status":"in_progress","duration":null,"release":"","environment":"production","contexts":{"trace":{"trace_id":"21160e9b836d479f81611368b2aa3d2c","span_id":"5dd538dc297544cc"}}} +TEXT + , + false, + ]; + + $checkinId = SentryUid::generate(); + $checkIn = new CheckIn( + 'my-monitor', + CheckInStatus::ok(), + $checkinId, + '1.0.0', + 'dev', + 10, + new MonitorConfig( + MonitorSchedule::crontab('0 0 * * *'), + 10, + 12, + 'Europe/Amsterdam' + ) + ); + + $event = Event::createCheckIn(new EventId('fc9442f5aef34234bb22b9a615e30ccd')); + $event->setCheckIn($checkIn); + $event->setContext('trace', [ + 'trace_id' => '21160e9b836d479f81611368b2aa3d2c', + 'span_id' => '5dd538dc297544cc', + ]); + + yield [ + $event, + <<