Skip to content

Commit 86b564f

Browse files
mulpuriHarness
authored andcommitted
[fix]: [CCM-30181]: Add all available types to aks debug the issues, debug prod env (#33)
* 761859 CCM-30181: Add all available types to aks debug the issues * 5580d7 CCM-30181: Add all available types to aks debug the issues * 37b374 CCM-30181: Add all available types to aks debug the issues * d6e8da CCM-30181: Add all available types to aks debug the issues
1 parent 3eb195e commit 86b564f

File tree

2 files changed

+240
-42
lines changed

2 files changed

+240
-42
lines changed

internal/cloudinfo/providers/azure/cloudinfo.go

Lines changed: 176 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,16 @@ func (a *AzureInfoer) getPricingWithRetailPricesAPI() (map[string]map[string]typ
229229
baseURL := "https://prices.azure.com/api/retail/prices?$filter=" + url.QueryEscape(filter)
230230
// ex: https://prices.azure.com/api/retail/prices?$filter=serviceName%20eq%20%27Virtual%20Machines%27%20and%20priceType%20eq%20%27Consumption%27%20and%20armSkuName%20eq%20%27Standard_D8as_v5%27%20and%20armRegionName%20eq%20%27australiaeast%27
231231

232+
startTime := time.Now()
233+
a.log.Info("RetailPricesAPI: starting fetch")
234+
235+
pageCount := 0
236+
totalItems := 0
237+
totalSkippedWindows := 0
238+
totalSkippedNonVM := 0
239+
totalOnDemandSet := 0
240+
totalSpotSet := 0
241+
232242
url := baseURL
233243
for url != "" {
234244
client := &http.Client{}
@@ -237,12 +247,23 @@ func (a *AzureInfoer) getPricingWithRetailPricesAPI() (map[string]map[string]typ
237247

238248
resp, err := client.Do(req)
239249
if err != nil {
250+
a.log.Error("RetailPricesAPI: request failed", map[string]interface{}{
251+
"page": pageCount,
252+
"elapsedMins": time.Since(startTime).Minutes(),
253+
"error": err.Error(),
254+
})
240255
return allPrices, fmt.Errorf("failed to call retail API: %w", err)
241256
}
242257
defer resp.Body.Close()
243258

244259
if resp.StatusCode != http.StatusOK {
245260
body, _ := io.ReadAll(resp.Body)
261+
a.log.Error("RetailPricesAPI: non-200 status", map[string]interface{}{
262+
"statusCode": resp.StatusCode,
263+
"page": pageCount,
264+
"elapsedMins": time.Since(startTime).Minutes(),
265+
"body": string(body),
266+
})
246267
return allPrices, fmt.Errorf("unexpected status code %d: %s", resp.StatusCode, string(body))
247268
}
248269

@@ -256,14 +277,19 @@ func (a *AzureInfoer) getPricingWithRetailPricesAPI() (map[string]map[string]typ
256277
return nil, fmt.Errorf("failed to unmarshal retail API response: %w", err)
257278
}
258279

280+
pageCount++
281+
totalItems += len(data.Items)
282+
259283
for _, item := range data.Items {
260284
// Ignoring the windows pricing similar to below
261285
if strings.Contains(strings.ToLower(item.ProductName), "windows") {
286+
totalSkippedWindows++
262287
continue
263288
}
264289

265290
// Ignoring the product if it do not contain virtual machines
266291
if !strings.Contains(strings.ToLower(item.ProductName), "virtual machines") {
292+
totalSkippedNonVM++
267293
continue
268294
}
269295

@@ -278,10 +304,12 @@ func (a *AzureInfoer) getPricingWithRetailPricesAPI() (map[string]map[string]typ
278304
spotPrice := make(types.SpotPriceInfo)
279305
spotPrice[region] = item.Price
280306
price.SpotPrice = spotPrice
307+
totalSpotSet++
281308
} else if strings.Contains(strings.ToLower(item.MeterName), "low priority") {
282309
// ignore this as this is old spot type pricing
283310
} else {
284311
price.OnDemandPrice = item.Price
312+
totalOnDemandSet++
285313
}
286314

287315
allPrices[region][item.ArmSkuName] = price
@@ -290,6 +318,24 @@ func (a *AzureInfoer) getPricingWithRetailPricesAPI() (map[string]map[string]typ
290318
url = data.NextPageURL
291319
}
292320

321+
// Count unique VMs per region for summary
322+
totalUniqueVMs := 0
323+
for _, regionPrices := range allPrices {
324+
totalUniqueVMs += len(regionPrices)
325+
}
326+
327+
a.log.Info("RetailPricesAPI: fetch complete", map[string]interface{}{
328+
"totalPages": pageCount,
329+
"totalItems": totalItems,
330+
"skippedWindows": totalSkippedWindows,
331+
"skippedNonVM": totalSkippedNonVM,
332+
"onDemandPricesSet": totalOnDemandSet,
333+
"spotPricesSet": totalSpotSet,
334+
"regionsWithPrices": len(allPrices),
335+
"totalUniqueVMPrices": totalUniqueVMs,
336+
"elapsedMins": time.Since(startTime).Minutes(),
337+
})
338+
293339
return allPrices, nil
294340
}
295341

@@ -302,6 +348,17 @@ func (a *AzureInfoer) Initialize() (map[string]map[string]types.Price, error) {
302348
allPrices = make(map[string]map[string]types.Price)
303349
}
304350

351+
// Count prices after Retail API
352+
retailVMCount := 0
353+
retailRegionCount := len(allPrices)
354+
for _, regionPrices := range allPrices {
355+
retailVMCount += len(regionPrices)
356+
}
357+
a.log.Info("Initialize: after RetailPricesAPI", map[string]interface{}{
358+
"retailRegions": retailRegionCount,
359+
"retailVMPrices": retailVMCount,
360+
})
361+
305362
regions, err := a.GetRegions("compute")
306363
if err != nil {
307364
return nil, err
@@ -310,64 +367,127 @@ func (a *AzureInfoer) Initialize() (map[string]map[string]types.Price, error) {
310367
rateCardFilter := "OfferDurableId eq 'MS-AZR-0003p' and Currency eq 'USD' and Locale eq 'en-US' and RegionInfo eq 'US'"
311368
// ResourceRateCardInfo is a huge object, it takes around 3-5 minutes to fetch this
312369
startTime := time.Now()
313-
a.log.Info("Fetching Azure ResourceRateCardInfo")
370+
a.log.Info("RateCardAPI: starting fetch")
314371
result, err := a.rateCardClient.Get(context.TODO(), rateCardFilter)
315-
a.log.Info("Fetched Azure ResourceRateCardInfo", map[string]interface{}{"minutesTaken": time.Since(startTime).Minutes()})
372+
a.log.Info("RateCardAPI: fetch complete", map[string]interface{}{"elapsedMins": time.Since(startTime).Minutes()})
316373
if err != nil {
374+
a.log.Error("RateCardAPI: fetch failed", map[string]interface{}{"error": err.Error()})
317375
return nil, err
318376
}
319377

378+
totalMeters := len(*result.Meters)
379+
vmMeters := 0
380+
skippedWindows := 0
381+
skippedNoRegion := 0
382+
skippedTags := 0
383+
rateCardOnDemandSet := 0
384+
rateCardOnDemandSkippedRetailExists := 0
385+
rateCardSpotSet := 0
386+
rateCardVariantsSet := 0
387+
320388
var missingRegions []string
321389
for _, v := range *result.Meters {
322-
if *v.MeterCategory == "Virtual Machines" && len(*v.MeterTags) == 0 && *v.MeterRegion != "" {
323-
if !strings.Contains(*v.MeterSubCategory, "Windows") {
324-
region, err := a.toRegionID(*v.MeterRegion, regions)
325-
if err != nil {
326-
missingRegions = appendIfMissing(missingRegions, *v.MeterRegion)
327-
continue
328-
}
390+
if *v.MeterCategory != "Virtual Machines" {
391+
continue
392+
}
393+
if len(*v.MeterTags) != 0 {
394+
skippedTags++
395+
continue
396+
}
397+
if *v.MeterRegion == "" {
398+
skippedNoRegion++
399+
continue
400+
}
401+
if strings.Contains(*v.MeterSubCategory, "Windows") {
402+
skippedWindows++
403+
continue
404+
}
329405

330-
instanceTypes := a.machineType(*v.MeterName, *v.MeterSubCategory)
406+
vmMeters++
407+
region, err := a.toRegionID(*v.MeterRegion, regions)
408+
if err != nil {
409+
missingRegions = appendIfMissing(missingRegions, *v.MeterRegion)
410+
continue
411+
}
331412

332-
var priceInUsd float64
413+
instanceTypes := a.machineType(*v.MeterName, *v.MeterSubCategory)
333414

334-
if len(v.MeterRates) < 1 {
335-
a.log.Debug("missing rate info", map[string]interface{}{"MeterSubCategory": *v.MeterSubCategory, "region": region})
336-
continue
337-
}
338-
for _, rate := range v.MeterRates {
339-
priceInUsd += *rate
415+
var priceInUsd float64
416+
417+
if len(v.MeterRates) < 1 {
418+
a.log.Warn("missing rate info", map[string]interface{}{"MeterSubCategory": *v.MeterSubCategory, "region": region})
419+
continue
420+
}
421+
for _, rate := range v.MeterRates {
422+
priceInUsd += *rate
423+
}
424+
if allPrices[region] == nil {
425+
allPrices[region] = make(map[string]types.Price)
426+
}
427+
for _, instanceType := range instanceTypes {
428+
price := allPrices[region][instanceType]
429+
if !strings.Contains(*v.MeterName, "Low Priority") {
430+
if price.OnDemandPrice == 0 {
431+
price.OnDemandPrice = priceInUsd
432+
rateCardOnDemandSet++
433+
} else {
434+
rateCardOnDemandSkippedRetailExists++
340435
}
341-
if allPrices[region] == nil {
342-
allPrices[region] = make(map[string]types.Price)
436+
} else {
437+
if price.SpotPrice == nil {
438+
spotPrice := make(types.SpotPriceInfo)
439+
spotPrice[region] = priceInUsd
440+
price.SpotPrice = spotPrice
441+
metrics.ReportAzureSpotPrice(region, instanceType, priceInUsd)
442+
rateCardSpotSet++
343443
}
344-
for _, instanceType := range instanceTypes {
345-
price := allPrices[region][instanceType]
346-
if !strings.Contains(*v.MeterName, "Low Priority") {
347-
if price.OnDemandPrice == 0 {
348-
price.OnDemandPrice = priceInUsd
349-
}
350-
} else {
351-
if price.SpotPrice == nil {
352-
spotPrice := make(types.SpotPriceInfo)
353-
spotPrice[region] = priceInUsd
354-
price.SpotPrice = spotPrice
355-
metrics.ReportAzureSpotPrice(region, instanceType, priceInUsd)
356-
}
357-
}
444+
}
358445

359-
allPrices[region][instanceType] = price
446+
allPrices[region][instanceType] = price
360447

361-
mts := a.getMachineTypeVariants(instanceType)
362-
for _, mt := range mts {
363-
allPrices[region][mt] = price
364-
}
365-
}
448+
mts := a.getMachineTypeVariants(instanceType)
449+
for _, mt := range mts {
450+
allPrices[region][mt] = price
451+
rateCardVariantsSet++
366452
}
367453
}
368454
}
369455
a.log.Debug("couldn't find regions", map[string]interface{}{"missingRegions": missingRegions})
370456

457+
a.log.Info("RateCardAPI: processing complete", map[string]interface{}{
458+
"totalMeters": totalMeters,
459+
"vmMeters": vmMeters,
460+
"skippedWindows": skippedWindows,
461+
"skippedNoRegion": skippedNoRegion,
462+
"skippedTags": skippedTags,
463+
"missingRegions": len(missingRegions),
464+
"rateCardOnDemandSet": rateCardOnDemandSet,
465+
"rateCardOnDemandSkippedRetail": rateCardOnDemandSkippedRetailExists,
466+
"rateCardSpotSet": rateCardSpotSet,
467+
"rateCardVariantsSet": rateCardVariantsSet,
468+
})
469+
470+
// Final summary after merging both APIs
471+
finalVMCount := 0
472+
finalRegionCount := len(allPrices)
473+
zeroOnDemandCount := 0
474+
for _, regionPrices := range allPrices {
475+
for _, p := range regionPrices {
476+
finalVMCount++
477+
if p.OnDemandPrice == 0 {
478+
zeroOnDemandCount++
479+
}
480+
}
481+
}
482+
a.log.Info("Initialize: final merged prices", map[string]interface{}{
483+
"finalRegions": finalRegionCount,
484+
"finalVMPrices": finalVMCount,
485+
"zeroOnDemandVMs": zeroOnDemandCount,
486+
"retailContrib": retailVMCount,
487+
"rateCardContrib": rateCardOnDemandSet,
488+
"variantsContrib": rateCardVariantsSet,
489+
})
490+
371491
a.log.Debug("finished initializing price info")
372492
return allPrices, nil
373493
}
@@ -524,8 +644,25 @@ func (a *AzureInfoer) GetProducts(vms []types.VMInfo, service, regionId string)
524644
return nil, emperror.Wrap(err, "failed to get products")
525645
}
526646
}
647+
527648
switch service {
528649
case svcAks:
650+
dasCount := 0
651+
dasSample := make([]string, 0)
652+
for _, vm := range vmList {
653+
if strings.Contains(strings.ToLower(vm.Type), "as_v") {
654+
dasCount++
655+
if len(dasSample) < 10 {
656+
dasSample = append(dasSample, vm.Type)
657+
}
658+
}
659+
}
660+
a.log.Info("GetProducts for AKS - VM summary", map[string]interface{}{
661+
"region": regionId,
662+
"totalVMs": len(vmList),
663+
"dasFamilyCount": dasCount,
664+
"dasSample": fmt.Sprintf("%v", dasSample),
665+
})
529666
return vmList, nil
530667
case "compute":
531668
return vmList, nil

0 commit comments

Comments
 (0)