github.com/xtls/xray-core@v1.8.12-0.20240518155711-3168d27b0bdb/app/stats/command/command.go (about)

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