Repository: vllm-project/aibrix
File: pkg/controller/podautoscaler/metrics/utils.go (Go)

Code before:
		metricsTotal += metric.Value
	}

	currentUsage = metricsTotal / int64(len(metrics))

	return float64(currentUsage) / float64(targetUsage), currentUsage
}

func GetPodContainerMetric(ctx context.Context, fetcher MetricFetcher, pod corev1.Pod, source autoscalingv1alpha1.MetricSource) (PodMetricsInfo, time.Time, error) {
	_, err := fetcher.FetchPodMetrics(ctx, pod, source)
	currentTimestamp := time.Now()
	if err != nil {
		return nil, currentTimestamp, err
	}

	// TODO(jiaxin.shan): convert this raw metric to PodMetrics
	return nil, currentTimestamp, nil
}

func GetMetricsFromPods(ctx context.Context, fetcher MetricFetcher, pods []corev1.Pod, source autoscalingv1alpha1.MetricSource) ([]float64, error) {
	metrics := make([]float64, 0, len(pods))
	for _, pod := range pods {
		// TODO: Let's optimize the performance for multi-metrics later.
		metric, err := fetcher.FetchPodMetrics(ctx, pod, source)
		if err != nil {
			klog.ErrorS(err, "Failed to get metrics from pod", "pod", klog.KObj(&pod))
			// If we fail to get metrics for a pod, we should continue to get metrics from other pods.
			continue
		}
		metrics = append(metrics, metric)
	}
	if len(metrics) == 0 && len(pods) > 0 {
		return nil, fmt.Errorf("failed to get metrics from any of the %d pods", len(pods))
	}
	return metrics, nil
}

func GetMetricFromSource(ctx context.Context, fetcher MetricFetcher, source autoscalingv1alpha1.MetricSource) (float64, error) {
	endpoint := source.Endpoint

	// If port specified, try override.
	if source.Port != "" {
		u := url.URL{Host: source.Endpoint}
		if u.Port() == "" {
			endpoint = fmt.Sprintf("%s:%s", u.Hostname(), source.Port)
		}
	}
	return fetcher.FetchMetric(ctx, source.ProtocolType, endpoint, source.Path, source.TargetMetric)
}


Review comment (suggestion):
There was error logging before, but if there is a persistant error then it floods the logs making them difficult to read.

I will suggest to either add metrics to track this or open to other alternative which does not floods the log.

Code after:
		metricsTotal += metric.Value
	}

	currentUsage = metricsTotal / int64(len(metrics))

	return float64(currentUsage) / float64(targetUsage), currentUsage
}

func GetPodContainerMetric(ctx context.Context, fetcher MetricFetcher, pod corev1.Pod, source autoscalingv1alpha1.MetricSource) (PodMetricsInfo, time.Time, error) {
	_, err := fetcher.FetchPodMetrics(ctx, pod, source)
	currentTimestamp := time.Now()
	if err != nil {
		return nil, currentTimestamp, err
	}

	// TODO(jiaxin.shan): convert this raw metric to PodMetrics
	return nil, currentTimestamp, nil
}

func GetMetricsFromPods(ctx context.Context, fetcher MetricFetcher, pods []corev1.Pod, source autoscalingv1alpha1.MetricSource) ([]float64, error) {
	metrics := make([]float64, 0, len(pods))
	var failedPods []string
	var lastErrorMessage string
	for _, pod := range pods {
		// TODO: Let's optimize the performance for multi-metrics later.
		metric, err := fetcher.FetchPodMetrics(ctx, pod, source)
		if err != nil {
			lastErrorMessage = err.Error()
			failedPods = append(failedPods, fmt.Sprintf("%s/%s", pod.Namespace, pod.Name))
			continue
		}
		metrics = append(metrics, metric)
	}
	// If we fail to get metrics from some pods, we should log a warning message.
	if len(metrics) < len(pods) {
		klog.Warningf("failed to get metrics from some pods: got %d/%d metrics. Failed pods: %v, with last error: %v", len(metrics), len(pods), failedPods, lastErrorMessage)
	}
	// If we fail to get metrics from all pods, we should return an error.
	if len(metrics) == 0 && len(pods) > 0 {
		return nil, fmt.Errorf("failed to get metrics from any of the %d pods", len(pods))
	}
	return metrics, nil
}

func GetMetricFromSource(ctx context.Context, fetcher MetricFetcher, source autoscalingv1alpha1.MetricSource) (float64, error) {
	endpoint := source.Endpoint

	// If port specified, try override.
	if source.Port != "" {
		u := url.URL{Host: source.Endpoint}
		if u.Port() == "" {