Tizen_4.0 base
[platform/upstream/docker-engine.git] / vendor / github.com / armon / go-metrics / metrics.go
1 package metrics
2
3 import (
4         "runtime"
5         "time"
6 )
7
8 func (m *Metrics) SetGauge(key []string, val float32) {
9         if m.HostName != "" && m.EnableHostname {
10                 key = insert(0, m.HostName, key)
11         }
12         if m.EnableTypePrefix {
13                 key = insert(0, "gauge", key)
14         }
15         if m.ServiceName != "" {
16                 key = insert(0, m.ServiceName, key)
17         }
18         m.sink.SetGauge(key, val)
19 }
20
21 func (m *Metrics) EmitKey(key []string, val float32) {
22         if m.EnableTypePrefix {
23                 key = insert(0, "kv", key)
24         }
25         if m.ServiceName != "" {
26                 key = insert(0, m.ServiceName, key)
27         }
28         m.sink.EmitKey(key, val)
29 }
30
31 func (m *Metrics) IncrCounter(key []string, val float32) {
32         if m.EnableTypePrefix {
33                 key = insert(0, "counter", key)
34         }
35         if m.ServiceName != "" {
36                 key = insert(0, m.ServiceName, key)
37         }
38         m.sink.IncrCounter(key, val)
39 }
40
41 func (m *Metrics) AddSample(key []string, val float32) {
42         if m.EnableTypePrefix {
43                 key = insert(0, "sample", key)
44         }
45         if m.ServiceName != "" {
46                 key = insert(0, m.ServiceName, key)
47         }
48         m.sink.AddSample(key, val)
49 }
50
51 func (m *Metrics) MeasureSince(key []string, start time.Time) {
52         if m.EnableTypePrefix {
53                 key = insert(0, "timer", key)
54         }
55         if m.ServiceName != "" {
56                 key = insert(0, m.ServiceName, key)
57         }
58         now := time.Now()
59         elapsed := now.Sub(start)
60         msec := float32(elapsed.Nanoseconds()) / float32(m.TimerGranularity)
61         m.sink.AddSample(key, msec)
62 }
63
64 // Periodically collects runtime stats to publish
65 func (m *Metrics) collectStats() {
66         for {
67                 time.Sleep(m.ProfileInterval)
68                 m.emitRuntimeStats()
69         }
70 }
71
72 // Emits various runtime statsitics
73 func (m *Metrics) emitRuntimeStats() {
74         // Export number of Goroutines
75         numRoutines := runtime.NumGoroutine()
76         m.SetGauge([]string{"runtime", "num_goroutines"}, float32(numRoutines))
77
78         // Export memory stats
79         var stats runtime.MemStats
80         runtime.ReadMemStats(&stats)
81         m.SetGauge([]string{"runtime", "alloc_bytes"}, float32(stats.Alloc))
82         m.SetGauge([]string{"runtime", "sys_bytes"}, float32(stats.Sys))
83         m.SetGauge([]string{"runtime", "malloc_count"}, float32(stats.Mallocs))
84         m.SetGauge([]string{"runtime", "free_count"}, float32(stats.Frees))
85         m.SetGauge([]string{"runtime", "heap_objects"}, float32(stats.HeapObjects))
86         m.SetGauge([]string{"runtime", "total_gc_pause_ns"}, float32(stats.PauseTotalNs))
87         m.SetGauge([]string{"runtime", "total_gc_runs"}, float32(stats.NumGC))
88
89         // Export info about the last few GC runs
90         num := stats.NumGC
91
92         // Handle wrap around
93         if num < m.lastNumGC {
94                 m.lastNumGC = 0
95         }
96
97         // Ensure we don't scan more than 256
98         if num-m.lastNumGC >= 256 {
99                 m.lastNumGC = num - 255
100         }
101
102         for i := m.lastNumGC; i < num; i++ {
103                 pause := stats.PauseNs[i%256]
104                 m.AddSample([]string{"runtime", "gc_pause_ns"}, float32(pause))
105         }
106         m.lastNumGC = num
107 }
108
109 // Inserts a string value at an index into the slice
110 func insert(i int, v string, s []string) []string {
111         s = append(s, "")
112         copy(s[i+1:], s[i:])
113         s[i] = v
114         return s
115 }