Skip to content

Commit 68cc6eb

Browse files
authored
Merge pull request #1968 from CachetHQ/system-status-api
Implement the system status api endpoint
2 parents 0cd3ea0 + fdfebc1 commit 68cc6eb

File tree

8 files changed

+217
-37
lines changed

8 files changed

+217
-37
lines changed

app/Composers/StatusPageComposer.php

+27-37
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,38 @@
1111

1212
namespace CachetHQ\Cachet\Composers;
1313

14+
use CachetHQ\Cachet\Integrations\Core\System;
1415
use CachetHQ\Cachet\Models\Component;
1516
use CachetHQ\Cachet\Models\ComponentGroup;
1617
use CachetHQ\Cachet\Models\Incident;
1718
use Illuminate\Contracts\View\View;
1819

20+
/**
21+
* This is the status page composer.
22+
*
23+
* @author James Brooks <james@alt-three.com>
24+
*/
1925
class StatusPageComposer
2026
{
27+
/**
28+
* The system instance.
29+
*
30+
* @var \CachetHQ\Cachet\Integrations\Contracts\System
31+
*/
32+
protected $system;
33+
34+
/**
35+
* Create a new status page composer instance.
36+
*
37+
* @param \CachetHQ\Cachet\Integrations\Contracts\System $system
38+
*
39+
* @return void
40+
*/
41+
public function __construct(System $system)
42+
{
43+
$this->system = $system;
44+
}
45+
2146
/**
2247
* Index page view composer.
2348
*
@@ -27,42 +52,7 @@ class StatusPageComposer
2752
*/
2853
public function compose(View $view)
2954
{
30-
$totalComponents = Component::enabled()->count();
31-
$majorOutages = Component::enabled()->status(4)->count();
32-
$isMajorOutage = $totalComponents ? ($majorOutages / $totalComponents) >= 0.5 : false;
33-
34-
// Default data
35-
$withData = [
36-
'system_status' => 'info',
37-
'system_message' => trans_choice('cachet.service.bad', $totalComponents),
38-
'favicon' => 'favicon-high-alert',
39-
];
40-
41-
if ($isMajorOutage) {
42-
$withData = [
43-
'system_status' => 'danger',
44-
'system_message' => trans_choice('cachet.service.major', $totalComponents),
45-
'favicon' => 'favicon-high-alert',
46-
];
47-
} elseif (Component::enabled()->notStatus(1)->count() === 0) {
48-
// If all our components are ok, do we have any non-fixed incidents?
49-
$incidents = Incident::notScheduled()->orderBy('created_at', 'desc')->get()->filter(function ($incident) {
50-
return $incident->status > 0;
51-
});
52-
$incidentCount = $incidents->count();
53-
54-
if ($incidentCount === 0 || ($incidentCount >= 1 && (int) $incidents->first()->status === 4)) {
55-
$withData = [
56-
'system_status' => 'success',
57-
'system_message' => trans_choice('cachet.service.good', $totalComponents),
58-
'favicon' => 'favicon',
59-
];
60-
}
61-
} else {
62-
if (Component::enabled()->whereIn('status', [2, 3])->count() > 0) {
63-
$withData['favicon'] = 'favicon-medium-alert';
64-
}
65-
}
55+
$status = $this->system->getStatus();
6656

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

75-
$view->with($withData)
65+
$view->with($status)
7666
->withComponentGroups($componentGroups)
7767
->withUngroupedComponents($ungroupedComponents)
7868
->withScheduledMaintenance($scheduledMaintenance);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
/*
4+
* This file is part of Cachet.
5+
*
6+
* (c) Alt Three Services Limited
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace CachetHQ\Cachet\Foundation\Providers;
13+
14+
use CachetHQ\Cachet\Integrations\Contracts\System as SystemContract;
15+
use CachetHQ\Cachet\Integrations\Core\System;
16+
use Illuminate\Contracts\Container\Container;
17+
use Illuminate\Support\ServiceProvider;
18+
19+
/**
20+
* This is the integration service provider.
21+
*
22+
* @author James Brooks <james@alt-three.com>
23+
*/
24+
class IntegrationServiceProvider extends ServiceProvider
25+
{
26+
/**
27+
* Register the service provider.
28+
*
29+
* @return void
30+
*/
31+
public function register()
32+
{
33+
$this->registerSystem();
34+
}
35+
36+
/**
37+
* Register the system class.
38+
*
39+
* @return void
40+
*/
41+
protected function registerSystem()
42+
{
43+
$this->app->singleton(SystemContract::class, function (Container $app) {
44+
return new System();
45+
});
46+
}
47+
}

app/Http/Controllers/Api/GeneralController.php

+13
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace CachetHQ\Cachet\Http\Controllers\Api;
1313

14+
use CachetHQ\Cachet\Integrations\Contracts\System;
1415
use CachetHQ\Cachet\Integrations\Releases;
1516

1617
/**
@@ -44,4 +45,16 @@ public function version()
4445
'latest' => $latest,
4546
])->item(CACHET_VERSION);
4647
}
48+
49+
/**
50+
* Get the system status message.
51+
*
52+
* @return \Illuminate\Http\JsonResponse
53+
*/
54+
public function status()
55+
{
56+
$system = app()->make(System::class)->getStatus();
57+
58+
return $this->item($system['system_message']);
59+
}
4760
}

app/Http/Routes/ApiRoutes.php

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public function map(Registrar $router)
3333
$router->group(['middleware' => ['auth.api']], function (Registrar $router) {
3434
$router->get('ping', 'GeneralController@ping');
3535
$router->get('version', 'GeneralController@version');
36+
$router->get('status', 'GeneralController@status');
3637

3738
$router->get('components', 'ComponentController@getComponents');
3839
$router->get('components/groups', 'ComponentGroupController@getGroups');

app/Integrations/Contracts/System.php

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
/*
4+
* This file is part of Cachet.
5+
*
6+
* (c) Alt Three Services Limited
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace CachetHQ\Cachet\Integrations\Contracts;
13+
14+
/**
15+
* This is the system interface.
16+
*
17+
* @author James Brooks <james@alt-three.com>
18+
*/
19+
interface System
20+
{
21+
/**
22+
* Get the entire system status.
23+
*
24+
* @return array
25+
*/
26+
public function getStatus();
27+
}

app/Integrations/Core/System.php

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
/*
4+
* This file is part of Cachet.
5+
*
6+
* (c) Alt Three Services Limited
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace CachetHQ\Cachet\Integrations\Core;
13+
14+
use CachetHQ\Cachet\Integrations\Contracts\System as SystemContract;
15+
use CachetHQ\Cachet\Models\Component;
16+
use CachetHQ\Cachet\Models\Incident;
17+
18+
/**
19+
* This is the core system class.
20+
*
21+
* @author James Brooks <james@alt-three.com>
22+
*/
23+
class System implements SystemContract
24+
{
25+
/**
26+
* Get the entire system status.
27+
*
28+
* @return array
29+
*/
30+
public function getStatus()
31+
{
32+
$enabledScope = Component::enabled();
33+
$totalComponents = Component::enabled()->count();
34+
$majorOutages = Component::enabled()->status(4)->count();
35+
$isMajorOutage = $totalComponents ? ($majorOutages / $totalComponents) >= 0.5 : false;
36+
37+
// Default data
38+
$status = [
39+
'system_status' => 'info',
40+
'system_message' => trans_choice('cachet.service.bad', $totalComponents),
41+
'favicon' => 'favicon-high-alert',
42+
];
43+
44+
if ($isMajorOutage) {
45+
$status = [
46+
'system_status' => 'danger',
47+
'system_message' => trans_choice('cachet.service.major', $totalComponents),
48+
'favicon' => 'favicon-high-alert',
49+
];
50+
} elseif (Component::enabled()->notStatus(1)->count() === 0) {
51+
// If all our components are ok, do we have any non-fixed incidents?
52+
$incidents = Incident::notScheduled()->orderBy('created_at', 'desc')->get()->filter(function ($incident) {
53+
return $incident->status > 0;
54+
});
55+
$incidentCount = $incidents->count();
56+
57+
if ($incidentCount === 0 || ($incidentCount >= 1 && (int) $incidents->first()->status === 4)) {
58+
$status = [
59+
'system_status' => 'success',
60+
'system_message' => trans_choice('cachet.service.good', $totalComponents),
61+
'favicon' => 'favicon',
62+
];
63+
}
64+
} elseif (Component::enabled()->whereIn('status', [2, 3])->count() > 0) {
65+
$status['favicon'] = 'favicon-medium-alert';
66+
}
67+
68+
return $status;
69+
}
70+
}

config/app.php

+1
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@
184184
'CachetHQ\Cachet\Foundation\Providers\ComposerServiceProvider',
185185
'CachetHQ\Cachet\Foundation\Providers\ConsoleServiceProvider',
186186
'CachetHQ\Cachet\Foundation\Providers\ConfigServiceProvider',
187+
'CachetHQ\Cachet\Foundation\Providers\IntegrationServiceProvider',
187188
'CachetHQ\Cachet\Foundation\Providers\EventServiceProvider',
188189
'CachetHQ\Cachet\Foundation\Providers\RepositoryServiceProvider',
189190
'CachetHQ\Cachet\Foundation\Providers\RouteServiceProvider',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
/*
4+
* This file is part of Cachet.
5+
*
6+
* (c) Alt Three Services Limited
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace CachetHQ\Tests\Cachet\Foundation\Providers;
13+
14+
use AltThree\TestBench\ServiceProviderTrait;
15+
use CachetHQ\Cachet\Integrations\Contracts\System;
16+
use CachetHQ\Tests\Cachet\AbstractTestCase;
17+
18+
/**
19+
* This is the integration service provider test class.
20+
*
21+
* @author James Brooks <james@alt-three.com>
22+
*/
23+
class IntegrationServiceProviderTest extends AbstractTestCase
24+
{
25+
use ServiceProviderTrait;
26+
27+
public function testSystemIsInjectable()
28+
{
29+
$this->assertIsInjectable(System::class);
30+
}
31+
}

0 commit comments

Comments
 (0)