-
Notifications
You must be signed in to change notification settings - Fork 824
/
metricsconfig.go
158 lines (144 loc) · 4.3 KB
/
metricsconfig.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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package config
import (
"slices"
"sync"
"time"
corev1 "k8s.io/api/core/v1"
)
// MetricsConfig stores the config for metrics
type MetricsConfiguration interface {
// GetExcludeNamespaces returns the namespaces to ignore for metrics exposure
GetExcludeNamespaces() []string
// GetIncludeNamespaces returns the namespaces to specifically consider for metrics exposure
GetIncludeNamespaces() []string
// GetMetricsRefreshInterval returns the refresh interval for the metrics
GetMetricsRefreshInterval() time.Duration
// CheckNamespace returns `true` if the namespace has to be considered
CheckNamespace(string) bool
// Load loads configuration from a configmap
Load(*corev1.ConfigMap)
// OnChanged adds a callback to be invoked when the configuration is reloaded
OnChanged(func())
}
// metricsConfig stores the config for metrics
type metricsConfig struct {
namespaces namespacesConfig
metricsRefreshInterval time.Duration
mux sync.RWMutex
callbacks []func()
}
// NewDefaultMetricsConfiguration ...
func NewDefaultMetricsConfiguration() *metricsConfig {
return &metricsConfig{
metricsRefreshInterval: 0,
namespaces: namespacesConfig{
IncludeNamespaces: []string{},
ExcludeNamespaces: []string{},
},
}
}
func (cd *metricsConfig) OnChanged(callback func()) {
cd.mux.Lock()
defer cd.mux.Unlock()
cd.callbacks = append(cd.callbacks, callback)
}
// GetExcludeNamespaces returns the namespaces to ignore for metrics exposure
func (mcd *metricsConfig) GetExcludeNamespaces() []string {
mcd.mux.RLock()
defer mcd.mux.RUnlock()
return mcd.namespaces.ExcludeNamespaces
}
// GetIncludeNamespaces returns the namespaces to specifically consider for metrics exposure
func (mcd *metricsConfig) GetIncludeNamespaces() []string {
mcd.mux.RLock()
defer mcd.mux.RUnlock()
return mcd.namespaces.IncludeNamespaces
}
// GetMetricsRefreshInterval returns the refresh interval for the metrics
func (mcd *metricsConfig) GetMetricsRefreshInterval() time.Duration {
mcd.mux.RLock()
defer mcd.mux.RUnlock()
return mcd.metricsRefreshInterval
}
// CheckNamespace returns `true` if the namespace has to be considered
func (mcd *metricsConfig) CheckNamespace(namespace string) bool {
mcd.mux.RLock()
defer mcd.mux.RUnlock()
// TODO(eddycharly): check we actually need `"-"`
if namespace == "" || namespace == "-" {
return true
}
if slices.Contains(mcd.namespaces.ExcludeNamespaces, namespace) {
return false
}
if len(mcd.namespaces.IncludeNamespaces) == 0 {
return true
}
return slices.Contains(mcd.namespaces.IncludeNamespaces, namespace)
}
func (mcd *metricsConfig) Load(cm *corev1.ConfigMap) {
if cm != nil {
mcd.load(cm)
} else {
mcd.unload()
}
}
func (cd *metricsConfig) load(cm *corev1.ConfigMap) {
logger := logger.WithValues("name", cm.Name, "namespace", cm.Namespace)
cd.mux.Lock()
defer cd.mux.Unlock()
defer cd.notify()
data := cm.Data
if data == nil {
data = map[string]string{}
}
// reset
cd.metricsRefreshInterval = 0
cd.namespaces = namespacesConfig{
IncludeNamespaces: []string{},
ExcludeNamespaces: []string{},
}
// load metricsRefreshInterval
metricsRefreshInterval, ok := data["metricsRefreshInterval"]
if !ok {
logger.Info("metricsRefreshInterval not set")
} else {
logger := logger.WithValues("metricsRefreshInterval", metricsRefreshInterval)
metricsRefreshInterval, err := time.ParseDuration(metricsRefreshInterval)
if err != nil {
logger.Error(err, "failed to parse metricsRefreshInterval")
} else {
cd.metricsRefreshInterval = metricsRefreshInterval
logger.Info("metricsRefreshInterval configured")
}
}
// load namespaces
namespaces, ok := data["namespaces"]
if !ok {
logger.Info("namespaces not set")
} else {
logger := logger.WithValues("namespaces", namespaces)
namespaces, err := parseIncludeExcludeNamespacesFromNamespacesConfig(namespaces)
if err != nil {
logger.Error(err, "failed to parse namespaces")
} else {
cd.namespaces = namespaces
logger.Info("namespaces configured")
}
}
}
func (mcd *metricsConfig) unload() {
mcd.mux.Lock()
defer mcd.mux.Unlock()
defer mcd.notify()
mcd.metricsRefreshInterval = 0
mcd.namespaces = namespacesConfig{
IncludeNamespaces: []string{},
ExcludeNamespaces: []string{},
}
}
func (mcd *metricsConfig) notify() {
for _, callback := range mcd.callbacks {
callback()
}
}