github.com/kubewharf/katalyst-core@v0.5.3/pkg/util/metric/store.go (about) 1 /* 2 Copyright 2022 The Katalyst Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package metric 18 19 import ( 20 "errors" 21 "fmt" 22 "sync" 23 "time" 24 ) 25 26 // MetricData represents the standard response data for metric getter functions 27 type MetricData struct { 28 Value float64 29 30 // Time may have different meanings in different scenarios 31 // - for single metric: it represents the exact collecting time 32 // - for aggregated metric: it represents the newest time among all metric items 33 Time *time.Time 34 } 35 36 // MetricStore stores those metric data. Including: 37 // 1. raw data collected from agent.MetricsFetcher. 38 // 2. data calculated based on raw data. 39 type MetricStore struct { 40 mutex sync.RWMutex 41 42 nodeMetricMap map[string]MetricData // map[metricName]data 43 numaMetricMap map[int]map[string]MetricData // map[numaID]map[metricName]data 44 deviceMetricMap map[string]map[string]MetricData // map[deviceName]map[metricName]data 45 networkMetricMap map[string]map[string]MetricData // map[networkName]map[metricName]data 46 cpuMetricMap map[int]map[string]MetricData // map[cpuID]map[metricName]data 47 podContainerMetricMap map[string]map[string]map[string]MetricData // map[podUID]map[containerName]map[metricName]data 48 podContainerNumaMetricMap map[string]map[string]map[string]map[string]MetricData // map[podUID]map[containerName]map[numaNode]map[metricName]data 49 podVolumeMetricMap map[string]map[string]map[string]MetricData // map[podUID]map[volumeName]map[metricName]data 50 cgroupMetricMap map[string]map[string]MetricData // map[cgroupPath]map[metricName]value 51 cgroupNumaMetricMap map[string]map[int]map[string]MetricData // map[cgroupPath]map[numaNode]map[metricName]value 52 } 53 54 func NewMetricStore() *MetricStore { 55 return &MetricStore{ 56 nodeMetricMap: make(map[string]MetricData), 57 numaMetricMap: make(map[int]map[string]MetricData), 58 deviceMetricMap: make(map[string]map[string]MetricData), 59 networkMetricMap: make(map[string]map[string]MetricData), 60 cpuMetricMap: make(map[int]map[string]MetricData), 61 podContainerMetricMap: make(map[string]map[string]map[string]MetricData), 62 podContainerNumaMetricMap: make(map[string]map[string]map[string]map[string]MetricData), 63 podVolumeMetricMap: make(map[string]map[string]map[string]MetricData), 64 cgroupMetricMap: make(map[string]map[string]MetricData), 65 cgroupNumaMetricMap: make(map[string]map[int]map[string]MetricData), 66 } 67 } 68 69 func (c *MetricStore) SetNodeMetric(metricName string, data MetricData) { 70 c.mutex.Lock() 71 defer c.mutex.Unlock() 72 c.nodeMetricMap[metricName] = data 73 } 74 75 func (c *MetricStore) SetNumaMetric(numaID int, metricName string, data MetricData) { 76 c.mutex.Lock() 77 defer c.mutex.Unlock() 78 if _, ok := c.numaMetricMap[numaID]; !ok { 79 c.numaMetricMap[numaID] = make(map[string]MetricData) 80 } 81 c.numaMetricMap[numaID][metricName] = data 82 } 83 84 func (c *MetricStore) SetDeviceMetric(deviceName string, metricName string, data MetricData) { 85 c.mutex.Lock() 86 defer c.mutex.Unlock() 87 if _, ok := c.deviceMetricMap[deviceName]; !ok { 88 c.deviceMetricMap[deviceName] = make(map[string]MetricData) 89 } 90 c.deviceMetricMap[deviceName][metricName] = data 91 } 92 93 func (c *MetricStore) SetNetworkMetric(networkName string, metricName string, data MetricData) { 94 c.mutex.Lock() 95 defer c.mutex.Unlock() 96 if _, ok := c.networkMetricMap[networkName]; !ok { 97 c.networkMetricMap[networkName] = make(map[string]MetricData) 98 } 99 c.networkMetricMap[networkName][metricName] = data 100 } 101 102 func (c *MetricStore) SetCPUMetric(cpuID int, metricName string, data MetricData) { 103 c.mutex.Lock() 104 defer c.mutex.Unlock() 105 if _, ok := c.cpuMetricMap[cpuID]; !ok { 106 c.cpuMetricMap[cpuID] = make(map[string]MetricData) 107 } 108 c.cpuMetricMap[cpuID][metricName] = data 109 } 110 111 func (c *MetricStore) SetContainerMetric(podUID, containerName, metricName string, data MetricData) { 112 c.mutex.Lock() 113 defer c.mutex.Unlock() 114 if _, ok := c.podContainerMetricMap[podUID]; !ok { 115 c.podContainerMetricMap[podUID] = make(map[string]map[string]MetricData) 116 } 117 118 if _, ok := c.podContainerMetricMap[podUID][containerName]; !ok { 119 c.podContainerMetricMap[podUID][containerName] = make(map[string]MetricData) 120 } 121 c.podContainerMetricMap[podUID][containerName][metricName] = data 122 } 123 124 func (c *MetricStore) SetContainerNumaMetric(podUID, containerName, numaNode, metricName string, data MetricData) { 125 c.mutex.Lock() 126 defer c.mutex.Unlock() 127 128 if _, ok := c.podContainerNumaMetricMap[podUID]; !ok { 129 c.podContainerNumaMetricMap[podUID] = make(map[string]map[string]map[string]MetricData) 130 } 131 132 if _, ok := c.podContainerNumaMetricMap[podUID][containerName]; !ok { 133 c.podContainerNumaMetricMap[podUID][containerName] = make(map[string]map[string]MetricData) 134 } 135 136 if _, ok := c.podContainerNumaMetricMap[podUID][containerName][numaNode]; !ok { 137 c.podContainerNumaMetricMap[podUID][containerName][numaNode] = make(map[string]MetricData) 138 } 139 c.podContainerNumaMetricMap[podUID][containerName][numaNode][metricName] = data 140 } 141 142 func (c *MetricStore) SetPodVolumeMetric(podUID, volumeName, metricName string, data MetricData) { 143 c.mutex.Lock() 144 defer c.mutex.Unlock() 145 146 if _, ok := c.podVolumeMetricMap[podUID]; !ok { 147 c.podVolumeMetricMap[podUID] = make(map[string]map[string]MetricData) 148 } 149 150 if _, ok := c.podVolumeMetricMap[podUID][volumeName]; !ok { 151 c.podVolumeMetricMap[podUID][volumeName] = make(map[string]MetricData) 152 } 153 154 c.podVolumeMetricMap[podUID][volumeName][metricName] = data 155 } 156 157 func (c *MetricStore) GetNodeMetric(metricName string) (MetricData, error) { 158 c.mutex.RLock() 159 defer c.mutex.RUnlock() 160 if data, ok := c.nodeMetricMap[metricName]; ok { 161 return data, nil 162 } else { 163 return MetricData{}, errors.New(fmt.Sprintf("[MetricStore] load value failed, metric=%v", metricName)) 164 } 165 } 166 167 func (c *MetricStore) GetNumaMetric(numaID int, metricName string) (MetricData, error) { 168 c.mutex.RLock() 169 defer c.mutex.RUnlock() 170 if c.numaMetricMap[numaID] != nil { 171 if data, ok := c.numaMetricMap[numaID][metricName]; ok { 172 return data, nil 173 } else { 174 return MetricData{}, errors.New(fmt.Sprintf("[MetricStore] load value failed, metric=%v, numaID=%v", metricName, numaID)) 175 } 176 } 177 return MetricData{}, errors.New(fmt.Sprintf("[MetricStore] empty map, metric=%v, numaID=%v", metricName, numaID)) 178 } 179 180 func (c *MetricStore) GetDeviceMetric(deviceName string, metricName string) (MetricData, error) { 181 c.mutex.RLock() 182 defer c.mutex.RUnlock() 183 if c.deviceMetricMap[deviceName] != nil { 184 if data, ok := c.deviceMetricMap[deviceName][metricName]; ok { 185 return data, nil 186 } else { 187 return MetricData{}, errors.New(fmt.Sprintf("[MetricStore] load value failed, metric=%v, deviceName=%v", metricName, deviceName)) 188 } 189 } 190 return MetricData{}, errors.New(fmt.Sprintf("[MetricStore] empty map, metric=%v, deviceName=%v", metricName, deviceName)) 191 } 192 193 func (c *MetricStore) GetNetworkMetric(networkName string, metricName string) (MetricData, error) { 194 c.mutex.RLock() 195 defer c.mutex.RUnlock() 196 if c.networkMetricMap[networkName] != nil { 197 if data, ok := c.networkMetricMap[networkName][metricName]; ok { 198 return data, nil 199 } else { 200 return MetricData{}, errors.New(fmt.Sprintf("[MetricStore] load value failed, metric=%v, networkName=%v", metricName, networkName)) 201 } 202 } 203 return MetricData{}, errors.New(fmt.Sprintf("[MetricStore] empty map, metric=%v, networkName=%v", metricName, networkName)) 204 } 205 206 func (c *MetricStore) GetCPUMetric(coreID int, metricName string) (MetricData, error) { 207 c.mutex.RLock() 208 defer c.mutex.RUnlock() 209 if c.cpuMetricMap[coreID] != nil { 210 if data, ok := c.cpuMetricMap[coreID][metricName]; ok { 211 return data, nil 212 } else { 213 return MetricData{}, errors.New(fmt.Sprintf("[MetricStore] load value failed, metric=%v, coreID=%v", metricName, coreID)) 214 } 215 } 216 return MetricData{}, errors.New(fmt.Sprintf("[MetricStore] empty map, metric=%v, coreID=%v", metricName, coreID)) 217 } 218 219 func (c *MetricStore) GetContainerMetric(podUID, containerName, metricName string) (MetricData, error) { 220 c.mutex.RLock() 221 defer c.mutex.RUnlock() 222 if c.podContainerMetricMap[podUID] != nil { 223 if c.podContainerMetricMap[podUID][containerName] != nil { 224 if data, ok := c.podContainerMetricMap[podUID][containerName][metricName]; ok { 225 return data, nil 226 } else { 227 return MetricData{}, errors.New(fmt.Sprintf("[MetricStore] load value failed, metric=%v, podUID=%v, containerName=%v", metricName, podUID, containerName)) 228 } 229 } 230 } 231 return MetricData{}, errors.New(fmt.Sprintf("[MetricStore] empty map, metric=%v, podUID=%v, containerName=%v", metricName, podUID, containerName)) 232 } 233 234 func (c *MetricStore) GetContainerNumaMetric(podUID, containerName, numaNode, metricName string) (MetricData, error) { 235 c.mutex.RLock() 236 defer c.mutex.RUnlock() 237 if c.podContainerNumaMetricMap[podUID] != nil { 238 if c.podContainerNumaMetricMap[podUID][containerName] != nil { 239 if c.podContainerNumaMetricMap[podUID][containerName][numaNode] != nil { 240 if data, ok := c.podContainerNumaMetricMap[podUID][containerName][numaNode][metricName]; ok { 241 return data, nil 242 } else { 243 return MetricData{}, errors.New(fmt.Sprintf("[MetricStore] load value failed, metric=%v, podUID=%v, containerName=%v, numaNode=%v", metricName, podUID, containerName, numaNode)) 244 } 245 } 246 } 247 } 248 return MetricData{}, errors.New(fmt.Sprintf("[MetricStore] empty map, metric=%v, podUID=%v, containerName=%v, numaNode=%v", metricName, podUID, containerName, numaNode)) 249 } 250 251 func (c *MetricStore) GetPodVolumeMetric(podUID, volumeName, metricName string) (MetricData, error) { 252 c.mutex.RLock() 253 defer c.mutex.RUnlock() 254 255 if c.podVolumeMetricMap[podUID] != nil { 256 if c.podVolumeMetricMap[podUID][volumeName] != nil { 257 if data, ok := c.podVolumeMetricMap[podUID][volumeName][metricName]; ok { 258 return data, nil 259 } else { 260 return MetricData{}, errors.New(fmt.Sprintf("[MetricStore] load value failed, metric=%v, podUID=%v, volumeName=%v", metricName, podUID, volumeName)) 261 } 262 } 263 } 264 return MetricData{}, errors.New(fmt.Sprintf("[MetricStore] empty map, metric=%v, podUID=%v, volumeName=%v", metricName, podUID, volumeName)) 265 } 266 267 func (c *MetricStore) GCPodsMetric(livingPodUIDSet map[string]bool) { 268 c.mutex.Lock() 269 defer c.mutex.Unlock() 270 for podUID := range c.podContainerMetricMap { 271 if _, ok := livingPodUIDSet[podUID]; !ok { 272 delete(c.podContainerMetricMap, podUID) 273 delete(c.podContainerNumaMetricMap, podUID) 274 } 275 } 276 } 277 278 func (c *MetricStore) SetCgroupMetric(cgroupPath, metricName string, data MetricData) { 279 c.mutex.Lock() 280 defer c.mutex.Unlock() 281 metrics, ok := c.cgroupMetricMap[cgroupPath] 282 if !ok { 283 metrics = make(map[string]MetricData) 284 c.cgroupMetricMap[cgroupPath] = metrics 285 } 286 metrics[metricName] = data 287 } 288 289 func (c *MetricStore) GetCgroupMetric(cgroupPath, metricName string) (MetricData, error) { 290 c.mutex.RLock() 291 defer c.mutex.RUnlock() 292 293 metrics, ok := c.cgroupMetricMap[cgroupPath] 294 if !ok { 295 return MetricData{}, fmt.Errorf("[MetricStore] load value for %v failed", cgroupPath) 296 } 297 data, ok := metrics[metricName] 298 if !ok { 299 return MetricData{}, fmt.Errorf("[MetricStore] load value for %v failed", metricName) 300 } 301 return data, nil 302 } 303 304 func (c *MetricStore) SetCgroupNumaMetric(cgroupPath string, numaNode int, metricName string, data MetricData) { 305 c.mutex.Lock() 306 defer c.mutex.Unlock() 307 308 numaMetrics, ok := c.cgroupNumaMetricMap[cgroupPath] 309 if !ok { 310 numaMetrics = make(map[int]map[string]MetricData) 311 c.cgroupNumaMetricMap[cgroupPath] = numaMetrics 312 } 313 metrics, ok := numaMetrics[numaNode] 314 if !ok { 315 metrics = make(map[string]MetricData) 316 numaMetrics[numaNode] = metrics 317 } 318 metrics[metricName] = data 319 } 320 321 func (c *MetricStore) GetCgroupNumaMetric(cgroupPath string, numaNode int, metricName string) (MetricData, error) { 322 c.mutex.RLock() 323 defer c.mutex.RUnlock() 324 numaMetrics, ok := c.cgroupNumaMetricMap[cgroupPath] 325 if !ok { 326 return MetricData{}, fmt.Errorf("[MetricStore] load value for %v failed", cgroupPath) 327 } 328 metrics, ok := numaMetrics[numaNode] 329 if !ok { 330 return MetricData{}, fmt.Errorf("[MetricStore] load value for %v failed", numaNode) 331 } 332 metric, ok := metrics[metricName] 333 if !ok { 334 return MetricData{}, fmt.Errorf("[MetricStore] load value for %v failed", metricName) 335 } 336 return metric, nil 337 }