Nota
L-aċċess għal din il-paġna jeħtieġ l-awtorizzazzjoni. Tista’ tipprova tidħol jew tibdel id-direttorji.
L-aċċess għal din il-paġna jeħtieġ l-awtorizzazzjoni. Tista’ tipprova tibdel id-direttorji.
FinOps hubs collect recommendations from multiple sources and ingest them into the Recommendations managed dataset alongside reservation recommendations from Cost Management exports. Recommendations are sourced from Azure Resource Graph using a configurable set of queries that pull Azure Advisor recommendations and identify various optimization scenarios based on resource configuration. Queries are managed in simple JSON files in storage, making it easy to add your own custom recommendations by uploading query files to hub storage.
Prerequisites
Before you begin, you must have:
- Deployed a FinOps hub instance.
- Assigned the Reader role to the Data Factory managed identity on the management groups or subscriptions you want to query. This permission must be configured separately from the FinOps hub deployment.
How recommendations are processed
The recommendations pipeline runs daily and processes query files stored in the config/queries folder in hub storage:
- The queries_DailySchedule trigger runs once per day.
- The queries_ExecuteETL pipeline iterates through all query files in the config/queries storage folder.
- The queries_ETL_ingestion pipeline executes each query against Azure Resource Graph, deduplicates results, and saves data as parquet in the ingestion/Recommendations folder.
- If using Azure Data Explorer, data is ingested into the
Recommendations_rawtable and transformed using theRecommendations_transform_v1_2()function.
Hubs recommendations are combined with reservation recommendations from Cost Management exports in the same Recommendations managed dataset. You can distinguish between sources using the x_SourceType column.
Built-in recommendations
FinOps hubs include the following recommendations. Most are enabled by default. Optional recommendations may generate noise for organizations where they don't apply and can be enabled during deployment via the specified template parameter.
Compute
- Virtual Machines
- Deallocate stopped VMs.
- Migrate to managed disks.
- Optional: Use Azure Hybrid Benefit for Windows VMs. Enabled via the
enableAHBRecommendationsoption.
- SQL Virtual Machines
- Optional: Use Azure Hybrid Benefit for SQL VMs. Enabled via the
enableAHBRecommendationsoption.
- Optional: Use Azure Hybrid Benefit for SQL VMs. Enabled via the
- Azure Kubernetes Service
- Optional: Use Spot VMs for AKS clusters. Enabled via the
enableSpotRecommendationsoption.
- Optional: Use Spot VMs for AKS clusters. Enabled via the
Databases
- Azure SQL Database
Management and Governance
- Azure Advisor
Networking
- Application Gateway
- DDoS Protection
- ExpressRoute
- Load Balancer
- NAT Gateway
- Network Interfaces
- Network Security Groups
- Public IP Addresses
- VPN Gateway
Storage
- Managed Disks
- Storage Accounts
Web
- App Service
To disable a specific default recommendation, delete its query file from the config/queries folder in hub storage. The pipeline only processes query files that are present.
Add custom recommendations
You can add custom recommendations by uploading query files to the config/queries folder in hub storage. The pipeline picks up new query files automatically on the next daily run.
File naming convention
Name query files using the {dataset}-{provider}-{type}.json format:
- Dataset — The target dataset (for example,
Recommendations). - Provider — The provider of the service data is for (for example,
Microsoft,Contoso). - Type — The recommendation type identifier using PascalCase (for example,
StoppedVMs,IdleCosmosDB).
For example: Recommendations-Contoso-IdleCosmosDB.json
Query file format
Each query file is a JSON file with the following properties:
{
"dataset": "Recommendations",
"provider": "Microsoft",
"query": "<Azure Resource Graph query>",
"queryEngine": "ResourceGraph",
"scope": "Tenant",
"source": "<descriptive source name>",
"type": "<unique type identifier>",
"version": "1.0"
}
| Property | Description |
|---|---|
dataset |
Must be "Recommendations". |
provider |
Provider name (for example, "Microsoft"). |
query |
The Azure Resource Graph query to execute, on a single line. |
queryEngine |
Must be "ResourceGraph". |
scope |
Query scope. Use "Tenant" to query all subscriptions the Data Factory managed identity has access to within the tenant. Cross-tenant queries aren't supported but resources delegated via Azure Lighthouse are included in tenant-scope queries. |
source |
Descriptive name for the recommendation source (for example, "Azure Advisor" or "FinOps hubs"). |
type |
Programmatic identifier for this recommendation type. Use a {provider}-{name} format with alphanumeric characters and hyphens only (for example, "Contoso-IdleCosmosDB"). This value is used as part of the output file name. |
version |
Schema version. Use "1.0". |
Required output columns
Your query must return the following columns:
| Column | Description |
|---|---|
ResourceId |
Resource ID (lowercase). |
ResourceName |
Resource name (lowercase). |
SubAccountId |
Subscription ID. |
SubAccountName |
Subscription name. Join with resourcecontainers to populate this. |
x_RecommendationCategory |
Recommendation category. Use "Cost", "HighAvailability", "OperationalExcellence", "Performance", or "Security". |
x_RecommendationDate |
Recommendation date (use now() for point-in-time queries). |
x_RecommendationDescription |
Short description of the issue. |
x_RecommendationDetails |
JSON string with additional properties. Include x_RecommendationProvider, x_RecommendationSolution, x_RecommendationTypeId, and x_ResourceType along with any custom properties specific to the recommendation. |
x_RecommendationId |
Unique identifier for the recommendation (for example, resource ID + suffix). |
x_ResourceGroupName |
Resource group name (lowercase). |
Tips for writing queries
To populate the subscription name, join with
resourcecontainersat the end of your query:| join kind=leftouter ( resourcecontainers | where type == 'microsoft.resources/subscriptions' | project SubAccountName=name, SubAccountId=subscriptionId ) on SubAccountId | project-away SubAccountId1Generate
x_RecommendationIdby combining the resource ID with a descriptive suffix (for example,strcat(tolower(id), '-idle')).Build
x_RecommendationDetailsusingtostring(bag_pack(...))to produce a JSON string. Wrapping withtostring()is required because the data pipeline can't serialize dynamic objects to parquet; the value must be a string. You can also usestrcat()to build a JSON string manually, butbag_pack()is recommended because it handles escaping automatically.Include
x_RecommendationTypeIdas a stable GUID to uniquely identify the recommendation type across runs.
For examples, review the built-in query files in the FinOps toolkit source code.
Give feedback
Let us know how we're doing with a quick review. We use these reviews to improve and expand FinOps tools and resources.
If you're looking for something specific, vote for an existing or create a new idea. Share ideas with others to get more votes. We focus on ideas with the most votes.