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