-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
client.go
121 lines (105 loc) · 2.88 KB
/
client.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
package metric
import (
"configcenter/src/common"
"configcenter/src/common/types"
"encoding/json"
"fmt"
"net/http"
"time"
"configcenter/src/common/blog"
)
var metricController *MetricController
func newMetricController(conf Config, healthFunc HealthFunc, collectors ...*Collector) []Action {
metricController = new(MetricController)
meta := MetaData{
Module: conf.ModuleName,
ServerAddress: conf.ServerAddress,
Labels: conf.Labels,
}
// set default golang metric.
collectors = append(collectors, newGoMetricCollector())
metricController.MetaData = &meta
metricController.Collectors = make(map[CollectorName]CollectInter)
for _, c := range collectors {
metricController.Collectors[c.Name] = c.Collector
}
metricHandler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "application/json")
metric, err := metricController.PackMetrics()
if nil != err {
w.WriteHeader(http.StatusInternalServerError)
info := fmt.Sprintf("get metrics failed. err: %v", err)
w.Write([]byte(info))
return
}
w.Write(*metric)
})
healthHandler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "application/json")
h := healthFunc()
info := HealthInfo{
Module: conf.ModuleName,
Address: conf.ServerAddress,
HealthMeta: h,
AtTime: types.Now(),
}
rsp := HealthResponse{
Code: common.CCSuccess,
Data: info,
OK: h.IsHealthy,
Result: h.IsHealthy,
Message: h.Message,
}
js, err := json.Marshal(rsp)
if nil != err {
w.WriteHeader(http.StatusInternalServerError)
info := fmt.Sprintf("get health info failed. err: %v", err)
w.Write([]byte(info))
return
}
w.Write(js)
})
actions := []Action{
{Method: "GET", Path: "/metrics", HandlerFunc: metricHandler},
{Method: "GET", Path: "/healthz", HandlerFunc: healthHandler},
}
return actions
}
type MetricController struct {
MetaData *MetaData
Collectors map[CollectorName]CollectInter
}
func (mc *MetricController) PackMetrics() (*[]byte, error) {
mf := MetricFamily{
MetaData: mc.MetaData,
MetricBundle: make(map[CollectorName][]*Metric),
}
for name, collector := range mc.Collectors {
mf.MetricBundle[name] = make([]*Metric, 0)
done := make(chan struct{}, 0)
go func(c CollectInter) {
for _, mc := range c.Collect() {
metric, err := newMetric(mc)
if nil != err {
blog.Errorf("new metric failed. err: %v", err)
continue
}
mf.MetricBundle[name] = append(mf.MetricBundle[name], metric)
}
done <- struct{}{}
}(collector)
select {
case <-time.After(time.Duration(10 * time.Second)):
blog.Errorf("get metric bundle: %s timeout, skip it.", name)
continue
case <-done:
close(done)
}
}
mf.ReportTimeMs = time.Now().Unix()
js, err := json.Marshal(mf)
if nil != err {
return nil, err
}
return &js, nil
}