feat(sdk): track active_tunnels_per_relay gauge in accept loop
cognitive committed
Apr 30, 2026 at 05:20 UTC
ef4b980a81e8999dc1716a8a962068262685e1df
1 file changed
+25
-2
sdk/expose.go
+25
-2
@@ -357,6 +357,21 @@ func (c *exposureConn) Close() error {
357
return closeErr
358
}
359
360
+// tunnelCounterConn wraps a net.Conn and calls decr exactly once on the first
361
+// Close invocation to decrement the active_tunnels_per_relay gauge. Subsequent
362
+// Close calls are forwarded to the underlying conn but do not double-decrement.
363
+// Concurrency is guaranteed by sync.Once.
364
+type tunnelCounterConn struct {
365
+ net.Conn
366
+ once sync.Once
367
+ decr func()
368
+}
369
+
370
+func (c *tunnelCounterConn) Close() error {
371
+ c.once.Do(c.decr)
372
+ return c.Conn.Close()
373
+}
374
+
375
func (e *Exposure) Accept() (net.Conn, error) {
376
select {
377
case <-e.done:
@@ -609,11 +624,19 @@ func (e *Exposure) runListenerAcceptLoop(listener *listener) {
624
return
625
}
626
627
+ discovery.ActiveTunnelsPerRelay.WithLabelValues(relayURL).Inc()
628
+ wrappedConn := &tunnelCounterConn{
629
+ Conn: conn,
630
+ decr: func() {
631
+ discovery.ActiveTunnelsPerRelay.WithLabelValues(relayURL).Dec()
632
+ },
633
+ }
634
+
635
select {
636
case <-e.done:
614
- _ = conn.Close()
637
+ _ = wrappedConn.Close()
638
return
616
- case e.accepted <- conn:
639
+ case e.accepted <- wrappedConn:
640
}
641
}
642
}