diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f8e539a..4ad90b9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -67,6 +67,7 @@ jobs: - name: Install dependencies run: | composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update + if [ "${{ matrix.laravel }}" = "7.*" ]; then composer require "guzzlehttp/guzzle:7.6.*" --no-interaction --no-update; fi composer update --${{ matrix.stability }} --prefer-dist --no-interaction - name: Execute tests run: vendor/bin/phpunit diff --git a/composer.json b/composer.json index 85fc298..8b11d40 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ ], "require": { "php": "^7.4|^8.0", - "guzzlehttp/guzzle": "^6.3|^7.0", + "guzzlehttp/guzzle": "^6.3.1|^7.0", "illuminate/console": "^7.0|^8.0|^9.0|^10.0", "illuminate/support": "^7.0|^8.0|^9.0|^10.0" }, @@ -58,4 +58,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/AppkeepProvider.php b/src/AppkeepProvider.php index 425addb..969ce00 100644 --- a/src/AppkeepProvider.php +++ b/src/AppkeepProvider.php @@ -4,6 +4,7 @@ use Illuminate\Support\ServiceProvider; use Appkeep\Laravel\Commands\RunCommand; +use Illuminate\Console\Scheduling\Event; use Appkeep\Laravel\Commands\InitCommand; use Appkeep\Laravel\Commands\ListCommand; use Appkeep\Laravel\Commands\LoginCommand; @@ -66,7 +67,31 @@ public function bootForConsole() $schedule->command('appkeep:run') ->everyMinute() - ->runInBackground(); + ->runInBackground() + ->evenInMaintenanceMode(); + + collect($schedule->events()) + ->filter(function ($event) { + return $event->command && ! str_contains($event->command, 'appkeep:run'); + }) + ->each(function (Event $event) { + /** + * @var AppkeepService + */ + $appkeep = app('appkeep'); + + $event->before( + fn () => $appkeep->scheduledTaskStarted($event) + ); + + $event->onFailureWithOutput( + fn ($output) => $appkeep->scheduledTaskFailed($event, $output) + ); + + $event->onSuccessWithOutput( + fn ($output) => $appkeep->scheduledTaskCompleted($event, $output) + ); + }); }); } } diff --git a/src/AppkeepService.php b/src/AppkeepService.php index 913fe6c..fde2714 100644 --- a/src/AppkeepService.php +++ b/src/AppkeepService.php @@ -3,14 +3,17 @@ namespace Appkeep\Laravel; use InvalidArgumentException; +use Appkeep\Laravel\Concerns\ReportsScheduledTaskOutputs; class AppkeepService { + use ReportsScheduledTaskOutputs; + public $checks = []; public function version() { - return '0.5.0'; + return '0.6.0'; } public function client() diff --git a/src/Concerns/ReportsScheduledTaskOutputs.php b/src/Concerns/ReportsScheduledTaskOutputs.php new file mode 100644 index 0000000..6c3ad29 --- /dev/null +++ b/src/Concerns/ReportsScheduledTaskOutputs.php @@ -0,0 +1,64 @@ +scheduledTaskStartMs = hrtime(true); + $this->scheduledTaskStartedAt = now(); + } + + /** + * Get the duration of the scheduled task run in milliseconds + */ + private function getScheduledTaskRunDuration(): int + { + return round((hrtime(true) - $this->scheduledTaskStartMs) / 1e+6); + } + + public function scheduledTaskFailed(Event $task, $output) + { + $duration = $this->getScheduledTaskRunDuration(); + $finishedAt = now(); + + $output = ScheduledTaskOutput::fromScheduledTask($task) + ->failed() + ->setDuration($duration) + ->setStartedAt($this->scheduledTaskStartedAt) + ->setFinishedAt($finishedAt) + ->setOutput($output); + + try { + $this->client()->sendScheduledTaskOutput($output); + } catch (\Exception $e) { + report($e); + } + } + + public function scheduledTaskCompleted(Event $task, $output) + { + $duration = $this->getScheduledTaskRunDuration(); + $finishedAt = now(); + + $output = ScheduledTaskOutput::fromScheduledTask($task) + ->succeeded() + ->setDuration($duration) + ->setStartedAt($this->scheduledTaskStartedAt) + ->setFinishedAt($finishedAt) + ->setOutput($output); + + try { + $this->client()->sendScheduledTaskOutput($output); + } catch (\Exception $e) { + report($e); + } + } +} diff --git a/src/Contexts/SpecsContext.php b/src/Contexts/SpecsContext.php index bafa143..b8e6c27 100644 --- a/src/Contexts/SpecsContext.php +++ b/src/Contexts/SpecsContext.php @@ -45,7 +45,8 @@ private function totalDiskspace() private function totalMemory() { if (PHP_OS === 'Linux') { - $output = shell_exec('free -g | grep Mem | awk \'{print $2}\''); + $output = shell_exec('free -m | grep Mem | awk \'{print $2}\''); + $output = $output / 1024; // convert MB to GB } elseif (PHP_OS === 'Darwin' || PHP_OS === 'FreeBSD') { $output = shell_exec('sysctl -n hw.memsize'); $output = $output / 1073741824; // convert bytes to GB @@ -53,6 +54,6 @@ private function totalMemory() throw new RuntimeException('Operating system not supported!'); } - return (int) trim($output); + return (int) round(trim($output)); } } diff --git a/src/Events/PostDeployEvent.php b/src/Events/PostDeployEvent.php index 3331502..eac3695 100644 --- a/src/Events/PostDeployEvent.php +++ b/src/Events/PostDeployEvent.php @@ -6,7 +6,7 @@ use Appkeep\Laravel\Contexts\GitContext; use Appkeep\Laravel\Contexts\SpecsContext; use Illuminate\Console\Scheduling\Schedule; -use Appkeep\Laravel\Support\ScheduledEventId; +use Appkeep\Laravel\Support\ScheduledTaskId; /** * This event sends data that changes with every deployment to Appkeep. @@ -48,14 +48,14 @@ private function getScheduledTasks() // We can't track scheduled events without a signature (callbacks) // We also don't want to track scheduled events that won't fire off in this environment anyway. ->filter(function ($event) { - return $event->command && empty($event->environments) || in_array( + return $event->command && (empty($event->environments) || in_array( app()->environment(), $event->environments - ); + )); }) ->map(function ($event) { return [ - 'id' => ScheduledEventId::get($event), + 'id' => ScheduledTaskId::get($event), 'command' => $event->command, 'description' => $event->description, 'expression' => $event->expression, diff --git a/src/Events/ScheduledTaskEvent.php b/src/Events/ScheduledTaskEvent.php new file mode 100644 index 0000000..16ea05f --- /dev/null +++ b/src/Events/ScheduledTaskEvent.php @@ -0,0 +1,32 @@ + [ + 'id' => $this->output->id, + 'success' => $this->output->success, + 'duration' => $this->output->duration, + 'output' => $this->output->output, + 'started_at' => $this->output->startedAt, + 'finished_at' => $this->output->finishedAt, + ], + ] + ); + } +} diff --git a/src/HttpClient.php b/src/HttpClient.php index b46d98e..7b6c80b 100644 --- a/src/HttpClient.php +++ b/src/HttpClient.php @@ -5,6 +5,7 @@ use Appkeep\Laravel\Facades\Appkeep; use Illuminate\Support\Facades\Http; use Appkeep\Laravel\Events\AbstractEvent; +use Appkeep\Laravel\Events\ScheduledTaskEvent; class HttpClient { @@ -23,12 +24,20 @@ public function __construct($key) */ public function sendEvent(AbstractEvent $event) { - return Http::withoutVerifying()->withHeaders($this->defaultHeaders())->post( + return Http::withHeaders($this->defaultHeaders())->post( config('appkeep.endpoint'), $event->toArray() ); } + /** + * Send scheduled task result + */ + public function sendScheduledTaskOutput(ScheduledTaskOutput $output) + { + return $this->sendEvent(new ScheduledTaskEvent($output))->throw(); + } + protected function defaultHeaders() { return [ diff --git a/src/ScheduledTaskOutput.php b/src/ScheduledTaskOutput.php new file mode 100644 index 0000000..050d4df --- /dev/null +++ b/src/ScheduledTaskOutput.php @@ -0,0 +1,69 @@ +success = true; + + return $this; + } + + public function failed() + { + $this->success = false; + + return $this; + } + + public function setDuration(float $duration) + { + $this->duration = $duration; + + return $this; + } + + public function setOutput(string $output) + { + $this->output = $output; + + return $this; + } + + public function setStartedAt(DateTime $startedAt) + { + $this->startedAt = $startedAt; + + return $this; + } + + public function setFinishedAt(DateTime $finishedAt) + { + $this->finishedAt = $finishedAt; + + return $this; + } +} diff --git a/src/Support/ScheduledEventId.php b/src/Support/ScheduledTaskId.php similarity index 72% rename from src/Support/ScheduledEventId.php rename to src/Support/ScheduledTaskId.php index 2462b17..a58c04c 100644 --- a/src/Support/ScheduledEventId.php +++ b/src/Support/ScheduledTaskId.php @@ -8,10 +8,10 @@ * Allows us to get a ID for a scheduled event. * This way we can match up pings from events to records on Appkeep server. */ -class ScheduledEventId +class ScheduledTaskId { public static function get(Event $event) { - return hash('md5', $event->command . '-' . $event->expression); + return hash('md5', 'laravel-' . $event->command . '-' . $event->expression); } }