1
0

stats.go 4.3 KB

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