Explorar el Código

stats feature

Darien Raymond hace 7 años
padre
commit
35e160a1ff
Se han modificado 9 ficheros con 239 adiciones y 5 borrados
  1. 13 0
      app/stats/config.go
  2. 42 0
      app/stats/config.pb.go
  3. 11 0
      app/stats/config.proto
  4. 5 0
      app/stats/errors.generated.go
  5. 68 0
      app/stats/stats.go
  6. 15 0
      app/stats/stats_test.go
  7. 6 4
      config.pb.go
  8. 71 0
      stats.go
  9. 8 1
      v2ray.go

+ 13 - 0
app/stats/config.go

@@ -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 - 0
app/stats/config.pb.go

@@ -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 - 0
app/stats/config.proto

@@ -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 - 0
app/stats/errors.generated.go

@@ -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 - 0
app/stats/stats.go

@@ -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 - 0
app/stats/stats_test.go

@@ -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))
+}

+ 6 - 4
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 - 0
stats.go

@@ -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
+}

+ 8 - 1
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)
+}