package statistic import ( "os" "sync" "time" "github.com/Dreamacro/clash/common/atomic" "github.com/shirou/gopsutil/v3/process" ) var DefaultManager *Manager func init() { DefaultManager = &Manager{ uploadTemp: atomic.NewInt64(0), downloadTemp: atomic.NewInt64(0), uploadBlip: atomic.NewInt64(0), downloadBlip: atomic.NewInt64(0), uploadTotal: atomic.NewInt64(0), downloadTotal: atomic.NewInt64(0), process: &process.Process{Pid: int32(os.Getpid())}, } go DefaultManager.handle() } type Manager struct { connections sync.Map uploadTemp *atomic.Int64 downloadTemp *atomic.Int64 uploadBlip *atomic.Int64 downloadBlip *atomic.Int64 uploadTotal *atomic.Int64 downloadTotal *atomic.Int64 process *process.Process memory uint64 } func (m *Manager) Join(c tracker) { m.connections.Store(c.ID(), c) } func (m *Manager) Leave(c tracker) { m.connections.Delete(c.ID()) } func (m *Manager) PushUploaded(size int64) { m.uploadTemp.Add(size) m.uploadTotal.Add(size) } func (m *Manager) PushDownloaded(size int64) { m.downloadTemp.Add(size) m.downloadTotal.Add(size) } func (m *Manager) Now() (up int64, down int64) { return m.uploadBlip.Load(), m.downloadBlip.Load() } func (m *Manager) Memory() uint64 { m.updateMemory() return m.memory } func (m *Manager) Snapshot() *Snapshot { connections := []tracker{} m.connections.Range(func(key, value any) bool { connections = append(connections, value.(tracker)) return true }) return &Snapshot{ UploadTotal: m.uploadTotal.Load(), DownloadTotal: m.downloadTotal.Load(), Connections: connections, Memory: m.memory, } } func (m *Manager) updateMemory() { stat, err := m.process.MemoryInfo() if err != nil { return } m.memory = stat.RSS } func (m *Manager) ResetStatistic() { m.uploadTemp.Store(0) m.uploadBlip.Store(0) m.uploadTotal.Store(0) m.downloadTemp.Store(0) m.downloadBlip.Store(0) m.downloadTotal.Store(0) } func (m *Manager) handle() { ticker := time.NewTicker(time.Second) for range ticker.C { m.uploadBlip.Store(m.uploadTemp.Load()) m.uploadTemp.Store(0) m.downloadBlip.Store(m.downloadTemp.Load()) m.downloadTemp.Store(0) } } type Snapshot struct { DownloadTotal int64 `json:"downloadTotal"` UploadTotal int64 `json:"uploadTotal"` Connections []tracker `json:"connections"` Memory uint64 `json:"memory"` }