-
Notifications
You must be signed in to change notification settings - Fork 168
/
statistic.go
145 lines (122 loc) · 3.84 KB
/
statistic.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 statistic
import (
"fmt"
"strconv"
"time"
"github.com/caicloud/nirvana/log"
"github.com/caicloud/cyclone/pkg/apis/cyclone/v1alpha1"
api "github.com/caicloud/cyclone/pkg/server/apis/v1alpha1"
)
// Stats counts every StatusPhase number of wfrs, and calculate success ratio of the workflowruns.
func Stats(list *v1alpha1.WorkflowRunList, startTime, endTime string) (*api.Statistic, error) {
start, end, err := checkAndTransTimes(startTime, endTime)
if err != nil {
return nil, err
}
log.Infof("stats wfrs length: %d, start time: %s, end time: %s", len(list.Items), start.String(), end.String())
// filter all wfr by : start < creationTimestamp < end
wfrs := make([]v1alpha1.WorkflowRun, 0)
for _, wfr := range list.Items {
t := wfr.CreationTimestamp.Time
if t.Before(end) && t.After(start) {
wfrs = append(wfrs, wfr)
}
}
statistics := &api.Statistic{
Overview: api.StatsOverview{
Total: len(wfrs),
SuccessRatio: "0.00%",
},
Details: []*api.StatsDetail{},
}
initStatsDetails(statistics, start, end)
for _, wfr := range wfrs {
for _, detail := range statistics.Details {
if detail.Timestamp == formatTimeToDay(wfr.CreationTimestamp.Time) {
// set details status
detail.StatsPhase = statsStatus(detail.StatsPhase, wfr.Status.Overall.Phase)
}
}
// set overview status
statistics.Overview.StatsPhase = statsStatus(statistics.Overview.StatsPhase, wfr.Status.Overall.Phase)
}
if statistics.Overview.Total != 0 {
statistics.Overview.SuccessRatio = fmt.Sprintf("%.2f%%",
float64(statistics.Overview.Succeeded)/float64(statistics.Overview.Total)*100)
}
return statistics, nil
}
// checkAndTransTimes validates start, end times; and translates them to time.Time format.
func checkAndTransTimes(start, end string) (time.Time, time.Time, error) {
var startTime, endTime time.Time
if start == "" || end == "" {
err := fmt.Errorf(" `startTime` and `endTime` can not be empty")
return startTime, endTime, err
}
startTime, endTime, err := transTimes(start, end)
if err != nil {
err := fmt.Errorf("`startTime` and `endTime` must be int positive integer")
return startTime, endTime, err
}
if startTime.After(endTime) {
err := fmt.Errorf("`startTime` must less or equal than `endTime`")
return startTime, endTime, err
}
return startTime, endTime, nil
}
// transTimes trans startTime and endTime from string to time.Time.
func transTimes(start, end string) (time.Time, time.Time, error) {
var startTime, endTime time.Time
startInt, err := strconv.ParseInt(start, 10, 64)
if err != nil {
return startTime, endTime, err
}
startTime = time.Unix(startInt, 0)
endInt, err := strconv.ParseInt(end, 10, 64)
if err != nil {
return startTime, endTime, err
}
endTime = time.Unix(endInt, 0)
return startTime, endTime, nil
}
func initStatsDetails(statistics *api.Statistic, start, end time.Time) {
for ; !start.After(end); start = start.Add(24 * time.Hour) {
detail := &api.StatsDetail{
Timestamp: formatTimeToDay(start),
}
statistics.Details = append(statistics.Details, detail)
}
// if last day not equal end day, append end day.
endDay := formatTimeToDay(end)
length := len(statistics.Details)
if length > 0 {
if statistics.Details[length-1].Timestamp != endDay {
detail := &api.StatsDetail{
Timestamp: endDay,
}
statistics.Details = append(statistics.Details, detail)
}
}
}
func formatTimeToDay(t time.Time) int64 {
timestamp := t.Unix()
return timestamp - (timestamp % 86400)
}
func statsStatus(s api.StatsPhase, recordStatus v1alpha1.StatusPhase) api.StatsPhase {
switch recordStatus {
case v1alpha1.StatusSucceeded:
s.Succeeded++
case v1alpha1.StatusFailed:
s.Failed++
case v1alpha1.StatusCancelled:
s.Cancelled++
case v1alpha1.StatusRunning:
s.Running++
case v1alpha1.StatusPending:
s.Pending++
case v1alpha1.StatusWaiting:
s.Waiting++
default:
}
return s
}