-
Notifications
You must be signed in to change notification settings - Fork 239
/
metrics.go
205 lines (178 loc) · 7.44 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
package controller
import (
"fmt"
"reflect"
"github.com/mvisonneau/gitlab-ci-pipelines-exporter/pkg/gitlab"
"github.com/mvisonneau/gitlab-ci-pipelines-exporter/pkg/schemas"
"github.com/mvisonneau/gitlab-ci-pipelines-exporter/pkg/store"
"github.com/prometheus/client_golang/prometheus"
log "github.com/sirupsen/logrus"
)
// Registry wraps a pointer of prometheus.Registry
type Registry struct {
*prometheus.Registry
InternalCollectors struct {
CurrentlyQueuedTasksCount prometheus.Collector
EnvironmentsCount prometheus.Collector
ExecutedTasksCount prometheus.Collector
GitLabAPIRequestsCount prometheus.Collector
MetricsCount prometheus.Collector
ProjectsCount prometheus.Collector
RefsCount prometheus.Collector
}
Collectors RegistryCollectors
}
// RegistryCollectors ..
type RegistryCollectors map[schemas.MetricKind]prometheus.Collector
// NewRegistry initialize a new registry
func NewRegistry() *Registry {
r := &Registry{
Registry: prometheus.NewRegistry(),
Collectors: RegistryCollectors{
schemas.MetricKindCoverage: NewCollectorCoverage(),
schemas.MetricKindDurationSeconds: NewCollectorDurationSeconds(),
schemas.MetricKindEnvironmentBehindCommitsCount: NewCollectorEnvironmentBehindCommitsCount(),
schemas.MetricKindEnvironmentBehindDurationSeconds: NewCollectorEnvironmentBehindDurationSeconds(),
schemas.MetricKindEnvironmentDeploymentCount: NewCollectorEnvironmentDeploymentCount(),
schemas.MetricKindEnvironmentDeploymentDurationSeconds: NewCollectorEnvironmentDeploymentDurationSeconds(),
schemas.MetricKindEnvironmentDeploymentJobID: NewCollectorEnvironmentDeploymentJobID(),
schemas.MetricKindEnvironmentDeploymentStatus: NewCollectorEnvironmentDeploymentStatus(),
schemas.MetricKindEnvironmentDeploymentTimestamp: NewCollectorEnvironmentDeploymentTimestamp(),
schemas.MetricKindEnvironmentInformation: NewCollectorEnvironmentInformation(),
schemas.MetricKindID: NewCollectorID(),
schemas.MetricKindJobArtifactSizeBytes: NewCollectorJobArtifactSizeBytes(),
schemas.MetricKindJobDurationSeconds: NewCollectorJobDurationSeconds(),
schemas.MetricKindJobID: NewCollectorJobID(),
schemas.MetricKindJobQueuedDurationSeconds: NewCollectorJobQueuedDurationSeconds(),
schemas.MetricKindJobRunCount: NewCollectorJobRunCount(),
schemas.MetricKindJobStatus: NewCollectorJobStatus(),
schemas.MetricKindJobTimestamp: NewCollectorJobTimestamp(),
schemas.MetricKindQueuedDurationSeconds: NewCollectorQueuedDurationSeconds(),
schemas.MetricKindRunCount: NewCollectorRunCount(),
schemas.MetricKindStatus: NewCollectorStatus(),
schemas.MetricKindTimestamp: NewCollectorTimestamp(),
},
}
r.RegisterInternalCollectors()
if err := r.RegisterCollectors(); err != nil {
log.Fatal(err)
}
return r
}
// RegisterInternalCollectors declare our internal collectors to the registry
func (r *Registry) RegisterInternalCollectors() {
r.InternalCollectors.CurrentlyQueuedTasksCount = NewInternalCollectorCurrentlyQueuedTasksCount()
r.InternalCollectors.EnvironmentsCount = NewInternalCollectorEnvironmentsCount()
r.InternalCollectors.ExecutedTasksCount = NewInternalCollectorExecutedTasksCount()
r.InternalCollectors.GitLabAPIRequestsCount = NewInternalCollectorGitLabAPIRequestsCount()
r.InternalCollectors.MetricsCount = NewInternalCollectorMetricsCount()
r.InternalCollectors.ProjectsCount = NewInternalCollectorProjectsCount()
r.InternalCollectors.RefsCount = NewInternalCollectorRefsCount()
_ = r.Register(r.InternalCollectors.CurrentlyQueuedTasksCount)
_ = r.Register(r.InternalCollectors.EnvironmentsCount)
_ = r.Register(r.InternalCollectors.ExecutedTasksCount)
_ = r.Register(r.InternalCollectors.GitLabAPIRequestsCount)
_ = r.Register(r.InternalCollectors.MetricsCount)
_ = r.Register(r.InternalCollectors.ProjectsCount)
_ = r.Register(r.InternalCollectors.RefsCount)
}
// ExportInternalMetrics ..
func (r *Registry) ExportInternalMetrics(
g *gitlab.Client,
s store.Store,
) (err error) {
var (
currentlyQueuedTasks uint64
environmentsCount int64
executedTasksCount uint64
metricsCount int64
projectsCount int64
refsCount int64
)
currentlyQueuedTasks, err = s.CurrentlyQueuedTasksCount()
if err != nil {
return
}
executedTasksCount, err = s.ExecutedTasksCount()
if err != nil {
return
}
projectsCount, err = s.ProjectsCount()
if err != nil {
return
}
environmentsCount, err = s.EnvironmentsCount()
if err != nil {
return
}
refsCount, err = s.RefsCount()
if err != nil {
return
}
metricsCount, err = s.MetricsCount()
if err != nil {
return
}
r.InternalCollectors.CurrentlyQueuedTasksCount.(*prometheus.GaugeVec).With(prometheus.Labels{}).Set(float64(currentlyQueuedTasks))
r.InternalCollectors.EnvironmentsCount.(*prometheus.GaugeVec).With(prometheus.Labels{}).Set(float64(environmentsCount))
r.InternalCollectors.ExecutedTasksCount.(*prometheus.GaugeVec).With(prometheus.Labels{}).Set(float64(executedTasksCount))
r.InternalCollectors.GitLabAPIRequestsCount.(*prometheus.GaugeVec).With(prometheus.Labels{}).Set(float64(g.RequestsCounter))
r.InternalCollectors.MetricsCount.(*prometheus.GaugeVec).With(prometheus.Labels{}).Set(float64(metricsCount))
r.InternalCollectors.ProjectsCount.(*prometheus.GaugeVec).With(prometheus.Labels{}).Set(float64(projectsCount))
r.InternalCollectors.RefsCount.(*prometheus.GaugeVec).With(prometheus.Labels{}).Set(float64(refsCount))
return
}
// RegisterCollectors add all our metrics to the registry
func (r *Registry) RegisterCollectors() error {
for _, c := range r.Collectors {
if err := r.Register(c); err != nil {
return fmt.Errorf("could not add provided collector '%v' to the Prometheus registry: %v", c, err)
}
}
return nil
}
// GetCollector ..
func (r *Registry) GetCollector(kind schemas.MetricKind) prometheus.Collector {
return r.Collectors[kind]
}
// ExportMetrics ..
func (r *Registry) ExportMetrics(metrics schemas.Metrics) {
for _, m := range metrics {
switch c := r.GetCollector(m.Kind).(type) {
case *prometheus.GaugeVec:
c.With(m.Labels).Set(m.Value)
case *prometheus.CounterVec:
c.With(m.Labels).Add(m.Value)
default:
log.Errorf("unsupported collector type : %v", reflect.TypeOf(c))
}
}
}
func emitStatusMetric(s store.Store, metricKind schemas.MetricKind, labelValues map[string]string, statuses []string, status string, sparseMetrics bool) {
// Moved into separate function to reduce cyclomatic complexity
// List of available statuses from the API spec
// ref: https://docs.gitlab.com/ee/api/jobs.html#list-pipeline-jobs
for _, currentStatus := range statuses {
var value float64
statusLabels := make(map[string]string)
for k, v := range labelValues {
statusLabels[k] = v
}
statusLabels["status"] = currentStatus
statusMetric := schemas.Metric{
Kind: metricKind,
Labels: statusLabels,
Value: value,
}
if currentStatus == status {
statusMetric.Value = 1
} else {
if sparseMetrics {
storeDelMetric(s, statusMetric)
continue
}
statusMetric.Value = 0
}
storeSetMetric(s, statusMetric)
}
}