stats.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package stats
  2. //go:generate errorgen
  3. import (
  4. "context"
  5. "sync"
  6. "sync/atomic"
  7. "v2ray.com/core"
  8. )
  9. // Counter is an implementation of core.StatCounter.
  10. type Counter struct {
  11. value int64
  12. }
  13. // Value implements core.StatCounter.
  14. func (c *Counter) Value() int64 {
  15. return atomic.LoadInt64(&c.value)
  16. }
  17. // Set implements core.StatCounter.
  18. func (c *Counter) Set(newValue int64) int64 {
  19. return atomic.SwapInt64(&c.value, newValue)
  20. }
  21. // Add implements core.StatCounter.
  22. func (c *Counter) Add(delta int64) int64 {
  23. return atomic.AddInt64(&c.value, delta)
  24. }
  25. // Manager is an implementation of core.StatManager.
  26. type Manager struct {
  27. access sync.RWMutex
  28. counters map[string]*Counter
  29. }
  30. func NewManager(ctx context.Context, config *Config) (*Manager, error) {
  31. m := &Manager{
  32. counters: make(map[string]*Counter),
  33. }
  34. v := core.FromContext(ctx)
  35. if v != nil {
  36. if err := v.RegisterFeature((*core.StatManager)(nil), m); err != nil {
  37. return nil, newError("failed to register StatManager").Base(err)
  38. }
  39. }
  40. return m, nil
  41. }
  42. func (m *Manager) RegisterCounter(name string) (core.StatCounter, error) {
  43. m.access.Lock()
  44. defer m.access.Unlock()
  45. if _, found := m.counters[name]; found {
  46. return nil, newError("Counter ", name, " already registered.")
  47. }
  48. newError("create new counter ", name).AtDebug().WriteToLog()
  49. c := new(Counter)
  50. m.counters[name] = c
  51. return c, nil
  52. }
  53. func (m *Manager) GetCounter(name string) core.StatCounter {
  54. m.access.RLock()
  55. defer m.access.RUnlock()
  56. if c, found := m.counters[name]; found {
  57. return c
  58. }
  59. return nil
  60. }
  61. func (m *Manager) Visit(visitor func(string, core.StatCounter) bool) {
  62. m.access.RLock()
  63. defer m.access.RUnlock()
  64. for name, c := range m.counters {
  65. if !visitor(name, c) {
  66. break
  67. }
  68. }
  69. }
  70. // Start implements common.Runnable.
  71. func (m *Manager) Start() error {
  72. return nil
  73. }
  74. // Close implement common.Closable.
  75. func (m *Manager) Close() error {
  76. return nil
  77. }