mirror of
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake.git
synced 2025-10-13 20:11:19 -04:00
Implement binned counts for polling metrics
This commit is contained in:
parent
83ef0b6f6d
commit
92bd900bc5
4 changed files with 108 additions and 23 deletions
|
@ -20,11 +20,11 @@ import (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
once sync.Once
|
once sync.Once
|
||||||
promMetrics *PromMetrics
|
promMetrics = initPrometheus()
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PrometheusNamespace = "snowflake"
|
prometheusNamespace = "snowflake"
|
||||||
metricsResolution = 60 * 60 * 24 * time.Second //86400 seconds
|
metricsResolution = 60 * 60 * 24 * time.Second //86400 seconds
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -147,6 +147,7 @@ func (m *Metrics) UpdateCountryStats(addr string, proxyType string, natType stri
|
||||||
} else {
|
} else {
|
||||||
m.countryStats.unknown[addr] = true
|
m.countryStats.unknown[addr] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
promMetrics.ProxyTotal.With(prometheus.Labels{
|
promMetrics.ProxyTotal.With(prometheus.Labels{
|
||||||
"nat": natType,
|
"nat": natType,
|
||||||
"type": proxyType,
|
"type": proxyType,
|
||||||
|
@ -261,40 +262,47 @@ func binCount(count uint) uint {
|
||||||
|
|
||||||
type PromMetrics struct {
|
type PromMetrics struct {
|
||||||
ProxyTotal *prometheus.CounterVec
|
ProxyTotal *prometheus.CounterVec
|
||||||
ProxyPollTotal *prometheus.CounterVec
|
ProxyPollTotal *RoundedCounterVec
|
||||||
ClientPollTotal *prometheus.CounterVec
|
ClientPollTotal *RoundedCounterVec
|
||||||
}
|
}
|
||||||
|
|
||||||
//Initialize metrics for prometheus exporter
|
//Initialize metrics for prometheus exporter
|
||||||
func InitPrometheus() {
|
func initPrometheus() *PromMetrics {
|
||||||
|
|
||||||
promMetrics = &PromMetrics{}
|
promMetrics := &PromMetrics{}
|
||||||
|
|
||||||
promMetrics.ProxyTotal = promauto.NewCounterVec(
|
promMetrics.ProxyTotal = promauto.NewCounterVec(
|
||||||
prometheus.CounterOpts{
|
prometheus.CounterOpts{
|
||||||
Namespace: PrometheusNamespace,
|
Namespace: prometheusNamespace,
|
||||||
Name: "proxy_total",
|
Name: "proxy_total",
|
||||||
Help: "The number of unique snowflake IPs",
|
Help: "The number of unique snowflake IPs",
|
||||||
},
|
},
|
||||||
[]string{"type", "nat", "cc"},
|
[]string{"type", "nat", "cc"},
|
||||||
)
|
)
|
||||||
|
|
||||||
promMetrics.ProxyPollTotal = promauto.NewCounterVec(
|
promMetrics.ProxyPollTotal = NewRoundedCounterVec(
|
||||||
prometheus.CounterOpts{
|
prometheus.CounterOpts{
|
||||||
Namespace: PrometheusNamespace,
|
Namespace: prometheusNamespace,
|
||||||
Name: "proxy_poll_total",
|
Name: "rounded_proxy_poll_total",
|
||||||
Help: "The number of snowflake proxy polls",
|
Help: "The number of snowflake proxy polls, rounded up to a multiple of 8",
|
||||||
},
|
},
|
||||||
[]string{"nat", "status"},
|
[]string{"nat", "status"},
|
||||||
)
|
)
|
||||||
|
|
||||||
promMetrics.ClientPollTotal = promauto.NewCounterVec(
|
promMetrics.ClientPollTotal = NewRoundedCounterVec(
|
||||||
prometheus.CounterOpts{
|
prometheus.CounterOpts{
|
||||||
Namespace: PrometheusNamespace,
|
Namespace: prometheusNamespace,
|
||||||
Name: "client_poll_total",
|
Name: "rounded_client_poll_total",
|
||||||
Help: "The number of snowflake client polls",
|
Help: "The number of snowflake client polls, rounded up to a multiple of 8",
|
||||||
},
|
},
|
||||||
[]string{"nat", "status"},
|
[]string{"nat", "status"},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// We need to register this new metric type because there is no constructor
|
||||||
|
// for it in promauto.
|
||||||
|
prometheus.DefaultRegisterer.MustRegister(promMetrics.ClientPollTotal)
|
||||||
|
prometheus.DefaultRegisterer.MustRegister(promMetrics.ProxyPollTotal)
|
||||||
|
|
||||||
|
return promMetrics
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
83
broker/prometheus.go
Normal file
83
broker/prometheus.go
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
Implements some additional prometheus metrics that we need for privacy preserving
|
||||||
|
counts of users and proxies
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
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 RoundedCounter interface {
|
||||||
|
prometheus.Metric
|
||||||
|
|
||||||
|
Inc()
|
||||||
|
}
|
||||||
|
|
||||||
|
type roundedCounter struct {
|
||||||
|
total uint64 //reflects the true count
|
||||||
|
value uint64 //reflects the rounded count
|
||||||
|
|
||||||
|
desc *prometheus.Desc
|
||||||
|
labelPairs []*dto.LabelPair
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements the RoundedCounter interface
|
||||||
|
func (c *roundedCounter) Inc() {
|
||||||
|
atomic.AddUint64(&c.total, 1)
|
||||||
|
if c.total > c.value {
|
||||||
|
atomic.AddUint64(&c.value, 8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements the prometheus.Metric interface
|
||||||
|
func (c *roundedCounter) Desc() *prometheus.Desc {
|
||||||
|
return c.desc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements the prometheus.Metric interface
|
||||||
|
func (c *roundedCounter) 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 RoundedCounter metrics
|
||||||
|
// accross multiple labels
|
||||||
|
type RoundedCounterVec struct {
|
||||||
|
*prometheus.MetricVec
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRoundedCounterVec(opts prometheus.CounterOpts, labelNames []string) *RoundedCounterVec {
|
||||||
|
desc := prometheus.NewDesc(
|
||||||
|
prometheus.BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
|
||||||
|
opts.Help,
|
||||||
|
labelNames,
|
||||||
|
opts.ConstLabels,
|
||||||
|
)
|
||||||
|
return &RoundedCounterVec{
|
||||||
|
MetricVec: prometheus.NewMetricVec(desc, func(lvs ...string) prometheus.Metric {
|
||||||
|
if len(lvs) != len(labelNames) {
|
||||||
|
panic("inconsistent cardinality")
|
||||||
|
}
|
||||||
|
return &roundedCounter{desc: desc, labelPairs: prometheus.MakeLabelPairs(desc, lvs)}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to return the underlying RoundedCounter metric from MetricVec
|
||||||
|
func (v *RoundedCounterVec) With(labels prometheus.Labels) RoundedCounter {
|
||||||
|
metric, err := v.GetMetricWith(labels)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return metric.(RoundedCounter)
|
||||||
|
}
|
|
@ -26,8 +26,6 @@ var promOnce sync.Once
|
||||||
|
|
||||||
func TestBroker(t *testing.T) {
|
func TestBroker(t *testing.T) {
|
||||||
|
|
||||||
promOnce.Do(InitPrometheus)
|
|
||||||
|
|
||||||
Convey("Context", t, func() {
|
Convey("Context", t, func() {
|
||||||
ctx := NewBrokerContext(NullLogger())
|
ctx := NewBrokerContext(NullLogger())
|
||||||
|
|
||||||
|
@ -303,8 +301,6 @@ func TestBroker(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSnowflakeHeap(t *testing.T) {
|
func TestSnowflakeHeap(t *testing.T) {
|
||||||
promOnce.Do(InitPrometheus)
|
|
||||||
|
|
||||||
Convey("SnowflakeHeap", t, func() {
|
Convey("SnowflakeHeap", t, func() {
|
||||||
h := new(SnowflakeHeap)
|
h := new(SnowflakeHeap)
|
||||||
heap.Init(h)
|
heap.Init(h)
|
||||||
|
@ -348,8 +344,6 @@ func TestSnowflakeHeap(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGeoip(t *testing.T) {
|
func TestGeoip(t *testing.T) {
|
||||||
promOnce.Do(InitPrometheus)
|
|
||||||
|
|
||||||
Convey("Geoip", t, func() {
|
Convey("Geoip", t, func() {
|
||||||
tv4 := new(GeoIPv4Table)
|
tv4 := new(GeoIPv4Table)
|
||||||
err := GeoIPLoadFile(tv4, "test_geoip")
|
err := GeoIPLoadFile(tv4, "test_geoip")
|
||||||
|
@ -454,8 +448,6 @@ func TestGeoip(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMetrics(t *testing.T) {
|
func TestMetrics(t *testing.T) {
|
||||||
promOnce.Do(InitPrometheus)
|
|
||||||
|
|
||||||
Convey("Test metrics...", t, func() {
|
Convey("Test metrics...", t, func() {
|
||||||
done := make(chan bool)
|
done := make(chan bool)
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -12,10 +12,12 @@ require (
|
||||||
github.com/pion/transport v0.12.3 // indirect
|
github.com/pion/transport v0.12.3 // indirect
|
||||||
github.com/pion/webrtc/v3 v3.0.15
|
github.com/pion/webrtc/v3 v3.0.15
|
||||||
github.com/prometheus/client_golang v1.10.0
|
github.com/prometheus/client_golang v1.10.0
|
||||||
|
github.com/prometheus/client_model v0.2.0
|
||||||
github.com/smartystreets/goconvey v1.6.4
|
github.com/smartystreets/goconvey v1.6.4
|
||||||
github.com/xtaci/kcp-go/v5 v5.5.12
|
github.com/xtaci/kcp-go/v5 v5.5.12
|
||||||
github.com/xtaci/smux v1.5.12
|
github.com/xtaci/smux v1.5.12
|
||||||
golang.org/x/crypto v0.0.0-20210317152858-513c2a44f670
|
golang.org/x/crypto v0.0.0-20210317152858-513c2a44f670
|
||||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4
|
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4
|
||||||
golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e // indirect
|
golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e // indirect
|
||||||
|
google.golang.org/protobuf v1.23.0
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue