Skip to content

Commit 1b9b74b

Browse files
committed
Final touch changes
1 parent c7ef4d6 commit 1b9b74b

File tree

2 files changed

+71
-74
lines changed

2 files changed

+71
-74
lines changed

pkg/autoscaler/metricsclient/k8s.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,18 +67,6 @@ func NewCustomMetricsClient(
6767
}, nil
6868
}
6969

70-
// getMetricNames extracts unique metric names from resources
71-
func (cmw *K8sCustomMetricsClient) getMetricNames(resources []scalertypes.Resource) []string {
72-
var metricNames []string
73-
for _, resource := range resources {
74-
for _, scaleResource := range resource.ScaleResources {
75-
metricNames = append(metricNames, scaleResource.GetKubernetesMetricName())
76-
}
77-
}
78-
metricNames = common.UniquifyStringSlice(metricNames)
79-
return metricNames
80-
}
81-
8270
func (cmw *K8sCustomMetricsClient) GetResourceMetrics(resources []scalertypes.Resource) (map[string]map[string]int, error) {
8371
metricNames := cmw.getMetricNames(resources)
8472
resourcesMetricsMap := make(map[string]map[string]int)
@@ -121,3 +109,15 @@ func (cmw *K8sCustomMetricsClient) GetResourceMetrics(resources []scalertypes.Re
121109
}
122110
return resourcesMetricsMap, nil
123111
}
112+
113+
// getMetricNames extracts unique metric names from resources
114+
func (cmw *K8sCustomMetricsClient) getMetricNames(resources []scalertypes.Resource) []string {
115+
var metricNames []string
116+
for _, resource := range resources {
117+
for _, scaleResource := range resource.ScaleResources {
118+
metricNames = append(metricNames, scaleResource.GetKubernetesMetricName())
119+
}
120+
}
121+
metricNames = common.UniquifyStringSlice(metricNames)
122+
return metricNames
123+
}

pkg/autoscaler/metricsclient/prometheus.go

Lines changed: 59 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -91,60 +91,6 @@ func NewPrometheusClient(parentLogger logger.Logger, prometheusURL, namespace st
9191
}, nil
9292
}
9393

