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