github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/app/stats/stats.go (about)

     1  // +build !confonly
     2  
     3  package stats
     4  
     5  //go:generate go run v2ray.com/core/common/errors/errorgen
     6  
     7  import (
     8  	"context"
     9  	"sync"
    10  
    11  	"v2ray.com/core/common"
    12  	"v2ray.com/core/common/errors"
    13  	"v2ray.com/core/features/stats"
    14  )
    15  
    16  // Manager is an implementation of stats.Manager.
    17  type Manager struct {
    18  	access   sync.RWMutex
    19  	counters map[string]*Counter
    20  	ipStoragers map[string]*IPStorager
    21  	channels map[string]*Channel
    22  	running  bool
    23  }
    24  
    25  // Type implements common.HasType.
    26  func (*Manager) Type() interface{} {
    27  	return stats.ManagerType()
    28  }
    29  
    30  // NewManager creates an instance of Statistics Manager.
    31  func NewManager(ctx context.Context, config *Config) (*Manager, error) {
    32  	m := &Manager{
    33  		counters: make(map[string]*Counter),
    34  		channels: make(map[string]*Channel),
    35  	}
    36  	 if config.TrackIp {
    37  		m.ipStoragers = make(map[string]*IPStorager)
    38  	}
    39  	return m, nil
    40  }
    41  
    42  func (m *Manager) RegisterIPStorager(name string) (stats.IPStorager, error) {
    43  	if m.ipStoragers == nil {
    44  		return nil, newError("IPStorager is disabled")
    45  	}
    46  
    47  	m.access.Lock()
    48  	defer m.access.Unlock()
    49  
    50  	if _, found := m.ipStoragers[name]; found {
    51  		return nil, newError("IPStorager ", name, " already registered.")
    52  	}
    53  	newError("create new IPStorager ", name).AtDebug().WriteToLog()
    54  	s := new(IPStorager)
    55  	m.ipStoragers[name] = s
    56  	return s, nil
    57  }
    58  
    59  func (m *Manager) GetIPStorager(name string) stats.IPStorager {
    60  	if m.ipStoragers == nil {
    61  		return nil
    62  	}
    63  
    64  	m.access.RLock()
    65  	defer m.access.RUnlock()
    66  
    67  	if s, found := m.ipStoragers[name]; found {
    68  		return s
    69  	}
    70  	return nil
    71  }
    72  
    73  func (m *Manager) VisitIPStoragers(visitor func(string, stats.IPStorager) bool) {
    74  	m.access.RLock()
    75  	defer m.access.RUnlock()
    76  
    77  	for name, c := range m.ipStoragers {
    78  		if !visitor(name, c) {
    79  			break
    80  		}
    81  	}
    82  }
    83  
    84  
    85  
    86  
    87  
    88  // RegisterCounter implements stats.Manager.
    89  func (m *Manager) RegisterCounter(name string) (stats.Counter, error) {
    90  	m.access.Lock()
    91  	defer m.access.Unlock()
    92  
    93  	if _, found := m.counters[name]; found {
    94  		return nil, newError("Counter ", name, " already registered.")
    95  	}
    96  	newError("create new counter ", name).AtDebug().WriteToLog()
    97  	c := new(Counter)
    98  	m.counters[name] = c
    99  	return c, nil
   100  }
   101  
   102  // UnregisterCounter implements stats.Manager.
   103  func (m *Manager) UnregisterCounter(name string) error {
   104  	m.access.Lock()
   105  	defer m.access.Unlock()
   106  
   107  	if _, found := m.counters[name]; found {
   108  		newError("remove counter ", name).AtDebug().WriteToLog()
   109  		delete(m.counters, name)
   110  	}
   111  	return nil
   112  }
   113  
   114  // GetCounter implements stats.Manager.
   115  func (m *Manager) GetCounter(name string) stats.Counter {
   116  	m.access.RLock()
   117  	defer m.access.RUnlock()
   118  
   119  	if c, found := m.counters[name]; found {
   120  		return c
   121  	}
   122  	return nil
   123  }
   124  
   125  // VisitCounters calls visitor function on all managed counters.
   126  func (m *Manager) VisitCounters(visitor func(string, stats.Counter) bool) {
   127  	m.access.RLock()
   128  	defer m.access.RUnlock()
   129  
   130  	for name, c := range m.counters {
   131  		if !visitor(name, c) {
   132  			break
   133  		}
   134  	}
   135  }
   136  
   137  // RegisterChannel implements stats.Manager.
   138  func (m *Manager) RegisterChannel(name string) (stats.Channel, error) {
   139  	m.access.Lock()
   140  	defer m.access.Unlock()
   141  
   142  	if _, found := m.channels[name]; found {
   143  		return nil, newError("Channel ", name, " already registered.")
   144  	}
   145  	newError("create new channel ", name).AtDebug().WriteToLog()
   146  	c := NewChannel(&ChannelConfig{BufferSize: 64, Blocking: false})
   147  	m.channels[name] = c
   148  	if m.running {
   149  		return c, c.Start()
   150  	}
   151  	return c, nil
   152  }
   153  
   154  // UnregisterChannel implements stats.Manager.
   155  func (m *Manager) UnregisterChannel(name string) error {
   156  	m.access.Lock()
   157  	defer m.access.Unlock()
   158  
   159  	if c, found := m.channels[name]; found {
   160  		newError("remove channel ", name).AtDebug().WriteToLog()
   161  		delete(m.channels, name)
   162  		return c.Close()
   163  	}
   164  	return nil
   165  }
   166  
   167  // GetChannel implements stats.Manager.
   168  func (m *Manager) GetChannel(name string) stats.Channel {
   169  	m.access.RLock()
   170  	defer m.access.RUnlock()
   171  
   172  	if c, found := m.channels[name]; found {
   173  		return c
   174  	}
   175  	return nil
   176  }
   177  
   178  // Start implements common.Runnable.
   179  func (m *Manager) Start() error {
   180  	m.access.Lock()
   181  	defer m.access.Unlock()
   182  	m.running = true
   183  	errs := []error{}
   184  	for _, channel := range m.channels {
   185  		if err := channel.Start(); err != nil {
   186  			errs = append(errs, err)
   187  		}
   188  	}
   189  	if len(errs) != 0 {
   190  		return errors.Combine(errs...)
   191  	}
   192  	return nil
   193  }
   194  
   195  // Close implement common.Closable.
   196  func (m *Manager) Close() error {
   197  	m.access.Lock()
   198  	defer m.access.Unlock()
   199  	m.running = false
   200  	errs := []error{}
   201  	for name, channel := range m.channels {
   202  		newError("remove channel ", name).AtDebug().WriteToLog()
   203  		delete(m.channels, name)
   204  		if err := channel.Close(); err != nil {
   205  			errs = append(errs, err)
   206  		}
   207  	}
   208  	if len(errs) != 0 {
   209  		return errors.Combine(errs...)
   210  	}
   211  	return nil
   212  }
   213  
   214  func init() {
   215  	common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
   216  		return NewManager(ctx, config.(*Config))
   217  	}))
   218  }