github.com/sagernet/sing-box@v1.9.0-rc.20/experimental/clashapi/trafficontrol/manager.go (about) 1 package trafficontrol 2 3 import ( 4 "runtime" 5 "time" 6 7 "github.com/sagernet/sing-box/experimental/clashapi/compatible" 8 "github.com/sagernet/sing/common/atomic" 9 ) 10 11 type Manager struct { 12 uploadTemp atomic.Int64 13 downloadTemp atomic.Int64 14 uploadBlip atomic.Int64 15 downloadBlip atomic.Int64 16 uploadTotal atomic.Int64 17 downloadTotal atomic.Int64 18 19 connections compatible.Map[string, tracker] 20 ticker *time.Ticker 21 done chan struct{} 22 // process *process.Process 23 memory uint64 24 } 25 26 func NewManager() *Manager { 27 manager := &Manager{ 28 ticker: time.NewTicker(time.Second), 29 done: make(chan struct{}), 30 // process: &process.Process{Pid: int32(os.Getpid())}, 31 } 32 go manager.handle() 33 return manager 34 } 35 36 func (m *Manager) Join(c tracker) { 37 m.connections.Store(c.ID(), c) 38 } 39 40 func (m *Manager) Leave(c tracker) { 41 m.connections.Delete(c.ID()) 42 } 43 44 func (m *Manager) PushUploaded(size int64) { 45 m.uploadTemp.Add(size) 46 m.uploadTotal.Add(size) 47 } 48 49 func (m *Manager) PushDownloaded(size int64) { 50 m.downloadTemp.Add(size) 51 m.downloadTotal.Add(size) 52 } 53 54 func (m *Manager) Now() (up int64, down int64) { 55 return m.uploadBlip.Load(), m.downloadBlip.Load() 56 } 57 58 func (m *Manager) Total() (up int64, down int64) { 59 return m.uploadTotal.Load(), m.downloadTotal.Load() 60 } 61 62 func (m *Manager) Connections() int { 63 return m.connections.Len() 64 } 65 66 func (m *Manager) Snapshot() *Snapshot { 67 var connections []tracker 68 m.connections.Range(func(_ string, value tracker) bool { 69 connections = append(connections, value) 70 return true 71 }) 72 73 var memStats runtime.MemStats 74 runtime.ReadMemStats(&memStats) 75 m.memory = memStats.StackInuse + memStats.HeapInuse + memStats.HeapIdle - memStats.HeapReleased 76 77 return &Snapshot{ 78 UploadTotal: m.uploadTotal.Load(), 79 DownloadTotal: m.downloadTotal.Load(), 80 Connections: connections, 81 Memory: m.memory, 82 } 83 } 84 85 func (m *Manager) ResetStatistic() { 86 m.uploadTemp.Store(0) 87 m.uploadBlip.Store(0) 88 m.uploadTotal.Store(0) 89 m.downloadTemp.Store(0) 90 m.downloadBlip.Store(0) 91 m.downloadTotal.Store(0) 92 } 93 94 func (m *Manager) handle() { 95 var uploadTemp int64 96 var downloadTemp int64 97 for { 98 select { 99 case <-m.done: 100 return 101 case <-m.ticker.C: 102 } 103 uploadTemp = m.uploadTemp.Swap(0) 104 downloadTemp = m.downloadTemp.Swap(0) 105 m.uploadBlip.Store(uploadTemp) 106 m.downloadBlip.Store(downloadTemp) 107 } 108 } 109 110 func (m *Manager) Close() error { 111 m.ticker.Stop() 112 close(m.done) 113 return nil 114 } 115 116 type Snapshot struct { 117 DownloadTotal int64 `json:"downloadTotal"` 118 UploadTotal int64 `json:"uploadTotal"` 119 Connections []tracker `json:"connections"` 120 Memory uint64 `json:"memory"` 121 }