build-logs: surface runtime_secs in header; show duration in dashboard row
This commit is contained in:
parent
e99330ef0f
commit
26c9c13cf5
2 changed files with 30 additions and 4 deletions
|
|
@ -1126,10 +1126,19 @@ window.marked = marked;
|
||||||
: 'running';
|
: 'running';
|
||||||
const age = h.started_at
|
const age = h.started_at
|
||||||
? fmtAgeSecs(nowUnix - h.started_at) + ' ago' : '?';
|
? fmtAgeSecs(nowUnix - h.started_at) + ' ago' : '?';
|
||||||
|
const runtimeSpan = h.runtime_secs != null
|
||||||
|
? el('span', { class: 'build-logs-runtime meta' }, fmtDuration(h.runtime_secs))
|
||||||
|
: h.started_at && !h.finished_at
|
||||||
|
? el('span', {
|
||||||
|
class: 'build-logs-runtime meta',
|
||||||
|
'data-bl-elapsed': String(h.started_at),
|
||||||
|
}, fmtElapsed(Math.max(0, nowUnix - h.started_at)))
|
||||||
|
: null;
|
||||||
const rowBtn = el('button',
|
const rowBtn = el('button',
|
||||||
{ type: 'button', class: 'build-logs-row-btn', 'aria-expanded': 'false' },
|
{ type: 'button', class: 'build-logs-row-btn', 'aria-expanded': 'false' },
|
||||||
el('span', { class: `badge ${statusCls}` }, statusLabel),
|
el('span', { class: `badge ${statusCls}` }, statusLabel),
|
||||||
el('span', { class: 'build-logs-kind' }, h.kind),
|
el('span', { class: 'build-logs-kind' }, h.kind),
|
||||||
|
runtimeSpan,
|
||||||
el('span', { class: 'build-logs-age meta' }, age),
|
el('span', { class: 'build-logs-age meta' }, age),
|
||||||
el('span', { class: 'build-logs-cmdline meta' }, h.cmdline),
|
el('span', { class: 'build-logs-cmdline meta' }, h.cmdline),
|
||||||
);
|
);
|
||||||
|
|
@ -2192,6 +2201,12 @@ window.marked = marked;
|
||||||
const elapsed = Math.max(0, Math.floor(Date.now() / 1000 - started));
|
const elapsed = Math.max(0, Math.floor(Date.now() / 1000 - started));
|
||||||
span.textContent = '· ' + fmtElapsed(elapsed);
|
span.textContent = '· ' + fmtElapsed(elapsed);
|
||||||
}
|
}
|
||||||
|
for (const span of document.querySelectorAll('.build-logs-runtime[data-bl-elapsed]')) {
|
||||||
|
const started = parseInt(span.dataset.blElapsed, 10);
|
||||||
|
if (!started) continue;
|
||||||
|
const elapsed = Math.max(0, Math.floor(Date.now() / 1000 - started));
|
||||||
|
span.textContent = fmtElapsed(elapsed);
|
||||||
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
// ─── reminders ──────────────────────────────────────────────────────────
|
// ─── reminders ──────────────────────────────────────────────────────────
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,9 @@ pub struct BuildLogHeader {
|
||||||
pub started_at: i64,
|
pub started_at: i64,
|
||||||
pub finished_at: Option<i64>,
|
pub finished_at: Option<i64>,
|
||||||
pub status: Option<String>,
|
pub status: Option<String>,
|
||||||
|
/// Elapsed seconds from `started_at` to `finished_at`. `None` while
|
||||||
|
/// the build is still in progress.
|
||||||
|
pub runtime_secs: Option<i64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Full row with stdout/stderr text inlined. Returned by `get_full`,
|
/// Full row with stdout/stderr text inlined. Returned by `get_full`,
|
||||||
|
|
@ -328,15 +331,19 @@ impl BuildLogs {
|
||||||
)?;
|
)?;
|
||||||
let row = stmt
|
let row = stmt
|
||||||
.query_row(params![id], |r| {
|
.query_row(params![id], |r| {
|
||||||
|
let started_at: i64 = r.get(4)?;
|
||||||
|
let finished_at: Option<i64> = r.get(5)?;
|
||||||
|
let runtime_secs = finished_at.map(|f| f - started_at);
|
||||||
Ok(BuildLogFull {
|
Ok(BuildLogFull {
|
||||||
header: BuildLogHeader {
|
header: BuildLogHeader {
|
||||||
id: r.get(0)?,
|
id: r.get(0)?,
|
||||||
agent: r.get(1)?,
|
agent: r.get(1)?,
|
||||||
kind: r.get(2)?,
|
kind: r.get(2)?,
|
||||||
cmdline: r.get(3)?,
|
cmdline: r.get(3)?,
|
||||||
started_at: r.get(4)?,
|
started_at,
|
||||||
finished_at: r.get(5)?,
|
finished_at,
|
||||||
status: r.get(6)?,
|
status: r.get(6)?,
|
||||||
|
runtime_secs,
|
||||||
},
|
},
|
||||||
stdout: r.get(7)?,
|
stdout: r.get(7)?,
|
||||||
stderr: r.get(8)?,
|
stderr: r.get(8)?,
|
||||||
|
|
@ -404,14 +411,18 @@ pub fn spawn_vacuum(coord: &Arc<crate::coordinator::Coordinator>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn row_to_header(r: &rusqlite::Row) -> rusqlite::Result<BuildLogHeader> {
|
fn row_to_header(r: &rusqlite::Row) -> rusqlite::Result<BuildLogHeader> {
|
||||||
|
let started_at: i64 = r.get(4)?;
|
||||||
|
let finished_at: Option<i64> = r.get(5)?;
|
||||||
|
let runtime_secs = finished_at.map(|f| f - started_at);
|
||||||
Ok(BuildLogHeader {
|
Ok(BuildLogHeader {
|
||||||
id: r.get(0)?,
|
id: r.get(0)?,
|
||||||
agent: r.get(1)?,
|
agent: r.get(1)?,
|
||||||
kind: r.get(2)?,
|
kind: r.get(2)?,
|
||||||
cmdline: r.get(3)?,
|
cmdline: r.get(3)?,
|
||||||
started_at: r.get(4)?,
|
started_at,
|
||||||
finished_at: r.get(5)?,
|
finished_at,
|
||||||
status: r.get(6)?,
|
status: r.get(6)?,
|
||||||
|
runtime_secs,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue