Skip to content

Commit

Permalink
Clean up API route to get stats of containers
Browse files Browse the repository at this point in the history
  • Loading branch information
nzxl101 committed Sep 19, 2024
1 parent 4c8a600 commit ff1a4ef
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 113 deletions.
4 changes: 2 additions & 2 deletions root/app/www/public/ajax/tasks.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@
<td align="center"><i class="far fa-play-circle text-info" style="cursor: pointer;" onclick="runTask('aliasFile')"></i></td>
</tr>
<tr>
<td>View Dockwatch stats</td>
<td align="center"><i class="far fa-play-circle text-info" style="cursor: pointer;" onclick="runTask('dwStats')"></i></td>
<td>API: View containers</td>
<td align="center"><i class="far fa-play-circle text-info" style="cursor: pointer;" onclick="runTask('containersList')"></i></td>
</tr>
</tbody>
</table>
Expand Down
4 changes: 3 additions & 1 deletion root/app/www/public/functions/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ function apiRequestLocal($endpoint, $parameters = [], $payload = [])
if (!$parameters['name']) {
apiResponse(400, ['error' => 'Missing name parameter']);
}

return $docker->inspect($parameters['name'], $parameters['useCache'], $parameters['format'], $parameters['params']);
case 'docker-logs':
if (!$parameters['name']) {
Expand Down Expand Up @@ -254,6 +254,8 @@ function apiRequestLocal($endpoint, $parameters = [], $payload = [])
}

return defined('DOCKWATCH_COMMITS') && defined('DOCKWATCH_BRANCH') ? 'v' . APP_X . '.' . APP_Y . '.' . DOCKWATCH_COMMITS . ' - ' . DOCKWATCH_BRANCH : 'v0.0.0';
case 'stats-getContainersList':
return apiResponse(200, getContainersList());
default:
apiResponse(405, ['error' => 'Invalid GET request (endpoint=' . $endpoint . ')']);
break;
Expand Down
193 changes: 89 additions & 104 deletions root/app/www/public/functions/stats.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,127 +7,112 @@
----------------------------------
*/

