mirror of
https://github.com/v2fly/v2ray-core.git
synced 2025-01-02 15:36:41 -05:00
stats feature
This commit is contained in:
parent
24f393a23f
commit
35e160a1ff
13
app/stats/config.go
Normal file
13
app/stats/config.go
Normal file
@ -0,0 +1,13 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"v2ray.com/core/common"
|
||||
)
|
||||
|
||||
func init() {
|
||||
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||
return NewManager(ctx, config.(*Config))
|
||||
}))
|
||||
}
|
42
app/stats/config.pb.go
Normal file
42
app/stats/config.pb.go
Normal file
@ -0,0 +1,42 @@
|
||||
package stats
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type Config struct {
|
||||
}
|
||||
|
||||
func (m *Config) Reset() { *m = Config{} }
|
||||
func (m *Config) String() string { return proto.CompactTextString(m) }
|
||||
func (*Config) ProtoMessage() {}
|
||||
func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Config)(nil), "v2ray.core.app.stats.Config")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("v2ray.com/core/app/stats/config.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 123 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2d, 0x33, 0x2a, 0x4a,
|
||||
0xac, 0xd4, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0x4a, 0xd5, 0x4f, 0x2c, 0x28, 0xd0, 0x2f,
|
||||
0x2e, 0x49, 0x2c, 0x29, 0xd6, 0x4f, 0xce, 0xcf, 0x4b, 0xcb, 0x4c, 0xd7, 0x2b, 0x28, 0xca, 0x2f,
|
||||
0xc9, 0x17, 0x12, 0x81, 0x29, 0x2b, 0x4a, 0xd5, 0x4b, 0x2c, 0x28, 0xd0, 0x03, 0x2b, 0x51, 0xe2,
|
||||
0xe0, 0x62, 0x73, 0x06, 0xab, 0x72, 0xb2, 0xe2, 0x92, 0x48, 0xce, 0xcf, 0xd5, 0xc3, 0xa6, 0x2a,
|
||||
0x80, 0x31, 0x8a, 0x15, 0xcc, 0x58, 0xc5, 0x24, 0x12, 0x66, 0x14, 0x94, 0x58, 0xa9, 0xe7, 0x0c,
|
||||
0x92, 0x77, 0x2c, 0x28, 0xd0, 0x0b, 0x06, 0x09, 0x27, 0xb1, 0x81, 0xad, 0x30, 0x06, 0x04, 0x00,
|
||||
0x00, 0xff, 0xff, 0x88, 0x24, 0xc6, 0x41, 0x8b, 0x00, 0x00, 0x00,
|
||||
}
|
11
app/stats/config.proto
Normal file
11
app/stats/config.proto
Normal file
@ -0,0 +1,11 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package v2ray.core.app.stats;
|
||||
option csharp_namespace = "V2Ray.Core.App.Stats";
|
||||
option go_package = "stats";
|
||||
option java_package = "com.v2ray.core.app.stats";
|
||||
option java_multiple_files = true;
|
||||
|
||||
message Config {
|
||||
|
||||
}
|
5
app/stats/errors.generated.go
Normal file
5
app/stats/errors.generated.go
Normal file
@ -0,0 +1,5 @@
|
||||
package stats
|
||||
|
||||
import "v2ray.com/core/common/errors"
|
||||
|
||||
func newError(values ...interface{}) *errors.Error { return errors.New(values...).Path("App", "Stats") }
|
68
app/stats/stats.go
Normal file
68
app/stats/stats.go
Normal file
@ -0,0 +1,68 @@
|
||||
package stats
|
||||
|
||||
//go:generate go run $GOPATH/src/v2ray.com/core/common/errors/errorgen/main.go -pkg stats -path App,Stats
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"v2ray.com/core"
|
||||
)
|
||||
|
||||
type Counter struct {
|
||||
value int64
|
||||
}
|
||||
|
||||
func (c *Counter) Value() int64 {
|
||||
return atomic.LoadInt64(&c.value)
|
||||
}
|
||||
|
||||
func (c *Counter) Exchange(newValue int64) int64 {
|
||||
return atomic.SwapInt64(&c.value, newValue)
|
||||
}
|
||||
|
||||
func (c *Counter) Add(delta int64) int64 {
|
||||
return atomic.AddInt64(&c.value, delta)
|
||||
}
|
||||
|
||||
type Manager struct {
|
||||
access sync.RWMutex
|
||||
counters map[string]*Counter
|
||||
}
|
||||
|
||||
func NewManager(ctx context.Context, config *Config) (*Manager, error) {
|
||||
return &Manager{
|
||||
counters: make(map[string]*Counter),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *Manager) RegisterCounter(name string) (core.StatCounter, error) {
|
||||
m.access.Lock()
|
||||
defer m.access.Unlock()
|
||||
|
||||
if _, found := m.counters[name]; found {
|
||||
return nil, newError("Counter ", name, " already registered.")
|
||||
}
|
||||
c := new(Counter)
|
||||
m.counters[name] = c
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (m *Manager) GetCounter(name string) core.StatCounter {
|
||||
m.access.RLock()
|
||||
defer m.access.RUnlock()
|
||||
|
||||
if c, found := m.counters[name]; found {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) Start() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) Close() error {
|
||||
return nil
|
||||
}
|
15
app/stats/stats_test.go
Normal file
15
app/stats/stats_test.go
Normal file
@ -0,0 +1,15 @@
|
||||
package stats_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"v2ray.com/core"
|
||||
. "v2ray.com/core/app/stats"
|
||||
. "v2ray.com/ext/assert"
|
||||
)
|
||||
|
||||
func TestInternface(t *testing.T) {
|
||||
assert := With(t)
|
||||
|
||||
assert((*Manager)(nil), Implements, (*core.StatManager)(nil))
|
||||
}
|
10
config.pb.go
10
config.pb.go
@ -23,7 +23,7 @@ type Config struct {
|
||||
Inbound []*InboundHandlerConfig `protobuf:"bytes,1,rep,name=inbound" json:"inbound,omitempty"`
|
||||
// Outbound handler configurations. Must have at least one item. The first item is used as default for routing.
|
||||
Outbound []*OutboundHandlerConfig `protobuf:"bytes,2,rep,name=outbound" json:"outbound,omitempty"`
|
||||
// App configuration. Must be one in the app directory.
|
||||
// App is for configurations of all features in V2Ray. A feature must implement the Feature interface, and its config type must be registered through common.RegisterConfig.
|
||||
App []*v2ray_core_common_serial.TypedMessage `protobuf:"bytes,4,rep,name=app" json:"app,omitempty"`
|
||||
// Transport settings.
|
||||
Transport *v2ray_core_transport.Config `protobuf:"bytes,5,opt,name=transport" json:"transport,omitempty"`
|
||||
@ -72,10 +72,11 @@ func (m *Config) GetExtension() []*v2ray_core_common_serial.TypedMessage {
|
||||
return nil
|
||||
}
|
||||
|
||||
// InboundHandlerConfig is the configuration for inbound handler.
|
||||
type InboundHandlerConfig struct {
|
||||
// Tag of the inbound handler.
|
||||
// Tag of the inbound handler. The tag must be unique among all inbound handlers
|
||||
Tag string `protobuf:"bytes,1,opt,name=tag" json:"tag,omitempty"`
|
||||
// Settings for how this inbound proxy is handled. Must be ReceiverConfig above.
|
||||
// Settings for how this inbound proxy is handled.
|
||||
ReceiverSettings *v2ray_core_common_serial.TypedMessage `protobuf:"bytes,2,opt,name=receiver_settings,json=receiverSettings" json:"receiver_settings,omitempty"`
|
||||
// Settings for inbound proxy. Must be one of the inbound proxies.
|
||||
ProxySettings *v2ray_core_common_serial.TypedMessage `protobuf:"bytes,3,opt,name=proxy_settings,json=proxySettings" json:"proxy_settings,omitempty"`
|
||||
@ -107,10 +108,11 @@ func (m *InboundHandlerConfig) GetProxySettings() *v2ray_core_common_serial.Type
|
||||
return nil
|
||||
}
|
||||
|
||||
// OutboundHandlerConfig is the configuration for outbound handler.
|
||||
type OutboundHandlerConfig struct {
|
||||
// Tag of this outbound handler.
|
||||
Tag string `protobuf:"bytes,1,opt,name=tag" json:"tag,omitempty"`
|
||||
// Settings for how to dial connection for this outbound handler. Must be SenderConfig above.
|
||||
// Settings for how to dial connection for this outbound handler.
|
||||
SenderSettings *v2ray_core_common_serial.TypedMessage `protobuf:"bytes,2,opt,name=sender_settings,json=senderSettings" json:"sender_settings,omitempty"`
|
||||
// Settings for this outbound proxy. Must be one of the outbound proxies.
|
||||
ProxySettings *v2ray_core_common_serial.TypedMessage `protobuf:"bytes,3,opt,name=proxy_settings,json=proxySettings" json:"proxy_settings,omitempty"`
|
||||
|
71
stats.go
Normal file
71
stats.go
Normal file
@ -0,0 +1,71 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type StatCounter interface {
|
||||
Value() int64
|
||||
Exchange(int64) int64
|
||||
Add(int64) int64
|
||||
}
|
||||
|
||||
type StatManager interface {
|
||||
Feature
|
||||
|
||||
RegisterCounter(string) (StatCounter, error)
|
||||
GetCounter(string) StatCounter
|
||||
}
|
||||
|
||||
type syncStatManager struct {
|
||||
sync.RWMutex
|
||||
StatManager
|
||||
}
|
||||
|
||||
func (s *syncStatManager) Start() error {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
|
||||
if s.StatManager == nil {
|
||||
return newError("StatManager not set.")
|
||||
}
|
||||
|
||||
return s.StatManager.Start()
|
||||
}
|
||||
|
||||
func (s *syncStatManager) Close() error {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
|
||||
if s.StatManager == nil {
|
||||
return newError("StatManager not set.")
|
||||
}
|
||||
return s.StatManager.Close()
|
||||
}
|
||||
|
||||
func (s *syncStatManager) RegisterCounter(name string) (StatCounter, error) {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
|
||||
if s.StatManager == nil {
|
||||
return nil, newError("StatManager not set.")
|
||||
}
|
||||
return s.StatManager.RegisterCounter(name)
|
||||
}
|
||||
|
||||
func (s *syncStatManager) GetCounter(name string) StatCounter {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
|
||||
if s.StatManager == nil {
|
||||
return nil
|
||||
}
|
||||
return s.StatManager.GetCounter(name)
|
||||
}
|
||||
|
||||
func (s *syncStatManager) Set(m StatManager) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
s.StatManager = m
|
||||
}
|
9
v2ray.go
9
v2ray.go
@ -28,6 +28,7 @@ type Instance struct {
|
||||
router syncRouter
|
||||
ihm syncInboundHandlerManager
|
||||
ohm syncOutboundHandlerManager
|
||||
stats syncStatManager
|
||||
|
||||
access sync.Mutex
|
||||
features []Feature
|
||||
@ -148,6 +149,8 @@ func (s *Instance) RegisterFeature(feature interface{}, instance Feature) error
|
||||
s.ihm.Set(instance.(InboundHandlerManager))
|
||||
case OutboundHandlerManager, *OutboundHandlerManager:
|
||||
s.ohm.Set(instance.(OutboundHandlerManager))
|
||||
case StatManager, *StatManager:
|
||||
s.stats.Set(instance.(StatManager))
|
||||
default:
|
||||
s.access.Lock()
|
||||
s.features = append(s.features, instance)
|
||||
@ -162,7 +165,7 @@ func (s *Instance) RegisterFeature(feature interface{}, instance Feature) error
|
||||
}
|
||||
|
||||
func (s *Instance) allFeatures() []Feature {
|
||||
return append([]Feature{s.DNSClient(), s.PolicyManager(), s.Dispatcher(), s.Router(), s.InboundHandlerManager(), s.OutboundHandlerManager()}, s.features...)
|
||||
return append([]Feature{s.DNSClient(), s.PolicyManager(), s.Dispatcher(), s.Router(), s.InboundHandlerManager(), s.OutboundHandlerManager(), s.Stats()}, s.features...)
|
||||
}
|
||||
|
||||
// GetFeature returns a feature that was registered in this Instance. Nil if not found.
|
||||
@ -207,3 +210,7 @@ func (s *Instance) InboundHandlerManager() InboundHandlerManager {
|
||||
func (s *Instance) OutboundHandlerManager() OutboundHandlerManager {
|
||||
return &(s.ohm)
|
||||
}
|
||||
|
||||
func (s *Instance) Stats() StatManager {
|
||||
return &(s.stats)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user