diff --git a/box.go b/box.go index db57d095..f500df12 100644 --- a/box.go +++ b/box.go @@ -441,18 +441,6 @@ func New(options Options) (*Box, error) { service.MustRegister[adapter.V2RayServer](ctx, v2rayServer) } } - if experimentalOptions.UserManager != nil { - err = serviceManager.Create( - ctx, - logFactory.NewLogger("service/user_manager"), - "user_manager", - C.TypeUserManager, - experimentalOptions.UserManager, - ) - if err != nil { - return nil, E.Cause(err, "create user_manager") - } - } if ntpOptions.Enabled { ntpDialer, err := dialer.New(ctx, ntpOptions.DialerOptions, ntpOptions.ServerIsDomain()) if err != nil { diff --git a/service/usermanager/manager.go b/service/usermanager/manager.go index 8cecb63d..10ed243e 100644 --- a/service/usermanager/manager.go +++ b/service/usermanager/manager.go @@ -576,6 +576,20 @@ func (m *Manager) reportTrafficToServer() { } resp.Body.Close() m.logger.Debug("traffic reported, users=", len(traffic)) + + // Reset counters after successful report so the next report only + // contains fresh traffic (delta since last report). + // This avoids overcounting when multiple nodes or user_manager + // instances report for the same user — the control panel always + // receives independent per-interval values. + m.trafficAccess.Lock() + for username := range traffic { + if stored, ok := m.traffic[username]; ok { + stored.Tx.Add(-traffic[username].Tx) + stored.Rx.Add(-traffic[username].Rx) + } + } + m.trafficAccess.Unlock() } // HTTP API