blob: dbcdda4158ce4e8570082d87b93660f784e3900f [file] [log] [blame]
Robin Thellend8eb77522014-08-28 14:12:01 -07001package ipc
2
3import (
4 "sync"
5 "time"
6
Jiri Simsa764efb72014-12-25 20:57:03 -08007 "v.io/core/veyron/lib/stats"
8 "v.io/core/veyron/lib/stats/counter"
9 "v.io/core/veyron/lib/stats/histogram"
Robin Thellend8eb77522014-08-28 14:12:01 -070010
Jiri Simsa764efb72014-12-25 20:57:03 -080011 "v.io/core/veyron2/naming"
Robin Thellend8eb77522014-08-28 14:12:01 -070012)
13
14type ipcStats struct {
Suharsh Sivakumar720b7042014-12-22 17:33:23 -080015 mu sync.RWMutex
16 prefix string
17 methods map[string]*perMethodStats
18 blessingsCacheStats *blessingsCacheStats
Robin Thellend8eb77522014-08-28 14:12:01 -070019}
20
21func newIPCStats(prefix string) *ipcStats {
Suharsh Sivakumar720b7042014-12-22 17:33:23 -080022 return &ipcStats{
23 prefix: prefix,
24 methods: make(map[string]*perMethodStats),
25 blessingsCacheStats: newBlessingsCacheStats(prefix),
26 }
Robin Thellend8eb77522014-08-28 14:12:01 -070027}
28
29type perMethodStats struct {
30 latency *histogram.Histogram
31}
32
Robin Thellenddf428232014-10-06 12:50:44 -070033func (s *ipcStats) stop() {
34 stats.Delete(s.prefix)
35}
36
Robin Thellend8eb77522014-08-28 14:12:01 -070037func (s *ipcStats) record(method string, latency time.Duration) {
38 // Try first with a read lock. This will succeed in the most common
39 // case. If it fails, try again with a write lock and create the stats
40 // objects if they are still not there.
41 s.mu.RLock()
42 m, ok := s.methods[method]
43 s.mu.RUnlock()
44 if !ok {
45 m = s.newPerMethodStats(method)
46 }
47 m.latency.Add(int64(latency / time.Millisecond))
48}
49
Suharsh Sivakumar720b7042014-12-22 17:33:23 -080050func (s *ipcStats) recordBlessingCache(hit bool) {
51 s.blessingsCacheStats.incr(hit)
52}
53
Robin Thellend8eb77522014-08-28 14:12:01 -070054// newPerMethodStats creates a new perMethodStats object if one doesn't exist
55// already. It returns the newly created object, or the already existing one.
56func (s *ipcStats) newPerMethodStats(method string) *perMethodStats {
57 s.mu.Lock()
58 defer s.mu.Unlock()
59 m, ok := s.methods[method]
60 if !ok {
Bogdan Capritae7376312014-11-10 13:13:17 -080061 name := naming.Join(s.prefix, "methods", method, "latency-ms")
Robin Thellend8eb77522014-08-28 14:12:01 -070062 s.methods[method] = &perMethodStats{
63 latency: stats.NewHistogram(name, histogram.Options{
64 NumBuckets: 25,
65 GrowthFactor: 1,
66 SmallestBucketSize: 1,
67 MinValue: 0,
68 }),
69 }
70 m = s.methods[method]
71 }
72 return m
73}
Suharsh Sivakumar720b7042014-12-22 17:33:23 -080074
75// blessingsCacheStats keeps blessing cache hits and total calls received to determine
76// how often the blessingCache is being used.
77type blessingsCacheStats struct {
78 callsReceived, cacheHits *counter.Counter
79}
80
81func newBlessingsCacheStats(prefix string) *blessingsCacheStats {
82 cachePrefix := naming.Join(prefix, "security", "blessings", "cache")
83 return &blessingsCacheStats{
84 callsReceived: stats.NewCounter(naming.Join(cachePrefix, "attempts")),
85 cacheHits: stats.NewCounter(naming.Join(cachePrefix, "hits")),
86 }
87}
88
89// Incr increments the cache attempt counter and the cache hit counter if hit is true.
90func (s *blessingsCacheStats) incr(hit bool) {
91 s.callsReceived.Incr(1)
92 if hit {
93 s.cacheHits.Incr(1)
94 }
95}