forked from minotar/imgd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstatus.go
124 lines (105 loc) · 2.91 KB
/
status.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
123
124
package main
import (
"encoding/json"
"runtime"
"time"
)
// The different MessageTypes for statusCollectorMessage
const (
StatusTypeCacheHit = iota
StatusTypeCacheMiss
StatusTypeRequestServed
)
type statusCollectorMessage struct {
// The type of message this is.
MessageType uint
// If MessageType==StatusTypeRequestServed, then the type of request that was served.
RequestType string
}
type StatusCollector struct {
info struct {
// Number of bytes allocated to the process.
Memory uint64
// Time in seconds the process has been running for
Uptime int64
// Number of times a request type has been served.
Served map[string]uint
// Number of times skins have been served from the cache.
CacheHits uint
// Number of times skins have failed to be served from the cache.
CacheMisses uint
// Size of cached skins
Cached uint64
}
// Unix timestamp the process was booted at.
StartedAt int64
// Channel for feeding in input data.
inputData chan statusCollectorMessage
}
func MakeStatsCollector() *StatusCollector {
collector := &StatusCollector{}
collector.StartedAt = time.Now().Unix()
collector.info.Served = map[string]uint{}
collector.inputData = make(chan statusCollectorMessage, 5)
// Run a function every five seconds to collect time-based info.
go func() {
ticker := time.NewTicker(time.Second * 5)
for {
select {
case <-ticker.C:
collector.Collect()
case msg := <-collector.inputData:
collector.handleMessage(msg)
}
}
}()
return collector
}
// Message handler function, called inside goroutine.
func (s *StatusCollector) handleMessage(msg statusCollectorMessage) {
switch msg.MessageType {
case StatusTypeCacheHit:
s.info.CacheHits += 1
case StatusTypeCacheMiss:
s.info.CacheMisses += 1
case StatusTypeRequestServed:
req := msg.RequestType
if _, exists := s.info.Served[req]; exists {
s.info.Served[req] += 1
} else {
s.info.Served[req] = 1
}
}
}
// Encodes the info struct to a JSON string byte slice
func (s *StatusCollector) ToJSON() []byte {
results, _ := json.Marshal(s.info)
return results
}
// "cron" function that updates current information
func (s *StatusCollector) Collect() {
memstats := &runtime.MemStats{}
runtime.ReadMemStats(memstats)
s.info.Memory = memstats.Alloc
s.info.Uptime = time.Now().Unix() - s.StartedAt
s.info.Cached = cache.memory()
}
// Increments the request counter for the specific type of request.
func (s *StatusCollector) Served(req string) {
s.inputData <- statusCollectorMessage{
MessageType: StatusTypeRequestServed,
RequestType: req,
}
}
// Should be called every time we serve a cached skin.
func (s *StatusCollector) HitCache() {
s.inputData <- statusCollectorMessage{
MessageType: StatusTypeCacheHit,
}
}
// Should be called every time we try and fail to serve a cached skin.
func (s *StatusCollector) MissCache() {
s.inputData <- statusCollectorMessage{
MessageType: StatusTypeCacheMiss,
}
}