command.go 3.0 KB

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