/
job_history.go
145 lines (127 loc) · 2.95 KB
/
job_history.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package models
import (
"fmt"
"os"
"strings"
"time"
"github.com/flanksource/commons/logger"
"github.com/flanksource/duty/types"
"github.com/google/uuid"
"gorm.io/gorm"
)
type JobStatus string
const (
StatusRunning = "RUNNING"
StatusSuccess = "SUCCESS"
StatusWarning = "WARNING"
StatusFinished = "FINISHED"
StatusFailed = "FAILED"
StatusSkipped = "SKIPPED"
)
type JobHistory struct {
ID uuid.UUID `gorm:"default:generate_ulid()"`
Name string
SuccessCount int
ErrorCount int
Hostname string
DurationMillis int64
ResourceType string
ResourceID string
Details types.JSONMap
Status string
TimeStart time.Time
TimeEnd *time.Time
Errors []string `gorm:"-"`
Logger logger.Logger `gorm:"-"`
}
func (j JobHistory) AsError() error {
if len(j.Errors) == 0 {
return nil
}
return fmt.Errorf(strings.Join(j.Errors, ","))
}
func (j JobHistory) TableName() string {
return "job_history"
}
func NewJobHistory(log logger.Logger, name, resourceType, resourceID string) *JobHistory {
return &JobHistory{
Name: name,
ResourceType: resourceType,
ResourceID: resourceID,
Logger: log,
}
}
func (h *JobHistory) Start() *JobHistory {
h.TimeStart = time.Now()
h.Status = StatusRunning
h.Hostname, _ = os.Hostname()
return h
}
func (h *JobHistory) End() *JobHistory {
timeEnd := time.Now()
h.TimeEnd = &timeEnd
h.DurationMillis = timeEnd.Sub(h.TimeStart).Milliseconds()
h.Details = map[string]any{
"errors": h.Errors,
}
h.evaluateStatus()
return h
}
func (h *JobHistory) Persist(db *gorm.DB) error {
return db.Save(h).Error
}
func (h *JobHistory) AddErrorf(msg string, args ...interface{}) *JobHistory {
err := fmt.Sprintf(msg, args...)
h.ErrorCount += 1
if err != "" {
h.Errors = append(h.Errors, err)
}
h.Logger.WithSkipReportLevel(1).Errorf("%s %s", h, err)
return h
}
func (h *JobHistory) AddError(err string) *JobHistory {
h.ErrorCount += 1
if err != "" {
h.Errors = append(h.Errors, err)
}
h.Logger.WithSkipReportLevel(1).Errorf("%s %s", h, err)
return h
}
func (h *JobHistory) AddErrorWithSkipReportLevel(err string, level int) *JobHistory {
h.ErrorCount += 1
if err != "" {
h.Errors = append(h.Errors, err)
}
h.Logger.WithSkipReportLevel(level).Errorf("%s %s", h, err)
return h
}
func (h *JobHistory) String() string {
if h.ResourceID != "" {
return fmt.Sprintf("%s{%s}", h.Name, h.End().ResourceID)
}
return h.Name
}
func (h *JobHistory) IncrSuccess() *JobHistory {
h.SuccessCount += 1
return h
}
// EvaluateStatus updates the Status field of JobHistory based on the counts of
// Success and Error in it.
func (h *JobHistory) evaluateStatus() {
if h.Status != StatusRunning {
return
}
if h.SuccessCount == 0 {
if h.ErrorCount > 0 {
h.Status = StatusFailed
} else {
h.Status = StatusFinished
}
} else {
if h.ErrorCount == 0 {
h.Status = StatusSuccess
} else {
h.Status = StatusWarning
}
}
}