Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/ide-metrics/pkg/metrics/aggregated-histograms.go
2500 views
1
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package metrics
6
7
import (
8
"errors"
9
"sync"
10
11
"github.com/gitpod-io/gitpod/common-go/log"
12
"github.com/prometheus/client_golang/prometheus"
13
)
14
15
type AggregatedHistograms struct {
16
Labels []string
17
18
desc *prometheus.Desc
19
upperBounds []float64
20
21
mu sync.RWMutex
22
histograms map[string]*aggregatedHistogram
23
}
24
25
func NewAggregatedHistograms(name string, help string, labels []string, upperBounds []float64) *AggregatedHistograms {
26
return &AggregatedHistograms{
27
desc: prometheus.NewDesc(
28
name,
29
help,
30
labels,
31
nil,
32
),
33
Labels: labels,
34
upperBounds: upperBounds,
35
histograms: make(map[string]*aggregatedHistogram),
36
}
37
}
38
39
type aggregatedHistogram struct {
40
count uint64
41
sum float64
42
buckets map[float64]uint64
43
labelValues []string
44
}
45
46
func (h *AggregatedHistograms) Describe(descs chan<- *prometheus.Desc) {
47
descs <- h.desc
48
}
49
50
func (h *AggregatedHistograms) Collect(metrics chan<- prometheus.Metric) {
51
for _, m := range h.collect() {
52
metrics <- m
53
}
54
}
55
56
func (h *AggregatedHistograms) collect() (metrics []prometheus.Metric) {
57
h.mu.RLock()
58
defer h.mu.RUnlock()
59
for _, histogram := range h.histograms {
60
metric, err := prometheus.NewConstHistogram(
61
h.desc,
62
histogram.count,
63
histogram.sum,
64
histogram.buckets,
65
histogram.labelValues...,
66
)
67
if err != nil {
68
log.WithError(err).Error("aggregated histogram: failed to collect")
69
} else {
70
metrics = append(metrics, metric)
71
}
72
}
73
return
74
}
75
76
func (h *AggregatedHistograms) Add(labelValues []string, count uint64, sum float64, buckets []uint64) error {
77
if len(labelValues) != len(h.Labels) {
78
return errors.New("invalid labels")
79
}
80
if len(buckets) != len(h.upperBounds) {
81
return errors.New("invalid buckets")
82
}
83
var key string
84
for _, v := range labelValues {
85
key = key + v + ":"
86
}
87
88
h.mu.Lock()
89
defer h.mu.Unlock()
90
histogram := h.histograms[key]
91
if histogram == nil {
92
histogram = &aggregatedHistogram{
93
labelValues: labelValues,
94
buckets: make(map[float64]uint64, len(h.upperBounds)),
95
}
96
h.histograms[key] = histogram
97
}
98
histogram.count = histogram.count + count
99
histogram.sum = histogram.sum + sum
100
for i, upperBound := range h.upperBounds {
101
histogram.buckets[upperBound] = histogram.buckets[upperBound] + buckets[i]
102
}
103
return nil
104
}
105
106