/
stats_handler.go
73 lines (58 loc) · 1.44 KB
/
stats_handler.go
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
package runner
import (
"context"
"sync"
"google.golang.org/grpc/stats"
"google.golang.org/grpc/status"
)
// StatsHandler is for gRPC stats
type statsHandler struct {
results chan *callResult
id int
hasLog bool
log Logger
lock sync.RWMutex
ignore bool
}
// HandleConn handle the connection
func (c *statsHandler) HandleConn(ctx context.Context, cs stats.ConnStats) {
// no-op
}
// TagConn exists to satisfy gRPC stats.Handler.
func (c *statsHandler) TagConn(ctx context.Context, cti *stats.ConnTagInfo) context.Context {
// no-op
return ctx
}
// HandleRPC implements per-RPC tracing and stats instrumentation.
func (c *statsHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) {
switch rs := rs.(type) {
case *stats.End:
ign := false
c.lock.RLock()
ign = c.ignore
c.lock.RUnlock()
if !ign {
duration := rs.EndTime.Sub(rs.BeginTime)
var st string
s, ok := status.FromError(rs.Error)
if ok {
st = s.Code().String()
}
c.results <- &callResult{rs.Error, st, duration, rs.EndTime}
if c.hasLog {
c.log.Debugw("Received RPC Stats",
"statsID", c.id, "code", st, "error", rs.Error,
"duration", duration, "stats", rs)
}
}
}
}
func (c *statsHandler) Ignore(val bool) {
c.lock.Lock()
defer c.lock.Unlock()
c.ignore = val
}
// TagRPC implements per-RPC context management.
func (c *statsHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context {
return ctx
}