github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/app/stats/stats.go (about) 1 // +build !confonly 2 3 package stats 4 5 //go:generate go run v2ray.com/core/common/errors/errorgen 6 7 import ( 8 "context" 9 "sync" 10 11 "v2ray.com/core/common" 12 "v2ray.com/core/common/errors" 13 "v2ray.com/core/features/stats" 14 ) 15 16 // Manager is an implementation of stats.Manager. 17 type Manager struct { 18 access sync.RWMutex 19 counters map[string]*Counter 20 ipStoragers map[string]*IPStorager 21 channels map[string]*Channel 22 running bool 23 } 24 25 // Type implements common.HasType. 26 func (*Manager) Type() interface{} { 27 return stats.ManagerType() 28 } 29 30 // NewManager creates an instance of Statistics Manager. 31 func NewManager(ctx context.Context, config *Config) (*Manager, error) { 32 m := &Manager{ 33 counters: make(map[string]*Counter), 34 channels: make(map[string]*Channel), 35 } 36 if config.TrackIp { 37 m.ipStoragers = make(map[string]*IPStorager) 38 } 39 return m, nil 40 } 41 42 func (m *Manager) RegisterIPStorager(name string) (stats.IPStorager, error) { 43 if m.ipStoragers == nil { 44 return nil, newError("IPStorager is disabled") 45 } 46 47 m.access.Lock() 48 defer m.access.Unlock() 49 50 if _, found := m.ipStoragers[name]; found { 51 return nil, newError("IPStorager ", name, " already registered.") 52 } 53 newError("create new IPStorager ", name).AtDebug().WriteToLog() 54 s := new(IPStorager) 55 m.ipStoragers[name] = s 56 return s, nil 57 } 58 59 func (m *Manager) GetIPStorager(name string) stats.IPStorager { 60 if m.ipStoragers == nil { 61 return nil 62 } 63 64 m.access.RLock() 65 defer m.access.RUnlock() 66 67 if s, found := m.ipStoragers[name]; found { 68 return s 69 } 70 return nil 71 } 72 73 func (m *Manager) VisitIPStoragers(visitor func(string, stats.IPStorager) bool) { 74 m.access.RLock() 75 defer m.access.RUnlock() 76 77 for name, c := range m.ipStoragers { 78 if !visitor(name, c) { 79 break 80 } 81 } 82 } 83 84 85 86 87 88 // RegisterCounter implements stats.Manager. 89 func (m *Manager) RegisterCounter(name string) (stats.Counter, error) { 90 m.access.Lock() 91 defer m.access.Unlock() 92 93 if _, found := m.counters[name]; found { 94 return nil, newError("Counter ", name, " already registered.") 95 } 96 newError("create new counter ", name).AtDebug().WriteToLog() 97 c := new(Counter) 98 m.counters[name] = c 99 return c, nil 100 } 101 102 // UnregisterCounter implements stats.Manager. 103 func (m *Manager) UnregisterCounter(name string) error { 104 m.access.Lock() 105 defer m.access.Unlock() 106 107 if _, found := m.counters[name]; found { 108 newError("remove counter ", name).AtDebug().WriteToLog() 109 delete(m.counters, name) 110 } 111 return nil 112 } 113 114 // GetCounter implements stats.Manager. 115 func (m *Manager) GetCounter(name string) stats.Counter { 116 m.access.RLock() 117 defer m.access.RUnlock() 118 119 if c, found := m.counters[name]; found { 120 return c 121 } 122 return nil 123 } 124 125 // VisitCounters calls visitor function on all managed counters. 126 func (m *Manager) VisitCounters(visitor func(string, stats.Counter) bool) { 127 m.access.RLock() 128 defer m.access.RUnlock() 129 130 for name, c := range m.counters { 131 if !visitor(name, c) { 132 break 133 } 134 } 135 } 136 137 // RegisterChannel implements stats.Manager. 138 func (m *Manager) RegisterChannel(name string) (stats.Channel, error) { 139 m.access.Lock() 140 defer m.access.Unlock() 141 142 if _, found := m.channels[name]; found { 143 return nil, newError("Channel ", name, " already registered.") 144 } 145 newError("create new channel ", name).AtDebug().WriteToLog() 146 c := NewChannel(&ChannelConfig{BufferSize: 64, Blocking: false}) 147 m.channels[name] = c 148 if m.running { 149 return c, c.Start() 150 } 151 return c, nil 152 } 153 154 // UnregisterChannel implements stats.Manager. 155 func (m *Manager) UnregisterChannel(name string) error { 156 m.access.Lock() 157 defer m.access.Unlock() 158 159 if c, found := m.channels[name]; found { 160 newError("remove channel ", name).AtDebug().WriteToLog() 161 delete(m.channels, name) 162 return c.Close() 163 } 164 return nil 165 } 166 167 // GetChannel implements stats.Manager. 168 func (m *Manager) GetChannel(name string) stats.Channel { 169 m.access.RLock() 170 defer m.access.RUnlock() 171 172 if c, found := m.channels[name]; found { 173 return c 174 } 175 return nil 176 } 177 178 // Start implements common.Runnable. 179 func (m *Manager) Start() error { 180 m.access.Lock() 181 defer m.access.Unlock() 182 m.running = true 183 errs := []error{} 184 for _, channel := range m.channels { 185 if err := channel.Start(); err != nil { 186 errs = append(errs, err) 187 } 188 } 189 if len(errs) != 0 { 190 return errors.Combine(errs...) 191 } 192 return nil 193 } 194 195 // Close implement common.Closable. 196 func (m *Manager) Close() error { 197 m.access.Lock() 198 defer m.access.Unlock() 199 m.running = false 200 errs := []error{} 201 for name, channel := range m.channels { 202 newError("remove channel ", name).AtDebug().WriteToLog() 203 delete(m.channels, name) 204 if err := channel.Close(); err != nil { 205 errs = append(errs, err) 206 } 207 } 208 if len(errs) != 0 { 209 return errors.Combine(errs...) 210 } 211 return nil 212 } 213 214 func init() { 215 common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { 216 return NewManager(ctx, config.(*Config)) 217 })) 218 }