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