blob: 640618ac15c599e9a95567018e0cf8c425cd4ea9 [file] [log] [blame]
Jiri Simsad7616c92015-03-24 23:44:30 -07001// Copyright 2015 The Vanadium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Matt Rosencrantz94502cf2015-03-18 09:43:44 -07005package rpc
Robin Thellend8eb77522014-08-28 14:12:01 -07006
7import (
8 "sync"
9 "time"
10
Jiri Simsaffceefa2015-02-28 11:03:34 -080011 "v.io/x/ref/lib/stats"
12 "v.io/x/ref/lib/stats/counter"
13 "v.io/x/ref/lib/stats/histogram"
Robin Thellend8eb77522014-08-28 14:12:01 -070014
Jiri Simsa6ac95222015-02-23 16:11:49 -080015 "v.io/v23/naming"
Robin Thellend8eb77522014-08-28 14:12:01 -070016)
17
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070018type rpcStats struct {
Suharsh Sivakumar720b7042014-12-22 17:33:23 -080019 mu sync.RWMutex
20 prefix string
21 methods map[string]*perMethodStats
22 blessingsCacheStats *blessingsCacheStats
Robin Thellend8eb77522014-08-28 14:12:01 -070023}
24
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070025func newRPCStats(prefix string) *rpcStats {
26 return &rpcStats{
Suharsh Sivakumar720b7042014-12-22 17:33:23 -080027 prefix: prefix,
28 methods: make(map[string]*perMethodStats),
29 blessingsCacheStats: newBlessingsCacheStats(prefix),
30 }
Robin Thellend8eb77522014-08-28 14:12:01 -070031}
32
33type perMethodStats struct {
34 latency *histogram.Histogram
35}
36
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070037func (s *rpcStats) stop() {
Robin Thellenddf428232014-10-06 12:50:44 -070038 stats.Delete(s.prefix)
39}
40
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070041func (s *rpcStats) record(method string, latency time.Duration) {
Robin Thellend8eb77522014-08-28 14:12:01 -070042 // Try first with a read lock. This will succeed in the most common
43 // case. If it fails, try again with a write lock and create the stats
44 // objects if they are still not there.
45 s.mu.RLock()
46 m, ok := s.methods[method]
47 s.mu.RUnlock()
48 if !ok {
49 m = s.newPerMethodStats(method)
50 }
51 m.latency.Add(int64(latency / time.Millisecond))
52}
53
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070054func (s *rpcStats) recordBlessingCache(hit bool) {
Suharsh Sivakumar720b7042014-12-22 17:33:23 -080055 s.blessingsCacheStats.incr(hit)
56}
57
Robin Thellend8eb77522014-08-28 14:12:01 -070058// newPerMethodStats creates a new perMethodStats object if one doesn't exist
59// already. It returns the newly created object, or the already existing one.
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070060func (s *rpcStats) newPerMethodStats(method string) *perMethodStats {
Robin Thellend8eb77522014-08-28 14:12:01 -070061 s.mu.Lock()
62 defer s.mu.Unlock()
63 m, ok := s.methods[method]
64 if !ok {
Bogdan Capritae7376312014-11-10 13:13:17 -080065 name := naming.Join(s.prefix, "methods", method, "latency-ms")
Robin Thellend8eb77522014-08-28 14:12:01 -070066 s.methods[method] = &perMethodStats{
67 latency: stats.NewHistogram(name, histogram.Options{
68 NumBuckets: 25,
69 GrowthFactor: 1,
70 SmallestBucketSize: 1,
71 MinValue: 0,
72 }),
73 }
74 m = s.methods[method]
75 }
76 return m
77}
Suharsh Sivakumar720b7042014-12-22 17:33:23 -080078
79// blessingsCacheStats keeps blessing cache hits and total calls received to determine
80// how often the blessingCache is being used.
81type blessingsCacheStats struct {
82 callsReceived, cacheHits *counter.Counter
83}
84
85func newBlessingsCacheStats(prefix string) *blessingsCacheStats {
86 cachePrefix := naming.Join(prefix, "security", "blessings", "cache")
87 return &blessingsCacheStats{
88 callsReceived: stats.NewCounter(naming.Join(cachePrefix, "attempts")),
89 cacheHits: stats.NewCounter(naming.Join(cachePrefix, "hits")),
90 }
91}
92
93// Incr increments the cache attempt counter and the cache hit counter if hit is true.
94func (s *blessingsCacheStats) incr(hit bool) {
95 s.callsReceived.Incr(1)
96 if hit {
97 s.cacheHits.Incr(1)
98 }
99}