stats.go 5.9 KB

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