github.com/kubewharf/katalyst-core@v0.5.3/pkg/util/metric/store_util.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  	"time"
    21  
    22  	v1 "k8s.io/api/core/v1"
    23  	"k8s.io/apimachinery/pkg/util/sets"
    24  	"k8s.io/klog/v2"
    25  
    26  	"github.com/kubewharf/katalyst-core/pkg/util/general"
    27  	"github.com/kubewharf/katalyst-core/pkg/util/machine"
    28  )
    29  
    30  type Aggregator string
    31  
    32  const (
    33  	AggregatorSum Aggregator = "sum"
    34  	AggregatorAvg Aggregator = "avg"
    35  )
    36  
    37  // ContainerMetricFilter is used to filter out unnecessary metrics if this function returns false
    38  type ContainerMetricFilter func(pod *v1.Pod, container *v1.Container) bool
    39  
    40  var DefaultContainerMetricFilter = func(_ *v1.Pod, _ *v1.Container) bool { return true }
    41  
    42  // AggregatePodNumaMetric handles numa-level metric for all pods
    43  func (c *MetricStore) AggregatePodNumaMetric(podList []*v1.Pod, numa, metricName string, agg Aggregator, filter ContainerMetricFilter) MetricData {
    44  	now := time.Now()
    45  	data := MetricData{Value: .0, Time: &now}
    46  
    47  	validPods := sets.NewString()
    48  	for _, pod := range podList {
    49  		if validPods.Has(string(pod.UID)) {
    50  			continue
    51  		}
    52  
    53  		for _, container := range pod.Spec.Containers {
    54  			if !filter(pod, &container) {
    55  				continue
    56  			}
    57  
    58  			metric, err := c.GetContainerNumaMetric(string(pod.UID), container.Name, numa, metricName)
    59  			if err != nil {
    60  				klog.Errorf("failed to get numa-metric pod %v, container %v, numa %v, metric %v, err: %v",
    61  					pod.Name, container.Name, numa, metricName, err)
    62  				continue
    63  			}
    64  			validPods.Insert(string(pod.UID))
    65  
    66  			data.Value += metric.Value
    67  			data.Time = general.MaxTimePtr(data.Time, metric.Time)
    68  		}
    69  	}
    70  
    71  	switch agg {
    72  	case AggregatorAvg:
    73  		if validPods.Len() > 0 {
    74  			data.Value /= float64(validPods.Len())
    75  		}
    76  	}
    77  	return data
    78  }
    79  
    80  // AggregatePodMetric handles metric for all pods
    81  func (c *MetricStore) AggregatePodMetric(podList []*v1.Pod, metricName string, agg Aggregator, filter ContainerMetricFilter) MetricData {
    82  	now := time.Now()
    83  	data := MetricData{Value: .0, Time: &now}
    84  
    85  	validPods := sets.NewString()
    86  	for _, pod := range podList {
    87  		if validPods.Has(string(pod.UID)) {
    88  			continue
    89  		}
    90  
    91  		for _, container := range pod.Spec.Containers {
    92  			if !filter(pod, &container) {
    93  				continue
    94  			}
    95  
    96  			metric, err := c.GetContainerMetric(string(pod.UID), container.Name, metricName)
    97  			if err != nil {
    98  				klog.Errorf("failed to get metric pod %v, container %v, metric %v, err: %v",
    99  					pod.Name, container.Name, metricName, err)
   100  				continue
   101  			}
   102  			validPods.Insert(string(pod.UID))
   103  
   104  			data.Value += metric.Value
   105  			data.Time = general.MaxTimePtr(data.Time, metric.Time)
   106  		}
   107  	}
   108  
   109  	switch agg {
   110  	case AggregatorAvg:
   111  		if validPods.Len() > 0 {
   112  			data.Value /= float64(validPods.Len())
   113  		}
   114  	}
   115  	return data
   116  }
   117  
   118  // AggregateCoreMetric handles metric for all cores
   119  func (c *MetricStore) AggregateCoreMetric(cpuset machine.CPUSet, metricName string, agg Aggregator) MetricData {
   120  	now := time.Now()
   121  	data := MetricData{Value: .0, Time: &now}
   122  
   123  	coreCount := 0.
   124  	for _, cpu := range cpuset.ToSliceInt() {
   125  		metric, err := c.GetCPUMetric(cpu, metricName)
   126  		if err != nil {
   127  			klog.V(4).Infof("failed to get metric cpu %v, metric %v, err: %v", cpu, metricName, err)
   128  			continue
   129  		}
   130  
   131  		coreCount++
   132  		data.Value += metric.Value
   133  		data.Time = general.MaxTimePtr(data.Time, metric.Time)
   134  	}
   135  
   136  	switch agg {
   137  	case AggregatorAvg:
   138  		if coreCount > 0 {
   139  			data.Value /= coreCount
   140  		}
   141  	}
   142  	return data
   143  }