forked from gree/futurama
-
Notifications
You must be signed in to change notification settings - Fork 0
/
stat.go
122 lines (107 loc) · 2.3 KB
/
stat.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package futurama
import (
"github.com/golang/glog"
"reflect"
"runtime"
"runtime/debug"
"sort"
"sync"
"time"
)
type Stat struct {
m sync.RWMutex
knownStats map[string]StatInterface
quitChan chan chan bool
collectIntervalSec int
}
func NewStat(collectIntervalSec int) *Stat {
stat := &Stat{
knownStats: make(map[string]StatInterface),
collectIntervalSec: collectIntervalSec,
quitChan: make(chan chan bool, 1),
}
stat.Add(&sys{time.Now()})
return stat
}
func (self *Stat) Add(s StatInterface) {
name := reflect.TypeOf(s).Elem().String()
glog.Infoln("Add stat", name)
self.m.Lock()
self.knownStats[name] = s
self.m.Unlock()
}
func (self *Stat) GetStat(reset bool) map[string]interface{} {
self.m.RLock()
defer self.m.RUnlock()
res := make(map[string]interface{})
for k, v := range self.knownStats {
stat := v.GetStat(reset)
for k2, v2 := range stat {
res[k+"."+k2] = v2
}
}
return res
}
func (self *Stat) log() {
s := self.GetStat(true)
mk := make([]string, len(s))
i := 0
for k, _ := range s {
mk[i] = k
i++
}
sort.Strings(mk)
for _, k := range mk {
glog.Infof("%s: %v", k, s[k])
}
}
func (self *Stat) Start() {
if self.collectIntervalSec == 0 {
return
}
go func() {
ticker := time.NewTicker(time.Duration(self.collectIntervalSec) * time.Second)
defer func() {
glog.Infoln("Stat stop")
if r := recover(); r != nil {
glog.Errorf("Recovered in GetStat, msg: %s stack: %s", r, debug.Stack())
}
}()
for {
select {
case c := <-self.quitChan:
close(c)
return
case <-ticker.C:
self.log()
}
}
}()
glog.Infof("Stat start get stats every %ds", self.collectIntervalSec)
}
func (self *Stat) Stop() {
glog.Infoln("Stop stat")
if self.collectIntervalSec != 0 {
c := make(chan bool)
self.quitChan <- c
<-c
}
self.log()
}
type sys struct {
startTime time.Time
}
func (self *sys) GetStat(reset bool) map[string]interface{} {
stat := make(map[string]interface{})
stat["StartTime"] = self.startTime
stat["UpTime"] = time.Since(self.startTime).String()
stat["CollectedTime"] = time.Now()
stat["NumGoroutine"] = runtime.NumGoroutine()
var m runtime.MemStats
runtime.ReadMemStats(&m)
stat["MemAlloc"] = m.Alloc
stat["HeapAlloc"] = m.HeapAlloc
stat["NextGC"] = m.NextGC
stat["NumGC"] = m.NumGC
return stat
}