Robin Thellend | 8eb7752 | 2014-08-28 14:12:01 -0700 | [diff] [blame] | 1 | package ipc |
| 2 | |
| 3 | import ( |
| 4 | "sync" |
| 5 | "time" |
| 6 | |
Jiri Simsa | 764efb7 | 2014-12-25 20:57:03 -0800 | [diff] [blame] | 7 | "v.io/core/veyron/lib/stats" |
| 8 | "v.io/core/veyron/lib/stats/counter" |
| 9 | "v.io/core/veyron/lib/stats/histogram" |
Robin Thellend | 8eb7752 | 2014-08-28 14:12:01 -0700 | [diff] [blame] | 10 | |
Jiri Simsa | 764efb7 | 2014-12-25 20:57:03 -0800 | [diff] [blame] | 11 | "v.io/core/veyron2/naming" |
Robin Thellend | 8eb7752 | 2014-08-28 14:12:01 -0700 | [diff] [blame] | 12 | ) |
| 13 | |
| 14 | type ipcStats struct { |
Suharsh Sivakumar | 720b704 | 2014-12-22 17:33:23 -0800 | [diff] [blame] | 15 | mu sync.RWMutex |
| 16 | prefix string |
| 17 | methods map[string]*perMethodStats |
| 18 | blessingsCacheStats *blessingsCacheStats |
Robin Thellend | 8eb7752 | 2014-08-28 14:12:01 -0700 | [diff] [blame] | 19 | } |
| 20 | |
| 21 | func newIPCStats(prefix string) *ipcStats { |
Suharsh Sivakumar | 720b704 | 2014-12-22 17:33:23 -0800 | [diff] [blame] | 22 | return &ipcStats{ |
| 23 | prefix: prefix, |
| 24 | methods: make(map[string]*perMethodStats), |
| 25 | blessingsCacheStats: newBlessingsCacheStats(prefix), |
| 26 | } |
Robin Thellend | 8eb7752 | 2014-08-28 14:12:01 -0700 | [diff] [blame] | 27 | } |
| 28 | |
| 29 | type perMethodStats struct { |
| 30 | latency *histogram.Histogram |
| 31 | } |
| 32 | |
Robin Thellend | df42823 | 2014-10-06 12:50:44 -0700 | [diff] [blame] | 33 | func (s *ipcStats) stop() { |
| 34 | stats.Delete(s.prefix) |
| 35 | } |
| 36 | |
Robin Thellend | 8eb7752 | 2014-08-28 14:12:01 -0700 | [diff] [blame] | 37 | func (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 Sivakumar | 720b704 | 2014-12-22 17:33:23 -0800 | [diff] [blame] | 50 | func (s *ipcStats) recordBlessingCache(hit bool) { |
| 51 | s.blessingsCacheStats.incr(hit) |
| 52 | } |
| 53 | |
Robin Thellend | 8eb7752 | 2014-08-28 14:12:01 -0700 | [diff] [blame] | 54 | // newPerMethodStats creates a new perMethodStats object if one doesn't exist |
| 55 | // already. It returns the newly created object, or the already existing one. |
| 56 | func (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 Caprita | e737631 | 2014-11-10 13:13:17 -0800 | [diff] [blame] | 61 | name := naming.Join(s.prefix, "methods", method, "latency-ms") |
Robin Thellend | 8eb7752 | 2014-08-28 14:12:01 -0700 | [diff] [blame] | 62 | 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 Sivakumar | 720b704 | 2014-12-22 17:33:23 -0800 | [diff] [blame] | 74 | |
| 75 | // blessingsCacheStats keeps blessing cache hits and total calls received to determine |
| 76 | // how often the blessingCache is being used. |
| 77 | type blessingsCacheStats struct { |
| 78 | callsReceived, cacheHits *counter.Counter |
| 79 | } |
| 80 | |
| 81 | func 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. |
| 90 | func (s *blessingsCacheStats) incr(hit bool) { |
| 91 | s.callsReceived.Incr(1) |
| 92 | if hit { |
| 93 | s.cacheHits.Incr(1) |
| 94 | } |
| 95 | } |