/
metrics.go
182 lines (156 loc) · 5.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
package npp
import (
"net"
"reflect"
"github.com/prometheus/client_golang/prometheus"
prometheusIO "github.com/prometheus/client_model/go"
"github.com/rcrowley/go-metrics"
"go.uber.org/atomic"
)
type ListenerMetrics struct {
RendezvousAddr net.Addr
NumConnectionsDirect uint64
NumConnectionsNAT uint64
NumConnectionsRelay uint64
}
type listeneMetrics struct {
NumConnectionsDirect *atomic.Uint64
NumConnectionsNAT *atomic.Uint64
NumConnectionsRelay *atomic.Uint64
}
func newListenerMetrics() *listeneMetrics {
return &listeneMetrics{
NumConnectionsDirect: atomic.NewUint64(0),
NumConnectionsNAT: atomic.NewUint64(0),
NumConnectionsRelay: atomic.NewUint64(0),
}
}
type dialMetrics struct {
// NumAttempts describes the total number of attempts to connect
// to a remote address using NPP dialer.
NumAttempts *meterWrapper
// NumSuccess describes the total number of successful attempts to connect
// to a remote address using NPP dialer no matter which method was
// successful.
NumSuccess *meterWrapper
// NumFailed describes the total number of failed attempts to connect to
// a remote address.
NumFailed *meterWrapper
// UsingTCPDirectHistogram describes the distribution of connect times for
// successful connection attempts using direct TCP connection.
UsingTCPDirectHistogram *histogramWrapper
// UsingNATHistogram describes the distribution of resolve and connect
// times for successful connection attempts using NPP NAT traversal.
UsingNATHistogram *histogramWrapper
// UsingQNATHistogram describes the distribution of resolve and connect
// times for successful connection attempts using NPP NAT traversal over
// UDP for QUIC.
UsingQNATHistogram *histogramWrapper
// UsingRelayHistogram describes the distribution of resolve and connect
// times for successful connection attempts using Relay server.
UsingRelayHistogram *histogramWrapper
// SummaryHistogram describes the distribution of connect times for overall
// dialing.
SummaryHistogram *histogramWrapper
// LastTimeActive shows the time when the last connection attempt was made.
LastTimeActive *gaugeWrapper
// LastTimeSuccess shows the time when the last successful connection
// attempt was made.
LastTimeSuccess *gaugeWrapper
}
func newDialMetrics() *dialMetrics {
return &dialMetrics{
NumAttempts: newMeterWrapper(),
NumSuccess: newMeterWrapper(),
NumFailed: newMeterWrapper(),
UsingTCPDirectHistogram: newHistogramWrapper(),
UsingNATHistogram: newHistogramWrapper(),
UsingQNATHistogram: newHistogramWrapper(),
UsingRelayHistogram: newHistogramWrapper(),
SummaryHistogram: newHistogramWrapper(),
LastTimeActive: newGaugeWrapper(),
LastTimeSuccess: newGaugeWrapper(),
}
}
func (m *dialMetrics) MetricNames() []string {
v := reflect.ValueOf(m).Elem()
ty := v.Type()
names := make([]string, v.NumField())
for id := 0; id < v.NumField(); id++ {
names[id] = ty.Field(id).Name
}
return names
}
type NamedMetric struct {
Name string
Metric *prometheusIO.Metric
}
type gaugeWrapper struct {
prometheus.Gauge
}
func newGaugeWrapper() *gaugeWrapper {
return &gaugeWrapper{
Gauge: prometheus.NewGauge(prometheus.GaugeOpts{}),
}
}
func (m *gaugeWrapper) ToNamedMetrics(prefix string) []*NamedMetric {
return []*NamedMetric{{Name: prefix + "", Metric: newPrometheusMetric(m)}}
}
type meterWrapper struct {
metrics.Meter
}
func newMeterWrapper() *meterWrapper {
return &meterWrapper{
Meter: metrics.NewMeter(),
}
}
func (m *meterWrapper) ToNamedMetrics(prefix string) []*NamedMetric {
return []*NamedMetric{
{Name: prefix + "", Metric: newPrometheusCounterMetric(m.Count)},
{Name: prefix + "Rate01", Metric: newPrometheusGaugeMetric(m.Rate1)},
{Name: prefix + "Rate05", Metric: newPrometheusGaugeMetric(m.Rate5)},
{Name: prefix + "Rate15", Metric: newPrometheusGaugeMetric(m.Rate15)},
{Name: prefix + "RateMean", Metric: newPrometheusGaugeMetric(m.RateMean)},
}
}
type histogramWrapper struct {
prometheus.Histogram
meter metrics.Meter
}
func newHistogramWrapper() *histogramWrapper {
return &histogramWrapper{
Histogram: prometheus.NewHistogram(prometheus.HistogramOpts{}),
meter: metrics.NewMeter(),
}
}
func (m *histogramWrapper) Observe(v float64) {
m.Histogram.Observe(v)
m.meter.Mark(1)
}
func (m *histogramWrapper) ToNamedMetrics(prefix string) []*NamedMetric {
return []*NamedMetric{
{Name: prefix + "", Metric: newPrometheusMetric(m)},
{Name: prefix + "Rate01", Metric: newPrometheusGaugeMetric(m.meter.Rate1)},
{Name: prefix + "Rate05", Metric: newPrometheusGaugeMetric(m.meter.Rate5)},
{Name: prefix + "Rate15", Metric: newPrometheusGaugeMetric(m.meter.Rate15)},
{Name: prefix + "RateMean", Metric: newPrometheusGaugeMetric(m.meter.RateMean)},
}
}
func newPrometheusMetric(metric prometheus.Metric) *prometheusIO.Metric {
value := &prometheusIO.Metric{}
if err := metric.Write(value); err != nil {
// Unreachable actually.
return nil
}
return value
}
func newPrometheusCounterMetric(fn func() int64) *prometheusIO.Metric {
metric := prometheus.NewCounter(prometheus.CounterOpts{})
metric.Add(float64(fn()))
return newPrometheusMetric(metric)
}
func newPrometheusGaugeMetric(fn func() float64) *prometheusIO.Metric {
metric := prometheus.NewGauge(prometheus.GaugeOpts{})
metric.Set(fn())
return newPrometheusMetric(metric)
}