-
Notifications
You must be signed in to change notification settings - Fork 0
/
cache.go
136 lines (117 loc) · 3.12 KB
/
cache.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
125
126
127
128
129
130
131
132
133
134
135
136
package goddd
import (
"fmt"
"io/ioutil"
"os"
"strings"
"github.com/hyperpilotio/node-agent/pkg/snap"
"github.com/mailru/easyjson"
dto "github.com/prometheus/client_model/go"
)
var (
cachePath = "/tmp/snap-plugin-collector-goddd-cache.json"
)
func readCache() (*CacheType, error) {
file, err := ioutil.ReadFile(cachePath)
if err != nil {
return nil, fmt.Errorf("Unable to read file %s msg %s", cachePath, err.Error())
}
var cache CacheType
err = easyjson.Unmarshal(file, &cache)
if err != nil {
return nil, fmt.Errorf("Unable to parse json from file %s msg %s", cachePath, err.Error())
}
if cache.CounterType == nil {
return NewCache(), nil
}
return &cache, nil
}
func updateCache(cache *CacheType) error {
buf, err := easyjson.Marshal(cache)
if err != nil {
return fmt.Errorf("Unable to marshal cache %s", err.Error())
}
err = ioutil.WriteFile(cachePath, buf, 0644)
if err != nil {
return fmt.Errorf("Unable to write cache %s", err.Error())
}
return err
}
// NewCache return an object of CacheType
func NewCache() *CacheType {
return &CacheType{
CounterType: make(map[string]CounterCache),
}
}
func initCache() error {
if _, err := os.Stat(cachePath); os.IsNotExist(err) {
cache := NewCache()
buf, err := easyjson.Marshal(cache)
if err != nil {
return fmt.Errorf("Unable to parse json %s", err.Error())
}
err = ioutil.WriteFile(cachePath, buf, 0644)
if err != nil {
return fmt.Errorf("Unable to write json file %s", err.Error())
}
}
return nil
}
type metricWithType struct {
snap.Metric
Type dto.MetricType
}
func eliminateType(mts []metricWithType) []snap.Metric {
var metrics []snap.Metric
for _, m := range mts {
temp := snap.Metric{
Namespace: m.Namespace,
Data: m.Data,
Config: m.Config,
Description: m.Description,
Timestamp: m.Timestamp,
Version: m.Version,
Unit: m.Unit,
Tags: m.Tags,
}
metrics = append(metrics, temp)
}
return metrics
}
func (c *GodddCollector) _cache(mts []metricWithType) ([]snap.Metric, error) {
var err error
c.cache, err = readCache()
if err != nil {
return eliminateType(mts), fmt.Errorf("Unable to resume cache %s", err)
}
for idx, metric := range mts {
switch metric.Type {
case dto.MetricType_COUNTER:
keyForCache, exist := generateCacheKey(metric.Namespace, metric.Tags)
if !exist {
break
}
if cache, ok := c.cache.CounterType[keyForCache]; ok {
c.cache.CounterType[keyForCache] = CounterCache{Pre: metric.Data.(float64)}
metric.Data = metric.Data.(float64) - cache.Pre
mts[idx] = metric
} else {
// add cache of this counter
c.cache.CounterType[keyForCache] = CounterCache{Pre: metric.Data.(float64)}
metric.Data = float64(0)
mts[idx] = metric
}
}
}
err = updateCache(c.cache)
if err != nil {
return eliminateType(mts), fmt.Errorf("Failed to call updateCache %s", err.Error())
}
return eliminateType(mts), nil
}
func generateCacheKey(ns snap.Namespace, tags map[string]string) (string, bool) {
if val, ok := tags["method"]; ok {
return fmt.Sprintf("%s_method=%s", strings.Join(ns.Strings(), "/"), val), true
}
return "", false
}