github.com/moqsien/xraycore@v1.8.5/app/stats/command/command.go (about) 1 package command 2 3 //go:generate go run github.com/moqsien/xraycore/common/errors/errorgen 4 5 import ( 6 "context" 7 "runtime" 8 "time" 9 10 "github.com/moqsien/xraycore/app/stats" 11 "github.com/moqsien/xraycore/common" 12 "github.com/moqsien/xraycore/common/strmatcher" 13 "github.com/moqsien/xraycore/core" 14 feature_stats "github.com/moqsien/xraycore/features/stats" 15 grpc "google.golang.org/grpc" 16 ) 17 18 // statsServer is an implementation of StatsService. 19 type statsServer struct { 20 stats feature_stats.Manager 21 startTime time.Time 22 } 23 24 func NewStatsServer(manager feature_stats.Manager) StatsServiceServer { 25 return &statsServer{ 26 stats: manager, 27 startTime: time.Now(), 28 } 29 } 30 31 func (s *statsServer) GetStats(ctx context.Context, request *GetStatsRequest) (*GetStatsResponse, error) { 32 c := s.stats.GetCounter(request.Name) 33 if c == nil { 34 return nil, newError(request.Name, " not found.") 35 } 36 var value int64 37 if request.Reset_ { 38 value = c.Set(0) 39 } else { 40 value = c.Value() 41 } 42 return &GetStatsResponse{ 43 Stat: &Stat{ 44 Name: request.Name, 45 Value: value, 46 }, 47 }, nil 48 } 49 50 func (s *statsServer) QueryStats(ctx context.Context, request *QueryStatsRequest) (*QueryStatsResponse, error) { 51 matcher, err := strmatcher.Substr.New(request.Pattern) 52 if err != nil { 53 return nil, err 54 } 55 56 response := &QueryStatsResponse{} 57 58 manager, ok := s.stats.(*stats.Manager) 59 if !ok { 60 return nil, newError("QueryStats only works its own stats.Manager.") 61 } 62 63 manager.VisitCounters(func(name string, c feature_stats.Counter) bool { 64 if matcher.Match(name) { 65 var value int64 66 if request.Reset_ { 67 value = c.Set(0) 68 } else { 69 value = c.Value() 70 } 71 response.Stat = append(response.Stat, &Stat{ 72 Name: name, 73 Value: value, 74 }) 75 } 76 return true 77 }) 78 79 return response, nil 80 } 81 82 func (s *statsServer) GetSysStats(ctx context.Context, request *SysStatsRequest) (*SysStatsResponse, error) { 83 var rtm runtime.MemStats 84 runtime.ReadMemStats(&rtm) 85 86 uptime := time.Since(s.startTime) 87 88 response := &SysStatsResponse{ 89 Uptime: uint32(uptime.Seconds()), 90 NumGoroutine: uint32(runtime.NumGoroutine()), 91 Alloc: rtm.Alloc, 92 TotalAlloc: rtm.TotalAlloc, 93 Sys: rtm.Sys, 94 Mallocs: rtm.Mallocs, 95 Frees: rtm.Frees, 96 LiveObjects: rtm.Mallocs - rtm.Frees, 97 NumGC: rtm.NumGC, 98 PauseTotalNs: rtm.PauseTotalNs, 99 } 100 101 return response, nil 102 } 103 104 func (s *statsServer) mustEmbedUnimplementedStatsServiceServer() {} 105 106 type service struct { 107 statsManager feature_stats.Manager 108 } 109 110 func (s *service) Register(server *grpc.Server) { 111 ss := NewStatsServer(s.statsManager) 112 RegisterStatsServiceServer(server, ss) 113 114 // For compatibility purposes 115 vCoreDesc := StatsService_ServiceDesc 116 vCoreDesc.ServiceName = "v2ray.core.app.stats.command.StatsService" 117 server.RegisterService(&vCoreDesc, ss) 118 } 119 120 func init() { 121 common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, cfg interface{}) (interface{}, error) { 122 s := new(service) 123 124 core.RequireFeatures(ctx, func(sm feature_stats.Manager) { 125 s.statsManager = sm 126 }) 127 128 return s, nil 129 })) 130 }