finops-toolkit icon indicating copy to clipboard operation
finops-toolkit copied to clipboard

[Open data] Azure Advisor recommendation types

Open flanakin opened this issue 11 months ago • 6 comments

Are you submitting your tool or someone else's?

I'm submitting a tool that I own.

Tool ownership responsibilities (only applicable to tool owners)

  • [x] I acknowledge the responsibilities of a technical lead and agree to serve in this role for the proposed tool upon its approval.

Tool name

RecommendationTypes.csv

Description

Azure Advisor doesn't expose details about the different recommendations that are available. We should include a new open data file that includes the recommendation type details to describe each recommendation made available in Azure Advisor.

Use case

Organize and provide additional context for Azure Advisor recommendations.

Services used

None

Dependencies

This information can be parsed out of Microsoft Learn docs in GitHub via a PowerShell script. There are no runtime dependencies.

flanakin avatar Jan 20 '25 22:01 flanakin

Partial sample from the generated file (6 columns removed):

RecommendationTypeId Category Impact ServiceName ResourceType Key Message Version LearnMoreLink
a06456ed-afb7-4d16-86fd-0054e25268ed Performance Medium Virtual Machines microsoft.compute/virtualmachines AccelNetDisengaged Enable Accelerated Networking to improve network performance and latency 2.1 https://docs.microsoft.com/azure/virtual-network/create-vm-accelerated-networking-cli#enable-accelerated-networking-on-existing-vms
9c0c3708-17f6-4108-9aff-f0e052c3cd41 OperationalExcellence Low Azure App Service microsoft.subscriptions/subscriptions AzureApplicationService Eliminate replica staging environments and ship new versions and features with zero downtime using deployment slots 1.0 https://docs.microsoft.com/azure/app-service/deploy-staging-slots
a205074f-8049-48b3-903f-556f5e530ae3 Cost High ReservedInstances microsoft.subscriptions/subscriptions CosmosDBReservedCapacity Buy reserved instance 9.1 https://aka.ms/rirecommendations
94aea435-ef39-493f-a547-8408092c22a7 Cost High Virtual Machine Scale Sets microsoft.compute/virtualmachinescalesets LowUsageVmss Shut down or resize your virtual machine scale sets 9.9 https://aka.ms/aa_lowusagerec_vmss_learnmore
afdf4c1a-e46b-4817-a5d6-4b9909f58e2a Cost Low Azure Synapse Analytics microsoft.synapse/workspaces EnableSynapseSparkComputeAutoPauseGuidance Consider enabling automatic pause feature on spark compute 3.1 https://aka.ms/EnableSynapseSparkComputeAutoPauseGuidance
ed651749-cd37-4fd5-9897-01b416926745 HighAvailability Medium Site Recovery microsoft.compute/virtualmachines ASRUnprotectedVMs Enable virtual machine replication 7 https://aka.ms/azure-site-recovery-dr-azure-vms

flanakin avatar Jan 20 '25 22:01 flanakin

@arthurclares / @helderpinto / @nteyan, I figure y'all have spent the most time looking at the Advisor recommendations. I was thinking about adding more context to our Power BI report and wasn't able to find this level of detail. I haven't fully thought thru how we'd use it but I figure y'all are the best to review the proposal. Let me know if you have any questions.

flanakin avatar Jan 20 '25 22:01 flanakin

I don't think we have a central pace for these recommendations, so having this file seems to be a good idea. Hwoever, from a Hub perspective, we could simply have an ARG query that would surface these recommendations and then add it to the dashboards, wouldn't that be easier? Actually, if I'm not mistaken, Helder has done this already.

arthurclares avatar Jan 22 '25 10:01 arthurclares

@flanakin, I didn't find any GitHub docs reference where we could parse all the recommendation types columns. Can you share the source where you got the sample table from?

The metadata Azure Advisor REST API endpoint would probably be the best source of truth for this information. However, it does not contain data for the recommendation version nor the learn more link.

