diff --git a/src/domain/record.go b/src/domain/record.go index 4ec8b03..e4d5999 100644 --- a/src/domain/record.go +++ b/src/domain/record.go @@ -4,12 +4,13 @@ package domain // output is also written to a log file; the in-memory Output copy exists so the // latest run can be displayed without reopening the log on every repaint. type RunRecord struct { - Time string `yaml:"time"` - JobID int `yaml:"job_id"` - JobName string `yaml:"job_name"` - Trigger string `yaml:"trigger,omitempty"` - State string `yaml:"state"` - Detail string `yaml:"detail"` - LogFile string `yaml:"log_file,omitempty"` - Output string `yaml:"output,omitempty"` + Time string `yaml:"time"` + JobID int `yaml:"job_id"` + JobName string `yaml:"job_name"` + Trigger string `yaml:"trigger,omitempty"` + State string `yaml:"state"` + Detail string `yaml:"detail"` + LogFile string `yaml:"log_file,omitempty"` + Output string `yaml:"output,omitempty"` + DurationMS int64 `yaml:"duration_ms,omitempty"` } diff --git a/src/runner/runner.go b/src/runner/runner.go index 41d5ec9..0e24a96 100644 --- a/src/runner/runner.go +++ b/src/runner/runner.go @@ -27,9 +27,12 @@ func RunJob(ctx context.Context, job *domain.Job, trigger string, logsDir string var output string var state string var detail string + var durationMS int64 if job.StartOnly { invocation := jobInvocation(context.Background(), *job) state, detail, output = startJobOnly(invocation, *job, started) + // StartOnly jobs don't wait for process exit, so no meaningful duration. + durationMS = 0 } else { var stdoutBuf strings.Builder var stderrBuf strings.Builder @@ -44,6 +47,7 @@ func RunJob(ctx context.Context, job *domain.Job, trigger string, logsDir string err := command.Run() duration := time.Since(started).Round(time.Millisecond) + durationMS = duration.Milliseconds() output = formatOutput(stdoutBuf.String(), stderrBuf.String()) state, detail = runStateDetail(err, runCtx.Err(), duration) } @@ -56,14 +60,15 @@ func RunJob(ctx context.Context, job *domain.Job, trigger string, logsDir string // lets the caller fold that record into the job's JobRuntime. Run state no // longer lives on Job, so there is nothing on the job to mutate here. return domain.RunRecord{ - Time: timestamp, - JobID: job.ID, - JobName: job.Name, - Trigger: trigger, - State: state, - Detail: detail, - LogFile: logFile, - Output: output, + Time: timestamp, + JobID: job.ID, + JobName: job.Name, + Trigger: trigger, + State: state, + Detail: detail, + LogFile: logFile, + Output: output, + DurationMS: durationMS, } }