From a939085e5c721a042690ffcc1491f22578a6b104 Mon Sep 17 00:00:00 2001 From: Michael Hoffmann Date: Wed, 5 Apr 2023 11:37:32 +0200 Subject: [PATCH 1/8] feat: Cron Monitor upsert --- src/CheckIn.php | 19 +++++- src/MonitorConfig.php | 93 ++++++++++++++++++++++++++++ src/MonitorSchedule.php | 90 +++++++++++++++++++++++++++ src/MonitorScheduleUnit.php | 67 ++++++++++++++++++++ src/Serializer/PayloadSerializer.php | 4 ++ 5 files changed, 272 insertions(+), 1 deletion(-) create mode 100644 src/MonitorConfig.php create mode 100644 src/MonitorSchedule.php create mode 100644 src/MonitorScheduleUnit.php 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..582c02167 --- /dev/null +++ b/src/MonitorConfig.php @@ -0,0 +1,93 @@ +schedule = $schedule; + $this->checkinMargin = $checkinMargin; + $this->maxRuntime = $maxRuntime; + $this->timezone = $timezone; + } + + public function getShedule(): MonitorSchedule + { + return $this->schedule; + } + + public function setSchedule(MonitorSchedule $schedule): void + { + $this->schedule = $schedule; + } + + public function getCheckinMargin(): ?int + { + return $this->checkinMargin; + } + + public function setCheckinMargin(?int $checkinMargin): void + { + $this->checkinMargin = $checkinMargin; + } + + public function getMaxRuntime(): ?int + { + return $this->maxRuntime; + } + + public function setMaxRuntime(?int $maxRuntime): void + { + $this->maxRuntime = $maxRuntime; + } + + public function getTimezone(): ?string + { + return $this->timezone; + } + + public function setTimezone(?string $timezone): void + { + $this->timezone = $timezone; + } + + /** + * @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..2ca895e6c --- /dev/null +++ b/src/MonitorSchedule.php @@ -0,0 +1,90 @@ +type = $type; + $this->value = $value; + $this->unit = $unit; + } + + public function getType(): string + { + return $this->type; + } + + public function setType(string $type): void + { + $this->type = $type; + } + + /** + * @return string|int + */ + public function getValue() + { + return $this->value; + } + + /** + * @param string|int $value + */ + public function setValue($value): void + { + $this->value = $value; + } + + public function getUnit(): ?MonitorScheduleUnit + { + return $this->unit; + } + + public function setUnit(?MonitorScheduleUnit $unit): void + { + $this->unit = $unit; + } + + /** + * @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 09155fce4..e1243f88c 100644 --- a/src/Serializer/PayloadSerializer.php +++ b/src/Serializer/PayloadSerializer.php @@ -81,6 +81,10 @@ private function serializeAsCheckInEvent(Event $event): string 'release' => $checkIn->getRelease(), 'environment' => $checkIn->getEnvironment(), ]; + + if (null !== $checkIn->getMonitorConfig()) { + $result['monitor_config'] = $checkIn->getMonitorConfig()->toArray(); + } } return JSON::encode($result); From e0b8c4ce08a10a237a80fb05cb77170c74353910 Mon Sep 17 00:00:00 2001 From: Alex Bouma Date: Thu, 13 Apr 2023 11:57:10 +0200 Subject: [PATCH 2/8] Set default values for nullable parameters --- src/MonitorConfig.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/MonitorConfig.php b/src/MonitorConfig.php index 582c02167..600ab0aae 100644 --- a/src/MonitorConfig.php +++ b/src/MonitorConfig.php @@ -28,9 +28,9 @@ final class MonitorConfig public function __construct( MonitorSchedule $schedule, - ?int $checkinMargin, - ?int $maxRuntime, - ?string $timezone + ?int $checkinMargin = null, + ?int $maxRuntime = null, + ?string $timezone = null ) { $this->schedule = $schedule; $this->checkinMargin = $checkinMargin; From 91f0ad16e2e180a269ddad1316f120d0f619ce64 Mon Sep 17 00:00:00 2001 From: Alex Bouma Date: Mon, 12 Jun 2023 20:02:21 +0200 Subject: [PATCH 3/8] Make monitor schedule and config fluent --- src/MonitorConfig.php | 16 ++++++++++++---- src/MonitorSchedule.php | 12 +++++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/MonitorConfig.php b/src/MonitorConfig.php index 600ab0aae..fffcd706a 100644 --- a/src/MonitorConfig.php +++ b/src/MonitorConfig.php @@ -43,9 +43,11 @@ public function getShedule(): MonitorSchedule return $this->schedule; } - public function setSchedule(MonitorSchedule $schedule): void + public function setSchedule(MonitorSchedule $schedule): self { $this->schedule = $schedule; + + return $this; } public function getCheckinMargin(): ?int @@ -53,9 +55,11 @@ public function getCheckinMargin(): ?int return $this->checkinMargin; } - public function setCheckinMargin(?int $checkinMargin): void + public function setCheckinMargin(?int $checkinMargin): self { $this->checkinMargin = $checkinMargin; + + return $this; } public function getMaxRuntime(): ?int @@ -63,9 +67,11 @@ public function getMaxRuntime(): ?int return $this->maxRuntime; } - public function setMaxRuntime(?int $maxRuntime): void + public function setMaxRuntime(?int $maxRuntime): self { $this->maxRuntime = $maxRuntime; + + return $this; } public function getTimezone(): ?string @@ -73,9 +79,11 @@ public function getTimezone(): ?string return $this->timezone; } - public function setTimezone(?string $timezone): void + public function setTimezone(?string $timezone): self { $this->timezone = $timezone; + + return $this; } /** diff --git a/src/MonitorSchedule.php b/src/MonitorSchedule.php index 2ca895e6c..898dcefb0 100644 --- a/src/MonitorSchedule.php +++ b/src/MonitorSchedule.php @@ -45,9 +45,11 @@ public function getType(): string return $this->type; } - public function setType(string $type): void + public function setType(string $type): self { $this->type = $type; + + return $this; } /** @@ -61,9 +63,11 @@ public function getValue() /** * @param string|int $value */ - public function setValue($value): void + public function setValue($value): self { $this->value = $value; + + return $this; } public function getUnit(): ?MonitorScheduleUnit @@ -71,9 +75,11 @@ public function getUnit(): ?MonitorScheduleUnit return $this->unit; } - public function setUnit(?MonitorScheduleUnit $unit): void + public function setUnit(?MonitorScheduleUnit $unit): self { $this->unit = $unit; + + return $this; } /** From 785b79f543814dbaa2fb2cf2283c48946625e88a Mon Sep 17 00:00:00 2001 From: Alex Bouma Date: Mon, 12 Jun 2023 20:15:09 +0200 Subject: [PATCH 4/8] Fix typo --- src/MonitorConfig.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MonitorConfig.php b/src/MonitorConfig.php index fffcd706a..c03c82700 100644 --- a/src/MonitorConfig.php +++ b/src/MonitorConfig.php @@ -38,7 +38,7 @@ public function __construct( $this->timezone = $timezone; } - public function getShedule(): MonitorSchedule + public function getSchedule(): MonitorSchedule { return $this->schedule; } From d6a6a274557153081e1a18a9fe59772d734f0d2c Mon Sep 17 00:00:00 2001 From: Alex Bouma Date: Mon, 12 Jun 2023 20:15:34 +0200 Subject: [PATCH 5/8] Add convenience methods --- src/MonitorSchedule.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/MonitorSchedule.php b/src/MonitorSchedule.php index 898dcefb0..f9eee21fe 100644 --- a/src/MonitorSchedule.php +++ b/src/MonitorSchedule.php @@ -40,6 +40,16 @@ public function __construct( $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; From 1c129f2f45bf219f447b10b4e5a4f2725b6b5775 Mon Sep 17 00:00:00 2001 From: Alex Bouma Date: Mon, 12 Jun 2023 20:15:39 +0200 Subject: [PATCH 6/8] Add tests --- tests/CheckInTest.php | 3 ++ tests/MonitorConfigTest.php | 51 +++++++++++++++++++++++++++ tests/MonitorScheduleTest.php | 65 +++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 tests/MonitorConfigTest.php create mode 100644 tests/MonitorScheduleTest.php 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()], + ]; + } +} From 0c3b72dee94b012905ffd7882c607a73b06cc966 Mon Sep 17 00:00:00 2001 From: Alex Bouma Date: Mon, 12 Jun 2023 20:26:14 +0200 Subject: [PATCH 7/8] Add payload test --- tests/Serializer/PayloadSerializerTest.php | 36 ++++++++++++++++++++++ 1 file changed, 36 insertions(+) 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, + << Date: Tue, 13 Jun 2023 07:09:44 +0200 Subject: [PATCH 8/8] Add MonitorScheduleUnitTest --- tests/MonitorScheduleUnitTest.php | 53 +++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 tests/MonitorScheduleUnitTest.php 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); + } +}