123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- package command
- import (
- "context"
- "runtime"
- "time"
- "github.com/xtls/xray-core/app/stats"
- "github.com/xtls/xray-core/common"
- "github.com/xtls/xray-core/common/errors"
- "github.com/xtls/xray-core/common/strmatcher"
- "github.com/xtls/xray-core/core"
- feature_stats "github.com/xtls/xray-core/features/stats"
- grpc "google.golang.org/grpc"
- )
- // statsServer is an implementation of StatsService.
- type statsServer struct {
- stats feature_stats.Manager
- startTime time.Time
- }
- func NewStatsServer(manager feature_stats.Manager) StatsServiceServer {
- return &statsServer{
- stats: manager,
- startTime: time.Now(),
- }
- }
- func (s *statsServer) GetStats(ctx context.Context, request *GetStatsRequest) (*GetStatsResponse, error) {
- c := s.stats.GetCounter(request.Name)
- if c == nil {
- return nil, errors.New(request.Name, " not found.")
- }
- var value int64
- if request.Reset_ {
- value = c.Set(0)
- } else {
- value = c.Value()
- }
- return &GetStatsResponse{
- Stat: &Stat{
- Name: request.Name,
- Value: value,
- },
- }, nil
- }
- func (s *statsServer) QueryStats(ctx context.Context, request *QueryStatsRequest) (*QueryStatsResponse, error) {
- matcher, err := strmatcher.Substr.New(request.Pattern)
- if err != nil {
- return nil, err
- }
- response := &QueryStatsResponse{}
- manager, ok := s.stats.(*stats.Manager)
- if !ok {
- return nil, errors.New("QueryStats only works its own stats.Manager.")
- }
- manager.VisitCounters(func(name string, c feature_stats.Counter) bool {
- if matcher.Match(name) {
- var value int64
- if request.Reset_ {
- value = c.Set(0)
- } else {
- value = c.Value()
- }
- response.Stat = append(response.Stat, &Stat{
- Name: name,
- Value: value,
- })
- }
- return true
- })
- return response, nil
- }
- func (s *statsServer) GetSysStats(ctx context.Context, request *SysStatsRequest) (*SysStatsResponse, error) {
- var rtm runtime.MemStats
- runtime.ReadMemStats(&rtm)
- uptime := time.Since(s.startTime)
- response := &SysStatsResponse{
- Uptime: uint32(uptime.Seconds()),
- NumGoroutine: uint32(runtime.NumGoroutine()),
- Alloc: rtm.Alloc,
- TotalAlloc: rtm.TotalAlloc,
- Sys: rtm.Sys,
- Mallocs: rtm.Mallocs,
- Frees: rtm.Frees,
- LiveObjects: rtm.Mallocs - rtm.Frees,
- NumGC: rtm.NumGC,
- PauseTotalNs: rtm.PauseTotalNs,
- }
- return response, nil
- }
- func (s *statsServer) mustEmbedUnimplementedStatsServiceServer() {}
- type service struct {
- statsManager feature_stats.Manager
- }
- func (s *service) Register(server *grpc.Server) {
- ss := NewStatsServer(s.statsManager)
- RegisterStatsServiceServer(server, ss)
- // For compatibility purposes
- vCoreDesc := StatsService_ServiceDesc
- vCoreDesc.ServiceName = "v2ray.core.app.stats.command.StatsService"
- server.RegisterService(&vCoreDesc, ss)
- }
- func init() {
- common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, cfg interface{}) (interface{}, error) {
- s := new(service)
- core.RequireFeatures(ctx, func(sm feature_stats.Manager) {
- s.statsManager = sm
- })
- return s, nil
- }))
- }
|