This repository has been archived by the owner on Jan 11, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 560
/
metrics.go
222 lines (193 loc) · 6.34 KB
/
metrics.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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
package metrics
import (
"log"
"time"
client "github.com/influxdata/influxdb/client/v2"
"github.com/kelseyhightower/envconfig"
)
// Config holds information on how to talk to influxdb
type Config struct {
Address string `envconfig:"INFLUX_ADDRESS" required:"true"`
Username string `envconfig:"INFLUX_USERNAME" required:"true"`
Password string `envconfig:"INFLUX_PASSWORD" required:"true"`
Database string `envconfig:"INFLUX_DATABASE" required:"true"`
IsCircle bool `envconfig:"CIRCLECI"`
JenkinsURL string `envconfig:"JENKINS_URL"`
CircleEnv *CircleCIEnvironment
JenkinsEnv *JenkinsCIEnvironment
}
// IsJenkins returns true if running in jenkins env
func (c *Config) IsJenkins() bool {
if c.JenkinsURL == "" {
return false
}
return true
}
// CircleCIEnvironment holds information about a test run within circleci
type CircleCIEnvironment struct {
Branch string `envconfig:"CIRCLE_BRANCH"`
BuildNumber string `envconfig:"CIRCLE_BUILD_NUM"`
CommitSha string `envconfig:"CIRCLE_SHA1"`
Job string `envconfig:"CIRCLE_JOB"`
}
// JenkinsCIEnvironment holds information about a test run within jenkins
type JenkinsCIEnvironment struct {
Branch string `envconfig:"GIT_BRANCH"`
BuildNumber string `envconfig:"BUILD_NUMBER"`
CommitSha string `envconfig:"GIT_COMMIT"`
Job string `envconfig:"JOB_NAME"`
}
// Point holds data that will be written to influx
type Point struct {
ProvisionStart time.Time
NodeWaitStart time.Time
TestStart time.Time
OverallStart time.Time
ProvisionDuration time.Duration
NodeWaitDuration time.Duration
TestDuration time.Duration
OverallDuration time.Duration
TestErrorCount float64
ProvisionErrorCount float64
NodeWaitErrorCount float64
Tags map[string]string
}
// ParseConfig will parse needed environment variables for running the tests
func ParseConfig() (*Config, error) {
c := new(Config)
if err := envconfig.Process("config", c); err != nil {
return nil, err
}
if c.IsCircle {
circleci := new(CircleCIEnvironment)
if err := envconfig.Process("circleci-config", circleci); err != nil {
return nil, err
}
c.CircleEnv = circleci
}
if c.IsJenkins() {
jenkinsci := new(JenkinsCIEnvironment)
if err := envconfig.Process("jenkinsci-config", jenkinsci); err != nil {
return nil, err
}
c.JenkinsEnv = jenkinsci
}
return c, nil
}
// BuildPoint scaffolds a point object that stores information before being written to influx
func BuildPoint(orchestrator, location, clusterDefinition, subscriptionID string) *Point {
p := Point{
OverallStart: time.Now(),
ProvisionDuration: 0 * time.Second,
NodeWaitDuration: 0 * time.Second,
TestDuration: 0 * time.Second,
OverallDuration: 0 * time.Second,
ProvisionErrorCount: 0,
TestErrorCount: 0,
NodeWaitErrorCount: 0,
Tags: map[string]string{
"orchestrator": orchestrator,
"location": location,
"definition": clusterDefinition,
"subscription_id": subscriptionID,
},
}
return &p
}
// SetTestStart will set TestStart value to time.Now()
func (p *Point) SetTestStart() {
p.TestStart = time.Now()
}
// SetProvisionStart will set ProvisionStart value to time.Now()
func (p *Point) SetProvisionStart() {
p.ProvisionStart = time.Now()
}
// RecordProvisionError sets appropriate values for when a test error occurs
func (p *Point) RecordProvisionError() {
p.ProvisionDuration = time.Since(p.ProvisionStart)
p.ProvisionErrorCount = p.ProvisionErrorCount + 1
}
// RecordProvisionSuccess sets TestErrorCount to 0 to mark tests succeeded
func (p *Point) RecordProvisionSuccess() {
p.ProvisionDuration = time.Since(p.ProvisionStart)
}
// SetNodeWaitStart will set NodeWaitStart value to time.Now()
func (p *Point) SetNodeWaitStart() {
p.NodeWaitStart = time.Now()
}
// RecordNodeWait will set NodeWaitDuration to time.Since(p.NodeWaitStart)
func (p *Point) RecordNodeWait(err error) {
if err != nil {
p.NodeWaitErrorCount = p.NodeWaitErrorCount + 1
}
p.NodeWaitDuration = time.Since(p.NodeWaitStart)
}
// RecordTestError sets appropriate values for when a test error occurs
func (p *Point) RecordTestError() {
p.TestDuration = time.Since(p.TestStart)
p.TestErrorCount = p.TestErrorCount + 1
}
// RecordTestSuccess sets TestErrorCount to 0 to mark tests succeeded
func (p *Point) RecordTestSuccess() {
p.TestDuration = time.Since(p.TestStart)
}
// RecordTotalTime captures total runtime of tests
func (p *Point) RecordTotalTime() {
p.OverallDuration = time.Since(p.OverallStart)
}
// SetProvisionMetrics will parse the csv data retrieved from /opt/m and set appropriate fields
func (p *Point) SetProvisionMetrics(data []byte) {
}
func (p *Point) Write() {
cfg, err := ParseConfig()
if err == nil {
log.Printf("Circle?:%v\n", cfg.IsCircle)
log.Printf("Jenkins?:%v\n", cfg.IsJenkins())
if cfg.IsCircle {
p.Tags["branch"] = cfg.CircleEnv.Branch
p.Tags["commit-sha"] = cfg.CircleEnv.CommitSha
p.Tags["build_number"] = cfg.CircleEnv.BuildNumber
p.Tags["job"] = cfg.CircleEnv.Job
p.Tags["ci"] = "circleci"
}
if cfg.IsJenkins() {
p.Tags["branch"] = cfg.JenkinsEnv.Branch
p.Tags["commit-sha"] = cfg.JenkinsEnv.CommitSha
p.Tags["build_number"] = cfg.JenkinsEnv.BuildNumber
p.Tags["job"] = cfg.JenkinsEnv.Job
p.Tags["ci"] = "jenkins"
}
fields := map[string]interface{}{
"provision-secs": p.ProvisionDuration.Seconds(),
"node-wait-secs": p.NodeWaitDuration.Seconds(),
"test-secs": p.TestDuration.Seconds(),
"total-secs": p.OverallDuration.Seconds(),
"test-error-count": p.TestErrorCount,
"provision-error-count": p.ProvisionErrorCount,
"node-wait-error-count": p.NodeWaitErrorCount,
}
c, err := client.NewHTTPClient(client.HTTPConfig{
Addr: cfg.Address,
Username: cfg.Username,
Password: cfg.Password,
})
if err != nil {
log.Printf("Error trying to create influx http client:%s\n", err)
}
// Create a new point batch
bp, err := client.NewBatchPoints(client.BatchPointsConfig{
Database: cfg.Database,
Precision: "s",
})
if err != nil {
log.Printf("Error trying to create batch points:%s\n", err)
}
pt, err := client.NewPoint("test", p.Tags, fields, time.Now())
log.Printf("Point:%+v\n", pt)
if err != nil {
log.Printf("Error trying to create metric point:%s\n", err)
}
bp.AddPoint(pt)
c.Write(bp)
}
}