command.go 2.9 KB

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