Hunter0x7c7
2022-08-11 a82f9cb69f63aaeba40c024960deda7d75b9fece
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package command
 
//go:generate go run github.com/v2fly/v2ray-core/v5/common/errors/errorgen
 
import (
    "context"
    "runtime"
    "time"
 
    grpc "google.golang.org/grpc"
 
    core "github.com/v2fly/v2ray-core/v5"
    "github.com/v2fly/v2ray-core/v5/app/stats"
    "github.com/v2fly/v2ray-core/v5/common"
    "github.com/v2fly/v2ray-core/v5/common/strmatcher"
    feature_stats "github.com/v2fly/v2ray-core/v5/features/stats"
)
 
// 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, newError(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) {
    mgroup := &strmatcher.LinearIndexMatcher{}
    if request.Pattern != "" {
        request.Patterns = append(request.Patterns, request.Pattern)
    }
    t := strmatcher.Substr
    if request.Regexp {
        t = strmatcher.Regex
    }
    for _, p := range request.Patterns {
        m, err := t.New(p)
        if err != nil {
            return nil, err
        }
        mgroup.Add(m)
    }
 
    response := &QueryStatsResponse{}
 
    manager, ok := s.stats.(*stats.Manager)
    if !ok {
        return nil, newError("QueryStats only works its own stats.Manager.")
    }
 
    manager.VisitCounters(func(name string, c feature_stats.Counter) bool {
        if mgroup.Size() == 0 || len(mgroup.Match(name)) > 0 {
            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) {
    RegisterStatsServiceServer(server, NewStatsServer(s.statsManager))
}
 
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
    }))
}