aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--index.html137
1 files changed, 137 insertions, 0 deletions
diff --git a/index.html b/index.html
index e12adeb..018e021 100644
--- a/index.html
+++ b/index.html
@@ -12,6 +12,15 @@
h1, .h1 {
margin-top: 20px;
}
+td > code {
+ color: inherit;
+}
+.mark-success {
+ color: #00d100;
+}
+.mark-failure {
+ color: red;
+}
</style>
</head>
<body>
@@ -36,6 +45,11 @@ h1, .h1 {
<pre class="pre-scrollable" id="top"></pre>
</div>
<hr>
+ <p><button type="button" class="btn btn-outline-primary btn-sm button-expand" data-toggle="collapse" data-target="#collapse_docker">+</button><a href="#collapse_docker" data-toggle="collapse"><code>docker ps -a</code></a></p>
+ <div class="collapse" id="collapse_docker">
+ <div id="docker">No data has been loaded yet.</div>
+ </div>
+ <hr>
<p><button type="button" class="btn btn-outline-primary btn-sm button-expand" data-toggle="collapse" data-target="#collapse_failed_system">+</button><a href="#collapse_failed_system" data-toggle="collapse"><code>systemctl --system list-units --failed</code></a></p>
<div class="collapse show" id="collapse_failed_system">
<pre class="pre-scrollable" id="failed_system"></pre>
@@ -64,6 +78,37 @@ h1, .h1 {
<script src="js/jquery-3.3.1.min.js"></script>
<script src="js/bootstrap.bundle.min.js"></script>
<script>
+function format_duration(duration) {
+ let MSECS_IN_MIN = 60 * 1000;
+ let MSECS_IN_HOUR = 60 * MSECS_IN_MIN;
+ let MSECS_IN_DAY = 24 * MSECS_IN_HOUR;
+
+ let days = Math.floor(duration / MSECS_IN_DAY);
+ duration -= days * MSECS_IN_DAY;
+
+ let hours = Math.floor(duration / MSECS_IN_HOUR);
+ duration -= hours * MSECS_IN_HOUR;
+
+ let mins = Math.floor(duration / MSECS_IN_MIN);
+ duration -= mins * MSECS_IN_MIN;
+
+ if (days > 0) {
+ let result = `${days}d`;
+ if (days == 1 && hours > 0)
+ result += ` ${hours}h`;
+ return result;
+ }
+
+ if (hours > 0) {
+ let result = `${hours}h`;
+ if (hours == 1 && mins > 0)
+ result += ` ${mins}m`;
+ return result;
+ }
+
+ return ` ${mins}m`;
+}
+
function dump_fail(data) {
console.log('Response code was: ' + data.status + ' ' + data.statusText);
console.log('Response was:\n' + data.responseText);
@@ -103,7 +148,99 @@ function loop_top() {
$('#top_refresh_interval').text(top_refresh_interval_seconds);
}
+function docker_container_is_ok(info) {
+ if (info.status == 'restarting' || info.status == 'dead')
+ return false;
+ if (info.status == 'exited' && info.exit_code != 0)
+ return false;
+ if (info.health == 'unhealthy')
+ return false;
+ return true;
+}
+
+function docker_container_format_status(info) {
+ let result = info.status;
+ result = result.charAt(0).toUpperCase() + result.slice(1);
+
+ if (info.status == 'exited' && info.exit_code != 0)
+ result += ` (${info.exit_code})`;
+
+ if (info.status == 'running') {
+ if (info.health == 'unhealthy') {
+ result = 'Up (unhealthy)';
+ } else {
+ let since = new Date(info.started_at);
+ result = `Up ${format_duration(Date.now() - since)}`;
+ }
+ }
+
+ return result;
+}
+
+function docker_fill_data(data) {
+ data.forEach(function(info) {
+ info.ok = docker_container_is_ok(info);
+ info.pretty_status = docker_container_format_status(info);
+ });
+}
+
+function make_docker_table_header() {
+ return $('<thead/>')
+ .append($('<tr/>')
+ .append($('<th/>'))
+ .append($('<th/>').text('Container'))
+ .append($('<th/>').text('Image'))
+ .append($('<th/>').text('Status')));
+}
+
+function make_docker_table_row(info) {
+ let success_mark = $('<span/>', {'class': 'mark-success'}).html('&#10004;');
+ let failure_mark = $('<span/>', {'class': 'mark-failure'}).html('&#10008;');
+ let success_class = 'table-light';
+ let failure_class = 'table-warning';
+
+ let mark = success_mark;
+ let _class = success_class;
+ if (!info.ok) {
+ mark = failure_mark;
+ _class = failure_class;
+ }
+
+ return $('<tr/>', {'class': _class})
+ .append($('<td/>').html(mark))
+ .append($('<td/>').append($('<code/>').text(info.name)))
+ .append($('<td/>').append($('<code/>').text(info.image)))
+ .append($('<td/>').text(info.pretty_status));
+}
+
+function make_docker_table(data) {
+ let body = $('<tbody/>');
+ data.forEach(function(info) {
+ body.append(make_docker_table_row(info));
+ });
+ let table = $('<div/>', {'class': 'table-responsive'})
+ .append($('<table/>', {'class': 'table table-hover table-sm text-nowrap'})
+ .append(make_docker_table_header())
+ .append(body));
+ return table;
+}
+
+function set_docker(data) {
+ docker_fill_data(data);
+
+ $('#docker').empty();
+ $('#docker').append(make_docker_table(data));
+
+ data.forEach(function(info) {
+ if (!info.ok)
+ $('#collapse_docker').addClass('show');
+ });
+}
+
function set_system(data) {
+ if ('docker' in data) {
+ set_docker(data['docker']);
+ }
if ('failed' in data) {
$('#failed_system').text(data['failed']);
}