Browse Source

stats feature

pull/1008/head
Darien Raymond 7 years ago
parent
commit
35e160a1ff
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
  1. 13
      app/stats/config.go
  2. 42
      app/stats/config.pb.go
  3. 11
      app/stats/config.proto
  4. 5
      app/stats/errors.generated.go
  5. 68
      app/stats/stats.go
  6. 15
      app/stats/stats_test.go
  7. 10
      config.pb.go
  8. 71
      stats.go
  9. 9
      v2ray.go

13
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
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
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
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
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
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))
}

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

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

@ -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…
Cancel
Save