github.com/imannamdari/v2ray-core/v5@v5.0.5/features/stats/stats.go (about) 1 package stats 2 3 //go:generate go run github.com/imannamdari/v2ray-core/v5/common/errors/errorgen 4 5 import ( 6 "context" 7 8 "github.com/imannamdari/v2ray-core/v5/common" 9 "github.com/imannamdari/v2ray-core/v5/features" 10 ) 11 12 // Counter is the interface for stats counters. 13 // 14 // v2ray:api:stable 15 type Counter interface { 16 // Value is the current value of the counter. 17 Value() int64 18 // Set sets a new value to the counter, and returns the previous one. 19 Set(int64) int64 20 // Add adds a value to the current counter value, and returns the previous value. 21 Add(int64) int64 22 } 23 24 // Channel is the interface for stats channel. 25 // 26 // v2ray:api:stable 27 type Channel interface { 28 // Channel is a runnable unit. 29 common.Runnable 30 // Publish broadcasts a message through the channel with a controlling context. 31 Publish(context.Context, interface{}) 32 // SubscriberCount returns the number of the subscribers. 33 Subscribers() []chan interface{} 34 // Subscribe registers for listening to channel stream and returns a new listener channel. 35 Subscribe() (chan interface{}, error) 36 // Unsubscribe unregisters a listener channel from current Channel object. 37 Unsubscribe(chan interface{}) error 38 } 39 40 // SubscribeRunnableChannel subscribes the channel and starts it if there is first subscriber coming. 41 func SubscribeRunnableChannel(c Channel) (chan interface{}, error) { 42 if len(c.Subscribers()) == 0 { 43 if err := c.Start(); err != nil { 44 return nil, err 45 } 46 } 47 return c.Subscribe() 48 } 49 50 // UnsubscribeClosableChannel unsubscribes the channel and close it if there is no more subscriber. 51 func UnsubscribeClosableChannel(c Channel, sub chan interface{}) error { 52 if err := c.Unsubscribe(sub); err != nil { 53 return err 54 } 55 if len(c.Subscribers()) == 0 { 56 return c.Close() 57 } 58 return nil 59 } 60 61 // Manager is the interface for stats manager. 62 // 63 // v2ray:api:stable 64 type Manager interface { 65 features.Feature 66 67 // RegisterCounter registers a new counter to the manager. The identifier string must not be empty, and unique among other counters. 68 RegisterCounter(string) (Counter, error) 69 // UnregisterCounter unregisters a counter from the manager by its identifier. 70 UnregisterCounter(string) error 71 // GetCounter returns a counter by its identifier. 72 GetCounter(string) Counter 73 74 // RegisterChannel registers a new channel to the manager. The identifier string must not be empty, and unique among other channels. 75 RegisterChannel(string) (Channel, error) 76 // UnregisterCounter unregisters a channel from the manager by its identifier. 77 UnregisterChannel(string) error 78 // GetChannel returns a channel by its identifier. 79 GetChannel(string) Channel 80 } 81 82 // GetOrRegisterCounter tries to get the StatCounter first. If not exist, it then tries to create a new counter. 83 func GetOrRegisterCounter(m Manager, name string) (Counter, error) { 84 counter := m.GetCounter(name) 85 if counter != nil { 86 return counter, nil 87 } 88 89 return m.RegisterCounter(name) 90 } 91 92 // GetOrRegisterChannel tries to get the StatChannel first. If not exist, it then tries to create a new channel. 93 func GetOrRegisterChannel(m Manager, name string) (Channel, error) { 94 channel := m.GetChannel(name) 95 if channel != nil { 96 return channel, nil 97 } 98 99 return m.RegisterChannel(name) 100 } 101 102 // ManagerType returns the type of Manager interface. Can be used to implement common.HasType. 103 // 104 // v2ray:api:stable 105 func ManagerType() interface{} { 106 return (*Manager)(nil) 107 } 108 109 // NoopManager is an implementation of Manager, which doesn't has actual functionalities. 110 type NoopManager struct{} 111 112 // Type implements common.HasType. 113 func (NoopManager) Type() interface{} { 114 return ManagerType() 115 } 116 117 // RegisterCounter implements Manager. 118 func (NoopManager) RegisterCounter(string) (Counter, error) { 119 return nil, newError("not implemented") 120 } 121 122 // UnregisterCounter implements Manager. 123 func (NoopManager) UnregisterCounter(string) error { 124 return nil 125 } 126 127 // GetCounter implements Manager. 128 func (NoopManager) GetCounter(string) Counter { 129 return nil 130 } 131 132 // RegisterChannel implements Manager. 133 func (NoopManager) RegisterChannel(string) (Channel, error) { 134 return nil, newError("not implemented") 135 } 136 137 // UnregisterChannel implements Manager. 138 func (NoopManager) UnregisterChannel(string) error { 139 return nil 140 } 141 142 // GetChannel implements Manager. 143 func (NoopManager) GetChannel(string) Channel { 144 return nil 145 } 146 147 // Start implements common.Runnable. 148 func (NoopManager) Start() error { return nil } 149 150 // Close implements common.Closable. 151 func (NoopManager) Close() error { return nil }