github.com/eagleql/xray-core@v1.4.4/app/stats/command/command.go (about)

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