github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/experimental/clashapi/trafficontrol/manager.go (about) 1 package trafficontrol 2 3 import ( 4 "runtime" 5 "time" 6 7 "github.com/inazumav/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 //if memoryInfo, err := m.process.MemoryInfo(); err == nil { 74 // m.memory = memoryInfo.RSS 75 //} else { 76 var memStats runtime.MemStats 77 runtime.ReadMemStats(&memStats) 78 m.memory = memStats.StackInuse + memStats.HeapInuse + memStats.HeapIdle - memStats.HeapReleased 79 80 return &Snapshot{ 81 UploadTotal: m.uploadTotal.Load(), 82 DownloadTotal: m.downloadTotal.Load(), 83 Connections: connections, 84 Memory: m.memory, 85 } 86 } 87 88 func (m *Manager) ResetStatistic() { 89 m.uploadTemp.Store(0) 90 m.uploadBlip.Store(0) 91 m.uploadTotal.Store(0) 92 m.downloadTemp.Store(0) 93 m.downloadBlip.Store(0) 94 m.downloadTotal.Store(0) 95 } 96 97 func (m *Manager) handle() { 98 var uploadTemp int64 99 var downloadTemp int64 100 for { 101 select { 102 case <-m.done: 103 return 104 case <-m.ticker.C: 105 } 106 uploadTemp = m.uploadTemp.Swap(0) 107 downloadTemp = m.downloadTemp.Swap(0) 108 m.uploadBlip.Store(uploadTemp) 109 m.downloadBlip.Store(downloadTemp) 110 } 111 } 112 113 func (m *Manager) Close() error { 114 m.ticker.Stop() 115 close(m.done) 116 return nil 117 } 118 119 type Snapshot struct { 120 DownloadTotal int64 `json:"downloadTotal"` 121 UploadTotal int64 `json:"uploadTotal"` 122 Connections []tracker `json:"connections"` 123 Memory uint64 `json:"memory"` 124 }