File: prometheus.go

package info (click to toggle)
golang-ptutil 0.0~git20240710.6c4d8ed-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 100 kB
  • sloc: makefile: 2
file content (103 lines) | stat: -rw-r--r-- 2,783 bytes parent folder | download
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
/*
Implements some additional prometheus metrics that we need for privacy preserving
counts of users and proxies
*/

package safeprom

import (
	"sync/atomic"

	"github.com/prometheus/client_golang/prometheus"
	dto "github.com/prometheus/client_model/go"
	"google.golang.org/protobuf/proto"
)

// New Prometheus counter type that produces rounded counts of metrics
// for privacy preserving reasons
type Counter interface {
	prometheus.Metric

	Inc()
}

type counter struct {
	total uint64 //reflects the true count
	value uint64 //reflects the rounded count

	desc       *prometheus.Desc
	labelPairs []*dto.LabelPair
}

// Implements the Counter interface
func (c *counter) Inc() {
	atomic.AddUint64(&c.total, 1)
	if c.total > c.value {
		atomic.AddUint64(&c.value, 8)
	}
}

// Implements the prometheus.Metric interface
func (c *counter) Desc() *prometheus.Desc {
	return c.desc
}

// Implements the prometheus.Metric interface
func (c *counter) Write(m *dto.Metric) error {
	m.Label = c.labelPairs

	m.Counter = &dto.Counter{Value: proto.Float64(float64(c.value))}
	return nil
}

// New prometheus vector type that will track Counter metrics
// accross multiple labels
type CounterVec struct {
	*prometheus.MetricVec
}

// NewCounterVec will create a CounterVec but will not register it, users must register it themselves.
// The behaviour of this function is similar to github.com/prometheus/client_golang/prometheus
func NewCounterVec(opts prometheus.CounterOpts, labelNames []string) *CounterVec {
	desc := prometheus.NewDesc(
		prometheus.BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
		opts.Help,
		labelNames,
		opts.ConstLabels,
	)
	c := &CounterVec{
		MetricVec: prometheus.NewMetricVec(desc, func(lvs ...string) prometheus.Metric {
			if len(lvs) != len(labelNames) {
				panic("inconsistent cardinality")
			}
			return &counter{desc: desc, labelPairs: prometheus.MakeLabelPairs(desc, lvs)}
		}),
	}
	return c
}

// NewCounterVecRegistered will create a CounterVec and register it.
// The behaviour of this function is similar to github.com/prometheus/client_golang/prometheus/promauto
func NewCounterVecRegistered(opts prometheus.CounterOpts, labelNames []string) *CounterVec {
	c := NewCounterVec(opts, labelNames)
	prometheus.DefaultRegisterer.MustRegister(c)
	return c
}

// Helper function to return the underlying Counter metric from MetricVec
func (v *CounterVec) With(labels prometheus.Labels) Counter {
	metric, err := v.GetMetricWith(labels)
	if err != nil {
		panic(err)
	}
	return metric.(Counter)
}

// Helper function to return the underlying Counter metric from MetricVec
func (v *CounterVec) WithLabelValues(lvs ...string) Counter {
	metric, err := v.GetMetricWithLabelValues(lvs...)
	if err != nil {
		panic(err)
	}
	return metric.(Counter)
}