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