94-
// renderQuery renders the Prometheus query template
95-
func (pc *PrometheusClient) renderQuery(queryTemplate *template.Template, windowSize, resourceNameRegex string) (string, error) {
96-
templateData := make(map[string]string)
97-
templateData["Namespace"] = pc.namespace
98-
templateData["WindowSize"] = windowSize
99-
templateData["Resources"] = resourceNameRegex
100-
101-
var queryBuffer bytes.Buffer
102-
if err := queryTemplate.Execute(&queryBuffer, templateData); err != nil {
103-
return "", fmt.Errorf("error executing template: %w", err)
104-
}
105-
106-
return queryBuffer.String(), nil
107-
}
108-
109-
// extractWindowSizesForMetric extracts unique window sizes from resources' ScaleResources for a specific metric name.
110-
func (pc *PrometheusClient) extractWindowSizesForMetric(resources []scalertypes.Resource, metricName string) map[string]bool {
111-
windowSizes := make(map[string]bool)
112-
for _, resource := range resources {
113-
for _, scaleResource := range resource.ScaleResources {
114-
if scaleResource.MetricName == metricName {
115-
windowSizeStr := scalertypes.ShortDurationString(scaleResource.WindowSize)
116-
windowSizes[windowSizeStr] = true
117-
}
118-
}
119-
}
120-
return windowSizes
121-
}
122-
123-
// buildResourceNameRegex creates a pipe-separated regex pattern from resource names for Prometheus query filtering (e.g., "func1|func2|func3")
124-
func (pc *PrometheusClient) buildResourceNameRegex(resources []scalertypes.Resource) string {
125-
resourceNames := make([]string, len(resources))
126-
for i, resource := range resources {
127-
resourceNames[i] = resource.Name
128-
}
129-
return strings.Join(resourceNames, "|")
130-
}
131-
132-
// resolveFullMetricName finds the matching ScaleResource for a given metric name and window size,
133-
// and returns the full metric name (e.g., "metric_name_per_1m").
134-
func (pc *PrometheusClient) resolveFullMetricName(resources []scalertypes.Resource, metricName, windowSize string) (string, error) {
135-
for _, resource := range resources {
136-
for _, scaleResource := range resource.ScaleResources {
137-
if scaleResource.MetricName == metricName {
138-
scaleResourceWindowSize := scalertypes.ShortDurationString(scaleResource.WindowSize)
139-
if scaleResourceWindowSize == windowSize {
140-
return scaleResource.GetKubernetesMetricName(), nil
141-
}
142-
}
143-
}
144-
}
145-
return "", errors.Errorf("Failed to find ScaleResource matching metric name and window size: metricName=%s, windowSize=%s", metricName, windowSize)
146-
}
147-
14894
// GetResourceMetrics retrieves metrics for multiple resources
14995
func (pc *PrometheusClient) GetResourceMetrics(resources []scalertypes.Resource) (map[string]map[string]int, error) {
15096
metricsByResource := make(map[string]map[string]int)
@@ -203,23 +149,23 @@ func (pc *PrometheusClient) GetResourceMetrics(resources []scalertypes.Resource)
203149
for _, metricSample := range metricSamples {
204150
resourceName, err := pc.extractResourceName(metricSample.Metric)
205151
if err != nil {
206-
pc.logger.WarnWith("Failed to extract resource name from Prometheus metricSample labels",
152+
pc.logger.WarnWith("Failed to extract resource name from the Prometheus metric's labels",
207153
"metricName", metricName,
208154
"windowSize", windowSize,
209155
"labels", metricSample.Metric.String(),
210156
"error", err)
211157
continue
212158
}
213159

214-
// Use Ceil to ensure any fractional value > 0 becomes at least 1
160+
// Round up values to ensure any fractional value > 0 becomes at least 1
215161
// This prevents incorrect scale-to-zero decisions for resources with low activity
216162
metricValue := int(math.Ceil(float64(metricSample.Value)))
217163

218164
if _, found := metricsByResource[resourceName]; !found {
219165
metricsByResource[resourceName] = make(map[string]int)
220166
}
221167

222-
pc.logger.DebugWith("Retrieved metricSample sample",
168+
pc.logger.DebugWith("Retrieved metric",
223169
"resourceName", resourceName,
224170
"metricName", fullMetricName,
225171
"windowSize", windowSize,
@@ -228,29 +174,80 @@ func (pc *PrometheusClient) GetResourceMetrics(resources []scalertypes.Resource)
228174
if _, found := metricsByResource[resourceName][fullMetricName]; found {
229175
return nil, errors.Errorf("Cannot have more than one metricSample value per resource: resource=%s, metricSample=%s", resourceName, fullMetricName)
230176
}
231-
232177
metricsByResource[resourceName][fullMetricName] = metricValue
233178
}
234179
}
235180
}
236-
237181
return metricsByResource, nil
238182
}
239183

184+
// renderQuery renders the Prometheus query template
185+
func (pc *PrometheusClient) renderQuery(queryTemplate *template.Template, windowSize, resourceNameRegex string) (string, error) {
186+
templateData := make(map[string]string)
187+
templateData["Namespace"] = pc.namespace
188+
templateData["WindowSize"] = windowSize
189+
templateData["Resources"] = resourceNameRegex
190+
191+
var queryBuffer bytes.Buffer
192+
if err := queryTemplate.Execute(&queryBuffer, templateData); err != nil {
193+
return "", fmt.Errorf("error executing template: %w", err)
194+
}
195+
196+
return queryBuffer.String(), nil
197+
}
198+
199+
// extractWindowSizesForMetric extracts unique window sizes from resources' ScaleResources for a specific metric name.
200+
func (pc *PrometheusClient) extractWindowSizesForMetric(resources []scalertypes.Resource, metricName string) map[string]bool {
201+
windowSizes := make(map[string]bool)
202+
for _, resource := range resources {
203+
for _, scaleResource := range resource.ScaleResources {
204+
if scaleResource.MetricName == metricName {
205+
windowSizeStr := scalertypes.ShortDurationString(scaleResource.WindowSize)
206+
windowSizes[windowSizeStr] = true
207+
}
208+
}
209+
}
210+
return windowSizes
211+
}
212+
213+
// buildResourceNameRegex creates a Prometheus regex pattern for query filtering
214+
func (pc *PrometheusClient) buildResourceNameRegex(resources []scalertypes.Resource) string {
215+
resourceNames := make([]string, len(resources))
216+
for i, resource := range resources {
217+
resourceNames[i] = resource.Name
218+
}
219+
// creates a pipe-separated regex pattern from resource names for Prometheus query filtering (e.g., "resource1|resource2")
220+
return strings.Join(resourceNames, "|")
221+
}
222+
223+
// resolveFullMetricName resolves the full metric name because the same resource can have multiple
224+
// metrics with the same base name but different window sizes (e.g., "metric_name_per_1m" vs "metric_name_per_5m"),
225+
// and we need unique keys in our internal metrics map to store them separately.
226+
func (pc *PrometheusClient) resolveFullMetricName(resources []scalertypes.Resource, metricName, windowSize string) (string, error) {
227+
for _, resource := range resources {
228+
for _, scaleResource := range resource.ScaleResources {
229+
if scaleResource.MetricName == metricName {
230+
scaleResourceWindowSize := scalertypes.ShortDurationString(scaleResource.WindowSize)
231+
if scaleResourceWindowSize == windowSize {
232+
return scaleResource.GetKubernetesMetricName(), nil
233+
}
234+
}
235+
}
236+
}
237+
return "", errors.Errorf("Failed to find ScaleResource matching metric name and window size: metricName=%s, windowSize=%s", metricName, windowSize)
238+
}
239+
240240
// extractResourceName extracts the resource name from Prometheus metric labels.
241241
func (pc *PrometheusClient) extractResourceName(labels model.Metric) (string, error) {
242242
labelNames := []model.LabelName{
243243
"function", // For nuclio functions (nuclio_processor_handled_events_total) - maps to nucliofunction resource
244244
"service_name", // For deployments (num_of_requests, jupyter_kernel_busyness) - maps to deployment resource
245245
"pod", // For pod-based metrics (DCGM_FI_DEV_GPU_UTIL) - maps to pod resource
246246
}
247-
248247
for _, labelName := range labelNames {
249248
if value, ok := labels[labelName]; ok {
250249
return string(value), nil
251250
}
252251
}
253-
254-
// If no common label found, return error
255252
return "", errors.Errorf("Could not extract resource name from labels: %v", labels)
256253
}

0 commit comments

Comments
 (0)