command.go 3.1 KB

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