github.com/v2fly/v2ray-core/v4@v4.45.2/app/stats/stats.go (about)

     1  //go:build !confonly
     2  // +build !confonly
     3  
     4  package stats
     5  
     6  //go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen
     7  
     8  import (
     9  	"context"
    10  	"sync"
    11  
    12  	"github.com/v2fly/v2ray-core/v4/common"
    13  	"github.com/v2fly/v2ray-core/v4/common/errors"
    14  	"github.com/v2fly/v2ray-core/v4/features/stats"
    15  )
    16  
    17  // Manager is an implementation of stats.Manager.
    18  type Manager struct {
    19  	access   sync.RWMutex
    20  	counters map[string]*Counter
    21  	channels map[string]*Channel
    22  	running  bool
    23  }
    24  
    25  // NewManager creates an instance of Statistics Manager.
    26  func NewManager(ctx context.Context, config *Config) (*Manager, error) {
    27  	m := &Manager{
    28  		counters: make(map[string]*Counter),
    29  		channels: make(map[string]*Channel),
    30  	}
    31  
    32  	return m, nil
    33  }
    34  
    35  // Type implements common.HasType.
    36  func (*Manager) Type() interface{} {
    37  	return stats.ManagerType()
    38  }
    39  
    40  // RegisterCounter implements stats.Manager.
    41  func (m *Manager) RegisterCounter(name string) (stats.Counter, error) {
    42  	m.access.Lock()
    43  	defer m.access.Unlock()
    44  
    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  
    54  // UnregisterCounter implements stats.Manager.
    55  func (m *Manager) UnregisterCounter(name string) error {
    56  	m.access.Lock()
    57  	defer m.access.Unlock()
    58  
    59  	if _, found := m.counters[name]; found {
    60  		newError("remove counter ", name).AtDebug().WriteToLog()
    61  		delete(m.counters, name)
    62  	}
    63  	return nil
    64  }
    65  
    66  // GetCounter implements stats.Manager.
    67  func (m *Manager) GetCounter(name string) stats.Counter {
    68  	m.access.RLock()
    69  	defer m.access.RUnlock()
    70  
    71  	if c, found := m.counters[name]; found {
    72  		return c
    73  	}
    74  	return nil
    75  }
    76  
    77  // VisitCounters calls visitor function on all managed counters.
    78  func (m *Manager) VisitCounters(visitor func(string, stats.Counter) bool) {
    79  	m.access.RLock()
    80  	defer m.access.RUnlock()
    81  
    82  	for name, c := range m.counters {
    83  		if !visitor(name, c) {
    84  			break
    85  		}
    86  	}
    87  }
    88  
    89  // RegisterChannel implements stats.Manager.
    90  func (m *Manager) RegisterChannel(name string) (stats.Channel, error) {
    91  	m.access.Lock()
    92  	defer m.access.Unlock()
    93  
    94  	if _, found := m.channels[name]; found {
    95  		return nil, newError("Channel ", name, " already registered.")
    96  	}
    97  	newError("create new channel ", name).AtDebug().WriteToLog()
    98  	c := NewChannel(&ChannelConfig{BufferSize: 64, Blocking: false})
    99  	m.channels[name] = c
   100  	if m.running {
   101  		return c, c.Start()
   102  	}
   103  	return c, nil
   104  }
   105  
   106  // UnregisterChannel implements stats.Manager.
   107  func (m *Manager) UnregisterChannel(name string) error {
   108  	m.access.Lock()
   109  	defer m.access.Unlock()
   110  
   111  	if c, found := m.channels[name]; found {
   112  		newError("remove channel ", name).AtDebug().WriteToLog()
   113  		delete(m.channels, name)
   114  		return c.Close()
   115  	}
   116  	return nil
   117  }
   118  
   119  // GetChannel implements stats.Manager.
   120  func (m *Manager) GetChannel(name string) stats.Channel {
   121  	m.access.RLock()
   122  	defer m.access.RUnlock()
   123  
   124  	if c, found := m.channels[name]; found {
   125  		return c
   126  	}
   127  	return nil
   128  }
   129  
   130  // Start implements common.Runnable.
   131  func (m *Manager) Start() error {
   132  	m.access.Lock()
   133  	defer m.access.Unlock()
   134  	m.running = true
   135  	errs := []error{}
   136  	for _, channel := range m.channels {
   137  		if err := channel.Start(); err != nil {
   138  			errs = append(errs, err)
   139  		}
   140  	}
   141  	if len(errs) != 0 {
   142  		return errors.Combine(errs...)
   143  	}
   144  	return nil
   145  }
   146  
   147  // Close implement common.Closable.
   148  func (m *Manager) Close() error {
   149  	m.access.Lock()
   150  	defer m.access.Unlock()
   151  	m.running = false
   152  	errs := []error{}
   153  	for name, channel := range m.channels {
   154  		newError("remove channel ", name).AtDebug().WriteToLog()
   155  		delete(m.channels, name)
   156  		if err := channel.Close(); err != nil {
   157  			errs = append(errs, err)
   158  		}
   159  	}
   160  	if len(errs) != 0 {
   161  		return errors.Combine(errs...)
   162  	}
   163  	return nil
   164  }
   165  
   166  func init() {
   167  	common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
   168  		return NewManager(ctx, config.(*Config))
   169  	}))
   170  }