function getStats()
{
function getContainersList() {
global $docker;

$stateFile = getFile(STATE_FILE);
$pullsFile = getFile(PULL_FILE);

$containers = [];
$ports = $networks = [];
$running = $stopped = $memory = $cpu = $network = $size = $updated = $outdated = $healthy = $unhealthy = $unknownhealth = 0;

foreach ($stateFile as $state) {
$size += bytesFromString($state['size']);

$healthStatus = 'Unknown';
if (str_contains($state['Status'], 'healthy')) {
$healthy++;
$healthStatus = 'Healthy';
} elseif (str_contains($state['Status'], 'unhealthy')) {
$unhealthy++;
$healthStatus = 'Unhealthy';
} elseif (!str_contains($state['Status'], 'health')) {
$unknownhealth++;
}

if ($state['State'] == 'running') {
$running++;
} else {
$stopped++;
}
foreach ($stateFile as $container) {
$id = $container['ID'];
$name = $container['Names'];
$image = $container['Image'];
$imageSize = $container['size'];
$status = $container['State'];
$health = $container['inspect'][0]['State']['Health']['Status'];
$createdAt = $container['CreatedAt'];

//-- GET UPDATES
$pullInfo = 'Unchecked';
if ($pullsFile) {
foreach ($pullsFile as $hash => $pull) {
if (md5($state['Names']) == $hash) {
if ($pull['regctlDigest'] == $pull['imageDigest']) {
$updated++;
$pullInfo = 'Updated';
} else {
$outdated++;
$pullInfo = 'Outdated';
}
break;
}
$startedAt = $container['inspect'][0]['State']['StartedAt'];
$uptime = (new DateTime())->diff(new DateTime($startedAt));
$hours = $uptime->h + ($uptime->days * 24);
$minutes = $uptime->i;
$uptime = sprintf('%02dh%02dm', $hours, $minutes);

$networkMode = !empty($container['Networks']) ? $container['Networks'] : 'container:' . explode(':', $container['inspect'][0]['Config']['Labels']['com.docker.compose.depends_on'])[0];

$ports = [];
$portList = explode(',', $container['Ports']);
foreach ($portList as $port) {
$protocol = $ip = $publicPort = $privatePort = $exposedPort = [];

//-- GET PROTOCOL
if (preg_match('/\/(\w+)/', $port, $matches)) {
$protocol = $matches[1];
}
}

//-- GET USED NETWORKS
if ($state['inspect'][0]['NetworkSettings']['Networks']) {
$networkKeys = array_keys($state['inspect'][0]['NetworkSettings']['Networks']);
foreach ($networkKeys as $networkKey) {
$networks[$networkKey]++;
//-- GET IP
if (preg_match('/^(\d+.\d+.\d+.\d+|::)\:/', trim($port), $matches)) {
$ip = $matches[1];
}
} else {
$containerNetwork = $state['inspect'][0]['HostConfig']['NetworkMode'];
if (str_contains($containerNetwork, ':')) {
list($null, $containerId) = explode(':', $containerNetwork);
$containerNetwork = 'container:' . $docker->findContainer(['id' => $containerId, 'data' => $stateFile]);

//-- GET PRIVATE PORT
if (preg_match('/->(\d+)\//', $port, $matches)) {
$privatePort = $matches[1];
}

$networks[$containerNetwork]++;
//-- GET PUBLIC PORT
if (preg_match('/:(\d+)->|->(\d+)\//', $port, $matches)) {
$publicPort = $matches[1];
}

//-- GET EXPOSED PORT
if (preg_match('/:(\d+)\/|^(\d+)\//', $port, $matches)) {
$exposedPort = $matches[1];
}

if (empty($privatePort) && empty($publicPort)) {
continue;
}

$ports[] = [
'ip' => $ip,
'publicPort' => !empty($publicPort) ? $publicPort : $exposedPort,
'privatePort' => $privatePort,
'protocol' => $protocol,
];
}

//-- GET USED PORTS
if ($state['inspect'][0]['HostConfig']['PortBindings']) {
foreach ($state['inspect'][0]['HostConfig']['PortBindings'] as $internalBind => $portBinds) {
foreach ($portBinds as $portBind) {
if ($portBind['HostPort']) {
$ports[$state['Names']][] = $portBind['HostPort'];
}
$dockwatch = [];
foreach ($pullsFile as $hash => $pull) {
if (md5($name) == $hash) {
if ($pull['regctlDigest'] == $pull['imageDigest']) {
$dockwatch['pull'] = 'Up to date';
} else {
$dockwatch['pull'] = 'Outdated';
}

$checked = (new DateTime());
$checked->setTimestamp($pull['checked']);
$dockwatch['lastPull'] = $checked->format('Y-m-d H:i:s');

break;
}
}

//-- GET MEMORY UAGE
$memory += floatval(str_replace('%', '', $state['stats']['MemPerc']));

//-- GET CPU USAGE
$cpu += floatval(str_replace('%', '', $state['stats']['CPUPerc']));

//-- GET NETWORK USAGE
list($netUsed, $netAllowed) = explode(' / ', $state['stats']['NetIO']);
$network += bytesFromString($netUsed);

$containers['containers'][$state['Names']] = [
'id' => $state['ID'],
'image' => $state['Image'],
'ports' => $state['Ports'],
'started' => $state['RunningFor'],
'running' => $state['State'] == 'running' ? true : false,
'status' => $healthStatus,
'size' => $state['size'],
'update' => $pullInfo
];
}
$usage = [];
$usage['cpuPerc'] = $container['stats']['CPUPerc'];
$usage['memPerc'] = $container['stats']['MemPerc'];
$usage['memSize'] = $container['stats']['MemUsage'];
$usage['blockIO'] = $container['stats']['BlockIO'];
$usage['netIO'] = $container['stats']['NetIO'];

return [
...$containers,
'status' => [
'running' => $running,
'stopped' => $stopped,
'total' => ($running + $stopped),
],
'health' => [
'healthy' => $healthy,
'unhealthy' => $unhealthy,
'unknown' => $unknownhealth
],
'updates' => [
'updated' => $updated,
'outdated' => $outdated,
'unchecked' => (($running + $stopped) - ($updated + $outdated))
],
'usage' => [
'disk' => byteConversion($size),
'cpu' => $cpu,
'memory' => $memory,
'network' => byteConversion($network)
],
'networks' => $networks,
'ports' => $ports
$containers[] = [
'id' => $id,
'name' => $name,
'image' => $image,
'imageSize' => $imageSize,
'status' => $status,
'health' => $health,
'createdAt' => $createdAt,
'uptime' => $uptime,
'networkMode' => $networkMode,
'ports' => $ports,
'dockwatch' => $dockwatch,
'usage' => $usage
];
}

return $containers;
}
4 changes: 2 additions & 2 deletions root/app/www/public/functions/tasks.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ function executeTask($task)
return json_encode(getFile(STATE_FILE), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
case 'dependencyFile':
return json_encode(getFile(DEPENDENCY_FILE), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
case 'dwStats':
return json_encode(getStats(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
case 'containersList':
return json_encode(getContainersList(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
default:
return 'Invalid task requested (task=' . $task . ')';
}
Expand Down
10 changes: 6 additions & 4 deletions root/app/www/public/loader.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,11 @@
$pullsFile = apiRequest('file-pull')['result'];
}

$fetchProc = in_array($_POST['page'], $getProc) || $_POST['hash'] || $_GET['request'] == 'dwStats';
$fetchStats = in_array($_POST['page'], $getStats) || $_POST['hash'] || $_GET['request'] == 'dwStats';
$fetchInspect = in_array($_POST['page'], $getInspect) || $_POST['hash'] || $_GET['request'] == 'dwStats';
$getContainersList = $_GET['request'] === 'stats-getContainersList';

$fetchProc = in_array($_POST['page'], $getProc) || $_POST['hash'] || $getContainersList;
$fetchStats = in_array($_POST['page'], $getStats) || $_POST['hash'] || $getContainersList;
$fetchInspect = in_array($_POST['page'], $getInspect) || $_POST['hash'] || $getContainersList;

$loadTimes[] = trackTime('getExpandedProcessList ->');
$getExpandedProcessList = getExpandedProcessList($fetchProc, $fetchStats, $fetchInspect);
Expand All @@ -156,7 +158,7 @@
$loadTimes[] = trackTime('getExpandedProcessList <-');

//-- UPDATE THE STATE FILE WHEN EVERYTHING IS FETCHED
if ($_POST['page'] == 'overview' || $_POST['page'] == 'containers' || $_GET['request'] == 'dwStats') {
if ($_POST['page'] == 'overview' || $_POST['page'] == 'containers' || $getContainersList) {
if ($processList) {
apiRequest('file-state', [], ['contents' => $processList]);
}
Expand Down

0 comments on commit ff1a4ef

Please sign in to comment.