Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the system status api endpoint #1968

Merged
merged 1 commit into from
Jul 13, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 27 additions & 37 deletions app/Composers/StatusPageComposer.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,38 @@

namespace CachetHQ\Cachet\Composers;

use CachetHQ\Cachet\Integrations\Core\System;
use CachetHQ\Cachet\Models\Component;
use CachetHQ\Cachet\Models\ComponentGroup;
use CachetHQ\Cachet\Models\Incident;
use Illuminate\Contracts\View\View;

/**
* This is the status page composer.
*
* @author James Brooks <[email protected]>
*/
class StatusPageComposer
{
/**
* The system instance.
*
* @var \CachetHQ\Cachet\Integrations\Contracts\System
*/
protected $system;

/**
* Create a new status page composer instance.
*
* @param \CachetHQ\Cachet\Integrations\Contracts\System $system
*
* @return void
*/
public function __construct(System $system)
{
$this->system = $system;
}

/**
* Index page view composer.
*
Expand All @@ -27,42 +52,7 @@ class StatusPageComposer
*/
public function compose(View $view)
{
$totalComponents = Component::enabled()->count();
$majorOutages = Component::enabled()->status(4)->count();
$isMajorOutage = $totalComponents ? ($majorOutages / $totalComponents) >= 0.5 : false;

// Default data
$withData = [
'system_status' => 'info',
'system_message' => trans_choice('cachet.service.bad', $totalComponents),
'favicon' => 'favicon-high-alert',
];

if ($isMajorOutage) {
$withData = [
'system_status' => 'danger',
'system_message' => trans_choice('cachet.service.major', $totalComponents),
'favicon' => 'favicon-high-alert',
];
} elseif (Component::enabled()->notStatus(1)->count() === 0) {
// If all our components are ok, do we have any non-fixed incidents?
$incidents = Incident::notScheduled()->orderBy('created_at', 'desc')->get()->filter(function ($incident) {
return $incident->status > 0;
});
$incidentCount = $incidents->count();

if ($incidentCount === 0 || ($incidentCount >= 1 && (int) $incidents->first()->status === 4)) {
$withData = [
'system_status' => 'success',
'system_message' => trans_choice('cachet.service.good', $totalComponents),
'favicon' => 'favicon',
];
}
} else {
if (Component::enabled()->whereIn('status', [2, 3])->count() > 0) {
$withData['favicon'] = 'favicon-medium-alert';
}
}
$status = $this->system->getStatus();

// Scheduled maintenance code.
$scheduledMaintenance = Incident::scheduled()->orderBy('scheduled_at')->get();
Expand All @@ -72,7 +62,7 @@ public function compose(View $view)
$componentGroups = ComponentGroup::whereIn('id', $usedComponentGroups)->orderBy('order')->get();
$ungroupedComponents = Component::enabled()->where('group_id', 0)->orderBy('order')->orderBy('created_at')->get();

$view->with($withData)
$view->with($status)
->withComponentGroups($componentGroups)
->withUngroupedComponents($ungroupedComponents)
->withScheduledMaintenance($scheduledMaintenance);
Expand Down
47 changes: 47 additions & 0 deletions app/Foundation/Providers/IntegrationServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace CachetHQ\Cachet\Foundation\Providers;

use CachetHQ\Cachet\Integrations\Contracts\System as SystemContract;
use CachetHQ\Cachet\Integrations\Core\System;
use Illuminate\Contracts\Container\Container;
use Illuminate\Support\ServiceProvider;

/**
* This is the integration service provider.
*
* @author James Brooks <[email protected]>
*/
class IntegrationServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->registerSystem();
}

/**
* Register the system class.
*
* @return void
*/
protected function registerSystem()
{
$this->app->singleton(SystemContract::class, function (Container $app) {
return new System();
});
}
}
13 changes: 13 additions & 0 deletions app/Http/Controllers/Api/GeneralController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace CachetHQ\Cachet\Http\Controllers\Api;

use CachetHQ\Cachet\Integrations\Contracts\System;
use CachetHQ\Cachet\Integrations\Releases;

