stats.go 4.2 KB

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