Alternatively, we could use Azure Resource Graph, but it only contains metadata for recommendations that have been generated in the context of the customer, which is only a subset of all possible recommendation types.

helderpinto avatar Jan 26 '25 22:01 helderpinto

I didn't find any GitHub docs reference where we could parse all the recommendation types columns. Can you share the source where you got the sample table from?

@helderpinto We talked about this, but sharing with others: I found the details in the MicrosoftDocs/SelfHelpContent repo. I believe the repo is private to FTEs only. This repo has self-help guidance for every Azure service used in the Azure portal.

The metadata Azure Advisor REST API endpoint would probably be the best source of truth for this information. However, it does not contain data for the recommendation version nor the learn more link.

I wasn't aware of the RecommendationMetadata API. I would agree that would be a better source for the core details. We can merge the self-help content as well.

Alternatively, we could use Azure Resource Graph, but it only contains metadata for recommendations that have been generated in the context of the customer, which is only a subset of all possible recommendation types.

This works for Power BI, but not ADX dashboards.

The question is, do we see value in providing a CSV dataset that we can ingest into Power BI and Data Explorer to improve our reports and dashboards? Power BI can call the current API, but not the self-help guidance, but I'm not sure I'd do this for the self-help guidance only. I don't know if ADX dashboards can call ARM APIs.

flanakin avatar Feb 02 '25 16:02 flanakin

I see the value, use case, we're consuming advisor recommendations from Graph, into our Recomendations_Final_v1_0, I find it useful to track the values of Recommendations over time.

mapping, parsing the typeIDs into some semblance of Focus Formatting is what we're doing, but it would be nice to have a Consolidated CSV or Json with all of the Fields defined.

graph {"query": "advisorresources | where type == 'microsoft.advisor/recommendations' | where properties.category == 'Cost' | project id, tenantId, subscriptionId, properties, ['date'] = startofday(now()) "} -> daily_cost_recommendations_raw

then functions to move it into Recommendations_final_v1_0 example for orphaned disks which doesnt' have an advisor calculated Cost savings

.create function with (docstring = 'Returns daily cost recommendations for orphaned disks', folder = 'AdvisorRecommendations') daily_cost_recommendations_orphanedDisks { daily_cost_recommendations_raw | where ['date'] == startofday(now()) | extend x_properties = parse_json(properties) | extend RecommendationTypeID = tostring(x_properties.recommendationTypeId) | where RecommendationTypeID == '48eda464-1485-4dcf-a674-d0905df5054a' | extend resourceId = tostring(x_properties.resourceMetadata.resourceId) | extend ProviderName = 'Microsoft' | extend SubAccountId = strcat('/subscriptions/', subscriptionId) | extend x_ingestionTime = now() | extend x_RecommendationDate = ['date'] | extend x_RecommendationDetails = x_properties | extend x_SourceName = 'Advisor' | extend x_SourceProvider = 'Microsoft' | extend x_SourceVersion = '2025-08-15' | extend lowID = tolower(resourceId) | extend x_SourceType = 'OrphanedDiskRecommendations' | join ( Costs_final_v1_0 | where ChargePeriodStart == datetime_add('day', -1, startofday(now())) | extend lowID = tolower(ResourceId) | summarize x_EffectiveCostBefore = todecimal(sum(EffectiveCost) * 365.25) by lowID ) on lowID | extend x_EffectiveCostAfter = todecimal(0) | extend x_EffectiveCostSavings = todecimal(x_EffectiveCostBefore) | project ProviderName, SubAccountId, x_ingestionTime, x_EffectiveCostAfter, x_EffectiveCostBefore, x_EffectiveCostSavings, x_RecommendationDate, x_RecommendationDetails, x_SourceName, x_SourceProvider, x_SourceType, x_SourceVersion }

ch10299342 avatar Aug 15 '25 17:08 ch10299342