stats.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // +build !confonly
  2. package stats
  3. //go:generate errorgen
  4. import (
  5. "context"
  6. "sync"
  7. "v2ray.com/core/features/stats"
  8. )
  9. // Manager is an implementation of stats.Manager.
  10. type Manager struct {
  11. access sync.RWMutex
  12. counters map[string]*Counter
  13. channels map[string]*Channel
  14. running bool
  15. }
  16. // NewManager creates an instance of Statistics Manager.
  17. func NewManager(ctx context.Context, config *Config) (*Manager, error) {
  18. m := &Manager{
  19. counters: make(map[string]*Counter),
  20. channels: make(map[string]*Channel),
  21. }
  22. return m, nil
  23. }
  24. // Type implements common.HasType.
  25. func (*Manager) Type() interface{} {
  26. return stats.ManagerType()
  27. }
  28. // RegisterCounter implements stats.Manager.
  29. func (m *Manager) RegisterCounter(name string) (stats.Counter, error) {
  30. m.access.Lock()
  31. defer m.access.Unlock()
  32. if _, found := m.counters[name]; found {
  33. return nil, newError("Counter ", name, " already registered.")
  34. }
  35. newError("create new counter ", name).AtDebug().WriteToLog()
  36. c := new(Counter)
  37. m.counters[name] = c
  38. return c, nil
  39. }
  40. // UnregisterCounter implements stats.Manager.
  41. func (m *Manager) UnregisterCounter(name string) error {
  42. m.access.Lock()
  43. defer m.access.Unlock()
  44. if _, found := m.counters[name]; found {
  45. newError("remove counter ", name).AtDebug().WriteToLog()
  46. delete(m.counters, name)
  47. }
  48. return nil
  49. }
  50. // GetCounter implements stats.Manager.
  51. func (m *Manager) GetCounter(name string) stats.Counter {
  52. m.access.RLock()
  53. defer m.access.RUnlock()
  54. if c, found := m.counters[name]; found {
  55. return c
  56. }
  57. return nil
  58. }
  59. // VisitCounters calls visitor function on all managed counters.
  60. func (m *Manager) VisitCounters(visitor func(string, stats.Counter) bool) {
  61. m.access.RLock()
  62. defer m.access.RUnlock()
  63. for name, c := range m.counters {
  64. if !visitor(name, c) {
  65. break
  66. }
  67. }
  68. }
  69. // RegisterChannel implements stats.Manager.
  70. func (m *Manager) RegisterChannel(name string) (stats.Channel, error) {
  71. m.access.Lock()
  72. defer m.access.Unlock()
  73. if _, found := m.channels[name]; found {
  74. return nil, newError("Channel ", name, " already registered.")
  75. }
  76. newError("create new channel ", name).AtDebug().WriteToLog()
  77. c := new(Channel)
  78. m.channels[name] = c
  79. if m.running {
  80. c.Start()
  81. }
  82. return c, nil
  83. }
  84. // UnregisterChannel implements stats.Manager.
  85. func (m *Manager) UnregisterChannel(name string) error {
  86. m.access.Lock()
  87. defer m.access.Unlock()
  88. if c, found := m.channels[name]; found {
  89. newError("remove channel ", name).AtDebug().WriteToLog()
  90. delete(m.channels, name)
  91. c.Close()
  92. }
  93. return nil
  94. }
  95. // GetChannel implements stats.Manager.
  96. func (m *Manager) GetChannel(name string) stats.Channel {
  97. m.access.RLock()
  98. defer m.access.RUnlock()
  99. if c, found := m.channels[name]; found {
  100. return c
  101. }
  102. return nil
  103. }
  104. // Start implements common.Runnable.
  105. func (m *Manager) Start() error {
  106. m.access.Lock()
  107. defer m.access.Unlock()
  108. m.running = true
  109. for _, channel := range m.channels {
  110. channel.Start()
  111. }
  112. return nil
  113. }
  114. // Close implement common.Closable.
  115. func (m *Manager) Close() error {
  116. m.access.Lock()
  117. defer m.access.Unlock()
  118. m.running = false
  119. for name, channel := range m.channels {
  120. newError("remove channel ", name).AtDebug().WriteToLog()
  121. delete(m.channels, name)
  122. channel.Close()
  123. }
  124. return nil
  125. }