github.com/eagleql/xray-core@v1.4.4/features/stats/stats.go (about)

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