[client] Extract stateDump into its own state_dump package

Move the debug state dumper out of the peer package into
client/internal/peer/state_dump with an exported StateDump type and
NewStateDump constructor. Update conn.go, wg_watcher.go and the watcher
test to reference it through the package.
This commit is contained in:
Zoltan Papp
2026-08-05 16:14:11 +02:00
committed by Zoltán Papp
parent 9d92bc8abc
commit a84302ac71
4 changed files with 25 additions and 22 deletions
+3 -2
View File
@@ -22,6 +22,7 @@ import (
"github.com/netbirdio/netbird/client/internal/peer/guard" "github.com/netbirdio/netbird/client/internal/peer/guard"
icemaker "github.com/netbirdio/netbird/client/internal/peer/ice" icemaker "github.com/netbirdio/netbird/client/internal/peer/ice"
"github.com/netbirdio/netbird/client/internal/peer/id" "github.com/netbirdio/netbird/client/internal/peer/id"
"github.com/netbirdio/netbird/client/internal/peer/state_dump"
"github.com/netbirdio/netbird/client/internal/peer/status" "github.com/netbirdio/netbird/client/internal/peer/status"
"github.com/netbirdio/netbird/client/internal/peer/worker" "github.com/netbirdio/netbird/client/internal/peer/worker"
"github.com/netbirdio/netbird/client/internal/portforward" "github.com/netbirdio/netbird/client/internal/portforward"
@@ -155,7 +156,7 @@ type Conn struct {
wg sync.WaitGroup wg sync.WaitGroup
// debug purpose // debug purpose
dumpState *stateDump dumpState *state_dump.StateDump
endpointUpdater *EndpointUpdater endpointUpdater *EndpointUpdater
@@ -177,7 +178,7 @@ func NewConn(config ConnConfig, services ServiceDependencies) (*Conn, error) {
connLog := log.WithField("peer", config.Key) connLog := log.WithField("peer", config.Key)
dumpState := newStateDump(config.Key, connLog, services.StatusRecorder) dumpState := state_dump.NewStateDump(config.Key, connLog, services.StatusRecorder)
var conn = &Conn{ var conn = &Conn{
Log: connLog, Log: connLog,
config: config, config: config,
@@ -1,4 +1,4 @@
package peer package state_dump
import ( import (
"context" "context"
@@ -10,7 +10,7 @@ import (
"github.com/netbirdio/netbird/client/internal/peer/status" "github.com/netbirdio/netbird/client/internal/peer/status"
) )
type stateDump struct { type StateDump struct {
log *log.Entry log *log.Entry
status *status.Recorder status *status.Recorder
key string key string
@@ -28,15 +28,15 @@ type stateDump struct {
mu sync.Mutex mu sync.Mutex
} }
func newStateDump(key string, log *log.Entry, statusRecorder *status.Recorder) *stateDump { func NewStateDump(key string, log *log.Entry, statusRecorder *status.Recorder) *StateDump {
return &stateDump{ return &StateDump{
log: log, log: log,
status: statusRecorder, status: statusRecorder,
key: key, key: key,
} }
} }
func (s *stateDump) Start(ctx context.Context) { func (s *StateDump) Start(ctx context.Context) {
ticker := time.NewTicker(10 * time.Minute) ticker := time.NewTicker(10 * time.Minute)
defer ticker.Stop() defer ticker.Stop()
@@ -50,25 +50,25 @@ func (s *stateDump) Start(ctx context.Context) {
} }
} }
func (s *stateDump) RemoteOffer() { func (s *StateDump) RemoteOffer() {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
s.remoteOffer++ s.remoteOffer++
} }
func (s *stateDump) RemoteCandidate() { func (s *StateDump) RemoteCandidate() {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
s.remoteCandidate++ s.remoteCandidate++
} }
func (s *stateDump) SendOffer() { func (s *StateDump) SendOffer() {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
s.sentOffer++ s.sentOffer++
} }
func (s *stateDump) dumpState() { func (s *StateDump) dumpState() {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
@@ -82,41 +82,41 @@ func (s *stateDump) dumpState() {
status, s.sentOffer, s.remoteOffer, s.remoteAnswer, s.remoteCandidate, s.p2pConnected, s.switchToRelay, s.wgCheckSuccess, s.relayConnected, s.localProxies) status, s.sentOffer, s.remoteOffer, s.remoteAnswer, s.remoteCandidate, s.p2pConnected, s.switchToRelay, s.wgCheckSuccess, s.relayConnected, s.localProxies)
} }
func (s *stateDump) RemoteAnswer() { func (s *StateDump) RemoteAnswer() {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
s.remoteAnswer++ s.remoteAnswer++
} }
func (s *stateDump) P2PConnected() { func (s *StateDump) P2PConnected() {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
s.p2pConnected++ s.p2pConnected++
} }
func (s *stateDump) SwitchToRelay() { func (s *StateDump) SwitchToRelay() {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
s.switchToRelay++ s.switchToRelay++
} }
func (s *stateDump) WGcheckSuccess() { func (s *StateDump) WGcheckSuccess() {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
s.wgCheckSuccess++ s.wgCheckSuccess++
} }
func (s *stateDump) RelayConnected() { func (s *StateDump) RelayConnected() {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
s.relayConnected++ s.relayConnected++
} }
func (s *stateDump) NewLocalProxy() { func (s *StateDump) NewLocalProxy() {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
+3 -2
View File
@@ -8,6 +8,7 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/netbirdio/netbird/client/iface/configurer" "github.com/netbirdio/netbird/client/iface/configurer"
"github.com/netbirdio/netbird/client/internal/peer/state_dump"
) )
const ( const (
@@ -29,7 +30,7 @@ type WGWatcher struct {
log *log.Entry log *log.Entry
wgIfaceStater WGInterfaceStater wgIfaceStater WGInterfaceStater
peerKey string peerKey string
stateDump *stateDump stateDump *state_dump.StateDump
// initialHandshake is not thread-safe; never call PrepareInitialHandshake and EnableWgWatcher concurrently. // initialHandshake is not thread-safe; never call PrepareInitialHandshake and EnableWgWatcher concurrently.
initialHandshake time.Time initialHandshake time.Time
@@ -37,7 +38,7 @@ type WGWatcher struct {
resetCh chan struct{} resetCh chan struct{}
} }
func NewWGWatcher(log *log.Entry, wgIfaceStater WGInterfaceStater, peerKey string, stateDump *stateDump) *WGWatcher { func NewWGWatcher(log *log.Entry, wgIfaceStater WGInterfaceStater, peerKey string, stateDump *state_dump.StateDump) *WGWatcher {
return &WGWatcher{ return &WGWatcher{
log: log, log: log,
wgIfaceStater: wgIfaceStater, wgIfaceStater: wgIfaceStater,
+4 -3
View File
@@ -9,6 +9,7 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/netbirdio/netbird/client/iface/configurer" "github.com/netbirdio/netbird/client/iface/configurer"
"github.com/netbirdio/netbird/client/internal/peer/state_dump"
"github.com/netbirdio/netbird/client/internal/peer/status" "github.com/netbirdio/netbird/client/internal/peer/status"
) )
@@ -57,7 +58,7 @@ func TestWGWatcher_CheckSuccessCallback(t *testing.T) {
// platforms with coarse clock resolution (Windows), where two time.Now() calls // platforms with coarse clock resolution (Windows), where two time.Now() calls
// microseconds apart can return the same instant and read as a timed-out handshake. // microseconds apart can return the same instant and read as a timed-out handshake.
stats := &mockHandshakeStats{handshake: time.Now().Add(-time.Hour)} stats := &mockHandshakeStats{handshake: time.Now().Add(-time.Hour)}
watcher := NewWGWatcher(mlog, stats, "", newStateDump("peer", mlog, &status.Recorder{})) watcher := NewWGWatcher(mlog, stats, "", state_dump.NewStateDump("peer", mlog, &status.Recorder{}))
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
@@ -105,7 +106,7 @@ func TestWGWatcher_EnableWgWatcher(t *testing.T) {
mlog := log.WithField("peer", "tet") mlog := log.WithField("peer", "tet")
mocWgIface := &MocWgIface{} mocWgIface := &MocWgIface{}
watcher := NewWGWatcher(mlog, mocWgIface, "", newStateDump("peer", mlog, &status.Recorder{})) watcher := NewWGWatcher(mlog, mocWgIface, "", state_dump.NewStateDump("peer", mlog, &status.Recorder{}))
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
@@ -137,7 +138,7 @@ func TestWGWatcher_ReEnable(t *testing.T) {
mlog := log.WithField("peer", "tet") mlog := log.WithField("peer", "tet")
mocWgIface := &MocWgIface{} mocWgIface := &MocWgIface{}
watcher := NewWGWatcher(mlog, mocWgIface, "", newStateDump("peer", mlog, &status.Recorder{})) watcher := NewWGWatcher(mlog, mocWgIface, "", state_dump.NewStateDump("peer", mlog, &status.Recorder{}))
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
watcher.PrepareInitialHandshake() watcher.PrepareInitialHandshake()