veyron/runtimes/google/ipc: Adding per-method stats
This change adds two per-method stats to server calls: the number of
calls, and the latency distribution.
It is intended as a proof of concept.
Change-Id: Id0e9abb8b744c74b71a4db88941ba234114cff56
diff --git a/runtimes/google/ipc/stats.go b/runtimes/google/ipc/stats.go
new file mode 100644
index 0000000..1b8344d
--- /dev/null
+++ b/runtimes/google/ipc/stats.go
@@ -0,0 +1,59 @@
+package ipc
+
+import (
+ "sync"
+ "time"
+
+ "veyron/lib/stats"
+ "veyron/lib/stats/histogram"
+
+ "veyron2/naming"
+)
+
+type ipcStats struct {
+ mu sync.RWMutex
+ prefix string
+ methods map[string]*perMethodStats
+}
+
+func newIPCStats(prefix string) *ipcStats {
+ return &ipcStats{prefix: prefix, methods: make(map[string]*perMethodStats)}
+}
+
+type perMethodStats struct {
+ latency *histogram.Histogram
+}
+
+func (s *ipcStats) record(method string, latency time.Duration) {
+ // Try first with a read lock. This will succeed in the most common
+ // case. If it fails, try again with a write lock and create the stats
+ // objects if they are still not there.
+ s.mu.RLock()
+ m, ok := s.methods[method]
+ s.mu.RUnlock()
+ if !ok {
+ m = s.newPerMethodStats(method)
+ }
+ m.latency.Add(int64(latency / time.Millisecond))
+}
+
+// newPerMethodStats creates a new perMethodStats object if one doesn't exist
+// already. It returns the newly created object, or the already existing one.
+func (s *ipcStats) newPerMethodStats(method string) *perMethodStats {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ m, ok := s.methods[method]
+ if !ok {
+ name := naming.Join(s.prefix, method, "latency-ms")
+ s.methods[method] = &perMethodStats{
+ latency: stats.NewHistogram(name, histogram.Options{
+ NumBuckets: 25,
+ GrowthFactor: 1,
+ SmallestBucketSize: 1,
+ MinValue: 0,
+ }),
+ }
+ m = s.methods[method]
+ }
+ return m
+}