github.com/v2fly/v2ray-core/v4@v4.45.2/app/stats/command/command.go (about)

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