-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathprometheus.go
103 lines (91 loc) · 2.36 KB
/
prometheus.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
// Package prometheus is a tRPC metric filter that provides prometheus exporter, Sink and Labels feature.
package prometheus
import (
"fmt"
"net/http"
"strconv"
"strings"
"sync"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/prometheus/common/model"
"trpc.group/trpc-go/trpc-go/log"
)
type metricsNameCache struct {
locker sync.RWMutex
cache map[string]string
}
func newMetricsNameCache() *metricsNameCache {
return &metricsNameCache{
locker: sync.RWMutex{},
cache: make(map[string]string),
}
}
var (
mNameCache = newMetricsNameCache()
)
// initMetrics initialize metrics and metrics handler
func initMetrics(ip string, port int32, path string) error {
metricsHTTPHandler := http.NewServeMux()
metricsHTTPHandler.Handle(path, promhttp.Handler())
addr := fmt.Sprintf("%s:%d", ip, port)
server := &http.Server{
Addr: addr,
Handler: metricsHTTPHandler,
}
log.Infof("prometheus exporter running at %s, metrics path %s", addr, path)
return server.ListenAndServe()
}
// convertSpecialChars convert utf8 chars to _
func convertSpecialChars(in string) (out string) {
if len(in) == 0 {
return
}
var outBuilder strings.Builder
for i, b := range []rune(in) {
if !isNormalChar(i, b) {
// use '_' instead of illegal character
if b < 127 {
outBuilder.WriteByte('_')
} else {
// convert utf8 to int string
outBuilder.WriteString(strconv.Itoa(int(b)))
outBuilder.WriteByte('_')
}
continue
}
outBuilder.WriteByte(byte(b))
}
return outBuilder.String()
}
// convertSpecialCharsWithCache convert utf8 chars to _ with cache
func convertSpecialCharsWithCache(in string) (out string) {
if len(in) == 0 {
return
}
// use cache
mNameCache.locker.RLock()
if v, ok := mNameCache.cache[in]; ok {
mNameCache.locker.RUnlock()
return v
}
mNameCache.locker.RUnlock()
// add cache
out = convertSpecialChars(in)
mNameCache.locker.Lock()
mNameCache.cache[in] = out
mNameCache.locker.Unlock()
return
}
func isNum(b rune) bool {
return b >= '0' && b <= '9'
}
func isChar(b rune) bool {
return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z')
}
func isNormalChar(i int, b rune) bool {
return isChar(b) || b == '_' || b == ':' || (isNum(b) && i > 0)
}
// checkMetricsValid metrics only support ascii letters and digists
func checkMetricsValid(name string) bool {
return model.IsValidMetricName(model.LabelValue(name))
}