main
go 123 lines 3.93 KB
Raw
1 package telemetry
2
3 // Package telemetry provides Prometheus-based observability for relay selection.
4 //
5 // Cardinality Control:
6 // - Labels: No per-client information (e.g., ClientHash, LocalAddress).
7 // - Relay Cardinality: Bounded by MaxRelayLabelCardinality.
8 // URLs exceeding this are bucketed as 'other'.
9
10 import (
11 "sync"
12
13 "github.com/prometheus/client_golang/prometheus"
14 "github.com/prometheus/client_golang/prometheus/promauto"
15 )
16
17 const MaxRelayLabelCardinality = 64
18
19 var relayBudget = struct {
20 mu sync.Mutex
21 seen map[string]struct{}
22 }{
23 seen: make(map[string]struct{}),
24 }
25
26 // BoundedRelay limits relay label cardinality to MaxRelayLabelCardinality.
27 // Excess URLs are returned as "other".
28 func BoundedRelay(url string) string {
29 relayBudget.mu.Lock()
30 defer relayBudget.mu.Unlock()
31 if _, ok := relayBudget.seen[url]; ok {
32 return url
33 }
34 if len(relayBudget.seen) >= MaxRelayLabelCardinality {
35 return "other"
36 }
37 relayBudget.seen[url] = struct{}{}
38 return url
39 }
40
41 // --------------------------------------------------------------------------
42 // Metric registrations
43 // --------------------------------------------------------------------------
44
45 // RelaySelectedTotal counts relay-selection events by (relay, reason).
46 // reason ∈ {explicit, auto, fallback, congestion-promoted, variant-grid}.
47 var RelaySelectedTotal = promauto.NewCounterVec(
48 prometheus.CounterOpts{
49 Name: "portal_discovery_relay_selected_total",
50 Help: "Total relays selected by reason.",
51 },
52 []string{"relay", "reason"},
53 )
54
55 // RelayPoolSize is a gauge of auto-pool size partitioned by state.
56 // state ∈ {total, active, banned, expired, suppressed, fallback}.
57 var RelayPoolSize = promauto.NewGaugeVec(
58 prometheus.GaugeOpts{
59 Name: "portal_discovery_relay_pool_size",
60 Help: "Auto-pool size by state.",
61 },
62 []string{"state"},
63 )
64
65 // RTTSeconds is a histogram of per-relay discovery RTT observations.
66 // label: relay. Buckets: 10 ms … 5 s.
67 var RTTSeconds = promauto.NewHistogramVec(
68 prometheus.HistogramOpts{
69 Name: "portal_discovery_rtt_seconds",
70 Help: "Discovery RTT per relay (seconds).",
71 Buckets: []float64{0.010, 0.050, 0.100, 0.250, 0.500, 1.0, 2.0, 5.0},
72 },
73 []string{"relay"},
74 )
75
76 // ActiveTunnelsPerRelay is a gauge of tunnel count for each relay.
77 // SDK-local measurement: tracks this process's tunnel distribution only.
78 var ActiveTunnelsPerRelay = promauto.NewGaugeVec(
79 prometheus.GaugeOpts{
80 Name: "portal_discovery_active_tunnels_per_relay",
81 Help: "SDK-local; measures this exposure's tunnel distribution, not relay-wide load.",
82 },
83 []string{"relay"},
84 )
85
86 // SelectionDurationSeconds is a histogram of wall time per selection call.
87 // No labels; uses prometheus default buckets.
88 var SelectionDurationSeconds = promauto.NewHistogram(
89 prometheus.HistogramOpts{
90 Name: "portal_discovery_selection_duration_seconds",
91 Help: "Wall time of a single relay-selection invocation.",
92 // Default prometheus buckets (.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10).
93 },
94 )
95
96 // SelectionSkippedTotal counts relays excluded from selection by reason.
97 // reason ∈ {expired, require_udp, require_tcp, suppressed, banned, no_descriptor, no_overlay_peer}.
98 var SelectionSkippedTotal = promauto.NewCounterVec(
99 prometheus.CounterOpts{
100 Name: "portal_discovery_selection_skipped_total",
101 Help: "Relays skipped during selection by reason.",
102 },
103 []string{"reason"},
104 )
105
106 // FailuresTotal counts discovery and active-path failures per relay.
107 // labels: relay, kind ∈ {discovery, active}.
108 var FailuresTotal = promauto.NewCounterVec(
109 prometheus.CounterOpts{
110 Name: "portal_discovery_failures_total",
111 Help: "Discovery and active failures per relay.",
112 },
113 []string{"relay", "kind"},
114 )
115
116 // CongestionMode is a gauge encoding the current congestion state.
117 // 0 = normal, 1 = congested (no variant-grid), 2 = variant-grid active.
118 var CongestionMode = promauto.NewGauge(
119 prometheus.GaugeOpts{
120 Name: "portal_discovery_congestion_mode",
121 Help: "Active congestion mode (0=normal, 1=congested, 2=variant-grid).",
122 },
123 )