123 lines
2.9 KiB
Go
123 lines
2.9 KiB
Go
// Licensed to Elasticsearch B.V. under one or more contributor
|
|
// license agreements. See the NOTICE file distributed with
|
|
// this work for additional information regarding copyright
|
|
// ownership. Elasticsearch B.V. licenses this file to you under
|
|
// the Apache License, Version 2.0 (the "License"); you may
|
|
// not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing,
|
|
// software distributed under the License is distributed on an
|
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations
|
|
// under the License.
|
|
|
|
package util
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// PerfMetrics stores known metrics from Kubernetes nodes and containers
|
|
var PerfMetrics = NewPerfMetricsCache()
|
|
|
|
const defaultTimeout = 120 * time.Second
|
|
|
|
var now = time.Now
|
|
var sleep = time.Sleep
|
|
|
|
// NewPerfMetricsCache initializes and returns a new PerfMetricsCache
|
|
func NewPerfMetricsCache() *PerfMetricsCache {
|
|
return &PerfMetricsCache{
|
|
NodeMemAllocatable: newValueMap(defaultTimeout),
|
|
NodeCoresAllocatable: newValueMap(defaultTimeout),
|
|
|
|
ContainerMemLimit: newValueMap(defaultTimeout),
|
|
ContainerCoresLimit: newValueMap(defaultTimeout),
|
|
}
|
|
}
|
|
|
|
// PerfMetricsCache stores known metrics from Kubernetes nodes and containers
|
|
type PerfMetricsCache struct {
|
|
mutex sync.RWMutex
|
|
NodeMemAllocatable *valueMap
|
|
NodeCoresAllocatable *valueMap
|
|
|
|
ContainerMemLimit *valueMap
|
|
ContainerCoresLimit *valueMap
|
|
}
|
|
|
|
func newValueMap(timeout time.Duration) *valueMap {
|
|
return &valueMap{
|
|
values: map[string]value{},
|
|
timeout: timeout,
|
|
}
|
|
}
|
|
|
|
type valueMap struct {
|
|
sync.RWMutex
|
|
running bool
|
|
timeout time.Duration
|
|
values map[string]value
|
|
}
|
|
|
|
type value struct {
|
|
value float64
|
|
expires int64
|
|
}
|
|
|
|
// ContainerUID creates an unique ID for from namespace, pod name and container name
|
|
func ContainerUID(namespace, pod, container string) string {
|
|
return namespace + "-" + pod + "-" + container
|
|
}
|
|
|
|
// Get value
|
|
func (m *valueMap) Get(name string) float64 {
|
|
m.RLock()
|
|
defer m.RUnlock()
|
|
return m.values[name].value
|
|
}
|
|
|
|
// Get value
|
|
func (m *valueMap) GetWithDefault(name string, def float64) float64 {
|
|
m.RLock()
|
|
defer m.RUnlock()
|
|
val, ok := m.values[name]
|
|
if ok {
|
|
return val.value
|
|
}
|
|
return def
|
|
}
|
|
|
|
// Set value
|
|
func (m *valueMap) Set(name string, val float64) {
|
|
m.Lock()
|
|
defer m.Unlock()
|
|
m.ensureCleanupWorker()
|
|
m.values[name] = value{val, now().Add(m.timeout).Unix()}
|
|
}
|
|
|
|
func (m *valueMap) ensureCleanupWorker() {
|
|
if !m.running {
|
|
// Run worker to cleanup expired entries
|
|
m.running = true
|
|
go func() {
|
|
for {
|
|
sleep(m.timeout)
|
|
m.Lock()
|
|
now := now().Unix()
|
|
for name, val := range m.values {
|
|
if now > val.expires {
|
|
delete(m.values, name)
|
|
}
|
|
}
|
|
m.Unlock()
|
|
}
|
|
}()
|
|
}
|
|
}
|