From 5281abcb509dccb2f6b597068c4a090e5cca1e3e Mon Sep 17 00:00:00 2001 From: oppiliappan Date: Thu, 30 Oct 2025 12:04:16 +0000 Subject: [PATCH] appview/pages: show live updating counters for steps spindles can now give us detailed logs for start and end of steps. the appview can ingest these logs to indicate live durations for steps. it is implemented like so: - the logs handler keeps track of start and end times for each step - whenever we recieve a start or end time, we update the html to add a `data-start` or `data-end` attribute - using some javascript, we print a live updating timer for each step: * if only `data-start` is present: then use Now - Start and update each second * if both `data-start` and `data-end` are present, then use End - Start Signed-off-by: oppiliappan --- appview/pages/pages.go | 12 ++++++++++++ appview/pipelines/pipelines.go | 38 +++++++++++++++++++++++++------------- appview/pages/templates/fragments/workflow-timers.html | 36 ++++++++++++++++++++++++++++++++++++ appview/pages/templates/repo/pipelines/workflow.html | 1 + appview/pages/templates/repo/pipelines/fragments/logBlock.html | 13 +++++++------ appview/pages/templates/repo/pipelines/fragments/logBlockEnd.html | 9 +++++++++ 6 file(s) changed, 90 insertion(s)(+), 19 deletion(s)(-) diff --git a/appview/pages/pages.go b/appview/pages/pages.go --- a/appview/pages/pages.go +++ b/appview/pages/pages.go @@ -15,6 +15,7 @@ "path/filepath" "strings" "sync" + "time" "tangled.org/core/api/tangled" "tangled.org/core/appview/commitverify" @@ -1361,10 +1362,21 @@ Name string Command string Collapsed bool + StartTime time.Time } func (p *Pages) LogBlock(w io.Writer, params LogBlockParams) error { return p.executePlain("repo/pipelines/fragments/logBlock", w, params) +} + +type LogBlockEndParams struct { + Id int + StartTime time.Time + EndTime time.Time +} + +func (p *Pages) LogBlockEnd(w io.Writer, params LogBlockEndParams) error { + return p.executePlain("repo/pipelines/fragments/logBlockEnd", w, params) } type LogLineParams struct { diff --git a/appview/pipelines/pipelines.go b/appview/pipelines/pipelines.go --- a/appview/pipelines/pipelines.go +++ b/appview/pipelines/pipelines.go @@ -236,7 +236,7 @@ // start a goroutine to read from spindle go readLogs(spindleConn, evChan) - stepIdx := 0 + stepStartTimes := make(map[int]time.Time) var fragment bytes.Buffer for { select { @@ -268,22 +268,34 @@ switch logLine.Kind { case spindlemodel.LogKindControl: - // control messages create a new step block - stepIdx++ - collapsed := false - if logLine.StepKind == spindlemodel.StepKindSystem { - collapsed = true + switch logLine.StepStatus { + case spindlemodel.StepStatusStart: + stepStartTimes[logLine.StepId] = logLine.Time + collapsed := false + if logLine.StepKind == spindlemodel.StepKindSystem { + collapsed = true + } + err = p.pages.LogBlock(&fragment, pages.LogBlockParams{ + Id: logLine.StepId, + Name: logLine.Content, + Command: logLine.StepCommand, + Collapsed: collapsed, + StartTime: logLine.Time, + }) + case spindlemodel.StepStatusEnd: + startTime := stepStartTimes[logLine.StepId] + endTime := logLine.Time + err = p.pages.LogBlockEnd(&fragment, pages.LogBlockEndParams{ + Id: logLine.StepId, + StartTime: startTime, + EndTime: endTime, + }) } - err = p.pages.LogBlock(&fragment, pages.LogBlockParams{ - Id: stepIdx, - Name: logLine.Content, - Command: logLine.StepCommand, - Collapsed: collapsed, - }) + case spindlemodel.LogKindData: // data messages simply insert new log lines into current step err = p.pages.LogLine(&fragment, pages.LogLineParams{ - Id: stepIdx, + Id: logLine.StepId, Content: logLine.Content, }) } diff --git a/appview/pages/templates/fragments/workflow-timers.html b/appview/pages/templates/fragments/workflow-timers.html new file mode 100644 --- /dev/null +++ b/appview/pages/templates/fragments/workflow-timers.html @@ -0,0 +1,36 @@ +{{ define "fragments/workflow-timers" }} + +{{ end }} diff --git a/appview/pages/templates/repo/pipelines/workflow.html b/appview/pages/templates/repo/pipelines/workflow.html --- a/appview/pages/templates/repo/pipelines/workflow.html +++ b/appview/pages/templates/repo/pipelines/workflow.html @@ -15,6 +15,7 @@ {{ block "logs" . }} {{ end }} +{{ template "fragments/workflow-timers" }} {{ end }} {{ define "sidebar" }} diff --git a/appview/pages/templates/repo/pipelines/fragments/logBlock.html b/appview/pages/templates/repo/pipelines/fragments/logBlock.html --- a/appview/pages/templates/repo/pipelines/fragments/logBlock.html +++ b/appview/pages/templates/repo/pipelines/fragments/logBlock.html @@ -2,14 +2,15 @@
-
- {{ i "chevron-right" "w-4 h-4" }} {{ .Name }} -
- +
{{ template "stepHeader" . }}
+
{{ .Command }}
+{{ end }} + +{{ define "stepHeader" }} + {{ i "chevron-right" "w-4 h-4" }} {{ .Name }} + {{ end }} diff --git a/appview/pages/templates/repo/pipelines/fragments/logBlockEnd.html b/appview/pages/templates/repo/pipelines/fragments/logBlockEnd.html new file mode 100644 --- /dev/null +++ b/appview/pages/templates/repo/pipelines/fragments/logBlockEnd.html @@ -0,0 +1,9 @@ +{{ define "repo/pipelines/fragments/logBlockEnd" }} + +{{ end }} + -- tangled.sh