@@ -85,60 +85,6 @@ func NewPrometheusClient(parentLogger logger.Logger, prometheusURL, namespace st
8585 }, nil
8686}
8787
88- // renderQuery renders the Prometheus query template
89- func (pc * PrometheusClient ) renderQuery (queryTemplate * template.Template , windowSize , resourceNameRegex string ) (string , error ) {
90- templateData := make (map [string ]string )
91- templateData ["Namespace" ] = pc .namespace
92- templateData ["WindowSize" ] = windowSize
93- templateData ["Resources" ] = resourceNameRegex
94-
95- var queryBuffer bytes.Buffer
96- if err := queryTemplate .Execute (& queryBuffer , templateData ); err != nil {
97- return "" , fmt .Errorf ("error executing template: %w" , err )
98- }
99-
100- return queryBuffer .String (), nil
101- }
102-
103- // extractWindowSizesForMetric extracts unique window sizes from resources' ScaleResources for a specific metric name.
104- func (pc * PrometheusClient ) extractWindowSizesForMetric (resources []scalertypes.Resource , metricName string ) map [string ]bool {
105- windowSizes := make (map [string ]bool )
106- for _ , resource := range resources {
107- for _ , scaleResource := range resource .ScaleResources {
108- if scaleResource .MetricName == metricName {
109- windowSizeStr := scalertypes .ShortDurationString (scaleResource .WindowSize )
110- windowSizes [windowSizeStr ] = true
111- }
112- }
113- }
114- return windowSizes
115- }
116-
117- // buildResourceNameRegex creates a pipe-separated regex pattern from resource names for Prometheus query filtering (e.g., "func1|func2|func3")
118- func (pc * PrometheusClient ) buildResourceNameRegex (resources []scalertypes.Resource ) string {
119- resourceNames := make ([]string , len (resources ))
120- for i , resource := range resources {
121- resourceNames [i ] = resource .Name
122- }
123- return strings .Join (resourceNames , "|" )
124- }
125-
126- // resolveFullMetricName finds the matching ScaleResource for a given metric name and window size,
127- // and returns the full metric name (e.g., "metric_name_per_1m").
128- func (pc * PrometheusClient ) resolveFullMetricName (resources []scalertypes.Resource , metricName , windowSize string ) (string , error ) {
129- for _ , resource := range resources {
130- for _ , scaleResource := range resource .ScaleResources {
131- if scaleResource .MetricName == metricName {
132- scaleResourceWindowSize := scalertypes .ShortDurationString (scaleResource .WindowSize )
133- if scaleResourceWindowSize == windowSize {
134- return scaleResource .GetKubernetesMetricName (), nil
135- }
136- }
137- }
138- }
139- return "" , errors .Errorf ("Failed to find ScaleResource matching metric name and window size: metricName=%s, windowSize=%s" , metricName , windowSize )
140- }
141-
14288// GetResourceMetrics retrieves metrics for multiple resources
14389func (pc * PrometheusClient ) GetResourceMetrics (resources []scalertypes.Resource ) (map [string ]map [string ]int , error ) {
14490 metricsByResource := make (map [string ]map [string ]int )
@@ -197,23 +143,23 @@ func (pc *PrometheusClient) GetResourceMetrics(resources []scalertypes.Resource)
197143 for _ , metricSample := range metricSamples {
198144 resourceName , err := pc .extractResourceName (metricSample .Metric )
199145 if err != nil {
200- pc .logger .WarnWith ("Failed to extract resource name from Prometheus metricSample labels" ,
146+ pc .logger .WarnWith ("Failed to extract resource name from the Prometheus metric's labels" ,
201147 "metricName" , metricName ,
202148 "windowSize" , windowSize ,
203149 "labels" , metricSample .Metric .String (),
204150 "error" , err )
205151 continue
206152 }
207153
208- // Use Ceil to ensure any fractional value > 0 becomes at least 1
154+ // Round up values to ensure any fractional value > 0 becomes at least 1
209155 // This prevents incorrect scale-to-zero decisions for resources with low activity
210156 metricValue := int (math .Ceil (float64 (metricSample .Value )))
211157
212158 if _ , found := metricsByResource [resourceName ]; ! found {
213159 metricsByResource [resourceName ] = make (map [string ]int )
214160 }
215161
216- pc .logger .DebugWith ("Retrieved metricSample sample " ,
162+ pc .logger .DebugWith ("Retrieved metric " ,
217163 "resourceName" , resourceName ,
218164 "metricName" , fullMetricName ,
219165 "windowSize" , windowSize ,
@@ -222,29 +168,80 @@ func (pc *PrometheusClient) GetResourceMetrics(resources []scalertypes.Resource)
222168 if _ , found := metricsByResource [resourceName ][fullMetricName ]; found {
223169 return nil , errors .Errorf ("Cannot have more than one metricSample value per resource: resource=%s, metricSample=%s" , resourceName , fullMetricName )
224170 }
225-
226171 metricsByResource [resourceName ][fullMetricName ] = metricValue
227172 }
228173 }
229174 }
230-
231175 return metricsByResource , nil
232176}
233177
178+ // renderQuery renders the Prometheus query template
179+ func (pc * PrometheusClient ) renderQuery (queryTemplate * template.Template , windowSize , resourceNameRegex string ) (string , error ) {
180+ templateData := make (map [string ]string )
181+ templateData ["Namespace" ] = pc .namespace
182+ templateData ["WindowSize" ] = windowSize
183+ templateData ["Resources" ] = resourceNameRegex
184+
185+ var queryBuffer bytes.Buffer
186+ if err := queryTemplate .Execute (& queryBuffer , templateData ); err != nil {
187+ return "" , fmt .Errorf ("error executing template: %w" , err )
188+ }
189+
190+ return queryBuffer .String (), nil
191+ }
192+
193+ // extractWindowSizesForMetric extracts unique window sizes from resources' ScaleResources for a specific metric name.
194+ func (pc * PrometheusClient ) extractWindowSizesForMetric (resources []scalertypes.Resource , metricName string ) map [string ]bool {
195+ windowSizes := make (map [string ]bool )
196+ for _ , resource := range resources {
197+ for _ , scaleResource := range resource .ScaleResources {
198+ if scaleResource .MetricName == metricName {
199+ windowSizeStr := scalertypes .ShortDurationString (scaleResource .WindowSize )
200+ windowSizes [windowSizeStr ] = true
201+ }
202+ }
203+ }
204+ return windowSizes
205+ }
206+
207+ // buildResourceNameRegex creates a Prometheus regex pattern for query filtering
208+ func (pc * PrometheusClient ) buildResourceNameRegex (resources []scalertypes.Resource ) string {
209+ resourceNames := make ([]string , len (resources ))
210+ for i , resource := range resources {
211+ resourceNames [i ] = resource .Name
212+ }
213+ // creates a pipe-separated regex pattern from resource names for Prometheus query filtering (e.g., "resource1|resource2")
214+ return strings .Join (resourceNames , "|" )
215+ }
216+
217+ // resolveFullMetricName resolves the full metric name because the same resource can have multiple
218+ // metrics with the same base name but different window sizes (e.g., "metric_name_per_1m" vs "metric_name_per_5m"),
219+ // and we need unique keys in our internal metrics map to store them separately.
220+ func (pc * PrometheusClient ) resolveFullMetricName (resources []scalertypes.Resource , metricName , windowSize string ) (string , error ) {
221+ for _ , resource := range resources {
222+ for _ , scaleResource := range resource .ScaleResources {
223+ if scaleResource .MetricName == metricName {
224+ scaleResourceWindowSize := scalertypes .ShortDurationString (scaleResource .WindowSize )
225+ if scaleResourceWindowSize == windowSize {
226+ return scaleResource .GetKubernetesMetricName (), nil
227+ }
228+ }
229+ }
230+ }
231+ return "" , errors .Errorf ("Failed to find ScaleResource matching metric name and window size: metricName=%s, windowSize=%s" , metricName , windowSize )
232+ }
233+
234234// extractResourceName extracts the resource name from Prometheus metric labels.
235235func (pc * PrometheusClient ) extractResourceName (labels model.Metric ) (string , error ) {
236236 labelNames := []model.LabelName {
237237 "function" , // For nuclio functions (nuclio_processor_handled_events_total) - maps to nucliofunction resource
238238 "service_name" , // For deployments (num_of_requests, jupyter_kernel_busyness) - maps to deployment resource
239239 "pod" , // For pod-based metrics (DCGM_FI_DEV_GPU_UTIL) - maps to pod resource
240240 }
241-
242241 for _ , labelName := range labelNames {
243242 if value , ok := labels [labelName ]; ok {
244243 return string (value ), nil
245244 }
246245 }
247-
248- // If no common label found, return error
249246 return "" , errors .Errorf ("Could not extract resource name from labels: %v" , labels )
250247}
0 commit comments