1
0

command.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. package command
  2. import (
  3. "context"
  4. "runtime"
  5. "time"
  6. "github.com/xtls/xray-core/app/stats"
  7. "github.com/xtls/xray-core/common"
  8. "github.com/xtls/xray-core/common/errors"
  9. "github.com/xtls/xray-core/common/strmatcher"
  10. "github.com/xtls/xray-core/core"
  11. feature_stats "github.com/xtls/xray-core/features/stats"
  12. grpc "google.golang.org/grpc"
  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, errors.New(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) GetStatsOnline(ctx context.Context, request *GetStatsRequest) (*GetStatsResponse, error) {
  44. c := s.stats.GetOnlineMap(request.Name)
  45. if c == nil {
  46. return nil, errors.New(request.Name, " not found.")
  47. }
  48. value := int64(c.Count())
  49. return &GetStatsResponse{
  50. Stat: &Stat{
  51. Name: request.Name,
  52. Value: value,
  53. },
  54. }, nil
  55. }
  56. func (s *statsServer) GetStatsOnlineIpList(ctx context.Context, request *GetStatsRequest) (*GetStatsOnlineIpListResponse, error) {
  57. c := s.stats.GetOnlineMap(request.Name)
  58. if c == nil {
  59. return nil, errors.New(request.Name, " not found.")
  60. }
  61. ips := make(map[string]int64)
  62. for ip, t := range c.IpTimeMap() {
  63. ips[ip] = t.Unix()
  64. }
  65. return &GetStatsOnlineIpListResponse{
  66. Name: request.Name,
  67. Ips: ips,
  68. }, nil
  69. }
  70. func (s *statsServer) QueryStats(ctx context.Context, request *QueryStatsRequest) (*QueryStatsResponse, error) {
  71. matcher, err := strmatcher.Substr.New(request.Pattern)
  72. if err != nil {
  73. return nil, err
  74. }
  75. response := &QueryStatsResponse{}
  76. manager, ok := s.stats.(*stats.Manager)
  77. if !ok {
  78. return nil, errors.New("QueryStats only works its own stats.Manager.")
  79. }
  80. manager.VisitCounters(func(name string, c feature_stats.Counter) bool {
  81. if matcher.Match(name) {
  82. var value int64
  83. if request.Reset_ {
  84. value = c.Set(0)
  85. } else {
  86. value = c.Value()
  87. }
  88. response.Stat = append(response.Stat, &Stat{
  89. Name: name,
  90. Value: value,
  91. })
  92. }
  93. return true
  94. })
  95. return response, nil
  96. }
  97. func (s *statsServer) GetSysStats(ctx context.Context, request *SysStatsRequest) (*SysStatsResponse, error) {
  98. var rtm runtime.MemStats
  99. runtime.ReadMemStats(&rtm)
  100. uptime := time.Since(s.startTime)
  101. response := &SysStatsResponse{
  102. Uptime: uint32(uptime.Seconds()),
  103. NumGoroutine: uint32(runtime.NumGoroutine()),
  104. Alloc: rtm.Alloc,
  105. TotalAlloc: rtm.TotalAlloc,
  106. Sys: rtm.Sys,
  107. Mallocs: rtm.Mallocs,
  108. Frees: rtm.Frees,
  109. LiveObjects: rtm.Mallocs - rtm.Frees,
  110. NumGC: rtm.NumGC,
  111. PauseTotalNs: rtm.PauseTotalNs,
  112. }
  113. return response, nil
  114. }
  115. func (s *statsServer) mustEmbedUnimplementedStatsServiceServer() {}
  116. type service struct {
  117. statsManager feature_stats.Manager
  118. }
  119. func (s *service) Register(server *grpc.Server) {
  120. ss := NewStatsServer(s.statsManager)
  121. RegisterStatsServiceServer(server, ss)
  122. // For compatibility purposes
  123. vCoreDesc := StatsService_ServiceDesc
  124. vCoreDesc.ServiceName = "v2ray.core.app.stats.command.StatsService"
  125. server.RegisterService(&vCoreDesc, ss)
  126. }
  127. func init() {
  128. common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, cfg interface{}) (interface{}, error) {
  129. s := new(service)
  130. core.RequireFeatures(ctx, func(sm feature_stats.Manager) {
  131. s.statsManager = sm
  132. })
  133. return s, nil
  134. }))
  135. }