/**
Expand Down Expand Up @@ -44,4 +45,16 @@ public function version()
'latest' => $latest,
])->item(CACHET_VERSION);
}

/**
* Get the system status message.
*
* @return \Illuminate\Http\JsonResponse
*/
public function status()
{
$system = app()->make(System::class)->getStatus();

return $this->item($system['system_message']);
}
}
1 change: 1 addition & 0 deletions app/Http/Routes/ApiRoutes.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public function map(Registrar $router)
$router->group(['middleware' => ['auth.api']], function (Registrar $router) {
$router->get('ping', 'GeneralController@ping');
$router->get('version', 'GeneralController@version');
$router->get('status', 'GeneralController@status');

$router->get('components', 'ComponentController@getComponents');
$router->get('components/groups', 'ComponentGroupController@getGroups');
Expand Down
27 changes: 27 additions & 0 deletions app/Integrations/Contracts/System.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace CachetHQ\Cachet\Integrations\Contracts;

/**
* This is the system interface.
*
* @author James Brooks <[email protected]>
*/
interface System
{
/**
* Get the entire system status.
*
* @return array
*/
public function getStatus();
}
70 changes: 70 additions & 0 deletions app/Integrations/Core/System.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace CachetHQ\Cachet\Integrations\Core;

use CachetHQ\Cachet\Integrations\Contracts\System as SystemContract;
use CachetHQ\Cachet\Models\Component;
use CachetHQ\Cachet\Models\Incident;

/**
* This is the core system class.
*
* @author James Brooks <[email protected]>
*/
class System implements SystemContract
{
/**
* Get the entire system status.
*
* @return array
*/
public function getStatus()
{
$enabledScope = Component::enabled();
$totalComponents = Component::enabled()->count();
$majorOutages = Component::enabled()->status(4)->count();
$isMajorOutage = $totalComponents ? ($majorOutages / $totalComponents) >= 0.5 : false;

// Default data
$status = [
'system_status' => 'info',
'system_message' => trans_choice('cachet.service.bad', $totalComponents),
'favicon' => 'favicon-high-alert',
];

if ($isMajorOutage) {
$status = [
'system_status' => 'danger',
'system_message' => trans_choice('cachet.service.major', $totalComponents),
'favicon' => 'favicon-high-alert',
];
} elseif (Component::enabled()->notStatus(1)->count() === 0) {
// If all our components are ok, do we have any non-fixed incidents?
$incidents = Incident::notScheduled()->orderBy('created_at', 'desc')->get()->filter(function ($incident) {
return $incident->status > 0;
});
$incidentCount = $incidents->count();

if ($incidentCount === 0 || ($incidentCount >= 1 && (int) $incidents->first()->status === 4)) {
$status = [
'system_status' => 'success',
'system_message' => trans_choice('cachet.service.good', $totalComponents),
'favicon' => 'favicon',
];
}
} elseif (Component::enabled()->whereIn('status', [2, 3])->count() > 0) {
$status['favicon'] = 'favicon-medium-alert';
}

return $status;
}
}
1 change: 1 addition & 0 deletions config/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@
'CachetHQ\Cachet\Foundation\Providers\ComposerServiceProvider',
'CachetHQ\Cachet\Foundation\Providers\ConsoleServiceProvider',
'CachetHQ\Cachet\Foundation\Providers\ConfigServiceProvider',
'CachetHQ\Cachet\Foundation\Providers\IntegrationServiceProvider',
'CachetHQ\Cachet\Foundation\Providers\EventServiceProvider',
'CachetHQ\Cachet\Foundation\Providers\RepositoryServiceProvider',
'CachetHQ\Cachet\Foundation\Providers\RouteServiceProvider',
Expand Down
31 changes: 31 additions & 0 deletions tests/Foundation/Providers/IntegrationServiceProviderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace CachetHQ\Tests\Cachet\Foundation\Providers;

use AltThree\TestBench\ServiceProviderTrait;
use CachetHQ\Cachet\Integrations\Contracts\System;
use CachetHQ\Tests\Cachet\AbstractTestCase;

/**
* This is the integration service provider test class.
*
* @author James Brooks <[email protected]>
*/
class IntegrationServiceProviderTest extends AbstractTestCase
{
use ServiceProviderTrait;

public function testSystemIsInjectable()
{
$this->assertIsInjectable(System::class);
}
}