From d70eeda94f9006aed114e9144169dd443d2a426d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 18 May 2026 07:52:42 +0000 Subject: [PATCH 1/6] Initial plan From 7b94d471a4acd52107d2f0442eea67a92b2866ae Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 18 May 2026 07:55:31 +0000 Subject: [PATCH 2/6] Fix ingestion memory errors by replacing strcat() in empty checks Agent-Logs-Url: https://github.com/microsoft/finops-toolkit/sessions/ab35dd4d-dd87-400b-8550-60c4a73c71e3 Co-authored-by: flanakin <399533+flanakin@users.noreply.github.com> --- .../Analytics/scripts/IngestionSetup_v1_0.kql | 2 +- .../Analytics/scripts/IngestionSetup_v1_2.kql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/templates/finops-hub/modules/Microsoft.FinOpsHubs/Analytics/scripts/IngestionSetup_v1_0.kql b/src/templates/finops-hub/modules/Microsoft.FinOpsHubs/Analytics/scripts/IngestionSetup_v1_0.kql index 1484f82ab..2f68d2c82 100644 --- a/src/templates/finops-hub/modules/Microsoft.FinOpsHubs/Analytics/scripts/IngestionSetup_v1_0.kql +++ b/src/templates/finops-hub/modules/Microsoft.FinOpsHubs/Analytics/scripts/IngestionSetup_v1_0.kql @@ -408,7 +408,7 @@ Costs_transform_v1_0() and (ListUnitPrice == 0 or ContractedUnitPrice == 0) and x_EffectiveUnitPrice != 0 and not(CommitmentDiscountCategory == 'Spend' and CommitmentDiscountStatus == 'Unused') - and isnotempty(strcat(x_SkuMeterId, x_SkuOfferId)) + and isnotempty(x_SkuMeterId) and isnotempty(x_SkuOfferId) | as allCosts | where tmp_MissingPrices | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(ChargePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId)) diff --git a/src/templates/finops-hub/modules/Microsoft.FinOpsHubs/Analytics/scripts/IngestionSetup_v1_2.kql b/src/templates/finops-hub/modules/Microsoft.FinOpsHubs/Analytics/scripts/IngestionSetup_v1_2.kql index daeab5527..3ffee099d 100644 --- a/src/templates/finops-hub/modules/Microsoft.FinOpsHubs/Analytics/scripts/IngestionSetup_v1_2.kql +++ b/src/templates/finops-hub/modules/Microsoft.FinOpsHubs/Analytics/scripts/IngestionSetup_v1_2.kql @@ -413,7 +413,7 @@ Costs_transform_v1_2() and (isempty(ListUnitPrice) or isempty(ContractedUnitPrice) or ListUnitPrice == 0 or ContractedUnitPrice == 0) and x_EffectiveUnitPrice != 0 and not(CommitmentDiscountCategory == 'Spend' and CommitmentDiscountStatus == 'Unused') - and isnotempty(strcat(x_SkuMeterId, x_SkuOfferId)) + and isnotempty(x_SkuMeterId) and isnotempty(x_SkuOfferId) | as allCosts | where tmp_MissingPrices | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(ChargePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId)) From 24e794a5f96d2935a60286101f36ea0c08d08965 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 26 May 2026 06:34:15 +0000 Subject: [PATCH 3/6] Fix isnotempty(strcat()) pattern in finops-hub-14.0 and latest ARM templates --- docs/deploy/finops-hub-14.0.json | 4 ++-- docs/deploy/finops-hub-latest.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/deploy/finops-hub-14.0.json b/docs/deploy/finops-hub-14.0.json index f9d71a4ab..f90016f65 100644 --- a/docs/deploy/finops-hub-14.0.json +++ b/docs/deploy/finops-hub-14.0.json @@ -18320,7 +18320,7 @@ "variables": { "$fxv#0": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n.create-or-alter function \nwith (docstring = 'Return details about the specified ID.', folder = 'OpenData/Internal')\n_resource_type_1(id: string) {\n dynamic({\n \"arizeai.observabilityeval/organizations\": { \"SingularDisplayName\": \"Azure Native Arize AI Cloud Service\" }\n ,\"astronomer.astro/organizations\": { \"SingularDisplayName\": \"Astro Organization\" }\n ,\"citrix.services/xenappessentials\": { \"SingularDisplayName\": \"Citrix Virtual Apps Essentials\" }\n ,\"citrix.services/xendesktopessentials\": { \"SingularDisplayName\": \"Citrix Virtual Desktops Essentials\" }\n ,\"commvault.contentstore/cloudaccounts\": { \"SingularDisplayName\": \"Commvault Cloud Account\" }\n ,\"commvault.contentstore/cloudaccounts/plans\": { \"SingularDisplayName\": \"Commvault.ContentStore cloud accounts plan\" }\n ,\"commvault.contentstore/cloudaccounts/protectiongroups\": { \"SingularDisplayName\": \"Commvault.ContentStore cloud accounts protection group\" }\n ,\"commvault.contentstore/cloudaccounts/protectiongroups/protecteditems\": { \"SingularDisplayName\": \"Commvault.ContentStore cloud accounts protection groups protected item\" }\n ,\"commvault.contentstore/cloudaccounts/storages\": { \"SingularDisplayName\": \"Commvault.ContentStore cloud accounts storage\" }\n ,\"dell.storage/filesystems\": { \"SingularDisplayName\": \"Dell PowerScale\" }\n ,\"dynatrace.observability/monitors\": { \"SingularDisplayName\": \"Dynatrace\" }\n ,\"github.network/networksettings\": { \"SingularDisplayName\": \"GitHub.Network network setting\" }\n ,\"informatica.datamanagement/organizations\": { \"SingularDisplayName\": \"Informatica Organization\" }\n ,\"lambdatest.hyperexecute/organizations\": { \"SingularDisplayName\": \"Azure Native LambdaTest - HyperExecute Cloud Service\" }\n ,\"microsoft.aad/domainservices\": { \"SingularDisplayName\": \"Microsoft Entra Domain Services\" }\n ,\"microsoft.aadiam/diagnosticsettings\": { \"SingularDisplayName\": \"Microsoft.aadiam diagnostic setting\" }\n ,\"microsoft.aadiam/privatelinkforazuread\": { \"SingularDisplayName\": \"Private Link for Microsoft Entra ID\" }\n ,\"microsoft.advisor/advisorscore\": { \"SingularDisplayName\": \"Microsoft.Advisor advisor score\" }\n ,\"microsoft.advisor/assessments\": { \"SingularDisplayName\": \"Microsoft.Advisor assessment\" }\n ,\"microsoft.advisor/configurations\": { \"SingularDisplayName\": \"Microsoft.Advisor configuration\" }\n ,\"microsoft.advisor/generaterecommendations\": { \"SingularDisplayName\": \"Microsoft.Advisor generate recommendation\" }\n ,\"microsoft.advisor/metadata\": { \"SingularDisplayName\": \"Microsoft.Advisor metadata\" }\n ,\"microsoft.advisor/recommendations\": { \"SingularDisplayName\": \"Microsoft.Advisor recommendation\" }\n ,\"microsoft.advisor/recommendations/suppressions\": { \"SingularDisplayName\": \"Microsoft.Advisor recommendations suppression\" }\n ,\"microsoft.advisor/resiliencyreviews\": { \"SingularDisplayName\": \"Microsoft.Advisor resiliency review\" }\n ,\"microsoft.agfoodplatform/farmbeats\": { \"SingularDisplayName\": \"Azure Data Manager for Agriculture\" }\n ,\"microsoft.agfoodplatform/farmbeatsextensiondefinitions\": { \"SingularDisplayName\": \"Microsoft.AgFoodPlatform farm beats extension definition\" }\n ,\"microsoft.agfoodplatform/farmbeatssolutiondefinitions\": { \"SingularDisplayName\": \"Microsoft.AgFoodPlatform farm beats solution definition\" }\n ,\"microsoft.agricultureplatform/agriservices\": { \"SingularDisplayName\": \"Agriculture data solutions\" }\n ,\"microsoft.akshybrid/agentpools\": { \"SingularDisplayName\": \"Microsoft.AksHybrid agent pool\" }\n ,\"microsoft.akshybrid/provisionedclusters\": { \"SingularDisplayName\": \"Microsoft.AksHybrid provisioned cluster\" }\n ,\"microsoft.akshybrid/upgradeprofiles\": { \"SingularDisplayName\": \"Microsoft.AksHybrid upgrade profile\" }\n ,\"microsoft.alertsmanagement/actionrules\": { \"SingularDisplayName\": \"Alert processing rule\" }\n ,\"microsoft.alertsmanagement/alerts\": { \"SingularDisplayName\": \"Microsoft.AlertsManagement alert\" }\n ,\"microsoft.alertsmanagement/alerts/enrichments\": { \"SingularDisplayName\": \"Microsoft.AlertsManagement alerts enrichment\" }\n ,\"microsoft.alertsmanagement/prometheusrulegroups\": { \"SingularDisplayName\": \"Prometheus rule group\" }\n ,\"microsoft.alertsmanagement/smartdetectoralertrules\": { \"SingularDisplayName\": \"Smart detector alert rule\" }\n ,\"microsoft.alertsmanagement/smartgroups\": { \"SingularDisplayName\": \"Microsoft.AlertsManagement smart group\" }\n ,\"microsoft.alertsmanagement/tenantactivitylogalerts\": { \"SingularDisplayName\": \"Microsoft.AlertsManagement tenant activity log alert\" }\n ,\"microsoft.all/arcvirtualmachines\": { \"SingularDisplayName\": \"Azure Arc virtual machine\" }\n ,\"microsoft.all/hcivirtualmachines\": { \"SingularDisplayName\": \"Azure Local Virtual Machine - Azure Arc\" }\n ,\"microsoft.all/virtualmachines\": { \"SingularDisplayName\": \"Virtual machine\" }\n ,\"microsoft.analysisservices/servers\": { \"SingularDisplayName\": \"Analysis Services server\" }\n ,\"microsoft.anybuild/clusters\": { \"SingularDisplayName\": \"AnyBuild cluster\" }\n ,\"microsoft.apicenter/deletedservices\": { \"SingularDisplayName\": \"Microsoft.ApiCenter deleted service\" }\n ,\"microsoft.apicenter/services\": { \"SingularDisplayName\": \"API Center\" }\n ,\"microsoft.apicenter/services/workspaces\": { \"SingularDisplayName\": \"Workspace\" }\n ,\"microsoft.apimanagement/gateways\": { \"SingularDisplayName\": \"API Management gateway\" }\n ,\"microsoft.apimanagement/gateways/configconnections\": { \"SingularDisplayName\": \"Microsoft.ApiManagement gateways config connection\" }\n ,\"microsoft.apimanagement/service\": { \"SingularDisplayName\": \"API Management service\" }\n ,\"microsoft.apimanagement/service/workspaces\": { \"SingularDisplayName\": \"Workspace\" }\n ,\"microsoft.apisecurity/defendersettings\": { \"SingularDisplayName\": \"Microsoft.ApiSecurity defender setting\" }\n ,\"microsoft.app/agents\": { \"SingularDisplayName\": \"SRE Agent\" }\n ,\"microsoft.app/builders\": { \"SingularDisplayName\": \"Microsoft.App builder\" }\n ,\"microsoft.app/builders/builds\": { \"SingularDisplayName\": \"Microsoft.App builders build\" }\n ,\"microsoft.app/connectedenvironments\": { \"SingularDisplayName\": \"Container Apps Connected Environment\" }\n ,\"microsoft.app/containerapps\": { \"SingularDisplayName\": \"Container App\" }\n ,\"microsoft.app/jobs\": { \"SingularDisplayName\": \"Container App Job\" }\n ,\"microsoft.app/logicapps\": { \"SingularDisplayName\": \"Logic app\" }\n ,\"microsoft.app/logicapps/workflows\": { \"SingularDisplayName\": \"Logic app workflow\" }\n ,\"microsoft.app/managedenvironments\": { \"SingularDisplayName\": \"Container Apps Environment\" }\n ,\"microsoft.app/sessionpools\": { \"SingularDisplayName\": \"Container App Session Pool\" }\n ,\"microsoft.app/spaces\": { \"SingularDisplayName\": \"App Space\" }\n ,\"microsoft.appassessment/migrateprojects\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate project\" }\n ,\"microsoft.appassessment/migrateprojects/assessments\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects assessment\" }\n ,\"microsoft.appassessment/migrateprojects/assessments/assessedapplications\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects assessments assessed application\" }\n ,\"microsoft.appassessment/migrateprojects/assessments/assessedmachines\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects assessments assessed machine\" }\n ,\"microsoft.appassessment/migrateprojects/assessments/machinestoassess\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects assessments machines to asses\" }\n ,\"microsoft.appassessment/migrateprojects/sites\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects site\" }\n ,\"microsoft.appassessment/migrateprojects/sites/applianceconfigurations\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects sites appliance configuration\" }\n ,\"microsoft.appcomplianceautomation/reports\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation report\" }\n ,\"microsoft.appcomplianceautomation/reports/evidences\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports evidence\" }\n ,\"microsoft.appcomplianceautomation/reports/scopingconfigurations\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports scoping configuration\" }\n ,\"microsoft.appcomplianceautomation/reports/snapshots\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports snapshot\" }\n ,\"microsoft.appcomplianceautomation/reports/snapshots/controls\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports snapshots control\" }\n ,\"microsoft.appcomplianceautomation/reports/webhooks\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports webhook\" }\n ,\"microsoft.appconfiguration/configurationstores\": { \"SingularDisplayName\": \"App Configuration\" }\n ,\"microsoft.applicationmigration/discoveryhubs\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration discovery hub\" }\n ,\"microsoft.applicationmigration/discoveryhubs/applications\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration discovery hubs application\" }\n ,\"microsoft.applicationmigration/discoveryhubs/applications/members\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration discovery hubs applications member\" }\n ,\"microsoft.applicationmigration/pgsqlsites\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration pgsqlsite\" }\n ,\"microsoft.applicationmigration/pgsqlsites/agents\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration pgsqlsites agent\" }\n ,\"microsoft.applicationmigration/pgsqlsites/pgsqldatabases\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration pgsqlsites pgsqldatabase\" }\n ,\"microsoft.applicationmigration/pgsqlsites/pgsqlinstances\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration pgsqlsites pgsqlinstance\" }\n ,\"microsoft.appplatform/spring\": { \"SingularDisplayName\": \"Azure Spring Apps\" }\n ,\"microsoft.appsecurity/appprotectmanagedrulesetmanifests\": { \"SingularDisplayName\": \"Microsoft.AppSecurity app protect managed rule set manifest\" }\n ,\"microsoft.appsecurity/policies\": { \"SingularDisplayName\": \"App Protect Policy\" }\n ,\"microsoft.arc/all\": { \"SingularDisplayName\": \"Azure Arc enabled resource\" }\n ,\"microsoft.arc/allfairfax\": { \"SingularDisplayName\": \"Azure Arc enabled resource\" }\n ,\"microsoft.arc/kubernetesresources\": { \"SingularDisplayName\": \"Azure Arc Kubernetes cluster\" }\n ,\"microsoft.arc/kubernetesresourcesfairfax\": { \"SingularDisplayName\": \"Azure Arc Kubernetes cluster\" }\n ,\"microsoft.arcnetworking/arcnwloadbalancers\": { \"SingularDisplayName\": \"Microsoft.ArcNetworking arc nw load balancer\" }\n ,\"microsoft.aszlabhardware/labservers\": { \"SingularDisplayName\": \"Microsoft.AszLabHardware labserver\" }\n ,\"microsoft.aszlabhardware/reservations\": { \"SingularDisplayName\": \"Microsoft.AszLabHardware reservation\" }\n ,\"microsoft.aszlabhardware/reservations/servers\": { \"SingularDisplayName\": \"Microsoft.AszLabHardware reservations server\" }\n ,\"microsoft.aszlabhardware/servers\": { \"SingularDisplayName\": \"Microsoft.AszLabHardware server\" }\n ,\"microsoft.attestation/attestationproviders\": { \"SingularDisplayName\": \"Attestation provider\" }\n ,\"microsoft.authorization/accessreviewhistorydefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization access review history definition\" }\n ,\"microsoft.authorization/accessreviewscheduledefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization access review schedule definition\" }\n ,\"microsoft.authorization/accessreviewscheduledefinitions/instances\": { \"SingularDisplayName\": \"Microsoft.Authorization access review schedule definitions instance\" }\n ,\"microsoft.authorization/accessreviewscheduledefinitions/instances/decisions\": { \"SingularDisplayName\": \"Microsoft.Authorization access review schedule definitions instances decision\" }\n ,\"microsoft.authorization/accessreviewschedulesettings\": { \"SingularDisplayName\": \"Microsoft.Authorization access review schedule setting\" }\n ,\"microsoft.authorization/datapolicymanifests\": { \"SingularDisplayName\": \"Microsoft.Authorization data policy manifest\" }\n ,\"microsoft.authorization/denyassignments\": { \"SingularDisplayName\": \"Microsoft.Authorization deny assignment\" }\n ,\"microsoft.authorization/locks\": { \"SingularDisplayName\": \"Microsoft.Authorization lock\" }\n ,\"microsoft.authorization/policyassignments\": { \"SingularDisplayName\": \"Microsoft.Authorization policy assignment\" }\n ,\"microsoft.authorization/policydefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy definition\" }\n ,\"microsoft.authorization/policydefinitions/versions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy definitions version\" }\n ,\"microsoft.authorization/policyexemptions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy exemption\" }\n ,\"microsoft.authorization/policysetdefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy set definition\" }\n ,\"microsoft.authorization/policysetdefinitions/versions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy set definitions version\" }\n ,\"microsoft.authorization/privatelinkassociations\": { \"SingularDisplayName\": \"Microsoft.Authorization private link association\" }\n ,\"microsoft.authorization/provideroperations\": { \"SingularDisplayName\": \"Microsoft.Authorization provider operation\" }\n ,\"microsoft.authorization/resourcemanagementprivatelinks\": { \"SingularDisplayName\": \"Resource management private link\" }\n ,\"microsoft.authorization/roleassignmentapprovals\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment approval\" }\n ,\"microsoft.authorization/roleassignmentapprovals/stages\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment approvals stage\" }\n ,\"microsoft.authorization/roleassignments\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment\" }\n ,\"microsoft.authorization/roleassignmentscheduleinstances\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment schedule instance\" }\n ,\"microsoft.authorization/roleassignmentschedulerequests\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment schedule request\" }\n ,\"microsoft.authorization/roleassignmentschedules\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment schedule\" }\n ,\"microsoft.authorization/roledefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization role definition\" }\n ,\"microsoft.authorization/roleeligibilityscheduleinstances\": { \"SingularDisplayName\": \"Microsoft.Authorization role eligibility schedule instance\" }\n ,\"microsoft.authorization/roleeligibilityschedulerequests\": { \"SingularDisplayName\": \"Microsoft.Authorization role eligibility schedule request\" }\n ,\"microsoft.authorization/roleeligibilityschedules\": { \"SingularDisplayName\": \"Microsoft.Authorization role eligibility schedule\" }\n ,\"microsoft.authorization/rolemanagementalertconfigurations\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alert configuration\" }\n ,\"microsoft.authorization/rolemanagementalertdefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alert definition\" }\n ,\"microsoft.authorization/rolemanagementalertoperations\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alert operation\" }\n ,\"microsoft.authorization/rolemanagementalerts\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alert\" }\n ,\"microsoft.authorization/rolemanagementalerts/alertincidents\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alerts alert incident\" }\n ,\"microsoft.authorization/rolemanagementpolicies\": { \"SingularDisplayName\": \"Microsoft.Authorization role management policy\" }\n ,\"microsoft.authorization/rolemanagementpolicyassignments\": { \"SingularDisplayName\": \"Microsoft.Authorization role management policy assignment\" }\n ,\"microsoft.automanage/bestpractices\": { \"SingularDisplayName\": \"Microsoft.Automanage best practice\" }\n ,\"microsoft.automanage/bestpractices/versions\": { \"SingularDisplayName\": \"Microsoft.Automanage best practices version\" }\n ,\"microsoft.automanage/configurationprofileassignments\": { \"SingularDisplayName\": \"Microsoft.Automanage configuration profile assignment\" }\n ,\"microsoft.automanage/configurationprofileassignments/reports\": { \"SingularDisplayName\": \"Microsoft.Automanage configuration profile assignments report\" }\n ,\"microsoft.automanage/configurationprofiles\": { \"SingularDisplayName\": \"Microsoft.Automanage configuration profile\" }\n ,\"microsoft.automanage/configurationprofiles/versions\": { \"SingularDisplayName\": \"Microsoft.Automanage configuration profiles version\" }\n ,\"microsoft.automanage/serviceprincipals\": { \"SingularDisplayName\": \"ServicePrincipals\" }\n ,\"microsoft.automation/automationaccounts\": { \"SingularDisplayName\": \"Automation account\" }\n ,\"microsoft.automation/automationaccounts/hybridrunbookworkergroups\": { \"SingularDisplayName\": \"Automation hybrid worker group\" }\n ,\"microsoft.automation/automationaccounts/runbooks\": { \"SingularDisplayName\": \"Automation runbook\" }\n ,\"microsoft.autonomousdevelopmentplatform/accounts\": { \"SingularDisplayName\": \"Microsoft.AutonomousDevelopmentPlatform account\" }\n ,\"microsoft.autonomousdevelopmentplatform/accounts/datapools\": { \"SingularDisplayName\": \"Microsoft.AutonomousDevelopmentPlatform accounts data pool\" }\n ,\"microsoft.autonomousdevelopmentplatform/workspaces\": { \"SingularDisplayName\": \"Microsoft.AutonomousDevelopmentPlatform workspace\" }\n ,\"microsoft.avs/privateclouds\": { \"SingularDisplayName\": \"Azure VMware Solution private cloud\" }\n ,\"microsoft.awsconnector/accessanalyzeranalyzers\": { \"SingularDisplayName\": \"Access Analyzer Analyzer\" }\n ,\"microsoft.awsconnector/acmcertificatesummaries\": { \"SingularDisplayName\": \"ACM Certificate Summary\" }\n ,\"microsoft.awsconnector/apigatewayrestapis\": { \"SingularDisplayName\": \"Api Gateway Rest Api\" }\n ,\"microsoft.awsconnector/apigatewaystages\": { \"SingularDisplayName\": \"Api Gateway Stage\" }\n ,\"microsoft.awsconnector/applicationautoscalingscalabletargets\": { \"SingularDisplayName\": \"Application Auto Scaling Scalable Target\" }\n ,\"microsoft.awsconnector/appsyncgraphqlapis\": { \"SingularDisplayName\": \"App Sync Graphql Api\" }\n ,\"microsoft.awsconnector/autoscalingautoscalinggroups\": { \"SingularDisplayName\": \"Auto Scaling Auto Scaling Group\" }\n ,\"microsoft.awsconnector/cloudformationstacks\": { \"SingularDisplayName\": \"Cloud Formation Stack\" }\n ,\"microsoft.awsconnector/cloudformationstacksets\": { \"SingularDisplayName\": \"Cloud Formation Stack Set\" }\n ,\"microsoft.awsconnector/cloudfrontdistributions\": { \"SingularDisplayName\": \"Cloud Front Distribution\" }\n ,\"microsoft.awsconnector/cloudtrailtrails\": { \"SingularDisplayName\": \"Cloud Trail Trail\" }\n ,\"microsoft.awsconnector/cloudwatchalarms\": { \"SingularDisplayName\": \"Cloud Watch Alarm\" }\n ,\"microsoft.awsconnector/codebuildprojects\": { \"SingularDisplayName\": \"Code Build Project\" }\n ,\"microsoft.awsconnector/codebuildsourcecredentialsinfos\": { \"SingularDisplayName\": \"Code Build Source Credentials Info\" }\n ,\"microsoft.awsconnector/configserviceconfigurationrecorders\": { \"SingularDisplayName\": \"Config Service Configuration Recorder\" }\n ,\"microsoft.awsconnector/configserviceconfigurationrecorderstatuses\": { \"SingularDisplayName\": \"Config Service Configuration Recorder Status\" }\n ,\"microsoft.awsconnector/configservicedeliverychannels\": { \"SingularDisplayName\": \"Config Service Delivery Channel\" }\n ,\"microsoft.awsconnector/databasemigrationservicereplicationinstances\": { \"SingularDisplayName\": \"Database Migration Service Replication Instance\" }\n ,\"microsoft.awsconnector/daxclusters\": { \"SingularDisplayName\": \"DAX Cluster\" }\n ,\"microsoft.awsconnector/dynamodbcontinuousbackupsdescriptions\": { \"SingularDisplayName\": \"Dynamo DB Continuous Backups Description\" }\n ,\"microsoft.awsconnector/dynamodbtables\": { \"SingularDisplayName\": \"Dynamo DB Table\" }\n ,\"microsoft.awsconnector/ec2accountattributes\": { \"SingularDisplayName\": \"EC2 Account Attribute\" }\n ,\"microsoft.awsconnector/ec2addresses\": { \"SingularDisplayName\": \"EC2 Address\" }\n ,\"microsoft.awsconnector/ec2flowlogs\": { \"SingularDisplayName\": \"EC2 Flow Log\" }\n ,\"microsoft.awsconnector/ec2images\": { \"SingularDisplayName\": \"EC2 Image\" }\n ,\"microsoft.awsconnector/ec2instances\": { \"SingularDisplayName\": \"Microsoft.AwsConnector ec2 instance\" }\n ,\"microsoft.awsconnector/ec2instancestatuses\": { \"SingularDisplayName\": \"EC2 Instance Status\" }\n ,\"microsoft.awsconnector/ec2ipams\": { \"SingularDisplayName\": \"EC2 Ipam\" }\n ,\"microsoft.awsconnector/ec2keypairs\": { \"SingularDisplayName\": \"EC2 Key Pair\" }\n ,\"microsoft.awsconnector/ec2networkacls\": { \"SingularDisplayName\": \"EC2 Network Acl\" }\n ,\"microsoft.awsconnector/ec2networkinterfaces\": { \"SingularDisplayName\": \"EC2 Network Interface\" }\n ,\"microsoft.awsconnector/ec2routetables\": { \"SingularDisplayName\": \"EC2 Route Table\" }\n ,\"microsoft.awsconnector/ec2securitygroups\": { \"SingularDisplayName\": \"EC2 Security Group\" }\n ,\"microsoft.awsconnector/ec2snapshots\": { \"SingularDisplayName\": \"EC2 Snapshot\" }\n ,\"microsoft.awsconnector/ec2subnets\": { \"SingularDisplayName\": \"EC2 Subnet\" }\n ,\"microsoft.awsconnector/ec2volumes\": { \"SingularDisplayName\": \"EC2 Volume\" }\n ,\"microsoft.awsconnector/ec2vpcendpoints\": { \"SingularDisplayName\": \"EC2 VPCEndpoint\" }\n ,\"microsoft.awsconnector/ec2vpcpeeringconnections\": { \"SingularDisplayName\": \"EC2 VPCPeering Connection\" }\n ,\"microsoft.awsconnector/ec2vpcs\": { \"SingularDisplayName\": \"EC2 VPC\" }\n ,\"microsoft.awsconnector/ecrimagedetails\": { \"SingularDisplayName\": \"ECR Image Detail\" }\n ,\"microsoft.awsconnector/ecrrepositories\": { \"SingularDisplayName\": \"ECR Repository\" }\n ,\"microsoft.awsconnector/ecsclusters\": { \"SingularDisplayName\": \"ECS Cluster\" }\n ,\"microsoft.awsconnector/ecsservices\": { \"SingularDisplayName\": \"ECS Service\" }\n ,\"microsoft.awsconnector/ecstaskdefinitions\": { \"SingularDisplayName\": \"ECS Task Definition\" }\n ,\"microsoft.awsconnector/efsfilesystems\": { \"SingularDisplayName\": \"EFS File System\" }\n ,\"microsoft.awsconnector/efsmounttargets\": { \"SingularDisplayName\": \"EFS Mount Target\" }\n ,\"microsoft.awsconnector/eksnodegroups\": { \"SingularDisplayName\": \"EKS Nodegroup\" }\n ,\"microsoft.awsconnector/elasticbeanstalkapplications\": { \"SingularDisplayName\": \"Elastic Beanstalk Application\" }\n ,\"microsoft.awsconnector/elasticbeanstalkconfigurationtemplates\": { \"SingularDisplayName\": \"Elastic Beanstalk Configuration Template\" }\n ,\"microsoft.awsconnector/elasticbeanstalkenvironments\": { \"SingularDisplayName\": \"Elastic Beanstalk Environment\" }\n ,\"microsoft.awsconnector/elasticloadbalancingv2listeners\": { \"SingularDisplayName\": \"Elastic Load Balancing V2 Listener\" }\n ,\"microsoft.awsconnector/elasticloadbalancingv2loadbalancers\": { \"SingularDisplayName\": \"Elastic Load Balancing V2 Load Balancer\" }\n ,\"microsoft.awsconnector/elasticloadbalancingv2targetgroups\": { \"SingularDisplayName\": \"Elastic Load Balancing V2 Target Group\" }\n ,\"microsoft.awsconnector/elasticloadbalancingv2targethealthdescriptions\": { \"SingularDisplayName\": \"Elastic Load Balancing v2 Target Health Description\" }\n ,\"microsoft.awsconnector/elasticsearchdomains\": { \"SingularDisplayName\": \"Elasticsearch Domain\" }\n ,\"microsoft.awsconnector/emrclusters\": { \"SingularDisplayName\": \"EMR Cluster\" }\n ,\"microsoft.awsconnector/guarddutydetectors\": { \"SingularDisplayName\": \"Guard Duty Detector\" }\n ,\"microsoft.awsconnector/iamaccesskeylastuseds\": { \"SingularDisplayName\": \"IAM Access Key Last Used\" }\n ,\"microsoft.awsconnector/iamaccesskeymetadata\": { \"SingularDisplayName\": \"IAM Access Key Metadata\" }\n ,\"microsoft.awsconnector/iamgroups\": { \"SingularDisplayName\": \"IAM Group\" }\n ,\"microsoft.awsconnector/iaminstanceprofiles\": { \"SingularDisplayName\": \"IAM Instance Profile\" }\n ,\"microsoft.awsconnector/iammanagedpolicies\": { \"SingularDisplayName\": \"IAM Managed Policy\" }\n ,\"microsoft.awsconnector/iammfadevices\": { \"SingularDisplayName\": \"IAM MFADevice\" }\n ,\"microsoft.awsconnector/iampasswordpolicies\": { \"SingularDisplayName\": \"IAM Password Policy\" }\n ,\"microsoft.awsconnector/iampolicyversions\": { \"SingularDisplayName\": \"IAM Policy Version\" }\n ,\"microsoft.awsconnector/iamroles\": { \"SingularDisplayName\": \"IAM Role\" }\n ,\"microsoft.awsconnector/iamservercertificates\": { \"SingularDisplayName\": \"IAM Server Certificate\" }\n ,\"microsoft.awsconnector/iamuserpolicies\": { \"SingularDisplayName\": \"IAM User Policy\" }\n ,\"microsoft.awsconnector/iamvirtualmfadevices\": { \"SingularDisplayName\": \"IAM Virtual MFADevice\" }\n ,\"microsoft.awsconnector/kmsaliases\": { \"SingularDisplayName\": \"KMS Alias\" }\n ,\"microsoft.awsconnector/kmskeys\": { \"SingularDisplayName\": \"KMS Key\" }\n ,\"microsoft.awsconnector/lambdafunctioncodelocations\": { \"SingularDisplayName\": \"Lambda Function Code Location\" }\n ,\"microsoft.awsconnector/lambdafunctionconfigurations\": { \"SingularDisplayName\": \"Microsoft.AwsConnector lambda function configuration\" }\n ,\"microsoft.awsconnector/lambdafunctions\": { \"SingularDisplayName\": \"Lambda Function\" }\n ,\"microsoft.awsconnector/licensemanagerlicenses\": { \"SingularDisplayName\": \"License Manager License\" }\n ,\"microsoft.awsconnector/lightsailbuckets\": { \"SingularDisplayName\": \"Lightsail Bucket\" }\n ,\"microsoft.awsconnector/lightsailinstances\": { \"SingularDisplayName\": \"Lightsail Instance\" }\n ,\"microsoft.awsconnector/logsloggroups\": { \"SingularDisplayName\": \"Logs Log Group\" }\n ,\"microsoft.awsconnector/logslogstreams\": { \"SingularDisplayName\": \"Logs Log Stream\" }\n ,\"microsoft.awsconnector/logsmetricfilters\": { \"SingularDisplayName\": \"Logs Metric Filter\" }\n ,\"microsoft.awsconnector/logssubscriptionfilters\": { \"SingularDisplayName\": \"Logs Subscription Filter\" }\n ,\"microsoft.awsconnector/macie2jobsummaries\": { \"SingularDisplayName\": \"Macie2 Job Summary\" }\n ,\"microsoft.awsconnector/macieallowlists\": { \"SingularDisplayName\": \"Macie Allow List\" }\n ,\"microsoft.awsconnector/networkfirewallfirewallpolicies\": { \"SingularDisplayName\": \"Network Firewall Firewall Policy\" }\n ,\"microsoft.awsconnector/networkfirewallfirewalls\": { \"SingularDisplayName\": \"Network Firewall Firewall\" }\n ,\"microsoft.awsconnector/networkfirewallrulegroups\": { \"SingularDisplayName\": \"Network Firewall Rule Group\" }\n ,\"microsoft.awsconnector/opensearchdomainstatuses\": { \"SingularDisplayName\": \"Open Search Domain Status\" }\n ,\"microsoft.awsconnector/opensearchservicedomains\": { \"SingularDisplayName\": \"Open Search Service Domain\" }\n ,\"microsoft.awsconnector/organizationsaccounts\": { \"SingularDisplayName\": \"Organizations Account\" }\n ,\"microsoft.awsconnector/organizationsorganizations\": { \"SingularDisplayName\": \"Organizations Organization\" }\n ,\"microsoft.awsconnector/rdsdbclusters\": { \"SingularDisplayName\": \"RDS DBCluster\" }\n ,\"microsoft.awsconnector/rdsdbinstances\": { \"SingularDisplayName\": \"RDS DBInstance\" }\n ,\"microsoft.awsconnector/rdsdbsnapshotattributesresults\": { \"SingularDisplayName\": \"RDS DBSnapshot Attributes Result\" }\n ,\"microsoft.awsconnector/rdsdbsnapshots\": { \"SingularDisplayName\": \"RDS DBSnapshot\" }\n ,\"microsoft.awsconnector/rdseventsubscriptions\": { \"SingularDisplayName\": \"RDS Event Subscription\" }\n ,\"microsoft.awsconnector/rdsexporttasks\": { \"SingularDisplayName\": \"RDS Export Task\" }\n ,\"microsoft.awsconnector/redshiftclusterparametergroups\": { \"SingularDisplayName\": \"Redshift Cluster Parameter Group\" }\n ,\"microsoft.awsconnector/redshiftclusters\": { \"SingularDisplayName\": \"Redshift Cluster\" }\n ,\"microsoft.awsconnector/route53domainsdomainsummaries\": { \"SingularDisplayName\": \"Route 53 Domains Domain Summary\" }\n ,\"microsoft.awsconnector/route53hostedzones\": { \"SingularDisplayName\": \"Route53 Hosted Zone\" }\n ,\"microsoft.awsconnector/route53resourcerecordsets\": { \"SingularDisplayName\": \"Route 53 Resource Record Set\" }\n ,\"microsoft.awsconnector/s3accesscontrolpolicies\": { \"SingularDisplayName\": \"S3 Access Control Policy\" }\n ,\"microsoft.awsconnector/s3accesspoints\": { \"SingularDisplayName\": \"S3 Access Point\" }\n ,\"microsoft.awsconnector/s3bucketpolicies\": { \"SingularDisplayName\": \"S3 Bucket Policy\" }\n ,\"microsoft.awsconnector/s3buckets\": { \"SingularDisplayName\": \"S3 Bucket\" }\n ,\"microsoft.awsconnector/s3controlmultiregionaccesspointpolicydocuments\": { \"SingularDisplayName\": \"S3 Control Multi Region Access Point Policy Document\" }\n ,\"microsoft.awsconnector/sagemakerapps\": { \"SingularDisplayName\": \"Sage Maker App\" }\n ,\"microsoft.awsconnector/sagemakerdevices\": { \"SingularDisplayName\": \"Sage Maker Device\" }\n ,\"microsoft.awsconnector/sagemakerimages\": { \"SingularDisplayName\": \"Sage Maker Image\" }\n ,\"microsoft.awsconnector/sagemakernotebookinstancesummaries\": { \"SingularDisplayName\": \"Sage Maker Notebook Instance Summary\" }\n ,\"microsoft.awsconnector/secretsmanagerresourcepolicies\": { \"SingularDisplayName\": \"Secrets Manager Resource Policy\" }\n ,\"microsoft.awsconnector/secretsmanagersecrets\": { \"SingularDisplayName\": \"Secrets Manager Secret\" }\n ,\"microsoft.awsconnector/snssubscriptions\": { \"SingularDisplayName\": \"SNS Subscription\" }\n ,\"microsoft.awsconnector/snstopics\": { \"SingularDisplayName\": \"SNS Topic\" }\n ,\"microsoft.awsconnector/sqsqueues\": { \"SingularDisplayName\": \"SQS Queue\" }\n ,\"microsoft.awsconnector/ssminstanceinformations\": { \"SingularDisplayName\": \"SSM Instance Information\" }\n ,\"microsoft.awsconnector/ssmparameters\": { \"SingularDisplayName\": \"SSM Parameter\" }\n ,\"microsoft.awsconnector/ssmresourcecompliancesummaryitems\": { \"SingularDisplayName\": \"SSM Resource Compliance Summary Item\" }\n ,\"microsoft.awsconnector/wafv2ipsets\": { \"SingularDisplayName\": \"WAFv2 IPSet\" }\n ,\"microsoft.awsconnector/wafv2loggingconfigurations\": { \"SingularDisplayName\": \"WAFv2 Logging Configuration\" }\n ,\"microsoft.awsconnector/wafv2webaclassociations\": { \"SingularDisplayName\": \"WAFv2 Web ACLAssociation\" }\n ,\"microsoft.awsconnector/wafwebaclsummaries\": { \"SingularDisplayName\": \"WAF Web ACLSummary\" }\n ,\"microsoft.azureactivedirectory/b2cdirectories\": { \"SingularDisplayName\": \"B2C tenant\" }\n ,\"microsoft.azureactivedirectory/ciamdirectories\": { \"SingularDisplayName\": \"External Configuration Tenant\" }\n ,\"microsoft.azureactivedirectory/guestusages\": { \"SingularDisplayName\": \"Guest Usage\" }\n ,\"microsoft.azurearcdata/datacontrollers\": { \"SingularDisplayName\": \"Azure Arc data controller\" }\n ,\"microsoft.azurearcdata/mysqlserver\": { \"SingularDisplayName\": \"MySql Server - Azure Arc\" }\n ,\"microsoft.azurearcdata/postgresinstances\": { \"SingularDisplayName\": \"PostgreSQL server ? Azure Arc\" }\n ,\"microsoft.azurearcdata/postgressqlserver\": { \"SingularDisplayName\": \"PostgresSql Server - Azure Arc\" }\n ,\"microsoft.azurearcdata/sqlmanagedinstances\": { \"SingularDisplayName\": \"SQL managed instance - Azure Arc\" }\n ,\"microsoft.azurearcdata/sqlserveresulicenses\": { \"SingularDisplayName\": \"SQL Server ESU license\" }\n ,\"microsoft.azurearcdata/sqlserverinstances\": { \"SingularDisplayName\": \"SQL Server - Azure Arc\" }\n ,\"microsoft.azurearcdata/sqlserverinstances/databases\": { \"SingularDisplayName\": \"SQL Server database - Azure Arc\" }\n ,\"microsoft.azurearcdata/sqlserverlicenses\": { \"SingularDisplayName\": \"SQL Server License\" }\n ,\"microsoft.azurebusinesscontinuity/deletedunifiedprotecteditems\": { \"SingularDisplayName\": \"Microsoft.AzureBusinessContinuity deleted unified protected item\" }\n ,\"microsoft.azurebusinesscontinuity/unifiedprotecteditems\": { \"SingularDisplayName\": \"Microsoft.AzureBusinessContinuity unified protected item\" }\n ,\"microsoft.azurecis/aadapplications\": { \"SingularDisplayName\": \"Microsoft.AzureCis AAD application\" }\n ,\"microsoft.azurecis/addressrecords\": { \"SingularDisplayName\": \"Microsoft.AzureCis address record\" }\n ,\"microsoft.azurecis/autopilotenvironments\": { \"SingularDisplayName\": \"Microsoft.AzureCis autopilot environment\" }\n ,\"microsoft.azurecis/autopilotmachinefunctions\": { \"SingularDisplayName\": \"Microsoft.AzureCis autopilot machine function\" }\n ,\"microsoft.azurecis/autopilotsoftwareloadbalancevirtualips\": { \"SingularDisplayName\": \"Microsoft.AzureCis auto pilot software load balance virtual IP\" }\n ,\"microsoft.azurecis/azcopies\": { \"SingularDisplayName\": \"Microsoft.AzureCis az copy\" }\n ,\"microsoft.azurecis/canonicalnamerecords\": { \"SingularDisplayName\": \"Microsoft.AzureCis canonical name record\" }\n ,\"microsoft.azurecis/dsmsallowlists\": { \"SingularDisplayName\": \"Microsoft.AzureCis ds msallowlist\" }\n ,\"microsoft.azurecis/dsmscertificates\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsms certificate\" }\n ,\"microsoft.azurecis/dsmsrootfolders\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsms root folder\" }\n ,\"microsoft.azurecis/dstsapplications\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsts application\" }\n ,\"microsoft.azurecis/dstsserviceaccounts\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsts service account\" }\n ,\"microsoft.azurecis/dstsserviceclientidentities\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsts service client identity\" }\n ,\"microsoft.azurecis/genericgenevaactions\": { \"SingularDisplayName\": \"Microsoft.AzureCis generic geneva action\" }\n ,\"microsoft.azurecis/plannedquotas\": { \"SingularDisplayName\": \"Microsoft.AzureCis planned quota\" }\n ,\"microsoft.azurecis/pointerrecords\": { \"SingularDisplayName\": \"Microsoft.AzureCis pointer record\" }\n ,\"microsoft.azurecis/publishconfigvalues\": { \"SingularDisplayName\": \"Microsoft.AzureCis publish config value\" }\n ,\"microsoft.azurecis/pushagentv2accounts\": { \"SingularDisplayName\": \"Microsoft.AzureCis push agent v2 account\" }\n ,\"microsoft.azurecis/servicerecords\": { \"SingularDisplayName\": \"Microsoft.AzureCis service record\" }\n ,\"microsoft.azurecis/sharedconfigvalues\": { \"SingularDisplayName\": \"Microsoft.AzureCis shared config value\" }\n ,\"microsoft.azurecloudmetadata/clouds\": { \"SingularDisplayName\": \"Microsoft.AzureCloudMetadata cloud\" }\n ,\"microsoft.azurecloudmetadata/clouds/geographies\": { \"SingularDisplayName\": \"Microsoft.AzureCloudMetadata clouds geography\" }\n ,\"microsoft.azurecloudmetadata/clouds/geographies/regions\": { \"SingularDisplayName\": \"Microsoft.AzureCloudMetadata clouds geographies region\" }\n ,\"microsoft.azuredatatransfer/connections\": { \"SingularDisplayName\": \"Connection\" }\n ,\"microsoft.azuredatatransfer/connections/flows\": { \"SingularDisplayName\": \"Flow\" }\n ,\"microsoft.azuredatatransfer/pipelines\": { \"SingularDisplayName\": \"Pipeline\" }\n ,\"microsoft.azurefleet/fleets\": { \"SingularDisplayName\": \"Compute Fleet\" }\n ,\"microsoft.azurefleet/fleetscomputehub\": { \"SingularDisplayName\": \"Compute Fleet\" }\n ,\"microsoft.azureimagetestingforlinux/jobs\": { \"SingularDisplayName\": \"Microsoft.AzureImageTestingForLinux job\" }\n ,\"microsoft.azureimagetestingforlinux/jobtemplates\": { \"SingularDisplayName\": \"Microsoft.AzureImageTestingForLinux job template\" }\n ,\"microsoft.azurelargeinstance/azurelargeinstances\": { \"SingularDisplayName\": \"Azure Large Instance\" }\n ,\"microsoft.azurelargeinstance/azurelargestorageinstances\": { \"SingularDisplayName\": \"Microsoft.AzureLargeInstance Azure large storage instance\" }\n ,\"microsoft.azurepercept/accounts\": { \"SingularDisplayName\": \"Microsoft.AzurePercept account\" }\n ,\"microsoft.azurepercept/accounts/devices\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts device\" }\n ,\"microsoft.azurepercept/accounts/devices/sensors\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts devices sensor\" }\n ,\"microsoft.azurepercept/accounts/sensors\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts sensor\" }\n ,\"microsoft.azurepercept/accounts/solutioninstances\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts solutioninstance\" }\n ,\"microsoft.azurepercept/accounts/solutions\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts solution\" }\n ,\"microsoft.azurepercept/accounts/targets\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts target\" }\n ,\"microsoft.azureplaywrightservice/accounts\": { \"SingularDisplayName\": \"Playwright Testing\" }\n ,\"microsoft.azurescan/scanningaccounts\": { \"SingularDisplayName\": \"ESRP Scan\" }\n ,\"microsoft.azuresphere/catalogs\": { \"SingularDisplayName\": \"Azure Sphere Catalog\" }\n ,\"microsoft.azurespherev2/catalogs\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalog\" }\n ,\"microsoft.azurespherev2/catalogs/artifacts\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs artifact\" }\n ,\"microsoft.azurespherev2/catalogs/certificates\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs certificate\" }\n ,\"microsoft.azurespherev2/catalogs/deviceregistrations\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs device registration\" }\n ,\"microsoft.azurespherev2/catalogs/provisioningpackages\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs provisioning package\" }\n ,\"microsoft.azurespherev2/catalogs/syndicationchannels\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs syndication channel\" }\n ,\"microsoft.azurespherev2/catalogs/syndicationchannels/deployments\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs syndication channels deployment\" }\n ,\"microsoft.azurespherev2/catalogs/updatepackages\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs update package\" }\n ,\"microsoft.azurestack/cloudmanifestfiles\": { \"SingularDisplayName\": \"Microsoft.AzureStack cloud manifest file\" }\n ,\"microsoft.azurestack/linkedsubscriptions\": { \"SingularDisplayName\": \"Microsoft.AzureStack linked subscription\" }\n ,\"microsoft.azurestack/registrations\": { \"SingularDisplayName\": \"Microsoft.AzureStack registration\" }\n ,\"microsoft.azurestack/registrations/customersubscriptions\": { \"SingularDisplayName\": \"Microsoft.AzureStack registrations customer subscription\" }\n ,\"microsoft.azurestack/registrations/products\": { \"SingularDisplayName\": \"Microsoft.AzureStack registrations product\" }\n ,\"microsoft.azurestackhci/clusters\": { \"SingularDisplayName\": \"Azure Local\" }\n ,\"microsoft.azurestackhci/clusters/updates/updateruns\": { \"SingularDisplayName\": \"Azure Local\" }\n ,\"microsoft.azurestackhci/clusters/updatesummaries\": { \"SingularDisplayName\": \"Azure Local\" }\n ,\"microsoft.azurestackhci/devicepools\": { \"SingularDisplayName\": \"Azure Stack\" }\n ,\"microsoft.azurestackhci/edgedevices\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI edge device\" }\n ,\"microsoft.azurestackhci/edgedevices/jobs\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI edge devices job\" }\n ,\"microsoft.azurestackhci/edgemachines\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI edge machine\" }\n ,\"microsoft.azurestackhci/edgemachines/jobs\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI edge machines job\" }\n ,\"microsoft.azurestackhci/edgenodepools\": { \"SingularDisplayName\": \"Azure Stack\" }\n ,\"microsoft.azurestackhci/galleryimages\": { \"SingularDisplayName\": \"Azure Local Gallery image\" }\n ,\"microsoft.azurestackhci/logicalnetworks\": { \"SingularDisplayName\": \"Azure Local Logical network\" }\n ,\"microsoft.azurestackhci/marketplacegalleryimages\": { \"SingularDisplayName\": \"Azure Local Marketplace Gallery image\" }\n ,\"microsoft.azurestackhci/networkinterfaces\": { \"SingularDisplayName\": \"Azure Local VM Network Interface\" }\n ,\"microsoft.azurestackhci/networksecuritygroups\": { \"SingularDisplayName\": \"Azure Local Network Security Group\" }\n ,\"microsoft.azurestackhci/networksecuritygroups/securityrules\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI network security groups security rule\" }\n ,\"microsoft.azurestackhci/storagecontainers\": { \"SingularDisplayName\": \"Azure Local Storage path\" }\n ,\"microsoft.azurestackhci/virtualharddisks\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual hard disk\" }\n ,\"microsoft.azurestackhci/virtualmachineinstances\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual machine instance\" }\n ,\"microsoft.azurestackhci/virtualmachineinstances/guestagents\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual machine instances guest agent\" }\n ,\"microsoft.azurestackhci/virtualmachineinstances/hybrididentitymetadata\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual machine instances hybrid identity metadata\" }\n ,\"microsoft.azurestackhci/virtualmachines\": { \"SingularDisplayName\": \"Azure Local virtual machine - Azure Arc\" }\n ,\"microsoft.azurestackhci/virtualnetworks\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual network\" }\n ,\"microsoft.backupsolutions/vmwareapplications\": { \"SingularDisplayName\": \"Microsoft.BackupSolutions vmware application\" }\n ,\"microsoft.bakeryhybrid/pies\": { \"SingularDisplayName\": \"Microsoft.BakeryHybrid py\" }\n ,\"microsoft.bakeryhybrid/pies/nestedresourcetype\": { \"SingularDisplayName\": \"Microsoft.BakeryHybrid pies nested resource type\" }\n ,\"microsoft.baremetal/baremetalconnections\": { \"SingularDisplayName\": \"Microsoft.BareMetal bare metal connection\" }\n ,\"microsoft.baremetal/crayservers\": { \"SingularDisplayName\": \"Cray Server\" }\n ,\"microsoft.baremetal/monitoringservers\": { \"SingularDisplayName\": \"Monitoring Server\" }\n ,\"microsoft.baremetal/peeringsettings\": { \"SingularDisplayName\": \"Microsoft.BareMetal peering setting\" }\n ,\"microsoft.baremetalinfrastructure/baremetalinstances\": { \"SingularDisplayName\": \"BareMetal Instance\" }\n ,\"microsoft.baremetalinfrastructure/baremetalstorageinstances\": { \"SingularDisplayName\": \"Microsoft.BareMetalInfrastructure bare metal storage instance\" }\n ,\"microsoft.batch/batchaccounts\": { \"SingularDisplayName\": \"Batch account\" }\n ,\"microsoft.billing/billingaccounts\": { \"SingularDisplayName\": \"Microsoft.Billing billing account\" }\n ,\"microsoft.billing/billingaccounts/agreements\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts agreement\" }\n ,\"microsoft.billing/billingaccounts/associatedtenants\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts associated tenant\" }\n ,\"microsoft.billing/billingaccounts/availablebalance\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts available balance\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profile\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/availablebalance\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles available balance\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles billing role definition\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles billing subscription\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/customers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles customer\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/customers/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles customers billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/customers/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles customers billing role definition\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/customers/transfers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles customers transfer\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/instructions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles instruction\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoices\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice section\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections billing role definition\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections billing subscription\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/products\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections product\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/transfers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections transfer\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/paymentmethodlinks\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles payment method link\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/policies\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles policy\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/transactions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles transaction\" }\n ,\"microsoft.billing/billingaccounts/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing role definition\" }\n ,\"microsoft.billing/billingaccounts/billingsubscriptionaliases\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing subscription aliase\" }\n ,\"microsoft.billing/billingaccounts/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing subscription\" }\n ,\"microsoft.billing/billingaccounts/billingsubscriptions/invoices\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing subscriptions invoice\" }\n ,\"microsoft.billing/billingaccounts/customers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts customer\" }\n ,\"microsoft.billing/billingaccounts/customers/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts customers billing subscription\" }\n ,\"microsoft.billing/billingaccounts/customers/policies\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts customers policy\" }\n ,\"microsoft.billing/billingaccounts/customers/products\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts customers product\" }\n ,\"microsoft.billing/billingaccounts/departments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts department\" }\n ,\"microsoft.billing/billingaccounts/departments/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts departments billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/departments/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts departments billing role definition\" }\n ,\"microsoft.billing/billingaccounts/departments/enrollmentaccounts\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts departments enrollment account\" }\n ,\"microsoft.billing/billingaccounts/enrollmentaccounts\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts enrollment account\" }\n ,\"microsoft.billing/billingaccounts/enrollmentaccounts/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts enrollment accounts billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/enrollmentaccounts/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts enrollment accounts billing role definition\" }\n ,\"microsoft.billing/billingaccounts/incentiveschedules\": { \"SingularDisplayName\": \"Incentive Schedule\" }\n ,\"microsoft.billing/billingaccounts/incentiveschedules/milestones\": { \"SingularDisplayName\": \"Milestone\" }\n ,\"microsoft.billing/billingaccounts/invoices\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice\" }\n ,\"microsoft.billing/billingaccounts/invoicesections\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice section\" }\n ,\"microsoft.billing/billingaccounts/invoicesections/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice sections billing subscription\" }\n ,\"microsoft.billing/billingaccounts/invoicesections/products\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice sections product\" }\n ,\"microsoft.billing/billingaccounts/invoicesections/transfers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice sections transfer\" }\n ,\"microsoft.billing/billingaccounts/lineofcredit\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts line of credit\" }\n ,\"microsoft.billing/billingaccounts/migrations\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts migration\" }\n ,\"microsoft.billing/billingaccounts/paymentmethods\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts payment method\" }\n ,\"microsoft.billing/billingaccounts/policies\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts policy\" }\n ,\"microsoft.billing/billingaccounts/products\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts product\" }\n ,\"microsoft.billing/billingaccounts/reservationorders\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts reservation order\" }\n ,\"microsoft.billing/billingaccounts/reservationorders/reservations\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts reservation orders reservation\" }\n ,\"microsoft.billing/billingaccounts/savingsplanorders\": { \"SingularDisplayName\": \"Savings plan order\" }\n ,\"microsoft.billing/billingaccounts/savingsplanorders/savingsplans\": { \"SingularDisplayName\": \"Savings plan\" }\n ,\"microsoft.billing/billingperiods\": { \"SingularDisplayName\": \"Microsoft.Billing billing period\" }\n ,\"microsoft.billing/billingproperty\": { \"SingularDisplayName\": \"Microsoft.Billing billing property\" }\n ,\"microsoft.billing/billingrequests\": { \"SingularDisplayName\": \"Microsoft.Billing billing request\" }\n ,\"microsoft.billing/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing role assignment\" }\n ,\"microsoft.billing/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing role definition\" }\n ,\"microsoft.billing/enrollmentaccounts\": { \"SingularDisplayName\": \"Microsoft.Billing enrollment account\" }\n ,\"microsoft.billing/paymentmethods\": { \"SingularDisplayName\": \"Microsoft.Billing payment method\" }\n ,\"microsoft.billing/policies\": { \"SingularDisplayName\": \"Microsoft.Billing policy\" }\n ,\"microsoft.billing/promotions\": { \"SingularDisplayName\": \"Microsoft.Billing promotion\" }\n ,\"microsoft.billing/transfers\": { \"SingularDisplayName\": \"Microsoft.Billing transfer\" }\n ,\"microsoft.billingbenefits/credits\": { \"SingularDisplayName\": \"Credit\" }\n ,\"microsoft.billingbenefits/discounts\": { \"SingularDisplayName\": \"Discount\" }\n ,\"microsoft.billingbenefits/incentiveschedules\": { \"SingularDisplayName\": \"Incentive Schedule\" }\n ,\"microsoft.billingbenefits/incentiveschedules/milestones\": { \"SingularDisplayName\": \"Milestone\" }\n ,\"microsoft.billingbenefits/maccs\": { \"SingularDisplayName\": \"Microsoft Azure Consumption Commitment\" }\n ,\"microsoft.billingbenefits/reservationorderaliases\": { \"SingularDisplayName\": \"Microsoft.BillingBenefits reservation order aliase\" }\n ,\"microsoft.billingbenefits/savingsplanorderaliases\": { \"SingularDisplayName\": \"Microsoft.BillingBenefits savings plan order aliase\" }\n ,\"microsoft.billingbenefits/savingsplanorders\": { \"SingularDisplayName\": \"Savings plan order\" }\n ,\"microsoft.billingbenefits/savingsplanorders/savingsplans\": { \"SingularDisplayName\": \"Savings plan\" }\n ,\"microsoft.bing/accounts\": { \"SingularDisplayName\": \"Bing Resource\" }\n ,\"microsoft.blockchain/blockchainmembers\": { \"SingularDisplayName\": \"Microsoft.Blockchain blockchain member\" }\n ,\"microsoft.blockchain/blockchainmembers/transactionnodes\": { \"SingularDisplayName\": \"Microsoft.Blockchain blockchain members transaction node\" }\n ,\"microsoft.blockchaintokens/tokenservices\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token service\" }\n ,\"microsoft.blockchaintokens/tokenservices/blockchainnetworks\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token services blockchain network\" }\n ,\"microsoft.blockchaintokens/tokenservices/groups\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token services group\" }\n ,\"microsoft.blockchaintokens/tokenservices/groups/accounts\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token services groups account\" }\n ,\"microsoft.blockchaintokens/tokenservices/tokentemplates\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token services token template\" }\n ,\"microsoft.bluefin/instances\": { \"SingularDisplayName\": \"Microsoft.Bluefin instance\" }\n ,\"microsoft.bluefin/instances/datasets\": { \"SingularDisplayName\": \"Microsoft.Bluefin instances dataset\" }\n ,\"microsoft.bluefin/instances/pipelines\": { \"SingularDisplayName\": \"Microsoft.Bluefin instances pipeline\" }\n ,\"microsoft.blueprint/blueprintassignments\": { \"SingularDisplayName\": \"Microsoft.Blueprint blueprint assignment\" }\n ,\"microsoft.blueprint/blueprints\": { \"SingularDisplayName\": \"Microsoft.Blueprint blueprint\" }\n ,\"microsoft.blueprint/blueprints/artifacts\": { \"SingularDisplayName\": \"Microsoft.Blueprint blueprints artifact\" }\n ,\"microsoft.blueprint/blueprints/versions\": { \"SingularDisplayName\": \"Microsoft.Blueprint blueprints version\" }\n ,\"microsoft.botservice/botservices\": { \"SingularDisplayName\": \"Bot Service\" }\n ,\"microsoft.cache/redis\": { \"SingularDisplayName\": \"Redis cache\" }\n ,\"microsoft.cache/redisenterprise\": { \"SingularDisplayName\": \"Azure Managed Redis\" }\n ,\"microsoft.cache/redisenterprise/databases\": { \"SingularDisplayName\": \"Redis Enterprise database\" }\n ,\"microsoft.capacity/reservationorders\": { \"SingularDisplayName\": \"Reservation order\" }\n ,\"microsoft.capacity/reservationorders/reservations\": { \"SingularDisplayName\": \"Reservation\" }\n ,\"microsoft.cascade/sites\": { \"SingularDisplayName\": \"Microsoft.Cascade site\" }\n ,\"microsoft.cdn/cdnwebapplicationfirewallpolicies\": { \"SingularDisplayName\": \"Content Delivery Network WAF policy\" }\n ,\"microsoft.cdn/edgeactions\": { \"SingularDisplayName\": \"Edge Action\" }\n ,\"microsoft.cdn/profiles\": { \"SingularDisplayName\": \"Front Door and CDN profile\" }\n ,\"microsoft.cdn/profiles/afdendpoints\": { \"SingularDisplayName\": \"Endpoint\" }\n ,\"microsoft.cdn/profiles/afdendpoints/routes\": { \"SingularDisplayName\": \"Route\" }\n ,\"microsoft.cdn/profiles/customdomains\": { \"SingularDisplayName\": \"Custom domain\" }\n ,\"microsoft.cdn/profiles/endpoints\": { \"SingularDisplayName\": \"CDN endpoint\" }\n ,\"microsoft.cdn/profiles/endpoints/customdomains\": { \"SingularDisplayName\": \"CDN custom domain\" }\n ,\"microsoft.cdn/profiles/endpoints/origins\": { \"SingularDisplayName\": \"CDN origin\" }\n ,\"microsoft.cdn/profiles/origingroups\": { \"SingularDisplayName\": \"Origin group\" }\n ,\"microsoft.cdn/profiles/origingroups/origins\": { \"SingularDisplayName\": \"Origin\" }\n ,\"microsoft.cdn/profiles/rulesets\": { \"SingularDisplayName\": \"Rule set\" }\n ,\"microsoft.cdn/profiles/rulesets/rules\": { \"SingularDisplayName\": \"Rule\" }\n ,\"microsoft.cdn/profiles/secrets\": { \"SingularDisplayName\": \"Secret\" }\n ,\"microsoft.cdn/profiles/securitypolicies\": { \"SingularDisplayName\": \"Security policy\" }\n ,\"microsoft.certificateregistration/certificateorders\": { \"SingularDisplayName\": \"App Service certificate\" }\n ,\"microsoft.certify/testsuites\": { \"SingularDisplayName\": \"Microsoft.Certify test suite\" }\n ,\"microsoft.certify/validationjobs\": { \"SingularDisplayName\": \"Microsoft.Certify validation job\" }\n ,\"microsoft.changeanalysis/profile\": { \"SingularDisplayName\": \"Microsoft.ChangeAnalysis profile\" }\n ,\"microsoft.changesafety/changestates\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety change state\" }\n ,\"microsoft.changesafety/changestates/stageprogressions\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety change states stage progression\" }\n ,\"microsoft.changesafety/stagemaps\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety stage map\" }\n ,\"microsoft.changesafety/validations\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety validation\" }\n ,\"microsoft.changesafety/validators\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety validator\" }\n ,\"microsoft.changesafety/validators/versions\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety validators version\" }\n ,\"microsoft.chaos/experiments\": { \"SingularDisplayName\": \"Chaos Experiment\" }\n ,\"microsoft.chaos/privateaccesses\": { \"SingularDisplayName\": \"Agent Private Access\" }\n ,\"microsoft.chaos/targets\": { \"SingularDisplayName\": \"Microsoft.Chaos target\" }\n ,\"microsoft.chaos/targets/capabilities\": { \"SingularDisplayName\": \"Microsoft.Chaos targets capability\" }\n ,\"microsoft.classiccompute/domainnames\": { \"SingularDisplayName\": \"Cloud service (classic)\" }\n ,\"microsoft.classiccompute/domainnames/slots/roles\": { \"SingularDisplayName\": \"Cloud service role (classic)\" }\n ,\"microsoft.classiccompute/virtualmachines\": { \"SingularDisplayName\": \"Virtual machine (classic)\" }\n ,\"microsoft.classicnetwork/networksecuritygroups\": { \"SingularDisplayName\": \"Network security group (classic)\" }\n ,\"microsoft.classicnetwork/reservedips\": { \"SingularDisplayName\": \"Reserved IP address (classic)\" }\n ,\"microsoft.classicnetwork/virtualnetworks\": { \"SingularDisplayName\": \"Virtual network (classic)\" }\n })[tolower(id)]\n}\n", "$fxv#1": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n.create-or-alter function \nwith (docstring = 'Return details about the specified ID.', folder = 'OpenData/Internal')\n_resource_type_2(id: string) {\n dynamic({\n \"microsoft.classicstorage/storageaccounts\": { \"SingularDisplayName\": \"Storage account (classic)\" }\n ,\"microsoft.classicstorage/storageaccounts/disks\": { \"SingularDisplayName\": \"Disk (classic)\" }\n ,\"microsoft.classicstorage/storageaccounts/osimages\": { \"SingularDisplayName\": \"OS image (classic)\" }\n ,\"microsoft.classicstorage/storageaccounts/vmimages\": { \"SingularDisplayName\": \"VM image (classic)\" }\n ,\"microsoft.cleanroom/cleanrooms\": { \"SingularDisplayName\": \"Microsoft.CleanRoom cleanroom\" }\n ,\"microsoft.cleanroom/collaborations\": { \"SingularDisplayName\": \"Microsoft.CleanRoom collaboration\" }\n ,\"microsoft.cleanroom/collaborations/contracts\": { \"SingularDisplayName\": \"Microsoft.CleanRoom collaborations contract\" }\n ,\"microsoft.cleanroom/consortiums\": { \"SingularDisplayName\": \"Microsoft.CleanRoom consortium\" }\n ,\"microsoft.cleanroom/microservices\": { \"SingularDisplayName\": \"Microsoft.CleanRoom microservice\" }\n ,\"microsoft.cloud/hubs\": { \"SingularDisplayName\": \"FinOps hub\" }\n ,\"microsoft.clouddeviceplatform/delegatedidentities\": { \"SingularDisplayName\": \"Microsoft.CloudDevicePlatform delegated identity\" }\n ,\"microsoft.cloudhealth/healthmodels\": { \"SingularDisplayName\": \"Health Model\" }\n ,\"microsoft.cloudtest/accounts\": { \"SingularDisplayName\": \"CloudTest Account\" }\n ,\"microsoft.cloudtest/buildcaches\": { \"SingularDisplayName\": \"1ES Build Cache\" }\n ,\"microsoft.cloudtest/hostedpools\": { \"SingularDisplayName\": \"1ES Hosted Pool\" }\n ,\"microsoft.cloudtest/images\": { \"SingularDisplayName\": \"1ES Image\" }\n ,\"microsoft.cloudtest/pools\": { \"SingularDisplayName\": \"CloudTest Pool\" }\n ,\"microsoft.clusterstor/nodes\": { \"SingularDisplayName\": \"ClusterStor\" }\n ,\"microsoft.codesigning/codesigningaccounts\": { \"SingularDisplayName\": \"Trusted Signing Account\" }\n ,\"microsoft.codespaces/plans\": { \"SingularDisplayName\": \"Microsoft.Codespaces plan\" }\n ,\"microsoft.cognitiveservices/accounts\": { \"SingularDisplayName\": \"Azure AI Foundry\" }\n ,\"microsoft.cognitiveservices/accounts/projects\": { \"SingularDisplayName\": \"Azure AI Foundry project\" }\n ,\"microsoft.cognitiveservices/commitmentplans\": { \"SingularDisplayName\": \"Microsoft.CognitiveServices commitment plan\" }\n ,\"microsoft.cognitiveservices/commitmentplans/accountassociations\": { \"SingularDisplayName\": \"Microsoft.CognitiveServices commitment plans account association\" }\n ,\"microsoft.communication/communicationservices\": { \"SingularDisplayName\": \"Communication Service\" }\n ,\"microsoft.communication/emailservices\": { \"SingularDisplayName\": \"Email Communication Service\" }\n ,\"microsoft.communication/emailservices/domains\": { \"SingularDisplayName\": \"Email Communication Services Domain\" }\n ,\"microsoft.community/communitytrainings\": { \"SingularDisplayName\": \"Community Training\" }\n ,\"microsoft.compositesolutions/compositesolutiondefinitions\": { \"SingularDisplayName\": \"Microsoft.CompositeSolutions composite solution definition\" }\n ,\"microsoft.compositesolutions/compositesolutions\": { \"SingularDisplayName\": \"Microsoft.CompositeSolutions composite solution\" }\n ,\"microsoft.compute/availabilitysets\": { \"SingularDisplayName\": \"Availability set\" }\n ,\"microsoft.compute/capacityreservationgroups\": { \"SingularDisplayName\": \"Capacity Reservation Group\" }\n ,\"microsoft.compute/capacityreservationgroups/capacityreservations\": { \"SingularDisplayName\": \"Capacity reservation\" }\n ,\"microsoft.compute/capacityreservationgroupscomputehub\": { \"SingularDisplayName\": \"Capacity Reservation Group\" }\n ,\"microsoft.compute/cloudservices\": { \"SingularDisplayName\": \"Cloud service (extended support)\" }\n ,\"microsoft.compute/computefleetinstances\": { \"SingularDisplayName\": \"Instance\" }\n ,\"microsoft.compute/computefleetscalesets\": { \"SingularDisplayName\": \"Virtual machine scale set\" }\n ,\"microsoft.compute/diskaccesses\": { \"SingularDisplayName\": \"Disk Access\" }\n ,\"microsoft.compute/diskencryptionsets\": { \"SingularDisplayName\": \"Disk Encryption Set\" }\n ,\"microsoft.compute/disks\": { \"SingularDisplayName\": \"Disk\" }\n ,\"microsoft.compute/galleries\": { \"SingularDisplayName\": \"Azure compute gallery\" }\n ,\"microsoft.compute/galleries/applications\": { \"SingularDisplayName\": \"VM application definition\" }\n ,\"microsoft.compute/galleries/applications/versions\": { \"SingularDisplayName\": \"VM application version\" }\n ,\"microsoft.compute/galleries/images\": { \"SingularDisplayName\": \"VM image definition\" }\n ,\"microsoft.compute/galleries/images/versions\": { \"SingularDisplayName\": \"VM image version\" }\n ,\"microsoft.compute/galleries/imagescomputehub\": { \"SingularDisplayName\": \"VM image definition\" }\n ,\"microsoft.compute/hostgroups\": { \"SingularDisplayName\": \"Host group\" }\n ,\"microsoft.compute/hostgroups/hosts\": { \"SingularDisplayName\": \"Host\" }\n ,\"microsoft.compute/hostgroupscomputehub\": { \"SingularDisplayName\": \"Host group\" }\n ,\"microsoft.compute/images\": { \"SingularDisplayName\": \"Image\" }\n ,\"microsoft.compute/imagescomputehub\": { \"SingularDisplayName\": \"Image\" }\n ,\"microsoft.compute/locations/communitygalleries/images\": { \"SingularDisplayName\": \"Community image\" }\n ,\"microsoft.compute/locations/communitygalleries/imagescomputehub\": { \"SingularDisplayName\": \"Community image\" }\n ,\"microsoft.compute/proximityplacementgroups\": { \"SingularDisplayName\": \"Proximity placement group\" }\n ,\"microsoft.compute/proximityplacementgroupscomputehub\": { \"SingularDisplayName\": \"Proximity placement group\" }\n ,\"microsoft.compute/restorepointcollections\": { \"SingularDisplayName\": \"Restore Point Collection\" }\n ,\"microsoft.compute/restorepointcollections/restorepoints\": { \"SingularDisplayName\": \"Restore Point\" }\n ,\"microsoft.compute/snapshots\": { \"SingularDisplayName\": \"Snapshot\" }\n ,\"microsoft.compute/sshpublickeys\": { \"SingularDisplayName\": \"SSH key\" }\n ,\"microsoft.compute/standbypoolinstance\": { \"SingularDisplayName\": \"Standby pool\" }\n ,\"microsoft.compute/virtualmachinecomputehub\": { \"SingularDisplayName\": \"Virtual machine\" }\n ,\"microsoft.compute/virtualmachineflexinstances\": { \"SingularDisplayName\": \"Instance\" }\n ,\"microsoft.compute/virtualmachines\": { \"SingularDisplayName\": \"Virtual machine\" }\n ,\"microsoft.compute/virtualmachines/providers/guestconfigurationassignments\": { \"SingularDisplayName\": \"Guest Assignment\" }\n ,\"microsoft.compute/virtualmachinescalesets\": { \"SingularDisplayName\": \"Virtual machine scale set\" }\n ,\"microsoft.compute/virtualmachinescalesets/providers/guestconfigurationassignments\": { \"SingularDisplayName\": \"Guest Assignment\" }\n ,\"microsoft.compute/virtualmachinescalesets/virtualmachines\": { \"SingularDisplayName\": \"Virtual machine scale set instance\" }\n ,\"microsoft.compute/virtualmachinescalesets/virtualmachines/networkinterfaces/ipconfigurations/publicipaddresses\": { \"SingularDisplayName\": \"Public IP address\" }\n ,\"microsoft.compute/virtualmachinescalesetscomputehub\": { \"SingularDisplayName\": \"Virtual machine scale set\" }\n ,\"microsoft.computehub/advisorcost\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/advisoroperationalexcellence\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/advisorperformance\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/advisorreliability\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/advisorsecurity\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/all\": { \"SingularDisplayName\": \"All resources\" }\n ,\"microsoft.computehub/backup\": { \"SingularDisplayName\": \"Backup job\" }\n ,\"microsoft.computehub/computehubmain\": { \"SingularDisplayName\": \"Compute infrastructure\" }\n ,\"microsoft.computehub/healthevents\": { \"SingularDisplayName\": \"Health events\" }\n ,\"microsoft.computehub/linuxostype\": { \"SingularDisplayName\": \"Linux OS\" }\n ,\"microsoft.computehub/microsoftdefenderfreetrialsubscription\": { \"SingularDisplayName\": \"Microsoft defender\" }\n ,\"microsoft.computehub/microsoftdefenderstandardsubscription\": { \"SingularDisplayName\": \"Microsoft defender\" }\n ,\"microsoft.computehub/outages\": { \"SingularDisplayName\": \"Outages\" }\n ,\"microsoft.computehub/powerstatedeallocated\": { \"SingularDisplayName\": \"Power states\" }\n ,\"microsoft.computehub/powerstaterunning\": { \"SingularDisplayName\": \"Power states\" }\n ,\"microsoft.computehub/powerstatestopped\": { \"SingularDisplayName\": \"Power states\" }\n ,\"microsoft.computehub/provisioningstatefailedresources\": { \"SingularDisplayName\": \"Provisioning states\" }\n ,\"microsoft.computehub/provisioningstatesucceededresources\": { \"SingularDisplayName\": \"Provisioning states\" }\n ,\"microsoft.computehub/windowsostype\": { \"SingularDisplayName\": \"Windows OS\" }\n ,\"microsoft.computeschedule/autoactions\": { \"SingularDisplayName\": \"Automatic Action\" }\n ,\"microsoft.computeschedule/autoactions/occurrences\": { \"SingularDisplayName\": \"Microsoft.ComputeSchedule auto actions occurrence\" }\n ,\"microsoft.confidentialledger/ledgers\": { \"SingularDisplayName\": \"Confidential Ledger\" }\n ,\"microsoft.confidentialledger/managedccfs\": { \"SingularDisplayName\": \"Managed CCF App\" }\n ,\"microsoft.confluent/agreements\": { \"SingularDisplayName\": \"Microsoft.Confluent agreement\" }\n ,\"microsoft.confluent/organizations\": { \"SingularDisplayName\": \"Confluent organization\" }\n ,\"microsoft.connectedcache/cachenodes\": { \"SingularDisplayName\": \"Connected Cache for ISP\" }\n ,\"microsoft.connectedcache/enterprisecustomers\": { \"SingularDisplayName\": \"Connected Cache for Enterprise & Education\" }\n ,\"microsoft.connectedcache/enterprisemcccustomers\": { \"SingularDisplayName\": \"Connected Cache for Enterprise & Education\" }\n ,\"microsoft.connectedcache/enterprisemcccustomers/enterprisemcccachenodes\": { \"SingularDisplayName\": \"MCC CacheNode for Enterprise\" }\n ,\"microsoft.connectedcache/ispcustomers\": { \"SingularDisplayName\": \"Connected Cache for ISP\" }\n ,\"microsoft.connectedcredentials/credentials\": { \"SingularDisplayName\": \"Microsoft.ConnectedCredentials credential\" }\n ,\"microsoft.connectedvehicle/platformaccounts\": { \"SingularDisplayName\": \"Microsoft.ConnectedVehicle platform account\" }\n ,\"microsoft.connectedvmwarevsphere/clusters\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere cluster\" }\n ,\"microsoft.connectedvmwarevsphere/datastores\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere datastore\" }\n ,\"microsoft.connectedvmwarevsphere/hosts\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere host\" }\n ,\"microsoft.connectedvmwarevsphere/resourcepools\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere resource pool\" }\n ,\"microsoft.connectedvmwarevsphere/vcenters\": { \"SingularDisplayName\": \"VMware vCenter\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachineinstances\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual machine instance\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachineinstances/guestagents\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual machine instances guest agent\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachineinstances/hybrididentitymetadata\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual machine instances hybrid identity metadata\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachines\": { \"SingularDisplayName\": \"VMware + AVS virtual machine\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachines/providers/guestconfigurationassignments\": { \"SingularDisplayName\": \"Guest Assignment\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachinetemplates\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual machine template\" }\n ,\"microsoft.connectedvmwarevsphere/virtualnetworks\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual network\" }\n ,\"microsoft.consumption/budgets\": { \"SingularDisplayName\": \"Microsoft.Consumption budget\" }\n ,\"microsoft.consumption/credits\": { \"SingularDisplayName\": \"Microsoft.Consumption credit\" }\n ,\"microsoft.consumption/pricesheets\": { \"SingularDisplayName\": \"Microsoft.Consumption pricesheet\" }\n ,\"microsoft.containerinstance/containergroupprofiles\": { \"SingularDisplayName\": \"Microsoft.ContainerInstance container group profile\" }\n ,\"microsoft.containerinstance/containergroupprofiles/revisions\": { \"SingularDisplayName\": \"Microsoft.ContainerInstance container group profiles revision\" }\n ,\"microsoft.containerinstance/containergroups\": { \"SingularDisplayName\": \"Container instances\" }\n ,\"microsoft.containerinstance/ngroups\": { \"SingularDisplayName\": \"Microsoft.ContainerInstance ngroup\" }\n ,\"microsoft.containerregistry/registries\": { \"SingularDisplayName\": \"Container registry\" }\n ,\"microsoft.containerregistry/registries/replications\": { \"SingularDisplayName\": \"Container registry replication\" }\n ,\"microsoft.containerregistry/registries/scopemaps\": { \"SingularDisplayName\": \"Container registry scope map\" }\n ,\"microsoft.containerregistry/registries/tokens\": { \"SingularDisplayName\": \"Container registry token\" }\n ,\"microsoft.containerregistry/registries/webhooks\": { \"SingularDisplayName\": \"Container registry webhook\" }\n ,\"microsoft.containerservice/fleets\": { \"SingularDisplayName\": \"Kubernetes fleet manager\" }\n ,\"microsoft.containerservice/managedclusters\": { \"SingularDisplayName\": \"Kubernetes service\" }\n ,\"microsoft.containerservice/managedclusters/managednamespaces\": { \"SingularDisplayName\": \"Managed namespace\" }\n ,\"microsoft.containerservice/managedclusters/microsoft.kubernetesconfiguration/extensions\": { \"SingularDisplayName\": \"Kubernetes service extension\" }\n ,\"microsoft.containerservice/managedclusters/microsoft.kubernetesconfiguration/fluxconfigurations\": { \"SingularDisplayName\": \"GitOps configuration\" }\n ,\"microsoft.containerservice/managedclusters/microsoft.kubernetesconfiguration/namespaces\": { \"SingularDisplayName\": \"Kubernetes namespace\" }\n ,\"microsoft.containerservice/managedclusters/namespaces\": { \"SingularDisplayName\": \"Managed namespace\" }\n ,\"microsoft.containerservice/managedclustersnapshots\": { \"SingularDisplayName\": \"Microsoft.ContainerService managedclustersnapshot\" }\n ,\"microsoft.containerservice/snapshots\": { \"SingularDisplayName\": \"Microsoft.ContainerService snapshot\" }\n ,\"microsoft.containerstorage/pools\": { \"SingularDisplayName\": \"Container storage\" }\n ,\"microsoft.costmanagement/alerts\": { \"SingularDisplayName\": \"Microsoft.CostManagement alert\" }\n ,\"microsoft.costmanagement/budgets\": { \"SingularDisplayName\": \"Microsoft.CostManagement budget\" }\n ,\"microsoft.costmanagement/cloudconnectors\": { \"SingularDisplayName\": \"Microsoft.CostManagement cloud connector\" }\n ,\"microsoft.costmanagement/connectors\": { \"SingularDisplayName\": \"Microsoft.CostManagement connector\" }\n ,\"microsoft.costmanagement/costallocationrules\": { \"SingularDisplayName\": \"Microsoft.CostManagement cost allocation rule\" }\n ,\"microsoft.costmanagement/costdetailsoperationresults\": { \"SingularDisplayName\": \"Microsoft.CostManagement cost details operation result\" }\n ,\"microsoft.costmanagement/exports\": { \"SingularDisplayName\": \"Microsoft.CostManagement export\" }\n ,\"microsoft.costmanagement/externalbillingaccounts\": { \"SingularDisplayName\": \"Microsoft.CostManagement external billing account\" }\n ,\"microsoft.costmanagement/externalsubscriptions\": { \"SingularDisplayName\": \"Microsoft.CostManagement external subscription\" }\n ,\"microsoft.costmanagement/markuprules\": { \"SingularDisplayName\": \"Microsoft.CostManagement markup rule\" }\n ,\"microsoft.costmanagement/operationstatus\": { \"SingularDisplayName\": \"Microsoft.CostManagement operation statu\" }\n ,\"microsoft.costmanagement/reportconfigs\": { \"SingularDisplayName\": \"Microsoft.CostManagement reportconfig\" }\n ,\"microsoft.costmanagement/reports\": { \"SingularDisplayName\": \"Microsoft.CostManagement report\" }\n ,\"microsoft.costmanagement/scheduledactions\": { \"SingularDisplayName\": \"Microsoft.CostManagement scheduled action\" }\n ,\"microsoft.costmanagement/settings\": { \"SingularDisplayName\": \"Microsoft.CostManagement setting\" }\n ,\"microsoft.costmanagement/views\": { \"SingularDisplayName\": \"Microsoft.CostManagement view\" }\n ,\"microsoft.customerlockbox/requests\": { \"SingularDisplayName\": \"Microsoft.CustomerLockbox request\" }\n ,\"microsoft.customerlockbox/tenantoptedin\": { \"SingularDisplayName\": \"Microsoft.CustomerLockbox tenant opted in\" }\n ,\"microsoft.customproviders/associations\": { \"SingularDisplayName\": \"Microsoft.CustomProviders association\" }\n ,\"microsoft.customproviders/resourceproviders\": { \"SingularDisplayName\": \"Microsoft.CustomProviders resource provider\" }\n ,\"microsoft.dashboard/dashboards\": { \"SingularDisplayName\": \"Azure Monitor dashboards with Grafana\" }\n ,\"microsoft.dashboard/grafana\": { \"SingularDisplayName\": \"Azure Managed Grafana\" }\n ,\"microsoft.dataaccelerator/indexclusters\": { \"SingularDisplayName\": \"Microsoft.DataAccelerator index cluster\" }\n ,\"microsoft.databasefleetmanager/fleets\": { \"SingularDisplayName\": \"Database fleet manager\" }\n ,\"microsoft.databasefleetmanager/fleets/fleetspaces\": { \"SingularDisplayName\": \"Fleetspaces\" }\n ,\"microsoft.databasefleetmanager/fleets/fleetspaces/databases\": { \"SingularDisplayName\": \"Fleet managed database\" }\n ,\"microsoft.databasefleetmanager/fleets/tiers\": { \"SingularDisplayName\": \"tier\" }\n ,\"microsoft.databasewatcher/watchers\": { \"SingularDisplayName\": \"Database watcher\" }\n ,\"microsoft.databox/jobs\": { \"SingularDisplayName\": \"Azure Data Box\" }\n ,\"microsoft.databoxedge/databoxedgedevices\": { \"SingularDisplayName\": \"Azure Stack Edge / Data Box Gateway\" }\n ,\"microsoft.databricks/accessconnectors\": { \"SingularDisplayName\": \"Access Connector for Azure Databricks\" }\n ,\"microsoft.databricks/workspaces\": { \"SingularDisplayName\": \"Azure Databricks Service\" }\n ,\"microsoft.datacatalog/catalogs\": { \"SingularDisplayName\": \"Data catalog\" }\n ,\"microsoft.datacollaboration/workspaces\": { \"SingularDisplayName\": \"Project CI\" }\n ,\"microsoft.datadog/agreements\": { \"SingularDisplayName\": \"Microsoft.Datadog agreement\" }\n ,\"microsoft.datadog/monitors\": { \"SingularDisplayName\": \"Datadog\" }\n ,\"microsoft.datadog/subscriptionstatuses\": { \"SingularDisplayName\": \"Microsoft.Datadog subscription statuse\" }\n ,\"microsoft.datafactory/datafactories\": { \"SingularDisplayName\": \"Data factory\" }\n ,\"microsoft.datafactory/factories\": { \"SingularDisplayName\": \"Data factory (V2)\" }\n ,\"microsoft.datafactory/factories/pipelines\": { \"SingularDisplayName\": \"Data Factory pipeline\" }\n ,\"microsoft.datafactory/factories/triggers\": { \"SingularDisplayName\": \"Data Factory trigger\" }\n ,\"microsoft.datalakeanalytics/accounts\": { \"SingularDisplayName\": \"Data Lake Analytics account\" }\n ,\"microsoft.datalakestore/accounts\": { \"SingularDisplayName\": \"Data Lake Storage Gen1\" }\n ,\"microsoft.datamigration/databasemigrations\": { \"SingularDisplayName\": \"Microsoft.DataMigration database migration\" }\n ,\"microsoft.datamigration/migrationservices\": { \"SingularDisplayName\": \"Microsoft.DataMigration migration service\" }\n ,\"microsoft.datamigration/services\": { \"SingularDisplayName\": \"Azure Database Migration Service (classic)\" }\n ,\"microsoft.datamigration/services/projects\": { \"SingularDisplayName\": \"Azure Database Migration Project\" }\n ,\"microsoft.datamigration/sqlmigrationservices\": { \"SingularDisplayName\": \"Azure Database Migration Service\" }\n ,\"microsoft.dataprotection/backupvaults\": { \"SingularDisplayName\": \"Backup vault\" }\n ,\"microsoft.dataprotection/resourceguards\": { \"SingularDisplayName\": \"Resource Guard\" }\n ,\"microsoft.datareplication/replicationfabrics\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication fabric\" }\n ,\"microsoft.datareplication/replicationfabrics/fabricagents\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication fabrics fabric agent\" }\n ,\"microsoft.datareplication/replicationfabrics/fabricagents/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication fabrics fabric agents operation\" }\n ,\"microsoft.datareplication/replicationfabrics/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication fabrics operation\" }\n ,\"microsoft.datareplication/replicationvaults\": { \"SingularDisplayName\": \"Data replication vault\" }\n ,\"microsoft.datareplication/replicationvaults/alertsettings\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults alert setting\" }\n ,\"microsoft.datareplication/replicationvaults/events\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults event\" }\n ,\"microsoft.datareplication/replicationvaults/jobs\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults job\" }\n ,\"microsoft.datareplication/replicationvaults/jobs/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults jobs operation\" }\n ,\"microsoft.datareplication/replicationvaults/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults operation\" }\n ,\"microsoft.datareplication/replicationvaults/privateendpointconnectionproxies\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults private endpoint connection proxy\" }\n ,\"microsoft.datareplication/replicationvaults/privateendpointconnections\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults private endpoint connection\" }\n ,\"microsoft.datareplication/replicationvaults/privatelinkresources\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults private link resource\" }\n ,\"microsoft.datareplication/replicationvaults/protecteditems\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults protected item\" }\n ,\"microsoft.datareplication/replicationvaults/protecteditems/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults protected items operation\" }\n ,\"microsoft.datareplication/replicationvaults/protecteditems/recoverypoints\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults protected items recovery point\" }\n ,\"microsoft.datareplication/replicationvaults/replicationextensions\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults replication extension\" }\n ,\"microsoft.datareplication/replicationvaults/replicationextensions/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults replication extensions operation\" }\n ,\"microsoft.datareplication/replicationvaults/replicationpolicies\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults replication policy\" }\n ,\"microsoft.datareplication/replicationvaults/replicationpolicies/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults replication policies operation\" }\n ,\"microsoft.datashare/accounts\": { \"SingularDisplayName\": \"Data Share\" }\n ,\"microsoft.dbformariadb/servers\": { \"SingularDisplayName\": \"Azure Database for MariaDB server\" }\n ,\"microsoft.dbformysql/flexibleservers\": { \"SingularDisplayName\": \"Azure Database for MySQL flexible server\" }\n ,\"microsoft.dbformysql/servers\": { \"SingularDisplayName\": \"MySQL server\" }\n ,\"microsoft.dbforpostgresql/flexibleservers\": { \"SingularDisplayName\": \"Azure Database for PostgreSQL flexible server\" }\n ,\"microsoft.dbforpostgresql/servergroupsv2\": { \"SingularDisplayName\": \"Azure Cosmos DB for PostgreSQL Cluster\" }\n ,\"microsoft.dbforpostgresql/servers\": { \"SingularDisplayName\": \"PostgreSQL server\" }\n ,\"microsoft.delegatednetwork/controller\": { \"SingularDisplayName\": \"Microsoft.DelegatedNetwork controller\" }\n ,\"microsoft.delegatednetwork/delegatedsubnets\": { \"SingularDisplayName\": \"Microsoft.DelegatedNetwork delegated subnet\" }\n ,\"microsoft.delegatednetwork/orchestrators\": { \"SingularDisplayName\": \"Microsoft.DelegatedNetwork orchestrator\" }\n ,\"microsoft.dependencymap/maps\": { \"SingularDisplayName\": \"Microsoft.DependencyMap map\" }\n ,\"microsoft.dependencymap/maps/discoverysources\": { \"SingularDisplayName\": \"Microsoft.DependencyMap maps discovery source\" }\n ,\"microsoft.deploymentmanager/artifactsources\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager artifact source\" }\n ,\"microsoft.deploymentmanager/rollouts\": { \"SingularDisplayName\": \"Rollout\" }\n ,\"microsoft.deploymentmanager/servicetopologies\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager service topology\" }\n ,\"microsoft.deploymentmanager/servicetopologies/services\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager service topologies service\" }\n ,\"microsoft.deploymentmanager/servicetopologies/services/serviceunits\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager service topologies services service unit\" }\n ,\"microsoft.deploymentmanager/steps\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager step\" }\n ,\"microsoft.desktopvirtualization/appattachpackages\": { \"SingularDisplayName\": \"App attach package\" }\n ,\"microsoft.desktopvirtualization/applicationgroups\": { \"SingularDisplayName\": \"Application group\" }\n ,\"microsoft.desktopvirtualization/hostpools\": { \"SingularDisplayName\": \"Host pool\" }\n ,\"microsoft.desktopvirtualization/scalingplans\": { \"SingularDisplayName\": \"Scaling plan\" }\n ,\"microsoft.desktopvirtualization/workspaces\": { \"SingularDisplayName\": \"Workspace\" }\n ,\"microsoft.devai/instances\": { \"SingularDisplayName\": \"Microsoft.DevAI instance\" }\n ,\"microsoft.devai/instances/experiments\": { \"SingularDisplayName\": \"Microsoft.DevAI instances experiment\" }\n ,\"microsoft.devai/instances/sandboxes\": { \"SingularDisplayName\": \"Microsoft.DevAI instances sandbox\" }\n ,\"microsoft.devai/instances/sandboxes/experiments\": { \"SingularDisplayName\": \"Microsoft.DevAI instances sandboxes experiment\" }\n ,\"microsoft.devcenter/devcenters\": { \"SingularDisplayName\": \"Dev center\" }\n ,\"microsoft.devcenter/devcenters/devboxdefinitions\": { \"SingularDisplayName\": \"Dev Box definition\" }\n ,\"microsoft.devcenter/networkconnections\": { \"SingularDisplayName\": \"Network connection\" }\n ,\"microsoft.devcenter/plans\": { \"SingularDisplayName\": \"Dev center plan\" }\n ,\"microsoft.devcenter/projects\": { \"SingularDisplayName\": \"Project\" }\n ,\"microsoft.devcenter/projects/pools\": { \"SingularDisplayName\": \"Pool\" }\n ,\"microsoft.developmentwindows365/developmentcloudpcdelegatedmsis\": { \"SingularDisplayName\": \"Microsoft.DevelopmentWindows365 development cloud pc delegated msi\" }\n ,\"microsoft.devhub/iacprofiles\": { \"SingularDisplayName\": \"Infrastructure as Code Automation\" }\n ,\"microsoft.devhub/templates\": { \"SingularDisplayName\": \"Microsoft.DevHub template\" }\n ,\"microsoft.devhub/templates/versions\": { \"SingularDisplayName\": \"Microsoft.DevHub templates version\" }\n ,\"microsoft.devhub/workflows\": { \"SingularDisplayName\": \"Microsoft.DevHub workflow\" }\n ,\"microsoft.deviceonboarding/discoveryservices\": { \"SingularDisplayName\": \"Microsoft.DeviceOnboarding discovery service\" }\n ,\"microsoft.deviceonboarding/discoveryservices/ownershipvoucherpublickeys\": { \"SingularDisplayName\": \"Microsoft.DeviceOnboarding discovery services ownership voucher public key\" }\n ,\"microsoft.deviceonboarding/onboardingservices\": { \"SingularDisplayName\": \"Microsoft.DeviceOnboarding onboarding service\" }\n ,\"microsoft.deviceonboarding/onboardingservices/policies\": { \"SingularDisplayName\": \"Microsoft.DeviceOnboarding onboarding services policy\" }\n ,\"microsoft.deviceregistry/assetendpointprofiles\": { \"SingularDisplayName\": \"IoT Asset Endpoint Profile\" }\n ,\"microsoft.deviceregistry/assets\": { \"SingularDisplayName\": \"IoT Asset\" }\n ,\"microsoft.deviceregistry/billingcontainers\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry billing container\" }\n ,\"microsoft.deviceregistry/devices\": { \"SingularDisplayName\": \"IoT Device\" }\n ,\"microsoft.deviceregistry/discoveredassetendpointprofiles\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry discovered asset endpoint profile\" }\n ,\"microsoft.deviceregistry/discoveredassets\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry discovered asset\" }\n ,\"microsoft.deviceregistry/namespaces\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespace\" }\n ,\"microsoft.deviceregistry/namespaces/assetendpointprofiles\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces asset endpoint profile\" }\n ,\"microsoft.deviceregistry/namespaces/assets\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces asset\" }\n ,\"microsoft.deviceregistry/namespaces/devices\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces device\" }\n ,\"microsoft.deviceregistry/namespaces/discoveredassetendpointprofiles\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces discovered asset endpoint profile\" }\n ,\"microsoft.deviceregistry/namespaces/discoveredassets\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces discovered asset\" }\n ,\"microsoft.deviceregistry/schemaregistries\": { \"SingularDisplayName\": \"IoT Schema Registry\" }\n ,\"microsoft.deviceregistry/schemaregistries/schemas\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry schema registries schema\" }\n ,\"microsoft.deviceregistry/schemaregistries/schemas/schemaversions\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry schema registries schemas schema version\" }\n ,\"microsoft.devices/iothubs\": { \"SingularDisplayName\": \"IoT hub\" }\n ,\"microsoft.devices/provisioningservices\": { \"SingularDisplayName\": \"Azure IoT Hub Device Provisioning Service (DPS)\" }\n ,\"microsoft.deviceupdate/accounts\": { \"SingularDisplayName\": \"Device Update for IoT Hub\" }\n ,\"microsoft.deviceupdate/updateaccounts\": { \"SingularDisplayName\": \"Device Update Account\" }\n ,\"microsoft.deviceupdate/updateaccounts/activedeployments\": { \"SingularDisplayName\": \"Device Update Active Deployment\" }\n ,\"microsoft.deviceupdate/updateaccounts/agents\": { \"SingularDisplayName\": \"Device Update Agent\" }\n ,\"microsoft.deviceupdate/updateaccounts/deployments\": { \"SingularDisplayName\": \"Device Update Deployment\" }\n ,\"microsoft.deviceupdate/updateaccounts/deviceclasses\": { \"SingularDisplayName\": \"Device Update Device Class\" }\n ,\"microsoft.deviceupdate/updateaccounts/updates\": { \"SingularDisplayName\": \"Device Update\" }\n ,\"microsoft.devops/pipelines\": { \"SingularDisplayName\": \"Microsoft.DevOps pipeline\" }\n ,\"microsoft.devopsinfrastructure/pools\": { \"SingularDisplayName\": \"Managed DevOps Pool\" }\n ,\"microsoft.devspaces/controllers\": { \"SingularDisplayName\": \"Microsoft.DevSpaces controller\" }\n ,\"microsoft.devtestlab/labs\": { \"SingularDisplayName\": \"DevTest lab\" }\n ,\"microsoft.devtestlab/labs/virtualmachines\": { \"SingularDisplayName\": \"DevTest Lab virtual machine\" }\n ,\"microsoft.devtestlab/schedules\": { \"SingularDisplayName\": \"Microsoft.DevTestLab schedule\" }\n ,\"microsoft.devtunnels/tunnelplans\": { \"SingularDisplayName\": \"Dev Tunnels Domain\" }\n ,\"microsoft.diagnostics/apollo\": { \"SingularDisplayName\": \"Microsoft.Diagnostics apollo\" }\n ,\"microsoft.digitaltwins/digitaltwinsinstances\": { \"SingularDisplayName\": \"Azure Digital Twins\" }\n ,\"microsoft.discovery/agents\": { \"SingularDisplayName\": \"Microsoft Discovery Agent\" }\n ,\"microsoft.discovery/bookshelves\": { \"SingularDisplayName\": \"Microsoft Discovery Bookshelf\" }\n ,\"microsoft.discovery/datacontainers\": { \"SingularDisplayName\": \"Microsoft Discovery Data Container\" }\n ,\"microsoft.discovery/datacontainers/dataassets\": { \"SingularDisplayName\": \"Data asset\" }\n ,\"microsoft.discovery/models\": { \"SingularDisplayName\": \"Microsoft Discovery Model\" }\n ,\"microsoft.discovery/storages\": { \"SingularDisplayName\": \"Microsoft Discovery Storage\" }\n ,\"microsoft.discovery/supercomputers\": { \"SingularDisplayName\": \"Microsoft Discovery Supercomputer\" }\n ,\"microsoft.discovery/supercomputers/nodepools\": { \"SingularDisplayName\": \"Nodepool\" }\n ,\"microsoft.discovery/tools\": { \"SingularDisplayName\": \"Microsoft Discovery Tool\" }\n ,\"microsoft.discovery/workflows\": { \"SingularDisplayName\": \"Microsoft Discovery Workflow\" }\n ,\"microsoft.discovery/workspaces\": { \"SingularDisplayName\": \"Microsoft Discovery Workspace\" }\n ,\"microsoft.discovery/workspaces/projects\": { \"SingularDisplayName\": \"Microsoft Discovery Project\" }\n ,\"microsoft.documentdb/cassandraclusters\": { \"SingularDisplayName\": \"Azure Managed Instance for Apache Cassandra\" }\n ,\"microsoft.documentdb/databaseaccounts\": { \"SingularDisplayName\": \"Cosmos DB account\" }\n ,\"microsoft.documentdb/fleets\": { \"SingularDisplayName\": \"Azure Cosmos DB Fleet\" }\n ,\"microsoft.documentdb/fleetspacepotentialdatabaseaccounts\": { \"SingularDisplayName\": \"Potential Azure Cosmos DB account\" }\n ,\"microsoft.documentdb/fleetspacepotentialdatabaseaccountswithlocations\": { \"SingularDisplayName\": \"Potential Azure Cosmos DB account\" }\n ,\"microsoft.documentdb/mongoclusters\": { \"SingularDisplayName\": \"Azure Cosmos DB for MongoDB (vCore)\" }\n ,\"microsoft.documentdb/throughputpools\": { \"SingularDisplayName\": \"Microsoft.DocumentDB throughput pool\" }\n ,\"microsoft.documentdb/throughputpools/throughputpoolaccounts\": { \"SingularDisplayName\": \"Microsoft.DocumentDB throughput pools throughput pool account\" }\n ,\"microsoft.domainregistration/domains\": { \"SingularDisplayName\": \"App Service Domain\" }\n ,\"microsoft.domainregistration/topleveldomains\": { \"SingularDisplayName\": \"Microsoft.DomainRegistration top level domain\" }\n ,\"microsoft.durabletask/namespaces\": { \"SingularDisplayName\": \"Microsoft.DurableTask namespace\" }\n ,\"microsoft.durabletask/namespaces/taskhubs\": { \"SingularDisplayName\": \"Task Hub\" }\n ,\"microsoft.durabletask/schedulers\": { \"SingularDisplayName\": \"Durable Task Scheduler\" }\n ,\"microsoft.durabletask/schedulers/taskhubs\": { \"SingularDisplayName\": \"Task Hub\" }\n ,\"microsoft.dynamics365fraudprotection/instances\": { \"SingularDisplayName\": \"Microsoft.Dynamics365FraudProtection instance\" }\n ,\"microsoft.easm/workspaces\": { \"SingularDisplayName\": \"Microsoft Defender EASM\" }\n ,\"microsoft.edge/configurations\": { \"SingularDisplayName\": \"Site configuration\" }\n ,\"microsoft.edge/configurations/arcgatewayconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations arc gateway configuration\" }\n ,\"microsoft.edge/configurations/connectivityconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations connectivity configuration\" }\n ,\"microsoft.edge/configurations/dynamicconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations dynamic configuration\" }\n ,\"microsoft.edge/configurations/dynamicconfigurations/versions\": { \"SingularDisplayName\": \"Microsoft.Edge configurations dynamic configurations version\" }\n ,\"microsoft.edge/configurations/networkconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations network configuration\" }\n ,\"microsoft.edge/configurations/securityconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations security configuration\" }\n ,\"microsoft.edge/configurations/timeserverconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations time server configuration\" }\n ,\"microsoft.edge/connectivitystatuses\": { \"SingularDisplayName\": \"Microsoft.Edge connectivity statuse\" }\n ,\"microsoft.edge/disconnectedoperations\": { \"SingularDisplayName\": \"Azure Local - disconnected operations\" }\n ,\"microsoft.edge/siteawareresourcetypes\": { \"SingularDisplayName\": \"Microsoft.Edge site aware resource type\" }\n ,\"microsoft.edge/sites\": { \"SingularDisplayName\": \"Site manager - Azure Arc\" }\n ,\"microsoft.edge/updates\": { \"SingularDisplayName\": \"Microsoft.Edge update\" }\n ,\"microsoft.edgemarketplace/offers\": { \"SingularDisplayName\": \"Microsoft.EdgeMarketplace offer\" }\n ,\"microsoft.edgemarketplace/publishers\": { \"SingularDisplayName\": \"Microsoft.EdgeMarketplace publisher\" }\n ,\"microsoft.edgeorder/addresses\": { \"SingularDisplayName\": \"Azure Edge Hardware Center Address\" }\n ,\"microsoft.edgeorder/bootstrapconfigurations\": { \"SingularDisplayName\": \"Site Key\" }\n ,\"microsoft.edgeorder/orderitems\": { \"SingularDisplayName\": \"Azure Edge Hardware Center\" }\n ,\"microsoft.edgeorder/virtual_orderitems\": { \"SingularDisplayName\": \"Device\" }\n ,\"microsoft.edgezones/extendedzones\": { \"SingularDisplayName\": \"Microsoft.EdgeZones extended zone\" }\n ,\"microsoft.education/grants\": { \"SingularDisplayName\": \"Microsoft.Education grant\" }\n ,\"microsoft.education/labs\": { \"SingularDisplayName\": \"Microsoft.Education lab\" }\n ,\"microsoft.education/labs/joinrequests\": { \"SingularDisplayName\": \"Microsoft.Education labs join request\" }\n ,\"microsoft.education/labs/students\": { \"SingularDisplayName\": \"Microsoft.Education labs student\" }\n ,\"microsoft.education/studentlabs\": { \"SingularDisplayName\": \"Microsoft.Education student lab\" }\n ,\"microsoft.elastic/monitors\": { \"SingularDisplayName\": \"Elastic Cloud Resource\" }\n ,\"microsoft.elasticsan/elasticsans\": { \"SingularDisplayName\": \"Elastic SAN\" }\n ,\"microsoft.energydataplatform/energyservices\": { \"SingularDisplayName\": \"Microsoft.EnergyDataPlatform energy service\" }\n ,\"microsoft.enterpriseknowledgegraph/services\": { \"SingularDisplayName\": \"Microsoft.EnterpriseKnowledgeGraph service\" }\n ,\"microsoft.enterprisesupport/enterprisesupports\": { \"SingularDisplayName\": \"Microsoft.EnterpriseSupport enterprise support\" }\n ,\"microsoft.eventgrid/domains\": { \"SingularDisplayName\": \"Event Grid Domain\" }\n ,\"microsoft.eventgrid/domains/topics\": { \"SingularDisplayName\": \"Event Grid Domain Topic\" }\n ,\"microsoft.eventgrid/eventsubscriptions\": { \"SingularDisplayName\": \"Microsoft.EventGrid event subscription\" }\n ,\"microsoft.eventgrid/extensiontopics\": { \"SingularDisplayName\": \"Event Grid extension topic\" }\n ,\"microsoft.eventgrid/namespaces\": { \"SingularDisplayName\": \"Event Grid Namespace\" }\n ,\"microsoft.eventgrid/namespaces/topics\": { \"SingularDisplayName\": \"Event Grid Namespace Topic\" }\n ,\"microsoft.eventgrid/namespaces/topics/eventsubscriptions\": { \"SingularDisplayName\": \"Event Subscription\" }\n ,\"microsoft.eventgrid/namespaces/topicspaces\": { \"SingularDisplayName\": \"Event Grid Topic Space\" }\n ,\"microsoft.eventgrid/partnerconfigurations\": { \"SingularDisplayName\": \"Event Grid Partner Configuration\" }\n ,\"microsoft.eventgrid/partnerdestinations\": { \"SingularDisplayName\": \"Event Grid Partner Destination\" }\n ,\"microsoft.eventgrid/partnernamespaces\": { \"SingularDisplayName\": \"Event Grid Partner Namespace\" }\n ,\"microsoft.eventgrid/partnernamespaces/channels\": { \"SingularDisplayName\": \"Event Grid Channel\" }\n ,\"microsoft.eventgrid/partnerregistrations\": { \"SingularDisplayName\": \"Event Grid Partner Registration\" }\n ,\"microsoft.eventgrid/partnertopics\": { \"SingularDisplayName\": \"Event Grid Partner Topic\" }\n ,\"microsoft.eventgrid/systemtopics\": { \"SingularDisplayName\": \"Event Grid System Topic\" }\n ,\"microsoft.eventgrid/systemtopics/eventsubscriptions\": { \"SingularDisplayName\": \"Event Grid Subscriptions\" }\n ,\"microsoft.eventgrid/topics\": { \"SingularDisplayName\": \"Event Grid Topic\" }\n ,\"microsoft.eventgrid/topictypes\": { \"SingularDisplayName\": \"Microsoft.EventGrid topic type\" }\n ,\"microsoft.eventgrid/verifiedpartners\": { \"SingularDisplayName\": \"Microsoft.EventGrid verified partner\" }\n ,\"microsoft.eventhub/clusters\": { \"SingularDisplayName\": \"Event Hubs Cluster\" }\n ,\"microsoft.eventhub/namespaces\": { \"SingularDisplayName\": \"Event Hubs namespace\" }\n ,\"microsoft.eventhub/namespaces/disasterrecoveryconfigs\": { \"SingularDisplayName\": \"Event Hubs Geo-DR Alias\" }\n ,\"microsoft.eventhub/namespaces/eventhubs\": { \"SingularDisplayName\": \"Event Hubs Instance\" }\n ,\"microsoft.eventhub/namespaces/providers/diagnosticsettings\": { \"SingularDisplayName\": \"Diagnostic settings\" }\n ,\"microsoft.eventhub/namespaces/schemagroups\": { \"SingularDisplayName\": \"Schema Group\" }\n ,\"microsoft.experimentation/experimentworkspaces\": { \"SingularDisplayName\": \"Experiment Workspace\" }\n ,\"microsoft.extendedlocation/customlocations\": { \"SingularDisplayName\": \"Custom location\" }\n ,\"microsoft.fabric/capacities\": { \"SingularDisplayName\": \"Fabric Capacity\" }\n ,\"microsoft.fabric/privatelinkservicesforfabric\": { \"SingularDisplayName\": \"Microsoft.Fabric private link services for fabric\" }\n ,\"microsoft.fabric/privatelinkservicesforfabric/operationresults\": { \"SingularDisplayName\": \"Microsoft.Fabric private link services for fabric operation result\" }\n ,\"microsoft.fabric/privatelinkservicesforfabric/privateendpointconnections\": { \"SingularDisplayName\": \"Microsoft.Fabric private link services for fabric private endpoint connection\" }\n ,\"microsoft.fabric/privatelinkservicesforfabric/privatelinkresources\": { \"SingularDisplayName\": \"Microsoft.Fabric private link services for fabric private link resource\" }\n ,\"microsoft.fairfieldgardens/deviceprovisioningstates\": { \"SingularDisplayName\": \"Microsoft.FairfieldGardens device provisioning state\" }\n ,\"microsoft.fairfieldgardens/provisioningresources\": { \"SingularDisplayName\": \"Fairfield Gardens\" }\n ,\"microsoft.fairfieldgardens/provisioningresources/provisioningpolicies\": { \"SingularDisplayName\": \"Provisioning policy\" }\n ,\"microsoft.falcon/namespaces\": { \"SingularDisplayName\": \"Microsoft.Falcon namespace\" }\n ,\"microsoft.features/featureprovidernamespaces/featureconfigurations\": { \"SingularDisplayName\": \"Preview features\" }\n ,\"microsoft.fidalgo/devcenters\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenter\" }\n ,\"microsoft.fidalgo/devcenters/attachednetworks\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters attachednetwork\" }\n ,\"microsoft.fidalgo/devcenters/catalogs\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters catalog\" }\n ,\"microsoft.fidalgo/devcenters/catalogs/items\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters catalogs item\" }\n ,\"microsoft.fidalgo/devcenters/devboxdefinitions\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters devboxdefinition\" }\n ,\"microsoft.fidalgo/devcenters/environmenttypes\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters environment type\" }\n ,\"microsoft.fidalgo/devcenters/galleries\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters gallery\" }\n ,\"microsoft.fidalgo/devcenters/galleries/images\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters galleries image\" }\n ,\"microsoft.fidalgo/devcenters/galleries/images/versions\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters galleries images version\" }\n ,\"microsoft.fidalgo/devcenters/mappings\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters mapping\" }\n ,\"microsoft.fidalgo/machinedefinitions\": { \"SingularDisplayName\": \"Microsoft.Fidalgo machinedefinition\" }\n ,\"microsoft.fidalgo/networksettings\": { \"SingularDisplayName\": \"Microsoft.Fidalgo networksetting\" }\n ,\"microsoft.fidalgo/networksettings/healthchecks\": { \"SingularDisplayName\": \"Microsoft.Fidalgo networksettings healthcheck\" }\n ,\"microsoft.fidalgo/projects\": { \"SingularDisplayName\": \"Microsoft.Fidalgo project\" }\n ,\"microsoft.fidalgo/projects/attachednetworks\": { \"SingularDisplayName\": \"Microsoft.Fidalgo projects attachednetwork\" }\n ,\"microsoft.fidalgo/projects/devboxdefinitions\": { \"SingularDisplayName\": \"Microsoft.Fidalgo projects devboxdefinition\" }\n ,\"microsoft.fidalgo/projects/environments\": { \"SingularDisplayName\": \"Microsoft.Fidalgo projects environment\" }\n ,\"microsoft.fidalgo/projects/pools\": { \"SingularDisplayName\": \"Microsoft.Fidalgo projects pool\" }\n ,\"microsoft.fileshares/fileshares\": { \"SingularDisplayName\": \"File share\" }\n ,\"microsoft.fluidrelay/fluidrelayservers\": { \"SingularDisplayName\": \"Fluid Relay\" }\n ,\"microsoft.footprintmonitoring/profiles\": { \"SingularDisplayName\": \"Microsoft.FootprintMonitoring profile\" }\n ,\"microsoft.footprintmonitoring/profiles/experiments\": { \"SingularDisplayName\": \"Microsoft.FootprintMonitoring profiles experiment\" }\n ,\"microsoft.footprintmonitoring/profiles/measurementendpoints\": { \"SingularDisplayName\": \"Microsoft.FootprintMonitoring profiles measurement endpoint\" }\n ,\"microsoft.footprintmonitoring/profiles/measurementendpoints/conditions\": { \"SingularDisplayName\": \"Microsoft.FootprintMonitoring profiles measurement endpoints condition\" }\n ,\"microsoft.gallery/myareas/galleryitems\": { \"SingularDisplayName\": \"Template\" }\n ,\"microsoft.genomics/accounts\": { \"SingularDisplayName\": \"Genomics account\" }\n ,\"microsoft.graph/azureadapplication\": { \"SingularDisplayName\": \"Entra application\" }\n ,\"microsoft.graph/azureadapplicationprototype\": { \"SingularDisplayName\": \"Microsoft.Graph Azure ad application prototype\" }\n ,\"microsoft.graphservices/accounts\": { \"SingularDisplayName\": \"Metered API account\" }\n ,\"microsoft.guestconfiguration/guestconfigurationassignments\": { \"SingularDisplayName\": \"Microsoft.GuestConfiguration guest configuration assignment\" }\n ,\"microsoft.guestconfiguration/guestconfigurationassignments/reports\": { \"SingularDisplayName\": \"Microsoft.GuestConfiguration guest configuration assignments report\" }\n ,\"microsoft.hanaonazure/hanainstances\": { \"SingularDisplayName\": \"SAP HANA on Azure\" }\n ,\"microsoft.hanaonazure/sapmonitors\": { \"SingularDisplayName\": \"Azure Monitor for SAP Solutions (classic)\" }\n ,\"microsoft.hardware/orders\": { \"SingularDisplayName\": \"Microsoft.Hardware order\" }\n ,\"microsoft.hardwaresecuritymodules/cloudhsmclusters\": { \"SingularDisplayName\": \"Azure Cloud HSM\" }\n ,\"microsoft.hdinsight/clusterpools\": { \"SingularDisplayName\": \"Azure HDInsight on AKS cluster pool\" }\n ,\"microsoft.hdinsight/clusterpools/clusters\": { \"SingularDisplayName\": \"Azure HDInsight on AKS cluster\" }\n ,\"microsoft.hdinsight/clusterpools/clusters/instanceviews\": { \"SingularDisplayName\": \"Microsoft.HDInsight clusterpools clusters instance view\" }\n ,\"microsoft.hdinsight/clusters\": { \"SingularDisplayName\": \"HDInsight cluster\" }\n ,\"microsoft.healthbot/healthbots\": { \"SingularDisplayName\": \"Healthcare agent service\" }\n ,\"microsoft.healthcareapis/services\": { \"SingularDisplayName\": \"Azure API for FHIR\" }\n ,\"microsoft.healthcareapis/workspaces\": { \"SingularDisplayName\": \"Health Data Services workspace\" }\n ,\"microsoft.healthcareapis/workspaces/dicomservices\": { \"SingularDisplayName\": \"DICOM service\" }\n ,\"microsoft.healthcareapis/workspaces/fhirservices\": { \"SingularDisplayName\": \"FHIR service\" }\n ,\"microsoft.healthcareapis/workspaces/iotconnectors\": { \"SingularDisplayName\": \"MedTech service\" }\n ,\"microsoft.healthdataaiservices/deidservices\": { \"SingularDisplayName\": \"De-identification Service\" }\n ,\"microsoft.healthmodel/healthmodels\": { \"SingularDisplayName\": \"Health Model\" }\n ,\"microsoft.healthplatform/accounts\": { \"SingularDisplayName\": \"Microsoft.HealthPlatform account\" }\n ,\"microsoft.help/diagnostics\": { \"SingularDisplayName\": \"Microsoft.Help diagnostic\" }\n ,\"microsoft.help/selfhelp\": { \"SingularDisplayName\": \"Microsoft.Help self help\" }\n ,\"microsoft.help/simplifiedsolutions\": { \"SingularDisplayName\": \"Microsoft.Help simplified solution\" }\n ,\"microsoft.help/solutions\": { \"SingularDisplayName\": \"Microsoft.Help solution\" }\n ,\"microsoft.help/troubleshooters\": { \"SingularDisplayName\": \"Microsoft.Help troubleshooter\" }\n ,\"microsoft.hpcworkbench/instances\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instance\" }\n ,\"microsoft.hpcworkbench/instances/chambers\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chamber\" }\n ,\"microsoft.hpcworkbench/instances/chambers/accessprofiles\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers access profile\" }\n ,\"microsoft.hpcworkbench/instances/chambers/filerequests\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers file request\" }\n ,\"microsoft.hpcworkbench/instances/chambers/files\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers file\" }\n ,\"microsoft.hpcworkbench/instances/chambers/storages\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers storage\" }\n ,\"microsoft.hpcworkbench/instances/chambers/workloads\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers workload\" }\n ,\"microsoft.hpcworkbench/instances/consortiums\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances consortium\" }\n ,\"microsoft.hybridcloud/cloudconnections\": { \"SingularDisplayName\": \"Microsoft.HybridCloud cloud connection\" }\n ,\"microsoft.hybridcloud/cloudconnectors\": { \"SingularDisplayName\": \"Microsoft.HybridCloud cloud connector\" }\n ,\"microsoft.hybridcompute/arcgatewayassociatedresources\": { \"SingularDisplayName\": \"Arc gateway associated resource\" }\n ,\"microsoft.hybridcompute/arcserverwithwac\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/gateways\": { \"SingularDisplayName\": \"Arc gateway\" }\n ,\"microsoft.hybridcompute/licenses\": { \"SingularDisplayName\": \"Extended Security Updates - Windows Server 2012/R2\" }\n ,\"microsoft.hybridcompute/machines\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/machines/microsoft.awsconnector/ec2instances\": { \"SingularDisplayName\": \"Microsoft.AwsConnector ec2 instance\" }\n ,\"microsoft.hybridcompute/machines/microsoft.connectedvmwarevsphere/virtualmachineinstances\": { \"SingularDisplayName\": \"VMware + AVS virtual machine\" }\n ,\"microsoft.hybridcompute/machines/providers/guestconfigurationassignments\": { \"SingularDisplayName\": \"Guest Assignment\" }\n ,\"microsoft.hybridcompute/machinesesu\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/machinespaygo\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/machinessoftwareassurance\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/machinessovereign\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/privatelinkscopes\": { \"SingularDisplayName\": \"Azure Arc Private Link Scope\" }\n ,\"microsoft.hybridcompute/settings\": { \"SingularDisplayName\": \"Microsoft.HybridCompute setting\" }\n ,\"microsoft.hybridconnectivity/endpoints\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity endpoint\" }\n ,\"microsoft.hybridconnectivity/endpoints/serviceconfigurations\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity endpoints service configuration\" }\n ,\"microsoft.hybridconnectivity/publiccloudconnectors\": { \"SingularDisplayName\": \"Multicloud connector\" }\n ,\"microsoft.hybridconnectivity/solutionconfigurations\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity solution configuration\" }\n ,\"microsoft.hybridconnectivity/solutionconfigurations/inventory\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity solution configurations inventory\" }\n ,\"microsoft.hybridconnectivity/solutiontypes\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity solution type\" }\n ,\"microsoft.hybridcontainerservice/kubernetesversions\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService kubernetes version\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusterinstances\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService provisioned cluster instance\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusterinstances/agentpools\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService provisioned cluster instances agent pool\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusterinstances/hybrididentitymetadata\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService provisioned cluster instances hybrid identity metadata\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusterinstances/upgradeprofiles\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService provisioned cluster instances upgrade profile\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusters\": { \"SingularDisplayName\": \"Kubernetes hybrid - Azure Arc\" }\n ,\"microsoft.hybridcontainerservice/skus\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService SKU\" }\n ,\"microsoft.hybridcontainerservice/storagespaces\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService storage space\" }\n ,\"microsoft.hybridcontainerservice/virtualnetworks\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService virtual network\" }\n ,\"microsoft.hybriddata/datamanagers\": { \"SingularDisplayName\": \"Microsoft.HybridData data manager\" }\n ,\"microsoft.hybriddata/datamanagers/dataservices\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data service\" }\n ,\"microsoft.hybriddata/datamanagers/dataservices/jobdefinitions\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data services job definition\" }\n ,\"microsoft.hybriddata/datamanagers/dataservices/jobdefinitions/jobs\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data services job definitions job\" }\n ,\"microsoft.hybriddata/datamanagers/datastores\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data store\" }\n ,\"microsoft.hybriddata/datamanagers/datastoretypes\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data store type\" }\n ,\"microsoft.hybriddata/datamanagers/publickeys\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers public key\" }\n ,\"microsoft.hybridnetwork/configurationgroupvalues\": { \"SingularDisplayName\": \"Configuration Group Value\" }\n ,\"microsoft.hybridnetwork/devices\": { \"SingularDisplayName\": \"Azure Network Function Manager ? Device\" }\n ,\"microsoft.hybridnetwork/networkfunctions\": { \"SingularDisplayName\": \"Azure Network Function Manager ? Network Function\" }\n ,\"microsoft.hybridnetwork/proxypublishers\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publisher\" }\n ,\"microsoft.hybridnetwork/proxypublishers/artifactstores\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers artifact store\" }\n ,\"microsoft.hybridnetwork/proxypublishers/configurationgroupschemas\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers configuration group schema\" }\n ,\"microsoft.hybridnetwork/proxypublishers/networkfunctiondefinitiongroups\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers network function definition group\" }\n ,\"microsoft.hybridnetwork/proxypublishers/networkfunctiondefinitiongroups/networkfunctiondefinitionversions\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers network function definition groups network function definition version\" }\n ,\"microsoft.hybridnetwork/proxypublishers/networkservicedesigngroups\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers network service design group\" }\n ,\"microsoft.hybridnetwork/proxypublishers/networkservicedesigngroups/networkservicedesignversions\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers network service design groups network service design version\" }\n ,\"microsoft.hybridnetwork/publishers\": { \"SingularDisplayName\": \"Publisher\" }\n ,\"microsoft.hybridnetwork/publishers/artifactstores\": { \"SingularDisplayName\": \"Publisher Artifact Store\" }\n ,\"microsoft.hybridnetwork/publishers/artifactstores/artifactmanifests\": { \"SingularDisplayName\": \"Publisher Artifact Manifest\" }\n ,\"microsoft.hybridnetwork/publishers/configurationgroupschemas\": { \"SingularDisplayName\": \"Configuration Group Schema\" }\n ,\"microsoft.hybridnetwork/publishers/networkfunctiondefinitiongroups\": { \"SingularDisplayName\": \"Network Function Definition\" }\n ,\"microsoft.hybridnetwork/publishers/networkfunctiondefinitiongroups/networkfunctiondefinitionversions\": { \"SingularDisplayName\": \"Network Function Definition Version\" }\n ,\"microsoft.hybridnetwork/publishers/networkservicedesigngroups\": { \"SingularDisplayName\": \"Network Service Design\" }\n ,\"microsoft.hybridnetwork/publishers/networkservicedesigngroups/networkservicedesignversions\": { \"SingularDisplayName\": \"Network Service Design Version\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management container\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/rolloutsequences\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers rollout sequence\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/rollouttiers\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers rollout tier\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/updatespecifications\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers update specification\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/updatespecifications/rollouts\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers update specifications rollout\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/updatespecifications/rollouts/statuses\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers update specifications rollouts statuse\" }\n ,\"microsoft.hybridnetwork/sitenetworkservices\": { \"SingularDisplayName\": \"Site Network Service\" }\n ,\"microsoft.hybridnetwork/sites\": { \"SingularDisplayName\": \"Site\" }\n })[tolower(id)]\n}\n", - "$fxv#10": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// See known issues @ https://github.com/microsoft/finops-toolkit/issues/1111\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Prices |=========================================================================================================\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_transform_v1_2 function\n.create-or-alter function\nwith (docstring='Transforms Prices_raw into FOCUS 1.2.', folder='Prices')\nPrices_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n let prices = materialize(\n Prices_raw\n | extend PricingCurrency = coalesce(Currency, CurrencyCode) // CurrencyCode last as a fallback only\n | extend x_SkuId = coalesce(SkuId, SkuID)\n | extend x_SkuMeterId = coalesce(MeterId, MeterID)\n | extend x_SkuProductId = coalesce(ProductId, ProductID)\n | extend x_SkuTerm = isoMonths(Term)\n | project-rename\n SkuMeter = MeterName,\n x_BaseUnitPrice = BasePrice,\n x_EffectivePeriodEnd = EffectiveEndDate,\n x_EffectivePeriodStart = EffectiveStartDate,\n x_PricingUnitDescription = UnitOfMeasure,\n x_SkuIncludedQuantity = IncludedQuantity,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuMeterType = MeterType,\n x_SkuOfferId = OfferID,\n x_SkuPartNumber = PartNumber,\n x_SkuPriceType = PriceType,\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTier = TierMinimumUnits\n | extend ContractedUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', UnitPrice, real(null)) // UnitPrice for savings plan is not the on-demand unit price\n | extend ListUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', MarketPrice, real(null)) // MarketPrice for savings plan is not the list price\n | extend ChargeCategory = case(\n x_SkuPriceType == 'Consumption', 'Usage',\n x_SkuPriceType == 'ReservedInstance', 'Purchase',\n x_SkuPriceType == 'SavingsPlan', 'Usage', // Savings plan prices are for committed usage, not the purchase\n ''\n )\n | extend SkuPriceIdv2 = strcat(case(x_SkuPriceType == 'Consumption', 'OD', x_SkuPriceType == 'ReservedInstance', 'RI', x_SkuPriceType == 'SavingsPlan', 'SP', 'XX'), substring(ChargeCategory, 0, 1), x_SkuTerm, '_', x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType, '_', x_SkuTier, x_SkuOfferId)\n | extend x_BillingAccountId = iff(BillingAccountId startswith '/', split(BillingAccountId, '/')[-1], coalesce(BillingAccountId, EnrollmentNumber))\n | extend x_BillingProfileId = iff(BillingProfileId startswith '/', split(BillingProfileId, '/')[-1], coalesce(BillingProfileId, EnrollmentNumber))\n | extend tmp_SavingsPlanKey = strcat(x_SkuMeterId, x_SkuProductId, x_SkuId, x_SkuTier, x_SkuOfferId)\n //\n // Get latest ingested row based on the unique ID\n | extend x_IngestionTime = ingestion_time()\n );\n //\n // Meters for reservations and savings plans to identify commitment eligibility\n let riMeters = prices | where x_SkuPriceType == 'ReservedInstance' | distinct x_SkuMeterId;\n let spMeters = prices | where x_SkuPriceType == 'SavingsPlan' | distinct x_SkuMeterId;\n //\n // Copy list/base/contracted prices from on-demand SKUs\n prices\n | where x_SkuPriceType == 'SavingsPlan'\n // If we use join, specify the shuffle key\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter hint.strategy=shuffle (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | lookup kind=leftouter (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | extend ListUnitPrice = coalesce(ListUnitPrice, ListUnitPrice1)\n | extend ContractedUnitPrice = coalesce(ContractedUnitPrice, ContractedUnitPrice1)\n | extend x_BaseUnitPrice = coalesce(x_BaseUnitPrice, x_BaseUnitPrice1)\n | project-away ListUnitPrice1, ContractedUnitPrice1, x_BaseUnitPrice1, tmp_SavingsPlanKey\n | union ((prices | where x_SkuPriceType != 'SavingsPlan'))\n //\n // Set CommitmentDiscountCategory for reuse\n | extend CommitmentDiscountCategory = case(\n x_SkuPriceType == 'ReservedInstance', 'Usage',\n x_SkuPriceType == 'SavingsPlan', 'Spend',\n ''\n )\n //\n // Calculate commitment discount eligibility\n // TODO: Would a join be faster?\n // TODO: Check this to ensure it's correct\n | extend x_CommitmentDiscountSpendEligibility = iff(x_SkuMeterId in (riMeters) and x_SkuPriceType != 'ReservedInstance', 'Eligible', 'Not Eligible')\n | extend x_CommitmentDiscountUsageEligibility = iff(x_SkuMeterId in (spMeters), 'Eligible', 'Not Eligible')\n //\n // TODO: Implement x_CommitmentDiscountNormalizedRatio\n | extend x_CommitmentDiscountNormalizedRatio = real(null)\n //\n // Add PricingUnit and x_PricingBlockSize\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter (PricingUnits) on x_PricingUnitDescription | project-away x_PricingUnitDescription1\n | lookup kind=leftouter (PricingUnits) on x_PricingUnitDescription\n //\n | extend x_EffectiveUnitPrice = iff(x_SkuPriceType == 'SavingsPlan', UnitPrice, real(null)) // Savings plan prices are for the effective price, not the contracted price\n | extend x_EffectiveUnitPriceDiscount = ContractedUnitPrice - x_EffectiveUnitPrice\n | extend x_ContractedUnitPriceDiscount = ListUnitPrice - ContractedUnitPrice\n | extend x_TotalUnitPriceDiscount = ListUnitPrice - x_EffectiveUnitPrice\n | project\n BillingAccountId = tolower(case(\n BillingProfileId startswith '/', BillingProfileId,\n BillingAccountId startswith '/', BillingAccountId,\n strcat('/providers/microsoft.billing/billingaccounts/', x_BillingAccountId, iff(x_BillingProfileId == x_BillingAccountId, '', strcat('/billingprofiles/', x_BillingProfileId)))\n )),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName, x_BillingProfileId),\n BillingCurrency = coalesce(BillingCurrency, CurrencyCode, Currency), // Currency last as a fallback only\n ChargeCategory,\n CommitmentDiscountCategory,\n CommitmentDiscountType = case(\n x_SkuPriceType == 'ReservedInstance', 'Reservation',\n x_SkuPriceType == 'SavingsPlan', 'Savings plan',\n ''\n ),\n CommitmentDiscountUnit = case(\n isempty(CommitmentDiscountCategory), '',\n CommitmentDiscountCategory == 'Spend', PricingCurrency,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio == real(1), PricingUnit,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio > real(1), strcat('Normalized ', PricingUnit),\n ''\n ),\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory = case(\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed',\n ''\n ),\n PricingCurrency,\n PricingUnit,\n SkuId = coalesce(ProductId, ProductID),\n SkuMeter,\n SkuPriceId = strcat(x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType),\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement = case(\n strlen(x_BillingAccountId) > 32, 'MCA',\n strlen(x_BillingAccountId) < 32, 'EA',\n 'Unknown'\n ),\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent = 1.0 * x_ContractedUnitPriceDiscount / ListUnitPrice * 100,\n x_EffectivePeriodEnd = startofmonth(x_EffectivePeriodEnd + 1h),\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent = 1.0 * x_EffectiveUnitPriceDiscount / ContractedUnitPrice * 100,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingSubcategory = case(\n x_SkuPriceType == 'Consumption' and (x_SkuIncludedQuantity > 0 or x_SkuTier > 0), 'Tiered',\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed Spend',\n ''\n ),\n x_PricingUnitDescription,\n x_SkuDescription = Product,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName = coalesce(x_SourceName, 'Cost Management'),\n x_SourceProvider = coalesce(x_SourceProvider, 'Microsoft'),\n x_SourceType = coalesce(x_SourceType, 'PriceSheet'),\n x_SourceVersion = coalesce(x_SourceVersion, '2023-05-01'),\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent = 1.0 * x_TotalUnitPriceDiscount / ListUnitPrice * 100\n}\n\n// Prices_final_v1_2 table\n.create-merge table Prices_final_v1_2 (\n BillingAccountId: string,\n BillingAccountName: string,\n BillingCurrency: string,\n ChargeCategory: string,\n CommitmentDiscountCategory: string,\n CommitmentDiscountType: string,\n CommitmentDiscountUnit: string,\n ContractedUnitPrice: real,\n ListUnitPrice: real,\n PricingCategory: string,\n PricingCurrency: string, // Azure\n PricingUnit: string,\n SkuId: string,\n SkuMeter: string, // Azure\n SkuPriceId: string,\n SkuPriceIdv2: string, // Hubs add-on\n x_BaseUnitPrice: real, // Azure\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure MCA\n x_BillingProfileId: string, // Azure MCA\n x_CommitmentDiscountNormalizedRatio: real, // Hubs add-on\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_ContractedUnitPriceDiscount: real, // Hubs add-on\n x_ContractedUnitPriceDiscountPercent: real, // Hubs add-on\n x_EffectivePeriodEnd: datetime, // Azure\n x_EffectivePeriodStart: datetime, // Azure\n x_EffectiveUnitPrice: real, // Azure\n x_EffectiveUnitPriceDiscount: real, // Hubs add-on\n x_EffectiveUnitPriceDiscountPercent: real, // Hubs add-on\n x_IngestionTime: datetime, // Hubs add-on\n x_PricingBlockSize: real, // Hubs add-on\n x_PricingSubcategory: string, // Hubs add-on\n x_PricingUnitDescription: string, // Azure\n x_SkuDescription: string, // Azure\n x_SkuId: string, // Azure\n x_SkuIncludedQuantity: real, // Azure EA\n x_SkuMeterCategory: string, // Azure\n x_SkuMeterId: string, // Azure\n x_SkuMeterSubcategory: string, // Azure\n x_SkuMeterType: string, // Azure\n x_SkuPriceType: string, // Azure\n x_SkuProductId: string, // Azure\n x_SkuRegion: string, // Azure\n x_SkuServiceFamily: string, // Azure\n x_SkuOfferId: string, // Azure EA\n x_SkuPartNumber: string, // Azure EA\n x_SkuTerm: int, // Azure\n x_SkuTier: real, // Azure MCA\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_TotalUnitPriceDiscount: real, // Hubs add-on\n x_TotalUnitPriceDiscountPercent: real // Hubs add-on\n)\n\n// Update policy for Prices_raw -> Prices_final_v1_2\n.alter table Prices_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Prices_raw\",\n \"Query\": \"Prices_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Cost and usage |=================================================================================================\n// Supported versions:\n// - MS: 1.2-preview, 1.0, 1.0-preview(v1)\n// https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0\n// https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024\n// https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 \n// https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All costs transformed to FOCUS 1.2.', folder='Costs')\nCosts_transform_v1_2()\n{\n let checkString = (column: string, oldValue: string, newValue: string) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n let checkInt = (column: string, oldValue: int, newValue: int) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n let checkReal = (column: string, oldValue: real, newValue: real) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n Costs_raw\n //\n // Dedupe rows\n | extend x_IngestionTime = ingestion_time()\n | extend x_ChargeId = ''\n // TODO: Consider adding a unique charge ID per row\n // hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // // 1. Resource hierarchy (including resource name), highest to lowest\n // BillingAccountId,\n // x_InvoiceSectionId,\n // x_AccountOwnerId,\n // SubAccountId,\n // x_ResourceGroupName,\n // ResourceName,\n // // 2. Resource details\n // ResourceId,\n // RegionId,\n // Tags,\n // CommitmentDiscountId,\n // x_CostCenter,\n // // 4. Meter details\n // SkuPriceId,\n // x_SkuMeterId,\n // x_SkuPartNumber,\n // x_SkuOfferId,\n // x_SkuDetails,\n // // 5. Date\n // ChargePeriodStart\n // ))\n //\n // Identify data quality issues\n // TODO: Remove x_SourceChanges in v1_3 (or later)\n | extend x_SourceChanges = trim_end(',', strcat(\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based', 'InvalidChargeFrequency,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and EffectiveCost > 0, 'InvalidEffectiveCost,', ''),\n iff((isempty(ContractedCost) or ContractedCost == 0) and EffectiveCost != 0, 'MissingContractedCost,', ''),\n iff((isempty(ContractedUnitPrice) or ContractedUnitPrice == 0) and x_EffectiveUnitPrice != 0, 'MissingContractedUnitPrice,', ''),\n iff(ListCost < ContractedCost, 'ListCostLessThanContractedCost,', ''),\n iff(ContractedCost < EffectiveCost, 'ContractedCostLessThanEffectiveCost,', ''),\n iff((isempty(ListCost) or ListCost == 0) and (ContractedCost != 0 or EffectiveCost != 0), 'MissingListCost,', ''),\n iff((isempty(ListUnitPrice) or ListUnitPrice == 0) and (ContractedUnitPrice != 0 or x_EffectiveUnitPrice != 0), 'MissingListUnitPrice,', ''),\n iff((isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001)\n or (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001),\n 'XEffectiveUnitPriceRoundingError,', ''),\n iff(ConsumedQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingConsumedQuantity,', ''),\n iff(PricingQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingPricingQuantity,', ''),\n iff(isempty(ProviderName), 'MissingProviderName,', ''),\n iff(isempty(PublisherName), 'MissingPublisherName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceId), 'MissingResourceId,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceName), 'MissingResourceName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceType), 'MissingResourceType,', ''),\n iff(BilledCost > 0 and x_BilledUnitPrice == 0, 'MissingXBilledUnitPrice,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(x_ResourceType), 'MissingXResourceType,', ''),\n iff(PricingCategory == 'Standard' and isnotempty(CommitmentDiscountId) and ChargeCategory == 'Usage', 'PricingCategoryShouldBeCommitted,', ''),\n iff(x_SkuTerm == '1Year' or x_SkuTerm == '3Years' or x_SkuTerm == '5Years', 'SkuTermShouldBeAnInteger,', '')\n ))\n //\n // Handle provider columns that moved to FOCUS\n | extend PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency)\n //\n // Backup original prices/costs before the merge\n | extend old_ContractedCost = ContractedCost\n | extend old_ContractedUnitPrice = ContractedUnitPrice\n | extend old_ListCost = ListCost\n | extend old_ListUnitPrice = ListUnitPrice\n | extend old_x_EffectiveUnitPrice = x_EffectiveUnitPrice\n //\n // Fix columns needed in other changes\n | extend old_ProviderName = ProviderName, ProviderName = case(\n isnotempty(ProviderName), ProviderName,\n isnotempty(coalesce(x_CostCategories, x_Discount, x_Operation, x_ServiceCode, x_UsageType)), 'AWS',\n isnotempty(coalesce(tostring(UsageAmount), tostring(x_Cost), x_Credits, x_CostType, tostring(x_CurrencyConversionRate), tostring(x_ExportTime), x_Project, x_ServiceId)), 'GCP',\n isnotempty(coalesce(x_BillingProfileId, x_InvoiceSectionId)), 'Microsoft',\n ''\n )\n //\n // Identify source\n | extend x_SourceName = coalesce(x_SourceName, iff(isnotempty(x_BillingProfileId), 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(isnotempty(x_BillingProfileId), 'FocusCost', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, case(\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)) and isempty(SkuPriceDetails) and isnotempty(x_SkuDetails), '1.2-preview',\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)), '1.2',\n isnotempty(coalesce(ChargeClass, CommitmentDiscountStatus, tostring(ConsumedQuantity), ConsumedUnit, tostring(ContractedCost), tostring(ContractedUnitPrice), RegionId, RegionName)), '1.0',\n isnotempty(coalesce(ChargeSubcategory, Region, tostring(UsageQuantity), UsageUnit)), iff(ProviderName == 'Microsoft', '1.0-preview(v1)', '1.0-preview'),\n ''\n ))\n // Append version check error code\n | extend x_SourceChanges = iff(x_SourceVersion == '1.0', x_SourceChanges,\n strcat(x_SourceChanges, iff(isempty(x_SourceChanges), '', ','), iff(x_SourceVersion == '', 'UnknownFocusVersion', 'LegacyFocusVersion'))\n )\n //\n // Fix quantities\n | extend old_PricingQuantity = PricingQuantity, PricingQuantity = case(\n PricingQuantity != 0 or (EffectiveCost == 0 and BilledCost == 0), PricingQuantity,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(EffectiveCost) and EffectiveCost != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0, EffectiveCost / x_EffectiveUnitPrice,\n PricingQuantity\n )\n | extend old_ConsumedQuantity = ConsumedQuantity, ConsumedQuantity = case(\n isnotempty(ConsumedQuantity) and ConsumedQuantity != 0, ConsumedQuantity,\n ChargeCategory == 'Usage', PricingQuantity / coalesce(x_PricingBlockSize, real(1)),\n ConsumedQuantity\n )\n //\n // Populate missing prices -- mapping to on-demand prices requires meter ID and offer ID\n | extend tmp_MissingPrices = ProviderName == 'Microsoft'\n and (isempty(ListUnitPrice) or isempty(ContractedUnitPrice) or ListUnitPrice == 0 or ContractedUnitPrice == 0)\n and x_EffectiveUnitPrice != 0\n and not(CommitmentDiscountCategory == 'Spend' and CommitmentDiscountStatus == 'Unused')\n and isnotempty(strcat(x_SkuMeterId, x_SkuOfferId))\n | as allCosts\n | where tmp_MissingPrices\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(ChargePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | as costsWithMissingPrices\n | join kind=leftouter (\n Prices_final_v1_2\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(x_EffectivePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | where x_SkuPriceType == 'Consumption' and tmp_ReservationPriceLookupKey in ((costsWithMissingPrices | summarize by tmp_ReservationPriceLookupKey))\n | summarize ListUnitPrice = min(ListUnitPrice), ContractedUnitPrice = min(ContractedUnitPrice) by tmp_ReservationPriceLookupKey, x_PricingBlockSize, PricingUnit\n ) on tmp_ReservationPriceLookupKey\n //\n // Select the best price to use for each row\n | extend x_EffectiveUnitPrice = case(\n // If price is a rounding error away from the billed price, use the billed price\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001, x_BilledUnitPrice,\n // If price is a rounding error away from the contracted price, use the contracted price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001, ContractedUnitPrice,\n x_EffectiveUnitPrice\n )\n | extend ContractedUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ContractedUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ContractedUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // If billed price is available, assume the billed price is the same as contracted price to support aggregations\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, x_EffectiveUnitPrice,\n // Otherwise, assume the effective price is the same as contracted price to support aggregations\n x_EffectiveUnitPrice\n )\n | extend ListUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ListUnitPrice) and ListUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ListUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ListUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ListUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // Otherwise, assume the contracted price is the same as list price to support aggregations\n ContractedUnitPrice\n )\n // Calculate missing costs based on new prices -- If cost is already correct, keep that; if not and price is available, recalculate the cost; otherwise, keep the existing cost\n | extend ContractedCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ContractedCost) and ContractedCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedCost,\n // ContractedCost is 0 in all other scenarios...\n // If 0 and there's a billed cost and prices are the same, use BilledCost\n isnotempty(BilledCost) and BilledCost != 0 and ContractedUnitPrice == x_BilledUnitPrice, BilledCost,\n // If 0 and there's a billed cost and prices are the same, use EffectiveCost\n isnotempty(EffectiveCost) and EffectiveCost != 0 and ContractedUnitPrice == x_EffectiveUnitPrice, EffectiveCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0, ContractedUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume EffectiveCost\n isempty(ContractedUnitPrice) or ContractedUnitPrice == 0, EffectiveCost,\n // Fall back to the original value for any unhandled scenarios\n ContractedCost\n )\n | extend ListCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ListCost) and ListCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ListCost,\n // ListCost is 0 in all other scenarios...\n // If 0 and there's a contracted cost and prices are the same, use ContractedCost\n isnotempty(ContractedCost) and ContractedCost != 0 and ListUnitPrice == ContractedUnitPrice, ContractedCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ListUnitPrice) and ListUnitPrice != 0, ListUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume ContractedCost\n isempty(ListUnitPrice) or ListUnitPrice == 0, ContractedCost,\n // Fall back to the original value for any unhandled scenarios\n ListCost\n )\n // Merge the rest of the unmodified cost records and remove excess columns\n | union (allCosts | where not(tmp_MissingPrices))\n | project-away x_PricingBlockSize1, PricingUnit1, ListUnitPrice1, ContractedUnitPrice1, tmp_MissingPrices, tmp_ReservationPriceLookupKey, tmp_ReservationPriceLookupKey1\n //\n | extend SkuPriceDetails = parse_json(SkuPriceDetails)\n | extend Tags = parse_json(Tags)\n | extend x_SkuDetails = parse_json(x_SkuDetails)\n //\n // Handle FOCUS 1.0-preview\n | extend old_ChargeSubcategory = ChargeSubcategory\n | extend old_ChargeCategory = ChargeCategory, ChargeCategory = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Credit', 'Credit',\n ChargeSubcategory == 'Refund', 'Purchase', // We are assuming purchase refunds since we don't have data to indicate usage refunds\n ChargeCategory\n )\n | extend old_ChargeClass = ChargeClass, ChargeClass = case(ChargeSubcategory == 'Refund', 'Correction', ChargeClass)\n //\n // Populate CapacityReservationId when not specified\n | extend CapacityReservationId = coalesce(CapacityReservationId, tostring(coalesce(x_SkuDetails.VMCapacityReservationId, SkuPriceDetails.VMCapacityReservationId, SkuPriceDetails.x_VMCapacityReservationId)))\n | extend old_CapacityReservationStatus = CapacityReservationStatus, CapacityReservationStatus = case(\n isempty(CapacityReservationId), '',\n isnotempty(CapacityReservationStatus), CapacityReservationStatus,\n tolower(x_ResourceType) == 'microsoft.compute/capacityreservationgroups/capacityreservations', 'Unused',\n 'Used'\n )\n //\n // BUG: ChargeFrequency shows \"Usage-Based\" for monthly recurring savings plan purchases\n | extend old_ChargeFrequency = ChargeFrequency, ChargeFrequency = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based' and ProviderName == 'Microsoft' and x_SourceVersion startswith '1.0', 'Recurring', ChargeFrequency)\n //\n // Commitment discounts\n | extend x_CommitmentDiscountNormalizedRatio = case(\n // Calculate from CommitmentDiscountQuantity, if specified\n isnotempty(CommitmentDiscountQuantity) and CommitmentDiscountQuantity != 0, CommitmentDiscountQuantity / PricingQuantity / coalesce(x_PricingBlockSize, real(1)),\n // Not applicable\n isempty(CommitmentDiscountStatus), real(null),\n // Parse from SKU details if not specified explicitly\n toreal(coalesce(x_SkuDetails.RINormalizationRatio, SkuPriceDetails.RINormalizationRatio, SkuPriceDetails.x_RINormalizationRatio, dynamic(1)))\n )\n | extend old_CommitmentDiscountQuantity = CommitmentDiscountQuantity, CommitmentDiscountQuantity = case(\n // FOCUS 1.2\n isnotempty(CommitmentDiscountQuantity), CommitmentDiscountQuantity,\n // FOCUS 1.0-preview, 1.0\n isempty(CommitmentDiscountStatus), real(null),\n CommitmentDiscountCategory == 'Spend', EffectiveCost / coalesce(x_BillingExchangeRate, real(1)),\n CommitmentDiscountCategory == 'Usage' and isnotempty(x_CommitmentDiscountNormalizedRatio), PricingQuantity / coalesce(x_PricingBlockSize, real(1)) * x_CommitmentDiscountNormalizedRatio,\n real(null)\n )\n | extend old_CommitmentDiscountUnit = CommitmentDiscountUnit, CommitmentDiscountUnit = case(\n // FOCUS 1.2\n isnotempty(CommitmentDiscountUnit), CommitmentDiscountUnit,\n // FOCUS 1.0\n isempty(CommitmentDiscountQuantity), '',\n CommitmentDiscountCategory == 'Spend', PricingCurrency,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio == real(1), ConsumedUnit,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio > real(1), strcat('Normalized ', ConsumedUnit),\n ''\n )\n | extend old_CommitmentDiscountStatus = CommitmentDiscountStatus, CommitmentDiscountStatus = case(\n // FOCUS 1.0+\n isnotempty(CommitmentDiscountStatus), CommitmentDiscountStatus,\n // FOCUS 1.0-preview\n ChargeSubcategory == 'Used Commitment', 'Used',\n ChargeSubcategory == 'Unused Commitment', 'Unused',\n ''\n )\n | extend x_CommitmentDiscountUtilizationPotential = case(\n ChargeCategory == 'Purchase', real(0),\n ProviderName == 'Microsoft' and isnotempty(CommitmentDiscountCategory), EffectiveCost,\n CommitmentDiscountCategory == 'Usage', ConsumedQuantity,\n CommitmentDiscountCategory == 'Spend', EffectiveCost,\n real(0)\n )\n | extend x_CommitmentDiscountUtilizationAmount = iff(CommitmentDiscountStatus == 'Used', x_CommitmentDiscountUtilizationPotential, real(0))\n //\n // Pricing\n | extend old_x_AmortizationClass = x_AmortizationClass, x_AmortizationClass = case(\n // FOCUS 1.2\n isnotempty(x_AmortizationClass), x_AmortizationClass,\n // FOCUS 1.0-preview+\n ChargeCategory == 'Purchase' and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeCategory == 'Usage' and isnotempty(CommitmentDiscountId) and isnotempty(CommitmentDiscountStatus), 'Amortized Charge',\n ''\n )\n | extend old_PricingCategory = PricingCategory, PricingCategory = case(\n // FOCUS 1.0+\n isnotempty(PricingCategory), PricingCategory,\n // FOCUS 1.0-preview\n PricingCategory == 'On-Demand', 'Standard',\n PricingCategory == 'Commitment-Based', 'Committed',\n ''\n )\n //\n // Commitment discount utilization\n | extend x_CommitmentDiscountUtilizationPotential = case(\n ChargeCategory == 'Purchase', real(0),\n ProviderName == 'Microsoft' and isnotempty(CommitmentDiscountCategory), EffectiveCost,\n CommitmentDiscountCategory == 'Usage', ConsumedQuantity,\n CommitmentDiscountCategory == 'Spend', EffectiveCost,\n real(0)\n )\n | extend x_CommitmentDiscountUtilizationAmount = iff(CommitmentDiscountStatus == 'Used', x_CommitmentDiscountUtilizationPotential, real(0))\n //\n // BUG: Fix ContractedCost that has bad values\n | extend ContractedCost = iff(ProviderName == 'Microsoft' and isnotempty(PricingQuantity) and isnotempty(x_PricingBlockSize) and ContractedCost != ContractedUnitPrice * PricingQuantity, ContractedUnitPrice * PricingQuantity, ContractedCost)\n //\n // Handle FOCUS 1.0-preview UsageQuantity/Unit\n | extend ConsumedQuantity = iff(ChargeCategory == 'Usage', coalesce(ConsumedQuantity, UsageQuantity, UsageAmount), real(null))\n | extend old_ConsumedUnit = ConsumedUnit, ConsumedUnit = iff(ChargeCategory == 'Usage' and isnotempty(ConsumedQuantity), coalesce(ConsumedUnit, UsageUnit, 'Units'), '')\n //\n // Convert IDs to lowercase for consistency\n | extend BillingAccountId = tolower(BillingAccountId)\n | extend CommitmentDiscountId = tolower(CommitmentDiscountId)\n //\n // BUG: Remove EffectiveCost for commitment discount purchases\n | extend old_EffectiveCost = EffectiveCost, EffectiveCost = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), real(0), EffectiveCost)\n | extend old_x_EffectiveCostInUsd = x_EffectiveCostInUsd, x_EffectiveCostInUsd = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), real(0), x_EffectiveCostInUsd)\n //\n // Clean up resource columns\n | extend old_ResourceId = ResourceId, ResourceId = case(\n isnotempty(ResourceId), ResourceId,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), CommitmentDiscountId,\n ResourceId\n )\n | extend old_ResourceName = ResourceName, ResourceName = tolower(case(\n isnotempty(ResourceName), ResourceName,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountName), CommitmentDiscountName,\n isnotempty(ResourceId), parse_resourceid(ResourceId).ResourceName,\n ResourceName\n ))\n | extend old_x_ResourceType = x_ResourceType, x_ResourceType = case(\n isnotempty(x_ResourceType), x_ResourceType,\n isnotempty(ResourceId), parse_resourceid(ResourceId).x_ResourceType,\n x_ResourceType\n )\n | extend old_ResourceType = ResourceType, ResourceType = case(\n // Use existing resource type display name unless it's an internal resource type ID\n isnotempty(ResourceType) and tolower(ResourceType) != tolower(x_ResourceType) and ResourceType !contains '/', ResourceType,\n // Use CommitmentDiscountType for commitment discount purchases\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountType), CommitmentDiscountType,\n // Look up display name from internal type\n isnotempty(x_ResourceType), coalesce(tostring(resource_type(x_ResourceType).SingularDisplayName), ResourceType, x_ResourceType),\n ResourceType\n )\n //\n // Handle missing values\n | extend old_PublisherName = PublisherName, PublisherName = case(PublisherName == 'Microsoft Corporation', 'Microsoft', isnotempty(PublisherName), PublisherName, x_PublisherCategory == 'Cloud Provider', ProviderName, '')\n //\n // Handle FOCUS 1.0-preview Region column\n | extend old_Region = Region\n | extend old_RegionId = RegionId, RegionId = coalesce(RegionId, iff(ProviderName == 'Microsoft', replace_string(tolower(Region), ' ', ''), Region))\n | extend RegionName = coalesce(RegionName, Region)\n //\n // SKU properties\n | extend x_SkuCoreCount = toint(coalesce(SkuPriceDetails.CoreCount, SkuPriceDetails.x_VCPUs, x_SkuDetails.VCPUs, SkuPriceDetails.x_VCores, x_SkuDetails.VCores, SkuPriceDetails.x_vCores, x_SkuDetails.vCores))\n | extend x_SkuInstanceType = tostring(coalesce(SkuPriceDetails.InstanceType, SkuPriceDetails.x_ServiceType, x_SkuDetails.ServiceType, SkuPriceDetails.x_ServerSku, x_SkuDetails.ServerSku))\n | extend x_SkuOperatingSystem = case(\n isnotempty(SkuPriceDetails.OperatingSystem), SkuPriceDetails.OperatingSystem,\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Canonical', 'Linux',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL', 'Windows Server',\n x_SkuMeterSubcategory endswith ' Series Windows', 'Windows Server',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType)\n )\n | extend x_ConsumedCoreHours = iff(ConsumedUnit == 'Hours' and isnotempty(x_SkuCoreCount), x_SkuCoreCount * ConsumedQuantity, real(null))\n | extend SkuPriceDetails = case(\n // FOCUS 1.2\n isnotempty(SkuPriceDetails), SkuPriceDetails,\n // FOCUS 1.0-preview, 1.0\n parse_json(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(tostring(x_SkuDetails)\n // Prefix all keys with x_ first to avoid double-prefixing\n , @'([\\{,])\"', @'\\1\"x_')\n // CoreCount for number of CPUs/vCPUs/cores/vCores\n , @'\"x_(VCPUs|VCores|vCores)\":', @'\"CoreCount\":')\n // TODO: DiskMaxIops for disk I/O operations per second (IOPS)\n // TODO: DiskSpace for disk size in GiB\n // TODO: DiskType for the kind of disk (e.g., SSD, HDD, NVMe)\n // TODO: GpuCount for the number of GPUs\n // InstanceType for the resource size/SKU (e.g., ArmSkuName)\n , @'\"x_(ServerSku|ServiceType)\":', @'\"InstanceType\":')\n // TODO: InstanceSeries for the size family/series\n // TODO: MemorySize for the RAM in GiB\n // TODO: NetworkMaxIops for network I/O operations per second (IOPS)\n // TODO: NetworkMaxThroughput for network max throughput for data transfer in Mbps\n // OperatingSystem for the OS name\n , @'(\"x_ImageType\":\"Canonical\")', @'\\1,\"OperatingSystem\":\"Linux\"')\n , @'(\"x_ImageType\":\"Windows Server( BYOL)?\")', @'\\1,\"OperatingSystem\":\"Windows Server\"')\n , @'(\"x_ImageType\":(\"[^\"]+\"))', @'\\1,\"OperatingSystem\":\\2')\n // TODO: Redundancy for the level of redundancy (e.g., Local, Zonal, Global)\n // TODO: StorageClass for the tier of storage (e.g., Hot, Archive, Nearline)\n )\n )\n | extend SkuPriceDetails = iff(isempty(SkuPriceDetails.OperatingSystem) and isnotempty(x_SkuOperatingSystem),\n parse_json(replace_string(tostring(SkuPriceDetails), '}', strcat(@',\"OperatingSystem\":\"', x_SkuOperatingSystem, '\"}'))),\n SkuPriceDetails)\n //\n // Azure Hybrid Benefit\n | extend tmp_SqlAhb = tolower(coalesce(x_SkuDetails.AHB, SkuPriceDetails.x_AHB))\n | extend x_SkuLicenseType = case(\n ChargeCategory != 'Usage', '',\n x_SkuMeterCategory in ('Virtual Machines', 'Virtual Machine Licenses') and (x_SkuMeterSubcategory contains 'Windows' or coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL'), 'Windows Server',\n isnotempty(tmp_SqlAhb) or x_SkuMeterSubcategory == 'SQL Server Azure Hybrid Benefit', 'SQL Server',\n ''\n )\n | extend x_SkuLicenseStatus = case(\n isempty(x_SkuLicenseType), '',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL' or tmp_SqlAhb == 'true' or x_SkuMeterSubcategory contains 'Azure Hybrid Benefit', 'Enabled',\n (x_SkuMeterSubcategory contains 'Windows') or tmp_SqlAhb == 'false', 'Not Enabled',\n ''\n )\n | extend x_SkuLicenseQuantity = case(\n isempty(x_SkuCoreCount) or isempty(x_SkuLicenseType), int(null),\n x_SkuCoreCount <= 8, int(8),\n x_SkuCoreCount > 8, x_SkuCoreCount,\n int(null)\n )\n | extend x_SkuLicenseUnit = iff(isnotempty(x_SkuLicenseQuantity), 'Cores', '')\n //\n // Savings\n | extend x_CommitmentDiscountSavings = iff(isempty(ContractedCost) or ContractedCost == 0 or ContractedCost - EffectiveCost < 0.0001, real(0), ContractedCost - EffectiveCost)\n | extend x_NegotiatedDiscountSavings = iff(isempty(ListCost) or ListCost == 0 or ListCost - ContractedCost < 0.0001, real(0), ListCost - ContractedCost)\n | extend x_TotalSavings = iff(isempty(ListCost) or ListCost == 0 or ListCost - EffectiveCost < 0.0001, real(0), ListCost - EffectiveCost)\n | extend x_CommitmentDiscountPercent = iff(isempty(ContractedUnitPrice) or ContractedUnitPrice == 0 or ContractedUnitPrice - x_EffectiveUnitPrice < 0.0001, real(0), (ContractedUnitPrice - x_EffectiveUnitPrice) / ContractedUnitPrice)\n | extend x_NegotiatedDiscountPercent = iff(isempty(ListUnitPrice) or ListUnitPrice == 0 or ListUnitPrice - ContractedUnitPrice < 0.0001, real(0), (ListUnitPrice - ContractedUnitPrice) / ListUnitPrice)\n | extend x_TotalDiscountPercent = iff(isempty(ListUnitPrice) or ListUnitPrice == 0 or ListUnitPrice - x_EffectiveUnitPrice < 0.0001, real(0), (ListUnitPrice - x_EffectiveUnitPrice) / ListUnitPrice)\n //\n // Minor fixes\n | extend old_BillingPeriodEnd = BillingPeriodEnd, BillingPeriodEnd = startofmonth(BillingPeriodEnd)\n | extend old_BillingPeriodStart = BillingPeriodStart, BillingPeriodStart = startofmonth(BillingPeriodStart)\n //\n // Sort columns and apply final transforms\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId,\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd,\n BillingPeriodStart,\n CapacityReservationId,\n CapacityReservationStatus,\n ChargeCategory,\n ChargeClass,\n ChargeDescription,\n ChargeFrequency,\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId,\n CommitmentDiscountName,\n CommitmentDiscountQuantity,\n CommitmentDiscountStatus,\n CommitmentDiscountType,\n CommitmentDiscountUnit,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost = coalesce(ContractedCost, x_OnDemandCost, x_Cost),\n ContractedUnitPrice = coalesce(ContractedUnitPrice, x_OnDemandUnitPrice),\n EffectiveCost,\n InvoiceId = coalesce(InvoiceId, x_InvoiceId),\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory,\n PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency),\n PricingQuantity,\n PricingUnit,\n ProviderName,\n PublisherName,\n RegionId,\n RegionName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory, // TODO: Populate ServiceSubcategory from ServiceName when missing\n SkuId,\n SkuMeter = coalesce(SkuMeter, x_SkuMeterName),\n SkuPriceDetails,\n SkuPriceId,\n SubAccountId,\n SubAccountName = iff(isempty(SubAccountId), '', SubAccountName),\n SubAccountType,\n Tags,\n x_AccountId = iff(x_AccountId == '-2', '', x_AccountId),\n x_AccountName = iff(x_AccountId == '-2', '', x_AccountName),\n x_AccountOwnerId = iff(x_AccountId == '-2', '', x_AccountOwnerId),\n x_AmortizationClass,\n x_BilledCostInUsd,\n x_BilledUnitPrice,\n x_BillingAccountAgreement = case(\n ProviderName == 'Microsoft' and x_BillingAccountId == x_BillingProfileId, 'EA',\n ProviderName == 'Microsoft' and x_BillingAccountId != x_BillingProfileId, 'MCA',\n ProviderName\n ),\n x_BillingAccountId,\n x_BillingAccountName,\n x_BillingExchangeRate,\n x_BillingExchangeRateDate,\n x_BillingItemCode,\n x_BillingItemName,\n x_BillingProfileId,\n x_BillingProfileName,\n x_ChargeId,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountPercent,\n x_CommitmentDiscountSavings,\n x_CommitmentDiscountSpendEligibility = '', // TODO: Add x_CommitmentDiscountSpendEligibility for Costs\n x_CommitmentDiscountUsageEligibility = '', // TODO: Add x_CommitmentDiscountUsageEligibility for Costs\n x_CommitmentDiscountUtilizationAmount,\n x_CommitmentDiscountUtilizationPotential,\n x_CommodityCode,\n x_CommodityName,\n x_ComponentName,\n x_ComponentType,\n x_ConsumedCoreHours,\n x_ContractedCostInUsd = coalesce(x_ContractedCostInUsd, x_OnDemandCostInUsd),\n x_CostAllocationRuleName,\n x_CostCategories = parse_json(x_CostCategories),\n x_CostCenter,\n x_CostType,\n x_Credits = parse_json(x_Credits),\n x_CurrencyConversionRate,\n x_CustomerId,\n x_CustomerName,\n x_Discount = parse_json(x_Discount),\n x_EffectiveCostInUsd,\n x_EffectiveUnitPrice,\n x_ExportTime,\n x_IngestionTime,\n x_InstanceID,\n x_InvoiceIssuerId,\n x_InvoiceSectionId = case(\n x_InvoiceSectionId == '-2', '',\n x_InvoiceSectionId\n ),\n x_InvoiceSectionName = case(\n x_InvoiceSectionName == 'Unassigned', '',\n x_InvoiceSectionName\n ),\n x_ListCostInUsd,\n x_Location,\n x_NegotiatedDiscountPercent,\n x_NegotiatedDiscountSavings,\n x_Operation,\n x_OwnerAccountID,\n x_PartnerCreditApplied,\n x_PartnerCreditRate,\n x_PricingBlockSize,\n x_PricingSubcategory,\n x_PricingUnitDescription = iff(x_PricingUnitDescription == 'Unassigned', '', x_PricingUnitDescription),\n x_Project,\n x_PublisherCategory,\n x_PublisherId,\n x_ResellerId,\n x_ResellerName,\n x_ResourceGroupName = tolower(x_ResourceGroupName),\n x_ResourceType,\n x_ServiceCode,\n x_ServiceId,\n x_ServiceModel, // TODO: Populate from ServiceName when missing\n x_ServicePeriodEnd,\n x_ServicePeriodStart,\n x_SkuCoreCount,\n x_SkuDescription,\n x_SkuDetails,\n x_SkuInstanceType,\n x_SkuIsCreditEligible,\n x_SkuLicenseQuantity,\n x_SkuLicenseStatus,\n x_SkuLicenseType,\n x_SkuLicenseUnit,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterSubcategory,\n x_SkuOfferId,\n x_SkuOperatingSystem,\n x_SkuOrderId,\n x_SkuOrderName,\n x_SkuPartNumber,\n x_SkuPlanName,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuTerm,\n x_SkuTier,\n x_SourceChanges,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceValues = bag_merge(\n checkString('BillingPeriodEnd', old_BillingPeriodEnd, BillingPeriodEnd),\n checkString('BillingPeriodStart', old_BillingPeriodStart, BillingPeriodStart),\n checkString('CapacityReservationStatus', old_CapacityReservationStatus, CapacityReservationStatus),\n checkString('ChargeCategory', old_ChargeCategory, ChargeCategory),\n checkString('ChargeClass', old_ChargeClass, ChargeClass),\n checkString('ChargeSubcategory', old_ChargeSubcategory, ''), // Not included in final schema; use empty string\n checkString('ChargeFrequency', old_ChargeFrequency, ChargeFrequency),\n checkReal('CommitmentDiscountQuantity', old_CommitmentDiscountQuantity, CommitmentDiscountQuantity),\n checkString('CommitmentDiscountUnit', old_CommitmentDiscountUnit, CommitmentDiscountUnit),\n checkString('CommitmentDiscountStatus', old_CommitmentDiscountStatus, CommitmentDiscountStatus),\n checkReal('ConsumedQuantity', old_ConsumedQuantity, ConsumedQuantity),\n checkString('ConsumedUnit', old_ConsumedUnit, ConsumedUnit),\n checkReal('ContractedCost', old_ContractedCost, ContractedCost),\n checkReal('ContractedUnitPrice', old_ContractedUnitPrice, ContractedUnitPrice),\n checkReal('EffectiveCost', old_EffectiveCost, EffectiveCost),\n checkReal('ListCost', old_ListCost, ListCost),\n checkReal('ListUnitPrice', old_ListUnitPrice, ListUnitPrice),\n checkString('PricingCategory', old_PricingCategory, PricingCategory),\n checkReal('PricingQuantity', old_PricingQuantity, PricingQuantity),\n checkString('ProviderName', old_ProviderName, ProviderName),\n checkString('PublisherName', old_PublisherName, PublisherName),\n checkString('Region', old_Region, ''), // Not included in final schema; use empty string\n checkString('RegionId', old_RegionId, RegionId),\n checkString('ResourceId', old_ResourceId, ResourceId),\n checkString('ResourceName', old_ResourceName, ResourceName),\n checkString('ResourceType', old_ResourceType, ResourceType),\n checkString('x_AmortizationClass', old_x_AmortizationClass, x_AmortizationClass),\n checkReal('x_EffectiveCostInUsd', old_x_EffectiveCostInUsd, x_EffectiveCostInUsd),\n checkReal('x_EffectiveUnitPrice', old_x_EffectiveUnitPrice, x_EffectiveUnitPrice),\n checkString('x_ResourceType', old_x_ResourceType, x_ResourceType)\n ),\n x_SourceVersion,\n x_SubproductName,\n x_TotalDiscountPercent,\n x_TotalSavings,\n x_UsageType\n}\n\n// Costs_final_v1_2 table\n.create-merge table Costs_final_v1_2 (\n AvailabilityZone: string,\n BilledCost: real,\n BillingAccountId: string,\n BillingAccountName: string,\n BillingAccountType: string,\n BillingCurrency: string,\n BillingPeriodEnd: datetime,\n BillingPeriodStart: datetime,\n CapacityReservationId: string,\n CapacityReservationStatus: string,\n ChargeCategory: string,\n ChargeClass: string,\n ChargeDescription: string,\n ChargeFrequency: string,\n ChargePeriodEnd: datetime,\n ChargePeriodStart: datetime,\n CommitmentDiscountCategory: string,\n CommitmentDiscountId: string,\n CommitmentDiscountName: string,\n CommitmentDiscountQuantity: real,\n CommitmentDiscountStatus: string,\n CommitmentDiscountType: string,\n CommitmentDiscountUnit: string,\n ConsumedQuantity: real,\n ConsumedUnit: string,\n ContractedCost: real,\n ContractedUnitPrice: real,\n EffectiveCost: real,\n InvoiceId: string,\n InvoiceIssuerName: string,\n ListCost: real,\n ListUnitPrice: real,\n PricingCategory: string,\n PricingCurrency: string,\n PricingQuantity: real,\n PricingUnit: string,\n ProviderName: string,\n PublisherName: string,\n RegionId: string,\n RegionName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n ServiceCategory: string,\n ServiceName: string,\n ServiceSubcategory: string,\n SkuId: string,\n SkuMeter: string,\n SkuPriceDetails: dynamic,\n SkuPriceId: string,\n SubAccountId: string,\n SubAccountName: string,\n SubAccountType: string,\n Tags: dynamic,\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_AmortizationClass: string, // Azure 1.2-preview+\n x_BilledCostInUsd: real, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: real, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: real, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingItemCode: string, // Alibaba 1.0\n x_BillingItemName: string, // Alibaba 1.0\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_CommitmentDiscountNormalizedRatio: real, // Azure 1.2-preview+\n x_CommitmentDiscountPercent: real, // Hubs add-on\n x_CommitmentDiscountSavings: real, // Hubs add-on\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_CommitmentDiscountUtilizationAmount: real, // Hubs add-on\n x_CommitmentDiscountUtilizationPotential: real, // Hubs add-on\n x_CommodityCode: string, // Alibaba 1.0\n x_CommodityName: string, // Alibaba 1.0\n x_ComponentName: string, // Tencent 1.0\n x_ComponentType: string, // Tencent 1.0\n x_ConsumedCoreHours: real, // Hubs add-on\n x_ContractedCostInUsd: real, // Azure 1.0+\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: dynamic, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_CostType: string, // GCP Jan 2024\n x_Credits: dynamic, // GCP Jan 2024\n x_CurrencyConversionRate: real, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: dynamic, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: real, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: real, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024 / Tencent 1.0\n x_IngestionTime: datetime, // Hubs add-on\n x_InstanceID: string, // Alibaba 1.0\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: real, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_NegotiatedDiscountPercent:real, // Hubs add-on\n x_NegotiatedDiscountSavings:real, // Hubs add-on\n x_Operation: string, // AWS 1.0\n x_OwnerAccountID: string, // Tencent 1.0\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: real, // Azure 1.0-preview(v1)+\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServiceModel: string, // Azure 1.2-preview+\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuCoreCount: int, // Hubs add-on\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: dynamic, // Azure 1.0-preview(v1)+\n x_SkuInstanceType: string, // Hubs add-on\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuLicenseQuantity: int, // Hubs add-on\n x_SkuLicenseStatus: string, // Hubs add-on\n x_SkuLicenseType: string, // Hubs add-on\n x_SkuLicenseUnit: string, // Hubs add-on\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOperatingSystem: string, // Hubs add-on\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuPlanName: string, // Azure 1.2-preview+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceChanges: string, // Hubs add-on\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceValues: dynamic, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubproductName: string, // Tencent 1.0\n x_TotalDiscountPercent: real, // Hubs add-on\n x_TotalSavings: real, // Hubs add-on\n x_UsageType: string // AWS 1.0\n)\n\n// Update policy for Costs_raw -> Costs_final_v1_2 table\n.alter table Costs_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Costs_raw\",\n \"Query\": \"Costs_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Actual costs |===================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_transform_v1_2 function\n.create-or-alter function\nwith (docstring='ActualCost exports transformed to FOCUS 1.2.', folder='Costs')\nActualCosts_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n ActualCosts_raw\n | where ChargeType in ('Purchase', 'Refund') and isnotempty(ReservationId)\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: PublisherName, x_PublisherCategory, x_Environment\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory), take_any(ServiceSubcategory), take_any(x_ServiceModel) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodEnd = Date + 1d,\n ChargePeriodStart = Date,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SkuId = '',\n SkuMeter = MeterName,\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = iff(isempty(SubscriptionId), '', SubscriptionName),\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentType = '',\n x_ComponentName = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = '',\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel,\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for ActualCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": true,\n \"Source\": \"ActualCosts_raw\",\n \"Query\": \"ActualCosts_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Amortized costs |================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_transform_v1_2 function\n.create-or-alter function\nwith (docstring='ActualCost exports transformed to FOCUS 1.2.', folder='Costs')\nAmortizedCosts_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n AmortizedCosts_raw\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: PublisherName, x_PublisherCategory, x_Environment\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory), take_any(ServiceSubcategory), take_any(x_ServiceModel) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodEnd = Date + 1d,\n ChargePeriodStart = Date,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SkuId = '',\n SkuMeter = MeterName,\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = iff(isempty(SubscriptionId), '', SubscriptionName),\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentType = '',\n x_ComponentName = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = '',\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel,\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for AmortizedCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": true,\n \"Source\": \"AmortizedCosts_raw\",\n \"Query\": \"AmortizedCosts_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All commitment discount usage transformed to FOCUS 1.2. This includes reservationdeatils_raw.', folder='Commitment discounts')\nCommitmentDiscountUsage_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n CommitmentDiscountUsage_raw\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Handle resource columns\n | extend ResourceId = tolower(InstanceId)\n | extend tmp_ResourceDetails = parse_resourceid(ResourceId)\n | extend ResourceName = tostring(tmp_ResourceDetails.ResourceName)\n | extend SubAccountId = tostring(tmp_ResourceDetails.SubAccountId)\n | extend x_ResourceGroupName = tostring(tmp_ResourceDetails.x_ResourceGroupName)\n | extend x_ResourceType = tostring(tmp_ResourceDetails.x_ResourceType)\n | lookup kind=leftouter (ResourceTypes | distinct x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n | lookup kind=leftouter (Services | distinct x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n //\n // Sort columns and apply final transforms\n | project\n ChargePeriodEnd = UsageDate + 1d,\n ChargePeriodStart = UsageDate,\n CommitmentDiscountCategory = 'Usage',\n CommitmentDiscountId = tolower(strcat('/providers/microsoft.capacity/reservationorders/', ReservationOrderId, '/reservations/', ReservationId)),\n CommitmentDiscountQuantity = UsedHours * InstanceFlexibilityRatio,\n CommitmentDiscountType = 'Reservation',\n CommitmentDiscountUnit = case(\n InstanceFlexibilityRatio == 1, 'Hours',\n InstanceFlexibilityRatio != 1, 'Normalized Hours',\n ''\n ),\n ConsumedQuantity = UsedHours,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SubAccountId,\n x_CommitmentDiscountCommittedCount = TotalReservedQuantity,\n x_CommitmentDiscountCommittedAmount = ReservedHours,\n // TODO: Is this needed? -- x_CommitmentDiscountKind = Kind,\n x_CommitmentDiscountNormalizedGroup = iff(InstanceFlexibilityGroup == 'NA', '', InstanceFlexibilityGroup),\n x_CommitmentDiscountNormalizedRatio = InstanceFlexibilityRatio,\n x_IngestionTime = ingestion_time(),\n x_ResourceGroupName,\n x_ResourceType,\n // x_RowId = hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // CommitmentDiscountId,\n // ResourceId,\n // ChargePeriodStart\n // )),\n x_ServiceModel,\n x_SkuOrderId = ReservationOrderId,\n x_SkuSize = iff(SkuName == 'NA', '', SkuName),\n x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName)),\n x_SourceProvider = coalesce(x_SourceProvider, ProviderName),\n x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationDetails', '')),\n x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2024-03-01', ''))\n}\n\n// CommitmentDiscountUsage_final_v1_2 table\n.create-merge table CommitmentDiscountUsage_final_v1_2 (\n ChargePeriodEnd: datetime, // Hubs add-on\n ChargePeriodStart: datetime, // MS 2023-03-01\n CommitmentDiscountCategory: string, // Hubs add-on\n CommitmentDiscountId: string, // MS 2023-03-01\n CommitmentDiscountQuantity: real, // MS 2023-03-01\n CommitmentDiscountType: string, // Hubs add-on\n CommitmentDiscountUnit: string, // Hubs add-on\n ConsumedQuantity: real, // MS 2023-03-01\n ProviderName: string, // Hubs add-on\n ResourceId: string, // MS 2023-03-01\n ResourceName: string, // Hubs add-on\n ResourceType: string, // Hubs add-on\n ServiceCategory: string, // Hubs add-on\n ServiceName: string, // Hubs add-on\n ServiceSubcategory: string, // Hubs add-on\n SubAccountId: string, // Hubs add-on\n x_CommitmentDiscountCommittedCount: real, // MS 2023-03-01\n x_CommitmentDiscountCommittedAmount: real, // MS 2023-03-01\n x_CommitmentDiscountNormalizedGroup: string, // MS 2023-03-01\n x_CommitmentDiscountNormalizedRatio: real, // MS 2023-03-01\n x_IngestionTime: datetime, // Hubs add-on\n x_ResourceGroupName: string, // Hubs add-on\n x_ResourceType: string, // Hubs add-on\n x_ServiceModel: string, // Hubs add-on\n x_SkuOrderId: string, // MS 2023-03-01\n x_SkuSize: string, // MS 2023-03-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string // Hubs add-on\n)\n\n// Update policy for CommitmentDiscountUsage_raw -> CommitmentDiscountUsage_final_v1_2 table\n.alter table CommitmentDiscountUsage_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"CommitmentDiscountUsage_raw\",\n \"Query\": \"CommitmentDiscountUsage_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All recommendations transformed to FOCUS 1.2.', folder='Recommendations')\nRecommendations_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Recommendations_raw\n | extend x_IngestionTime = ingestion_time()\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationRecommendations', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Convert JSON cost columns to real\n | extend CostWithNoReservedInstances = case(isnotempty(CostWithNoReservedInstances), CostWithNoReservedInstances, isnotempty(CostWithNoReservedInstancesJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, CostWithNoReservedInstancesJson)), CostWithNoReservedInstances)\n | extend NetSavings = case(isnotempty(NetSavings), NetSavings, isnotempty(NetSavingsJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, NetSavingsJson)), NetSavings)\n | extend TotalCostWithReservedInstances = case(isnotempty(TotalCostWithReservedInstances), TotalCostWithReservedInstances, isnotempty(TotalCostWithReservedInstancesJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, TotalCostWithReservedInstancesJson)), TotalCostWithReservedInstances)\n //\n // Parse x_RecommendationDetails from JSON string (ARG queries serialize to string for Parquet compatibility)\n | extend x_RecommendationDetails = iff(gettype(x_RecommendationDetails) == 'string', parse_json(tostring(x_RecommendationDetails)), x_RecommendationDetails)\n //\n // Normalize x_RecommendationDetails keys to x_PascalCase (Advisor extendedProperties use camelCase)\n // Guard: inject a placeholder key so mv-apply doesn't drop rows with null/empty bags\n | extend x_RecommendationDetails = bag_merge(coalesce(x_RecommendationDetails, dynamic({})), bag_pack('__placeholder', ''))\n | mv-apply k = bag_keys(x_RecommendationDetails) on (\n where isnotempty(tostring(k)) and tostring(k) != '__placeholder'\n | extend newKey = iff(tostring(k) startswith 'x_', tostring(k), strcat('x_', toupper(substring(tostring(k), 0, 1)), substring(tostring(k), 1)))\n | summarize x_RecommendationDetails = make_bag(bag_pack(newKey, x_RecommendationDetails[tostring(k)]))\n )\n //\n // Build recommendation details\n | lookup kind=leftouter (Regions | summarize RegionName = make_set(RegionName)[0] by Location = RegionId) on Location\n | extend x_RecommendationDetails = case(\n // Use incoming x_RecommendationDetails first\n isnotempty(x_RecommendationDetails), x_RecommendationDetails,\n // Create one for reservation recommendations if needed\n x_SourceType == 'ReservationRecommendations', bag_pack(\n 'CommitmentDiscountNormalizedGroup', InstanceFlexibilityGroup,\n 'CommitmentDiscountNormalizedRatio', InstanceFlexibilityRatio,\n 'CommitmentDiscountNormalizedSize', NormalizedSize,\n 'CommitmentDiscountResourceType', ResourceType,\n 'CommitmentDiscountScope', Scope,\n 'LookbackPeriodDuration', case(\n LookBackPeriod matches regex @'^Last([0-9]+)Days$', replace_regex(LookBackPeriod, @'^Last([0-9]+)Days$', @'P\\1D'),\n LookBackPeriod matches regex @'^[0-9]+$', strcat('P', LookBackPeriod, 'D'),\n ''\n ),\n 'LookbackPeriodStart', FirstUsageDate,\n 'RecommendedQuantity', RecommendedQuantity,\n 'RecommendedQuantityNormalized', RecommendedQuantityNormalized,\n 'RegionId', Location,\n 'RegionName', RegionName,\n 'SkuMeterId', MeterId,\n 'SkuPriceDetails', SkuProperties,\n 'SkuSize', coalesce(SKU, SkuName),\n 'SkuTerm', isoMonths(Term)\n ),\n dynamic({})\n )\n //\n // Prefer specified date, then fall back to generating a date based on reservation recommendation lookback period, then validate to ensure it's not in the future\n | extend x_RecommendationDate = coalesce(x_RecommendationDate, FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d))\n | extend x_RecommendationDate = iff(x_RecommendationDate > now(), startofday(now()), x_RecommendationDate)\n //\n // Derive x_ResourceType from ResourceId\n | extend tmp_ResourceType = tostring(parse_resourceid(ResourceId).x_ResourceType)\n | extend x_RecommendationDetails = iff(isnotempty(tmp_ResourceType), bag_merge(bag_pack('x_ResourceType', tmp_ResourceType), x_RecommendationDetails), x_RecommendationDetails)\n //\n // Set ResourceType display name from x_ResourceType code\n | extend ResourceType = coalesce(ResourceType, tostring(resource_type(tmp_ResourceType).SingularDisplayName), tmp_ResourceType)\n //\n | project\n ProviderName,\n ResourceId = tolower(ResourceId), // Force lowercase for consistent grouping/filtering\n ResourceName = tolower(iff(tmp_ResourceType =~ 'microsoft.resources/subscriptions', coalesce(SubAccountName, ResourceName), ResourceName)), // Use subscription name for subscription-level recommendations\n ResourceType,\n SubAccountId = coalesce(SubAccountId, iff(isnotempty(SubscriptionId), strcat('/subscriptions/', SubscriptionId), '')),\n SubAccountName,\n x_EffectiveCostAfter = coalesce(x_EffectiveCostAfter, TotalCostWithReservedInstances),\n x_EffectiveCostBefore = coalesce(x_EffectiveCostBefore, CostWithNoReservedInstances),\n x_EffectiveCostSavings = coalesce(x_EffectiveCostSavings, NetSavings, toreal(x_RecommendationDetails.x_SavingsAmount), toreal(x_RecommendationDetails.x_AnnualSavingsAmount) / 12),\n x_IngestionTime,\n x_RecommendationCategory, // TODO: Set for reservation recommendations\n x_RecommendationDate,\n x_RecommendationDescription = coalesce(x_RecommendationDescription, tostring(x_RecommendationDetails.x_RecommendationSolution), tostring(x_RecommendationDetails.x_RecommendationSubCategory)),\n x_RecommendationDetails,\n x_RecommendationId = tolower(x_RecommendationId), // TODO: Set for reservation recommendations; force lowercase for consistent grouping/filtering\n x_ResourceGroupName = tolower(x_ResourceGroupName), // Force lowercase for consistent grouping/filtering\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n// Recommendations_final_v1_2 table\n.create-merge table Recommendations_final_v1_2 (\n ProviderName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n SubAccountId: string,\n SubAccountName: string,\n x_EffectiveCostAfter: real,\n x_EffectiveCostBefore: real,\n x_EffectiveCostSavings: real,\n x_IngestionTime: datetime,\n x_RecommendationCategory: string,\n x_RecommendationDate: datetime,\n x_RecommendationDescription: string,\n x_RecommendationDetails: dynamic,\n x_RecommendationId: string,\n x_ResourceGroupName: string,\n x_SourceName: string,\n x_SourceProvider: string,\n x_SourceType: string,\n x_SourceVersion: string\n)\n\n// Update policy for Recommendations_raw -> Recommendations_final_v1_2 table\n.alter table Recommendations_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Recommendations_raw\",\n \"Query\": \"Recommendations_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All transactions transformed to FOCUS 1.2.', folder='Transactions')\nTransactions_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Transactions_raw\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationTransactions', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Handle BillingPeriodStart/End\n | extend BillingMonth = tostring(BillingMonth)\n | extend BillingPeriodStart = iff(isempty(BillingMonth), datetime(null), todatetime(strcat(substring(BillingMonth, 0, 4), \"-\", substring(BillingMonth, 4, 2), \"-\", substring(BillingMonth, 6, 2))))\n | extend BillingPeriodEnd = iff(isempty(BillingMonth), datetime(null), startofmonth(endofmonth(BillingPeriodStart) + 1d))\n //\n // Sort columns and apply final transforms\n | project\n BilledCost = Amount,\n BillingAccountId = case(\n BillingProfileId startswith '/', BillingProfileId,\n isnotempty(CurrentEnrollmentId), strcat('/providers/Microsoft.Billing/billingAccounts/', CurrentEnrollmentId),\n isnotempty(BillingProfileId), strcat('/providers/Microsoft.Billing/billingProfiles/', BillingProfileId),\n ''\n ),\n BillingAccountName = coalesce(BillingProfileName, CurrentEnrollmentId),\n BillingCurrency = Currency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory = case(\n EventType in ('Cancel', 'Purchase', 'Refund'), 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = case(\n EventType == 'Cancel', 'Cancel', // FOCUS does not handle this scenario\n EventType == 'Refund', 'Correction',\n ''\n ),\n ChargeDescription = Description,\n ChargeFrequency = case(\n BillingFrequency == 'OneTime', 'One-Time',\n BillingFrequency == 'Recurring', 'Recurring',\n BillingFrequency\n ),\n ChargePeriodStart = EventDate,\n InvoiceId,\n PricingQuantity = Quantity,\n PricingUnit = 'Reservations',\n ProviderName,\n RegionId = Region,\n RegionName = Region,\n SubAccountId = iff(isempty(PurchasingSubscriptionGuid), '', strcat('/subscriptions/', PurchasingSubscriptionGuid)),\n SubAccountName = iff(isempty(PurchasingSubscriptionGuid), '', PurchasingSubscriptionName),\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerEmail,\n x_CostCenter = CostCenter,\n x_InvoiceNumber = Invoice,\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = coalesce(InvoiceSectionName, DepartmentName),\n x_IngestionTime = ingestion_time(),\n x_MonetaryCommitment = MonetaryCommitment,\n x_Overage = Overage,\n x_PurchasingBillingAccountId = PurchasingEnrollment,\n x_SkuOrderId = ReservationOrderId,\n x_SkuOrderName = ReservationOrderName,\n x_SkuSize = ArmSkuName,\n x_SkuTerm = isoMonths(Term),\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId = PurchasingSubscriptionGuid,\n x_TransactionType = EventType\n}\n\n// Transactions_final_v1_2 table\n.create-merge table Transactions_final_v1_2 (\n BilledCost: real, // MS CM EA+MCA 2023-05-01\n BillingAccountId: string, // MS CM EA+MCA 2023-05-01\n BillingAccountName: string, // MS CM EA+MCA 2023-05-01\n BillingCurrency: string, // MS CM EA+MCA 2023-05-01\n BillingPeriodEnd: datetime, // MS CM EA+MCA 2023-05-01\n BillingPeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n ChargeCategory: string, // Hubs add-on\n ChargeClass: string, // Hubs add-on\n ChargeDescription: string, // MS CM EA+MCA 2023-05-01\n ChargeFrequency: string, // MS CM EA+MCA 2023-05-01\n ChargePeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n InvoiceId: string, // MS CM MCA 2023-05-01\n PricingQuantity: real, // MS CM EA+MCA 2023-05-01\n PricingUnit: string, // Hubs add-on\n ProviderName: string, // Hubs add-on\n RegionId: string, // MS CM EA+MCA 2023-05-01\n RegionName: string, // MS CM EA+MCA 2023-05-01\n SubAccountId: string, // MS CM EA+MCA 2023-05-01\n SubAccountName: string, // MS CM EA+MCA 2023-05-01\n x_AccountName: string, // MS CM EA 2023-05-01\n x_AccountOwnerId: string, // MS CM EA 2023-05-01\n x_CostCenter: string, // MS CM EA 2023-05-01\n x_InvoiceNumber: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionId: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionName: string, // MS CM MCA 2023-05-01\n x_IngestionTime: datetime, // Hubs add-on\n x_MonetaryCommitment: real, // MS CM EA 2023-05-01\n x_Overage: real, // MS CM EA 2023-05-01\n x_PurchasingBillingAccountId: string, // MS CM EA 2023-05-01\n x_SkuOrderId: string, // MS CM EA+MCA 2023-05-01\n x_SkuOrderName: string, // MS CM EA+MCA 2023-05-01\n x_SkuSize: string, // MS CM EA+MCA 2023-05-01\n x_SkuTerm: int, // MS CM EA+MCA 2023-05-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubscriptionId: string, // MS CM EA+MCA 2023-05-01\n x_TransactionType: string // MS CM EA+MCA 2023-05-01\n)\n\n// Update policy for Transactions_raw -> Transactions_final_v1_2 table\n.alter table Transactions_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Transactions_raw\",\n \"Query\": \"Transactions_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n", + "$fxv#10": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// See known issues @ https://github.com/microsoft/finops-toolkit/issues/1111\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Prices |=========================================================================================================\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_transform_v1_2 function\n.create-or-alter function\nwith (docstring='Transforms Prices_raw into FOCUS 1.2.', folder='Prices')\nPrices_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n let prices = materialize(\n Prices_raw\n | extend PricingCurrency = coalesce(Currency, CurrencyCode) // CurrencyCode last as a fallback only\n | extend x_SkuId = coalesce(SkuId, SkuID)\n | extend x_SkuMeterId = coalesce(MeterId, MeterID)\n | extend x_SkuProductId = coalesce(ProductId, ProductID)\n | extend x_SkuTerm = isoMonths(Term)\n | project-rename\n SkuMeter = MeterName,\n x_BaseUnitPrice = BasePrice,\n x_EffectivePeriodEnd = EffectiveEndDate,\n x_EffectivePeriodStart = EffectiveStartDate,\n x_PricingUnitDescription = UnitOfMeasure,\n x_SkuIncludedQuantity = IncludedQuantity,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuMeterType = MeterType,\n x_SkuOfferId = OfferID,\n x_SkuPartNumber = PartNumber,\n x_SkuPriceType = PriceType,\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTier = TierMinimumUnits\n | extend ContractedUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', UnitPrice, real(null)) // UnitPrice for savings plan is not the on-demand unit price\n | extend ListUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', MarketPrice, real(null)) // MarketPrice for savings plan is not the list price\n | extend ChargeCategory = case(\n x_SkuPriceType == 'Consumption', 'Usage',\n x_SkuPriceType == 'ReservedInstance', 'Purchase',\n x_SkuPriceType == 'SavingsPlan', 'Usage', // Savings plan prices are for committed usage, not the purchase\n ''\n )\n | extend SkuPriceIdv2 = strcat(case(x_SkuPriceType == 'Consumption', 'OD', x_SkuPriceType == 'ReservedInstance', 'RI', x_SkuPriceType == 'SavingsPlan', 'SP', 'XX'), substring(ChargeCategory, 0, 1), x_SkuTerm, '_', x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType, '_', x_SkuTier, x_SkuOfferId)\n | extend x_BillingAccountId = iff(BillingAccountId startswith '/', split(BillingAccountId, '/')[-1], coalesce(BillingAccountId, EnrollmentNumber))\n | extend x_BillingProfileId = iff(BillingProfileId startswith '/', split(BillingProfileId, '/')[-1], coalesce(BillingProfileId, EnrollmentNumber))\n | extend tmp_SavingsPlanKey = strcat(x_SkuMeterId, x_SkuProductId, x_SkuId, x_SkuTier, x_SkuOfferId)\n //\n // Get latest ingested row based on the unique ID\n | extend x_IngestionTime = ingestion_time()\n );\n //\n // Meters for reservations and savings plans to identify commitment eligibility\n let riMeters = prices | where x_SkuPriceType == 'ReservedInstance' | distinct x_SkuMeterId;\n let spMeters = prices | where x_SkuPriceType == 'SavingsPlan' | distinct x_SkuMeterId;\n //\n // Copy list/base/contracted prices from on-demand SKUs\n prices\n | where x_SkuPriceType == 'SavingsPlan'\n // If we use join, specify the shuffle key\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter hint.strategy=shuffle (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | lookup kind=leftouter (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | extend ListUnitPrice = coalesce(ListUnitPrice, ListUnitPrice1)\n | extend ContractedUnitPrice = coalesce(ContractedUnitPrice, ContractedUnitPrice1)\n | extend x_BaseUnitPrice = coalesce(x_BaseUnitPrice, x_BaseUnitPrice1)\n | project-away ListUnitPrice1, ContractedUnitPrice1, x_BaseUnitPrice1, tmp_SavingsPlanKey\n | union ((prices | where x_SkuPriceType != 'SavingsPlan'))\n //\n // Set CommitmentDiscountCategory for reuse\n | extend CommitmentDiscountCategory = case(\n x_SkuPriceType == 'ReservedInstance', 'Usage',\n x_SkuPriceType == 'SavingsPlan', 'Spend',\n ''\n )\n //\n // Calculate commitment discount eligibility\n // TODO: Would a join be faster?\n // TODO: Check this to ensure it's correct\n | extend x_CommitmentDiscountSpendEligibility = iff(x_SkuMeterId in (riMeters) and x_SkuPriceType != 'ReservedInstance', 'Eligible', 'Not Eligible')\n | extend x_CommitmentDiscountUsageEligibility = iff(x_SkuMeterId in (spMeters), 'Eligible', 'Not Eligible')\n //\n // TODO: Implement x_CommitmentDiscountNormalizedRatio\n | extend x_CommitmentDiscountNormalizedRatio = real(null)\n //\n // Add PricingUnit and x_PricingBlockSize\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter (PricingUnits) on x_PricingUnitDescription | project-away x_PricingUnitDescription1\n | lookup kind=leftouter (PricingUnits) on x_PricingUnitDescription\n //\n | extend x_EffectiveUnitPrice = iff(x_SkuPriceType == 'SavingsPlan', UnitPrice, real(null)) // Savings plan prices are for the effective price, not the contracted price\n | extend x_EffectiveUnitPriceDiscount = ContractedUnitPrice - x_EffectiveUnitPrice\n | extend x_ContractedUnitPriceDiscount = ListUnitPrice - ContractedUnitPrice\n | extend x_TotalUnitPriceDiscount = ListUnitPrice - x_EffectiveUnitPrice\n | project\n BillingAccountId = tolower(case(\n BillingProfileId startswith '/', BillingProfileId,\n BillingAccountId startswith '/', BillingAccountId,\n strcat('/providers/microsoft.billing/billingaccounts/', x_BillingAccountId, iff(x_BillingProfileId == x_BillingAccountId, '', strcat('/billingprofiles/', x_BillingProfileId)))\n )),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName, x_BillingProfileId),\n BillingCurrency = coalesce(BillingCurrency, CurrencyCode, Currency), // Currency last as a fallback only\n ChargeCategory,\n CommitmentDiscountCategory,\n CommitmentDiscountType = case(\n x_SkuPriceType == 'ReservedInstance', 'Reservation',\n x_SkuPriceType == 'SavingsPlan', 'Savings plan',\n ''\n ),\n CommitmentDiscountUnit = case(\n isempty(CommitmentDiscountCategory), '',\n CommitmentDiscountCategory == 'Spend', PricingCurrency,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio == real(1), PricingUnit,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio > real(1), strcat('Normalized ', PricingUnit),\n ''\n ),\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory = case(\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed',\n ''\n ),\n PricingCurrency,\n PricingUnit,\n SkuId = coalesce(ProductId, ProductID),\n SkuMeter,\n SkuPriceId = strcat(x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType),\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement = case(\n strlen(x_BillingAccountId) > 32, 'MCA',\n strlen(x_BillingAccountId) < 32, 'EA',\n 'Unknown'\n ),\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent = 1.0 * x_ContractedUnitPriceDiscount / ListUnitPrice * 100,\n x_EffectivePeriodEnd = startofmonth(x_EffectivePeriodEnd + 1h),\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent = 1.0 * x_EffectiveUnitPriceDiscount / ContractedUnitPrice * 100,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingSubcategory = case(\n x_SkuPriceType == 'Consumption' and (x_SkuIncludedQuantity > 0 or x_SkuTier > 0), 'Tiered',\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed Spend',\n ''\n ),\n x_PricingUnitDescription,\n x_SkuDescription = Product,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName = coalesce(x_SourceName, 'Cost Management'),\n x_SourceProvider = coalesce(x_SourceProvider, 'Microsoft'),\n x_SourceType = coalesce(x_SourceType, 'PriceSheet'),\n x_SourceVersion = coalesce(x_SourceVersion, '2023-05-01'),\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent = 1.0 * x_TotalUnitPriceDiscount / ListUnitPrice * 100\n}\n\n// Prices_final_v1_2 table\n.create-merge table Prices_final_v1_2 (\n BillingAccountId: string,\n BillingAccountName: string,\n BillingCurrency: string,\n ChargeCategory: string,\n CommitmentDiscountCategory: string,\n CommitmentDiscountType: string,\n CommitmentDiscountUnit: string,\n ContractedUnitPrice: real,\n ListUnitPrice: real,\n PricingCategory: string,\n PricingCurrency: string, // Azure\n PricingUnit: string,\n SkuId: string,\n SkuMeter: string, // Azure\n SkuPriceId: string,\n SkuPriceIdv2: string, // Hubs add-on\n x_BaseUnitPrice: real, // Azure\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure MCA\n x_BillingProfileId: string, // Azure MCA\n x_CommitmentDiscountNormalizedRatio: real, // Hubs add-on\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_ContractedUnitPriceDiscount: real, // Hubs add-on\n x_ContractedUnitPriceDiscountPercent: real, // Hubs add-on\n x_EffectivePeriodEnd: datetime, // Azure\n x_EffectivePeriodStart: datetime, // Azure\n x_EffectiveUnitPrice: real, // Azure\n x_EffectiveUnitPriceDiscount: real, // Hubs add-on\n x_EffectiveUnitPriceDiscountPercent: real, // Hubs add-on\n x_IngestionTime: datetime, // Hubs add-on\n x_PricingBlockSize: real, // Hubs add-on\n x_PricingSubcategory: string, // Hubs add-on\n x_PricingUnitDescription: string, // Azure\n x_SkuDescription: string, // Azure\n x_SkuId: string, // Azure\n x_SkuIncludedQuantity: real, // Azure EA\n x_SkuMeterCategory: string, // Azure\n x_SkuMeterId: string, // Azure\n x_SkuMeterSubcategory: string, // Azure\n x_SkuMeterType: string, // Azure\n x_SkuPriceType: string, // Azure\n x_SkuProductId: string, // Azure\n x_SkuRegion: string, // Azure\n x_SkuServiceFamily: string, // Azure\n x_SkuOfferId: string, // Azure EA\n x_SkuPartNumber: string, // Azure EA\n x_SkuTerm: int, // Azure\n x_SkuTier: real, // Azure MCA\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_TotalUnitPriceDiscount: real, // Hubs add-on\n x_TotalUnitPriceDiscountPercent: real // Hubs add-on\n)\n\n// Update policy for Prices_raw -> Prices_final_v1_2\n.alter table Prices_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Prices_raw\",\n \"Query\": \"Prices_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Cost and usage |=================================================================================================\n// Supported versions:\n// - MS: 1.2-preview, 1.0, 1.0-preview(v1)\n// https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0\n// https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024\n// https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 \n// https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All costs transformed to FOCUS 1.2.', folder='Costs')\nCosts_transform_v1_2()\n{\n let checkString = (column: string, oldValue: string, newValue: string) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n let checkInt = (column: string, oldValue: int, newValue: int) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n let checkReal = (column: string, oldValue: real, newValue: real) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n Costs_raw\n //\n // Dedupe rows\n | extend x_IngestionTime = ingestion_time()\n | extend x_ChargeId = ''\n // TODO: Consider adding a unique charge ID per row\n // hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // // 1. Resource hierarchy (including resource name), highest to lowest\n // BillingAccountId,\n // x_InvoiceSectionId,\n // x_AccountOwnerId,\n // SubAccountId,\n // x_ResourceGroupName,\n // ResourceName,\n // // 2. Resource details\n // ResourceId,\n // RegionId,\n // Tags,\n // CommitmentDiscountId,\n // x_CostCenter,\n // // 4. Meter details\n // SkuPriceId,\n // x_SkuMeterId,\n // x_SkuPartNumber,\n // x_SkuOfferId,\n // x_SkuDetails,\n // // 5. Date\n // ChargePeriodStart\n // ))\n //\n // Identify data quality issues\n // TODO: Remove x_SourceChanges in v1_3 (or later)\n | extend x_SourceChanges = trim_end(',', strcat(\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based', 'InvalidChargeFrequency,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and EffectiveCost > 0, 'InvalidEffectiveCost,', ''),\n iff((isempty(ContractedCost) or ContractedCost == 0) and EffectiveCost != 0, 'MissingContractedCost,', ''),\n iff((isempty(ContractedUnitPrice) or ContractedUnitPrice == 0) and x_EffectiveUnitPrice != 0, 'MissingContractedUnitPrice,', ''),\n iff(ListCost < ContractedCost, 'ListCostLessThanContractedCost,', ''),\n iff(ContractedCost < EffectiveCost, 'ContractedCostLessThanEffectiveCost,', ''),\n iff((isempty(ListCost) or ListCost == 0) and (ContractedCost != 0 or EffectiveCost != 0), 'MissingListCost,', ''),\n iff((isempty(ListUnitPrice) or ListUnitPrice == 0) and (ContractedUnitPrice != 0 or x_EffectiveUnitPrice != 0), 'MissingListUnitPrice,', ''),\n iff((isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001)\n or (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001),\n 'XEffectiveUnitPriceRoundingError,', ''),\n iff(ConsumedQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingConsumedQuantity,', ''),\n iff(PricingQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingPricingQuantity,', ''),\n iff(isempty(ProviderName), 'MissingProviderName,', ''),\n iff(isempty(PublisherName), 'MissingPublisherName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceId), 'MissingResourceId,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceName), 'MissingResourceName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceType), 'MissingResourceType,', ''),\n iff(BilledCost > 0 and x_BilledUnitPrice == 0, 'MissingXBilledUnitPrice,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(x_ResourceType), 'MissingXResourceType,', ''),\n iff(PricingCategory == 'Standard' and isnotempty(CommitmentDiscountId) and ChargeCategory == 'Usage', 'PricingCategoryShouldBeCommitted,', ''),\n iff(x_SkuTerm == '1Year' or x_SkuTerm == '3Years' or x_SkuTerm == '5Years', 'SkuTermShouldBeAnInteger,', '')\n ))\n //\n // Handle provider columns that moved to FOCUS\n | extend PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency)\n //\n // Backup original prices/costs before the merge\n | extend old_ContractedCost = ContractedCost\n | extend old_ContractedUnitPrice = ContractedUnitPrice\n | extend old_ListCost = ListCost\n | extend old_ListUnitPrice = ListUnitPrice\n | extend old_x_EffectiveUnitPrice = x_EffectiveUnitPrice\n //\n // Fix columns needed in other changes\n | extend old_ProviderName = ProviderName, ProviderName = case(\n isnotempty(ProviderName), ProviderName,\n isnotempty(coalesce(x_CostCategories, x_Discount, x_Operation, x_ServiceCode, x_UsageType)), 'AWS',\n isnotempty(coalesce(tostring(UsageAmount), tostring(x_Cost), x_Credits, x_CostType, tostring(x_CurrencyConversionRate), tostring(x_ExportTime), x_Project, x_ServiceId)), 'GCP',\n isnotempty(coalesce(x_BillingProfileId, x_InvoiceSectionId)), 'Microsoft',\n ''\n )\n //\n // Identify source\n | extend x_SourceName = coalesce(x_SourceName, iff(isnotempty(x_BillingProfileId), 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(isnotempty(x_BillingProfileId), 'FocusCost', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, case(\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)) and isempty(SkuPriceDetails) and isnotempty(x_SkuDetails), '1.2-preview',\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)), '1.2',\n isnotempty(coalesce(ChargeClass, CommitmentDiscountStatus, tostring(ConsumedQuantity), ConsumedUnit, tostring(ContractedCost), tostring(ContractedUnitPrice), RegionId, RegionName)), '1.0',\n isnotempty(coalesce(ChargeSubcategory, Region, tostring(UsageQuantity), UsageUnit)), iff(ProviderName == 'Microsoft', '1.0-preview(v1)', '1.0-preview'),\n ''\n ))\n // Append version check error code\n | extend x_SourceChanges = iff(x_SourceVersion == '1.0', x_SourceChanges,\n strcat(x_SourceChanges, iff(isempty(x_SourceChanges), '', ','), iff(x_SourceVersion == '', 'UnknownFocusVersion', 'LegacyFocusVersion'))\n )\n //\n // Fix quantities\n | extend old_PricingQuantity = PricingQuantity, PricingQuantity = case(\n PricingQuantity != 0 or (EffectiveCost == 0 and BilledCost == 0), PricingQuantity,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(EffectiveCost) and EffectiveCost != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0, EffectiveCost / x_EffectiveUnitPrice,\n PricingQuantity\n )\n | extend old_ConsumedQuantity = ConsumedQuantity, ConsumedQuantity = case(\n isnotempty(ConsumedQuantity) and ConsumedQuantity != 0, ConsumedQuantity,\n ChargeCategory == 'Usage', PricingQuantity / coalesce(x_PricingBlockSize, real(1)),\n ConsumedQuantity\n )\n //\n // Populate missing prices -- mapping to on-demand prices requires meter ID and offer ID\n | extend tmp_MissingPrices = ProviderName == 'Microsoft'\n and (isempty(ListUnitPrice) or isempty(ContractedUnitPrice) or ListUnitPrice == 0 or ContractedUnitPrice == 0)\n and x_EffectiveUnitPrice != 0\n and not(CommitmentDiscountCategory == 'Spend' and CommitmentDiscountStatus == 'Unused')\n and isnotempty(x_SkuMeterId) and isnotempty(x_SkuOfferId)\n | as allCosts\n | where tmp_MissingPrices\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(ChargePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | as costsWithMissingPrices\n | join kind=leftouter (\n Prices_final_v1_2\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(x_EffectivePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | where x_SkuPriceType == 'Consumption' and tmp_ReservationPriceLookupKey in ((costsWithMissingPrices | summarize by tmp_ReservationPriceLookupKey))\n | summarize ListUnitPrice = min(ListUnitPrice), ContractedUnitPrice = min(ContractedUnitPrice) by tmp_ReservationPriceLookupKey, x_PricingBlockSize, PricingUnit\n ) on tmp_ReservationPriceLookupKey\n //\n // Select the best price to use for each row\n | extend x_EffectiveUnitPrice = case(\n // If price is a rounding error away from the billed price, use the billed price\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001, x_BilledUnitPrice,\n // If price is a rounding error away from the contracted price, use the contracted price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001, ContractedUnitPrice,\n x_EffectiveUnitPrice\n )\n | extend ContractedUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ContractedUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ContractedUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // If billed price is available, assume the billed price is the same as contracted price to support aggregations\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, x_EffectiveUnitPrice,\n // Otherwise, assume the effective price is the same as contracted price to support aggregations\n x_EffectiveUnitPrice\n )\n | extend ListUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ListUnitPrice) and ListUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ListUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ListUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ListUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // Otherwise, assume the contracted price is the same as list price to support aggregations\n ContractedUnitPrice\n )\n // Calculate missing costs based on new prices -- If cost is already correct, keep that; if not and price is available, recalculate the cost; otherwise, keep the existing cost\n | extend ContractedCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ContractedCost) and ContractedCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedCost,\n // ContractedCost is 0 in all other scenarios...\n // If 0 and there's a billed cost and prices are the same, use BilledCost\n isnotempty(BilledCost) and BilledCost != 0 and ContractedUnitPrice == x_BilledUnitPrice, BilledCost,\n // If 0 and there's a billed cost and prices are the same, use EffectiveCost\n isnotempty(EffectiveCost) and EffectiveCost != 0 and ContractedUnitPrice == x_EffectiveUnitPrice, EffectiveCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0, ContractedUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume EffectiveCost\n isempty(ContractedUnitPrice) or ContractedUnitPrice == 0, EffectiveCost,\n // Fall back to the original value for any unhandled scenarios\n ContractedCost\n )\n | extend ListCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ListCost) and ListCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ListCost,\n // ListCost is 0 in all other scenarios...\n // If 0 and there's a contracted cost and prices are the same, use ContractedCost\n isnotempty(ContractedCost) and ContractedCost != 0 and ListUnitPrice == ContractedUnitPrice, ContractedCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ListUnitPrice) and ListUnitPrice != 0, ListUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume ContractedCost\n isempty(ListUnitPrice) or ListUnitPrice == 0, ContractedCost,\n // Fall back to the original value for any unhandled scenarios\n ListCost\n )\n // Merge the rest of the unmodified cost records and remove excess columns\n | union (allCosts | where not(tmp_MissingPrices))\n | project-away x_PricingBlockSize1, PricingUnit1, ListUnitPrice1, ContractedUnitPrice1, tmp_MissingPrices, tmp_ReservationPriceLookupKey, tmp_ReservationPriceLookupKey1\n //\n | extend SkuPriceDetails = parse_json(SkuPriceDetails)\n | extend Tags = parse_json(Tags)\n | extend x_SkuDetails = parse_json(x_SkuDetails)\n //\n // Handle FOCUS 1.0-preview\n | extend old_ChargeSubcategory = ChargeSubcategory\n | extend old_ChargeCategory = ChargeCategory, ChargeCategory = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Credit', 'Credit',\n ChargeSubcategory == 'Refund', 'Purchase', // We are assuming purchase refunds since we don't have data to indicate usage refunds\n ChargeCategory\n )\n | extend old_ChargeClass = ChargeClass, ChargeClass = case(ChargeSubcategory == 'Refund', 'Correction', ChargeClass)\n //\n // Populate CapacityReservationId when not specified\n | extend CapacityReservationId = coalesce(CapacityReservationId, tostring(coalesce(x_SkuDetails.VMCapacityReservationId, SkuPriceDetails.VMCapacityReservationId, SkuPriceDetails.x_VMCapacityReservationId)))\n | extend old_CapacityReservationStatus = CapacityReservationStatus, CapacityReservationStatus = case(\n isempty(CapacityReservationId), '',\n isnotempty(CapacityReservationStatus), CapacityReservationStatus,\n tolower(x_ResourceType) == 'microsoft.compute/capacityreservationgroups/capacityreservations', 'Unused',\n 'Used'\n )\n //\n // BUG: ChargeFrequency shows \"Usage-Based\" for monthly recurring savings plan purchases\n | extend old_ChargeFrequency = ChargeFrequency, ChargeFrequency = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based' and ProviderName == 'Microsoft' and x_SourceVersion startswith '1.0', 'Recurring', ChargeFrequency)\n //\n // Commitment discounts\n | extend x_CommitmentDiscountNormalizedRatio = case(\n // Calculate from CommitmentDiscountQuantity, if specified\n isnotempty(CommitmentDiscountQuantity) and CommitmentDiscountQuantity != 0, CommitmentDiscountQuantity / PricingQuantity / coalesce(x_PricingBlockSize, real(1)),\n // Not applicable\n isempty(CommitmentDiscountStatus), real(null),\n // Parse from SKU details if not specified explicitly\n toreal(coalesce(x_SkuDetails.RINormalizationRatio, SkuPriceDetails.RINormalizationRatio, SkuPriceDetails.x_RINormalizationRatio, dynamic(1)))\n )\n | extend old_CommitmentDiscountQuantity = CommitmentDiscountQuantity, CommitmentDiscountQuantity = case(\n // FOCUS 1.2\n isnotempty(CommitmentDiscountQuantity), CommitmentDiscountQuantity,\n // FOCUS 1.0-preview, 1.0\n isempty(CommitmentDiscountStatus), real(null),\n CommitmentDiscountCategory == 'Spend', EffectiveCost / coalesce(x_BillingExchangeRate, real(1)),\n CommitmentDiscountCategory == 'Usage' and isnotempty(x_CommitmentDiscountNormalizedRatio), PricingQuantity / coalesce(x_PricingBlockSize, real(1)) * x_CommitmentDiscountNormalizedRatio,\n real(null)\n )\n | extend old_CommitmentDiscountUnit = CommitmentDiscountUnit, CommitmentDiscountUnit = case(\n // FOCUS 1.2\n isnotempty(CommitmentDiscountUnit), CommitmentDiscountUnit,\n // FOCUS 1.0\n isempty(CommitmentDiscountQuantity), '',\n CommitmentDiscountCategory == 'Spend', PricingCurrency,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio == real(1), ConsumedUnit,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio > real(1), strcat('Normalized ', ConsumedUnit),\n ''\n )\n | extend old_CommitmentDiscountStatus = CommitmentDiscountStatus, CommitmentDiscountStatus = case(\n // FOCUS 1.0+\n isnotempty(CommitmentDiscountStatus), CommitmentDiscountStatus,\n // FOCUS 1.0-preview\n ChargeSubcategory == 'Used Commitment', 'Used',\n ChargeSubcategory == 'Unused Commitment', 'Unused',\n ''\n )\n | extend x_CommitmentDiscountUtilizationPotential = case(\n ChargeCategory == 'Purchase', real(0),\n ProviderName == 'Microsoft' and isnotempty(CommitmentDiscountCategory), EffectiveCost,\n CommitmentDiscountCategory == 'Usage', ConsumedQuantity,\n CommitmentDiscountCategory == 'Spend', EffectiveCost,\n real(0)\n )\n | extend x_CommitmentDiscountUtilizationAmount = iff(CommitmentDiscountStatus == 'Used', x_CommitmentDiscountUtilizationPotential, real(0))\n //\n // Pricing\n | extend old_x_AmortizationClass = x_AmortizationClass, x_AmortizationClass = case(\n // FOCUS 1.2\n isnotempty(x_AmortizationClass), x_AmortizationClass,\n // FOCUS 1.0-preview+\n ChargeCategory == 'Purchase' and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeCategory == 'Usage' and isnotempty(CommitmentDiscountId) and isnotempty(CommitmentDiscountStatus), 'Amortized Charge',\n ''\n )\n | extend old_PricingCategory = PricingCategory, PricingCategory = case(\n // FOCUS 1.0+\n isnotempty(PricingCategory), PricingCategory,\n // FOCUS 1.0-preview\n PricingCategory == 'On-Demand', 'Standard',\n PricingCategory == 'Commitment-Based', 'Committed',\n ''\n )\n //\n // Commitment discount utilization\n | extend x_CommitmentDiscountUtilizationPotential = case(\n ChargeCategory == 'Purchase', real(0),\n ProviderName == 'Microsoft' and isnotempty(CommitmentDiscountCategory), EffectiveCost,\n CommitmentDiscountCategory == 'Usage', ConsumedQuantity,\n CommitmentDiscountCategory == 'Spend', EffectiveCost,\n real(0)\n )\n | extend x_CommitmentDiscountUtilizationAmount = iff(CommitmentDiscountStatus == 'Used', x_CommitmentDiscountUtilizationPotential, real(0))\n //\n // BUG: Fix ContractedCost that has bad values\n | extend ContractedCost = iff(ProviderName == 'Microsoft' and isnotempty(PricingQuantity) and isnotempty(x_PricingBlockSize) and ContractedCost != ContractedUnitPrice * PricingQuantity, ContractedUnitPrice * PricingQuantity, ContractedCost)\n //\n // Handle FOCUS 1.0-preview UsageQuantity/Unit\n | extend ConsumedQuantity = iff(ChargeCategory == 'Usage', coalesce(ConsumedQuantity, UsageQuantity, UsageAmount), real(null))\n | extend old_ConsumedUnit = ConsumedUnit, ConsumedUnit = iff(ChargeCategory == 'Usage' and isnotempty(ConsumedQuantity), coalesce(ConsumedUnit, UsageUnit, 'Units'), '')\n //\n // Convert IDs to lowercase for consistency\n | extend BillingAccountId = tolower(BillingAccountId)\n | extend CommitmentDiscountId = tolower(CommitmentDiscountId)\n //\n // BUG: Remove EffectiveCost for commitment discount purchases\n | extend old_EffectiveCost = EffectiveCost, EffectiveCost = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), real(0), EffectiveCost)\n | extend old_x_EffectiveCostInUsd = x_EffectiveCostInUsd, x_EffectiveCostInUsd = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), real(0), x_EffectiveCostInUsd)\n //\n // Clean up resource columns\n | extend old_ResourceId = ResourceId, ResourceId = case(\n isnotempty(ResourceId), ResourceId,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), CommitmentDiscountId,\n ResourceId\n )\n | extend old_ResourceName = ResourceName, ResourceName = tolower(case(\n isnotempty(ResourceName), ResourceName,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountName), CommitmentDiscountName,\n isnotempty(ResourceId), parse_resourceid(ResourceId).ResourceName,\n ResourceName\n ))\n | extend old_x_ResourceType = x_ResourceType, x_ResourceType = case(\n isnotempty(x_ResourceType), x_ResourceType,\n isnotempty(ResourceId), parse_resourceid(ResourceId).x_ResourceType,\n x_ResourceType\n )\n | extend old_ResourceType = ResourceType, ResourceType = case(\n // Use existing resource type display name unless it's an internal resource type ID\n isnotempty(ResourceType) and tolower(ResourceType) != tolower(x_ResourceType) and ResourceType !contains '/', ResourceType,\n // Use CommitmentDiscountType for commitment discount purchases\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountType), CommitmentDiscountType,\n // Look up display name from internal type\n isnotempty(x_ResourceType), coalesce(tostring(resource_type(x_ResourceType).SingularDisplayName), ResourceType, x_ResourceType),\n ResourceType\n )\n //\n // Handle missing values\n | extend old_PublisherName = PublisherName, PublisherName = case(PublisherName == 'Microsoft Corporation', 'Microsoft', isnotempty(PublisherName), PublisherName, x_PublisherCategory == 'Cloud Provider', ProviderName, '')\n //\n // Handle FOCUS 1.0-preview Region column\n | extend old_Region = Region\n | extend old_RegionId = RegionId, RegionId = coalesce(RegionId, iff(ProviderName == 'Microsoft', replace_string(tolower(Region), ' ', ''), Region))\n | extend RegionName = coalesce(RegionName, Region)\n //\n // SKU properties\n | extend x_SkuCoreCount = toint(coalesce(SkuPriceDetails.CoreCount, SkuPriceDetails.x_VCPUs, x_SkuDetails.VCPUs, SkuPriceDetails.x_VCores, x_SkuDetails.VCores, SkuPriceDetails.x_vCores, x_SkuDetails.vCores))\n | extend x_SkuInstanceType = tostring(coalesce(SkuPriceDetails.InstanceType, SkuPriceDetails.x_ServiceType, x_SkuDetails.ServiceType, SkuPriceDetails.x_ServerSku, x_SkuDetails.ServerSku))\n | extend x_SkuOperatingSystem = case(\n isnotempty(SkuPriceDetails.OperatingSystem), SkuPriceDetails.OperatingSystem,\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Canonical', 'Linux',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL', 'Windows Server',\n x_SkuMeterSubcategory endswith ' Series Windows', 'Windows Server',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType)\n )\n | extend x_ConsumedCoreHours = iff(ConsumedUnit == 'Hours' and isnotempty(x_SkuCoreCount), x_SkuCoreCount * ConsumedQuantity, real(null))\n | extend SkuPriceDetails = case(\n // FOCUS 1.2\n isnotempty(SkuPriceDetails), SkuPriceDetails,\n // FOCUS 1.0-preview, 1.0\n parse_json(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(tostring(x_SkuDetails)\n // Prefix all keys with x_ first to avoid double-prefixing\n , @'([\\{,])\"', @'\\1\"x_')\n // CoreCount for number of CPUs/vCPUs/cores/vCores\n , @'\"x_(VCPUs|VCores|vCores)\":', @'\"CoreCount\":')\n // TODO: DiskMaxIops for disk I/O operations per second (IOPS)\n // TODO: DiskSpace for disk size in GiB\n // TODO: DiskType for the kind of disk (e.g., SSD, HDD, NVMe)\n // TODO: GpuCount for the number of GPUs\n // InstanceType for the resource size/SKU (e.g., ArmSkuName)\n , @'\"x_(ServerSku|ServiceType)\":', @'\"InstanceType\":')\n // TODO: InstanceSeries for the size family/series\n // TODO: MemorySize for the RAM in GiB\n // TODO: NetworkMaxIops for network I/O operations per second (IOPS)\n // TODO: NetworkMaxThroughput for network max throughput for data transfer in Mbps\n // OperatingSystem for the OS name\n , @'(\"x_ImageType\":\"Canonical\")', @'\\1,\"OperatingSystem\":\"Linux\"')\n , @'(\"x_ImageType\":\"Windows Server( BYOL)?\")', @'\\1,\"OperatingSystem\":\"Windows Server\"')\n , @'(\"x_ImageType\":(\"[^\"]+\"))', @'\\1,\"OperatingSystem\":\\2')\n // TODO: Redundancy for the level of redundancy (e.g., Local, Zonal, Global)\n // TODO: StorageClass for the tier of storage (e.g., Hot, Archive, Nearline)\n )\n )\n | extend SkuPriceDetails = iff(isempty(SkuPriceDetails.OperatingSystem) and isnotempty(x_SkuOperatingSystem),\n parse_json(replace_string(tostring(SkuPriceDetails), '}', strcat(@',\"OperatingSystem\":\"', x_SkuOperatingSystem, '\"}'))),\n SkuPriceDetails)\n //\n // Azure Hybrid Benefit\n | extend tmp_SqlAhb = tolower(coalesce(x_SkuDetails.AHB, SkuPriceDetails.x_AHB))\n | extend x_SkuLicenseType = case(\n ChargeCategory != 'Usage', '',\n x_SkuMeterCategory in ('Virtual Machines', 'Virtual Machine Licenses') and (x_SkuMeterSubcategory contains 'Windows' or coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL'), 'Windows Server',\n isnotempty(tmp_SqlAhb) or x_SkuMeterSubcategory == 'SQL Server Azure Hybrid Benefit', 'SQL Server',\n ''\n )\n | extend x_SkuLicenseStatus = case(\n isempty(x_SkuLicenseType), '',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL' or tmp_SqlAhb == 'true' or x_SkuMeterSubcategory contains 'Azure Hybrid Benefit', 'Enabled',\n (x_SkuMeterSubcategory contains 'Windows') or tmp_SqlAhb == 'false', 'Not Enabled',\n ''\n )\n | extend x_SkuLicenseQuantity = case(\n isempty(x_SkuCoreCount) or isempty(x_SkuLicenseType), int(null),\n x_SkuCoreCount <= 8, int(8),\n x_SkuCoreCount > 8, x_SkuCoreCount,\n int(null)\n )\n | extend x_SkuLicenseUnit = iff(isnotempty(x_SkuLicenseQuantity), 'Cores', '')\n //\n // Savings\n | extend x_CommitmentDiscountSavings = iff(isempty(ContractedCost) or ContractedCost == 0 or ContractedCost - EffectiveCost < 0.0001, real(0), ContractedCost - EffectiveCost)\n | extend x_NegotiatedDiscountSavings = iff(isempty(ListCost) or ListCost == 0 or ListCost - ContractedCost < 0.0001, real(0), ListCost - ContractedCost)\n | extend x_TotalSavings = iff(isempty(ListCost) or ListCost == 0 or ListCost - EffectiveCost < 0.0001, real(0), ListCost - EffectiveCost)\n | extend x_CommitmentDiscountPercent = iff(isempty(ContractedUnitPrice) or ContractedUnitPrice == 0 or ContractedUnitPrice - x_EffectiveUnitPrice < 0.0001, real(0), (ContractedUnitPrice - x_EffectiveUnitPrice) / ContractedUnitPrice)\n | extend x_NegotiatedDiscountPercent = iff(isempty(ListUnitPrice) or ListUnitPrice == 0 or ListUnitPrice - ContractedUnitPrice < 0.0001, real(0), (ListUnitPrice - ContractedUnitPrice) / ListUnitPrice)\n | extend x_TotalDiscountPercent = iff(isempty(ListUnitPrice) or ListUnitPrice == 0 or ListUnitPrice - x_EffectiveUnitPrice < 0.0001, real(0), (ListUnitPrice - x_EffectiveUnitPrice) / ListUnitPrice)\n //\n // Minor fixes\n | extend old_BillingPeriodEnd = BillingPeriodEnd, BillingPeriodEnd = startofmonth(BillingPeriodEnd)\n | extend old_BillingPeriodStart = BillingPeriodStart, BillingPeriodStart = startofmonth(BillingPeriodStart)\n //\n // Sort columns and apply final transforms\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId,\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd,\n BillingPeriodStart,\n CapacityReservationId,\n CapacityReservationStatus,\n ChargeCategory,\n ChargeClass,\n ChargeDescription,\n ChargeFrequency,\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId,\n CommitmentDiscountName,\n CommitmentDiscountQuantity,\n CommitmentDiscountStatus,\n CommitmentDiscountType,\n CommitmentDiscountUnit,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost = coalesce(ContractedCost, x_OnDemandCost, x_Cost),\n ContractedUnitPrice = coalesce(ContractedUnitPrice, x_OnDemandUnitPrice),\n EffectiveCost,\n InvoiceId = coalesce(InvoiceId, x_InvoiceId),\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory,\n PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency),\n PricingQuantity,\n PricingUnit,\n ProviderName,\n PublisherName,\n RegionId,\n RegionName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory, // TODO: Populate ServiceSubcategory from ServiceName when missing\n SkuId,\n SkuMeter = coalesce(SkuMeter, x_SkuMeterName),\n SkuPriceDetails,\n SkuPriceId,\n SubAccountId,\n SubAccountName = iff(isempty(SubAccountId), '', SubAccountName),\n SubAccountType,\n Tags,\n x_AccountId = iff(x_AccountId == '-2', '', x_AccountId),\n x_AccountName = iff(x_AccountId == '-2', '', x_AccountName),\n x_AccountOwnerId = iff(x_AccountId == '-2', '', x_AccountOwnerId),\n x_AmortizationClass,\n x_BilledCostInUsd,\n x_BilledUnitPrice,\n x_BillingAccountAgreement = case(\n ProviderName == 'Microsoft' and x_BillingAccountId == x_BillingProfileId, 'EA',\n ProviderName == 'Microsoft' and x_BillingAccountId != x_BillingProfileId, 'MCA',\n ProviderName\n ),\n x_BillingAccountId,\n x_BillingAccountName,\n x_BillingExchangeRate,\n x_BillingExchangeRateDate,\n x_BillingItemCode,\n x_BillingItemName,\n x_BillingProfileId,\n x_BillingProfileName,\n x_ChargeId,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountPercent,\n x_CommitmentDiscountSavings,\n x_CommitmentDiscountSpendEligibility = '', // TODO: Add x_CommitmentDiscountSpendEligibility for Costs\n x_CommitmentDiscountUsageEligibility = '', // TODO: Add x_CommitmentDiscountUsageEligibility for Costs\n x_CommitmentDiscountUtilizationAmount,\n x_CommitmentDiscountUtilizationPotential,\n x_CommodityCode,\n x_CommodityName,\n x_ComponentName,\n x_ComponentType,\n x_ConsumedCoreHours,\n x_ContractedCostInUsd = coalesce(x_ContractedCostInUsd, x_OnDemandCostInUsd),\n x_CostAllocationRuleName,\n x_CostCategories = parse_json(x_CostCategories),\n x_CostCenter,\n x_CostType,\n x_Credits = parse_json(x_Credits),\n x_CurrencyConversionRate,\n x_CustomerId,\n x_CustomerName,\n x_Discount = parse_json(x_Discount),\n x_EffectiveCostInUsd,\n x_EffectiveUnitPrice,\n x_ExportTime,\n x_IngestionTime,\n x_InstanceID,\n x_InvoiceIssuerId,\n x_InvoiceSectionId = case(\n x_InvoiceSectionId == '-2', '',\n x_InvoiceSectionId\n ),\n x_InvoiceSectionName = case(\n x_InvoiceSectionName == 'Unassigned', '',\n x_InvoiceSectionName\n ),\n x_ListCostInUsd,\n x_Location,\n x_NegotiatedDiscountPercent,\n x_NegotiatedDiscountSavings,\n x_Operation,\n x_OwnerAccountID,\n x_PartnerCreditApplied,\n x_PartnerCreditRate,\n x_PricingBlockSize,\n x_PricingSubcategory,\n x_PricingUnitDescription = iff(x_PricingUnitDescription == 'Unassigned', '', x_PricingUnitDescription),\n x_Project,\n x_PublisherCategory,\n x_PublisherId,\n x_ResellerId,\n x_ResellerName,\n x_ResourceGroupName = tolower(x_ResourceGroupName),\n x_ResourceType,\n x_ServiceCode,\n x_ServiceId,\n x_ServiceModel, // TODO: Populate from ServiceName when missing\n x_ServicePeriodEnd,\n x_ServicePeriodStart,\n x_SkuCoreCount,\n x_SkuDescription,\n x_SkuDetails,\n x_SkuInstanceType,\n x_SkuIsCreditEligible,\n x_SkuLicenseQuantity,\n x_SkuLicenseStatus,\n x_SkuLicenseType,\n x_SkuLicenseUnit,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterSubcategory,\n x_SkuOfferId,\n x_SkuOperatingSystem,\n x_SkuOrderId,\n x_SkuOrderName,\n x_SkuPartNumber,\n x_SkuPlanName,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuTerm,\n x_SkuTier,\n x_SourceChanges,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceValues = bag_merge(\n checkString('BillingPeriodEnd', old_BillingPeriodEnd, BillingPeriodEnd),\n checkString('BillingPeriodStart', old_BillingPeriodStart, BillingPeriodStart),\n checkString('CapacityReservationStatus', old_CapacityReservationStatus, CapacityReservationStatus),\n checkString('ChargeCategory', old_ChargeCategory, ChargeCategory),\n checkString('ChargeClass', old_ChargeClass, ChargeClass),\n checkString('ChargeSubcategory', old_ChargeSubcategory, ''), // Not included in final schema; use empty string\n checkString('ChargeFrequency', old_ChargeFrequency, ChargeFrequency),\n checkReal('CommitmentDiscountQuantity', old_CommitmentDiscountQuantity, CommitmentDiscountQuantity),\n checkString('CommitmentDiscountUnit', old_CommitmentDiscountUnit, CommitmentDiscountUnit),\n checkString('CommitmentDiscountStatus', old_CommitmentDiscountStatus, CommitmentDiscountStatus),\n checkReal('ConsumedQuantity', old_ConsumedQuantity, ConsumedQuantity),\n checkString('ConsumedUnit', old_ConsumedUnit, ConsumedUnit),\n checkReal('ContractedCost', old_ContractedCost, ContractedCost),\n checkReal('ContractedUnitPrice', old_ContractedUnitPrice, ContractedUnitPrice),\n checkReal('EffectiveCost', old_EffectiveCost, EffectiveCost),\n checkReal('ListCost', old_ListCost, ListCost),\n checkReal('ListUnitPrice', old_ListUnitPrice, ListUnitPrice),\n checkString('PricingCategory', old_PricingCategory, PricingCategory),\n checkReal('PricingQuantity', old_PricingQuantity, PricingQuantity),\n checkString('ProviderName', old_ProviderName, ProviderName),\n checkString('PublisherName', old_PublisherName, PublisherName),\n checkString('Region', old_Region, ''), // Not included in final schema; use empty string\n checkString('RegionId', old_RegionId, RegionId),\n checkString('ResourceId', old_ResourceId, ResourceId),\n checkString('ResourceName', old_ResourceName, ResourceName),\n checkString('ResourceType', old_ResourceType, ResourceType),\n checkString('x_AmortizationClass', old_x_AmortizationClass, x_AmortizationClass),\n checkReal('x_EffectiveCostInUsd', old_x_EffectiveCostInUsd, x_EffectiveCostInUsd),\n checkReal('x_EffectiveUnitPrice', old_x_EffectiveUnitPrice, x_EffectiveUnitPrice),\n checkString('x_ResourceType', old_x_ResourceType, x_ResourceType)\n ),\n x_SourceVersion,\n x_SubproductName,\n x_TotalDiscountPercent,\n x_TotalSavings,\n x_UsageType\n}\n\n// Costs_final_v1_2 table\n.create-merge table Costs_final_v1_2 (\n AvailabilityZone: string,\n BilledCost: real,\n BillingAccountId: string,\n BillingAccountName: string,\n BillingAccountType: string,\n BillingCurrency: string,\n BillingPeriodEnd: datetime,\n BillingPeriodStart: datetime,\n CapacityReservationId: string,\n CapacityReservationStatus: string,\n ChargeCategory: string,\n ChargeClass: string,\n ChargeDescription: string,\n ChargeFrequency: string,\n ChargePeriodEnd: datetime,\n ChargePeriodStart: datetime,\n CommitmentDiscountCategory: string,\n CommitmentDiscountId: string,\n CommitmentDiscountName: string,\n CommitmentDiscountQuantity: real,\n CommitmentDiscountStatus: string,\n CommitmentDiscountType: string,\n CommitmentDiscountUnit: string,\n ConsumedQuantity: real,\n ConsumedUnit: string,\n ContractedCost: real,\n ContractedUnitPrice: real,\n EffectiveCost: real,\n InvoiceId: string,\n InvoiceIssuerName: string,\n ListCost: real,\n ListUnitPrice: real,\n PricingCategory: string,\n PricingCurrency: string,\n PricingQuantity: real,\n PricingUnit: string,\n ProviderName: string,\n PublisherName: string,\n RegionId: string,\n RegionName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n ServiceCategory: string,\n ServiceName: string,\n ServiceSubcategory: string,\n SkuId: string,\n SkuMeter: string,\n SkuPriceDetails: dynamic,\n SkuPriceId: string,\n SubAccountId: string,\n SubAccountName: string,\n SubAccountType: string,\n Tags: dynamic,\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_AmortizationClass: string, // Azure 1.2-preview+\n x_BilledCostInUsd: real, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: real, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: real, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingItemCode: string, // Alibaba 1.0\n x_BillingItemName: string, // Alibaba 1.0\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_CommitmentDiscountNormalizedRatio: real, // Azure 1.2-preview+\n x_CommitmentDiscountPercent: real, // Hubs add-on\n x_CommitmentDiscountSavings: real, // Hubs add-on\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_CommitmentDiscountUtilizationAmount: real, // Hubs add-on\n x_CommitmentDiscountUtilizationPotential: real, // Hubs add-on\n x_CommodityCode: string, // Alibaba 1.0\n x_CommodityName: string, // Alibaba 1.0\n x_ComponentName: string, // Tencent 1.0\n x_ComponentType: string, // Tencent 1.0\n x_ConsumedCoreHours: real, // Hubs add-on\n x_ContractedCostInUsd: real, // Azure 1.0+\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: dynamic, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_CostType: string, // GCP Jan 2024\n x_Credits: dynamic, // GCP Jan 2024\n x_CurrencyConversionRate: real, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: dynamic, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: real, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: real, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024 / Tencent 1.0\n x_IngestionTime: datetime, // Hubs add-on\n x_InstanceID: string, // Alibaba 1.0\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: real, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_NegotiatedDiscountPercent:real, // Hubs add-on\n x_NegotiatedDiscountSavings:real, // Hubs add-on\n x_Operation: string, // AWS 1.0\n x_OwnerAccountID: string, // Tencent 1.0\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: real, // Azure 1.0-preview(v1)+\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServiceModel: string, // Azure 1.2-preview+\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuCoreCount: int, // Hubs add-on\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: dynamic, // Azure 1.0-preview(v1)+\n x_SkuInstanceType: string, // Hubs add-on\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuLicenseQuantity: int, // Hubs add-on\n x_SkuLicenseStatus: string, // Hubs add-on\n x_SkuLicenseType: string, // Hubs add-on\n x_SkuLicenseUnit: string, // Hubs add-on\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOperatingSystem: string, // Hubs add-on\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuPlanName: string, // Azure 1.2-preview+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceChanges: string, // Hubs add-on\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceValues: dynamic, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubproductName: string, // Tencent 1.0\n x_TotalDiscountPercent: real, // Hubs add-on\n x_TotalSavings: real, // Hubs add-on\n x_UsageType: string // AWS 1.0\n)\n\n// Update policy for Costs_raw -> Costs_final_v1_2 table\n.alter table Costs_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Costs_raw\",\n \"Query\": \"Costs_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Actual costs |===================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_transform_v1_2 function\n.create-or-alter function\nwith (docstring='ActualCost exports transformed to FOCUS 1.2.', folder='Costs')\nActualCosts_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n ActualCosts_raw\n | where ChargeType in ('Purchase', 'Refund') and isnotempty(ReservationId)\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: PublisherName, x_PublisherCategory, x_Environment\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory), take_any(ServiceSubcategory), take_any(x_ServiceModel) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodEnd = Date + 1d,\n ChargePeriodStart = Date,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SkuId = '',\n SkuMeter = MeterName,\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = iff(isempty(SubscriptionId), '', SubscriptionName),\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentType = '',\n x_ComponentName = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = '',\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel,\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for ActualCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": true,\n \"Source\": \"ActualCosts_raw\",\n \"Query\": \"ActualCosts_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Amortized costs |================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_transform_v1_2 function\n.create-or-alter function\nwith (docstring='ActualCost exports transformed to FOCUS 1.2.', folder='Costs')\nAmortizedCosts_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n AmortizedCosts_raw\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: PublisherName, x_PublisherCategory, x_Environment\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory), take_any(ServiceSubcategory), take_any(x_ServiceModel) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodEnd = Date + 1d,\n ChargePeriodStart = Date,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SkuId = '',\n SkuMeter = MeterName,\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = iff(isempty(SubscriptionId), '', SubscriptionName),\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentType = '',\n x_ComponentName = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = '',\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel,\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for AmortizedCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": true,\n \"Source\": \"AmortizedCosts_raw\",\n \"Query\": \"AmortizedCosts_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All commitment discount usage transformed to FOCUS 1.2. This includes reservationdeatils_raw.', folder='Commitment discounts')\nCommitmentDiscountUsage_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n CommitmentDiscountUsage_raw\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Handle resource columns\n | extend ResourceId = tolower(InstanceId)\n | extend tmp_ResourceDetails = parse_resourceid(ResourceId)\n | extend ResourceName = tostring(tmp_ResourceDetails.ResourceName)\n | extend SubAccountId = tostring(tmp_ResourceDetails.SubAccountId)\n | extend x_ResourceGroupName = tostring(tmp_ResourceDetails.x_ResourceGroupName)\n | extend x_ResourceType = tostring(tmp_ResourceDetails.x_ResourceType)\n | lookup kind=leftouter (ResourceTypes | distinct x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n | lookup kind=leftouter (Services | distinct x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n //\n // Sort columns and apply final transforms\n | project\n ChargePeriodEnd = UsageDate + 1d,\n ChargePeriodStart = UsageDate,\n CommitmentDiscountCategory = 'Usage',\n CommitmentDiscountId = tolower(strcat('/providers/microsoft.capacity/reservationorders/', ReservationOrderId, '/reservations/', ReservationId)),\n CommitmentDiscountQuantity = UsedHours * InstanceFlexibilityRatio,\n CommitmentDiscountType = 'Reservation',\n CommitmentDiscountUnit = case(\n InstanceFlexibilityRatio == 1, 'Hours',\n InstanceFlexibilityRatio != 1, 'Normalized Hours',\n ''\n ),\n ConsumedQuantity = UsedHours,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SubAccountId,\n x_CommitmentDiscountCommittedCount = TotalReservedQuantity,\n x_CommitmentDiscountCommittedAmount = ReservedHours,\n // TODO: Is this needed? -- x_CommitmentDiscountKind = Kind,\n x_CommitmentDiscountNormalizedGroup = iff(InstanceFlexibilityGroup == 'NA', '', InstanceFlexibilityGroup),\n x_CommitmentDiscountNormalizedRatio = InstanceFlexibilityRatio,\n x_IngestionTime = ingestion_time(),\n x_ResourceGroupName,\n x_ResourceType,\n // x_RowId = hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // CommitmentDiscountId,\n // ResourceId,\n // ChargePeriodStart\n // )),\n x_ServiceModel,\n x_SkuOrderId = ReservationOrderId,\n x_SkuSize = iff(SkuName == 'NA', '', SkuName),\n x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName)),\n x_SourceProvider = coalesce(x_SourceProvider, ProviderName),\n x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationDetails', '')),\n x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2024-03-01', ''))\n}\n\n// CommitmentDiscountUsage_final_v1_2 table\n.create-merge table CommitmentDiscountUsage_final_v1_2 (\n ChargePeriodEnd: datetime, // Hubs add-on\n ChargePeriodStart: datetime, // MS 2023-03-01\n CommitmentDiscountCategory: string, // Hubs add-on\n CommitmentDiscountId: string, // MS 2023-03-01\n CommitmentDiscountQuantity: real, // MS 2023-03-01\n CommitmentDiscountType: string, // Hubs add-on\n CommitmentDiscountUnit: string, // Hubs add-on\n ConsumedQuantity: real, // MS 2023-03-01\n ProviderName: string, // Hubs add-on\n ResourceId: string, // MS 2023-03-01\n ResourceName: string, // Hubs add-on\n ResourceType: string, // Hubs add-on\n ServiceCategory: string, // Hubs add-on\n ServiceName: string, // Hubs add-on\n ServiceSubcategory: string, // Hubs add-on\n SubAccountId: string, // Hubs add-on\n x_CommitmentDiscountCommittedCount: real, // MS 2023-03-01\n x_CommitmentDiscountCommittedAmount: real, // MS 2023-03-01\n x_CommitmentDiscountNormalizedGroup: string, // MS 2023-03-01\n x_CommitmentDiscountNormalizedRatio: real, // MS 2023-03-01\n x_IngestionTime: datetime, // Hubs add-on\n x_ResourceGroupName: string, // Hubs add-on\n x_ResourceType: string, // Hubs add-on\n x_ServiceModel: string, // Hubs add-on\n x_SkuOrderId: string, // MS 2023-03-01\n x_SkuSize: string, // MS 2023-03-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string // Hubs add-on\n)\n\n// Update policy for CommitmentDiscountUsage_raw -> CommitmentDiscountUsage_final_v1_2 table\n.alter table CommitmentDiscountUsage_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"CommitmentDiscountUsage_raw\",\n \"Query\": \"CommitmentDiscountUsage_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All recommendations transformed to FOCUS 1.2.', folder='Recommendations')\nRecommendations_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Recommendations_raw\n | extend x_IngestionTime = ingestion_time()\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationRecommendations', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Convert JSON cost columns to real\n | extend CostWithNoReservedInstances = case(isnotempty(CostWithNoReservedInstances), CostWithNoReservedInstances, isnotempty(CostWithNoReservedInstancesJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, CostWithNoReservedInstancesJson)), CostWithNoReservedInstances)\n | extend NetSavings = case(isnotempty(NetSavings), NetSavings, isnotempty(NetSavingsJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, NetSavingsJson)), NetSavings)\n | extend TotalCostWithReservedInstances = case(isnotempty(TotalCostWithReservedInstances), TotalCostWithReservedInstances, isnotempty(TotalCostWithReservedInstancesJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, TotalCostWithReservedInstancesJson)), TotalCostWithReservedInstances)\n //\n // Parse x_RecommendationDetails from JSON string (ARG queries serialize to string for Parquet compatibility)\n | extend x_RecommendationDetails = iff(gettype(x_RecommendationDetails) == 'string', parse_json(tostring(x_RecommendationDetails)), x_RecommendationDetails)\n //\n // Normalize x_RecommendationDetails keys to x_PascalCase (Advisor extendedProperties use camelCase)\n // Guard: inject a placeholder key so mv-apply doesn't drop rows with null/empty bags\n | extend x_RecommendationDetails = bag_merge(coalesce(x_RecommendationDetails, dynamic({})), bag_pack('__placeholder', ''))\n | mv-apply k = bag_keys(x_RecommendationDetails) on (\n where isnotempty(tostring(k)) and tostring(k) != '__placeholder'\n | extend newKey = iff(tostring(k) startswith 'x_', tostring(k), strcat('x_', toupper(substring(tostring(k), 0, 1)), substring(tostring(k), 1)))\n | summarize x_RecommendationDetails = make_bag(bag_pack(newKey, x_RecommendationDetails[tostring(k)]))\n )\n //\n // Build recommendation details\n | lookup kind=leftouter (Regions | summarize RegionName = make_set(RegionName)[0] by Location = RegionId) on Location\n | extend x_RecommendationDetails = case(\n // Use incoming x_RecommendationDetails first\n isnotempty(x_RecommendationDetails), x_RecommendationDetails,\n // Create one for reservation recommendations if needed\n x_SourceType == 'ReservationRecommendations', bag_pack(\n 'CommitmentDiscountNormalizedGroup', InstanceFlexibilityGroup,\n 'CommitmentDiscountNormalizedRatio', InstanceFlexibilityRatio,\n 'CommitmentDiscountNormalizedSize', NormalizedSize,\n 'CommitmentDiscountResourceType', ResourceType,\n 'CommitmentDiscountScope', Scope,\n 'LookbackPeriodDuration', case(\n LookBackPeriod matches regex @'^Last([0-9]+)Days$', replace_regex(LookBackPeriod, @'^Last([0-9]+)Days$', @'P\\1D'),\n LookBackPeriod matches regex @'^[0-9]+$', strcat('P', LookBackPeriod, 'D'),\n ''\n ),\n 'LookbackPeriodStart', FirstUsageDate,\n 'RecommendedQuantity', RecommendedQuantity,\n 'RecommendedQuantityNormalized', RecommendedQuantityNormalized,\n 'RegionId', Location,\n 'RegionName', RegionName,\n 'SkuMeterId', MeterId,\n 'SkuPriceDetails', SkuProperties,\n 'SkuSize', coalesce(SKU, SkuName),\n 'SkuTerm', isoMonths(Term)\n ),\n dynamic({})\n )\n //\n // Prefer specified date, then fall back to generating a date based on reservation recommendation lookback period, then validate to ensure it's not in the future\n | extend x_RecommendationDate = coalesce(x_RecommendationDate, FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d))\n | extend x_RecommendationDate = iff(x_RecommendationDate > now(), startofday(now()), x_RecommendationDate)\n //\n // Derive x_ResourceType from ResourceId\n | extend tmp_ResourceType = tostring(parse_resourceid(ResourceId).x_ResourceType)\n | extend x_RecommendationDetails = iff(isnotempty(tmp_ResourceType), bag_merge(bag_pack('x_ResourceType', tmp_ResourceType), x_RecommendationDetails), x_RecommendationDetails)\n //\n // Set ResourceType display name from x_ResourceType code\n | extend ResourceType = coalesce(ResourceType, tostring(resource_type(tmp_ResourceType).SingularDisplayName), tmp_ResourceType)\n //\n | project\n ProviderName,\n ResourceId = tolower(ResourceId), // Force lowercase for consistent grouping/filtering\n ResourceName = tolower(iff(tmp_ResourceType =~ 'microsoft.resources/subscriptions', coalesce(SubAccountName, ResourceName), ResourceName)), // Use subscription name for subscription-level recommendations\n ResourceType,\n SubAccountId = coalesce(SubAccountId, iff(isnotempty(SubscriptionId), strcat('/subscriptions/', SubscriptionId), '')),\n SubAccountName,\n x_EffectiveCostAfter = coalesce(x_EffectiveCostAfter, TotalCostWithReservedInstances),\n x_EffectiveCostBefore = coalesce(x_EffectiveCostBefore, CostWithNoReservedInstances),\n x_EffectiveCostSavings = coalesce(x_EffectiveCostSavings, NetSavings, toreal(x_RecommendationDetails.x_SavingsAmount), toreal(x_RecommendationDetails.x_AnnualSavingsAmount) / 12),\n x_IngestionTime,\n x_RecommendationCategory, // TODO: Set for reservation recommendations\n x_RecommendationDate,\n x_RecommendationDescription = coalesce(x_RecommendationDescription, tostring(x_RecommendationDetails.x_RecommendationSolution), tostring(x_RecommendationDetails.x_RecommendationSubCategory)),\n x_RecommendationDetails,\n x_RecommendationId = tolower(x_RecommendationId), // TODO: Set for reservation recommendations; force lowercase for consistent grouping/filtering\n x_ResourceGroupName = tolower(x_ResourceGroupName), // Force lowercase for consistent grouping/filtering\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n// Recommendations_final_v1_2 table\n.create-merge table Recommendations_final_v1_2 (\n ProviderName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n SubAccountId: string,\n SubAccountName: string,\n x_EffectiveCostAfter: real,\n x_EffectiveCostBefore: real,\n x_EffectiveCostSavings: real,\n x_IngestionTime: datetime,\n x_RecommendationCategory: string,\n x_RecommendationDate: datetime,\n x_RecommendationDescription: string,\n x_RecommendationDetails: dynamic,\n x_RecommendationId: string,\n x_ResourceGroupName: string,\n x_SourceName: string,\n x_SourceProvider: string,\n x_SourceType: string,\n x_SourceVersion: string\n)\n\n// Update policy for Recommendations_raw -> Recommendations_final_v1_2 table\n.alter table Recommendations_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Recommendations_raw\",\n \"Query\": \"Recommendations_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All transactions transformed to FOCUS 1.2.', folder='Transactions')\nTransactions_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Transactions_raw\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationTransactions', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Handle BillingPeriodStart/End\n | extend BillingMonth = tostring(BillingMonth)\n | extend BillingPeriodStart = iff(isempty(BillingMonth), datetime(null), todatetime(strcat(substring(BillingMonth, 0, 4), \"-\", substring(BillingMonth, 4, 2), \"-\", substring(BillingMonth, 6, 2))))\n | extend BillingPeriodEnd = iff(isempty(BillingMonth), datetime(null), startofmonth(endofmonth(BillingPeriodStart) + 1d))\n //\n // Sort columns and apply final transforms\n | project\n BilledCost = Amount,\n BillingAccountId = case(\n BillingProfileId startswith '/', BillingProfileId,\n isnotempty(CurrentEnrollmentId), strcat('/providers/Microsoft.Billing/billingAccounts/', CurrentEnrollmentId),\n isnotempty(BillingProfileId), strcat('/providers/Microsoft.Billing/billingProfiles/', BillingProfileId),\n ''\n ),\n BillingAccountName = coalesce(BillingProfileName, CurrentEnrollmentId),\n BillingCurrency = Currency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory = case(\n EventType in ('Cancel', 'Purchase', 'Refund'), 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = case(\n EventType == 'Cancel', 'Cancel', // FOCUS does not handle this scenario\n EventType == 'Refund', 'Correction',\n ''\n ),\n ChargeDescription = Description,\n ChargeFrequency = case(\n BillingFrequency == 'OneTime', 'One-Time',\n BillingFrequency == 'Recurring', 'Recurring',\n BillingFrequency\n ),\n ChargePeriodStart = EventDate,\n InvoiceId,\n PricingQuantity = Quantity,\n PricingUnit = 'Reservations',\n ProviderName,\n RegionId = Region,\n RegionName = Region,\n SubAccountId = iff(isempty(PurchasingSubscriptionGuid), '', strcat('/subscriptions/', PurchasingSubscriptionGuid)),\n SubAccountName = iff(isempty(PurchasingSubscriptionGuid), '', PurchasingSubscriptionName),\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerEmail,\n x_CostCenter = CostCenter,\n x_InvoiceNumber = Invoice,\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = coalesce(InvoiceSectionName, DepartmentName),\n x_IngestionTime = ingestion_time(),\n x_MonetaryCommitment = MonetaryCommitment,\n x_Overage = Overage,\n x_PurchasingBillingAccountId = PurchasingEnrollment,\n x_SkuOrderId = ReservationOrderId,\n x_SkuOrderName = ReservationOrderName,\n x_SkuSize = ArmSkuName,\n x_SkuTerm = isoMonths(Term),\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId = PurchasingSubscriptionGuid,\n x_TransactionType = EventType\n}\n\n// Transactions_final_v1_2 table\n.create-merge table Transactions_final_v1_2 (\n BilledCost: real, // MS CM EA+MCA 2023-05-01\n BillingAccountId: string, // MS CM EA+MCA 2023-05-01\n BillingAccountName: string, // MS CM EA+MCA 2023-05-01\n BillingCurrency: string, // MS CM EA+MCA 2023-05-01\n BillingPeriodEnd: datetime, // MS CM EA+MCA 2023-05-01\n BillingPeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n ChargeCategory: string, // Hubs add-on\n ChargeClass: string, // Hubs add-on\n ChargeDescription: string, // MS CM EA+MCA 2023-05-01\n ChargeFrequency: string, // MS CM EA+MCA 2023-05-01\n ChargePeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n InvoiceId: string, // MS CM MCA 2023-05-01\n PricingQuantity: real, // MS CM EA+MCA 2023-05-01\n PricingUnit: string, // Hubs add-on\n ProviderName: string, // Hubs add-on\n RegionId: string, // MS CM EA+MCA 2023-05-01\n RegionName: string, // MS CM EA+MCA 2023-05-01\n SubAccountId: string, // MS CM EA+MCA 2023-05-01\n SubAccountName: string, // MS CM EA+MCA 2023-05-01\n x_AccountName: string, // MS CM EA 2023-05-01\n x_AccountOwnerId: string, // MS CM EA 2023-05-01\n x_CostCenter: string, // MS CM EA 2023-05-01\n x_InvoiceNumber: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionId: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionName: string, // MS CM MCA 2023-05-01\n x_IngestionTime: datetime, // Hubs add-on\n x_MonetaryCommitment: real, // MS CM EA 2023-05-01\n x_Overage: real, // MS CM EA 2023-05-01\n x_PurchasingBillingAccountId: string, // MS CM EA 2023-05-01\n x_SkuOrderId: string, // MS CM EA+MCA 2023-05-01\n x_SkuOrderName: string, // MS CM EA+MCA 2023-05-01\n x_SkuSize: string, // MS CM EA+MCA 2023-05-01\n x_SkuTerm: int, // MS CM EA+MCA 2023-05-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubscriptionId: string, // MS CM EA+MCA 2023-05-01\n x_TransactionType: string // MS CM EA+MCA 2023-05-01\n)\n\n// Update policy for Transactions_raw -> Transactions_final_v1_2 table\n.alter table Transactions_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Transactions_raw\",\n \"Query\": \"Transactions_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n", "$fxv#11": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Common utility functions\n//\n// TIP: Use Ctrl+K,Ctrl+0 to collapse all regions in VS Code\n//======================================================================================================================\n\n\n//===| Date functions |=================================================================================================\n\n// monthstring\n.create-or-alter function \nwith (docstring = @'Returns the name of the month for the specified date (e.g. Jan or January)', folder =@'Common') \nmonthstring(['date']: datetime, length: int = 9)\n{\n substring(dynamic(['January','February','March','April','May','June','July','August','September','October','November','December'])[getmonth(['date']) - 1], 0, length)\n}\n\n// datestring\n.create-or-alter function \nwith (docstring = @'Converts 2 dates into a simple, user-friendly date range (e.g. Jan 1-Jan 3)', folder =@'Common') \ndatestring(start: datetime, end: datetime = datetime('0001-01-01'))\n{\n let month = (d: datetime) { monthstring(d, 3) };\n let endDate = iff(end == datetime('0001-01-01'), start, end);\n let sameDate = startofday(start) == startofday(endDate);\n let sameMonth = startofmonth(start) == startofmonth(endDate);\n let sameYear = startofyear(start) == startofyear(endDate);\n let fullMonth = startofday(start) == startofmonth(start) and startofday(endDate) == startofday(endofmonth(endDate));\n let fullYear = startofday(start) == startofyear(start) and startofday(endDate) == startofday(endofyear(endDate));\n let currentYear = sameYear and startofyear(start) == startofyear(now());\n case(\n // Full year | yyyy (same year) / yyyy-yyyy (diff years)\n fullYear,\n strcat(getyear(start), iff(sameYear, '', strcat('-', getyear(endDate)))),\n // 1 full mo, same year | Mmm yyyy\n fullMonth and sameMonth and sameYear,\n strcat(month(start), ' ', getyear(start)),\n // 2+ full mo, same year | Mmm-Mmm (current year) / Mmm-Mmm yyyy (other year)\n fullMonth and sameYear,\n strcat(month(start), '-', month(endDate), iff(currentYear, '', strcat(' ', getyear(endDate)))),\n // Full mo, diff year | Mmm yyyy-Mmm yyyy\n fullMonth and not(sameYear),\n strcat(month(start), ' ', getyear(start), '-', month(endDate), ' ', getyear(endDate)),\n // Same date | Mmm d (current year) / Mmm d, yyyy (other year)\n sameDate,\n strcat(month(start), ' ', dayofmonth(start), iff(currentYear, '', strcat(', ', getyear(endDate)))),\n // 1 partial M, same Y | Mmm d-d (current year) / Mmm d-d, yyyy (other year)\n not(fullMonth) and sameMonth and sameYear,\n strcat(month(start), ' ', dayofmonth(start), '-', dayofmonth(endDate), iff(currentYear, '', strcat(' ', getyear(endDate)))),\n // 2+ partial M, same Y | Mmm d-Mmm d (current year) / Mmm d-Mmm d, yyyy (other year)\n not(fullMonth) and not(sameMonth) and sameYear,\n strcat(month(start), ' ', dayofmonth(start), '-', month(endDate), ' ', dayofmonth(endDate), iff(currentYear, '', strcat(', ', getyear(endDate)))),\n // All other cases | Mmm d, yyyy-Mmm d, yyyy\n strcat(month(start), ' ', dayofmonth(start), ', ', getyear(start), '-', month(endDate), ' ', dayofmonth(endDate), ', ', getyear(endDate))\n )\n}\n\n// daterange\n.create-or-alter function \nwith (docstring = @'DEPRECATED: Please use datestring(); function will be removed on or after the Jan 2026 release', folder =@'Common') \ndaterange(start: datetime, end: datetime = datetime('0001-01-01'))\n{\n datestring(start, end)\n}\n\n// monthsago\n.create-or-alter function \nwith (docstring = 'DEPRECATED: Please use startofmonth(now(), -<# of months>); function will be removed on or after the Jan 2026 release', folder = 'Common')\nmonthsago(months: int)\n{\n datetime_add('month', -months, startofmonth(now()))\n}\n\n\n//===| Number functions |===============================================================================================\n// NOTE: Must be defined before string converters\n\n// delta\n.create-or-alter function \nwith (docstring = @'Compares 2 values and returns the percentage change from oldval to newval', folder =@'Common') \ndelta(oldval: double, newval: double)\n{\n (newval - todouble(oldval))/oldval\n}\n\n// percentOfTotal\n// NOTE: Must be before percent() function\n.create-or-alter function \nwith (docstring = @'Calculates the percentage of each record based on a required Count column', folder =@'Common') \npercentOfTotal(t: (Count: long), tot: long)\n{\n let total = todouble(tot);\n t \n | extend Percent = round(Count / total * 100, 3) \n | order by Count desc\n}\n\n// percent\n.create-or-alter function \nwith (docstring = @'Calculates the percentage of each record based on a required Count column', folder =@'Common') \npercent(t: (Count: long))\n{\n let total = todouble(toscalar(t | summarize sum(Count)));\n percentOfTotal(t, total)\n}\n\n// plusminus\n.create-or-alter function \nwith (docstring = 'Shows a +/- sign based on the direction of the number', folder = 'Common')\nplusminus(val: string)\n{\n let neg = substring(val, 0, 1) == '-';\n iff(neg, val, strcat('+', val))\n}\n\n// updown\n.create-or-alter function \nwith (docstring = 'Shows an up/down arrow based on the direction of the number', folder = 'Common')\nupdown(val: string)\n{\n // TODO: Handle 0\n let neg = substring(val, 0, 1) == '-';\n iff(neg, strcat('↓', substring(val, 1)), strcat('↑', val))\n}\n\n\n//===| String functions |===============================================================================================\n\n// percentstring\n// NOTE: Must be defined before deltastring\n.create-or-alter function \nwith (docstring = 'Calculate a percentage and render as a string', folder = 'Common')\npercentstring(num: double, total: double = 1.0, places: int = 9)\n{\n let value = 1.0 * num / total * 100;\n strcat(case(\n places != 9, round(value, places),\n value < 10, round(value, 2),\n round(value, 1)\n ), '%')\n}\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// arraystring\n.create-or-alter function \nwith (docstring = 'Convert an array to a comma-delimited string', folder = 'Common')\narraystring(arr: dynamic)\n{\n replace_string(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(\n tostring(arr)\n , @'^\\[\"', '')\n , @'\"\\]$', '')\n , @'^, ', '')\n , @', $', '')\n , @'^\\[]$', '')\n , '\",\"', ', ')\n}\n\n// deltastring\n.create-or-alter function \nwith (docstring = 'Calculate a delta percentage and render as a string', folder = 'Common')\ndeltastring(oldval: double, newval: double, places: int = 1, useArrows: bool = false)\n{\n let d = delta(oldval, newval);\n strcat(case(useArrows and d > 0, '↑', useArrows and d < 0, '↓', d < 0, '-', ''), percentstring(abs(d), 1, places))\n}\n\n// diffstring\n.create-or-alter function \nwith (docstring = 'Calculate the difference and render as a string', folder = 'Common')\ndiffstring(oldval: double, newval: double, places: int = 1)\n{\n plusminus(round(newval - oldval, places))\n}\n\n// numberstring\n.create-or-alter function \nwith (docstring = 'Convert a number to a string', folder = 'Common')\nnumberstring(num: double, abbrev: bool = true)\n{\n replace_regex(case(\n num >= 10000000000000, strcat(round(1.0 * num / 1000000000000, 1), 'T'),\n num >= 1000000000000, strcat(round(1.0 * num / 1000000000000, 2), 'T'),\n num >= 10000000000, strcat(round(1.0 * num / 1000000000, 1), 'B'),\n num >= 1000000000, strcat(round(1.0 * num / 1000000000, 2), 'B'),\n num >= 10000000, strcat(round(1.0 * num / 1000000, 1), 'M'),\n num >= 1000000, strcat(round(1.0 * num / 1000000, 2), 'M'),\n num >= 10000, strcat(round(1.0 * num / 1000, 1), 'K'),\n // Kusto doesn't support back-refs yet -- num > 1000, replace_regex(tostring(num), @'(\\d)(?=(\\d{3})+\\.)', @'\\1,'), // See https://docs.microsoft.com/azure/data-explorer/kusto/query/re2-library\n num > 1000, replace_regex(tostring(num), @'([0-9]{3})$', @',\\1'), //num / 1000, ',', substring(tostring(num), 0) - (num / 1000 * 1000)),\n tostring(num)\n ), @'\\.0$', '')\n}\n\n\n//===| Other |==========================================================================================================\n\n// ifempty\n.create-or-alter function \nwith (docstring = 'Replaces an empty value with the specified default value', folder = 'Common')\nifempty(val: dynamic, defaultVal: dynamic)\n{\n iff(isempty(val), defaultVal, val)\n}\n", "$fxv#12": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Hub database / Open data functions\n// Wrap Ingestion database tables for easy access.\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n\n// PricingUnits\n.create-or-alter function\nwith (docstring = 'Gets pricing units from the FinOps toolkit PricingUnits open data.', folder = 'OpenData')\nPricingUnits()\n{\n database('Ingestion').PricingUnits\n}\n\n// Regions\n.create-or-alter function\nwith (docstring = 'Gets regions from the FinOps toolkit Regions open data.', folder = 'OpenData')\nRegion()\n{\n database('Ingestion').Regions\n}\n\n// ResourceTypes\n.create-or-alter function\nwith (docstring = 'Gets resource types from the FinOps toolkit ResourceTypes open data.', folder = 'OpenData')\nResourceType()\n{\n database('Ingestion').ResourceTypes\n}\n\n// Services\n.create-or-alter function\nwith (docstring = 'Gets services from the FinOps toolkit Services open data.', folder = 'OpenData')\nServices()\n{\n database('Ingestion').Services\n}\n", "$fxv#13": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Hub database / FOCUS 1.0 functions\n// Used for reporting with backward compatibility.\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n\n// CommitmentDiscountUsage_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all commitment discount usage records aligned to FOCUS 1.0.', folder = 'CommitmentDiscountUsage')\nCommitmentDiscountUsage_v1_0()\n{\n database('Ingestion').CommitmentDiscountUsage_final_v1_0\n | union (\n database('Ingestion').CommitmentDiscountUsage_final_v1_2\n // Convert real to decimal\n | extend\n CommitmentDiscountQuantity = todecimal(CommitmentDiscountQuantity),\n ConsumedQuantity = todecimal(ConsumedQuantity),\n x_CommitmentDiscountCommittedCount = todecimal(x_CommitmentDiscountCommittedCount),\n x_CommitmentDiscountCommittedAmount = todecimal(x_CommitmentDiscountCommittedAmount),\n x_CommitmentDiscountNormalizedRatio = todecimal(x_CommitmentDiscountNormalizedRatio)\n )\n | project\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId,\n CommitmentDiscountType,\n ConsumedQuantity,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SubAccountId,\n x_CommitmentDiscountCommittedCount,\n x_CommitmentDiscountCommittedAmount,\n x_CommitmentDiscountNormalizedGroup,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountQuantity,\n x_IngestionTime,\n x_ResourceGroupName,\n x_ResourceType,\n x_ServiceModel,\n x_SkuOrderId,\n x_SkuSize,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n\n// Costs_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all cost and usage records aligned to FOCUS 1.0.', folder = 'Costs')\nCosts_v1_0()\n{\n database('Ingestion').Costs_final_v1_0\n | union (\n database('Ingestion').Costs_final_v1_2\n // Convert real to decimal\n | extend\n BilledCost = todecimal(BilledCost),\n CommitmentDiscountQuantity = todecimal(CommitmentDiscountQuantity),\n ConsumedQuantity = todecimal(ConsumedQuantity),\n ContractedCost = todecimal(ContractedCost),\n ContractedUnitPrice = todecimal(ContractedUnitPrice),\n EffectiveCost = todecimal(EffectiveCost),\n ListCost = todecimal(ListCost),\n ListUnitPrice = todecimal(ListUnitPrice),\n PricingQuantity = todecimal(PricingQuantity),\n x_BilledCostInUsd = todecimal(x_BilledCostInUsd),\n x_BilledUnitPrice = todecimal(x_BilledUnitPrice),\n x_BillingExchangeRate = todecimal(x_BillingExchangeRate),\n x_CommitmentDiscountNormalizedRatio = todecimal(x_CommitmentDiscountNormalizedRatio),\n x_ContractedCostInUsd = todecimal(x_ContractedCostInUsd),\n x_CurrencyConversionRate = todecimal(x_CurrencyConversionRate),\n x_EffectiveCostInUsd = todecimal(x_EffectiveCostInUsd),\n x_EffectiveUnitPrice = todecimal(x_EffectiveUnitPrice),\n x_ListCostInUsd = todecimal(x_ListCostInUsd),\n x_PricingBlockSize = todecimal(x_PricingBlockSize)\n // Rename columns\n | project-rename\n x_InvoiceId = InvoiceId,\n x_PricingCurrency = PricingCurrency,\n x_SkuMeterName = SkuMeter\n // Generate historical x_SkuDetails format from SkuPriceDetails\n | extend x_SkuDetails = iff(isnotempty(x_SkuDetails), x_SkuDetails, parse_json(replace_regex(tostring(SkuPriceDetails), @'([\\{,])\"x_', @'\\1\"')))\n )\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId,\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory,\n ChargeClass,\n ChargeDescription,\n ChargeFrequency,\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId,\n CommitmentDiscountName,\n CommitmentDiscountStatus,\n CommitmentDiscountType,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost,\n ContractedUnitPrice,\n EffectiveCost,\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory,\n PricingQuantity,\n PricingUnit,\n ProviderName,\n PublisherName,\n RegionId,\n RegionName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SkuId,\n SkuPriceId,\n SubAccountId,\n SubAccountName,\n SubAccountType,\n Tags,\n x_AccountId,\n x_AccountName,\n x_AccountOwnerId,\n x_BilledCostInUsd,\n x_BilledUnitPrice,\n x_BillingAccountAgreement,\n x_BillingAccountId,\n x_BillingAccountName,\n x_BillingExchangeRate,\n x_BillingExchangeRateDate,\n x_BillingProfileId,\n x_BillingProfileName,\n x_ChargeId,\n x_ContractedCostInUsd,\n x_CostAllocationRuleName,\n x_CostCategories,\n x_CostCenter,\n x_Credits,\n x_CostType,\n x_CurrencyConversionRate,\n x_CustomerId,\n x_CustomerName,\n x_Discount,\n x_EffectiveCostInUsd,\n x_EffectiveUnitPrice,\n x_ExportTime,\n x_IngestionTime,\n x_InvoiceId,\n x_InvoiceIssuerId,\n x_InvoiceSectionId,\n x_InvoiceSectionName,\n x_ListCostInUsd,\n x_Location,\n x_Operation,\n x_PartnerCreditApplied,\n x_PartnerCreditRate,\n x_PricingBlockSize,\n x_PricingCurrency,\n x_PricingSubcategory,\n x_PricingUnitDescription,\n x_Project,\n x_PublisherCategory,\n x_PublisherId,\n x_ResellerId,\n x_ResellerName,\n x_ResourceGroupName,\n x_ResourceType,\n x_ServiceCode,\n x_ServiceId,\n x_ServicePeriodEnd,\n x_ServicePeriodStart,\n x_SkuDescription,\n x_SkuDetails,\n x_SkuIsCreditEligible,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterName,\n x_SkuMeterSubcategory,\n x_SkuOfferId,\n x_SkuOrderId,\n x_SkuOrderName,\n x_SkuPartNumber,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuTerm,\n x_SkuTier,\n x_SourceChanges,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_UsageType\n}\n\n\n// Prices_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all prices aligned to FOCUS 1.0.', folder = 'Prices')\nPrices_v1_0()\n{\n database('Ingestion').Prices_final_v1_0\n | union (\n database('Ingestion').Prices_final_v1_2\n // Convert real to decimal\n | extend\n ContractedUnitPrice = todecimal(ContractedUnitPrice),\n ListUnitPrice = todecimal(ListUnitPrice),\n x_BaseUnitPrice = todecimal(x_BaseUnitPrice),\n x_CommitmentDiscountNormalizedRatio = todecimal(x_CommitmentDiscountNormalizedRatio),\n x_ContractedUnitPriceDiscount = todecimal(x_ContractedUnitPriceDiscount),\n x_ContractedUnitPriceDiscountPercent = todecimal(x_ContractedUnitPriceDiscountPercent),\n x_EffectiveUnitPrice = todecimal(x_EffectiveUnitPrice),\n x_EffectiveUnitPriceDiscount = todecimal(x_EffectiveUnitPriceDiscount),\n x_EffectiveUnitPriceDiscountPercent = todecimal(x_EffectiveUnitPriceDiscountPercent),\n x_PricingBlockSize = todecimal(x_PricingBlockSize),\n x_SkuIncludedQuantity = todecimal(x_SkuIncludedQuantity),\n x_SkuTier = todecimal(x_SkuTier),\n x_TotalUnitPriceDiscount = todecimal(x_TotalUnitPriceDiscount),\n x_TotalUnitPriceDiscountPercent = todecimal(x_TotalUnitPriceDiscountPercent) \n // Rename columns\n | project-rename\n x_PricingCurrency = PricingCurrency,\n x_SkuMeterName = SkuMeter\n )\n | project\n BillingAccountId,\n BillingAccountName,\n BillingCurrency,\n ChargeCategory,\n CommitmentDiscountCategory,\n CommitmentDiscountType,\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory,\n PricingUnit,\n SkuId,\n SkuPriceId,\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement,\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent,\n x_EffectivePeriodEnd,\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingCurrency,\n x_PricingSubcategory,\n x_PricingUnitDescription,\n x_SkuDescription,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterName,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent\n}\n\n\n// Recommendations_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all recommendations aligned to FOCUS 1.0.', folder = 'Recommendations')\nRecommendations_v1_0()\n{\n database('Ingestion').Recommendations_final_v1_0\n | union (\n database('Ingestion').Recommendations_final_v1_2\n // Convert real to decimal\n | extend\n x_EffectiveCostAfter = todecimal(x_EffectiveCostAfter),\n x_EffectiveCostBefore = todecimal(x_EffectiveCostBefore),\n x_EffectiveCostSavings = todecimal(x_EffectiveCostSavings)\n )\n | project\n ProviderName,\n SubAccountId,\n x_IngestionTime,\n x_EffectiveCostAfter,\n x_EffectiveCostBefore,\n x_EffectiveCostSavings,\n x_RecommendationDate,\n x_RecommendationDetails,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n\n// Transactions_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all transactions aligned to FOCUS 1.0.', folder = 'Transactions')\nTransactions_v1_0()\n{\n database('Ingestion').Transactions_final_v1_0\n | union (\n database('Ingestion').Transactions_final_v1_2\n // Convert real to decimal\n | extend\n BilledCost = todecimal(BilledCost),\n PricingQuantity = todecimal(PricingQuantity),\n x_MonetaryCommitment = todecimal(x_MonetaryCommitment),\n x_Overage = todecimal(x_Overage)\n // Rename columns\n | project-rename\n x_InvoiceId = InvoiceId\n )\n | project\n BilledCost,\n BillingAccountId,\n BillingAccountName,\n BillingCurrency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory,\n ChargeClass,\n ChargeDescription,\n ChargeFrequency,\n ChargePeriodStart,\n PricingQuantity,\n PricingUnit,\n ProviderName,\n RegionId,\n RegionName,\n SubAccountId,\n SubAccountName,\n x_AccountName,\n x_AccountOwnerId,\n x_CostCenter,\n x_InvoiceId,\n x_InvoiceNumber,\n x_InvoiceSectionId,\n x_InvoiceSectionName,\n x_IngestionTime,\n x_MonetaryCommitment,\n x_Overage,\n x_PurchasingBillingAccountId,\n x_SkuOrderId,\n x_SkuOrderName,\n x_SkuSize,\n x_SkuTerm,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId,\n x_TransactionType\n}\n", @@ -18333,7 +18333,7 @@ "$fxv#6": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Common utility functions\n//\n// TIP: Use Ctrl+K,Ctrl+0 to collapse all regions in VS Code\n//======================================================================================================================\n\n\n//===| Date functions |=================================================================================================\n\n// monthstring\n.create-or-alter function \nwith (docstring = @'Returns the name of the month for the specified date (e.g. Jan or January)', folder =@'Common') \nmonthstring(['date']: datetime, length: int = 9)\n{\n substring(dynamic(['January','February','March','April','May','June','July','August','September','October','November','December'])[getmonth(['date']) - 1], 0, length)\n}\n\n// datestring\n.create-or-alter function \nwith (docstring = @'Converts 2 dates into a simple, user-friendly date range (e.g. Jan 1-Jan 3)', folder =@'Common') \ndatestring(start: datetime, end: datetime = datetime('0001-01-01'))\n{\n let month = (d: datetime) { monthstring(d, 3) };\n let endDate = iff(end == datetime('0001-01-01'), start, end);\n let sameDate = startofday(start) == startofday(endDate);\n let sameMonth = startofmonth(start) == startofmonth(endDate);\n let sameYear = startofyear(start) == startofyear(endDate);\n let fullMonth = startofday(start) == startofmonth(start) and startofday(endDate) == startofday(endofmonth(endDate));\n let fullYear = startofday(start) == startofyear(start) and startofday(endDate) == startofday(endofyear(endDate));\n let currentYear = sameYear and startofyear(start) == startofyear(now());\n case(\n // Full year | yyyy (same year) / yyyy-yyyy (diff years)\n fullYear,\n strcat(getyear(start), iff(sameYear, '', strcat('-', getyear(endDate)))),\n // 1 full mo, same year | Mmm yyyy\n fullMonth and sameMonth and sameYear,\n strcat(month(start), ' ', getyear(start)),\n // 2+ full mo, same year | Mmm-Mmm (current year) / Mmm-Mmm yyyy (other year)\n fullMonth and sameYear,\n strcat(month(start), '-', month(endDate), iff(currentYear, '', strcat(' ', getyear(endDate)))),\n // Full mo, diff year | Mmm yyyy-Mmm yyyy\n fullMonth and not(sameYear),\n strcat(month(start), ' ', getyear(start), '-', month(endDate), ' ', getyear(endDate)),\n // Same date | Mmm d (current year) / Mmm d, yyyy (other year)\n sameDate,\n strcat(month(start), ' ', dayofmonth(start), iff(currentYear, '', strcat(', ', getyear(endDate)))),\n // 1 partial M, same Y | Mmm d-d (current year) / Mmm d-d, yyyy (other year)\n not(fullMonth) and sameMonth and sameYear,\n strcat(month(start), ' ', dayofmonth(start), '-', dayofmonth(endDate), iff(currentYear, '', strcat(' ', getyear(endDate)))),\n // 2+ partial M, same Y | Mmm d-Mmm d (current year) / Mmm d-Mmm d, yyyy (other year)\n not(fullMonth) and not(sameMonth) and sameYear,\n strcat(month(start), ' ', dayofmonth(start), '-', month(endDate), ' ', dayofmonth(endDate), iff(currentYear, '', strcat(', ', getyear(endDate)))),\n // All other cases | Mmm d, yyyy-Mmm d, yyyy\n strcat(month(start), ' ', dayofmonth(start), ', ', getyear(start), '-', month(endDate), ' ', dayofmonth(endDate), ', ', getyear(endDate))\n )\n}\n\n// daterange\n.create-or-alter function \nwith (docstring = @'DEPRECATED: Please use datestring(); function will be removed on or after the Jan 2026 release', folder =@'Common') \ndaterange(start: datetime, end: datetime = datetime('0001-01-01'))\n{\n datestring(start, end)\n}\n\n// monthsago\n.create-or-alter function \nwith (docstring = 'DEPRECATED: Please use startofmonth(now(), -<# of months>); function will be removed on or after the Jan 2026 release', folder = 'Common')\nmonthsago(months: int)\n{\n datetime_add('month', -months, startofmonth(now()))\n}\n\n\n//===| Number functions |===============================================================================================\n// NOTE: Must be defined before string converters\n\n// delta\n.create-or-alter function \nwith (docstring = @'Compares 2 values and returns the percentage change from oldval to newval', folder =@'Common') \ndelta(oldval: double, newval: double)\n{\n (newval - todouble(oldval))/oldval\n}\n\n// percentOfTotal\n// NOTE: Must be before percent() function\n.create-or-alter function \nwith (docstring = @'Calculates the percentage of each record based on a required Count column', folder =@'Common') \npercentOfTotal(t: (Count: long), tot: long)\n{\n let total = todouble(tot);\n t \n | extend Percent = round(Count / total * 100, 3) \n | order by Count desc\n}\n\n// percent\n.create-or-alter function \nwith (docstring = @'Calculates the percentage of each record based on a required Count column', folder =@'Common') \npercent(t: (Count: long))\n{\n let total = todouble(toscalar(t | summarize sum(Count)));\n percentOfTotal(t, total)\n}\n\n// plusminus\n.create-or-alter function \nwith (docstring = 'Shows a +/- sign based on the direction of the number', folder = 'Common')\nplusminus(val: string)\n{\n let neg = substring(val, 0, 1) == '-';\n iff(neg, val, strcat('+', val))\n}\n\n// updown\n.create-or-alter function \nwith (docstring = 'Shows an up/down arrow based on the direction of the number', folder = 'Common')\nupdown(val: string)\n{\n // TODO: Handle 0\n let neg = substring(val, 0, 1) == '-';\n iff(neg, strcat('↓', substring(val, 1)), strcat('↑', val))\n}\n\n\n//===| String functions |===============================================================================================\n\n// percentstring\n// NOTE: Must be defined before deltastring\n.create-or-alter function \nwith (docstring = 'Calculate a percentage and render as a string', folder = 'Common')\npercentstring(num: double, total: double = 1.0, places: int = 9)\n{\n let value = 1.0 * num / total * 100;\n strcat(case(\n places != 9, round(value, places),\n value < 10, round(value, 2),\n round(value, 1)\n ), '%')\n}\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// arraystring\n.create-or-alter function \nwith (docstring = 'Convert an array to a comma-delimited string', folder = 'Common')\narraystring(arr: dynamic)\n{\n replace_string(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(\n tostring(arr)\n , @'^\\[\"', '')\n , @'\"\\]$', '')\n , @'^, ', '')\n , @', $', '')\n , @'^\\[]$', '')\n , '\",\"', ', ')\n}\n\n// deltastring\n.create-or-alter function \nwith (docstring = 'Calculate a delta percentage and render as a string', folder = 'Common')\ndeltastring(oldval: double, newval: double, places: int = 1, useArrows: bool = false)\n{\n let d = delta(oldval, newval);\n strcat(case(useArrows and d > 0, '↑', useArrows and d < 0, '↓', d < 0, '-', ''), percentstring(abs(d), 1, places))\n}\n\n// diffstring\n.create-or-alter function \nwith (docstring = 'Calculate the difference and render as a string', folder = 'Common')\ndiffstring(oldval: double, newval: double, places: int = 1)\n{\n plusminus(round(newval - oldval, places))\n}\n\n// numberstring\n.create-or-alter function \nwith (docstring = 'Convert a number to a string', folder = 'Common')\nnumberstring(num: double, abbrev: bool = true)\n{\n replace_regex(case(\n num >= 10000000000000, strcat(round(1.0 * num / 1000000000000, 1), 'T'),\n num >= 1000000000000, strcat(round(1.0 * num / 1000000000000, 2), 'T'),\n num >= 10000000000, strcat(round(1.0 * num / 1000000000, 1), 'B'),\n num >= 1000000000, strcat(round(1.0 * num / 1000000000, 2), 'B'),\n num >= 10000000, strcat(round(1.0 * num / 1000000, 1), 'M'),\n num >= 1000000, strcat(round(1.0 * num / 1000000, 2), 'M'),\n num >= 10000, strcat(round(1.0 * num / 1000, 1), 'K'),\n // Kusto doesn't support back-refs yet -- num > 1000, replace_regex(tostring(num), @'(\\d)(?=(\\d{3})+\\.)', @'\\1,'), // See https://docs.microsoft.com/azure/data-explorer/kusto/query/re2-library\n num > 1000, replace_regex(tostring(num), @'([0-9]{3})$', @',\\1'), //num / 1000, ',', substring(tostring(num), 0) - (num / 1000 * 1000)),\n tostring(num)\n ), @'\\.0$', '')\n}\n\n\n//===| Other |==========================================================================================================\n\n// ifempty\n.create-or-alter function \nwith (docstring = 'Replaces an empty value with the specified default value', folder = 'Common')\nifempty(val: dynamic, defaultVal: dynamic)\n{\n iff(isempty(val), defaultVal, val)\n}\n", "$fxv#7": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// Used for data ingestion, normalization, and cleansing.\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Settings |=======================================================================================================\n\n.create-merge table HubSettingsLog (\n version: string,\n scopes: dynamic,\n retention: dynamic\n)\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// HubSettings function\n.create-or-alter function\nwith (docstring='Gets the latest version of hub settings.', folder='Settings')\nHubSettings()\n{\n HubSettingsLog\n | extend timestamp = ingestion_time()\n | summarize arg_max(timestamp, *)\n}\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// HubScopes function\n.create-or-alter function\nwith (docstring='Gets the currently configured scopes.', folder='Settings')\nHubScopes()\n{\n HubSettings\n | project scopes\n | mv-expand scopes\n}\n\n\n//===| Open data |======================================================================================================\n\n// PricingUnits -- Create table if it doesn't exist\n.create-merge table PricingUnits ( ignore: string )\n\n// PricingUnits -- Remove all columns\n.alter table PricingUnits ( ignore: string )\n\n// PricingUnits -- Redefine all columns to change types\n.alter table PricingUnits (\n x_PricingUnitDescription: string,\n x_PricingBlockSize: real,\n PricingUnit: string\n)\n\n// Regions\n.create-merge table Regions(\n ResourceLocation: string,\n RegionId: string,\n RegionName: string\n)\n\n// ResourceTypes\n.create-merge table ResourceTypes(\n x_ResourceType: string,\n SingularDisplayName: string,\n PluralDisplayName: string,\n LowerSingularDisplayName: string,\n LowerPluralDisplayName: string,\n IsPreview: bool,\n Description: string,\n IconUri: string\n)\n\n// Services\n.create-merge table Services(\n x_ConsumedService: string,\n x_ResourceType: string,\n ServiceName: string,\n ServiceCategory: string,\n ServiceSubcategory: string,\n PublisherName: string,\n x_PublisherCategory: string,\n x_Environment: string,\n x_ServiceModel: string\n)\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// parse_resourceid\n.create-or-alter function\nwith (docstring = 'Parses an Azure resource ID to extract resource attributes like the name, type, resource group, and subaccount ID.', folder = 'Common')\nparse_resourceid(resourceId: string) {\n let ResourceId = tolower(resourceId);\n // let ResourceId = tolower('/providers/Microsoft.BillingBenefits/savingsPlanOrders/2d2e284b-0638-427e-b8c6-1b874d4f17c8/sp/xxx');\n let SubAccountId = tostring(extract('/subscriptions/[^/]+', 1, ResourceId));\n let x_ResourceGroupName = tostring(extract('/resourcegroups/[^/]+', 1, ResourceId));\n let tmp_ResourceId = iff(ResourceId !contains '/providers/' and ResourceId startswith '/subscriptions/', strcat('/providers/microsoft.resources', ResourceId), ResourceId);\n let providerPath = iff(tmp_ResourceId !contains '/providers/', '', tostring(split(tmp_ResourceId, '/providers/')[-1]));\n let x_ResourceProvider = iff(isempty(providerPath), '', split(providerPath, '/')[0]);\n let tmp_ResourceProviderPath = iff(isempty(providerPath), '', substring(providerPath, strlen(x_ResourceProvider) + 1));\n let segments = split(tmp_ResourceProviderPath, '/');\n let ResourceName = trim(@'/+', replace_string(strcat_array(array_iff(\n dynamic([false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true]),\n segments, dynamic([])), '/'), '//', '/'));\n let x_ResourceTypePath = trim(@'/+', replace_string(strcat_array(array_iff(\n dynamic([true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false]),\n segments, dynamic([])), '/'), '//', '/'));\n let xRT = iff(isempty(x_ResourceProvider) or isempty(x_ResourceTypePath), '', strcat(x_ResourceProvider, '/', x_ResourceTypePath));\n // TODO: Remove ResourceType in 0.9\n bag_pack('ResourceId', ResourceId, 'ResourceName', ResourceName, 'ResourceType', xRT, 'SubAccountId', SubAccountId, 'x_ResourceGroupName', x_ResourceGroupName, 'x_ResourceProvider', x_ResourceProvider, 'x_ResourceType', xRT)\n}\n", "$fxv#8": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// Used for data ingestion, normalization, and cleansing.\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| ActualCosts |====================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_raw table -- Create the table if it doesn't exist\n.create-merge table ActualCosts_raw ( ignore: string )\n\n// ActualCosts_raw table -- Remove all columns to allow changing column types\n.alter table ActualCosts_raw ( ignore: string )\n\n// ActualCosts_raw table -- Redefine all columns\n.alter table ActualCosts_raw (\n AccountName: string,\n AccountOwnerId: string,\n AdditionalInfo: string,\n AvailabilityZone: string,\n BillingAccountId: string, \n BillingAccountName: string,\n BillingCurrency: string,\n BillingPeriodEndDate: datetime,\n BillingPeriodStartDate: datetime,\n BillingProfileId: string,\n BillingProfileName: string,\n ChargeType: string,\n ConsumedService: string,\n CostCenter: string,\n Cost: real,\n Date: datetime,\n EffectivePrice: real,\n Frequency: string,\n InvoiceSection: string,\n InvoiceSectionId: string,\n IsAzureCreditEligible: bool,\n MeterCategory: string,\n MeterId: string,\n MeterName: string,\n MeterRegion: string,\n MeterSubCategory: string,\n OfferId: string,\n PartNumber: string,\n PlanName: string,\n Product: string,\n ProductOrderId: string,\n ProductOrderName: string,\n PublisherName: string,\n PublisherType: string,\n Quantity: real,\n ReservationId: string,\n ReservationName: string,\n ResourceGroup: string,\n ResourceId: string,\n ResourceLocation: string,\n ResourceName: string,\n ServiceFamily: string,\n ServiceInfo1: string,\n ServiceInfo2: string,\n SubscriptionId: string,\n SubscriptionName: string,\n Tags: string,\n Term: string,\n UnitOfMeasure: string,\n UnitPrice: real\n)\n\n// ActualCosts_raw ingestion mapping\n.create-or-alter table ActualCosts_raw ingestion parquet mapping \"ActualCosts_raw_mapping\"\n```\n[\n { \"Column\": \"AccountName\", \"Properties\": { \"Field\": \"AccountName\" } },\n { \"Column\": \"AccountOwnerId\", \"Properties\": { \"Field\": \"AccountOwnerId\" } },\n { \"Column\": \"AdditionalInfo\", \"Properties\": { \"Field\": \"AdditionalInfo\" } },\n { \"Column\": \"AvailabilityZone\", \"Properties\": { \"Field\": \"AvailabilityZone\" } },\n { \"Column\": \"BillingAccountId\", \"Properties\": { \"Field\": \"BillingAccountId\" } },\n { \"Column\": \"BillingAccountName\", \"Properties\": { \"Field\": \"BillingAccountName\" } },\n { \"Column\": \"BillingCurrency\", \"Properties\": { \"Field\": \"BillingCurrency\" } },\n { \"Column\": \"BillingPeriodEndDate\", \"Properties\": { \"Field\": \"BillingPeriodEndDate\" } },\n { \"Column\": \"BillingPeriodStartDate\", \"Properties\": { \"Field\": \"BillingPeriodStartDate\" } },\n { \"Column\": \"BillingProfileId\", \"Properties\": { \"Field\": \"BillingProfileId\" } },\n { \"Column\": \"BillingProfileName\", \"Properties\": { \"Field\": \"BillingProfileName\" } },\n { \"Column\": \"ChargeType\", \"Properties\": { \"Field\": \"ChargeType\" } },\n { \"Column\": \"ConsumedService\", \"Properties\": { \"Field\": \"ConsumedService\" } },\n { \"Column\": \"CostCenter\", \"Properties\": { \"Field\": \"CostCenter\" } },\n { \"Column\": \"Cost\", \"Properties\": { \"Field\": \"Cost\" } },\n { \"Column\": \"Date\", \"Properties\": { \"Field\": \"Date\" } },\n { \"Column\": \"EffectivePrice\", \"Properties\": { \"Field\": \"EffectivePrice\" } },\n { \"Column\": \"Frequency\", \"Properties\": { \"Field\": \"Frequency\" } },\n { \"Column\": \"InvoiceSection\", \"Properties\": { \"Field\": \"InvoiceSection\" } },\n { \"Column\": \"InvoiceSectionId\", \"Properties\": { \"Field\": \"InvoiceSectionId\" } },\n { \"Column\": \"IsAzureCreditEligible\", \"Properties\": { \"Field\": \"IsAzureCreditEligible\" } },\n { \"Column\": \"MeterCategory\", \"Properties\": { \"Field\": \"MeterCategory\" } },\n { \"Column\": \"MeterId\", \"Properties\": { \"Field\": \"MeterId\" } },\n { \"Column\": \"MeterName\", \"Properties\": { \"Field\": \"MeterName\" } },\n { \"Column\": \"MeterRegion\", \"Properties\": { \"Field\": \"MeterRegion\" } },\n { \"Column\": \"MeterSubCategory\", \"Properties\": { \"Field\": \"MeterSubCategory\" } },\n { \"Column\": \"OfferId\", \"Properties\": { \"Field\": \"OfferId\" } },\n { \"Column\": \"PartNumber\", \"Properties\": { \"Field\": \"PartNumber\" } },\n { \"Column\": \"PlanName\", \"Properties\": { \"Field\": \"PlanName\" } },\n { \"Column\": \"Product\", \"Properties\": { \"Field\": \"Product\" } },\n { \"Column\": \"ProductOrderId\", \"Properties\": { \"Field\": \"ProductOrderId\" } },\n { \"Column\": \"ProductOrderName\", \"Properties\": { \"Field\": \"ProductOrderName\" } },\n { \"Column\": \"PublisherName\", \"Properties\": { \"Field\": \"PublisherName\" } },\n { \"Column\": \"PublisherType\", \"Properties\": { \"Field\": \"PublisherType\" } },\n { \"Column\": \"Quantity\", \"Properties\": { \"Field\": \"Quantity\" } },\n { \"Column\": \"ReservationId\", \"Properties\": { \"Field\": \"ReservationId\" } },\n { \"Column\": \"ReservationName\", \"Properties\": { \"Field\": \"ReservationName\" } },\n { \"Column\": \"ResourceGroup\", \"Properties\": { \"Field\": \"ResourceGroup\" } },\n { \"Column\": \"ResourceId\", \"Properties\": { \"Field\": \"ResourceId\" } },\n { \"Column\": \"ResourceLocation\", \"Properties\": { \"Field\": \"ResourceLocation\" } },\n { \"Column\": \"ResourceName\", \"Properties\": { \"Field\": \"ResourceName\" } },\n { \"Column\": \"ServiceFamily\", \"Properties\": { \"Field\": \"ServiceFamily\" } },\n { \"Column\": \"ServiceInfo1\", \"Properties\": { \"Field\": \"ServiceInfo1\" } },\n { \"Column\": \"ServiceInfo2\", \"Properties\": { \"Field\": \"ServiceInfo2\" } },\n { \"Column\": \"SubscriptionId\", \"Properties\": { \"Field\": \"SubscriptionId\" } },\n { \"Column\": \"SubscriptionName\", \"Properties\": { \"Field\": \"SubscriptionName\" } },\n { \"Column\": \"Tags\", \"Properties\": { \"Field\": \"Tags\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"UnitOfMeasure\", \"Properties\": { \"Field\": \"UnitOfMeasure\" } },\n { \"Column\": \"UnitPrice\", \"Properties\": { \"Field\": \"UnitPrice\" } }\n]\n```\n\n// ActualCosts_raw retention policy (clear historical data)\n.alter-merge table ActualCosts_raw policy retention softdelete = 0d recoverability = disabled\n\n// ActualCosts_raw retention policy (set the user-defined retention period)\n.alter-merge table ActualCosts_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable ActualCosts_raw streaming ingestion (required for Fabric)\n.alter table ActualCosts_raw policy streamingingestion disable\n\n\n//===| AmortizedCosts |=================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_raw table -- Create the table if it doesn't exist\n.create-merge table AmortizedCosts_raw ( ignore: string )\n\n// AmortizedCosts_raw table -- Remove all columns to allow changing column types\n.alter table AmortizedCosts_raw ( ignore: string )\n\n// AmortizedCosts_raw table -- Redefine all columns\n.alter table AmortizedCosts_raw (\n AccountName: string,\n AccountOwnerId: string,\n AdditionalInfo: string,\n AvailabilityZone: string,\n BillingAccountId: string, \n BillingAccountName: string,\n BillingCurrency: string,\n BillingPeriodEndDate: datetime,\n BillingPeriodStartDate: datetime,\n BillingProfileId: string,\n BillingProfileName: string,\n ChargeType: string,\n ConsumedService: string,\n CostCenter: string,\n Cost: real,\n Date: datetime,\n EffectivePrice: real,\n Frequency: string,\n InvoiceSection: string,\n InvoiceSectionId: string,\n IsAzureCreditEligible: bool,\n MeterCategory: string,\n MeterId: string,\n MeterName: string,\n MeterRegion: string,\n MeterSubCategory: string,\n OfferId: string,\n PartNumber: string,\n PlanName: string,\n Product: string,\n ProductOrderId: string,\n ProductOrderName: string,\n PublisherName: string,\n PublisherType: string,\n Quantity: real,\n ReservationId: string,\n ReservationName: string,\n ResourceGroup: string,\n ResourceId: string,\n ResourceLocation: string,\n ResourceName: string,\n ServiceFamily: string,\n ServiceInfo1: string,\n ServiceInfo2: string,\n SubscriptionId: string,\n SubscriptionName: string,\n Tags: string,\n Term: string,\n UnitOfMeasure: string,\n UnitPrice: real\n)\n\n// AmortizedCosts_raw ingestion mapping\n.create-or-alter table AmortizedCosts_raw ingestion parquet mapping \"AmortizedCosts_raw_mapping\"\n```\n[\n { \"Column\": \"AccountName\", \"Properties\": { \"Field\": \"AccountName\" } },\n { \"Column\": \"AccountOwnerId\", \"Properties\": { \"Field\": \"AccountOwnerId\" } },\n { \"Column\": \"AdditionalInfo\", \"Properties\": { \"Field\": \"AdditionalInfo\" } },\n { \"Column\": \"AvailabilityZone\", \"Properties\": { \"Field\": \"AvailabilityZone\" } },\n { \"Column\": \"BillingAccountId\", \"Properties\": { \"Field\": \"BillingAccountId\" } },\n { \"Column\": \"BillingAccountName\", \"Properties\": { \"Field\": \"BillingAccountName\" } },\n { \"Column\": \"BillingCurrency\", \"Properties\": { \"Field\": \"BillingCurrency\" } },\n { \"Column\": \"BillingPeriodEndDate\", \"Properties\": { \"Field\": \"BillingPeriodEndDate\" } },\n { \"Column\": \"BillingPeriodStartDate\", \"Properties\": { \"Field\": \"BillingPeriodStartDate\" } },\n { \"Column\": \"BillingProfileId\", \"Properties\": { \"Field\": \"BillingProfileId\" } },\n { \"Column\": \"BillingProfileName\", \"Properties\": { \"Field\": \"BillingProfileName\" } },\n { \"Column\": \"ChargeType\", \"Properties\": { \"Field\": \"ChargeType\" } },\n { \"Column\": \"ConsumedService\", \"Properties\": { \"Field\": \"ConsumedService\" } },\n { \"Column\": \"CostCenter\", \"Properties\": { \"Field\": \"CostCenter\" } },\n { \"Column\": \"Cost\", \"Properties\": { \"Field\": \"Cost\" } },\n { \"Column\": \"Date\", \"Properties\": { \"Field\": \"Date\" } },\n { \"Column\": \"EffectivePrice\", \"Properties\": { \"Field\": \"EffectivePrice\" } },\n { \"Column\": \"Frequency\", \"Properties\": { \"Field\": \"Frequency\" } },\n { \"Column\": \"InvoiceSection\", \"Properties\": { \"Field\": \"InvoiceSection\" } },\n { \"Column\": \"InvoiceSectionId\", \"Properties\": { \"Field\": \"InvoiceSectionId\" } },\n { \"Column\": \"IsAzureCreditEligible\", \"Properties\": { \"Field\": \"IsAzureCreditEligible\" } },\n { \"Column\": \"MeterCategory\", \"Properties\": { \"Field\": \"MeterCategory\" } },\n { \"Column\": \"MeterId\", \"Properties\": { \"Field\": \"MeterId\" } },\n { \"Column\": \"MeterName\", \"Properties\": { \"Field\": \"MeterName\" } },\n { \"Column\": \"MeterRegion\", \"Properties\": { \"Field\": \"MeterRegion\" } },\n { \"Column\": \"MeterSubCategory\", \"Properties\": { \"Field\": \"MeterSubCategory\" } },\n { \"Column\": \"OfferId\", \"Properties\": { \"Field\": \"OfferId\" } },\n { \"Column\": \"PartNumber\", \"Properties\": { \"Field\": \"PartNumber\" } },\n { \"Column\": \"PlanName\", \"Properties\": { \"Field\": \"PlanName\" } },\n { \"Column\": \"Product\", \"Properties\": { \"Field\": \"Product\" } },\n { \"Column\": \"ProductOrderId\", \"Properties\": { \"Field\": \"ProductOrderId\" } },\n { \"Column\": \"ProductOrderName\", \"Properties\": { \"Field\": \"ProductOrderName\" } },\n { \"Column\": \"PublisherName\", \"Properties\": { \"Field\": \"PublisherName\" } },\n { \"Column\": \"PublisherType\", \"Properties\": { \"Field\": \"PublisherType\" } },\n { \"Column\": \"Quantity\", \"Properties\": { \"Field\": \"Quantity\" } },\n { \"Column\": \"ReservationId\", \"Properties\": { \"Field\": \"ReservationId\" } },\n { \"Column\": \"ReservationName\", \"Properties\": { \"Field\": \"ReservationName\" } },\n { \"Column\": \"ResourceGroup\", \"Properties\": { \"Field\": \"ResourceGroup\" } },\n { \"Column\": \"ResourceId\", \"Properties\": { \"Field\": \"ResourceId\" } },\n { \"Column\": \"ResourceLocation\", \"Properties\": { \"Field\": \"ResourceLocation\" } },\n { \"Column\": \"ResourceName\", \"Properties\": { \"Field\": \"ResourceName\" } },\n { \"Column\": \"ServiceFamily\", \"Properties\": { \"Field\": \"ServiceFamily\" } },\n { \"Column\": \"ServiceInfo1\", \"Properties\": { \"Field\": \"ServiceInfo1\" } },\n { \"Column\": \"ServiceInfo2\", \"Properties\": { \"Field\": \"ServiceInfo2\" } },\n { \"Column\": \"SubscriptionId\", \"Properties\": { \"Field\": \"SubscriptionId\" } },\n { \"Column\": \"SubscriptionName\", \"Properties\": { \"Field\": \"SubscriptionName\" } },\n { \"Column\": \"Tags\", \"Properties\": { \"Field\": \"Tags\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"UnitOfMeasure\", \"Properties\": { \"Field\": \"UnitOfMeasure\" } },\n { \"Column\": \"UnitPrice\", \"Properties\": { \"Field\": \"UnitPrice\" } }\n]\n```\n\n// AmortizedCosts_raw retention policy (clear historical data)\n.alter-merge table AmortizedCosts_raw policy retention softdelete = 0d recoverability = disabled\n\n// AmortizedCosts_raw retention policy (set the user-defined retention period)\n.alter-merge table AmortizedCosts_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable AmortizedCosts_raw streaming ingestion (required for Fabric)\n.alter table AmortizedCosts_raw policy streamingingestion disable\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_raw table -- Create the table if it doesn't exist\n.create-merge table CommitmentDiscountUsage_raw ( ignore: string )\n\n// CommitmentDiscountUsage_raw table -- Remove all columns to allow changing column types\n.alter table CommitmentDiscountUsage_raw ( ignore: string )\n\n// CommitmentDiscountUsage_raw table -- Redefine all columns\n.alter table CommitmentDiscountUsage_raw (\n InstanceFlexibilityGroup: string,\n InstanceFlexibilityRatio: real,\n InstanceId: string,\n Kind: string,\n ReservationId: string,\n ReservationOrderId: string,\n ReservedHours: real,\n SkuName: string,\n TotalReservedQuantity: real,\n UsageDate: datetime,\n UsedHours: real,\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string // Hubs v1_0+\n)\n\n// CommitmentDiscountUsage_raw ingestion mapping\n.create-or-alter table CommitmentDiscountUsage_raw ingestion parquet mapping \"CommitmentDiscountUsage_raw_mapping\"\n```\n[\n { \"Column\": \"InstanceFlexibilityGroup\", \"Properties\": { \"Field\": \"InstanceFlexibilityGroup\" } },\n { \"Column\": \"InstanceFlexibilityRatio\", \"Properties\": { \"Field\": \"InstanceFlexibilityRatio\" } },\n { \"Column\": \"InstanceId\", \"Properties\": { \"Field\": \"InstanceId\" } },\n { \"Column\": \"Kind\", \"Properties\": { \"Field\": \"Kind\" } },\n { \"Column\": \"ReservationId\", \"Properties\": { \"Field\": \"ReservationId\" } },\n { \"Column\": \"ReservationOrderId\", \"Properties\": { \"Field\": \"ReservationOrderId\" } },\n { \"Column\": \"ReservedHours\", \"Properties\": { \"Field\": \"ReservedHours\" } },\n { \"Column\": \"SkuName\", \"Properties\": { \"Field\": \"SkuName\" } },\n { \"Column\": \"TotalReservedQuantity\", \"Properties\": { \"Field\": \"TotalReservedQuantity\" } },\n { \"Column\": \"UsageDate\", \"Properties\": { \"Field\": \"UsageDate\" } },\n { \"Column\": \"UsedHours\", \"Properties\": { \"Field\": \"UsedHours\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } }\n]\n```\n\n// CommitmentDiscountUsage_raw retention policy (clear historical data)\n.alter-merge table CommitmentDiscountUsage_raw policy retention softdelete = 0d recoverability = disabled\n\n// CommitmentDiscountUsage_raw retention policy (set the user-defined retention period)\n.alter-merge table CommitmentDiscountUsage_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable CommitmentDiscountUsage_raw streaming ingestion (required for Fabric)\n.alter table CommitmentDiscountUsage_raw policy streamingingestion disable\n\n\n//===| Costs |==========================================================================================================\n// Supported versions:\n// - MS: 1.0, 1.0-preview(v1) -- See https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0 -- See https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024 -- See https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 -- See https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n// - Tencent: 1.0 -- See https://www.tencentcloud.com/document/product/555/67495 / https://www.tencentcloud.com/document/product/555/67496\n// - Alibaba: 1.0 -- See https://www.alibabacloud.com/help/en/user-center/user-guide/export-alibaba-cloud-standard-billing-focus\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_raw table -- Create the table if it doesn't exist\n.create-merge table Costs_raw ( ignore: string )\n\n// Costs_raw table -- Remove all columns to allow changing column types\n.alter table Costs_raw ( ignore: string )\n\n// Costs_raw table -- Redefine all columns\n.alter table Costs_raw (\n AvailabilityZone: string, // FOCUS 0.5+\n BilledCost: real, // FOCUS 0.5+\n BillingAccountId: string, // FOCUS 0.5+\n BillingAccountName: string, // FOCUS 0.5+\n BillingAccountType: string, // Azure 1.0-preview(v1)+\n BillingCurrency: string, // FOCUS 0.5+\n BillingPeriodEnd: datetime, // FOCUS 0.5+\n BillingPeriodStart: datetime, // FOCUS 0.5+\n CapacityReservationId: string, // FOCUS 1.1+\n CapacityReservationStatus: string, // FOCUS 1.1+\n ChargeCategory: string, // FOCUS 1.0-preview+\n ChargeClass: string, // FOCUS 1.0+\n ChargeDescription: string, // FOCUS 1.0+\n ChargeFrequency: string, // FOCUS 1.0+\n ChargePeriodEnd: datetime, // FOCUS 0.5+\n ChargePeriodStart: datetime, // FOCUS 0.5+\n ChargeSubcategory: string, // FOCUS 1.0-preview only\n CommitmentDiscountCategory: string, // FOCUS 1.0-preview+\n CommitmentDiscountId: string, // FOCUS 1.0-preview+\n CommitmentDiscountName: string, // FOCUS 1.0-preview+\n CommitmentDiscountQuantity: real, // FOCUS 1.1+\n CommitmentDiscountStatus: string, // FOCUS 1.0+\n CommitmentDiscountType: string, // FOCUS 1.0-preview+\n CommitmentDiscountUnit: string, // FOCUS 1.1+\n ConsumedQuantity: real, // FOCUS 1.0+\n ConsumedUnit: string, // FOCUS 1.0+\n ContractedCost: real, // FOCUS 1.0+\n ContractedUnitPrice: real, // FOCUS 1.0+\n EffectiveCost: real, // FOCUS 1.0-preview+\n InvoiceId: string, // FOCUS 1.2+\n InvoiceIssuerName: string, // FOCUS 0.5+\n ListCost: real, // FOCUS 1.0-preview+\n ListUnitPrice: real, // FOCUS 1.0-preview+\n PricingCategory: string, // FOCUS 1.0-preview+\n PricingCurrency: string, // FOCUS 1.2+\n PricingQuantity: real, // FOCUS 1.0-preview+\n PricingUnit: string, // FOCUS 1.0-preview+\n ProviderName: string, // FOCUS 0.5+\n PublisherName: string, // FOCUS 0.5+\n Region: string, // FOCUS 0.5-1.0-preview (deprecated)\n RegionId: string, // FOCUS 1.0+\n RegionName: string, // FOCUS 1.0+\n ResourceId: string, // FOCUS 0.5+\n ResourceName: string, // FOCUS 0.5+\n ResourceType: string, // FOCUS 1.0-preview+\n ServiceCategory: string, // FOCUS 0.5+\n ServiceName: string, // FOCUS 0.5+\n ServiceSubcategory: string, // FOCUS 1.1+\n SkuId: string, // FOCUS 1.0-preview+\n SkuMeter: string, // FOCUS 1.1+\n SkuPriceDetails: string, // FOCUS 1.1+\n SkuPriceId: string, // FOCUS 1.0-preview+\n SubAccountId: string, // FOCUS 0.5+\n SubAccountName: string, // FOCUS 0.5+\n SubAccountType: string, // Azure 1.0-preview(v1)+\n Tags: string, // FOCUS 1.0-preview+\n UsageAmount: real, // GCP Jan 2024 -- Removed Mar 2024 (UsageQuantity)\n UsageQuantity: real, // FOCUS 1.0-preview only\n UsageUnit: string, // FOCUS 1.0-preview only\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_AmortizationClass: string, // Azure 1.2-preview+\n x_BilledCostInUsd: real, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: real, // Azure 1.0-preview(v1)+\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: real, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingItemCode: string, // Alibaba 1.0+\n x_BillingItemName: string, // Alibaba 1.0+\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_CommodityCode: string, // Alibaba 1.0+\n x_CommodityName: string, // Alibaba 1.0+\n x_ComponentName: string, // Tencent 1.0+\n x_ComponentType: string, // Tencent 1.0+\n x_ContractedCostInUsd: real, // Azure 1.0+\n x_Cost: real, // GCP Jan 2024 -- Removed Jun 2024 (ContractedCost)\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: string, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_CostType: string, // GCP Jan 2024\n x_Credits: string, // GCP Jan 2024\n x_CurrencyConversionRate: real, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: string, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: real, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: real, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024 / Tencent 1.0+\n x_InstanceID: string, // Alibaba 1.0+\n x_InvoiceId: string, // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: real, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_OnDemandCost: real, // Azure 1.0-preview(v1) only\n x_OnDemandCostInUsd: real, // Azure 1.0-preview(v1) only\n x_OnDemandUnitPrice: real, // Azure 1.0-preview(v1) only\n x_Operation: string, // AWS 1.0\n x_OwnerAccountID: string, // Tencent 1.0+\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: real, // Azure 1.0-preview(v1)+\n x_PricingCurrency: string, // Azure 1.0-preview(v1)-1.0r2\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServiceModel: string, // Azure 1.2-preview+\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: string, // Azure 1.0-preview(v1)-1.2-preview\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterName: string, // Azure 1.0-preview(v1)-1.0r2\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuPlanName: string, // Azure 1.2-preview+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string, // Hubs v1_0+\n x_SubproductName: string, // Tencent 1.0+ // cSpell:ignore Subproduct\n x_UsageType: string // AWS 1.0\n)\n\n// Costs_raw ingestion mapping\n.create-or-alter table Costs_raw ingestion parquet mapping \"Costs_raw_mapping\"\n```\n[\n { \"Column\": \"AvailabilityZone\", \"Properties\": { \"Field\": \"AvailabilityZone\" } },\n { \"Column\": \"BilledCost\", \"Properties\": { \"Field\": \"BilledCost\" } },\n { \"Column\": \"BillingAccountId\", \"Properties\": { \"Field\": \"BillingAccountId\" } },\n { \"Column\": \"BillingAccountName\", \"Properties\": { \"Field\": \"BillingAccountName\" } },\n { \"Column\": \"BillingAccountType\", \"Properties\": { \"Field\": \"BillingAccountType\" } },\n { \"Column\": \"BillingCurrency\", \"Properties\": { \"Field\": \"BillingCurrency\" } },\n { \"Column\": \"BillingPeriodEnd\", \"Properties\": { \"Field\": \"BillingPeriodEnd\" } },\n { \"Column\": \"BillingPeriodStart\", \"Properties\": { \"Field\": \"BillingPeriodStart\" } },\n { \"Column\": \"CapacityReservationId\", \"Properties\": { \"Field\": \"CapacityReservationId\" } },\n { \"Column\": \"CapacityReservationStatus\", \"Properties\": { \"Field\": \"CapacityReservationStatus\" } },\n { \"Column\": \"ChargeCategory\", \"Properties\": { \"Field\": \"ChargeCategory\" } },\n { \"Column\": \"ChargeClass\", \"Properties\": { \"Field\": \"ChargeClass\" } },\n { \"Column\": \"ChargeDescription\", \"Properties\": { \"Field\": \"ChargeDescription\" } },\n { \"Column\": \"ChargeFrequency\", \"Properties\": { \"Field\": \"ChargeFrequency\" } },\n { \"Column\": \"ChargePeriodEnd\", \"Properties\": { \"Field\": \"ChargePeriodEnd\" } },\n { \"Column\": \"ChargePeriodStart\", \"Properties\": { \"Field\": \"ChargePeriodStart\" } },\n { \"Column\": \"ChargeSubcategory\", \"Properties\": { \"Field\": \"ChargeSubcategory\" } },\n { \"Column\": \"CommitmentDiscountCategory\", \"Properties\": { \"Field\": \"CommitmentDiscountCategory\" } },\n { \"Column\": \"CommitmentDiscountId\", \"Properties\": { \"Field\": \"CommitmentDiscountId\" } },\n { \"Column\": \"CommitmentDiscountName\", \"Properties\": { \"Field\": \"CommitmentDiscountName\" } },\n { \"Column\": \"CommitmentDiscountQuantity\", \"Properties\": { \"Field\": \"CommitmentDiscountQuantity\" } },\n { \"Column\": \"CommitmentDiscountStatus\", \"Properties\": { \"Field\": \"CommitmentDiscountStatus\" } },\n { \"Column\": \"CommitmentDiscountType\", \"Properties\": { \"Field\": \"CommitmentDiscountType\" } },\n { \"Column\": \"CommitmentDiscountUnit\", \"Properties\": { \"Field\": \"CommitmentDiscountUnit\" } },\n { \"Column\": \"ConsumedQuantity\", \"Properties\": { \"Field\": \"ConsumedQuantity\" } },\n { \"Column\": \"ConsumedUnit\", \"Properties\": { \"Field\": \"ConsumedUnit\" } },\n { \"Column\": \"ContractedCost\", \"Properties\": { \"Field\": \"ContractedCost\" } },\n { \"Column\": \"ContractedUnitPrice\", \"Properties\": { \"Field\": \"ContractedUnitPrice\" } },\n { \"Column\": \"EffectiveCost\", \"Properties\": { \"Field\": \"EffectiveCost\" } },\n { \"Column\": \"InvoiceId\", \"Properties\": { \"Field\": \"InvoiceId\" } },\n { \"Column\": \"InvoiceIssuerName\", \"Properties\": { \"Field\": \"InvoiceIssuerName\" } },\n { \"Column\": \"ListCost\", \"Properties\": { \"Field\": \"ListCost\" } },\n { \"Column\": \"ListUnitPrice\", \"Properties\": { \"Field\": \"ListUnitPrice\" } },\n { \"Column\": \"PricingCategory\", \"Properties\": { \"Field\": \"PricingCategory\" } },\n { \"Column\": \"PricingCurrency\", \"Properties\": { \"Field\": \"PricingCurrency\" } },\n { \"Column\": \"PricingQuantity\", \"Properties\": { \"Field\": \"PricingQuantity\" } },\n { \"Column\": \"PricingUnit\", \"Properties\": { \"Field\": \"PricingUnit\" } },\n { \"Column\": \"ProviderName\", \"Properties\": { \"Field\": \"ProviderName\" } },\n { \"Column\": \"PublisherName\", \"Properties\": { \"Field\": \"PublisherName\" } },\n { \"Column\": \"Region\", \"Properties\": { \"Field\": \"Region\" } },\n { \"Column\": \"RegionId\", \"Properties\": { \"Field\": \"RegionId\" } },\n { \"Column\": \"RegionName\", \"Properties\": { \"Field\": \"RegionName\" } },\n { \"Column\": \"ResourceId\", \"Properties\": { \"Field\": \"ResourceId\" } },\n { \"Column\": \"ResourceName\", \"Properties\": { \"Field\": \"ResourceName\" } },\n { \"Column\": \"ResourceType\", \"Properties\": { \"Field\": \"ResourceType\" } },\n { \"Column\": \"ServiceCategory\", \"Properties\": { \"Field\": \"ServiceCategory\" } },\n { \"Column\": \"ServiceName\", \"Properties\": { \"Field\": \"ServiceName\" } },\n { \"Column\": \"ServiceSubcategory\", \"Properties\": { \"Field\": \"ServiceSubcategory\" } },\n { \"Column\": \"SkuId\", \"Properties\": { \"Field\": \"SkuId\" } },\n { \"Column\": \"SkuMeter\", \"Properties\": { \"Field\": \"SkuMeter\" } },\n { \"Column\": \"SkuPriceDetails\", \"Properties\": { \"Field\": \"SkuPriceDetails\" } },\n { \"Column\": \"SkuPriceId\", \"Properties\": { \"Field\": \"SkuPriceId\" } },\n { \"Column\": \"SubAccountId\", \"Properties\": { \"Field\": \"SubAccountId\" } },\n { \"Column\": \"SubAccountName\", \"Properties\": { \"Field\": \"SubAccountName\" } },\n { \"Column\": \"SubAccountType\", \"Properties\": { \"Field\": \"SubAccountType\" } },\n { \"Column\": \"Tags\", \"Properties\": { \"Field\": \"Tags\" } },\n { \"Column\": \"UsageAmount\", \"Properties\": { \"Field\": \"UsageAmount\" } },\n { \"Column\": \"UsageQuantity\", \"Properties\": { \"Field\": \"UsageQuantity\" } },\n { \"Column\": \"UsageUnit\", \"Properties\": { \"Field\": \"UsageUnit\" } },\n { \"Column\": \"x_AccountId\", \"Properties\": { \"Field\": \"x_AccountId\" } },\n { \"Column\": \"x_AccountName\", \"Properties\": { \"Field\": \"x_AccountName\" } },\n { \"Column\": \"x_AccountOwnerId\", \"Properties\": { \"Field\": \"x_AccountOwnerId\" } },\n { \"Column\": \"x_AmortizationClass\", \"Properties\": { \"Field\": \"x_AmortizationClass\" } },\n { \"Column\": \"x_BilledCostInUsd\", \"Properties\": { \"Field\": \"x_BilledCostInUsd\" } },\n { \"Column\": \"x_BilledUnitPrice\", \"Properties\": { \"Field\": \"x_BilledUnitPrice\" } },\n { \"Column\": \"x_BillingAccountId\", \"Properties\": { \"Field\": \"x_BillingAccountId\" } },\n { \"Column\": \"x_BillingAccountName\", \"Properties\": { \"Field\": \"x_BillingAccountName\" } },\n { \"Column\": \"x_BillingExchangeRate\", \"Properties\": { \"Field\": \"x_BillingExchangeRate\" } },\n { \"Column\": \"x_BillingExchangeRateDate\", \"Properties\": { \"Field\": \"x_BillingExchangeRateDate\" } },\n { \"Column\": \"x_BillingItemCode\", \"Properties\": { \"Field\": \"x_BillingItemCode\" } },\n { \"Column\": \"x_BillingItemName\", \"Properties\": { \"Field\": \"x_BillingItemName\" } },\n { \"Column\": \"x_BillingProfileId\", \"Properties\": { \"Field\": \"x_BillingProfileId\" } },\n { \"Column\": \"x_BillingProfileName\", \"Properties\": { \"Field\": \"x_BillingProfileName\" } },\n { \"Column\": \"x_ChargeId\", \"Properties\": { \"Field\": \"x_ChargeId\" } },\n { \"Column\": \"x_ContractedCostInUsd\", \"Properties\": { \"Field\": \"x_ContractedCostInUsd\" } },\n { \"Column\": \"x_CommodityCode\", \"Properties\": { \"Field\": \"x_CommodityCode\" } },\n { \"Column\": \"x_CommodityName\", \"Properties\": { \"Field\": \"x_CommodityName\" } },\n { \"Column\": \"x_ComponentName\", \"Properties\": { \"Field\": \"x_ComponentName\" } },\n { \"Column\": \"x_ComponentType\", \"Properties\": { \"Field\": \"x_ComponentType\" } },\n { \"Column\": \"x_Cost\", \"Properties\": { \"Field\": \"x_Cost\" } },\n { \"Column\": \"x_CostAllocationRuleName\", \"Properties\": { \"Field\": \"x_CostAllocationRuleName\" } },\n { \"Column\": \"x_CostCategories\", \"Properties\": { \"Field\": \"x_CostCategories\" } },\n { \"Column\": \"x_CostCenter\", \"Properties\": { \"Field\": \"x_CostCenter\" } },\n { \"Column\": \"x_Credits\", \"Properties\": { \"Field\": \"x_Credits\" } },\n { \"Column\": \"x_CostType\", \"Properties\": { \"Field\": \"x_CostType\" } },\n { \"Column\": \"x_CurrencyConversionRate\", \"Properties\": { \"Field\": \"x_CurrencyConversionRate\" } },\n { \"Column\": \"x_CustomerId\", \"Properties\": { \"Field\": \"x_CustomerId\" } },\n { \"Column\": \"x_CustomerName\", \"Properties\": { \"Field\": \"x_CustomerName\" } },\n { \"Column\": \"x_Discount\", \"Properties\": { \"Field\": \"x_Discount\" } },\n { \"Column\": \"x_EffectiveCostInUsd\", \"Properties\": { \"Field\": \"x_EffectiveCostInUsd\" } },\n { \"Column\": \"x_EffectiveUnitPrice\", \"Properties\": { \"Field\": \"x_EffectiveUnitPrice\" } },\n { \"Column\": \"x_ExportTime\", \"Properties\": { \"Field\": \"x_ExportTime\" } },\n { \"Column\": \"x_InstanceID\", \"Properties\": { \"Field\": \"x_InstanceID\" } },\n { \"Column\": \"x_InvoiceId\", \"Properties\": { \"Field\": \"x_InvoiceId\" } },\n { \"Column\": \"x_InvoiceIssuerId\", \"Properties\": { \"Field\": \"x_InvoiceIssuerId\" } },\n { \"Column\": \"x_InvoiceSectionId\", \"Properties\": { \"Field\": \"x_InvoiceSectionId\" } },\n { \"Column\": \"x_InvoiceSectionName\", \"Properties\": { \"Field\": \"x_InvoiceSectionName\" } },\n { \"Column\": \"x_ListCostInUsd\", \"Properties\": { \"Field\": \"x_ListCostInUsd\" } },\n { \"Column\": \"x_Location\", \"Properties\": { \"Field\": \"x_Location\" } },\n { \"Column\": \"x_OnDemandCost\", \"Properties\": { \"Field\": \"x_OnDemandCost\" } },\n { \"Column\": \"x_OnDemandCostInUsd\", \"Properties\": { \"Field\": \"x_OnDemandCostInUsd\" } },\n { \"Column\": \"x_OnDemandUnitPrice\", \"Properties\": { \"Field\": \"x_OnDemandUnitPrice\" } },\n { \"Column\": \"x_Operation\", \"Properties\": { \"Field\": \"x_Operation\" } },\n { \"Column\": \"x_OwnerAccountID\", \"Properties\": { \"Field\": \"x_OwnerAccountID\" } },\n { \"Column\": \"x_PartnerCreditApplied\", \"Properties\": { \"Field\": \"x_PartnerCreditApplied\" } },\n { \"Column\": \"x_PartnerCreditRate\", \"Properties\": { \"Field\": \"x_PartnerCreditRate\" } },\n { \"Column\": \"x_PricingBlockSize\", \"Properties\": { \"Field\": \"x_PricingBlockSize\" } },\n { \"Column\": \"x_PricingCurrency\", \"Properties\": { \"Field\": \"x_PricingCurrency\" } },\n { \"Column\": \"x_PricingSubcategory\", \"Properties\": { \"Field\": \"x_PricingSubcategory\" } },\n { \"Column\": \"x_PricingUnitDescription\", \"Properties\": { \"Field\": \"x_PricingUnitDescription\" } },\n { \"Column\": \"x_Project\", \"Properties\": { \"Field\": \"x_Project\" } },\n { \"Column\": \"x_PublisherCategory\", \"Properties\": { \"Field\": \"x_PublisherCategory\" } },\n { \"Column\": \"x_PublisherId\", \"Properties\": { \"Field\": \"x_PublisherId\" } },\n { \"Column\": \"x_ResellerId\", \"Properties\": { \"Field\": \"x_ResellerId\" } },\n { \"Column\": \"x_ResellerName\", \"Properties\": { \"Field\": \"x_ResellerName\" } },\n { \"Column\": \"x_ResourceGroupName\", \"Properties\": { \"Field\": \"x_ResourceGroupName\" } },\n { \"Column\": \"x_ResourceType\", \"Properties\": { \"Field\": \"x_ResourceType\" } },\n { \"Column\": \"x_ServiceCode\", \"Properties\": { \"Field\": \"x_ServiceCode\" } },\n { \"Column\": \"x_ServiceId\", \"Properties\": { \"Field\": \"x_ServiceId\" } },\n { \"Column\": \"x_ServiceModel\", \"Properties\": { \"Field\": \"x_ServiceModel\" } },\n { \"Column\": \"x_ServicePeriodEnd\", \"Properties\": { \"Field\": \"x_ServicePeriodEnd\" } },\n { \"Column\": \"x_ServicePeriodStart\", \"Properties\": { \"Field\": \"x_ServicePeriodStart\" } },\n { \"Column\": \"x_SkuDescription\", \"Properties\": { \"Field\": \"x_SkuDescription\" } },\n { \"Column\": \"x_SkuDetails\", \"Properties\": { \"Field\": \"x_SkuDetails\" } },\n { \"Column\": \"x_SkuIsCreditEligible\", \"Properties\": { \"Field\": \"x_SkuIsCreditEligible\" } },\n { \"Column\": \"x_SkuMeterCategory\", \"Properties\": { \"Field\": \"x_SkuMeterCategory\" } },\n { \"Column\": \"x_SkuMeterId\", \"Properties\": { \"Field\": \"x_SkuMeterId\" } },\n { \"Column\": \"x_SkuMeterName\", \"Properties\": { \"Field\": \"x_SkuMeterName\" } },\n { \"Column\": \"x_SkuMeterSubcategory\", \"Properties\": { \"Field\": \"x_SkuMeterSubcategory\" } },\n { \"Column\": \"x_SkuOfferId\", \"Properties\": { \"Field\": \"x_SkuOfferId\" } },\n { \"Column\": \"x_SkuOrderId\", \"Properties\": { \"Field\": \"x_SkuOrderId\" } },\n { \"Column\": \"x_SkuOrderName\", \"Properties\": { \"Field\": \"x_SkuOrderName\" } },\n { \"Column\": \"x_SkuPartNumber\", \"Properties\": { \"Field\": \"x_SkuPartNumber\" } },\n { \"Column\": \"x_SkuPlanName\", \"Properties\": { \"Field\": \"x_SkuPlanName\" } },\n { \"Column\": \"x_SkuRegion\", \"Properties\": { \"Field\": \"x_SkuRegion\" } },\n { \"Column\": \"x_SkuServiceFamily\", \"Properties\": { \"Field\": \"x_SkuServiceFamily\" } },\n { \"Column\": \"x_SkuTerm\", \"Properties\": { \"Field\": \"x_SkuTerm\" } },\n { \"Column\": \"x_SkuTier\", \"Properties\": { \"Field\": \"x_SkuTier\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } },\n { \"Column\": \"x_SubproductName\", \"Properties\": { \"Field\": \"x_SubproductName\" } },\n { \"Column\": \"x_UsageType\", \"Properties\": { \"Field\": \"x_UsageType\" } }\n]\n```\n\n// Costs_raw retention policy (clear historical data)\n.alter-merge table Costs_raw policy retention softdelete = 0d recoverability = disabled\n\n// Costs_raw retention policy (set the user-defined retention period)\n.alter-merge table Costs_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable Costs_raw streaming ingestion (required for Fabric)\n.alter table Costs_raw policy streamingingestion disable\n\n\n//===| Prices |=========================================================================================================\n// NOTE: Must be before cost details.\n//\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_raw table -- Create the table if it doesn't exist\n.create-merge table Prices_raw ( ignore: string )\n\n// Prices_raw table -- Remove all columns to allow changing column types\n.alter table Prices_raw ( ignore: string )\n\n// Prices_raw table -- Redefine all columns\n.alter table Prices_raw (\n BasePrice: real, // Azure EA + MCA\n BillingAccountId: string, // Azure MCA\n BillingAccountName: string, // Azure MCA\n BillingCurrency: string, // Azure MCA\n BillingProfileId: string, // Azure MCA\n BillingProfileName: string, // Azure MCA\n Currency: string, // Azure MCA\n CurrencyCode: string, // Azure EA\n EffectiveEndDate: datetime, // Azure MCA\n EffectiveStartDate: datetime, // Azure EA + MCA\n EnrollmentNumber: string, // Azure EA\n IncludedQuantity: real, // Azure EA\n MarketPrice: real, // Azure EA + MCA\n MeterCategory: string, // Azure EA + MCA\n MeterId: string, // Azure MCA\n MeterID: string, // Azure EA\n MeterName: string, // Azure EA + MCA\n MeterRegion: string, // Azure EA + MCA\n MeterSubCategory: string, // Azure EA + MCA\n MeterType: string, // Azure EA + MCA\n OfferID: string, // Azure EA\n PartNumber: string, // Azure EA\n PriceType: string, // Azure EA + MCA\n Product: string, // Azure EA + MCA\n ProductId: string, // Azure MCA\n ProductID: string, // Azure EA\n ServiceFamily: string, // Azure EA + MCA\n SkuId: string, // Azure MCA\n SkuID: string, // Azure EA\n Term: string, // Azure EA + MCA\n TierMinimumUnits: real, // Azure MCA\n UnitOfMeasure: string, // Azure EA + MCA\n UnitPrice: real, // Azure EA + MCA\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string // Hubs v1_0+\n)\n\n// Prices_raw ingestion mapping\n.create-or-alter table Prices_raw ingestion parquet mapping \"Prices_raw_mapping\"\n```\n[\n { \"Column\": \"BasePrice\", \"Properties\": { \"Field\": \"BasePrice\" } },\n { \"Column\": \"BillingAccountId\", \"Properties\": { \"Field\": \"BillingAccountId\" } },\n { \"Column\": \"BillingAccountName\", \"Properties\": { \"Field\": \"BillingAccountName\" } },\n { \"Column\": \"BillingCurrency\", \"Properties\": { \"Field\": \"BillingCurrency\" } },\n { \"Column\": \"BillingProfileId\", \"Properties\": { \"Field\": \"BillingProfileId\" } },\n { \"Column\": \"BillingProfileName\", \"Properties\": { \"Field\": \"BillingProfileName\" } },\n { \"Column\": \"Currency\", \"Properties\": { \"Field\": \"Currency\" } },\n { \"Column\": \"CurrencyCode\", \"Properties\": { \"Field\": \"CurrencyCode\" } },\n { \"Column\": \"EffectiveEndDate\", \"Properties\": { \"Field\": \"EffectiveEndDate\" } },\n { \"Column\": \"EffectiveStartDate\", \"Properties\": { \"Field\": \"EffectiveStartDate\" } },\n { \"Column\": \"EnrollmentNumber\", \"Properties\": { \"Field\": \"EnrollmentNumber\" } },\n { \"Column\": \"IncludedQuantity\", \"Properties\": { \"Field\": \"IncludedQuantity\" } },\n { \"Column\": \"MarketPrice\", \"Properties\": { \"Field\": \"MarketPrice\" } },\n { \"Column\": \"MeterCategory\", \"Properties\": { \"Field\": \"MeterCategory\" } },\n { \"Column\": \"MeterId\", \"Properties\": { \"Field\": \"MeterId\" } },\n { \"Column\": \"MeterID\", \"Properties\": { \"Field\": \"MeterID\" } },\n { \"Column\": \"MeterName\", \"Properties\": { \"Field\": \"MeterName\" } },\n { \"Column\": \"MeterRegion\", \"Properties\": { \"Field\": \"MeterRegion\" } },\n { \"Column\": \"MeterSubCategory\", \"Properties\": { \"Field\": \"MeterSubCategory\" } },\n { \"Column\": \"MeterType\", \"Properties\": { \"Field\": \"MeterType\" } },\n { \"Column\": \"OfferID\", \"Properties\": { \"Field\": \"OfferID\" } },\n { \"Column\": \"PartNumber\", \"Properties\": { \"Field\": \"PartNumber\" } },\n { \"Column\": \"PriceType\", \"Properties\": { \"Field\": \"PriceType\" } },\n { \"Column\": \"Product\", \"Properties\": { \"Field\": \"Product\" } },\n { \"Column\": \"ProductId\", \"Properties\": { \"Field\": \"ProductId\" } },\n { \"Column\": \"ProductID\", \"Properties\": { \"Field\": \"ProductID\" } },\n { \"Column\": \"ServiceFamily\", \"Properties\": { \"Field\": \"ServiceFamily\" } },\n { \"Column\": \"SkuId\", \"Properties\": { \"Field\": \"SkuId\" } },\n { \"Column\": \"SkuID\", \"Properties\": { \"Field\": \"SkuID\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"TierMinimumUnits\", \"Properties\": { \"Field\": \"TierMinimumUnits\" } },\n { \"Column\": \"UnitOfMeasure\", \"Properties\": { \"Field\": \"UnitOfMeasure\" } },\n { \"Column\": \"UnitPrice\", \"Properties\": { \"Field\": \"UnitPrice\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } }\n]\n```\n\n// Prices_raw retention policy (clear historical data)\n.alter-merge table Prices_raw policy retention softdelete = 0d recoverability = disabled\n\n// Prices_raw retention policy (set the user-defined retention period)\n.alter-merge table Prices_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable Prices_raw streaming ingestion (required for Fabric)\n.alter table Prices_raw policy streamingingestion disable\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_raw table -- Create the table if it doesn't exist\n.create-merge table Recommendations_raw ( ignore: string )\n\n// Recommendations_raw table -- Remove all columns to allow changing column types\n.alter table Recommendations_raw ( ignore: string )\n\n// Recommendations_raw table -- Redefine all columns\n.alter table Recommendations_raw (\n CostWithNoReservedInstances: real, // MS CM EA resv reco 2024-05-01\n CostWithNoReservedInstancesJson: string, // MS CM MCA resv reco 2024-05-01 -- Renamed to remove spaces and flag as JSON\n FirstUsageDate: datetime, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n InstanceFlexibilityGroup: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n InstanceFlexibilityRatio: real, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n Location: string, // MS CM EA+MCA resv reco 2024-05-01\n LookBackPeriod: string, // MS CM EA+MCA resv reco 2024-05-01\n MeterId: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n NetSavings: real, // MS CM EA resv reco 2024-05-01\n NetSavingsJson: string, // MS CM MCA resv reco 2024-05-01 -- Renamed to remove spaces and flag as JSON\n NormalizedSize: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n ProviderName: string, // Hubs v1_2\n RecommendedQuantity: real, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n RecommendedQuantityNormalized: real, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n ResourceId: string, // Hubs v1_2\n ResourceName: string, // Hubs v1_2\n ResourceType: string, // Hubs v1_2, MS CM EA+MCA resv reco 2024-05-01\n Scope: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n SKU: string, // MS CM EA resv reco 2024-05-01\n SkuName: string, // MS CM MCA resv reco 2024-05-01 -- Renamed to remove spaces\n SkuProperties: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n SubAccountId: string, // Hubs v1_2\n SubAccountName: string, // Hubs v1_2\n SubscriptionId: string, // MS CM EA+MCA resv reco 2024-05-01\n Term: string, // MS CM EA+MCA resv reco 2024-05-01\n TotalCostWithReservedInstances: real, // MS CM EA resv reco 2024-05-01\n TotalCostWithReservedInstancesJson: string, // MS CM MCA resv reco 2024-05-01 -- Renamed to remove spaces and flag as JSON\n x_EffectiveCostAfter: real, // Hubs v1_2\n x_EffectiveCostBefore: real, // Hubs v1_2\n x_EffectiveCostSavings: real, // Hubs v1_2\n x_RecommendationCategory: string, // Hubs v1_2\n x_RecommendationDate: datetime, // Hubs v1_2\n x_RecommendationDescription: string, // Hubs v1_2\n x_RecommendationDetails: dynamic, // Hubs v1_2\n x_RecommendationId: string, // Hubs v1_2\n x_ResourceGroupName: string, // Hubs v1_2\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string // Hubs v1_0+\n)\n\n// Recommendations_raw ingestion mapping\n.create-or-alter table Recommendations_raw ingestion parquet mapping \"Recommendations_raw_mapping\"\n```\n[\n { \"Column\": \"CostWithNoReservedInstances\", \"Properties\": { \"Field\": \"CostWithNoReservedInstances\" } },\n { \"Column\": \"CostWithNoReservedInstancesJson\", \"Properties\": { \"Field\": \"CostWithNoReservedInstancesJson\" } },\n { \"Column\": \"FirstUsageDate\", \"Properties\": { \"Field\": \"FirstUsageDate\" } },\n { \"Column\": \"InstanceFlexibilityGroup\", \"Properties\": { \"Field\": \"InstanceFlexibilityGroup\" } },\n { \"Column\": \"InstanceFlexibilityRatio\", \"Properties\": { \"Field\": \"InstanceFlexibilityRatio\" } },\n { \"Column\": \"Location\", \"Properties\": { \"Field\": \"Location\" } },\n { \"Column\": \"LookBackPeriod\", \"Properties\": { \"Field\": \"LookBackPeriod\" } },\n { \"Column\": \"MeterId\", \"Properties\": { \"Field\": \"MeterId\" } },\n { \"Column\": \"NetSavings\", \"Properties\": { \"Field\": \"NetSavings\" } },\n { \"Column\": \"NetSavingsJson\", \"Properties\": { \"Field\": \"NetSavingsJson\" } },\n { \"Column\": \"NormalizedSize\", \"Properties\": { \"Field\": \"NormalizedSize\" } },\n { \"Column\": \"ProviderName\", \"Properties\": { \"Field\": \"ProviderName\" } },\n { \"Column\": \"RecommendedQuantity\", \"Properties\": { \"Field\": \"RecommendedQuantity\" } },\n { \"Column\": \"RecommendedQuantityNormalized\", \"Properties\": { \"Field\": \"RecommendedQuantityNormalized\" } },\n { \"Column\": \"ResourceId\", \"Properties\": { \"Field\": \"ResourceId\" } },\n { \"Column\": \"ResourceName\", \"Properties\": { \"Field\": \"ResourceName\" } },\n { \"Column\": \"ResourceType\", \"Properties\": { \"Field\": \"ResourceType\" } },\n { \"Column\": \"Scope\", \"Properties\": { \"Field\": \"Scope\" } },\n { \"Column\": \"SKU\", \"Properties\": { \"Field\": \"SKU\" } },\n { \"Column\": \"SkuName\", \"Properties\": { \"Field\": \"SkuName\" } },\n { \"Column\": \"SkuProperties\", \"Properties\": { \"Field\": \"SkuProperties\" } },\n { \"Column\": \"SubAccountId\", \"Properties\": { \"Field\": \"SubAccountId\" } },\n { \"Column\": \"SubAccountName\", \"Properties\": { \"Field\": \"SubAccountName\" } },\n { \"Column\": \"SubscriptionId\", \"Properties\": { \"Field\": \"SubscriptionId\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"TotalCostWithReservedInstances\", \"Properties\": { \"Field\": \"TotalCostWithReservedInstances\" } },\n { \"Column\": \"TotalCostWithReservedInstancesJson\", \"Properties\": { \"Field\": \"TotalCostWithReservedInstancesJson\" } },\n { \"Column\": \"x_EffectiveCostAfter\", \"Properties\": { \"Field\": \"x_EffectiveCostAfter\" } },\n { \"Column\": \"x_EffectiveCostBefore\", \"Properties\": { \"Field\": \"x_EffectiveCostBefore\" } },\n { \"Column\": \"x_EffectiveCostSavings\", \"Properties\": { \"Field\": \"x_EffectiveCostSavings\" } },\n { \"Column\": \"x_RecommendationCategory\", \"Properties\": { \"Field\": \"x_RecommendationCategory\" } },\n { \"Column\": \"x_RecommendationDate\", \"Properties\": { \"Field\": \"x_RecommendationDate\" } },\n { \"Column\": \"x_RecommendationDescription\", \"Properties\": { \"Field\": \"x_RecommendationDescription\" } },\n { \"Column\": \"x_RecommendationDetails\", \"Properties\": { \"Field\": \"x_RecommendationDetails\" } },\n { \"Column\": \"x_RecommendationId\", \"Properties\": { \"Field\": \"x_RecommendationId\" } },\n { \"Column\": \"x_ResourceGroupName\", \"Properties\": { \"Field\": \"x_ResourceGroupName\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } }\n]\n```\n\n// Recommendations_raw retention policy (clear historical data)\n.alter-merge table Recommendations_raw policy retention softdelete = 0d recoverability = disabled\n\n// Recommendations_raw retention policy (set the user-defined retention period)\n.alter-merge table Recommendations_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable Recommendations_raw streaming ingestion (required for Fabric)\n.alter table Recommendations_raw policy streamingingestion disable\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_raw table -- Create the table if it doesn't exist\n.create-merge table Transactions_raw ( ignore: string )\n\n// Transactions_raw table -- Remove all columns to allow changing column types\n.alter table Transactions_raw ( ignore: string )\n\n// Transactions_raw table -- Redefine all columns\n.alter table Transactions_raw (\n AccountName: string, // MS CM EA resv trans 2023-05-01\n AccountOwnerEmail: string, // MS CM EA resv trans 2023-05-01\n Amount: real, // MS CM EA+MCA resv trans 2023-05-01\n ArmSkuName: string, // MS CM EA+MCA resv trans 2023-05-01\n BillingFrequency: string, // MS CM EA+MCA resv trans 2023-05-01\n BillingMonth: string, // MS CM EA resv trans 2023-05-01\n BillingProfileId: string, // MS CM MCA resv trans 2023-05-01\n BillingProfileName: string, // MS CM MCA resv trans 2023-05-01\n CostCenter: string, // MS CM EA resv trans 2023-05-01\n Currency: string, // MS CM EA+MCA resv trans 2023-05-01\n CurrentEnrollmentId: string, // MS CM EA resv trans 2023-05-01\n DepartmentName: string, // MS CM EA resv trans 2023-05-01\n Description: string, // MS CM EA+MCA resv trans 2023-05-01\n EventDate: datetime, // MS CM EA+MCA resv trans 2023-05-01\n EventType: string, // MS CM EA+MCA resv trans 2023-05-01\n Invoice: string, // MS CM EA+MCA resv trans 2023-05-01\n InvoiceId: string, // MS CM EA+MCA resv trans 2023-05-01\n InvoiceSectionId: string, // MS CM MCA resv trans 2023-05-01\n InvoiceSectionName: string, // MS CM MCA resv trans 2023-05-01\n MonetaryCommitment: real, // MS CM EA resv trans 2023-05-01\n Overage: real, // MS CM EA resv trans 2023-05-01\n PurchasingEnrollment: string, // MS CM EA resv trans 2023-05-01\n PurchasingSubscriptionGuid: string, // MS CM EA+MCA resv trans 2023-05-01\n PurchasingSubscriptionName: string, // MS CM EA+MCA resv trans 2023-05-01\n Quantity: real, // MS CM EA+MCA resv trans 2023-05-01\n Region: string, // MS CM EA+MCA resv trans 2023-05-01\n ReservationOrderId: string, // MS CM EA+MCA resv trans 2023-05-01\n ReservationOrderName: string, // MS CM EA+MCA resv trans 2023-05-01\n Term: string, // MS CM EA+MCA resv trans 2023-05-01\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string // Hubs v1_0+\n)\n\n// Transactions_raw ingestion mapping\n.create-or-alter table Transactions_raw ingestion parquet mapping \"Transactions_raw_mapping\"\n```\n[\n { \"Column\": \"AccountName\", \"Properties\": { \"Field\": \"AccountName\" } },\n { \"Column\": \"AccountOwnerEmail\", \"Properties\": { \"Field\": \"AccountOwnerEmail\" } },\n { \"Column\": \"Amount\", \"Properties\": { \"Field\": \"Amount\" } },\n { \"Column\": \"ArmSkuName\", \"Properties\": { \"Field\": \"ArmSkuName\" } },\n { \"Column\": \"BillingFrequency\", \"Properties\": { \"Field\": \"BillingFrequency\" } },\n { \"Column\": \"BillingMonth\", \"Properties\": { \"Field\": \"BillingMonth\" } },\n { \"Column\": \"BillingProfileId\", \"Properties\": { \"Field\": \"BillingProfileId\" } },\n { \"Column\": \"BillingProfileName\", \"Properties\": { \"Field\": \"BillingProfileName\" } },\n { \"Column\": \"CostCenter\", \"Properties\": { \"Field\": \"CostCenter\" } },\n { \"Column\": \"Currency\", \"Properties\": { \"Field\": \"Currency\" } },\n { \"Column\": \"CurrentEnrollmentId\", \"Properties\": { \"Field\": \"CurrentEnrollmentId\" } },\n { \"Column\": \"DepartmentName\", \"Properties\": { \"Field\": \"DepartmentName\" } },\n { \"Column\": \"Description\", \"Properties\": { \"Field\": \"Description\" } },\n { \"Column\": \"EventDate\", \"Properties\": { \"Field\": \"EventDate\" } },\n { \"Column\": \"EventType\", \"Properties\": { \"Field\": \"EventType\" } },\n { \"Column\": \"Invoice\", \"Properties\": { \"Field\": \"Invoice\" } },\n { \"Column\": \"InvoiceId\", \"Properties\": { \"Field\": \"InvoiceId\" } },\n { \"Column\": \"InvoiceSectionId\", \"Properties\": { \"Field\": \"InvoiceSectionId\" } },\n { \"Column\": \"InvoiceSectionName\", \"Properties\": { \"Field\": \"InvoiceSectionName\" } },\n { \"Column\": \"MonetaryCommitment\", \"Properties\": { \"Field\": \"MonetaryCommitment\" } },\n { \"Column\": \"Overage\", \"Properties\": { \"Field\": \"Overage\" } },\n { \"Column\": \"PurchasingEnrollment\", \"Properties\": { \"Field\": \"PurchasingEnrollment\" } },\n { \"Column\": \"PurchasingSubscriptionGuid\", \"Properties\": { \"Field\": \"PurchasingSubscriptionGuid\" } },\n { \"Column\": \"PurchasingSubscriptionName\", \"Properties\": { \"Field\": \"PurchasingSubscriptionName\" } },\n { \"Column\": \"Quantity\", \"Properties\": { \"Field\": \"Quantity\" } },\n { \"Column\": \"Region\", \"Properties\": { \"Field\": \"Region\" } },\n { \"Column\": \"ReservationOrderId\", \"Properties\": { \"Field\": \"ReservationOrderId\" } },\n { \"Column\": \"ReservationOrderName\", \"Properties\": { \"Field\": \"ReservationOrderName\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } }\n]\n```\n\n// Transactions_raw retention policy (clear historical data)\n.alter-merge table Transactions_raw policy retention softdelete = 0d recoverability = disabled\n\n// Transactions_raw retention policy (set the user-defined retention period)\n.alter-merge table Transactions_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable Transactions_raw streaming ingestion (required for Fabric)\n.alter table Transactions_raw policy streamingingestion disable\n\n", - "$fxv#9": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// Used for data ingestion, normalization, and cleansing.\n// See known issues @ https://github.com/microsoft/finops-toolkit/issues/1111\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Prices |=========================================================================================================\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All prices transformed to FOCUS 1.0. Use Prices_transform_v1_2() instead.', folder='Prices')\nPrices_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n let prices = materialize(\n Prices_raw\n //\n // Change real to decimal\n | extend\n BasePrice = todecimal(BasePrice),\n IncludedQuantity = todecimal(IncludedQuantity),\n MarketPrice = todecimal(MarketPrice),\n TierMinimumUnits = todecimal(TierMinimumUnits),\n UnitPrice = todecimal(UnitPrice)\n //\n | extend x_SkuId = coalesce(SkuId, SkuID)\n | extend x_SkuMeterId = coalesce(MeterId, MeterID)\n | extend x_SkuProductId = coalesce(ProductId, ProductID)\n | extend x_SkuTerm = isoMonths(Term)\n | project-rename\n x_BaseUnitPrice = BasePrice,\n x_EffectivePeriodEnd = EffectiveEndDate,\n x_EffectivePeriodStart = EffectiveStartDate,\n x_PricingUnitDescription = UnitOfMeasure,\n x_SkuIncludedQuantity = IncludedQuantity,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuMeterType = MeterType,\n x_SkuOfferId = OfferID,\n x_SkuPartNumber = PartNumber,\n x_SkuPriceType = PriceType,\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTier = TierMinimumUnits\n | extend ContractedUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', UnitPrice, todecimal('')) // UnitPrice for savings plan is not the on-demand unit price\n | extend ListUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', MarketPrice, todecimal('')) // MarketPrice for savings plan is not the list price\n | extend ChargeCategory = case(\n x_SkuPriceType == 'Consumption', 'Usage',\n x_SkuPriceType == 'ReservedInstance', 'Purchase',\n x_SkuPriceType == 'SavingsPlan', 'Usage', // Savings plan prices are for committed usage, not the purchase\n ''\n )\n | extend SkuPriceIdv2 = strcat(case(x_SkuPriceType == 'Consumption', 'OD', x_SkuPriceType == 'ReservedInstance', 'RI', x_SkuPriceType == 'SavingsPlan', 'SP', 'XX'), substring(ChargeCategory, 0, 1), x_SkuTerm, '_', x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType, '_', x_SkuTier, x_SkuOfferId)\n | extend x_BillingAccountId = iff(BillingAccountId startswith '/', split(BillingAccountId, '/')[-1], coalesce(BillingAccountId, EnrollmentNumber))\n | extend x_BillingProfileId = iff(BillingProfileId startswith '/', split(BillingProfileId, '/')[-1], coalesce(BillingProfileId, EnrollmentNumber))\n | extend tmp_SavingsPlanKey = strcat(x_SkuMeterId, x_SkuProductId, x_SkuId, x_SkuTier, x_SkuOfferId)\n //\n // Get latest ingested row based on the unique ID\n | extend x_IngestionTime = ingestion_time()\n );\n //\n // Meters for reservations and savings plans to identify commitment eligibility\n let riMeters = prices | where x_SkuPriceType == 'ReservedInstance' | distinct x_SkuMeterId;\n let spMeters = prices | where x_SkuPriceType == 'SavingsPlan' | distinct x_SkuMeterId;\n //\n // Copy list/base/contracted prices from on-demand SKUs\n prices\n | where x_SkuPriceType == 'SavingsPlan'\n // If we use join, specify the shuffle key\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter hint.strategy=shuffle (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | lookup kind=leftouter (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | extend ListUnitPrice = coalesce(ListUnitPrice, ListUnitPrice1)\n | extend ContractedUnitPrice = coalesce(ContractedUnitPrice, ContractedUnitPrice1)\n | extend x_BaseUnitPrice = coalesce(x_BaseUnitPrice, x_BaseUnitPrice1)\n | project-away ListUnitPrice1, ContractedUnitPrice1, x_BaseUnitPrice1, tmp_SavingsPlanKey\n | union ((prices | where x_SkuPriceType != 'SavingsPlan'))\n //\n // Calculate commitment discount elgibility\n // TODO: Would a join be faster?\n | extend x_CommitmentDiscountSpendEligibility = iff(x_SkuMeterId in (riMeters) and x_SkuPriceType != 'ReservedInstance', 'Eligible', 'Not Eligible')\n | extend x_CommitmentDiscountUsageEligibility = iff(x_SkuMeterId in (spMeters), 'Eligible', 'Not Eligible')\n //\n // Add PricingUnit and x_PricingBlockSize\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter (PricingUnits) on x_PricingUnitDescription | project-away x_PricingUnitDescription1\n | lookup kind=leftouter (PricingUnits | extend x_PricingBlockSize = todecimal(x_PricingBlockSize)) on x_PricingUnitDescription\n //\n | extend x_EffectiveUnitPrice = iff(x_SkuPriceType == 'SavingsPlan', UnitPrice, todecimal('')) // Savings plan prices are for the effective price, not the contracted price\n | extend x_EffectiveUnitPriceDiscount = ContractedUnitPrice - x_EffectiveUnitPrice\n | extend x_ContractedUnitPriceDiscount = ListUnitPrice - ContractedUnitPrice\n | extend x_TotalUnitPriceDiscount = ListUnitPrice - x_EffectiveUnitPrice\n | project\n BillingAccountId = tolower(case(\n BillingProfileId startswith '/', BillingProfileId,\n BillingAccountId startswith '/', BillingAccountId,\n strcat('/providers/microsoft.billing/billingaccounts/', x_BillingAccountId, iff(x_BillingProfileId == x_BillingAccountId, '', strcat('/billingprofiles/', x_BillingProfileId)))\n )),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName, x_BillingProfileId),\n BillingCurrency = coalesce(BillingCurrency, CurrencyCode, Currency), // Currency last as a fallback only\n ChargeCategory,\n CommitmentDiscountCategory = case(\n x_SkuPriceType == 'ReservedInstance', 'Usage',\n x_SkuPriceType == 'SavingsPlan', 'Spend',\n ''\n ),\n CommitmentDiscountType = case(\n x_SkuPriceType == 'ReservedInstance', 'Reservation',\n x_SkuPriceType == 'SavingsPlan', 'Savings plan',\n ''\n ),\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory = case(\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed',\n ''\n ),\n PricingUnit,\n SkuId = coalesce(ProductId, ProductID),\n SkuPriceId = strcat(x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType),\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement = case(\n strlen(x_BillingAccountId) > 32, 'MCA',\n strlen(x_BillingAccountId) < 32, 'EA',\n 'Unknown'\n ),\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent = 1.0 * x_ContractedUnitPriceDiscount / ListUnitPrice * 100,\n x_EffectivePeriodEnd = startofmonth(x_EffectivePeriodEnd + 1h),\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent = 1.0 * x_EffectiveUnitPriceDiscount / ContractedUnitPrice * 100,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingCurrency = coalesce(Currency, CurrencyCode), // CurrencyCode last as a fallback only\n x_PricingSubcategory = case(\n x_SkuPriceType == 'Consumption' and (x_SkuIncludedQuantity > 0 or x_SkuTier > 0), 'Tiered',\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed Spend',\n ''\n ),\n x_PricingUnitDescription,\n x_SkuDescription = Product,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterName,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName = coalesce(x_SourceName, 'Cost Management'),\n x_SourceProvider = coalesce(x_SourceProvider, 'Microsoft'),\n x_SourceType = coalesce(x_SourceType, 'PriceSheet'),\n x_SourceVersion = coalesce(x_SourceVersion, '2023-05-01'),\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent = 1.0 * x_TotalUnitPriceDiscount / ListUnitPrice * 100\n}\n\n// Prices_final_v1_0 table\n.create-merge table Prices_final_v1_0 (\n BillingAccountId: string,\n BillingAccountName: string,\n BillingCurrency: string,\n ChargeCategory: string,\n CommitmentDiscountCategory: string,\n CommitmentDiscountType: string,\n ContractedUnitPrice: decimal,\n ListUnitPrice: decimal,\n PricingCategory: string,\n PricingUnit: string,\n SkuId: string,\n SkuPriceId: string,\n SkuPriceIdv2: string, // Hubs add-on\n x_BaseUnitPrice: decimal, // Azure\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure MCA\n x_BillingProfileId: string, // Azure MCA\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_ContractedUnitPriceDiscount: decimal, // Hubs add-on\n x_ContractedUnitPriceDiscountPercent: decimal, // Hubs add-on\n x_EffectivePeriodEnd: datetime, // Azure\n x_EffectivePeriodStart: datetime, // Azure\n x_EffectiveUnitPrice: decimal, // Azure\n x_EffectiveUnitPriceDiscount: decimal, // Hubs add-on\n x_EffectiveUnitPriceDiscountPercent: decimal, // Hubs add-on\n x_IngestionTime: datetime, // Hubs add-on\n x_PricingBlockSize: decimal, // Hubs add-on\n x_PricingCurrency: string, // Azure\n x_PricingSubcategory: string, // Hubs add-on\n x_PricingUnitDescription: string, // Azure\n x_SkuDescription: string, // Azure\n x_SkuId: string, // Azure\n x_SkuIncludedQuantity: decimal, // Azure EA\n x_SkuMeterCategory: string, // Azure\n x_SkuMeterId: string, // Azure\n x_SkuMeterName: string, // Azure\n x_SkuMeterSubcategory: string, // Azure\n x_SkuMeterType: string, // Azure\n x_SkuPriceType: string, // Azure\n x_SkuProductId: string, // Azure\n x_SkuRegion: string, // Azure\n x_SkuServiceFamily: string, // Azure\n x_SkuOfferId: string, // Azure EA\n x_SkuPartNumber: string, // Azure EA\n x_SkuTerm: int, // Azure\n x_SkuTier: decimal, // Azure MCA\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_TotalUnitPriceDiscount: decimal, // Hubs add-on\n x_TotalUnitPriceDiscountPercent: decimal // Hubs add-on\n)\n\n// Update policy for Prices_raw -> Prices_final_v1_0\n.alter table Prices_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Prices_raw\",\n \"Query\": \"Prices_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Cost and usage |=================================================================================================\n// Supported versions:\n// - MS: 1.0, 1.0-preview(v1) -- See https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0 -- See https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024 -- See https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 -- See https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All costs transformed to FOCUS 1.0. Use Costs_transform_v1_2() instead.', folder='Costs')\nCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n Costs_raw\n //\n // Change real to decimal\n | extend\n BilledCost = todecimal(BilledCost),\n CommitmentDiscountQuantity = todecimal(CommitmentDiscountQuantity),\n ConsumedQuantity = todecimal(ConsumedQuantity),\n ContractedCost = todecimal(ContractedCost),\n ContractedUnitPrice = todecimal(ContractedUnitPrice),\n EffectiveCost = todecimal(EffectiveCost),\n ListCost = todecimal(ListCost),\n ListUnitPrice = todecimal(ListUnitPrice),\n PricingQuantity = todecimal(PricingQuantity),\n UsageAmount = todecimal(UsageAmount),\n UsageQuantity = todecimal(UsageQuantity),\n x_BilledCostInUsd = todecimal(x_BilledCostInUsd),\n x_BilledUnitPrice = todecimal(x_BilledUnitPrice),\n x_BillingExchangeRate = todecimal(x_BillingExchangeRate),\n x_ContractedCostInUsd = todecimal(x_ContractedCostInUsd),\n x_Cost = todecimal(x_Cost),\n x_CurrencyConversionRate = todecimal(x_CurrencyConversionRate),\n x_EffectiveCostInUsd = todecimal(x_EffectiveCostInUsd),\n x_EffectiveUnitPrice = todecimal(x_EffectiveUnitPrice),\n x_ListCostInUsd = todecimal(x_ListCostInUsd),\n x_OnDemandCost = todecimal(x_OnDemandCost),\n x_OnDemandCostInUsd = todecimal(x_OnDemandCostInUsd),\n x_OnDemandUnitPrice = todecimal(x_OnDemandUnitPrice),\n x_PricingBlockSize = todecimal(x_PricingBlockSize)\n //\n // Dedupe rows\n | extend x_IngestionTime = ingestion_time()\n | extend x_ChargeId = ''\n // TODO: Consider adding a unique charge ID per row\n // hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // // 1. Resource hierarchy (including resource name), highest to lowest\n // BillingAccountId,\n // x_InvoiceSectionId,\n // x_AccountOwnerId,\n // SubAccountId,\n // x_ResourceGroupName,\n // ResourceName,\n // // 2. Resource details\n // ResourceId,\n // RegionId,\n // Tags,\n // CommitmentDiscountId,\n // x_CostCenter,\n // // 4. Meter details\n // SkuPriceId,\n // x_SkuMeterId,\n // x_SkuPartNumber,\n // x_SkuOfferId,\n // x_SkuDetails,\n // // 5. Date\n // ChargePeriodStart\n // ))\n //\n // Identify data quality issues\n | extend x_SourceChanges = trim_end(',', strcat(\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based', 'InvalidChargeFrequency,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and EffectiveCost > 0, 'InvalidEffectiveCost,', ''),\n iff((isempty(ContractedCost) or ContractedCost == 0) and EffectiveCost != 0, 'MissingContractedCost,', ''),\n iff((isempty(ContractedUnitPrice) or ContractedUnitPrice == 0) and x_EffectiveUnitPrice != 0, 'MissingContractedUnitPrice,', ''),\n iff(ListCost < ContractedCost, 'ListCostLessThanContractedCost,', ''),\n iff(ContractedCost < EffectiveCost, 'ContractedCostLessThanEffectiveCost,', ''),\n iff((isempty(ListCost) or ListCost == 0) and (ContractedCost != 0 or EffectiveCost != 0), 'MissingListCost,', ''),\n iff((isempty(ListUnitPrice) or ListUnitPrice == 0) and (ContractedUnitPrice != 0 or x_EffectiveUnitPrice != 0), 'MissingListUnitPrice,', ''),\n iff((isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001)\n or (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001),\n 'XEffectiveUnitPriceRoundingError,', ''),\n iff(ConsumedQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingConsumedQuantity,', ''),\n iff(PricingQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingPricingQuantity,', ''),\n iff(isempty(ProviderName), 'MissingProviderName,', ''),\n iff(isempty(PublisherName), 'MissingPublisherName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceId), 'MissingResourceId,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceName), 'MissingResourceName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceType), 'MissingResourceType,', ''),\n iff(BilledCost > 0 and x_BilledUnitPrice == 0, 'MissingXBilledUnitPrice,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(x_ResourceType), 'MissingXResourceType,', ''),\n iff(PricingCategory == 'Standard' and isnotempty(CommitmentDiscountId) and ChargeCategory == 'Usage', 'PricingCategoryShouldBeCommitted,', ''),\n iff(x_SkuTerm == '1Year' or x_SkuTerm == '3Years' or x_SkuTerm == '5Years', 'SkuTermShouldBeAnInteger,', '')\n ))\n //\n // Fix columns needed in other changes\n | extend ProviderName = case(\n isnotempty(ProviderName), ProviderName,\n isnotempty(coalesce(x_CostCategories, x_Discount, x_Operation, x_ServiceCode, x_UsageType)), 'AWS',\n isnotempty(coalesce(tostring(UsageAmount), tostring(x_Cost), x_Credits, x_CostType, tostring(x_CurrencyConversionRate), tostring(x_ExportTime), x_Project, x_ServiceId)), 'GCP',\n isnotempty(coalesce(x_BillingProfileId, x_InvoiceSectionId)), 'Microsoft',\n ''\n )\n //\n // Identify source\n | extend x_SourceName = coalesce(x_SourceName, iff(isnotempty(x_BillingProfileId), 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(isnotempty(x_BillingProfileId), 'FocusCost', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, case(\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)) and isempty(SkuPriceDetails) and isnotempty(x_SkuDetails), '1.2-preview',\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)), '1.2',\n isnotempty(coalesce(ChargeClass, CommitmentDiscountStatus, tostring(ConsumedQuantity), ConsumedUnit, tostring(ContractedCost), tostring(ContractedUnitPrice), RegionId, RegionName)), '1.0',\n isnotempty(coalesce(ChargeSubcategory, Region, tostring(UsageQuantity), UsageUnit)), iff(ProviderName == 'Microsoft', '1.0-preview(v1)', '1.0-preview'),\n ''\n ))\n // Append version check error code\n | extend x_SourceChanges = iff(x_SourceVersion == '1.0', x_SourceChanges,\n strcat(x_SourceChanges, iff(isempty(x_SourceChanges), '', ','), iff(x_SourceVersion == '', 'UnknownFocusVersion', 'LegacyFocusVersion'))\n )\n //\n // Fix quantities\n | extend PricingQuantity = case(\n PricingQuantity != 0 or (EffectiveCost == 0 and BilledCost == 0), PricingQuantity,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(EffectiveCost) and EffectiveCost != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0, EffectiveCost / x_EffectiveUnitPrice,\n PricingQuantity\n )\n | extend ConsumedQuantity = case(\n isnotempty(ConsumedQuantity) and ConsumedQuantity != 0, ConsumedQuantity,\n ChargeCategory == 'Usage', PricingQuantity / coalesce(x_PricingBlockSize, decimal(1)),\n ConsumedQuantity\n )\n //\n // Populate missing prices -- mapping to on-demand prices requires meter ID and offer ID\n | extend tmp_MissingPrices = ProviderName == 'Microsoft'\n and (ListUnitPrice == 0 or ContractedUnitPrice == 0)\n and x_EffectiveUnitPrice != 0\n and not(CommitmentDiscountCategory == 'Spend' and CommitmentDiscountStatus == 'Unused')\n and isnotempty(strcat(x_SkuMeterId, x_SkuOfferId))\n | as allCosts\n | where tmp_MissingPrices\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(ChargePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | as costsWithMissingPrices\n | join kind=leftouter (\n Prices_final_v1_0\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(x_EffectivePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | where x_SkuPriceType == 'Consumption' and tmp_ReservationPriceLookupKey in ((costsWithMissingPrices | summarize by tmp_ReservationPriceLookupKey))\n | summarize ListUnitPrice = min(ListUnitPrice), ContractedUnitPrice = min(ContractedUnitPrice) by tmp_ReservationPriceLookupKey, x_PricingBlockSize, PricingUnit\n ) on tmp_ReservationPriceLookupKey\n //\n // Select the best price to use for each row\n // TODO: Save values before changing -- | extend x_old_ContractedUnitPrice = ContractedUnitPrice, x_old_EffectiveUnitPrice = x_EffectiveUnitPrice, x_old_ListUnitPrice = ListUnitPrice, x_old_ListCost = ListCost, x_old_ContractedCost = ContractedCost\n | extend x_EffectiveUnitPrice = case(\n // If price is a rounding error away from the billed price, use the billed price\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001, x_BilledUnitPrice,\n // If price is a rounding error away from the contracted price, use the contracted price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001, ContractedUnitPrice,\n x_EffectiveUnitPrice\n )\n | extend ContractedUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ContractedUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ContractedUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // If billed price is available, assume the billed price is the same as contracted price to support aggregations\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, x_EffectiveUnitPrice,\n // Otherwise, assume the effective price is the same as contracted price to support aggregations\n x_EffectiveUnitPrice\n )\n | extend ListUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ListUnitPrice) and ListUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ListUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ListUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ListUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // Otherwise, assume the contracted price is the same as list price to support aggregations\n ContractedUnitPrice\n )\n // Calculate missing costs based on new prices -- If cost is already correct, keep that; if not and price is available, recalculate the cost; otherwise, keep the existing cost\n | extend ContractedCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ContractedCost) and ContractedCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedCost,\n // ContractedCost is 0 in all other scenarios...\n // If 0 and there's a billed cost and prices are the same, use BilledCost\n isnotempty(BilledCost) and BilledCost != 0 and ContractedUnitPrice == x_BilledUnitPrice, BilledCost,\n // If 0 and there's a billed cost and prices are the same, use EffectiveCost\n isnotempty(EffectiveCost) and EffectiveCost != 0 and ContractedUnitPrice == x_EffectiveUnitPrice, EffectiveCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0, ContractedUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume EffectiveCost\n isempty(ContractedUnitPrice) or ContractedUnitPrice == 0, EffectiveCost,\n // Fall back to the original value for any unhandled scenarios\n ContractedCost\n )\n | extend ListCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ListCost) and ListCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ListCost,\n // ListCost is 0 in all other scenarios...\n // If 0 and there's a contracted cost and prices are the same, use ContractedCost\n isnotempty(ContractedCost) and ContractedCost != 0 and ListUnitPrice == ContractedUnitPrice, ContractedCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ListUnitPrice) and ListUnitPrice != 0, ListUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume ContractedCost\n isempty(ListUnitPrice) or ListUnitPrice == 0, ContractedCost,\n // Fall back to the original value for any unhandled scenarios\n ListCost\n )\n // Merge the rest of the unmodified cost records and remove excess columns\n | union (allCosts | where not(tmp_MissingPrices))\n | project-away x_PricingBlockSize1, PricingUnit1, ListUnitPrice1, ContractedUnitPrice1, tmp_MissingPrices, tmp_ReservationPriceLookupKey, tmp_ReservationPriceLookupKey1\n //\n // BUG: Fix ContractedCost that has bad values\n | extend ContractedCost = iff(ProviderName == 'Microsoft' and isnotempty(PricingQuantity) and isnotempty(x_PricingBlockSize) and ContractedCost != ContractedUnitPrice * PricingQuantity, ContractedUnitPrice * PricingQuantity, ContractedCost)\n //\n // Handle FOCUS 1.0-preview UsageQuantity/Unit\n | extend ConsumedQuantity = iff(ChargeCategory == 'Usage', coalesce(ConsumedQuantity, UsageQuantity, UsageAmount), todecimal(''))\n | extend ConsumedUnit = iff(ChargeCategory == 'Usage' and isnotempty(ConsumedQuantity), coalesce(ConsumedUnit, UsageUnit, 'Units'), '')\n //\n // Convert IDs to lowercase for consistency\n | extend CommitmentDiscountId = tolower(CommitmentDiscountId)\n //\n // BUG: Remove EffectiveCost for commitment discount purchases\n | extend EffectiveCost = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), decimal(0), EffectiveCost)\n | extend x_EffectiveCostInUsd = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), decimal(0), x_EffectiveCostInUsd)\n //\n // Clean up resource columns\n | extend ResourceId = case(\n isnotempty(ResourceId), ResourceId,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), CommitmentDiscountId,\n ResourceId)\n | extend ResourceName = tolower(case(\n isnotempty(ResourceName), ResourceName,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountName), CommitmentDiscountName,\n isnotempty(ResourceId), parse_resourceid(ResourceId).ResourceName,\n ResourceName))\n | extend x_ResourceType = case(\n isnotempty(x_ResourceType), x_ResourceType,\n isnotempty(ResourceId), parse_resourceid(ResourceId).x_ResourceType,\n x_ResourceType)\n | extend ResourceType = case(\n // Use existing resource type display name unless it's an internal resource type ID\n isnotempty(ResourceType) and tolower(ResourceType) != tolower(x_ResourceType) and ResourceType !contains '/', ResourceType,\n // Use CommitmentDiscountType for commitment discount purchases\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountType), CommitmentDiscountType,\n // Look up display name from internal type\n isnotempty(x_ResourceType), coalesce(resource_type(x_ResourceType).SingularDisplayName, ResourceType, x_ResourceType),\n ResourceType)\n //\n // Sort columns and apply final transforms\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId = tolower(BillingAccountId),\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEnd),\n BillingPeriodStart = startofmonth(BillingPeriodStart),\n ChargeCategory = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Credit', 'Credit',\n ChargeSubcategory == 'Refund', 'Purchase', // We are assuming purchase refunds since we don't have data to indicate usage refunds\n ChargeCategory\n ),\n ChargeClass = case(ChargeSubcategory == 'Refund', 'Correction', ChargeClass),\n ChargeDescription,\n // BUG: ChargeFrequency shows \"Usage-Based\" for monthly recurring savings plan purchases\n ChargeFrequency = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based' and ProviderName == 'Microsoft' and x_SourceVersion startswith '1.0', 'Recurring', ChargeFrequency),\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId = tolower(CommitmentDiscountId),\n CommitmentDiscountName,\n CommitmentDiscountStatus = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Used Commitment', 'Used',\n ChargeSubcategory == 'Unused Commitment', 'Unused',\n CommitmentDiscountStatus\n ),\n CommitmentDiscountType,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost = coalesce(ContractedCost, x_OnDemandCost, x_Cost),\n ContractedUnitPrice = coalesce(ContractedUnitPrice, x_OnDemandUnitPrice),\n EffectiveCost,\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory = case(\n // Handle FOCUS 1.0-preview PricingCategory values\n PricingCategory == 'On-Demand', 'Standard',\n PricingCategory == 'Commitment-Based', 'Committed',\n PricingCategory\n ),\n PricingQuantity,\n PricingUnit,\n ProviderName,\n // Handle missing PublisherName values\n PublisherName = case(PublisherName == 'Microsoft Corporation', 'Microsoft', isnotempty(PublisherName), PublisherName, x_PublisherCategory == 'Cloud Provider', ProviderName, ''),\n // Handle FOCUS 1.0-preview Region column\n RegionId = coalesce(RegionId, iff(ProviderName == 'Microsoft', replace_string(tolower(Region), ' ', ''), Region)),\n RegionName = coalesce(RegionName, Region),\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SkuId,\n SkuPriceId,\n SubAccountId,\n SubAccountName,\n SubAccountType, // Azure 1.0-preview(v1)+\n Tags = parse_json(Tags),\n x_AccountId, // Azure 1.0-preview(v1)+\n x_AccountName, // Azure 1.0-preview(v1)+\n x_AccountOwnerId, // Azure 1.0-preview(v1)+\n x_BilledCostInUsd, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement = case(\n ProviderName == 'Microsoft' and x_BillingAccountId == x_BillingProfileId, 'EA',\n ProviderName == 'Microsoft' and x_BillingAccountId != x_BillingProfileId, 'MCA',\n ProviderName\n ), // Hubs add-on\n x_BillingAccountId, // Azure 1.0-preview(v1)+\n x_BillingAccountName, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate, // Azure 1.0-preview(v1)+\n x_BillingProfileId, // Azure 1.0-preview(v1)+\n x_BillingProfileName, // Azure 1.0-preview(v1)+\n x_ChargeId, // Azure 1.0-preview(v1) only\n x_ContractedCostInUsd = coalesce(x_ContractedCostInUsd, x_OnDemandCostInUsd), // Azure 1.0+\n x_CostAllocationRuleName, // Azure 1.0-preview(v1)+\n x_CostCategories = parse_json(x_CostCategories), // AWS 1.0 (JSON)\n x_CostCenter, // Azure 1.0-preview(v1)+\n x_Credits = parse_json(x_Credits), // GCP Jan 2024\n x_CostType, // GCP Jan 2024\n x_CurrencyConversionRate, // GCP Jun 2024\n x_CustomerId, // Azure 1.0-preview(v1)+\n x_CustomerName, // Azure 1.0-preview(v1)+\n x_Discount = parse_json(x_Discount), // AWS 1.0 (JSON)\n x_EffectiveCostInUsd, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice, // Azure 1.0-preview(v1)+\n x_ExportTime, // GCP Jan 2024\n x_IngestionTime, // Hubs add-on\n x_InvoiceId = coalesce(InvoiceId, x_InvoiceId), // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId = case( // Azure 1.0-preview(v1)+\n x_InvoiceSectionId == '-2', '',\n x_InvoiceSectionId\n ),\n x_InvoiceSectionName = case( // Azure 1.0-preview(v1)+\n x_InvoiceSectionName == 'Unassigned', '',\n x_InvoiceSectionName\n ),\n x_ListCostInUsd, // Azure 1.0-preview(v1)+\n x_Location, // GCP Jan 2024\n x_Operation, // AWS 1.0\n x_PartnerCreditApplied, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate, // Azure 1.0-preview(v1)+\n x_PricingBlockSize, // Azure 1.0-preview(v1)+\n x_PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency), // Azure 1.0-preview(v1)+\n x_PricingSubcategory, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription, // Azure 1.0-preview(v1)+\n x_Project, // GCP Jan 2024\n x_PublisherCategory, // Azure 1.0-preview(v1)+\n x_PublisherId, // Azure 1.0-preview(v1)+\n x_ResellerId, // Azure 1.0-preview(v1)+\n x_ResellerName, // Azure 1.0-preview(v1)+\n x_ResourceGroupName = tolower(x_ResourceGroupName), // Azure 1.0-preview(v1)+\n x_ResourceType, // Azure 1.0-preview(v1)+\n x_ServiceCode, // AWS 1.0\n x_ServiceId, // GCP Jan 2024\n x_ServicePeriodEnd, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart, // Azure 1.0-preview(v1)+\n x_SkuDescription, // Azure 1.0-preview(v1)+\n x_SkuDetails = parse_json(x_SkuDetails), // Azure 1.0-preview(v1)+\n x_SkuIsCreditEligible, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory, // Azure 1.0-preview(v1)+\n x_SkuMeterId, // Azure 1.0-preview(v1)+\n x_SkuMeterName = coalesce(SkuMeter, x_SkuMeterName), // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory, // Azure 1.0-preview(v1)+\n x_SkuOfferId, // Azure 1.0-preview(v1)+\n x_SkuOrderId, // Azure 1.0-preview(v1)+\n x_SkuOrderName, // Azure 1.0-preview(v1)+\n x_SkuPartNumber, // Azure 1.0-preview(v1)+\n x_SkuRegion, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily, // Azure 1.0-preview(v1)+\n x_SkuTerm, // Azure 1.0-preview(v1)+\n x_SkuTier, // Azure 1.0-preview(v1)+\n x_SourceChanges, // Hubs add-on\n x_SourceName, // Hubs add-on\n x_SourceProvider, // Hubs add-on\n x_SourceType, // Hubs add-on\n x_SourceVersion, // Hubs add-on\n x_UsageType // AWS 1.0\n}\n\n// Costs_final_v1_0 table\n.create-merge table Costs_final_v1_0 (\n AvailabilityZone: string,\n BilledCost: decimal,\n BillingAccountId: string,\n BillingAccountName: string,\n BillingAccountType: string, // Azure 1.0-preview(v1)+\n BillingCurrency: string,\n BillingPeriodEnd: datetime,\n BillingPeriodStart: datetime,\n ChargeCategory: string,\n ChargeClass: string,\n ChargeDescription: string,\n ChargeFrequency: string,\n ChargePeriodEnd: datetime,\n ChargePeriodStart: datetime,\n CommitmentDiscountCategory: string, // FOCUS 1.0-preview only\n CommitmentDiscountId: string,\n CommitmentDiscountName: string,\n CommitmentDiscountStatus: string,\n CommitmentDiscountType: string,\n ConsumedQuantity: decimal,\n ConsumedUnit: string,\n ContractedCost: decimal,\n ContractedUnitPrice: decimal,\n EffectiveCost: decimal,\n InvoiceIssuerName: string,\n ListCost: decimal,\n ListUnitPrice: decimal,\n PricingCategory: string,\n PricingQuantity: decimal,\n PricingUnit: string,\n ProviderName: string,\n PublisherName: string,\n RegionId: string,\n RegionName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n ServiceCategory: string,\n ServiceName: string,\n SkuId: string,\n SkuPriceId: string,\n SubAccountId: string,\n SubAccountName: string,\n SubAccountType: string,\n Tags: dynamic,\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_BilledCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: decimal, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: decimal, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_ContractedCostInUsd: decimal, // Azure 1.0+\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: dynamic, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_Credits: dynamic, // GCP Jan 2024\n x_CostType: string, // GCP Jan 2024\n x_CurrencyConversionRate: decimal, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: dynamic, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: decimal, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024\n x_IngestionTime: datetime, // Hubs add-on\n x_InvoiceId: string, // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_Operation: string, // AWS 1.0\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: decimal, // Azure 1.0-preview(v1)+\n x_PricingCurrency: string, // Azure 1.0-preview(v1)+\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: dynamic, // Azure 1.0-preview(v1)+\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterName: string, // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceChanges: string, // Hubs add-on\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_UsageType: string // AWS 1.0\n)\n\n// Update policy for Costs_raw -> Costs_final_v1_0 table\n.alter table Costs_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Costs_raw\",\n \"Query\": \"Costs_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Actual costs |===================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: ActualCost exports transformed to FOCUS 1.0. Use ActualCosts_transform_v1_2() instead.', folder='Costs')\nActualCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n // TODO: Transform actual costs to FOCUS 1.0 format\n ActualCosts_raw\n | where ChargeType in ('Purchase', 'Refund') and isnotempty(ReservationId)\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: ServiceSubcategory, PublisherName, x_PublisherCategory, x_Environment, x_ServiceModel\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodStart = Date,\n ChargePeriodEnd = Date + 1d,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = '',\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory = '',\n SkuId = '',\n SkuMeter = '',\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = SubscriptionName,\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentName = '',\n x_ComponentType = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel = '',\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for ActualCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": false,\n \"Source\": \"ActualCosts_raw\",\n \"Query\": \"ActualCosts_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Amortized costs |================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: ActualCost exports transformed to FOCUS 1.0. Use AmortizedCosts_transform_v1_2() instead.', folder='Costs')\nAmortizedCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n // TODO: Transform actual costs to FOCUS 1.0 format\n AmortizedCosts_raw\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: ServiceSubcategory, PublisherName, x_PublisherCategory, x_Environment, x_ServiceModel\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodStart = Date,\n ChargePeriodEnd = Date + 1d,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = '',\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory = '',\n SkuId = '',\n SkuMeter = '',\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = SubscriptionName,\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentName = '',\n x_ComponentType = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel = '',\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for AmortizedCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": false,\n \"Source\": \"AmortizedCosts_raw\",\n \"Query\": \"AmortizedCosts_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All commitment discount usage transformed to FOCUS 1.0. This includes reservationdeatils_raw. Use CommitmentDiscountUsage_transform_v1_2() instead.', folder='Commitment discounts')\nCommitmentDiscountUsage_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n CommitmentDiscountUsage_raw\n //\n // Change real to decimal\n | extend\n InstanceFlexibilityRatio = todecimal(InstanceFlexibilityRatio),\n ReservedHours = todecimal(ReservedHours),\n TotalReservedQuantity = todecimal(TotalReservedQuantity),\n UsedHours = todecimal(UsedHours)\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Handle resource columns\n | extend ResourceId = tolower(InstanceId)\n | extend tmp_ResourceDetails = parse_resourceid(ResourceId)\n | extend ResourceName = tostring(tmp_ResourceDetails.ResourceName)\n | extend SubAccountId = tostring(tmp_ResourceDetails.SubAccountId)\n | extend x_ResourceGroupName = tostring(tmp_ResourceDetails.x_ResourceGroupName)\n | extend x_ResourceType = tostring(tmp_ResourceDetails.x_ResourceType)\n | lookup kind=leftouter (ResourceTypes | distinct x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n | lookup kind=leftouter (Services | distinct x_ResourceType, ServiceName, ServiceCategory, x_ServiceModel) on x_ResourceType\n //\n // Sort columns and apply final transforms\n | project\n ChargePeriodEnd = UsageDate + 1d,\n ChargePeriodStart = UsageDate,\n CommitmentDiscountCategory = 'Usage',\n CommitmentDiscountId = tolower(strcat('/providers/microsoft.capacity/reservationorders/', ReservationOrderId, '/reservations/', ReservationId)),\n CommitmentDiscountType = 'Reservation',\n ConsumedQuantity = UsedHours,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SubAccountId,\n x_CommitmentDiscountCommittedCount = TotalReservedQuantity,\n x_CommitmentDiscountCommittedAmount = ReservedHours,\n // TODO: Is this needed? -- x_CommitmentDiscountKind = Kind,\n x_CommitmentDiscountNormalizedGroup = iff(InstanceFlexibilityGroup == 'NA', '', InstanceFlexibilityGroup),\n x_CommitmentDiscountNormalizedRatio = InstanceFlexibilityRatio,\n x_CommitmentDiscountQuantity = UsedHours * InstanceFlexibilityRatio,\n x_IngestionTime = ingestion_time(),\n x_ResourceGroupName,\n x_ResourceType,\n // x_RowId = hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // CommitmentDiscountId,\n // ResourceId,\n // ChargePeriodStart\n // )),\n x_ServiceModel,\n x_SkuOrderId = ReservationOrderId,\n x_SkuSize = iff(SkuName == 'NA', '', SkuName),\n x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName)),\n x_SourceProvider = coalesce(x_SourceProvider, ProviderName),\n x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationDetails', '')),\n x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2024-03-01', ''))\n}\n\n// CommitmentDiscountUsage_final_v1_0 table\n.create-merge table CommitmentDiscountUsage_final_v1_0 (\n ChargePeriodEnd: datetime, // Hubs add-on\n ChargePeriodStart: datetime, // MS 2023-03-01\n CommitmentDiscountCategory: string, // Hubs add-on\n CommitmentDiscountId: string, // MS 2023-03-01\n CommitmentDiscountType: string, // Hubs add-on\n ConsumedQuantity: decimal, // MS 2023-03-01\n ProviderName: string, // Hubs add-on\n ResourceId: string, // MS 2023-03-01\n ResourceName: string, // Hubs add-on\n ResourceType: string, // Hubs add-on\n ServiceCategory: string, // Hubs add-on\n ServiceName: string, // Hubs add-on\n SubAccountId: string, // Hubs add-on\n x_CommitmentDiscountCommittedCount: decimal, // MS 2023-03-01\n x_CommitmentDiscountCommittedAmount: decimal, // MS 2023-03-01\n x_CommitmentDiscountNormalizedGroup: string, // MS 2023-03-01\n x_CommitmentDiscountNormalizedRatio: decimal, // MS 2023-03-01\n x_CommitmentDiscountQuantity: decimal, // MS 2023-03-01\n x_IngestionTime: datetime, // Hubs add-on\n x_ResourceGroupName: string, // Hubs add-on\n x_ResourceType: string, // Hubs add-on\n x_ServiceModel: string, // Hubs add-on\n x_SkuOrderId: string, // MS 2023-03-01\n x_SkuSize: string, // MS 2023-03-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string // Hubs add-on\n)\n\n// Update policy for CommitmentDiscountUsage_raw -> CommitmentDiscountUsage_final_v1_0 table\n.alter table CommitmentDiscountUsage_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"CommitmentDiscountUsage_raw\",\n \"Query\": \"CommitmentDiscountUsage_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All recommendations transformed to FOCUS 1.0. Use Recommendations_transform_v1_2() instead.', folder='Recommendations')\nRecommendations_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Recommendations_raw\n //\n // Change real to decimal\n | extend\n CostWithNoReservedInstances = todecimal(CostWithNoReservedInstances),\n InstanceFlexibilityRatio = todecimal(InstanceFlexibilityRatio),\n NetSavings = todecimal(NetSavings),\n RecommendedQuantity = todecimal(RecommendedQuantity),\n RecommendedQuantityNormalized = todecimal(RecommendedQuantityNormalized),\n TotalCostWithReservedInstances = todecimal(TotalCostWithReservedInstances)\n //\n | extend x_IngestionTime = ingestion_time()\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationRecommendations', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Convert JSON cost columns to decimal\n | extend CostWithNoReservedInstances = case(isnotempty(CostWithNoReservedInstances), CostWithNoReservedInstances, isnotempty(CostWithNoReservedInstancesJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, CostWithNoReservedInstancesJson)), CostWithNoReservedInstances)\n | extend NetSavings = case(isnotempty(NetSavings), NetSavings, isnotempty(NetSavingsJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, NetSavingsJson)), NetSavings)\n | extend TotalCostWithReservedInstances = case(isnotempty(TotalCostWithReservedInstances), TotalCostWithReservedInstances, isnotempty(TotalCostWithReservedInstancesJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, TotalCostWithReservedInstancesJson)), TotalCostWithReservedInstances)\n //\n // Build recommendation details\n | lookup kind=leftouter (Regions | summarize RegionName = make_set(RegionName)[0] by Location = RegionId) on Location\n | extend x_RecommendationDetails = case(\n x_SourceType == 'ReservationRecommendations', bag_pack(\n 'CommitmentDiscountNormalizedGroup', InstanceFlexibilityGroup,\n 'CommitmentDiscountNormalizedRatio', InstanceFlexibilityRatio,\n 'CommitmentDiscountNormalizedSize', NormalizedSize,\n 'CommitmentDiscountResourceType', ResourceType,\n 'CommitmentDiscountScope', Scope,\n 'LookbackPeriodDuration', case(\n LookBackPeriod matches regex @'^Last([0-9]+)Days$', replace_regex(LookBackPeriod, @'^Last([0-9]+)Days$', @'P\\1D'),\n LookBackPeriod matches regex @'^[0-9]+$', strcat('P', LookBackPeriod, 'D'),\n ''\n ),\n 'LookbackPeriodStart', FirstUsageDate,\n 'RecommendedQuantity', RecommendedQuantity,\n 'RecommendedQuantityNormalized', RecommendedQuantityNormalized,\n 'RegionId', Location,\n 'RegionName', RegionName,\n 'SkuMeterId', MeterId,\n 'SkuPriceDetails', SkuProperties,\n 'SkuSize', coalesce(SKU, SkuName),\n 'SkuTerm', isoMonths(Term)\n ),\n dynamic({})\n )\n //\n // Sort columns and apply final transforms\n | extend x_RecommendationDate = FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d)\n | extend x_RecommendationDate = iff(x_RecommendationDate > now(), startofday(now()), x_RecommendationDate)\n | project\n ProviderName,\n SubAccountId = iff(isnotempty(SubscriptionId), strcat('/subscriptions/', SubscriptionId), ''),\n x_IngestionTime,\n x_EffectiveCostAfter = TotalCostWithReservedInstances,\n x_EffectiveCostBefore = CostWithNoReservedInstances,\n x_EffectiveCostSavings = NetSavings,\n x_RecommendationDate = FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d),\n x_RecommendationDetails,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n// Recommendations_final_v1_0 table\n.create-merge table Recommendations_final_v1_0 (\n ProviderName: string,\n SubAccountId: string,\n x_IngestionTime: datetime,\n x_EffectiveCostAfter: decimal,\n x_EffectiveCostBefore: decimal,\n x_EffectiveCostSavings: decimal,\n x_RecommendationDate: datetime,\n x_RecommendationDetails: dynamic,\n x_SourceName: string,\n x_SourceProvider: string,\n x_SourceType: string,\n x_SourceVersion: string\n)\n\n// Update policy for Recommendations_raw -> Recommendations_final_v1_0 table\n.alter table Recommendations_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Recommendations_raw\",\n \"Query\": \"Recommendations_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All transactions transformed to FOCUS 1.0. Use Transactions_transform_v1_2() instead.', folder='Transactions')\nTransactions_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Transactions_raw\n //\n // Change real to decimal\n | extend\n Amount = todecimal(Amount),\n MonetaryCommitment = todecimal(MonetaryCommitment),\n Overage = todecimal(Overage),\n Quantity = todecimal(Quantity)\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationTransactions', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Handle BillingPeriodStart/End\n | extend BillingMonth = tostring(BillingMonth)\n | extend BillingPeriodStart = iff(isempty(BillingMonth), datetime(null), todatetime(strcat(substring(BillingMonth, 0, 4), \"-\", substring(BillingMonth, 4, 2), \"-\", substring(BillingMonth, 6, 2))))\n | extend BillingPeriodEnd = iff(isempty(BillingMonth), datetime(null), startofmonth(endofmonth(BillingPeriodStart) + 1d))\n //\n // Sort columns and apply final transforms\n | project\n BilledCost = Amount,\n BillingAccountId = case(\n BillingProfileId startswith '/', BillingProfileId,\n isnotempty(CurrentEnrollmentId), strcat('/providers/Microsoft.Billing/billingAccounts/', CurrentEnrollmentId),\n isnotempty(BillingProfileId), strcat('/providers/Microsoft.Billing/billingProfiles/', BillingProfileId),\n ''\n ),\n BillingAccountName = coalesce(BillingProfileName, CurrentEnrollmentId),\n BillingCurrency = Currency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory = case(\n EventType in ('Cancel', 'Purchase', 'Refund'), 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = case(\n EventType == 'Cancel', 'Cancel', // FOCUS does not handle this scenario\n EventType == 'Refund', 'Correction',\n ''\n ),\n ChargeDescription = Description,\n ChargeFrequency = case(\n BillingFrequency == 'OneTime', 'One-Time',\n BillingFrequency == 'Recurring', 'Recurring',\n BillingFrequency\n ),\n ChargePeriodStart = EventDate,\n PricingQuantity = Quantity,\n PricingUnit = 'Reservations',\n ProviderName,\n RegionId = Region,\n RegionName = Region,\n SubAccountId = iff(isempty(PurchasingSubscriptionGuid), '', strcat('/subscriptions/', PurchasingSubscriptionGuid)),\n SubAccountName = iff(isempty(PurchasingSubscriptionGuid), '', PurchasingSubscriptionName),\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerEmail,\n x_CostCenter = CostCenter,\n x_InvoiceId = InvoiceId,\n x_InvoiceNumber = Invoice,\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = coalesce(InvoiceSectionName, DepartmentName),\n x_IngestionTime = ingestion_time(),\n x_MonetaryCommitment = MonetaryCommitment,\n x_Overage = Overage,\n x_PurchasingBillingAccountId = PurchasingEnrollment,\n x_SkuOrderId = ReservationOrderId,\n x_SkuOrderName = ReservationOrderName,\n x_SkuSize = ArmSkuName,\n x_SkuTerm = isoMonths(Term),\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId = PurchasingSubscriptionGuid,\n x_TransactionType = EventType\n}\n\n// Transactions_final_v1_0 table\n.create-merge table Transactions_final_v1_0 (\n BilledCost: decimal, // MS CM EA+MCA 2023-05-01\n BillingAccountId: string, // MS CM EA+MCA 2023-05-01\n BillingAccountName: string, // MS CM EA+MCA 2023-05-01\n BillingCurrency: string, // MS CM EA+MCA 2023-05-01\n BillingPeriodEnd: datetime, // MS CM EA+MCA 2023-05-01\n BillingPeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n ChargeCategory: string, // Hubs add-on\n ChargeClass: string, // Hubs add-on\n ChargeDescription: string, // MS CM EA+MCA 2023-05-01\n ChargeFrequency: string, // MS CM EA+MCA 2023-05-01\n ChargePeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n PricingQuantity: decimal, // MS CM EA+MCA 2023-05-01\n PricingUnit: string, // Hubs add-on\n ProviderName: string, // Hubs add-on\n RegionId: string, // MS CM EA+MCA 2023-05-01\n RegionName: string, // MS CM EA+MCA 2023-05-01\n SubAccountId: string, // MS CM EA+MCA 2023-05-01\n SubAccountName: string, // MS CM EA+MCA 2023-05-01\n x_AccountName: string, // MS CM EA 2023-05-01\n x_AccountOwnerId: string, // MS CM EA 2023-05-01\n x_CostCenter: string, // MS CM EA 2023-05-01\n x_InvoiceId: string, // MS CM MCA 2023-05-01\n x_InvoiceNumber: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionId: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionName: string, // MS CM MCA 2023-05-01\n x_IngestionTime: datetime, // Hubs add-on\n x_MonetaryCommitment: decimal, // MS CM EA 2023-05-01\n x_Overage: decimal, // MS CM EA 2023-05-01\n x_PurchasingBillingAccountId: string, // MS CM EA 2023-05-01\n x_SkuOrderId: string, // MS CM EA+MCA 2023-05-01\n x_SkuOrderName: string, // MS CM EA+MCA 2023-05-01\n x_SkuSize: string, // MS CM EA+MCA 2023-05-01\n x_SkuTerm: int, // MS CM EA+MCA 2023-05-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubscriptionId: string, // MS CM EA+MCA 2023-05-01\n x_TransactionType: string // MS CM EA+MCA 2023-05-01\n)\n\n// Update policy for Transactions_raw -> Transactions_final_v1_0 table\n.alter table Transactions_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Transactions_raw\",\n \"Query\": \"Transactions_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n", + "$fxv#9": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// Used for data ingestion, normalization, and cleansing.\n// See known issues @ https://github.com/microsoft/finops-toolkit/issues/1111\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Prices |=========================================================================================================\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All prices transformed to FOCUS 1.0. Use Prices_transform_v1_2() instead.', folder='Prices')\nPrices_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n let prices = materialize(\n Prices_raw\n //\n // Change real to decimal\n | extend\n BasePrice = todecimal(BasePrice),\n IncludedQuantity = todecimal(IncludedQuantity),\n MarketPrice = todecimal(MarketPrice),\n TierMinimumUnits = todecimal(TierMinimumUnits),\n UnitPrice = todecimal(UnitPrice)\n //\n | extend x_SkuId = coalesce(SkuId, SkuID)\n | extend x_SkuMeterId = coalesce(MeterId, MeterID)\n | extend x_SkuProductId = coalesce(ProductId, ProductID)\n | extend x_SkuTerm = isoMonths(Term)\n | project-rename\n x_BaseUnitPrice = BasePrice,\n x_EffectivePeriodEnd = EffectiveEndDate,\n x_EffectivePeriodStart = EffectiveStartDate,\n x_PricingUnitDescription = UnitOfMeasure,\n x_SkuIncludedQuantity = IncludedQuantity,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuMeterType = MeterType,\n x_SkuOfferId = OfferID,\n x_SkuPartNumber = PartNumber,\n x_SkuPriceType = PriceType,\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTier = TierMinimumUnits\n | extend ContractedUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', UnitPrice, todecimal('')) // UnitPrice for savings plan is not the on-demand unit price\n | extend ListUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', MarketPrice, todecimal('')) // MarketPrice for savings plan is not the list price\n | extend ChargeCategory = case(\n x_SkuPriceType == 'Consumption', 'Usage',\n x_SkuPriceType == 'ReservedInstance', 'Purchase',\n x_SkuPriceType == 'SavingsPlan', 'Usage', // Savings plan prices are for committed usage, not the purchase\n ''\n )\n | extend SkuPriceIdv2 = strcat(case(x_SkuPriceType == 'Consumption', 'OD', x_SkuPriceType == 'ReservedInstance', 'RI', x_SkuPriceType == 'SavingsPlan', 'SP', 'XX'), substring(ChargeCategory, 0, 1), x_SkuTerm, '_', x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType, '_', x_SkuTier, x_SkuOfferId)\n | extend x_BillingAccountId = iff(BillingAccountId startswith '/', split(BillingAccountId, '/')[-1], coalesce(BillingAccountId, EnrollmentNumber))\n | extend x_BillingProfileId = iff(BillingProfileId startswith '/', split(BillingProfileId, '/')[-1], coalesce(BillingProfileId, EnrollmentNumber))\n | extend tmp_SavingsPlanKey = strcat(x_SkuMeterId, x_SkuProductId, x_SkuId, x_SkuTier, x_SkuOfferId)\n //\n // Get latest ingested row based on the unique ID\n | extend x_IngestionTime = ingestion_time()\n );\n //\n // Meters for reservations and savings plans to identify commitment eligibility\n let riMeters = prices | where x_SkuPriceType == 'ReservedInstance' | distinct x_SkuMeterId;\n let spMeters = prices | where x_SkuPriceType == 'SavingsPlan' | distinct x_SkuMeterId;\n //\n // Copy list/base/contracted prices from on-demand SKUs\n prices\n | where x_SkuPriceType == 'SavingsPlan'\n // If we use join, specify the shuffle key\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter hint.strategy=shuffle (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | lookup kind=leftouter (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | extend ListUnitPrice = coalesce(ListUnitPrice, ListUnitPrice1)\n | extend ContractedUnitPrice = coalesce(ContractedUnitPrice, ContractedUnitPrice1)\n | extend x_BaseUnitPrice = coalesce(x_BaseUnitPrice, x_BaseUnitPrice1)\n | project-away ListUnitPrice1, ContractedUnitPrice1, x_BaseUnitPrice1, tmp_SavingsPlanKey\n | union ((prices | where x_SkuPriceType != 'SavingsPlan'))\n //\n // Calculate commitment discount elgibility\n // TODO: Would a join be faster?\n | extend x_CommitmentDiscountSpendEligibility = iff(x_SkuMeterId in (riMeters) and x_SkuPriceType != 'ReservedInstance', 'Eligible', 'Not Eligible')\n | extend x_CommitmentDiscountUsageEligibility = iff(x_SkuMeterId in (spMeters), 'Eligible', 'Not Eligible')\n //\n // Add PricingUnit and x_PricingBlockSize\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter (PricingUnits) on x_PricingUnitDescription | project-away x_PricingUnitDescription1\n | lookup kind=leftouter (PricingUnits | extend x_PricingBlockSize = todecimal(x_PricingBlockSize)) on x_PricingUnitDescription\n //\n | extend x_EffectiveUnitPrice = iff(x_SkuPriceType == 'SavingsPlan', UnitPrice, todecimal('')) // Savings plan prices are for the effective price, not the contracted price\n | extend x_EffectiveUnitPriceDiscount = ContractedUnitPrice - x_EffectiveUnitPrice\n | extend x_ContractedUnitPriceDiscount = ListUnitPrice - ContractedUnitPrice\n | extend x_TotalUnitPriceDiscount = ListUnitPrice - x_EffectiveUnitPrice\n | project\n BillingAccountId = tolower(case(\n BillingProfileId startswith '/', BillingProfileId,\n BillingAccountId startswith '/', BillingAccountId,\n strcat('/providers/microsoft.billing/billingaccounts/', x_BillingAccountId, iff(x_BillingProfileId == x_BillingAccountId, '', strcat('/billingprofiles/', x_BillingProfileId)))\n )),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName, x_BillingProfileId),\n BillingCurrency = coalesce(BillingCurrency, CurrencyCode, Currency), // Currency last as a fallback only\n ChargeCategory,\n CommitmentDiscountCategory = case(\n x_SkuPriceType == 'ReservedInstance', 'Usage',\n x_SkuPriceType == 'SavingsPlan', 'Spend',\n ''\n ),\n CommitmentDiscountType = case(\n x_SkuPriceType == 'ReservedInstance', 'Reservation',\n x_SkuPriceType == 'SavingsPlan', 'Savings plan',\n ''\n ),\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory = case(\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed',\n ''\n ),\n PricingUnit,\n SkuId = coalesce(ProductId, ProductID),\n SkuPriceId = strcat(x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType),\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement = case(\n strlen(x_BillingAccountId) > 32, 'MCA',\n strlen(x_BillingAccountId) < 32, 'EA',\n 'Unknown'\n ),\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent = 1.0 * x_ContractedUnitPriceDiscount / ListUnitPrice * 100,\n x_EffectivePeriodEnd = startofmonth(x_EffectivePeriodEnd + 1h),\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent = 1.0 * x_EffectiveUnitPriceDiscount / ContractedUnitPrice * 100,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingCurrency = coalesce(Currency, CurrencyCode), // CurrencyCode last as a fallback only\n x_PricingSubcategory = case(\n x_SkuPriceType == 'Consumption' and (x_SkuIncludedQuantity > 0 or x_SkuTier > 0), 'Tiered',\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed Spend',\n ''\n ),\n x_PricingUnitDescription,\n x_SkuDescription = Product,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterName,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName = coalesce(x_SourceName, 'Cost Management'),\n x_SourceProvider = coalesce(x_SourceProvider, 'Microsoft'),\n x_SourceType = coalesce(x_SourceType, 'PriceSheet'),\n x_SourceVersion = coalesce(x_SourceVersion, '2023-05-01'),\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent = 1.0 * x_TotalUnitPriceDiscount / ListUnitPrice * 100\n}\n\n// Prices_final_v1_0 table\n.create-merge table Prices_final_v1_0 (\n BillingAccountId: string,\n BillingAccountName: string,\n BillingCurrency: string,\n ChargeCategory: string,\n CommitmentDiscountCategory: string,\n CommitmentDiscountType: string,\n ContractedUnitPrice: decimal,\n ListUnitPrice: decimal,\n PricingCategory: string,\n PricingUnit: string,\n SkuId: string,\n SkuPriceId: string,\n SkuPriceIdv2: string, // Hubs add-on\n x_BaseUnitPrice: decimal, // Azure\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure MCA\n x_BillingProfileId: string, // Azure MCA\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_ContractedUnitPriceDiscount: decimal, // Hubs add-on\n x_ContractedUnitPriceDiscountPercent: decimal, // Hubs add-on\n x_EffectivePeriodEnd: datetime, // Azure\n x_EffectivePeriodStart: datetime, // Azure\n x_EffectiveUnitPrice: decimal, // Azure\n x_EffectiveUnitPriceDiscount: decimal, // Hubs add-on\n x_EffectiveUnitPriceDiscountPercent: decimal, // Hubs add-on\n x_IngestionTime: datetime, // Hubs add-on\n x_PricingBlockSize: decimal, // Hubs add-on\n x_PricingCurrency: string, // Azure\n x_PricingSubcategory: string, // Hubs add-on\n x_PricingUnitDescription: string, // Azure\n x_SkuDescription: string, // Azure\n x_SkuId: string, // Azure\n x_SkuIncludedQuantity: decimal, // Azure EA\n x_SkuMeterCategory: string, // Azure\n x_SkuMeterId: string, // Azure\n x_SkuMeterName: string, // Azure\n x_SkuMeterSubcategory: string, // Azure\n x_SkuMeterType: string, // Azure\n x_SkuPriceType: string, // Azure\n x_SkuProductId: string, // Azure\n x_SkuRegion: string, // Azure\n x_SkuServiceFamily: string, // Azure\n x_SkuOfferId: string, // Azure EA\n x_SkuPartNumber: string, // Azure EA\n x_SkuTerm: int, // Azure\n x_SkuTier: decimal, // Azure MCA\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_TotalUnitPriceDiscount: decimal, // Hubs add-on\n x_TotalUnitPriceDiscountPercent: decimal // Hubs add-on\n)\n\n// Update policy for Prices_raw -> Prices_final_v1_0\n.alter table Prices_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Prices_raw\",\n \"Query\": \"Prices_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Cost and usage |=================================================================================================\n// Supported versions:\n// - MS: 1.0, 1.0-preview(v1) -- See https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0 -- See https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024 -- See https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 -- See https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All costs transformed to FOCUS 1.0. Use Costs_transform_v1_2() instead.', folder='Costs')\nCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n Costs_raw\n //\n // Change real to decimal\n | extend\n BilledCost = todecimal(BilledCost),\n CommitmentDiscountQuantity = todecimal(CommitmentDiscountQuantity),\n ConsumedQuantity = todecimal(ConsumedQuantity),\n ContractedCost = todecimal(ContractedCost),\n ContractedUnitPrice = todecimal(ContractedUnitPrice),\n EffectiveCost = todecimal(EffectiveCost),\n ListCost = todecimal(ListCost),\n ListUnitPrice = todecimal(ListUnitPrice),\n PricingQuantity = todecimal(PricingQuantity),\n UsageAmount = todecimal(UsageAmount),\n UsageQuantity = todecimal(UsageQuantity),\n x_BilledCostInUsd = todecimal(x_BilledCostInUsd),\n x_BilledUnitPrice = todecimal(x_BilledUnitPrice),\n x_BillingExchangeRate = todecimal(x_BillingExchangeRate),\n x_ContractedCostInUsd = todecimal(x_ContractedCostInUsd),\n x_Cost = todecimal(x_Cost),\n x_CurrencyConversionRate = todecimal(x_CurrencyConversionRate),\n x_EffectiveCostInUsd = todecimal(x_EffectiveCostInUsd),\n x_EffectiveUnitPrice = todecimal(x_EffectiveUnitPrice),\n x_ListCostInUsd = todecimal(x_ListCostInUsd),\n x_OnDemandCost = todecimal(x_OnDemandCost),\n x_OnDemandCostInUsd = todecimal(x_OnDemandCostInUsd),\n x_OnDemandUnitPrice = todecimal(x_OnDemandUnitPrice),\n x_PricingBlockSize = todecimal(x_PricingBlockSize)\n //\n // Dedupe rows\n | extend x_IngestionTime = ingestion_time()\n | extend x_ChargeId = ''\n // TODO: Consider adding a unique charge ID per row\n // hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // // 1. Resource hierarchy (including resource name), highest to lowest\n // BillingAccountId,\n // x_InvoiceSectionId,\n // x_AccountOwnerId,\n // SubAccountId,\n // x_ResourceGroupName,\n // ResourceName,\n // // 2. Resource details\n // ResourceId,\n // RegionId,\n // Tags,\n // CommitmentDiscountId,\n // x_CostCenter,\n // // 4. Meter details\n // SkuPriceId,\n // x_SkuMeterId,\n // x_SkuPartNumber,\n // x_SkuOfferId,\n // x_SkuDetails,\n // // 5. Date\n // ChargePeriodStart\n // ))\n //\n // Identify data quality issues\n | extend x_SourceChanges = trim_end(',', strcat(\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based', 'InvalidChargeFrequency,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and EffectiveCost > 0, 'InvalidEffectiveCost,', ''),\n iff((isempty(ContractedCost) or ContractedCost == 0) and EffectiveCost != 0, 'MissingContractedCost,', ''),\n iff((isempty(ContractedUnitPrice) or ContractedUnitPrice == 0) and x_EffectiveUnitPrice != 0, 'MissingContractedUnitPrice,', ''),\n iff(ListCost < ContractedCost, 'ListCostLessThanContractedCost,', ''),\n iff(ContractedCost < EffectiveCost, 'ContractedCostLessThanEffectiveCost,', ''),\n iff((isempty(ListCost) or ListCost == 0) and (ContractedCost != 0 or EffectiveCost != 0), 'MissingListCost,', ''),\n iff((isempty(ListUnitPrice) or ListUnitPrice == 0) and (ContractedUnitPrice != 0 or x_EffectiveUnitPrice != 0), 'MissingListUnitPrice,', ''),\n iff((isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001)\n or (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001),\n 'XEffectiveUnitPriceRoundingError,', ''),\n iff(ConsumedQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingConsumedQuantity,', ''),\n iff(PricingQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingPricingQuantity,', ''),\n iff(isempty(ProviderName), 'MissingProviderName,', ''),\n iff(isempty(PublisherName), 'MissingPublisherName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceId), 'MissingResourceId,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceName), 'MissingResourceName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceType), 'MissingResourceType,', ''),\n iff(BilledCost > 0 and x_BilledUnitPrice == 0, 'MissingXBilledUnitPrice,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(x_ResourceType), 'MissingXResourceType,', ''),\n iff(PricingCategory == 'Standard' and isnotempty(CommitmentDiscountId) and ChargeCategory == 'Usage', 'PricingCategoryShouldBeCommitted,', ''),\n iff(x_SkuTerm == '1Year' or x_SkuTerm == '3Years' or x_SkuTerm == '5Years', 'SkuTermShouldBeAnInteger,', '')\n ))\n //\n // Fix columns needed in other changes\n | extend ProviderName = case(\n isnotempty(ProviderName), ProviderName,\n isnotempty(coalesce(x_CostCategories, x_Discount, x_Operation, x_ServiceCode, x_UsageType)), 'AWS',\n isnotempty(coalesce(tostring(UsageAmount), tostring(x_Cost), x_Credits, x_CostType, tostring(x_CurrencyConversionRate), tostring(x_ExportTime), x_Project, x_ServiceId)), 'GCP',\n isnotempty(coalesce(x_BillingProfileId, x_InvoiceSectionId)), 'Microsoft',\n ''\n )\n //\n // Identify source\n | extend x_SourceName = coalesce(x_SourceName, iff(isnotempty(x_BillingProfileId), 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(isnotempty(x_BillingProfileId), 'FocusCost', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, case(\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)) and isempty(SkuPriceDetails) and isnotempty(x_SkuDetails), '1.2-preview',\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)), '1.2',\n isnotempty(coalesce(ChargeClass, CommitmentDiscountStatus, tostring(ConsumedQuantity), ConsumedUnit, tostring(ContractedCost), tostring(ContractedUnitPrice), RegionId, RegionName)), '1.0',\n isnotempty(coalesce(ChargeSubcategory, Region, tostring(UsageQuantity), UsageUnit)), iff(ProviderName == 'Microsoft', '1.0-preview(v1)', '1.0-preview'),\n ''\n ))\n // Append version check error code\n | extend x_SourceChanges = iff(x_SourceVersion == '1.0', x_SourceChanges,\n strcat(x_SourceChanges, iff(isempty(x_SourceChanges), '', ','), iff(x_SourceVersion == '', 'UnknownFocusVersion', 'LegacyFocusVersion'))\n )\n //\n // Fix quantities\n | extend PricingQuantity = case(\n PricingQuantity != 0 or (EffectiveCost == 0 and BilledCost == 0), PricingQuantity,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(EffectiveCost) and EffectiveCost != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0, EffectiveCost / x_EffectiveUnitPrice,\n PricingQuantity\n )\n | extend ConsumedQuantity = case(\n isnotempty(ConsumedQuantity) and ConsumedQuantity != 0, ConsumedQuantity,\n ChargeCategory == 'Usage', PricingQuantity / coalesce(x_PricingBlockSize, decimal(1)),\n ConsumedQuantity\n )\n //\n // Populate missing prices -- mapping to on-demand prices requires meter ID and offer ID\n | extend tmp_MissingPrices = ProviderName == 'Microsoft'\n and (ListUnitPrice == 0 or ContractedUnitPrice == 0)\n and x_EffectiveUnitPrice != 0\n and not(CommitmentDiscountCategory == 'Spend' and CommitmentDiscountStatus == 'Unused')\n and isnotempty(x_SkuMeterId) and isnotempty(x_SkuOfferId)\n | as allCosts\n | where tmp_MissingPrices\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(ChargePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | as costsWithMissingPrices\n | join kind=leftouter (\n Prices_final_v1_0\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(x_EffectivePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | where x_SkuPriceType == 'Consumption' and tmp_ReservationPriceLookupKey in ((costsWithMissingPrices | summarize by tmp_ReservationPriceLookupKey))\n | summarize ListUnitPrice = min(ListUnitPrice), ContractedUnitPrice = min(ContractedUnitPrice) by tmp_ReservationPriceLookupKey, x_PricingBlockSize, PricingUnit\n ) on tmp_ReservationPriceLookupKey\n //\n // Select the best price to use for each row\n // TODO: Save values before changing -- | extend x_old_ContractedUnitPrice = ContractedUnitPrice, x_old_EffectiveUnitPrice = x_EffectiveUnitPrice, x_old_ListUnitPrice = ListUnitPrice, x_old_ListCost = ListCost, x_old_ContractedCost = ContractedCost\n | extend x_EffectiveUnitPrice = case(\n // If price is a rounding error away from the billed price, use the billed price\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001, x_BilledUnitPrice,\n // If price is a rounding error away from the contracted price, use the contracted price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001, ContractedUnitPrice,\n x_EffectiveUnitPrice\n )\n | extend ContractedUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ContractedUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ContractedUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // If billed price is available, assume the billed price is the same as contracted price to support aggregations\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, x_EffectiveUnitPrice,\n // Otherwise, assume the effective price is the same as contracted price to support aggregations\n x_EffectiveUnitPrice\n )\n | extend ListUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ListUnitPrice) and ListUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ListUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ListUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ListUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // Otherwise, assume the contracted price is the same as list price to support aggregations\n ContractedUnitPrice\n )\n // Calculate missing costs based on new prices -- If cost is already correct, keep that; if not and price is available, recalculate the cost; otherwise, keep the existing cost\n | extend ContractedCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ContractedCost) and ContractedCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedCost,\n // ContractedCost is 0 in all other scenarios...\n // If 0 and there's a billed cost and prices are the same, use BilledCost\n isnotempty(BilledCost) and BilledCost != 0 and ContractedUnitPrice == x_BilledUnitPrice, BilledCost,\n // If 0 and there's a billed cost and prices are the same, use EffectiveCost\n isnotempty(EffectiveCost) and EffectiveCost != 0 and ContractedUnitPrice == x_EffectiveUnitPrice, EffectiveCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0, ContractedUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume EffectiveCost\n isempty(ContractedUnitPrice) or ContractedUnitPrice == 0, EffectiveCost,\n // Fall back to the original value for any unhandled scenarios\n ContractedCost\n )\n | extend ListCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ListCost) and ListCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ListCost,\n // ListCost is 0 in all other scenarios...\n // If 0 and there's a contracted cost and prices are the same, use ContractedCost\n isnotempty(ContractedCost) and ContractedCost != 0 and ListUnitPrice == ContractedUnitPrice, ContractedCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ListUnitPrice) and ListUnitPrice != 0, ListUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume ContractedCost\n isempty(ListUnitPrice) or ListUnitPrice == 0, ContractedCost,\n // Fall back to the original value for any unhandled scenarios\n ListCost\n )\n // Merge the rest of the unmodified cost records and remove excess columns\n | union (allCosts | where not(tmp_MissingPrices))\n | project-away x_PricingBlockSize1, PricingUnit1, ListUnitPrice1, ContractedUnitPrice1, tmp_MissingPrices, tmp_ReservationPriceLookupKey, tmp_ReservationPriceLookupKey1\n //\n // BUG: Fix ContractedCost that has bad values\n | extend ContractedCost = iff(ProviderName == 'Microsoft' and isnotempty(PricingQuantity) and isnotempty(x_PricingBlockSize) and ContractedCost != ContractedUnitPrice * PricingQuantity, ContractedUnitPrice * PricingQuantity, ContractedCost)\n //\n // Handle FOCUS 1.0-preview UsageQuantity/Unit\n | extend ConsumedQuantity = iff(ChargeCategory == 'Usage', coalesce(ConsumedQuantity, UsageQuantity, UsageAmount), todecimal(''))\n | extend ConsumedUnit = iff(ChargeCategory == 'Usage' and isnotempty(ConsumedQuantity), coalesce(ConsumedUnit, UsageUnit, 'Units'), '')\n //\n // Convert IDs to lowercase for consistency\n | extend CommitmentDiscountId = tolower(CommitmentDiscountId)\n //\n // BUG: Remove EffectiveCost for commitment discount purchases\n | extend EffectiveCost = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), decimal(0), EffectiveCost)\n | extend x_EffectiveCostInUsd = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), decimal(0), x_EffectiveCostInUsd)\n //\n // Clean up resource columns\n | extend ResourceId = case(\n isnotempty(ResourceId), ResourceId,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), CommitmentDiscountId,\n ResourceId)\n | extend ResourceName = tolower(case(\n isnotempty(ResourceName), ResourceName,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountName), CommitmentDiscountName,\n isnotempty(ResourceId), parse_resourceid(ResourceId).ResourceName,\n ResourceName))\n | extend x_ResourceType = case(\n isnotempty(x_ResourceType), x_ResourceType,\n isnotempty(ResourceId), parse_resourceid(ResourceId).x_ResourceType,\n x_ResourceType)\n | extend ResourceType = case(\n // Use existing resource type display name unless it's an internal resource type ID\n isnotempty(ResourceType) and tolower(ResourceType) != tolower(x_ResourceType) and ResourceType !contains '/', ResourceType,\n // Use CommitmentDiscountType for commitment discount purchases\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountType), CommitmentDiscountType,\n // Look up display name from internal type\n isnotempty(x_ResourceType), coalesce(resource_type(x_ResourceType).SingularDisplayName, ResourceType, x_ResourceType),\n ResourceType)\n //\n // Sort columns and apply final transforms\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId = tolower(BillingAccountId),\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEnd),\n BillingPeriodStart = startofmonth(BillingPeriodStart),\n ChargeCategory = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Credit', 'Credit',\n ChargeSubcategory == 'Refund', 'Purchase', // We are assuming purchase refunds since we don't have data to indicate usage refunds\n ChargeCategory\n ),\n ChargeClass = case(ChargeSubcategory == 'Refund', 'Correction', ChargeClass),\n ChargeDescription,\n // BUG: ChargeFrequency shows \"Usage-Based\" for monthly recurring savings plan purchases\n ChargeFrequency = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based' and ProviderName == 'Microsoft' and x_SourceVersion startswith '1.0', 'Recurring', ChargeFrequency),\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId = tolower(CommitmentDiscountId),\n CommitmentDiscountName,\n CommitmentDiscountStatus = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Used Commitment', 'Used',\n ChargeSubcategory == 'Unused Commitment', 'Unused',\n CommitmentDiscountStatus\n ),\n CommitmentDiscountType,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost = coalesce(ContractedCost, x_OnDemandCost, x_Cost),\n ContractedUnitPrice = coalesce(ContractedUnitPrice, x_OnDemandUnitPrice),\n EffectiveCost,\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory = case(\n // Handle FOCUS 1.0-preview PricingCategory values\n PricingCategory == 'On-Demand', 'Standard',\n PricingCategory == 'Commitment-Based', 'Committed',\n PricingCategory\n ),\n PricingQuantity,\n PricingUnit,\n ProviderName,\n // Handle missing PublisherName values\n PublisherName = case(PublisherName == 'Microsoft Corporation', 'Microsoft', isnotempty(PublisherName), PublisherName, x_PublisherCategory == 'Cloud Provider', ProviderName, ''),\n // Handle FOCUS 1.0-preview Region column\n RegionId = coalesce(RegionId, iff(ProviderName == 'Microsoft', replace_string(tolower(Region), ' ', ''), Region)),\n RegionName = coalesce(RegionName, Region),\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SkuId,\n SkuPriceId,\n SubAccountId,\n SubAccountName,\n SubAccountType, // Azure 1.0-preview(v1)+\n Tags = parse_json(Tags),\n x_AccountId, // Azure 1.0-preview(v1)+\n x_AccountName, // Azure 1.0-preview(v1)+\n x_AccountOwnerId, // Azure 1.0-preview(v1)+\n x_BilledCostInUsd, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement = case(\n ProviderName == 'Microsoft' and x_BillingAccountId == x_BillingProfileId, 'EA',\n ProviderName == 'Microsoft' and x_BillingAccountId != x_BillingProfileId, 'MCA',\n ProviderName\n ), // Hubs add-on\n x_BillingAccountId, // Azure 1.0-preview(v1)+\n x_BillingAccountName, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate, // Azure 1.0-preview(v1)+\n x_BillingProfileId, // Azure 1.0-preview(v1)+\n x_BillingProfileName, // Azure 1.0-preview(v1)+\n x_ChargeId, // Azure 1.0-preview(v1) only\n x_ContractedCostInUsd = coalesce(x_ContractedCostInUsd, x_OnDemandCostInUsd), // Azure 1.0+\n x_CostAllocationRuleName, // Azure 1.0-preview(v1)+\n x_CostCategories = parse_json(x_CostCategories), // AWS 1.0 (JSON)\n x_CostCenter, // Azure 1.0-preview(v1)+\n x_Credits = parse_json(x_Credits), // GCP Jan 2024\n x_CostType, // GCP Jan 2024\n x_CurrencyConversionRate, // GCP Jun 2024\n x_CustomerId, // Azure 1.0-preview(v1)+\n x_CustomerName, // Azure 1.0-preview(v1)+\n x_Discount = parse_json(x_Discount), // AWS 1.0 (JSON)\n x_EffectiveCostInUsd, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice, // Azure 1.0-preview(v1)+\n x_ExportTime, // GCP Jan 2024\n x_IngestionTime, // Hubs add-on\n x_InvoiceId = coalesce(InvoiceId, x_InvoiceId), // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId = case( // Azure 1.0-preview(v1)+\n x_InvoiceSectionId == '-2', '',\n x_InvoiceSectionId\n ),\n x_InvoiceSectionName = case( // Azure 1.0-preview(v1)+\n x_InvoiceSectionName == 'Unassigned', '',\n x_InvoiceSectionName\n ),\n x_ListCostInUsd, // Azure 1.0-preview(v1)+\n x_Location, // GCP Jan 2024\n x_Operation, // AWS 1.0\n x_PartnerCreditApplied, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate, // Azure 1.0-preview(v1)+\n x_PricingBlockSize, // Azure 1.0-preview(v1)+\n x_PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency), // Azure 1.0-preview(v1)+\n x_PricingSubcategory, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription, // Azure 1.0-preview(v1)+\n x_Project, // GCP Jan 2024\n x_PublisherCategory, // Azure 1.0-preview(v1)+\n x_PublisherId, // Azure 1.0-preview(v1)+\n x_ResellerId, // Azure 1.0-preview(v1)+\n x_ResellerName, // Azure 1.0-preview(v1)+\n x_ResourceGroupName = tolower(x_ResourceGroupName), // Azure 1.0-preview(v1)+\n x_ResourceType, // Azure 1.0-preview(v1)+\n x_ServiceCode, // AWS 1.0\n x_ServiceId, // GCP Jan 2024\n x_ServicePeriodEnd, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart, // Azure 1.0-preview(v1)+\n x_SkuDescription, // Azure 1.0-preview(v1)+\n x_SkuDetails = parse_json(x_SkuDetails), // Azure 1.0-preview(v1)+\n x_SkuIsCreditEligible, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory, // Azure 1.0-preview(v1)+\n x_SkuMeterId, // Azure 1.0-preview(v1)+\n x_SkuMeterName = coalesce(SkuMeter, x_SkuMeterName), // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory, // Azure 1.0-preview(v1)+\n x_SkuOfferId, // Azure 1.0-preview(v1)+\n x_SkuOrderId, // Azure 1.0-preview(v1)+\n x_SkuOrderName, // Azure 1.0-preview(v1)+\n x_SkuPartNumber, // Azure 1.0-preview(v1)+\n x_SkuRegion, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily, // Azure 1.0-preview(v1)+\n x_SkuTerm, // Azure 1.0-preview(v1)+\n x_SkuTier, // Azure 1.0-preview(v1)+\n x_SourceChanges, // Hubs add-on\n x_SourceName, // Hubs add-on\n x_SourceProvider, // Hubs add-on\n x_SourceType, // Hubs add-on\n x_SourceVersion, // Hubs add-on\n x_UsageType // AWS 1.0\n}\n\n// Costs_final_v1_0 table\n.create-merge table Costs_final_v1_0 (\n AvailabilityZone: string,\n BilledCost: decimal,\n BillingAccountId: string,\n BillingAccountName: string,\n BillingAccountType: string, // Azure 1.0-preview(v1)+\n BillingCurrency: string,\n BillingPeriodEnd: datetime,\n BillingPeriodStart: datetime,\n ChargeCategory: string,\n ChargeClass: string,\n ChargeDescription: string,\n ChargeFrequency: string,\n ChargePeriodEnd: datetime,\n ChargePeriodStart: datetime,\n CommitmentDiscountCategory: string, // FOCUS 1.0-preview only\n CommitmentDiscountId: string,\n CommitmentDiscountName: string,\n CommitmentDiscountStatus: string,\n CommitmentDiscountType: string,\n ConsumedQuantity: decimal,\n ConsumedUnit: string,\n ContractedCost: decimal,\n ContractedUnitPrice: decimal,\n EffectiveCost: decimal,\n InvoiceIssuerName: string,\n ListCost: decimal,\n ListUnitPrice: decimal,\n PricingCategory: string,\n PricingQuantity: decimal,\n PricingUnit: string,\n ProviderName: string,\n PublisherName: string,\n RegionId: string,\n RegionName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n ServiceCategory: string,\n ServiceName: string,\n SkuId: string,\n SkuPriceId: string,\n SubAccountId: string,\n SubAccountName: string,\n SubAccountType: string,\n Tags: dynamic,\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_BilledCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: decimal, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: decimal, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_ContractedCostInUsd: decimal, // Azure 1.0+\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: dynamic, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_Credits: dynamic, // GCP Jan 2024\n x_CostType: string, // GCP Jan 2024\n x_CurrencyConversionRate: decimal, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: dynamic, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: decimal, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024\n x_IngestionTime: datetime, // Hubs add-on\n x_InvoiceId: string, // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_Operation: string, // AWS 1.0\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: decimal, // Azure 1.0-preview(v1)+\n x_PricingCurrency: string, // Azure 1.0-preview(v1)+\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: dynamic, // Azure 1.0-preview(v1)+\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterName: string, // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceChanges: string, // Hubs add-on\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_UsageType: string // AWS 1.0\n)\n\n// Update policy for Costs_raw -> Costs_final_v1_0 table\n.alter table Costs_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Costs_raw\",\n \"Query\": \"Costs_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Actual costs |===================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: ActualCost exports transformed to FOCUS 1.0. Use ActualCosts_transform_v1_2() instead.', folder='Costs')\nActualCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n // TODO: Transform actual costs to FOCUS 1.0 format\n ActualCosts_raw\n | where ChargeType in ('Purchase', 'Refund') and isnotempty(ReservationId)\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: ServiceSubcategory, PublisherName, x_PublisherCategory, x_Environment, x_ServiceModel\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodStart = Date,\n ChargePeriodEnd = Date + 1d,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = '',\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory = '',\n SkuId = '',\n SkuMeter = '',\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = SubscriptionName,\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentName = '',\n x_ComponentType = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel = '',\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for ActualCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": false,\n \"Source\": \"ActualCosts_raw\",\n \"Query\": \"ActualCosts_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Amortized costs |================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: ActualCost exports transformed to FOCUS 1.0. Use AmortizedCosts_transform_v1_2() instead.', folder='Costs')\nAmortizedCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n // TODO: Transform actual costs to FOCUS 1.0 format\n AmortizedCosts_raw\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: ServiceSubcategory, PublisherName, x_PublisherCategory, x_Environment, x_ServiceModel\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodStart = Date,\n ChargePeriodEnd = Date + 1d,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = '',\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory = '',\n SkuId = '',\n SkuMeter = '',\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = SubscriptionName,\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentName = '',\n x_ComponentType = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel = '',\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for AmortizedCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": false,\n \"Source\": \"AmortizedCosts_raw\",\n \"Query\": \"AmortizedCosts_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All commitment discount usage transformed to FOCUS 1.0. This includes reservationdeatils_raw. Use CommitmentDiscountUsage_transform_v1_2() instead.', folder='Commitment discounts')\nCommitmentDiscountUsage_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n CommitmentDiscountUsage_raw\n //\n // Change real to decimal\n | extend\n InstanceFlexibilityRatio = todecimal(InstanceFlexibilityRatio),\n ReservedHours = todecimal(ReservedHours),\n TotalReservedQuantity = todecimal(TotalReservedQuantity),\n UsedHours = todecimal(UsedHours)\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Handle resource columns\n | extend ResourceId = tolower(InstanceId)\n | extend tmp_ResourceDetails = parse_resourceid(ResourceId)\n | extend ResourceName = tostring(tmp_ResourceDetails.ResourceName)\n | extend SubAccountId = tostring(tmp_ResourceDetails.SubAccountId)\n | extend x_ResourceGroupName = tostring(tmp_ResourceDetails.x_ResourceGroupName)\n | extend x_ResourceType = tostring(tmp_ResourceDetails.x_ResourceType)\n | lookup kind=leftouter (ResourceTypes | distinct x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n | lookup kind=leftouter (Services | distinct x_ResourceType, ServiceName, ServiceCategory, x_ServiceModel) on x_ResourceType\n //\n // Sort columns and apply final transforms\n | project\n ChargePeriodEnd = UsageDate + 1d,\n ChargePeriodStart = UsageDate,\n CommitmentDiscountCategory = 'Usage',\n CommitmentDiscountId = tolower(strcat('/providers/microsoft.capacity/reservationorders/', ReservationOrderId, '/reservations/', ReservationId)),\n CommitmentDiscountType = 'Reservation',\n ConsumedQuantity = UsedHours,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SubAccountId,\n x_CommitmentDiscountCommittedCount = TotalReservedQuantity,\n x_CommitmentDiscountCommittedAmount = ReservedHours,\n // TODO: Is this needed? -- x_CommitmentDiscountKind = Kind,\n x_CommitmentDiscountNormalizedGroup = iff(InstanceFlexibilityGroup == 'NA', '', InstanceFlexibilityGroup),\n x_CommitmentDiscountNormalizedRatio = InstanceFlexibilityRatio,\n x_CommitmentDiscountQuantity = UsedHours * InstanceFlexibilityRatio,\n x_IngestionTime = ingestion_time(),\n x_ResourceGroupName,\n x_ResourceType,\n // x_RowId = hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // CommitmentDiscountId,\n // ResourceId,\n // ChargePeriodStart\n // )),\n x_ServiceModel,\n x_SkuOrderId = ReservationOrderId,\n x_SkuSize = iff(SkuName == 'NA', '', SkuName),\n x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName)),\n x_SourceProvider = coalesce(x_SourceProvider, ProviderName),\n x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationDetails', '')),\n x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2024-03-01', ''))\n}\n\n// CommitmentDiscountUsage_final_v1_0 table\n.create-merge table CommitmentDiscountUsage_final_v1_0 (\n ChargePeriodEnd: datetime, // Hubs add-on\n ChargePeriodStart: datetime, // MS 2023-03-01\n CommitmentDiscountCategory: string, // Hubs add-on\n CommitmentDiscountId: string, // MS 2023-03-01\n CommitmentDiscountType: string, // Hubs add-on\n ConsumedQuantity: decimal, // MS 2023-03-01\n ProviderName: string, // Hubs add-on\n ResourceId: string, // MS 2023-03-01\n ResourceName: string, // Hubs add-on\n ResourceType: string, // Hubs add-on\n ServiceCategory: string, // Hubs add-on\n ServiceName: string, // Hubs add-on\n SubAccountId: string, // Hubs add-on\n x_CommitmentDiscountCommittedCount: decimal, // MS 2023-03-01\n x_CommitmentDiscountCommittedAmount: decimal, // MS 2023-03-01\n x_CommitmentDiscountNormalizedGroup: string, // MS 2023-03-01\n x_CommitmentDiscountNormalizedRatio: decimal, // MS 2023-03-01\n x_CommitmentDiscountQuantity: decimal, // MS 2023-03-01\n x_IngestionTime: datetime, // Hubs add-on\n x_ResourceGroupName: string, // Hubs add-on\n x_ResourceType: string, // Hubs add-on\n x_ServiceModel: string, // Hubs add-on\n x_SkuOrderId: string, // MS 2023-03-01\n x_SkuSize: string, // MS 2023-03-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string // Hubs add-on\n)\n\n// Update policy for CommitmentDiscountUsage_raw -> CommitmentDiscountUsage_final_v1_0 table\n.alter table CommitmentDiscountUsage_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"CommitmentDiscountUsage_raw\",\n \"Query\": \"CommitmentDiscountUsage_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All recommendations transformed to FOCUS 1.0. Use Recommendations_transform_v1_2() instead.', folder='Recommendations')\nRecommendations_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Recommendations_raw\n //\n // Change real to decimal\n | extend\n CostWithNoReservedInstances = todecimal(CostWithNoReservedInstances),\n InstanceFlexibilityRatio = todecimal(InstanceFlexibilityRatio),\n NetSavings = todecimal(NetSavings),\n RecommendedQuantity = todecimal(RecommendedQuantity),\n RecommendedQuantityNormalized = todecimal(RecommendedQuantityNormalized),\n TotalCostWithReservedInstances = todecimal(TotalCostWithReservedInstances)\n //\n | extend x_IngestionTime = ingestion_time()\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationRecommendations', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Convert JSON cost columns to decimal\n | extend CostWithNoReservedInstances = case(isnotempty(CostWithNoReservedInstances), CostWithNoReservedInstances, isnotempty(CostWithNoReservedInstancesJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, CostWithNoReservedInstancesJson)), CostWithNoReservedInstances)\n | extend NetSavings = case(isnotempty(NetSavings), NetSavings, isnotempty(NetSavingsJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, NetSavingsJson)), NetSavings)\n | extend TotalCostWithReservedInstances = case(isnotempty(TotalCostWithReservedInstances), TotalCostWithReservedInstances, isnotempty(TotalCostWithReservedInstancesJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, TotalCostWithReservedInstancesJson)), TotalCostWithReservedInstances)\n //\n // Build recommendation details\n | lookup kind=leftouter (Regions | summarize RegionName = make_set(RegionName)[0] by Location = RegionId) on Location\n | extend x_RecommendationDetails = case(\n x_SourceType == 'ReservationRecommendations', bag_pack(\n 'CommitmentDiscountNormalizedGroup', InstanceFlexibilityGroup,\n 'CommitmentDiscountNormalizedRatio', InstanceFlexibilityRatio,\n 'CommitmentDiscountNormalizedSize', NormalizedSize,\n 'CommitmentDiscountResourceType', ResourceType,\n 'CommitmentDiscountScope', Scope,\n 'LookbackPeriodDuration', case(\n LookBackPeriod matches regex @'^Last([0-9]+)Days$', replace_regex(LookBackPeriod, @'^Last([0-9]+)Days$', @'P\\1D'),\n LookBackPeriod matches regex @'^[0-9]+$', strcat('P', LookBackPeriod, 'D'),\n ''\n ),\n 'LookbackPeriodStart', FirstUsageDate,\n 'RecommendedQuantity', RecommendedQuantity,\n 'RecommendedQuantityNormalized', RecommendedQuantityNormalized,\n 'RegionId', Location,\n 'RegionName', RegionName,\n 'SkuMeterId', MeterId,\n 'SkuPriceDetails', SkuProperties,\n 'SkuSize', coalesce(SKU, SkuName),\n 'SkuTerm', isoMonths(Term)\n ),\n dynamic({})\n )\n //\n // Sort columns and apply final transforms\n | extend x_RecommendationDate = FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d)\n | extend x_RecommendationDate = iff(x_RecommendationDate > now(), startofday(now()), x_RecommendationDate)\n | project\n ProviderName,\n SubAccountId = iff(isnotempty(SubscriptionId), strcat('/subscriptions/', SubscriptionId), ''),\n x_IngestionTime,\n x_EffectiveCostAfter = TotalCostWithReservedInstances,\n x_EffectiveCostBefore = CostWithNoReservedInstances,\n x_EffectiveCostSavings = NetSavings,\n x_RecommendationDate = FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d),\n x_RecommendationDetails,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n// Recommendations_final_v1_0 table\n.create-merge table Recommendations_final_v1_0 (\n ProviderName: string,\n SubAccountId: string,\n x_IngestionTime: datetime,\n x_EffectiveCostAfter: decimal,\n x_EffectiveCostBefore: decimal,\n x_EffectiveCostSavings: decimal,\n x_RecommendationDate: datetime,\n x_RecommendationDetails: dynamic,\n x_SourceName: string,\n x_SourceProvider: string,\n x_SourceType: string,\n x_SourceVersion: string\n)\n\n// Update policy for Recommendations_raw -> Recommendations_final_v1_0 table\n.alter table Recommendations_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Recommendations_raw\",\n \"Query\": \"Recommendations_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All transactions transformed to FOCUS 1.0. Use Transactions_transform_v1_2() instead.', folder='Transactions')\nTransactions_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Transactions_raw\n //\n // Change real to decimal\n | extend\n Amount = todecimal(Amount),\n MonetaryCommitment = todecimal(MonetaryCommitment),\n Overage = todecimal(Overage),\n Quantity = todecimal(Quantity)\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationTransactions', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Handle BillingPeriodStart/End\n | extend BillingMonth = tostring(BillingMonth)\n | extend BillingPeriodStart = iff(isempty(BillingMonth), datetime(null), todatetime(strcat(substring(BillingMonth, 0, 4), \"-\", substring(BillingMonth, 4, 2), \"-\", substring(BillingMonth, 6, 2))))\n | extend BillingPeriodEnd = iff(isempty(BillingMonth), datetime(null), startofmonth(endofmonth(BillingPeriodStart) + 1d))\n //\n // Sort columns and apply final transforms\n | project\n BilledCost = Amount,\n BillingAccountId = case(\n BillingProfileId startswith '/', BillingProfileId,\n isnotempty(CurrentEnrollmentId), strcat('/providers/Microsoft.Billing/billingAccounts/', CurrentEnrollmentId),\n isnotempty(BillingProfileId), strcat('/providers/Microsoft.Billing/billingProfiles/', BillingProfileId),\n ''\n ),\n BillingAccountName = coalesce(BillingProfileName, CurrentEnrollmentId),\n BillingCurrency = Currency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory = case(\n EventType in ('Cancel', 'Purchase', 'Refund'), 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = case(\n EventType == 'Cancel', 'Cancel', // FOCUS does not handle this scenario\n EventType == 'Refund', 'Correction',\n ''\n ),\n ChargeDescription = Description,\n ChargeFrequency = case(\n BillingFrequency == 'OneTime', 'One-Time',\n BillingFrequency == 'Recurring', 'Recurring',\n BillingFrequency\n ),\n ChargePeriodStart = EventDate,\n PricingQuantity = Quantity,\n PricingUnit = 'Reservations',\n ProviderName,\n RegionId = Region,\n RegionName = Region,\n SubAccountId = iff(isempty(PurchasingSubscriptionGuid), '', strcat('/subscriptions/', PurchasingSubscriptionGuid)),\n SubAccountName = iff(isempty(PurchasingSubscriptionGuid), '', PurchasingSubscriptionName),\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerEmail,\n x_CostCenter = CostCenter,\n x_InvoiceId = InvoiceId,\n x_InvoiceNumber = Invoice,\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = coalesce(InvoiceSectionName, DepartmentName),\n x_IngestionTime = ingestion_time(),\n x_MonetaryCommitment = MonetaryCommitment,\n x_Overage = Overage,\n x_PurchasingBillingAccountId = PurchasingEnrollment,\n x_SkuOrderId = ReservationOrderId,\n x_SkuOrderName = ReservationOrderName,\n x_SkuSize = ArmSkuName,\n x_SkuTerm = isoMonths(Term),\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId = PurchasingSubscriptionGuid,\n x_TransactionType = EventType\n}\n\n// Transactions_final_v1_0 table\n.create-merge table Transactions_final_v1_0 (\n BilledCost: decimal, // MS CM EA+MCA 2023-05-01\n BillingAccountId: string, // MS CM EA+MCA 2023-05-01\n BillingAccountName: string, // MS CM EA+MCA 2023-05-01\n BillingCurrency: string, // MS CM EA+MCA 2023-05-01\n BillingPeriodEnd: datetime, // MS CM EA+MCA 2023-05-01\n BillingPeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n ChargeCategory: string, // Hubs add-on\n ChargeClass: string, // Hubs add-on\n ChargeDescription: string, // MS CM EA+MCA 2023-05-01\n ChargeFrequency: string, // MS CM EA+MCA 2023-05-01\n ChargePeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n PricingQuantity: decimal, // MS CM EA+MCA 2023-05-01\n PricingUnit: string, // Hubs add-on\n ProviderName: string, // Hubs add-on\n RegionId: string, // MS CM EA+MCA 2023-05-01\n RegionName: string, // MS CM EA+MCA 2023-05-01\n SubAccountId: string, // MS CM EA+MCA 2023-05-01\n SubAccountName: string, // MS CM EA+MCA 2023-05-01\n x_AccountName: string, // MS CM EA 2023-05-01\n x_AccountOwnerId: string, // MS CM EA 2023-05-01\n x_CostCenter: string, // MS CM EA 2023-05-01\n x_InvoiceId: string, // MS CM MCA 2023-05-01\n x_InvoiceNumber: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionId: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionName: string, // MS CM MCA 2023-05-01\n x_IngestionTime: datetime, // Hubs add-on\n x_MonetaryCommitment: decimal, // MS CM EA 2023-05-01\n x_Overage: decimal, // MS CM EA 2023-05-01\n x_PurchasingBillingAccountId: string, // MS CM EA 2023-05-01\n x_SkuOrderId: string, // MS CM EA+MCA 2023-05-01\n x_SkuOrderName: string, // MS CM EA+MCA 2023-05-01\n x_SkuSize: string, // MS CM EA+MCA 2023-05-01\n x_SkuTerm: int, // MS CM EA+MCA 2023-05-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubscriptionId: string, // MS CM EA+MCA 2023-05-01\n x_TransactionType: string // MS CM EA+MCA 2023-05-01\n)\n\n// Update policy for Transactions_raw -> Transactions_final_v1_0 table\n.alter table Transactions_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Transactions_raw\",\n \"Query\": \"Transactions_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n", "HUB_DATA_EXPLORER": "hubDataExplorer", "HUB_DB": "Hub", "INGESTION_DB": "Ingestion", diff --git a/docs/deploy/finops-hub-latest.json b/docs/deploy/finops-hub-latest.json index f9d71a4ab..f90016f65 100644 --- a/docs/deploy/finops-hub-latest.json +++ b/docs/deploy/finops-hub-latest.json @@ -18320,7 +18320,7 @@ "variables": { "$fxv#0": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n.create-or-alter function \nwith (docstring = 'Return details about the specified ID.', folder = 'OpenData/Internal')\n_resource_type_1(id: string) {\n dynamic({\n \"arizeai.observabilityeval/organizations\": { \"SingularDisplayName\": \"Azure Native Arize AI Cloud Service\" }\n ,\"astronomer.astro/organizations\": { \"SingularDisplayName\": \"Astro Organization\" }\n ,\"citrix.services/xenappessentials\": { \"SingularDisplayName\": \"Citrix Virtual Apps Essentials\" }\n ,\"citrix.services/xendesktopessentials\": { \"SingularDisplayName\": \"Citrix Virtual Desktops Essentials\" }\n ,\"commvault.contentstore/cloudaccounts\": { \"SingularDisplayName\": \"Commvault Cloud Account\" }\n ,\"commvault.contentstore/cloudaccounts/plans\": { \"SingularDisplayName\": \"Commvault.ContentStore cloud accounts plan\" }\n ,\"commvault.contentstore/cloudaccounts/protectiongroups\": { \"SingularDisplayName\": \"Commvault.ContentStore cloud accounts protection group\" }\n ,\"commvault.contentstore/cloudaccounts/protectiongroups/protecteditems\": { \"SingularDisplayName\": \"Commvault.ContentStore cloud accounts protection groups protected item\" }\n ,\"commvault.contentstore/cloudaccounts/storages\": { \"SingularDisplayName\": \"Commvault.ContentStore cloud accounts storage\" }\n ,\"dell.storage/filesystems\": { \"SingularDisplayName\": \"Dell PowerScale\" }\n ,\"dynatrace.observability/monitors\": { \"SingularDisplayName\": \"Dynatrace\" }\n ,\"github.network/networksettings\": { \"SingularDisplayName\": \"GitHub.Network network setting\" }\n ,\"informatica.datamanagement/organizations\": { \"SingularDisplayName\": \"Informatica Organization\" }\n ,\"lambdatest.hyperexecute/organizations\": { \"SingularDisplayName\": \"Azure Native LambdaTest - HyperExecute Cloud Service\" }\n ,\"microsoft.aad/domainservices\": { \"SingularDisplayName\": \"Microsoft Entra Domain Services\" }\n ,\"microsoft.aadiam/diagnosticsettings\": { \"SingularDisplayName\": \"Microsoft.aadiam diagnostic setting\" }\n ,\"microsoft.aadiam/privatelinkforazuread\": { \"SingularDisplayName\": \"Private Link for Microsoft Entra ID\" }\n ,\"microsoft.advisor/advisorscore\": { \"SingularDisplayName\": \"Microsoft.Advisor advisor score\" }\n ,\"microsoft.advisor/assessments\": { \"SingularDisplayName\": \"Microsoft.Advisor assessment\" }\n ,\"microsoft.advisor/configurations\": { \"SingularDisplayName\": \"Microsoft.Advisor configuration\" }\n ,\"microsoft.advisor/generaterecommendations\": { \"SingularDisplayName\": \"Microsoft.Advisor generate recommendation\" }\n ,\"microsoft.advisor/metadata\": { \"SingularDisplayName\": \"Microsoft.Advisor metadata\" }\n ,\"microsoft.advisor/recommendations\": { \"SingularDisplayName\": \"Microsoft.Advisor recommendation\" }\n ,\"microsoft.advisor/recommendations/suppressions\": { \"SingularDisplayName\": \"Microsoft.Advisor recommendations suppression\" }\n ,\"microsoft.advisor/resiliencyreviews\": { \"SingularDisplayName\": \"Microsoft.Advisor resiliency review\" }\n ,\"microsoft.agfoodplatform/farmbeats\": { \"SingularDisplayName\": \"Azure Data Manager for Agriculture\" }\n ,\"microsoft.agfoodplatform/farmbeatsextensiondefinitions\": { \"SingularDisplayName\": \"Microsoft.AgFoodPlatform farm beats extension definition\" }\n ,\"microsoft.agfoodplatform/farmbeatssolutiondefinitions\": { \"SingularDisplayName\": \"Microsoft.AgFoodPlatform farm beats solution definition\" }\n ,\"microsoft.agricultureplatform/agriservices\": { \"SingularDisplayName\": \"Agriculture data solutions\" }\n ,\"microsoft.akshybrid/agentpools\": { \"SingularDisplayName\": \"Microsoft.AksHybrid agent pool\" }\n ,\"microsoft.akshybrid/provisionedclusters\": { \"SingularDisplayName\": \"Microsoft.AksHybrid provisioned cluster\" }\n ,\"microsoft.akshybrid/upgradeprofiles\": { \"SingularDisplayName\": \"Microsoft.AksHybrid upgrade profile\" }\n ,\"microsoft.alertsmanagement/actionrules\": { \"SingularDisplayName\": \"Alert processing rule\" }\n ,\"microsoft.alertsmanagement/alerts\": { \"SingularDisplayName\": \"Microsoft.AlertsManagement alert\" }\n ,\"microsoft.alertsmanagement/alerts/enrichments\": { \"SingularDisplayName\": \"Microsoft.AlertsManagement alerts enrichment\" }\n ,\"microsoft.alertsmanagement/prometheusrulegroups\": { \"SingularDisplayName\": \"Prometheus rule group\" }\n ,\"microsoft.alertsmanagement/smartdetectoralertrules\": { \"SingularDisplayName\": \"Smart detector alert rule\" }\n ,\"microsoft.alertsmanagement/smartgroups\": { \"SingularDisplayName\": \"Microsoft.AlertsManagement smart group\" }\n ,\"microsoft.alertsmanagement/tenantactivitylogalerts\": { \"SingularDisplayName\": \"Microsoft.AlertsManagement tenant activity log alert\" }\n ,\"microsoft.all/arcvirtualmachines\": { \"SingularDisplayName\": \"Azure Arc virtual machine\" }\n ,\"microsoft.all/hcivirtualmachines\": { \"SingularDisplayName\": \"Azure Local Virtual Machine - Azure Arc\" }\n ,\"microsoft.all/virtualmachines\": { \"SingularDisplayName\": \"Virtual machine\" }\n ,\"microsoft.analysisservices/servers\": { \"SingularDisplayName\": \"Analysis Services server\" }\n ,\"microsoft.anybuild/clusters\": { \"SingularDisplayName\": \"AnyBuild cluster\" }\n ,\"microsoft.apicenter/deletedservices\": { \"SingularDisplayName\": \"Microsoft.ApiCenter deleted service\" }\n ,\"microsoft.apicenter/services\": { \"SingularDisplayName\": \"API Center\" }\n ,\"microsoft.apicenter/services/workspaces\": { \"SingularDisplayName\": \"Workspace\" }\n ,\"microsoft.apimanagement/gateways\": { \"SingularDisplayName\": \"API Management gateway\" }\n ,\"microsoft.apimanagement/gateways/configconnections\": { \"SingularDisplayName\": \"Microsoft.ApiManagement gateways config connection\" }\n ,\"microsoft.apimanagement/service\": { \"SingularDisplayName\": \"API Management service\" }\n ,\"microsoft.apimanagement/service/workspaces\": { \"SingularDisplayName\": \"Workspace\" }\n ,\"microsoft.apisecurity/defendersettings\": { \"SingularDisplayName\": \"Microsoft.ApiSecurity defender setting\" }\n ,\"microsoft.app/agents\": { \"SingularDisplayName\": \"SRE Agent\" }\n ,\"microsoft.app/builders\": { \"SingularDisplayName\": \"Microsoft.App builder\" }\n ,\"microsoft.app/builders/builds\": { \"SingularDisplayName\": \"Microsoft.App builders build\" }\n ,\"microsoft.app/connectedenvironments\": { \"SingularDisplayName\": \"Container Apps Connected Environment\" }\n ,\"microsoft.app/containerapps\": { \"SingularDisplayName\": \"Container App\" }\n ,\"microsoft.app/jobs\": { \"SingularDisplayName\": \"Container App Job\" }\n ,\"microsoft.app/logicapps\": { \"SingularDisplayName\": \"Logic app\" }\n ,\"microsoft.app/logicapps/workflows\": { \"SingularDisplayName\": \"Logic app workflow\" }\n ,\"microsoft.app/managedenvironments\": { \"SingularDisplayName\": \"Container Apps Environment\" }\n ,\"microsoft.app/sessionpools\": { \"SingularDisplayName\": \"Container App Session Pool\" }\n ,\"microsoft.app/spaces\": { \"SingularDisplayName\": \"App Space\" }\n ,\"microsoft.appassessment/migrateprojects\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate project\" }\n ,\"microsoft.appassessment/migrateprojects/assessments\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects assessment\" }\n ,\"microsoft.appassessment/migrateprojects/assessments/assessedapplications\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects assessments assessed application\" }\n ,\"microsoft.appassessment/migrateprojects/assessments/assessedmachines\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects assessments assessed machine\" }\n ,\"microsoft.appassessment/migrateprojects/assessments/machinestoassess\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects assessments machines to asses\" }\n ,\"microsoft.appassessment/migrateprojects/sites\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects site\" }\n ,\"microsoft.appassessment/migrateprojects/sites/applianceconfigurations\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects sites appliance configuration\" }\n ,\"microsoft.appcomplianceautomation/reports\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation report\" }\n ,\"microsoft.appcomplianceautomation/reports/evidences\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports evidence\" }\n ,\"microsoft.appcomplianceautomation/reports/scopingconfigurations\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports scoping configuration\" }\n ,\"microsoft.appcomplianceautomation/reports/snapshots\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports snapshot\" }\n ,\"microsoft.appcomplianceautomation/reports/snapshots/controls\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports snapshots control\" }\n ,\"microsoft.appcomplianceautomation/reports/webhooks\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports webhook\" }\n ,\"microsoft.appconfiguration/configurationstores\": { \"SingularDisplayName\": \"App Configuration\" }\n ,\"microsoft.applicationmigration/discoveryhubs\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration discovery hub\" }\n ,\"microsoft.applicationmigration/discoveryhubs/applications\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration discovery hubs application\" }\n ,\"microsoft.applicationmigration/discoveryhubs/applications/members\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration discovery hubs applications member\" }\n ,\"microsoft.applicationmigration/pgsqlsites\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration pgsqlsite\" }\n ,\"microsoft.applicationmigration/pgsqlsites/agents\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration pgsqlsites agent\" }\n ,\"microsoft.applicationmigration/pgsqlsites/pgsqldatabases\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration pgsqlsites pgsqldatabase\" }\n ,\"microsoft.applicationmigration/pgsqlsites/pgsqlinstances\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration pgsqlsites pgsqlinstance\" }\n ,\"microsoft.appplatform/spring\": { \"SingularDisplayName\": \"Azure Spring Apps\" }\n ,\"microsoft.appsecurity/appprotectmanagedrulesetmanifests\": { \"SingularDisplayName\": \"Microsoft.AppSecurity app protect managed rule set manifest\" }\n ,\"microsoft.appsecurity/policies\": { \"SingularDisplayName\": \"App Protect Policy\" }\n ,\"microsoft.arc/all\": { \"SingularDisplayName\": \"Azure Arc enabled resource\" }\n ,\"microsoft.arc/allfairfax\": { \"SingularDisplayName\": \"Azure Arc enabled resource\" }\n ,\"microsoft.arc/kubernetesresources\": { \"SingularDisplayName\": \"Azure Arc Kubernetes cluster\" }\n ,\"microsoft.arc/kubernetesresourcesfairfax\": { \"SingularDisplayName\": \"Azure Arc Kubernetes cluster\" }\n ,\"microsoft.arcnetworking/arcnwloadbalancers\": { \"SingularDisplayName\": \"Microsoft.ArcNetworking arc nw load balancer\" }\n ,\"microsoft.aszlabhardware/labservers\": { \"SingularDisplayName\": \"Microsoft.AszLabHardware labserver\" }\n ,\"microsoft.aszlabhardware/reservations\": { \"SingularDisplayName\": \"Microsoft.AszLabHardware reservation\" }\n ,\"microsoft.aszlabhardware/reservations/servers\": { \"SingularDisplayName\": \"Microsoft.AszLabHardware reservations server\" }\n ,\"microsoft.aszlabhardware/servers\": { \"SingularDisplayName\": \"Microsoft.AszLabHardware server\" }\n ,\"microsoft.attestation/attestationproviders\": { \"SingularDisplayName\": \"Attestation provider\" }\n ,\"microsoft.authorization/accessreviewhistorydefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization access review history definition\" }\n ,\"microsoft.authorization/accessreviewscheduledefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization access review schedule definition\" }\n ,\"microsoft.authorization/accessreviewscheduledefinitions/instances\": { \"SingularDisplayName\": \"Microsoft.Authorization access review schedule definitions instance\" }\n ,\"microsoft.authorization/accessreviewscheduledefinitions/instances/decisions\": { \"SingularDisplayName\": \"Microsoft.Authorization access review schedule definitions instances decision\" }\n ,\"microsoft.authorization/accessreviewschedulesettings\": { \"SingularDisplayName\": \"Microsoft.Authorization access review schedule setting\" }\n ,\"microsoft.authorization/datapolicymanifests\": { \"SingularDisplayName\": \"Microsoft.Authorization data policy manifest\" }\n ,\"microsoft.authorization/denyassignments\": { \"SingularDisplayName\": \"Microsoft.Authorization deny assignment\" }\n ,\"microsoft.authorization/locks\": { \"SingularDisplayName\": \"Microsoft.Authorization lock\" }\n ,\"microsoft.authorization/policyassignments\": { \"SingularDisplayName\": \"Microsoft.Authorization policy assignment\" }\n ,\"microsoft.authorization/policydefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy definition\" }\n ,\"microsoft.authorization/policydefinitions/versions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy definitions version\" }\n ,\"microsoft.authorization/policyexemptions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy exemption\" }\n ,\"microsoft.authorization/policysetdefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy set definition\" }\n ,\"microsoft.authorization/policysetdefinitions/versions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy set definitions version\" }\n ,\"microsoft.authorization/privatelinkassociations\": { \"SingularDisplayName\": \"Microsoft.Authorization private link association\" }\n ,\"microsoft.authorization/provideroperations\": { \"SingularDisplayName\": \"Microsoft.Authorization provider operation\" }\n ,\"microsoft.authorization/resourcemanagementprivatelinks\": { \"SingularDisplayName\": \"Resource management private link\" }\n ,\"microsoft.authorization/roleassignmentapprovals\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment approval\" }\n ,\"microsoft.authorization/roleassignmentapprovals/stages\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment approvals stage\" }\n ,\"microsoft.authorization/roleassignments\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment\" }\n ,\"microsoft.authorization/roleassignmentscheduleinstances\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment schedule instance\" }\n ,\"microsoft.authorization/roleassignmentschedulerequests\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment schedule request\" }\n ,\"microsoft.authorization/roleassignmentschedules\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment schedule\" }\n ,\"microsoft.authorization/roledefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization role definition\" }\n ,\"microsoft.authorization/roleeligibilityscheduleinstances\": { \"SingularDisplayName\": \"Microsoft.Authorization role eligibility schedule instance\" }\n ,\"microsoft.authorization/roleeligibilityschedulerequests\": { \"SingularDisplayName\": \"Microsoft.Authorization role eligibility schedule request\" }\n ,\"microsoft.authorization/roleeligibilityschedules\": { \"SingularDisplayName\": \"Microsoft.Authorization role eligibility schedule\" }\n ,\"microsoft.authorization/rolemanagementalertconfigurations\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alert configuration\" }\n ,\"microsoft.authorization/rolemanagementalertdefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alert definition\" }\n ,\"microsoft.authorization/rolemanagementalertoperations\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alert operation\" }\n ,\"microsoft.authorization/rolemanagementalerts\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alert\" }\n ,\"microsoft.authorization/rolemanagementalerts/alertincidents\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alerts alert incident\" }\n ,\"microsoft.authorization/rolemanagementpolicies\": { \"SingularDisplayName\": \"Microsoft.Authorization role management policy\" }\n ,\"microsoft.authorization/rolemanagementpolicyassignments\": { \"SingularDisplayName\": \"Microsoft.Authorization role management policy assignment\" }\n ,\"microsoft.automanage/bestpractices\": { \"SingularDisplayName\": \"Microsoft.Automanage best practice\" }\n ,\"microsoft.automanage/bestpractices/versions\": { \"SingularDisplayName\": \"Microsoft.Automanage best practices version\" }\n ,\"microsoft.automanage/configurationprofileassignments\": { \"SingularDisplayName\": \"Microsoft.Automanage configuration profile assignment\" }\n ,\"microsoft.automanage/configurationprofileassignments/reports\": { \"SingularDisplayName\": \"Microsoft.Automanage configuration profile assignments report\" }\n ,\"microsoft.automanage/configurationprofiles\": { \"SingularDisplayName\": \"Microsoft.Automanage configuration profile\" }\n ,\"microsoft.automanage/configurationprofiles/versions\": { \"SingularDisplayName\": \"Microsoft.Automanage configuration profiles version\" }\n ,\"microsoft.automanage/serviceprincipals\": { \"SingularDisplayName\": \"ServicePrincipals\" }\n ,\"microsoft.automation/automationaccounts\": { \"SingularDisplayName\": \"Automation account\" }\n ,\"microsoft.automation/automationaccounts/hybridrunbookworkergroups\": { \"SingularDisplayName\": \"Automation hybrid worker group\" }\n ,\"microsoft.automation/automationaccounts/runbooks\": { \"SingularDisplayName\": \"Automation runbook\" }\n ,\"microsoft.autonomousdevelopmentplatform/accounts\": { \"SingularDisplayName\": \"Microsoft.AutonomousDevelopmentPlatform account\" }\n ,\"microsoft.autonomousdevelopmentplatform/accounts/datapools\": { \"SingularDisplayName\": \"Microsoft.AutonomousDevelopmentPlatform accounts data pool\" }\n ,\"microsoft.autonomousdevelopmentplatform/workspaces\": { \"SingularDisplayName\": \"Microsoft.AutonomousDevelopmentPlatform workspace\" }\n ,\"microsoft.avs/privateclouds\": { \"SingularDisplayName\": \"Azure VMware Solution private cloud\" }\n ,\"microsoft.awsconnector/accessanalyzeranalyzers\": { \"SingularDisplayName\": \"Access Analyzer Analyzer\" }\n ,\"microsoft.awsconnector/acmcertificatesummaries\": { \"SingularDisplayName\": \"ACM Certificate Summary\" }\n ,\"microsoft.awsconnector/apigatewayrestapis\": { \"SingularDisplayName\": \"Api Gateway Rest Api\" }\n ,\"microsoft.awsconnector/apigatewaystages\": { \"SingularDisplayName\": \"Api Gateway Stage\" }\n ,\"microsoft.awsconnector/applicationautoscalingscalabletargets\": { \"SingularDisplayName\": \"Application Auto Scaling Scalable Target\" }\n ,\"microsoft.awsconnector/appsyncgraphqlapis\": { \"SingularDisplayName\": \"App Sync Graphql Api\" }\n ,\"microsoft.awsconnector/autoscalingautoscalinggroups\": { \"SingularDisplayName\": \"Auto Scaling Auto Scaling Group\" }\n ,\"microsoft.awsconnector/cloudformationstacks\": { \"SingularDisplayName\": \"Cloud Formation Stack\" }\n ,\"microsoft.awsconnector/cloudformationstacksets\": { \"SingularDisplayName\": \"Cloud Formation Stack Set\" }\n ,\"microsoft.awsconnector/cloudfrontdistributions\": { \"SingularDisplayName\": \"Cloud Front Distribution\" }\n ,\"microsoft.awsconnector/cloudtrailtrails\": { \"SingularDisplayName\": \"Cloud Trail Trail\" }\n ,\"microsoft.awsconnector/cloudwatchalarms\": { \"SingularDisplayName\": \"Cloud Watch Alarm\" }\n ,\"microsoft.awsconnector/codebuildprojects\": { \"SingularDisplayName\": \"Code Build Project\" }\n ,\"microsoft.awsconnector/codebuildsourcecredentialsinfos\": { \"SingularDisplayName\": \"Code Build Source Credentials Info\" }\n ,\"microsoft.awsconnector/configserviceconfigurationrecorders\": { \"SingularDisplayName\": \"Config Service Configuration Recorder\" }\n ,\"microsoft.awsconnector/configserviceconfigurationrecorderstatuses\": { \"SingularDisplayName\": \"Config Service Configuration Recorder Status\" }\n ,\"microsoft.awsconnector/configservicedeliverychannels\": { \"SingularDisplayName\": \"Config Service Delivery Channel\" }\n ,\"microsoft.awsconnector/databasemigrationservicereplicationinstances\": { \"SingularDisplayName\": \"Database Migration Service Replication Instance\" }\n ,\"microsoft.awsconnector/daxclusters\": { \"SingularDisplayName\": \"DAX Cluster\" }\n ,\"microsoft.awsconnector/dynamodbcontinuousbackupsdescriptions\": { \"SingularDisplayName\": \"Dynamo DB Continuous Backups Description\" }\n ,\"microsoft.awsconnector/dynamodbtables\": { \"SingularDisplayName\": \"Dynamo DB Table\" }\n ,\"microsoft.awsconnector/ec2accountattributes\": { \"SingularDisplayName\": \"EC2 Account Attribute\" }\n ,\"microsoft.awsconnector/ec2addresses\": { \"SingularDisplayName\": \"EC2 Address\" }\n ,\"microsoft.awsconnector/ec2flowlogs\": { \"SingularDisplayName\": \"EC2 Flow Log\" }\n ,\"microsoft.awsconnector/ec2images\": { \"SingularDisplayName\": \"EC2 Image\" }\n ,\"microsoft.awsconnector/ec2instances\": { \"SingularDisplayName\": \"Microsoft.AwsConnector ec2 instance\" }\n ,\"microsoft.awsconnector/ec2instancestatuses\": { \"SingularDisplayName\": \"EC2 Instance Status\" }\n ,\"microsoft.awsconnector/ec2ipams\": { \"SingularDisplayName\": \"EC2 Ipam\" }\n ,\"microsoft.awsconnector/ec2keypairs\": { \"SingularDisplayName\": \"EC2 Key Pair\" }\n ,\"microsoft.awsconnector/ec2networkacls\": { \"SingularDisplayName\": \"EC2 Network Acl\" }\n ,\"microsoft.awsconnector/ec2networkinterfaces\": { \"SingularDisplayName\": \"EC2 Network Interface\" }\n ,\"microsoft.awsconnector/ec2routetables\": { \"SingularDisplayName\": \"EC2 Route Table\" }\n ,\"microsoft.awsconnector/ec2securitygroups\": { \"SingularDisplayName\": \"EC2 Security Group\" }\n ,\"microsoft.awsconnector/ec2snapshots\": { \"SingularDisplayName\": \"EC2 Snapshot\" }\n ,\"microsoft.awsconnector/ec2subnets\": { \"SingularDisplayName\": \"EC2 Subnet\" }\n ,\"microsoft.awsconnector/ec2volumes\": { \"SingularDisplayName\": \"EC2 Volume\" }\n ,\"microsoft.awsconnector/ec2vpcendpoints\": { \"SingularDisplayName\": \"EC2 VPCEndpoint\" }\n ,\"microsoft.awsconnector/ec2vpcpeeringconnections\": { \"SingularDisplayName\": \"EC2 VPCPeering Connection\" }\n ,\"microsoft.awsconnector/ec2vpcs\": { \"SingularDisplayName\": \"EC2 VPC\" }\n ,\"microsoft.awsconnector/ecrimagedetails\": { \"SingularDisplayName\": \"ECR Image Detail\" }\n ,\"microsoft.awsconnector/ecrrepositories\": { \"SingularDisplayName\": \"ECR Repository\" }\n ,\"microsoft.awsconnector/ecsclusters\": { \"SingularDisplayName\": \"ECS Cluster\" }\n ,\"microsoft.awsconnector/ecsservices\": { \"SingularDisplayName\": \"ECS Service\" }\n ,\"microsoft.awsconnector/ecstaskdefinitions\": { \"SingularDisplayName\": \"ECS Task Definition\" }\n ,\"microsoft.awsconnector/efsfilesystems\": { \"SingularDisplayName\": \"EFS File System\" }\n ,\"microsoft.awsconnector/efsmounttargets\": { \"SingularDisplayName\": \"EFS Mount Target\" }\n ,\"microsoft.awsconnector/eksnodegroups\": { \"SingularDisplayName\": \"EKS Nodegroup\" }\n ,\"microsoft.awsconnector/elasticbeanstalkapplications\": { \"SingularDisplayName\": \"Elastic Beanstalk Application\" }\n ,\"microsoft.awsconnector/elasticbeanstalkconfigurationtemplates\": { \"SingularDisplayName\": \"Elastic Beanstalk Configuration Template\" }\n ,\"microsoft.awsconnector/elasticbeanstalkenvironments\": { \"SingularDisplayName\": \"Elastic Beanstalk Environment\" }\n ,\"microsoft.awsconnector/elasticloadbalancingv2listeners\": { \"SingularDisplayName\": \"Elastic Load Balancing V2 Listener\" }\n ,\"microsoft.awsconnector/elasticloadbalancingv2loadbalancers\": { \"SingularDisplayName\": \"Elastic Load Balancing V2 Load Balancer\" }\n ,\"microsoft.awsconnector/elasticloadbalancingv2targetgroups\": { \"SingularDisplayName\": \"Elastic Load Balancing V2 Target Group\" }\n ,\"microsoft.awsconnector/elasticloadbalancingv2targethealthdescriptions\": { \"SingularDisplayName\": \"Elastic Load Balancing v2 Target Health Description\" }\n ,\"microsoft.awsconnector/elasticsearchdomains\": { \"SingularDisplayName\": \"Elasticsearch Domain\" }\n ,\"microsoft.awsconnector/emrclusters\": { \"SingularDisplayName\": \"EMR Cluster\" }\n ,\"microsoft.awsconnector/guarddutydetectors\": { \"SingularDisplayName\": \"Guard Duty Detector\" }\n ,\"microsoft.awsconnector/iamaccesskeylastuseds\": { \"SingularDisplayName\": \"IAM Access Key Last Used\" }\n ,\"microsoft.awsconnector/iamaccesskeymetadata\": { \"SingularDisplayName\": \"IAM Access Key Metadata\" }\n ,\"microsoft.awsconnector/iamgroups\": { \"SingularDisplayName\": \"IAM Group\" }\n ,\"microsoft.awsconnector/iaminstanceprofiles\": { \"SingularDisplayName\": \"IAM Instance Profile\" }\n ,\"microsoft.awsconnector/iammanagedpolicies\": { \"SingularDisplayName\": \"IAM Managed Policy\" }\n ,\"microsoft.awsconnector/iammfadevices\": { \"SingularDisplayName\": \"IAM MFADevice\" }\n ,\"microsoft.awsconnector/iampasswordpolicies\": { \"SingularDisplayName\": \"IAM Password Policy\" }\n ,\"microsoft.awsconnector/iampolicyversions\": { \"SingularDisplayName\": \"IAM Policy Version\" }\n ,\"microsoft.awsconnector/iamroles\": { \"SingularDisplayName\": \"IAM Role\" }\n ,\"microsoft.awsconnector/iamservercertificates\": { \"SingularDisplayName\": \"IAM Server Certificate\" }\n ,\"microsoft.awsconnector/iamuserpolicies\": { \"SingularDisplayName\": \"IAM User Policy\" }\n ,\"microsoft.awsconnector/iamvirtualmfadevices\": { \"SingularDisplayName\": \"IAM Virtual MFADevice\" }\n ,\"microsoft.awsconnector/kmsaliases\": { \"SingularDisplayName\": \"KMS Alias\" }\n ,\"microsoft.awsconnector/kmskeys\": { \"SingularDisplayName\": \"KMS Key\" }\n ,\"microsoft.awsconnector/lambdafunctioncodelocations\": { \"SingularDisplayName\": \"Lambda Function Code Location\" }\n ,\"microsoft.awsconnector/lambdafunctionconfigurations\": { \"SingularDisplayName\": \"Microsoft.AwsConnector lambda function configuration\" }\n ,\"microsoft.awsconnector/lambdafunctions\": { \"SingularDisplayName\": \"Lambda Function\" }\n ,\"microsoft.awsconnector/licensemanagerlicenses\": { \"SingularDisplayName\": \"License Manager License\" }\n ,\"microsoft.awsconnector/lightsailbuckets\": { \"SingularDisplayName\": \"Lightsail Bucket\" }\n ,\"microsoft.awsconnector/lightsailinstances\": { \"SingularDisplayName\": \"Lightsail Instance\" }\n ,\"microsoft.awsconnector/logsloggroups\": { \"SingularDisplayName\": \"Logs Log Group\" }\n ,\"microsoft.awsconnector/logslogstreams\": { \"SingularDisplayName\": \"Logs Log Stream\" }\n ,\"microsoft.awsconnector/logsmetricfilters\": { \"SingularDisplayName\": \"Logs Metric Filter\" }\n ,\"microsoft.awsconnector/logssubscriptionfilters\": { \"SingularDisplayName\": \"Logs Subscription Filter\" }\n ,\"microsoft.awsconnector/macie2jobsummaries\": { \"SingularDisplayName\": \"Macie2 Job Summary\" }\n ,\"microsoft.awsconnector/macieallowlists\": { \"SingularDisplayName\": \"Macie Allow List\" }\n ,\"microsoft.awsconnector/networkfirewallfirewallpolicies\": { \"SingularDisplayName\": \"Network Firewall Firewall Policy\" }\n ,\"microsoft.awsconnector/networkfirewallfirewalls\": { \"SingularDisplayName\": \"Network Firewall Firewall\" }\n ,\"microsoft.awsconnector/networkfirewallrulegroups\": { \"SingularDisplayName\": \"Network Firewall Rule Group\" }\n ,\"microsoft.awsconnector/opensearchdomainstatuses\": { \"SingularDisplayName\": \"Open Search Domain Status\" }\n ,\"microsoft.awsconnector/opensearchservicedomains\": { \"SingularDisplayName\": \"Open Search Service Domain\" }\n ,\"microsoft.awsconnector/organizationsaccounts\": { \"SingularDisplayName\": \"Organizations Account\" }\n ,\"microsoft.awsconnector/organizationsorganizations\": { \"SingularDisplayName\": \"Organizations Organization\" }\n ,\"microsoft.awsconnector/rdsdbclusters\": { \"SingularDisplayName\": \"RDS DBCluster\" }\n ,\"microsoft.awsconnector/rdsdbinstances\": { \"SingularDisplayName\": \"RDS DBInstance\" }\n ,\"microsoft.awsconnector/rdsdbsnapshotattributesresults\": { \"SingularDisplayName\": \"RDS DBSnapshot Attributes Result\" }\n ,\"microsoft.awsconnector/rdsdbsnapshots\": { \"SingularDisplayName\": \"RDS DBSnapshot\" }\n ,\"microsoft.awsconnector/rdseventsubscriptions\": { \"SingularDisplayName\": \"RDS Event Subscription\" }\n ,\"microsoft.awsconnector/rdsexporttasks\": { \"SingularDisplayName\": \"RDS Export Task\" }\n ,\"microsoft.awsconnector/redshiftclusterparametergroups\": { \"SingularDisplayName\": \"Redshift Cluster Parameter Group\" }\n ,\"microsoft.awsconnector/redshiftclusters\": { \"SingularDisplayName\": \"Redshift Cluster\" }\n ,\"microsoft.awsconnector/route53domainsdomainsummaries\": { \"SingularDisplayName\": \"Route 53 Domains Domain Summary\" }\n ,\"microsoft.awsconnector/route53hostedzones\": { \"SingularDisplayName\": \"Route53 Hosted Zone\" }\n ,\"microsoft.awsconnector/route53resourcerecordsets\": { \"SingularDisplayName\": \"Route 53 Resource Record Set\" }\n ,\"microsoft.awsconnector/s3accesscontrolpolicies\": { \"SingularDisplayName\": \"S3 Access Control Policy\" }\n ,\"microsoft.awsconnector/s3accesspoints\": { \"SingularDisplayName\": \"S3 Access Point\" }\n ,\"microsoft.awsconnector/s3bucketpolicies\": { \"SingularDisplayName\": \"S3 Bucket Policy\" }\n ,\"microsoft.awsconnector/s3buckets\": { \"SingularDisplayName\": \"S3 Bucket\" }\n ,\"microsoft.awsconnector/s3controlmultiregionaccesspointpolicydocuments\": { \"SingularDisplayName\": \"S3 Control Multi Region Access Point Policy Document\" }\n ,\"microsoft.awsconnector/sagemakerapps\": { \"SingularDisplayName\": \"Sage Maker App\" }\n ,\"microsoft.awsconnector/sagemakerdevices\": { \"SingularDisplayName\": \"Sage Maker Device\" }\n ,\"microsoft.awsconnector/sagemakerimages\": { \"SingularDisplayName\": \"Sage Maker Image\" }\n ,\"microsoft.awsconnector/sagemakernotebookinstancesummaries\": { \"SingularDisplayName\": \"Sage Maker Notebook Instance Summary\" }\n ,\"microsoft.awsconnector/secretsmanagerresourcepolicies\": { \"SingularDisplayName\": \"Secrets Manager Resource Policy\" }\n ,\"microsoft.awsconnector/secretsmanagersecrets\": { \"SingularDisplayName\": \"Secrets Manager Secret\" }\n ,\"microsoft.awsconnector/snssubscriptions\": { \"SingularDisplayName\": \"SNS Subscription\" }\n ,\"microsoft.awsconnector/snstopics\": { \"SingularDisplayName\": \"SNS Topic\" }\n ,\"microsoft.awsconnector/sqsqueues\": { \"SingularDisplayName\": \"SQS Queue\" }\n ,\"microsoft.awsconnector/ssminstanceinformations\": { \"SingularDisplayName\": \"SSM Instance Information\" }\n ,\"microsoft.awsconnector/ssmparameters\": { \"SingularDisplayName\": \"SSM Parameter\" }\n ,\"microsoft.awsconnector/ssmresourcecompliancesummaryitems\": { \"SingularDisplayName\": \"SSM Resource Compliance Summary Item\" }\n ,\"microsoft.awsconnector/wafv2ipsets\": { \"SingularDisplayName\": \"WAFv2 IPSet\" }\n ,\"microsoft.awsconnector/wafv2loggingconfigurations\": { \"SingularDisplayName\": \"WAFv2 Logging Configuration\" }\n ,\"microsoft.awsconnector/wafv2webaclassociations\": { \"SingularDisplayName\": \"WAFv2 Web ACLAssociation\" }\n ,\"microsoft.awsconnector/wafwebaclsummaries\": { \"SingularDisplayName\": \"WAF Web ACLSummary\" }\n ,\"microsoft.azureactivedirectory/b2cdirectories\": { \"SingularDisplayName\": \"B2C tenant\" }\n ,\"microsoft.azureactivedirectory/ciamdirectories\": { \"SingularDisplayName\": \"External Configuration Tenant\" }\n ,\"microsoft.azureactivedirectory/guestusages\": { \"SingularDisplayName\": \"Guest Usage\" }\n ,\"microsoft.azurearcdata/datacontrollers\": { \"SingularDisplayName\": \"Azure Arc data controller\" }\n ,\"microsoft.azurearcdata/mysqlserver\": { \"SingularDisplayName\": \"MySql Server - Azure Arc\" }\n ,\"microsoft.azurearcdata/postgresinstances\": { \"SingularDisplayName\": \"PostgreSQL server ? Azure Arc\" }\n ,\"microsoft.azurearcdata/postgressqlserver\": { \"SingularDisplayName\": \"PostgresSql Server - Azure Arc\" }\n ,\"microsoft.azurearcdata/sqlmanagedinstances\": { \"SingularDisplayName\": \"SQL managed instance - Azure Arc\" }\n ,\"microsoft.azurearcdata/sqlserveresulicenses\": { \"SingularDisplayName\": \"SQL Server ESU license\" }\n ,\"microsoft.azurearcdata/sqlserverinstances\": { \"SingularDisplayName\": \"SQL Server - Azure Arc\" }\n ,\"microsoft.azurearcdata/sqlserverinstances/databases\": { \"SingularDisplayName\": \"SQL Server database - Azure Arc\" }\n ,\"microsoft.azurearcdata/sqlserverlicenses\": { \"SingularDisplayName\": \"SQL Server License\" }\n ,\"microsoft.azurebusinesscontinuity/deletedunifiedprotecteditems\": { \"SingularDisplayName\": \"Microsoft.AzureBusinessContinuity deleted unified protected item\" }\n ,\"microsoft.azurebusinesscontinuity/unifiedprotecteditems\": { \"SingularDisplayName\": \"Microsoft.AzureBusinessContinuity unified protected item\" }\n ,\"microsoft.azurecis/aadapplications\": { \"SingularDisplayName\": \"Microsoft.AzureCis AAD application\" }\n ,\"microsoft.azurecis/addressrecords\": { \"SingularDisplayName\": \"Microsoft.AzureCis address record\" }\n ,\"microsoft.azurecis/autopilotenvironments\": { \"SingularDisplayName\": \"Microsoft.AzureCis autopilot environment\" }\n ,\"microsoft.azurecis/autopilotmachinefunctions\": { \"SingularDisplayName\": \"Microsoft.AzureCis autopilot machine function\" }\n ,\"microsoft.azurecis/autopilotsoftwareloadbalancevirtualips\": { \"SingularDisplayName\": \"Microsoft.AzureCis auto pilot software load balance virtual IP\" }\n ,\"microsoft.azurecis/azcopies\": { \"SingularDisplayName\": \"Microsoft.AzureCis az copy\" }\n ,\"microsoft.azurecis/canonicalnamerecords\": { \"SingularDisplayName\": \"Microsoft.AzureCis canonical name record\" }\n ,\"microsoft.azurecis/dsmsallowlists\": { \"SingularDisplayName\": \"Microsoft.AzureCis ds msallowlist\" }\n ,\"microsoft.azurecis/dsmscertificates\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsms certificate\" }\n ,\"microsoft.azurecis/dsmsrootfolders\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsms root folder\" }\n ,\"microsoft.azurecis/dstsapplications\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsts application\" }\n ,\"microsoft.azurecis/dstsserviceaccounts\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsts service account\" }\n ,\"microsoft.azurecis/dstsserviceclientidentities\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsts service client identity\" }\n ,\"microsoft.azurecis/genericgenevaactions\": { \"SingularDisplayName\": \"Microsoft.AzureCis generic geneva action\" }\n ,\"microsoft.azurecis/plannedquotas\": { \"SingularDisplayName\": \"Microsoft.AzureCis planned quota\" }\n ,\"microsoft.azurecis/pointerrecords\": { \"SingularDisplayName\": \"Microsoft.AzureCis pointer record\" }\n ,\"microsoft.azurecis/publishconfigvalues\": { \"SingularDisplayName\": \"Microsoft.AzureCis publish config value\" }\n ,\"microsoft.azurecis/pushagentv2accounts\": { \"SingularDisplayName\": \"Microsoft.AzureCis push agent v2 account\" }\n ,\"microsoft.azurecis/servicerecords\": { \"SingularDisplayName\": \"Microsoft.AzureCis service record\" }\n ,\"microsoft.azurecis/sharedconfigvalues\": { \"SingularDisplayName\": \"Microsoft.AzureCis shared config value\" }\n ,\"microsoft.azurecloudmetadata/clouds\": { \"SingularDisplayName\": \"Microsoft.AzureCloudMetadata cloud\" }\n ,\"microsoft.azurecloudmetadata/clouds/geographies\": { \"SingularDisplayName\": \"Microsoft.AzureCloudMetadata clouds geography\" }\n ,\"microsoft.azurecloudmetadata/clouds/geographies/regions\": { \"SingularDisplayName\": \"Microsoft.AzureCloudMetadata clouds geographies region\" }\n ,\"microsoft.azuredatatransfer/connections\": { \"SingularDisplayName\": \"Connection\" }\n ,\"microsoft.azuredatatransfer/connections/flows\": { \"SingularDisplayName\": \"Flow\" }\n ,\"microsoft.azuredatatransfer/pipelines\": { \"SingularDisplayName\": \"Pipeline\" }\n ,\"microsoft.azurefleet/fleets\": { \"SingularDisplayName\": \"Compute Fleet\" }\n ,\"microsoft.azurefleet/fleetscomputehub\": { \"SingularDisplayName\": \"Compute Fleet\" }\n ,\"microsoft.azureimagetestingforlinux/jobs\": { \"SingularDisplayName\": \"Microsoft.AzureImageTestingForLinux job\" }\n ,\"microsoft.azureimagetestingforlinux/jobtemplates\": { \"SingularDisplayName\": \"Microsoft.AzureImageTestingForLinux job template\" }\n ,\"microsoft.azurelargeinstance/azurelargeinstances\": { \"SingularDisplayName\": \"Azure Large Instance\" }\n ,\"microsoft.azurelargeinstance/azurelargestorageinstances\": { \"SingularDisplayName\": \"Microsoft.AzureLargeInstance Azure large storage instance\" }\n ,\"microsoft.azurepercept/accounts\": { \"SingularDisplayName\": \"Microsoft.AzurePercept account\" }\n ,\"microsoft.azurepercept/accounts/devices\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts device\" }\n ,\"microsoft.azurepercept/accounts/devices/sensors\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts devices sensor\" }\n ,\"microsoft.azurepercept/accounts/sensors\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts sensor\" }\n ,\"microsoft.azurepercept/accounts/solutioninstances\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts solutioninstance\" }\n ,\"microsoft.azurepercept/accounts/solutions\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts solution\" }\n ,\"microsoft.azurepercept/accounts/targets\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts target\" }\n ,\"microsoft.azureplaywrightservice/accounts\": { \"SingularDisplayName\": \"Playwright Testing\" }\n ,\"microsoft.azurescan/scanningaccounts\": { \"SingularDisplayName\": \"ESRP Scan\" }\n ,\"microsoft.azuresphere/catalogs\": { \"SingularDisplayName\": \"Azure Sphere Catalog\" }\n ,\"microsoft.azurespherev2/catalogs\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalog\" }\n ,\"microsoft.azurespherev2/catalogs/artifacts\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs artifact\" }\n ,\"microsoft.azurespherev2/catalogs/certificates\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs certificate\" }\n ,\"microsoft.azurespherev2/catalogs/deviceregistrations\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs device registration\" }\n ,\"microsoft.azurespherev2/catalogs/provisioningpackages\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs provisioning package\" }\n ,\"microsoft.azurespherev2/catalogs/syndicationchannels\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs syndication channel\" }\n ,\"microsoft.azurespherev2/catalogs/syndicationchannels/deployments\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs syndication channels deployment\" }\n ,\"microsoft.azurespherev2/catalogs/updatepackages\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs update package\" }\n ,\"microsoft.azurestack/cloudmanifestfiles\": { \"SingularDisplayName\": \"Microsoft.AzureStack cloud manifest file\" }\n ,\"microsoft.azurestack/linkedsubscriptions\": { \"SingularDisplayName\": \"Microsoft.AzureStack linked subscription\" }\n ,\"microsoft.azurestack/registrations\": { \"SingularDisplayName\": \"Microsoft.AzureStack registration\" }\n ,\"microsoft.azurestack/registrations/customersubscriptions\": { \"SingularDisplayName\": \"Microsoft.AzureStack registrations customer subscription\" }\n ,\"microsoft.azurestack/registrations/products\": { \"SingularDisplayName\": \"Microsoft.AzureStack registrations product\" }\n ,\"microsoft.azurestackhci/clusters\": { \"SingularDisplayName\": \"Azure Local\" }\n ,\"microsoft.azurestackhci/clusters/updates/updateruns\": { \"SingularDisplayName\": \"Azure Local\" }\n ,\"microsoft.azurestackhci/clusters/updatesummaries\": { \"SingularDisplayName\": \"Azure Local\" }\n ,\"microsoft.azurestackhci/devicepools\": { \"SingularDisplayName\": \"Azure Stack\" }\n ,\"microsoft.azurestackhci/edgedevices\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI edge device\" }\n ,\"microsoft.azurestackhci/edgedevices/jobs\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI edge devices job\" }\n ,\"microsoft.azurestackhci/edgemachines\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI edge machine\" }\n ,\"microsoft.azurestackhci/edgemachines/jobs\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI edge machines job\" }\n ,\"microsoft.azurestackhci/edgenodepools\": { \"SingularDisplayName\": \"Azure Stack\" }\n ,\"microsoft.azurestackhci/galleryimages\": { \"SingularDisplayName\": \"Azure Local Gallery image\" }\n ,\"microsoft.azurestackhci/logicalnetworks\": { \"SingularDisplayName\": \"Azure Local Logical network\" }\n ,\"microsoft.azurestackhci/marketplacegalleryimages\": { \"SingularDisplayName\": \"Azure Local Marketplace Gallery image\" }\n ,\"microsoft.azurestackhci/networkinterfaces\": { \"SingularDisplayName\": \"Azure Local VM Network Interface\" }\n ,\"microsoft.azurestackhci/networksecuritygroups\": { \"SingularDisplayName\": \"Azure Local Network Security Group\" }\n ,\"microsoft.azurestackhci/networksecuritygroups/securityrules\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI network security groups security rule\" }\n ,\"microsoft.azurestackhci/storagecontainers\": { \"SingularDisplayName\": \"Azure Local Storage path\" }\n ,\"microsoft.azurestackhci/virtualharddisks\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual hard disk\" }\n ,\"microsoft.azurestackhci/virtualmachineinstances\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual machine instance\" }\n ,\"microsoft.azurestackhci/virtualmachineinstances/guestagents\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual machine instances guest agent\" }\n ,\"microsoft.azurestackhci/virtualmachineinstances/hybrididentitymetadata\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual machine instances hybrid identity metadata\" }\n ,\"microsoft.azurestackhci/virtualmachines\": { \"SingularDisplayName\": \"Azure Local virtual machine - Azure Arc\" }\n ,\"microsoft.azurestackhci/virtualnetworks\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual network\" }\n ,\"microsoft.backupsolutions/vmwareapplications\": { \"SingularDisplayName\": \"Microsoft.BackupSolutions vmware application\" }\n ,\"microsoft.bakeryhybrid/pies\": { \"SingularDisplayName\": \"Microsoft.BakeryHybrid py\" }\n ,\"microsoft.bakeryhybrid/pies/nestedresourcetype\": { \"SingularDisplayName\": \"Microsoft.BakeryHybrid pies nested resource type\" }\n ,\"microsoft.baremetal/baremetalconnections\": { \"SingularDisplayName\": \"Microsoft.BareMetal bare metal connection\" }\n ,\"microsoft.baremetal/crayservers\": { \"SingularDisplayName\": \"Cray Server\" }\n ,\"microsoft.baremetal/monitoringservers\": { \"SingularDisplayName\": \"Monitoring Server\" }\n ,\"microsoft.baremetal/peeringsettings\": { \"SingularDisplayName\": \"Microsoft.BareMetal peering setting\" }\n ,\"microsoft.baremetalinfrastructure/baremetalinstances\": { \"SingularDisplayName\": \"BareMetal Instance\" }\n ,\"microsoft.baremetalinfrastructure/baremetalstorageinstances\": { \"SingularDisplayName\": \"Microsoft.BareMetalInfrastructure bare metal storage instance\" }\n ,\"microsoft.batch/batchaccounts\": { \"SingularDisplayName\": \"Batch account\" }\n ,\"microsoft.billing/billingaccounts\": { \"SingularDisplayName\": \"Microsoft.Billing billing account\" }\n ,\"microsoft.billing/billingaccounts/agreements\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts agreement\" }\n ,\"microsoft.billing/billingaccounts/associatedtenants\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts associated tenant\" }\n ,\"microsoft.billing/billingaccounts/availablebalance\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts available balance\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profile\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/availablebalance\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles available balance\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles billing role definition\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles billing subscription\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/customers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles customer\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/customers/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles customers billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/customers/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles customers billing role definition\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/customers/transfers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles customers transfer\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/instructions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles instruction\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoices\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice section\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections billing role definition\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections billing subscription\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/products\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections product\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/transfers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections transfer\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/paymentmethodlinks\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles payment method link\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/policies\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles policy\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/transactions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles transaction\" }\n ,\"microsoft.billing/billingaccounts/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing role definition\" }\n ,\"microsoft.billing/billingaccounts/billingsubscriptionaliases\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing subscription aliase\" }\n ,\"microsoft.billing/billingaccounts/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing subscription\" }\n ,\"microsoft.billing/billingaccounts/billingsubscriptions/invoices\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing subscriptions invoice\" }\n ,\"microsoft.billing/billingaccounts/customers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts customer\" }\n ,\"microsoft.billing/billingaccounts/customers/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts customers billing subscription\" }\n ,\"microsoft.billing/billingaccounts/customers/policies\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts customers policy\" }\n ,\"microsoft.billing/billingaccounts/customers/products\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts customers product\" }\n ,\"microsoft.billing/billingaccounts/departments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts department\" }\n ,\"microsoft.billing/billingaccounts/departments/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts departments billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/departments/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts departments billing role definition\" }\n ,\"microsoft.billing/billingaccounts/departments/enrollmentaccounts\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts departments enrollment account\" }\n ,\"microsoft.billing/billingaccounts/enrollmentaccounts\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts enrollment account\" }\n ,\"microsoft.billing/billingaccounts/enrollmentaccounts/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts enrollment accounts billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/enrollmentaccounts/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts enrollment accounts billing role definition\" }\n ,\"microsoft.billing/billingaccounts/incentiveschedules\": { \"SingularDisplayName\": \"Incentive Schedule\" }\n ,\"microsoft.billing/billingaccounts/incentiveschedules/milestones\": { \"SingularDisplayName\": \"Milestone\" }\n ,\"microsoft.billing/billingaccounts/invoices\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice\" }\n ,\"microsoft.billing/billingaccounts/invoicesections\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice section\" }\n ,\"microsoft.billing/billingaccounts/invoicesections/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice sections billing subscription\" }\n ,\"microsoft.billing/billingaccounts/invoicesections/products\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice sections product\" }\n ,\"microsoft.billing/billingaccounts/invoicesections/transfers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice sections transfer\" }\n ,\"microsoft.billing/billingaccounts/lineofcredit\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts line of credit\" }\n ,\"microsoft.billing/billingaccounts/migrations\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts migration\" }\n ,\"microsoft.billing/billingaccounts/paymentmethods\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts payment method\" }\n ,\"microsoft.billing/billingaccounts/policies\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts policy\" }\n ,\"microsoft.billing/billingaccounts/products\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts product\" }\n ,\"microsoft.billing/billingaccounts/reservationorders\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts reservation order\" }\n ,\"microsoft.billing/billingaccounts/reservationorders/reservations\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts reservation orders reservation\" }\n ,\"microsoft.billing/billingaccounts/savingsplanorders\": { \"SingularDisplayName\": \"Savings plan order\" }\n ,\"microsoft.billing/billingaccounts/savingsplanorders/savingsplans\": { \"SingularDisplayName\": \"Savings plan\" }\n ,\"microsoft.billing/billingperiods\": { \"SingularDisplayName\": \"Microsoft.Billing billing period\" }\n ,\"microsoft.billing/billingproperty\": { \"SingularDisplayName\": \"Microsoft.Billing billing property\" }\n ,\"microsoft.billing/billingrequests\": { \"SingularDisplayName\": \"Microsoft.Billing billing request\" }\n ,\"microsoft.billing/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing role assignment\" }\n ,\"microsoft.billing/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing role definition\" }\n ,\"microsoft.billing/enrollmentaccounts\": { \"SingularDisplayName\": \"Microsoft.Billing enrollment account\" }\n ,\"microsoft.billing/paymentmethods\": { \"SingularDisplayName\": \"Microsoft.Billing payment method\" }\n ,\"microsoft.billing/policies\": { \"SingularDisplayName\": \"Microsoft.Billing policy\" }\n ,\"microsoft.billing/promotions\": { \"SingularDisplayName\": \"Microsoft.Billing promotion\" }\n ,\"microsoft.billing/transfers\": { \"SingularDisplayName\": \"Microsoft.Billing transfer\" }\n ,\"microsoft.billingbenefits/credits\": { \"SingularDisplayName\": \"Credit\" }\n ,\"microsoft.billingbenefits/discounts\": { \"SingularDisplayName\": \"Discount\" }\n ,\"microsoft.billingbenefits/incentiveschedules\": { \"SingularDisplayName\": \"Incentive Schedule\" }\n ,\"microsoft.billingbenefits/incentiveschedules/milestones\": { \"SingularDisplayName\": \"Milestone\" }\n ,\"microsoft.billingbenefits/maccs\": { \"SingularDisplayName\": \"Microsoft Azure Consumption Commitment\" }\n ,\"microsoft.billingbenefits/reservationorderaliases\": { \"SingularDisplayName\": \"Microsoft.BillingBenefits reservation order aliase\" }\n ,\"microsoft.billingbenefits/savingsplanorderaliases\": { \"SingularDisplayName\": \"Microsoft.BillingBenefits savings plan order aliase\" }\n ,\"microsoft.billingbenefits/savingsplanorders\": { \"SingularDisplayName\": \"Savings plan order\" }\n ,\"microsoft.billingbenefits/savingsplanorders/savingsplans\": { \"SingularDisplayName\": \"Savings plan\" }\n ,\"microsoft.bing/accounts\": { \"SingularDisplayName\": \"Bing Resource\" }\n ,\"microsoft.blockchain/blockchainmembers\": { \"SingularDisplayName\": \"Microsoft.Blockchain blockchain member\" }\n ,\"microsoft.blockchain/blockchainmembers/transactionnodes\": { \"SingularDisplayName\": \"Microsoft.Blockchain blockchain members transaction node\" }\n ,\"microsoft.blockchaintokens/tokenservices\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token service\" }\n ,\"microsoft.blockchaintokens/tokenservices/blockchainnetworks\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token services blockchain network\" }\n ,\"microsoft.blockchaintokens/tokenservices/groups\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token services group\" }\n ,\"microsoft.blockchaintokens/tokenservices/groups/accounts\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token services groups account\" }\n ,\"microsoft.blockchaintokens/tokenservices/tokentemplates\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token services token template\" }\n ,\"microsoft.bluefin/instances\": { \"SingularDisplayName\": \"Microsoft.Bluefin instance\" }\n ,\"microsoft.bluefin/instances/datasets\": { \"SingularDisplayName\": \"Microsoft.Bluefin instances dataset\" }\n ,\"microsoft.bluefin/instances/pipelines\": { \"SingularDisplayName\": \"Microsoft.Bluefin instances pipeline\" }\n ,\"microsoft.blueprint/blueprintassignments\": { \"SingularDisplayName\": \"Microsoft.Blueprint blueprint assignment\" }\n ,\"microsoft.blueprint/blueprints\": { \"SingularDisplayName\": \"Microsoft.Blueprint blueprint\" }\n ,\"microsoft.blueprint/blueprints/artifacts\": { \"SingularDisplayName\": \"Microsoft.Blueprint blueprints artifact\" }\n ,\"microsoft.blueprint/blueprints/versions\": { \"SingularDisplayName\": \"Microsoft.Blueprint blueprints version\" }\n ,\"microsoft.botservice/botservices\": { \"SingularDisplayName\": \"Bot Service\" }\n ,\"microsoft.cache/redis\": { \"SingularDisplayName\": \"Redis cache\" }\n ,\"microsoft.cache/redisenterprise\": { \"SingularDisplayName\": \"Azure Managed Redis\" }\n ,\"microsoft.cache/redisenterprise/databases\": { \"SingularDisplayName\": \"Redis Enterprise database\" }\n ,\"microsoft.capacity/reservationorders\": { \"SingularDisplayName\": \"Reservation order\" }\n ,\"microsoft.capacity/reservationorders/reservations\": { \"SingularDisplayName\": \"Reservation\" }\n ,\"microsoft.cascade/sites\": { \"SingularDisplayName\": \"Microsoft.Cascade site\" }\n ,\"microsoft.cdn/cdnwebapplicationfirewallpolicies\": { \"SingularDisplayName\": \"Content Delivery Network WAF policy\" }\n ,\"microsoft.cdn/edgeactions\": { \"SingularDisplayName\": \"Edge Action\" }\n ,\"microsoft.cdn/profiles\": { \"SingularDisplayName\": \"Front Door and CDN profile\" }\n ,\"microsoft.cdn/profiles/afdendpoints\": { \"SingularDisplayName\": \"Endpoint\" }\n ,\"microsoft.cdn/profiles/afdendpoints/routes\": { \"SingularDisplayName\": \"Route\" }\n ,\"microsoft.cdn/profiles/customdomains\": { \"SingularDisplayName\": \"Custom domain\" }\n ,\"microsoft.cdn/profiles/endpoints\": { \"SingularDisplayName\": \"CDN endpoint\" }\n ,\"microsoft.cdn/profiles/endpoints/customdomains\": { \"SingularDisplayName\": \"CDN custom domain\" }\n ,\"microsoft.cdn/profiles/endpoints/origins\": { \"SingularDisplayName\": \"CDN origin\" }\n ,\"microsoft.cdn/profiles/origingroups\": { \"SingularDisplayName\": \"Origin group\" }\n ,\"microsoft.cdn/profiles/origingroups/origins\": { \"SingularDisplayName\": \"Origin\" }\n ,\"microsoft.cdn/profiles/rulesets\": { \"SingularDisplayName\": \"Rule set\" }\n ,\"microsoft.cdn/profiles/rulesets/rules\": { \"SingularDisplayName\": \"Rule\" }\n ,\"microsoft.cdn/profiles/secrets\": { \"SingularDisplayName\": \"Secret\" }\n ,\"microsoft.cdn/profiles/securitypolicies\": { \"SingularDisplayName\": \"Security policy\" }\n ,\"microsoft.certificateregistration/certificateorders\": { \"SingularDisplayName\": \"App Service certificate\" }\n ,\"microsoft.certify/testsuites\": { \"SingularDisplayName\": \"Microsoft.Certify test suite\" }\n ,\"microsoft.certify/validationjobs\": { \"SingularDisplayName\": \"Microsoft.Certify validation job\" }\n ,\"microsoft.changeanalysis/profile\": { \"SingularDisplayName\": \"Microsoft.ChangeAnalysis profile\" }\n ,\"microsoft.changesafety/changestates\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety change state\" }\n ,\"microsoft.changesafety/changestates/stageprogressions\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety change states stage progression\" }\n ,\"microsoft.changesafety/stagemaps\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety stage map\" }\n ,\"microsoft.changesafety/validations\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety validation\" }\n ,\"microsoft.changesafety/validators\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety validator\" }\n ,\"microsoft.changesafety/validators/versions\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety validators version\" }\n ,\"microsoft.chaos/experiments\": { \"SingularDisplayName\": \"Chaos Experiment\" }\n ,\"microsoft.chaos/privateaccesses\": { \"SingularDisplayName\": \"Agent Private Access\" }\n ,\"microsoft.chaos/targets\": { \"SingularDisplayName\": \"Microsoft.Chaos target\" }\n ,\"microsoft.chaos/targets/capabilities\": { \"SingularDisplayName\": \"Microsoft.Chaos targets capability\" }\n ,\"microsoft.classiccompute/domainnames\": { \"SingularDisplayName\": \"Cloud service (classic)\" }\n ,\"microsoft.classiccompute/domainnames/slots/roles\": { \"SingularDisplayName\": \"Cloud service role (classic)\" }\n ,\"microsoft.classiccompute/virtualmachines\": { \"SingularDisplayName\": \"Virtual machine (classic)\" }\n ,\"microsoft.classicnetwork/networksecuritygroups\": { \"SingularDisplayName\": \"Network security group (classic)\" }\n ,\"microsoft.classicnetwork/reservedips\": { \"SingularDisplayName\": \"Reserved IP address (classic)\" }\n ,\"microsoft.classicnetwork/virtualnetworks\": { \"SingularDisplayName\": \"Virtual network (classic)\" }\n })[tolower(id)]\n}\n", "$fxv#1": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n.create-or-alter function \nwith (docstring = 'Return details about the specified ID.', folder = 'OpenData/Internal')\n_resource_type_2(id: string) {\n dynamic({\n \"microsoft.classicstorage/storageaccounts\": { \"SingularDisplayName\": \"Storage account (classic)\" }\n ,\"microsoft.classicstorage/storageaccounts/disks\": { \"SingularDisplayName\": \"Disk (classic)\" }\n ,\"microsoft.classicstorage/storageaccounts/osimages\": { \"SingularDisplayName\": \"OS image (classic)\" }\n ,\"microsoft.classicstorage/storageaccounts/vmimages\": { \"SingularDisplayName\": \"VM image (classic)\" }\n ,\"microsoft.cleanroom/cleanrooms\": { \"SingularDisplayName\": \"Microsoft.CleanRoom cleanroom\" }\n ,\"microsoft.cleanroom/collaborations\": { \"SingularDisplayName\": \"Microsoft.CleanRoom collaboration\" }\n ,\"microsoft.cleanroom/collaborations/contracts\": { \"SingularDisplayName\": \"Microsoft.CleanRoom collaborations contract\" }\n ,\"microsoft.cleanroom/consortiums\": { \"SingularDisplayName\": \"Microsoft.CleanRoom consortium\" }\n ,\"microsoft.cleanroom/microservices\": { \"SingularDisplayName\": \"Microsoft.CleanRoom microservice\" }\n ,\"microsoft.cloud/hubs\": { \"SingularDisplayName\": \"FinOps hub\" }\n ,\"microsoft.clouddeviceplatform/delegatedidentities\": { \"SingularDisplayName\": \"Microsoft.CloudDevicePlatform delegated identity\" }\n ,\"microsoft.cloudhealth/healthmodels\": { \"SingularDisplayName\": \"Health Model\" }\n ,\"microsoft.cloudtest/accounts\": { \"SingularDisplayName\": \"CloudTest Account\" }\n ,\"microsoft.cloudtest/buildcaches\": { \"SingularDisplayName\": \"1ES Build Cache\" }\n ,\"microsoft.cloudtest/hostedpools\": { \"SingularDisplayName\": \"1ES Hosted Pool\" }\n ,\"microsoft.cloudtest/images\": { \"SingularDisplayName\": \"1ES Image\" }\n ,\"microsoft.cloudtest/pools\": { \"SingularDisplayName\": \"CloudTest Pool\" }\n ,\"microsoft.clusterstor/nodes\": { \"SingularDisplayName\": \"ClusterStor\" }\n ,\"microsoft.codesigning/codesigningaccounts\": { \"SingularDisplayName\": \"Trusted Signing Account\" }\n ,\"microsoft.codespaces/plans\": { \"SingularDisplayName\": \"Microsoft.Codespaces plan\" }\n ,\"microsoft.cognitiveservices/accounts\": { \"SingularDisplayName\": \"Azure AI Foundry\" }\n ,\"microsoft.cognitiveservices/accounts/projects\": { \"SingularDisplayName\": \"Azure AI Foundry project\" }\n ,\"microsoft.cognitiveservices/commitmentplans\": { \"SingularDisplayName\": \"Microsoft.CognitiveServices commitment plan\" }\n ,\"microsoft.cognitiveservices/commitmentplans/accountassociations\": { \"SingularDisplayName\": \"Microsoft.CognitiveServices commitment plans account association\" }\n ,\"microsoft.communication/communicationservices\": { \"SingularDisplayName\": \"Communication Service\" }\n ,\"microsoft.communication/emailservices\": { \"SingularDisplayName\": \"Email Communication Service\" }\n ,\"microsoft.communication/emailservices/domains\": { \"SingularDisplayName\": \"Email Communication Services Domain\" }\n ,\"microsoft.community/communitytrainings\": { \"SingularDisplayName\": \"Community Training\" }\n ,\"microsoft.compositesolutions/compositesolutiondefinitions\": { \"SingularDisplayName\": \"Microsoft.CompositeSolutions composite solution definition\" }\n ,\"microsoft.compositesolutions/compositesolutions\": { \"SingularDisplayName\": \"Microsoft.CompositeSolutions composite solution\" }\n ,\"microsoft.compute/availabilitysets\": { \"SingularDisplayName\": \"Availability set\" }\n ,\"microsoft.compute/capacityreservationgroups\": { \"SingularDisplayName\": \"Capacity Reservation Group\" }\n ,\"microsoft.compute/capacityreservationgroups/capacityreservations\": { \"SingularDisplayName\": \"Capacity reservation\" }\n ,\"microsoft.compute/capacityreservationgroupscomputehub\": { \"SingularDisplayName\": \"Capacity Reservation Group\" }\n ,\"microsoft.compute/cloudservices\": { \"SingularDisplayName\": \"Cloud service (extended support)\" }\n ,\"microsoft.compute/computefleetinstances\": { \"SingularDisplayName\": \"Instance\" }\n ,\"microsoft.compute/computefleetscalesets\": { \"SingularDisplayName\": \"Virtual machine scale set\" }\n ,\"microsoft.compute/diskaccesses\": { \"SingularDisplayName\": \"Disk Access\" }\n ,\"microsoft.compute/diskencryptionsets\": { \"SingularDisplayName\": \"Disk Encryption Set\" }\n ,\"microsoft.compute/disks\": { \"SingularDisplayName\": \"Disk\" }\n ,\"microsoft.compute/galleries\": { \"SingularDisplayName\": \"Azure compute gallery\" }\n ,\"microsoft.compute/galleries/applications\": { \"SingularDisplayName\": \"VM application definition\" }\n ,\"microsoft.compute/galleries/applications/versions\": { \"SingularDisplayName\": \"VM application version\" }\n ,\"microsoft.compute/galleries/images\": { \"SingularDisplayName\": \"VM image definition\" }\n ,\"microsoft.compute/galleries/images/versions\": { \"SingularDisplayName\": \"VM image version\" }\n ,\"microsoft.compute/galleries/imagescomputehub\": { \"SingularDisplayName\": \"VM image definition\" }\n ,\"microsoft.compute/hostgroups\": { \"SingularDisplayName\": \"Host group\" }\n ,\"microsoft.compute/hostgroups/hosts\": { \"SingularDisplayName\": \"Host\" }\n ,\"microsoft.compute/hostgroupscomputehub\": { \"SingularDisplayName\": \"Host group\" }\n ,\"microsoft.compute/images\": { \"SingularDisplayName\": \"Image\" }\n ,\"microsoft.compute/imagescomputehub\": { \"SingularDisplayName\": \"Image\" }\n ,\"microsoft.compute/locations/communitygalleries/images\": { \"SingularDisplayName\": \"Community image\" }\n ,\"microsoft.compute/locations/communitygalleries/imagescomputehub\": { \"SingularDisplayName\": \"Community image\" }\n ,\"microsoft.compute/proximityplacementgroups\": { \"SingularDisplayName\": \"Proximity placement group\" }\n ,\"microsoft.compute/proximityplacementgroupscomputehub\": { \"SingularDisplayName\": \"Proximity placement group\" }\n ,\"microsoft.compute/restorepointcollections\": { \"SingularDisplayName\": \"Restore Point Collection\" }\n ,\"microsoft.compute/restorepointcollections/restorepoints\": { \"SingularDisplayName\": \"Restore Point\" }\n ,\"microsoft.compute/snapshots\": { \"SingularDisplayName\": \"Snapshot\" }\n ,\"microsoft.compute/sshpublickeys\": { \"SingularDisplayName\": \"SSH key\" }\n ,\"microsoft.compute/standbypoolinstance\": { \"SingularDisplayName\": \"Standby pool\" }\n ,\"microsoft.compute/virtualmachinecomputehub\": { \"SingularDisplayName\": \"Virtual machine\" }\n ,\"microsoft.compute/virtualmachineflexinstances\": { \"SingularDisplayName\": \"Instance\" }\n ,\"microsoft.compute/virtualmachines\": { \"SingularDisplayName\": \"Virtual machine\" }\n ,\"microsoft.compute/virtualmachines/providers/guestconfigurationassignments\": { \"SingularDisplayName\": \"Guest Assignment\" }\n ,\"microsoft.compute/virtualmachinescalesets\": { \"SingularDisplayName\": \"Virtual machine scale set\" }\n ,\"microsoft.compute/virtualmachinescalesets/providers/guestconfigurationassignments\": { \"SingularDisplayName\": \"Guest Assignment\" }\n ,\"microsoft.compute/virtualmachinescalesets/virtualmachines\": { \"SingularDisplayName\": \"Virtual machine scale set instance\" }\n ,\"microsoft.compute/virtualmachinescalesets/virtualmachines/networkinterfaces/ipconfigurations/publicipaddresses\": { \"SingularDisplayName\": \"Public IP address\" }\n ,\"microsoft.compute/virtualmachinescalesetscomputehub\": { \"SingularDisplayName\": \"Virtual machine scale set\" }\n ,\"microsoft.computehub/advisorcost\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/advisoroperationalexcellence\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/advisorperformance\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/advisorreliability\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/advisorsecurity\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/all\": { \"SingularDisplayName\": \"All resources\" }\n ,\"microsoft.computehub/backup\": { \"SingularDisplayName\": \"Backup job\" }\n ,\"microsoft.computehub/computehubmain\": { \"SingularDisplayName\": \"Compute infrastructure\" }\n ,\"microsoft.computehub/healthevents\": { \"SingularDisplayName\": \"Health events\" }\n ,\"microsoft.computehub/linuxostype\": { \"SingularDisplayName\": \"Linux OS\" }\n ,\"microsoft.computehub/microsoftdefenderfreetrialsubscription\": { \"SingularDisplayName\": \"Microsoft defender\" }\n ,\"microsoft.computehub/microsoftdefenderstandardsubscription\": { \"SingularDisplayName\": \"Microsoft defender\" }\n ,\"microsoft.computehub/outages\": { \"SingularDisplayName\": \"Outages\" }\n ,\"microsoft.computehub/powerstatedeallocated\": { \"SingularDisplayName\": \"Power states\" }\n ,\"microsoft.computehub/powerstaterunning\": { \"SingularDisplayName\": \"Power states\" }\n ,\"microsoft.computehub/powerstatestopped\": { \"SingularDisplayName\": \"Power states\" }\n ,\"microsoft.computehub/provisioningstatefailedresources\": { \"SingularDisplayName\": \"Provisioning states\" }\n ,\"microsoft.computehub/provisioningstatesucceededresources\": { \"SingularDisplayName\": \"Provisioning states\" }\n ,\"microsoft.computehub/windowsostype\": { \"SingularDisplayName\": \"Windows OS\" }\n ,\"microsoft.computeschedule/autoactions\": { \"SingularDisplayName\": \"Automatic Action\" }\n ,\"microsoft.computeschedule/autoactions/occurrences\": { \"SingularDisplayName\": \"Microsoft.ComputeSchedule auto actions occurrence\" }\n ,\"microsoft.confidentialledger/ledgers\": { \"SingularDisplayName\": \"Confidential Ledger\" }\n ,\"microsoft.confidentialledger/managedccfs\": { \"SingularDisplayName\": \"Managed CCF App\" }\n ,\"microsoft.confluent/agreements\": { \"SingularDisplayName\": \"Microsoft.Confluent agreement\" }\n ,\"microsoft.confluent/organizations\": { \"SingularDisplayName\": \"Confluent organization\" }\n ,\"microsoft.connectedcache/cachenodes\": { \"SingularDisplayName\": \"Connected Cache for ISP\" }\n ,\"microsoft.connectedcache/enterprisecustomers\": { \"SingularDisplayName\": \"Connected Cache for Enterprise & Education\" }\n ,\"microsoft.connectedcache/enterprisemcccustomers\": { \"SingularDisplayName\": \"Connected Cache for Enterprise & Education\" }\n ,\"microsoft.connectedcache/enterprisemcccustomers/enterprisemcccachenodes\": { \"SingularDisplayName\": \"MCC CacheNode for Enterprise\" }\n ,\"microsoft.connectedcache/ispcustomers\": { \"SingularDisplayName\": \"Connected Cache for ISP\" }\n ,\"microsoft.connectedcredentials/credentials\": { \"SingularDisplayName\": \"Microsoft.ConnectedCredentials credential\" }\n ,\"microsoft.connectedvehicle/platformaccounts\": { \"SingularDisplayName\": \"Microsoft.ConnectedVehicle platform account\" }\n ,\"microsoft.connectedvmwarevsphere/clusters\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere cluster\" }\n ,\"microsoft.connectedvmwarevsphere/datastores\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere datastore\" }\n ,\"microsoft.connectedvmwarevsphere/hosts\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere host\" }\n ,\"microsoft.connectedvmwarevsphere/resourcepools\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere resource pool\" }\n ,\"microsoft.connectedvmwarevsphere/vcenters\": { \"SingularDisplayName\": \"VMware vCenter\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachineinstances\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual machine instance\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachineinstances/guestagents\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual machine instances guest agent\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachineinstances/hybrididentitymetadata\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual machine instances hybrid identity metadata\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachines\": { \"SingularDisplayName\": \"VMware + AVS virtual machine\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachines/providers/guestconfigurationassignments\": { \"SingularDisplayName\": \"Guest Assignment\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachinetemplates\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual machine template\" }\n ,\"microsoft.connectedvmwarevsphere/virtualnetworks\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual network\" }\n ,\"microsoft.consumption/budgets\": { \"SingularDisplayName\": \"Microsoft.Consumption budget\" }\n ,\"microsoft.consumption/credits\": { \"SingularDisplayName\": \"Microsoft.Consumption credit\" }\n ,\"microsoft.consumption/pricesheets\": { \"SingularDisplayName\": \"Microsoft.Consumption pricesheet\" }\n ,\"microsoft.containerinstance/containergroupprofiles\": { \"SingularDisplayName\": \"Microsoft.ContainerInstance container group profile\" }\n ,\"microsoft.containerinstance/containergroupprofiles/revisions\": { \"SingularDisplayName\": \"Microsoft.ContainerInstance container group profiles revision\" }\n ,\"microsoft.containerinstance/containergroups\": { \"SingularDisplayName\": \"Container instances\" }\n ,\"microsoft.containerinstance/ngroups\": { \"SingularDisplayName\": \"Microsoft.ContainerInstance ngroup\" }\n ,\"microsoft.containerregistry/registries\": { \"SingularDisplayName\": \"Container registry\" }\n ,\"microsoft.containerregistry/registries/replications\": { \"SingularDisplayName\": \"Container registry replication\" }\n ,\"microsoft.containerregistry/registries/scopemaps\": { \"SingularDisplayName\": \"Container registry scope map\" }\n ,\"microsoft.containerregistry/registries/tokens\": { \"SingularDisplayName\": \"Container registry token\" }\n ,\"microsoft.containerregistry/registries/webhooks\": { \"SingularDisplayName\": \"Container registry webhook\" }\n ,\"microsoft.containerservice/fleets\": { \"SingularDisplayName\": \"Kubernetes fleet manager\" }\n ,\"microsoft.containerservice/managedclusters\": { \"SingularDisplayName\": \"Kubernetes service\" }\n ,\"microsoft.containerservice/managedclusters/managednamespaces\": { \"SingularDisplayName\": \"Managed namespace\" }\n ,\"microsoft.containerservice/managedclusters/microsoft.kubernetesconfiguration/extensions\": { \"SingularDisplayName\": \"Kubernetes service extension\" }\n ,\"microsoft.containerservice/managedclusters/microsoft.kubernetesconfiguration/fluxconfigurations\": { \"SingularDisplayName\": \"GitOps configuration\" }\n ,\"microsoft.containerservice/managedclusters/microsoft.kubernetesconfiguration/namespaces\": { \"SingularDisplayName\": \"Kubernetes namespace\" }\n ,\"microsoft.containerservice/managedclusters/namespaces\": { \"SingularDisplayName\": \"Managed namespace\" }\n ,\"microsoft.containerservice/managedclustersnapshots\": { \"SingularDisplayName\": \"Microsoft.ContainerService managedclustersnapshot\" }\n ,\"microsoft.containerservice/snapshots\": { \"SingularDisplayName\": \"Microsoft.ContainerService snapshot\" }\n ,\"microsoft.containerstorage/pools\": { \"SingularDisplayName\": \"Container storage\" }\n ,\"microsoft.costmanagement/alerts\": { \"SingularDisplayName\": \"Microsoft.CostManagement alert\" }\n ,\"microsoft.costmanagement/budgets\": { \"SingularDisplayName\": \"Microsoft.CostManagement budget\" }\n ,\"microsoft.costmanagement/cloudconnectors\": { \"SingularDisplayName\": \"Microsoft.CostManagement cloud connector\" }\n ,\"microsoft.costmanagement/connectors\": { \"SingularDisplayName\": \"Microsoft.CostManagement connector\" }\n ,\"microsoft.costmanagement/costallocationrules\": { \"SingularDisplayName\": \"Microsoft.CostManagement cost allocation rule\" }\n ,\"microsoft.costmanagement/costdetailsoperationresults\": { \"SingularDisplayName\": \"Microsoft.CostManagement cost details operation result\" }\n ,\"microsoft.costmanagement/exports\": { \"SingularDisplayName\": \"Microsoft.CostManagement export\" }\n ,\"microsoft.costmanagement/externalbillingaccounts\": { \"SingularDisplayName\": \"Microsoft.CostManagement external billing account\" }\n ,\"microsoft.costmanagement/externalsubscriptions\": { \"SingularDisplayName\": \"Microsoft.CostManagement external subscription\" }\n ,\"microsoft.costmanagement/markuprules\": { \"SingularDisplayName\": \"Microsoft.CostManagement markup rule\" }\n ,\"microsoft.costmanagement/operationstatus\": { \"SingularDisplayName\": \"Microsoft.CostManagement operation statu\" }\n ,\"microsoft.costmanagement/reportconfigs\": { \"SingularDisplayName\": \"Microsoft.CostManagement reportconfig\" }\n ,\"microsoft.costmanagement/reports\": { \"SingularDisplayName\": \"Microsoft.CostManagement report\" }\n ,\"microsoft.costmanagement/scheduledactions\": { \"SingularDisplayName\": \"Microsoft.CostManagement scheduled action\" }\n ,\"microsoft.costmanagement/settings\": { \"SingularDisplayName\": \"Microsoft.CostManagement setting\" }\n ,\"microsoft.costmanagement/views\": { \"SingularDisplayName\": \"Microsoft.CostManagement view\" }\n ,\"microsoft.customerlockbox/requests\": { \"SingularDisplayName\": \"Microsoft.CustomerLockbox request\" }\n ,\"microsoft.customerlockbox/tenantoptedin\": { \"SingularDisplayName\": \"Microsoft.CustomerLockbox tenant opted in\" }\n ,\"microsoft.customproviders/associations\": { \"SingularDisplayName\": \"Microsoft.CustomProviders association\" }\n ,\"microsoft.customproviders/resourceproviders\": { \"SingularDisplayName\": \"Microsoft.CustomProviders resource provider\" }\n ,\"microsoft.dashboard/dashboards\": { \"SingularDisplayName\": \"Azure Monitor dashboards with Grafana\" }\n ,\"microsoft.dashboard/grafana\": { \"SingularDisplayName\": \"Azure Managed Grafana\" }\n ,\"microsoft.dataaccelerator/indexclusters\": { \"SingularDisplayName\": \"Microsoft.DataAccelerator index cluster\" }\n ,\"microsoft.databasefleetmanager/fleets\": { \"SingularDisplayName\": \"Database fleet manager\" }\n ,\"microsoft.databasefleetmanager/fleets/fleetspaces\": { \"SingularDisplayName\": \"Fleetspaces\" }\n ,\"microsoft.databasefleetmanager/fleets/fleetspaces/databases\": { \"SingularDisplayName\": \"Fleet managed database\" }\n ,\"microsoft.databasefleetmanager/fleets/tiers\": { \"SingularDisplayName\": \"tier\" }\n ,\"microsoft.databasewatcher/watchers\": { \"SingularDisplayName\": \"Database watcher\" }\n ,\"microsoft.databox/jobs\": { \"SingularDisplayName\": \"Azure Data Box\" }\n ,\"microsoft.databoxedge/databoxedgedevices\": { \"SingularDisplayName\": \"Azure Stack Edge / Data Box Gateway\" }\n ,\"microsoft.databricks/accessconnectors\": { \"SingularDisplayName\": \"Access Connector for Azure Databricks\" }\n ,\"microsoft.databricks/workspaces\": { \"SingularDisplayName\": \"Azure Databricks Service\" }\n ,\"microsoft.datacatalog/catalogs\": { \"SingularDisplayName\": \"Data catalog\" }\n ,\"microsoft.datacollaboration/workspaces\": { \"SingularDisplayName\": \"Project CI\" }\n ,\"microsoft.datadog/agreements\": { \"SingularDisplayName\": \"Microsoft.Datadog agreement\" }\n ,\"microsoft.datadog/monitors\": { \"SingularDisplayName\": \"Datadog\" }\n ,\"microsoft.datadog/subscriptionstatuses\": { \"SingularDisplayName\": \"Microsoft.Datadog subscription statuse\" }\n ,\"microsoft.datafactory/datafactories\": { \"SingularDisplayName\": \"Data factory\" }\n ,\"microsoft.datafactory/factories\": { \"SingularDisplayName\": \"Data factory (V2)\" }\n ,\"microsoft.datafactory/factories/pipelines\": { \"SingularDisplayName\": \"Data Factory pipeline\" }\n ,\"microsoft.datafactory/factories/triggers\": { \"SingularDisplayName\": \"Data Factory trigger\" }\n ,\"microsoft.datalakeanalytics/accounts\": { \"SingularDisplayName\": \"Data Lake Analytics account\" }\n ,\"microsoft.datalakestore/accounts\": { \"SingularDisplayName\": \"Data Lake Storage Gen1\" }\n ,\"microsoft.datamigration/databasemigrations\": { \"SingularDisplayName\": \"Microsoft.DataMigration database migration\" }\n ,\"microsoft.datamigration/migrationservices\": { \"SingularDisplayName\": \"Microsoft.DataMigration migration service\" }\n ,\"microsoft.datamigration/services\": { \"SingularDisplayName\": \"Azure Database Migration Service (classic)\" }\n ,\"microsoft.datamigration/services/projects\": { \"SingularDisplayName\": \"Azure Database Migration Project\" }\n ,\"microsoft.datamigration/sqlmigrationservices\": { \"SingularDisplayName\": \"Azure Database Migration Service\" }\n ,\"microsoft.dataprotection/backupvaults\": { \"SingularDisplayName\": \"Backup vault\" }\n ,\"microsoft.dataprotection/resourceguards\": { \"SingularDisplayName\": \"Resource Guard\" }\n ,\"microsoft.datareplication/replicationfabrics\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication fabric\" }\n ,\"microsoft.datareplication/replicationfabrics/fabricagents\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication fabrics fabric agent\" }\n ,\"microsoft.datareplication/replicationfabrics/fabricagents/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication fabrics fabric agents operation\" }\n ,\"microsoft.datareplication/replicationfabrics/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication fabrics operation\" }\n ,\"microsoft.datareplication/replicationvaults\": { \"SingularDisplayName\": \"Data replication vault\" }\n ,\"microsoft.datareplication/replicationvaults/alertsettings\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults alert setting\" }\n ,\"microsoft.datareplication/replicationvaults/events\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults event\" }\n ,\"microsoft.datareplication/replicationvaults/jobs\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults job\" }\n ,\"microsoft.datareplication/replicationvaults/jobs/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults jobs operation\" }\n ,\"microsoft.datareplication/replicationvaults/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults operation\" }\n ,\"microsoft.datareplication/replicationvaults/privateendpointconnectionproxies\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults private endpoint connection proxy\" }\n ,\"microsoft.datareplication/replicationvaults/privateendpointconnections\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults private endpoint connection\" }\n ,\"microsoft.datareplication/replicationvaults/privatelinkresources\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults private link resource\" }\n ,\"microsoft.datareplication/replicationvaults/protecteditems\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults protected item\" }\n ,\"microsoft.datareplication/replicationvaults/protecteditems/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults protected items operation\" }\n ,\"microsoft.datareplication/replicationvaults/protecteditems/recoverypoints\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults protected items recovery point\" }\n ,\"microsoft.datareplication/replicationvaults/replicationextensions\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults replication extension\" }\n ,\"microsoft.datareplication/replicationvaults/replicationextensions/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults replication extensions operation\" }\n ,\"microsoft.datareplication/replicationvaults/replicationpolicies\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults replication policy\" }\n ,\"microsoft.datareplication/replicationvaults/replicationpolicies/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults replication policies operation\" }\n ,\"microsoft.datashare/accounts\": { \"SingularDisplayName\": \"Data Share\" }\n ,\"microsoft.dbformariadb/servers\": { \"SingularDisplayName\": \"Azure Database for MariaDB server\" }\n ,\"microsoft.dbformysql/flexibleservers\": { \"SingularDisplayName\": \"Azure Database for MySQL flexible server\" }\n ,\"microsoft.dbformysql/servers\": { \"SingularDisplayName\": \"MySQL server\" }\n ,\"microsoft.dbforpostgresql/flexibleservers\": { \"SingularDisplayName\": \"Azure Database for PostgreSQL flexible server\" }\n ,\"microsoft.dbforpostgresql/servergroupsv2\": { \"SingularDisplayName\": \"Azure Cosmos DB for PostgreSQL Cluster\" }\n ,\"microsoft.dbforpostgresql/servers\": { \"SingularDisplayName\": \"PostgreSQL server\" }\n ,\"microsoft.delegatednetwork/controller\": { \"SingularDisplayName\": \"Microsoft.DelegatedNetwork controller\" }\n ,\"microsoft.delegatednetwork/delegatedsubnets\": { \"SingularDisplayName\": \"Microsoft.DelegatedNetwork delegated subnet\" }\n ,\"microsoft.delegatednetwork/orchestrators\": { \"SingularDisplayName\": \"Microsoft.DelegatedNetwork orchestrator\" }\n ,\"microsoft.dependencymap/maps\": { \"SingularDisplayName\": \"Microsoft.DependencyMap map\" }\n ,\"microsoft.dependencymap/maps/discoverysources\": { \"SingularDisplayName\": \"Microsoft.DependencyMap maps discovery source\" }\n ,\"microsoft.deploymentmanager/artifactsources\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager artifact source\" }\n ,\"microsoft.deploymentmanager/rollouts\": { \"SingularDisplayName\": \"Rollout\" }\n ,\"microsoft.deploymentmanager/servicetopologies\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager service topology\" }\n ,\"microsoft.deploymentmanager/servicetopologies/services\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager service topologies service\" }\n ,\"microsoft.deploymentmanager/servicetopologies/services/serviceunits\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager service topologies services service unit\" }\n ,\"microsoft.deploymentmanager/steps\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager step\" }\n ,\"microsoft.desktopvirtualization/appattachpackages\": { \"SingularDisplayName\": \"App attach package\" }\n ,\"microsoft.desktopvirtualization/applicationgroups\": { \"SingularDisplayName\": \"Application group\" }\n ,\"microsoft.desktopvirtualization/hostpools\": { \"SingularDisplayName\": \"Host pool\" }\n ,\"microsoft.desktopvirtualization/scalingplans\": { \"SingularDisplayName\": \"Scaling plan\" }\n ,\"microsoft.desktopvirtualization/workspaces\": { \"SingularDisplayName\": \"Workspace\" }\n ,\"microsoft.devai/instances\": { \"SingularDisplayName\": \"Microsoft.DevAI instance\" }\n ,\"microsoft.devai/instances/experiments\": { \"SingularDisplayName\": \"Microsoft.DevAI instances experiment\" }\n ,\"microsoft.devai/instances/sandboxes\": { \"SingularDisplayName\": \"Microsoft.DevAI instances sandbox\" }\n ,\"microsoft.devai/instances/sandboxes/experiments\": { \"SingularDisplayName\": \"Microsoft.DevAI instances sandboxes experiment\" }\n ,\"microsoft.devcenter/devcenters\": { \"SingularDisplayName\": \"Dev center\" }\n ,\"microsoft.devcenter/devcenters/devboxdefinitions\": { \"SingularDisplayName\": \"Dev Box definition\" }\n ,\"microsoft.devcenter/networkconnections\": { \"SingularDisplayName\": \"Network connection\" }\n ,\"microsoft.devcenter/plans\": { \"SingularDisplayName\": \"Dev center plan\" }\n ,\"microsoft.devcenter/projects\": { \"SingularDisplayName\": \"Project\" }\n ,\"microsoft.devcenter/projects/pools\": { \"SingularDisplayName\": \"Pool\" }\n ,\"microsoft.developmentwindows365/developmentcloudpcdelegatedmsis\": { \"SingularDisplayName\": \"Microsoft.DevelopmentWindows365 development cloud pc delegated msi\" }\n ,\"microsoft.devhub/iacprofiles\": { \"SingularDisplayName\": \"Infrastructure as Code Automation\" }\n ,\"microsoft.devhub/templates\": { \"SingularDisplayName\": \"Microsoft.DevHub template\" }\n ,\"microsoft.devhub/templates/versions\": { \"SingularDisplayName\": \"Microsoft.DevHub templates version\" }\n ,\"microsoft.devhub/workflows\": { \"SingularDisplayName\": \"Microsoft.DevHub workflow\" }\n ,\"microsoft.deviceonboarding/discoveryservices\": { \"SingularDisplayName\": \"Microsoft.DeviceOnboarding discovery service\" }\n ,\"microsoft.deviceonboarding/discoveryservices/ownershipvoucherpublickeys\": { \"SingularDisplayName\": \"Microsoft.DeviceOnboarding discovery services ownership voucher public key\" }\n ,\"microsoft.deviceonboarding/onboardingservices\": { \"SingularDisplayName\": \"Microsoft.DeviceOnboarding onboarding service\" }\n ,\"microsoft.deviceonboarding/onboardingservices/policies\": { \"SingularDisplayName\": \"Microsoft.DeviceOnboarding onboarding services policy\" }\n ,\"microsoft.deviceregistry/assetendpointprofiles\": { \"SingularDisplayName\": \"IoT Asset Endpoint Profile\" }\n ,\"microsoft.deviceregistry/assets\": { \"SingularDisplayName\": \"IoT Asset\" }\n ,\"microsoft.deviceregistry/billingcontainers\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry billing container\" }\n ,\"microsoft.deviceregistry/devices\": { \"SingularDisplayName\": \"IoT Device\" }\n ,\"microsoft.deviceregistry/discoveredassetendpointprofiles\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry discovered asset endpoint profile\" }\n ,\"microsoft.deviceregistry/discoveredassets\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry discovered asset\" }\n ,\"microsoft.deviceregistry/namespaces\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespace\" }\n ,\"microsoft.deviceregistry/namespaces/assetendpointprofiles\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces asset endpoint profile\" }\n ,\"microsoft.deviceregistry/namespaces/assets\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces asset\" }\n ,\"microsoft.deviceregistry/namespaces/devices\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces device\" }\n ,\"microsoft.deviceregistry/namespaces/discoveredassetendpointprofiles\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces discovered asset endpoint profile\" }\n ,\"microsoft.deviceregistry/namespaces/discoveredassets\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces discovered asset\" }\n ,\"microsoft.deviceregistry/schemaregistries\": { \"SingularDisplayName\": \"IoT Schema Registry\" }\n ,\"microsoft.deviceregistry/schemaregistries/schemas\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry schema registries schema\" }\n ,\"microsoft.deviceregistry/schemaregistries/schemas/schemaversions\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry schema registries schemas schema version\" }\n ,\"microsoft.devices/iothubs\": { \"SingularDisplayName\": \"IoT hub\" }\n ,\"microsoft.devices/provisioningservices\": { \"SingularDisplayName\": \"Azure IoT Hub Device Provisioning Service (DPS)\" }\n ,\"microsoft.deviceupdate/accounts\": { \"SingularDisplayName\": \"Device Update for IoT Hub\" }\n ,\"microsoft.deviceupdate/updateaccounts\": { \"SingularDisplayName\": \"Device Update Account\" }\n ,\"microsoft.deviceupdate/updateaccounts/activedeployments\": { \"SingularDisplayName\": \"Device Update Active Deployment\" }\n ,\"microsoft.deviceupdate/updateaccounts/agents\": { \"SingularDisplayName\": \"Device Update Agent\" }\n ,\"microsoft.deviceupdate/updateaccounts/deployments\": { \"SingularDisplayName\": \"Device Update Deployment\" }\n ,\"microsoft.deviceupdate/updateaccounts/deviceclasses\": { \"SingularDisplayName\": \"Device Update Device Class\" }\n ,\"microsoft.deviceupdate/updateaccounts/updates\": { \"SingularDisplayName\": \"Device Update\" }\n ,\"microsoft.devops/pipelines\": { \"SingularDisplayName\": \"Microsoft.DevOps pipeline\" }\n ,\"microsoft.devopsinfrastructure/pools\": { \"SingularDisplayName\": \"Managed DevOps Pool\" }\n ,\"microsoft.devspaces/controllers\": { \"SingularDisplayName\": \"Microsoft.DevSpaces controller\" }\n ,\"microsoft.devtestlab/labs\": { \"SingularDisplayName\": \"DevTest lab\" }\n ,\"microsoft.devtestlab/labs/virtualmachines\": { \"SingularDisplayName\": \"DevTest Lab virtual machine\" }\n ,\"microsoft.devtestlab/schedules\": { \"SingularDisplayName\": \"Microsoft.DevTestLab schedule\" }\n ,\"microsoft.devtunnels/tunnelplans\": { \"SingularDisplayName\": \"Dev Tunnels Domain\" }\n ,\"microsoft.diagnostics/apollo\": { \"SingularDisplayName\": \"Microsoft.Diagnostics apollo\" }\n ,\"microsoft.digitaltwins/digitaltwinsinstances\": { \"SingularDisplayName\": \"Azure Digital Twins\" }\n ,\"microsoft.discovery/agents\": { \"SingularDisplayName\": \"Microsoft Discovery Agent\" }\n ,\"microsoft.discovery/bookshelves\": { \"SingularDisplayName\": \"Microsoft Discovery Bookshelf\" }\n ,\"microsoft.discovery/datacontainers\": { \"SingularDisplayName\": \"Microsoft Discovery Data Container\" }\n ,\"microsoft.discovery/datacontainers/dataassets\": { \"SingularDisplayName\": \"Data asset\" }\n ,\"microsoft.discovery/models\": { \"SingularDisplayName\": \"Microsoft Discovery Model\" }\n ,\"microsoft.discovery/storages\": { \"SingularDisplayName\": \"Microsoft Discovery Storage\" }\n ,\"microsoft.discovery/supercomputers\": { \"SingularDisplayName\": \"Microsoft Discovery Supercomputer\" }\n ,\"microsoft.discovery/supercomputers/nodepools\": { \"SingularDisplayName\": \"Nodepool\" }\n ,\"microsoft.discovery/tools\": { \"SingularDisplayName\": \"Microsoft Discovery Tool\" }\n ,\"microsoft.discovery/workflows\": { \"SingularDisplayName\": \"Microsoft Discovery Workflow\" }\n ,\"microsoft.discovery/workspaces\": { \"SingularDisplayName\": \"Microsoft Discovery Workspace\" }\n ,\"microsoft.discovery/workspaces/projects\": { \"SingularDisplayName\": \"Microsoft Discovery Project\" }\n ,\"microsoft.documentdb/cassandraclusters\": { \"SingularDisplayName\": \"Azure Managed Instance for Apache Cassandra\" }\n ,\"microsoft.documentdb/databaseaccounts\": { \"SingularDisplayName\": \"Cosmos DB account\" }\n ,\"microsoft.documentdb/fleets\": { \"SingularDisplayName\": \"Azure Cosmos DB Fleet\" }\n ,\"microsoft.documentdb/fleetspacepotentialdatabaseaccounts\": { \"SingularDisplayName\": \"Potential Azure Cosmos DB account\" }\n ,\"microsoft.documentdb/fleetspacepotentialdatabaseaccountswithlocations\": { \"SingularDisplayName\": \"Potential Azure Cosmos DB account\" }\n ,\"microsoft.documentdb/mongoclusters\": { \"SingularDisplayName\": \"Azure Cosmos DB for MongoDB (vCore)\" }\n ,\"microsoft.documentdb/throughputpools\": { \"SingularDisplayName\": \"Microsoft.DocumentDB throughput pool\" }\n ,\"microsoft.documentdb/throughputpools/throughputpoolaccounts\": { \"SingularDisplayName\": \"Microsoft.DocumentDB throughput pools throughput pool account\" }\n ,\"microsoft.domainregistration/domains\": { \"SingularDisplayName\": \"App Service Domain\" }\n ,\"microsoft.domainregistration/topleveldomains\": { \"SingularDisplayName\": \"Microsoft.DomainRegistration top level domain\" }\n ,\"microsoft.durabletask/namespaces\": { \"SingularDisplayName\": \"Microsoft.DurableTask namespace\" }\n ,\"microsoft.durabletask/namespaces/taskhubs\": { \"SingularDisplayName\": \"Task Hub\" }\n ,\"microsoft.durabletask/schedulers\": { \"SingularDisplayName\": \"Durable Task Scheduler\" }\n ,\"microsoft.durabletask/schedulers/taskhubs\": { \"SingularDisplayName\": \"Task Hub\" }\n ,\"microsoft.dynamics365fraudprotection/instances\": { \"SingularDisplayName\": \"Microsoft.Dynamics365FraudProtection instance\" }\n ,\"microsoft.easm/workspaces\": { \"SingularDisplayName\": \"Microsoft Defender EASM\" }\n ,\"microsoft.edge/configurations\": { \"SingularDisplayName\": \"Site configuration\" }\n ,\"microsoft.edge/configurations/arcgatewayconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations arc gateway configuration\" }\n ,\"microsoft.edge/configurations/connectivityconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations connectivity configuration\" }\n ,\"microsoft.edge/configurations/dynamicconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations dynamic configuration\" }\n ,\"microsoft.edge/configurations/dynamicconfigurations/versions\": { \"SingularDisplayName\": \"Microsoft.Edge configurations dynamic configurations version\" }\n ,\"microsoft.edge/configurations/networkconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations network configuration\" }\n ,\"microsoft.edge/configurations/securityconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations security configuration\" }\n ,\"microsoft.edge/configurations/timeserverconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations time server configuration\" }\n ,\"microsoft.edge/connectivitystatuses\": { \"SingularDisplayName\": \"Microsoft.Edge connectivity statuse\" }\n ,\"microsoft.edge/disconnectedoperations\": { \"SingularDisplayName\": \"Azure Local - disconnected operations\" }\n ,\"microsoft.edge/siteawareresourcetypes\": { \"SingularDisplayName\": \"Microsoft.Edge site aware resource type\" }\n ,\"microsoft.edge/sites\": { \"SingularDisplayName\": \"Site manager - Azure Arc\" }\n ,\"microsoft.edge/updates\": { \"SingularDisplayName\": \"Microsoft.Edge update\" }\n ,\"microsoft.edgemarketplace/offers\": { \"SingularDisplayName\": \"Microsoft.EdgeMarketplace offer\" }\n ,\"microsoft.edgemarketplace/publishers\": { \"SingularDisplayName\": \"Microsoft.EdgeMarketplace publisher\" }\n ,\"microsoft.edgeorder/addresses\": { \"SingularDisplayName\": \"Azure Edge Hardware Center Address\" }\n ,\"microsoft.edgeorder/bootstrapconfigurations\": { \"SingularDisplayName\": \"Site Key\" }\n ,\"microsoft.edgeorder/orderitems\": { \"SingularDisplayName\": \"Azure Edge Hardware Center\" }\n ,\"microsoft.edgeorder/virtual_orderitems\": { \"SingularDisplayName\": \"Device\" }\n ,\"microsoft.edgezones/extendedzones\": { \"SingularDisplayName\": \"Microsoft.EdgeZones extended zone\" }\n ,\"microsoft.education/grants\": { \"SingularDisplayName\": \"Microsoft.Education grant\" }\n ,\"microsoft.education/labs\": { \"SingularDisplayName\": \"Microsoft.Education lab\" }\n ,\"microsoft.education/labs/joinrequests\": { \"SingularDisplayName\": \"Microsoft.Education labs join request\" }\n ,\"microsoft.education/labs/students\": { \"SingularDisplayName\": \"Microsoft.Education labs student\" }\n ,\"microsoft.education/studentlabs\": { \"SingularDisplayName\": \"Microsoft.Education student lab\" }\n ,\"microsoft.elastic/monitors\": { \"SingularDisplayName\": \"Elastic Cloud Resource\" }\n ,\"microsoft.elasticsan/elasticsans\": { \"SingularDisplayName\": \"Elastic SAN\" }\n ,\"microsoft.energydataplatform/energyservices\": { \"SingularDisplayName\": \"Microsoft.EnergyDataPlatform energy service\" }\n ,\"microsoft.enterpriseknowledgegraph/services\": { \"SingularDisplayName\": \"Microsoft.EnterpriseKnowledgeGraph service\" }\n ,\"microsoft.enterprisesupport/enterprisesupports\": { \"SingularDisplayName\": \"Microsoft.EnterpriseSupport enterprise support\" }\n ,\"microsoft.eventgrid/domains\": { \"SingularDisplayName\": \"Event Grid Domain\" }\n ,\"microsoft.eventgrid/domains/topics\": { \"SingularDisplayName\": \"Event Grid Domain Topic\" }\n ,\"microsoft.eventgrid/eventsubscriptions\": { \"SingularDisplayName\": \"Microsoft.EventGrid event subscription\" }\n ,\"microsoft.eventgrid/extensiontopics\": { \"SingularDisplayName\": \"Event Grid extension topic\" }\n ,\"microsoft.eventgrid/namespaces\": { \"SingularDisplayName\": \"Event Grid Namespace\" }\n ,\"microsoft.eventgrid/namespaces/topics\": { \"SingularDisplayName\": \"Event Grid Namespace Topic\" }\n ,\"microsoft.eventgrid/namespaces/topics/eventsubscriptions\": { \"SingularDisplayName\": \"Event Subscription\" }\n ,\"microsoft.eventgrid/namespaces/topicspaces\": { \"SingularDisplayName\": \"Event Grid Topic Space\" }\n ,\"microsoft.eventgrid/partnerconfigurations\": { \"SingularDisplayName\": \"Event Grid Partner Configuration\" }\n ,\"microsoft.eventgrid/partnerdestinations\": { \"SingularDisplayName\": \"Event Grid Partner Destination\" }\n ,\"microsoft.eventgrid/partnernamespaces\": { \"SingularDisplayName\": \"Event Grid Partner Namespace\" }\n ,\"microsoft.eventgrid/partnernamespaces/channels\": { \"SingularDisplayName\": \"Event Grid Channel\" }\n ,\"microsoft.eventgrid/partnerregistrations\": { \"SingularDisplayName\": \"Event Grid Partner Registration\" }\n ,\"microsoft.eventgrid/partnertopics\": { \"SingularDisplayName\": \"Event Grid Partner Topic\" }\n ,\"microsoft.eventgrid/systemtopics\": { \"SingularDisplayName\": \"Event Grid System Topic\" }\n ,\"microsoft.eventgrid/systemtopics/eventsubscriptions\": { \"SingularDisplayName\": \"Event Grid Subscriptions\" }\n ,\"microsoft.eventgrid/topics\": { \"SingularDisplayName\": \"Event Grid Topic\" }\n ,\"microsoft.eventgrid/topictypes\": { \"SingularDisplayName\": \"Microsoft.EventGrid topic type\" }\n ,\"microsoft.eventgrid/verifiedpartners\": { \"SingularDisplayName\": \"Microsoft.EventGrid verified partner\" }\n ,\"microsoft.eventhub/clusters\": { \"SingularDisplayName\": \"Event Hubs Cluster\" }\n ,\"microsoft.eventhub/namespaces\": { \"SingularDisplayName\": \"Event Hubs namespace\" }\n ,\"microsoft.eventhub/namespaces/disasterrecoveryconfigs\": { \"SingularDisplayName\": \"Event Hubs Geo-DR Alias\" }\n ,\"microsoft.eventhub/namespaces/eventhubs\": { \"SingularDisplayName\": \"Event Hubs Instance\" }\n ,\"microsoft.eventhub/namespaces/providers/diagnosticsettings\": { \"SingularDisplayName\": \"Diagnostic settings\" }\n ,\"microsoft.eventhub/namespaces/schemagroups\": { \"SingularDisplayName\": \"Schema Group\" }\n ,\"microsoft.experimentation/experimentworkspaces\": { \"SingularDisplayName\": \"Experiment Workspace\" }\n ,\"microsoft.extendedlocation/customlocations\": { \"SingularDisplayName\": \"Custom location\" }\n ,\"microsoft.fabric/capacities\": { \"SingularDisplayName\": \"Fabric Capacity\" }\n ,\"microsoft.fabric/privatelinkservicesforfabric\": { \"SingularDisplayName\": \"Microsoft.Fabric private link services for fabric\" }\n ,\"microsoft.fabric/privatelinkservicesforfabric/operationresults\": { \"SingularDisplayName\": \"Microsoft.Fabric private link services for fabric operation result\" }\n ,\"microsoft.fabric/privatelinkservicesforfabric/privateendpointconnections\": { \"SingularDisplayName\": \"Microsoft.Fabric private link services for fabric private endpoint connection\" }\n ,\"microsoft.fabric/privatelinkservicesforfabric/privatelinkresources\": { \"SingularDisplayName\": \"Microsoft.Fabric private link services for fabric private link resource\" }\n ,\"microsoft.fairfieldgardens/deviceprovisioningstates\": { \"SingularDisplayName\": \"Microsoft.FairfieldGardens device provisioning state\" }\n ,\"microsoft.fairfieldgardens/provisioningresources\": { \"SingularDisplayName\": \"Fairfield Gardens\" }\n ,\"microsoft.fairfieldgardens/provisioningresources/provisioningpolicies\": { \"SingularDisplayName\": \"Provisioning policy\" }\n ,\"microsoft.falcon/namespaces\": { \"SingularDisplayName\": \"Microsoft.Falcon namespace\" }\n ,\"microsoft.features/featureprovidernamespaces/featureconfigurations\": { \"SingularDisplayName\": \"Preview features\" }\n ,\"microsoft.fidalgo/devcenters\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenter\" }\n ,\"microsoft.fidalgo/devcenters/attachednetworks\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters attachednetwork\" }\n ,\"microsoft.fidalgo/devcenters/catalogs\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters catalog\" }\n ,\"microsoft.fidalgo/devcenters/catalogs/items\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters catalogs item\" }\n ,\"microsoft.fidalgo/devcenters/devboxdefinitions\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters devboxdefinition\" }\n ,\"microsoft.fidalgo/devcenters/environmenttypes\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters environment type\" }\n ,\"microsoft.fidalgo/devcenters/galleries\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters gallery\" }\n ,\"microsoft.fidalgo/devcenters/galleries/images\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters galleries image\" }\n ,\"microsoft.fidalgo/devcenters/galleries/images/versions\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters galleries images version\" }\n ,\"microsoft.fidalgo/devcenters/mappings\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters mapping\" }\n ,\"microsoft.fidalgo/machinedefinitions\": { \"SingularDisplayName\": \"Microsoft.Fidalgo machinedefinition\" }\n ,\"microsoft.fidalgo/networksettings\": { \"SingularDisplayName\": \"Microsoft.Fidalgo networksetting\" }\n ,\"microsoft.fidalgo/networksettings/healthchecks\": { \"SingularDisplayName\": \"Microsoft.Fidalgo networksettings healthcheck\" }\n ,\"microsoft.fidalgo/projects\": { \"SingularDisplayName\": \"Microsoft.Fidalgo project\" }\n ,\"microsoft.fidalgo/projects/attachednetworks\": { \"SingularDisplayName\": \"Microsoft.Fidalgo projects attachednetwork\" }\n ,\"microsoft.fidalgo/projects/devboxdefinitions\": { \"SingularDisplayName\": \"Microsoft.Fidalgo projects devboxdefinition\" }\n ,\"microsoft.fidalgo/projects/environments\": { \"SingularDisplayName\": \"Microsoft.Fidalgo projects environment\" }\n ,\"microsoft.fidalgo/projects/pools\": { \"SingularDisplayName\": \"Microsoft.Fidalgo projects pool\" }\n ,\"microsoft.fileshares/fileshares\": { \"SingularDisplayName\": \"File share\" }\n ,\"microsoft.fluidrelay/fluidrelayservers\": { \"SingularDisplayName\": \"Fluid Relay\" }\n ,\"microsoft.footprintmonitoring/profiles\": { \"SingularDisplayName\": \"Microsoft.FootprintMonitoring profile\" }\n ,\"microsoft.footprintmonitoring/profiles/experiments\": { \"SingularDisplayName\": \"Microsoft.FootprintMonitoring profiles experiment\" }\n ,\"microsoft.footprintmonitoring/profiles/measurementendpoints\": { \"SingularDisplayName\": \"Microsoft.FootprintMonitoring profiles measurement endpoint\" }\n ,\"microsoft.footprintmonitoring/profiles/measurementendpoints/conditions\": { \"SingularDisplayName\": \"Microsoft.FootprintMonitoring profiles measurement endpoints condition\" }\n ,\"microsoft.gallery/myareas/galleryitems\": { \"SingularDisplayName\": \"Template\" }\n ,\"microsoft.genomics/accounts\": { \"SingularDisplayName\": \"Genomics account\" }\n ,\"microsoft.graph/azureadapplication\": { \"SingularDisplayName\": \"Entra application\" }\n ,\"microsoft.graph/azureadapplicationprototype\": { \"SingularDisplayName\": \"Microsoft.Graph Azure ad application prototype\" }\n ,\"microsoft.graphservices/accounts\": { \"SingularDisplayName\": \"Metered API account\" }\n ,\"microsoft.guestconfiguration/guestconfigurationassignments\": { \"SingularDisplayName\": \"Microsoft.GuestConfiguration guest configuration assignment\" }\n ,\"microsoft.guestconfiguration/guestconfigurationassignments/reports\": { \"SingularDisplayName\": \"Microsoft.GuestConfiguration guest configuration assignments report\" }\n ,\"microsoft.hanaonazure/hanainstances\": { \"SingularDisplayName\": \"SAP HANA on Azure\" }\n ,\"microsoft.hanaonazure/sapmonitors\": { \"SingularDisplayName\": \"Azure Monitor for SAP Solutions (classic)\" }\n ,\"microsoft.hardware/orders\": { \"SingularDisplayName\": \"Microsoft.Hardware order\" }\n ,\"microsoft.hardwaresecuritymodules/cloudhsmclusters\": { \"SingularDisplayName\": \"Azure Cloud HSM\" }\n ,\"microsoft.hdinsight/clusterpools\": { \"SingularDisplayName\": \"Azure HDInsight on AKS cluster pool\" }\n ,\"microsoft.hdinsight/clusterpools/clusters\": { \"SingularDisplayName\": \"Azure HDInsight on AKS cluster\" }\n ,\"microsoft.hdinsight/clusterpools/clusters/instanceviews\": { \"SingularDisplayName\": \"Microsoft.HDInsight clusterpools clusters instance view\" }\n ,\"microsoft.hdinsight/clusters\": { \"SingularDisplayName\": \"HDInsight cluster\" }\n ,\"microsoft.healthbot/healthbots\": { \"SingularDisplayName\": \"Healthcare agent service\" }\n ,\"microsoft.healthcareapis/services\": { \"SingularDisplayName\": \"Azure API for FHIR\" }\n ,\"microsoft.healthcareapis/workspaces\": { \"SingularDisplayName\": \"Health Data Services workspace\" }\n ,\"microsoft.healthcareapis/workspaces/dicomservices\": { \"SingularDisplayName\": \"DICOM service\" }\n ,\"microsoft.healthcareapis/workspaces/fhirservices\": { \"SingularDisplayName\": \"FHIR service\" }\n ,\"microsoft.healthcareapis/workspaces/iotconnectors\": { \"SingularDisplayName\": \"MedTech service\" }\n ,\"microsoft.healthdataaiservices/deidservices\": { \"SingularDisplayName\": \"De-identification Service\" }\n ,\"microsoft.healthmodel/healthmodels\": { \"SingularDisplayName\": \"Health Model\" }\n ,\"microsoft.healthplatform/accounts\": { \"SingularDisplayName\": \"Microsoft.HealthPlatform account\" }\n ,\"microsoft.help/diagnostics\": { \"SingularDisplayName\": \"Microsoft.Help diagnostic\" }\n ,\"microsoft.help/selfhelp\": { \"SingularDisplayName\": \"Microsoft.Help self help\" }\n ,\"microsoft.help/simplifiedsolutions\": { \"SingularDisplayName\": \"Microsoft.Help simplified solution\" }\n ,\"microsoft.help/solutions\": { \"SingularDisplayName\": \"Microsoft.Help solution\" }\n ,\"microsoft.help/troubleshooters\": { \"SingularDisplayName\": \"Microsoft.Help troubleshooter\" }\n ,\"microsoft.hpcworkbench/instances\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instance\" }\n ,\"microsoft.hpcworkbench/instances/chambers\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chamber\" }\n ,\"microsoft.hpcworkbench/instances/chambers/accessprofiles\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers access profile\" }\n ,\"microsoft.hpcworkbench/instances/chambers/filerequests\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers file request\" }\n ,\"microsoft.hpcworkbench/instances/chambers/files\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers file\" }\n ,\"microsoft.hpcworkbench/instances/chambers/storages\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers storage\" }\n ,\"microsoft.hpcworkbench/instances/chambers/workloads\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers workload\" }\n ,\"microsoft.hpcworkbench/instances/consortiums\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances consortium\" }\n ,\"microsoft.hybridcloud/cloudconnections\": { \"SingularDisplayName\": \"Microsoft.HybridCloud cloud connection\" }\n ,\"microsoft.hybridcloud/cloudconnectors\": { \"SingularDisplayName\": \"Microsoft.HybridCloud cloud connector\" }\n ,\"microsoft.hybridcompute/arcgatewayassociatedresources\": { \"SingularDisplayName\": \"Arc gateway associated resource\" }\n ,\"microsoft.hybridcompute/arcserverwithwac\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/gateways\": { \"SingularDisplayName\": \"Arc gateway\" }\n ,\"microsoft.hybridcompute/licenses\": { \"SingularDisplayName\": \"Extended Security Updates - Windows Server 2012/R2\" }\n ,\"microsoft.hybridcompute/machines\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/machines/microsoft.awsconnector/ec2instances\": { \"SingularDisplayName\": \"Microsoft.AwsConnector ec2 instance\" }\n ,\"microsoft.hybridcompute/machines/microsoft.connectedvmwarevsphere/virtualmachineinstances\": { \"SingularDisplayName\": \"VMware + AVS virtual machine\" }\n ,\"microsoft.hybridcompute/machines/providers/guestconfigurationassignments\": { \"SingularDisplayName\": \"Guest Assignment\" }\n ,\"microsoft.hybridcompute/machinesesu\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/machinespaygo\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/machinessoftwareassurance\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/machinessovereign\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/privatelinkscopes\": { \"SingularDisplayName\": \"Azure Arc Private Link Scope\" }\n ,\"microsoft.hybridcompute/settings\": { \"SingularDisplayName\": \"Microsoft.HybridCompute setting\" }\n ,\"microsoft.hybridconnectivity/endpoints\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity endpoint\" }\n ,\"microsoft.hybridconnectivity/endpoints/serviceconfigurations\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity endpoints service configuration\" }\n ,\"microsoft.hybridconnectivity/publiccloudconnectors\": { \"SingularDisplayName\": \"Multicloud connector\" }\n ,\"microsoft.hybridconnectivity/solutionconfigurations\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity solution configuration\" }\n ,\"microsoft.hybridconnectivity/solutionconfigurations/inventory\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity solution configurations inventory\" }\n ,\"microsoft.hybridconnectivity/solutiontypes\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity solution type\" }\n ,\"microsoft.hybridcontainerservice/kubernetesversions\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService kubernetes version\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusterinstances\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService provisioned cluster instance\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusterinstances/agentpools\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService provisioned cluster instances agent pool\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusterinstances/hybrididentitymetadata\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService provisioned cluster instances hybrid identity metadata\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusterinstances/upgradeprofiles\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService provisioned cluster instances upgrade profile\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusters\": { \"SingularDisplayName\": \"Kubernetes hybrid - Azure Arc\" }\n ,\"microsoft.hybridcontainerservice/skus\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService SKU\" }\n ,\"microsoft.hybridcontainerservice/storagespaces\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService storage space\" }\n ,\"microsoft.hybridcontainerservice/virtualnetworks\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService virtual network\" }\n ,\"microsoft.hybriddata/datamanagers\": { \"SingularDisplayName\": \"Microsoft.HybridData data manager\" }\n ,\"microsoft.hybriddata/datamanagers/dataservices\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data service\" }\n ,\"microsoft.hybriddata/datamanagers/dataservices/jobdefinitions\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data services job definition\" }\n ,\"microsoft.hybriddata/datamanagers/dataservices/jobdefinitions/jobs\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data services job definitions job\" }\n ,\"microsoft.hybriddata/datamanagers/datastores\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data store\" }\n ,\"microsoft.hybriddata/datamanagers/datastoretypes\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data store type\" }\n ,\"microsoft.hybriddata/datamanagers/publickeys\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers public key\" }\n ,\"microsoft.hybridnetwork/configurationgroupvalues\": { \"SingularDisplayName\": \"Configuration Group Value\" }\n ,\"microsoft.hybridnetwork/devices\": { \"SingularDisplayName\": \"Azure Network Function Manager ? Device\" }\n ,\"microsoft.hybridnetwork/networkfunctions\": { \"SingularDisplayName\": \"Azure Network Function Manager ? Network Function\" }\n ,\"microsoft.hybridnetwork/proxypublishers\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publisher\" }\n ,\"microsoft.hybridnetwork/proxypublishers/artifactstores\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers artifact store\" }\n ,\"microsoft.hybridnetwork/proxypublishers/configurationgroupschemas\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers configuration group schema\" }\n ,\"microsoft.hybridnetwork/proxypublishers/networkfunctiondefinitiongroups\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers network function definition group\" }\n ,\"microsoft.hybridnetwork/proxypublishers/networkfunctiondefinitiongroups/networkfunctiondefinitionversions\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers network function definition groups network function definition version\" }\n ,\"microsoft.hybridnetwork/proxypublishers/networkservicedesigngroups\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers network service design group\" }\n ,\"microsoft.hybridnetwork/proxypublishers/networkservicedesigngroups/networkservicedesignversions\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers network service design groups network service design version\" }\n ,\"microsoft.hybridnetwork/publishers\": { \"SingularDisplayName\": \"Publisher\" }\n ,\"microsoft.hybridnetwork/publishers/artifactstores\": { \"SingularDisplayName\": \"Publisher Artifact Store\" }\n ,\"microsoft.hybridnetwork/publishers/artifactstores/artifactmanifests\": { \"SingularDisplayName\": \"Publisher Artifact Manifest\" }\n ,\"microsoft.hybridnetwork/publishers/configurationgroupschemas\": { \"SingularDisplayName\": \"Configuration Group Schema\" }\n ,\"microsoft.hybridnetwork/publishers/networkfunctiondefinitiongroups\": { \"SingularDisplayName\": \"Network Function Definition\" }\n ,\"microsoft.hybridnetwork/publishers/networkfunctiondefinitiongroups/networkfunctiondefinitionversions\": { \"SingularDisplayName\": \"Network Function Definition Version\" }\n ,\"microsoft.hybridnetwork/publishers/networkservicedesigngroups\": { \"SingularDisplayName\": \"Network Service Design\" }\n ,\"microsoft.hybridnetwork/publishers/networkservicedesigngroups/networkservicedesignversions\": { \"SingularDisplayName\": \"Network Service Design Version\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management container\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/rolloutsequences\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers rollout sequence\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/rollouttiers\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers rollout tier\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/updatespecifications\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers update specification\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/updatespecifications/rollouts\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers update specifications rollout\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/updatespecifications/rollouts/statuses\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers update specifications rollouts statuse\" }\n ,\"microsoft.hybridnetwork/sitenetworkservices\": { \"SingularDisplayName\": \"Site Network Service\" }\n ,\"microsoft.hybridnetwork/sites\": { \"SingularDisplayName\": \"Site\" }\n })[tolower(id)]\n}\n", - "$fxv#10": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// See known issues @ https://github.com/microsoft/finops-toolkit/issues/1111\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Prices |=========================================================================================================\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_transform_v1_2 function\n.create-or-alter function\nwith (docstring='Transforms Prices_raw into FOCUS 1.2.', folder='Prices')\nPrices_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n let prices = materialize(\n Prices_raw\n | extend PricingCurrency = coalesce(Currency, CurrencyCode) // CurrencyCode last as a fallback only\n | extend x_SkuId = coalesce(SkuId, SkuID)\n | extend x_SkuMeterId = coalesce(MeterId, MeterID)\n | extend x_SkuProductId = coalesce(ProductId, ProductID)\n | extend x_SkuTerm = isoMonths(Term)\n | project-rename\n SkuMeter = MeterName,\n x_BaseUnitPrice = BasePrice,\n x_EffectivePeriodEnd = EffectiveEndDate,\n x_EffectivePeriodStart = EffectiveStartDate,\n x_PricingUnitDescription = UnitOfMeasure,\n x_SkuIncludedQuantity = IncludedQuantity,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuMeterType = MeterType,\n x_SkuOfferId = OfferID,\n x_SkuPartNumber = PartNumber,\n x_SkuPriceType = PriceType,\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTier = TierMinimumUnits\n | extend ContractedUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', UnitPrice, real(null)) // UnitPrice for savings plan is not the on-demand unit price\n | extend ListUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', MarketPrice, real(null)) // MarketPrice for savings plan is not the list price\n | extend ChargeCategory = case(\n x_SkuPriceType == 'Consumption', 'Usage',\n x_SkuPriceType == 'ReservedInstance', 'Purchase',\n x_SkuPriceType == 'SavingsPlan', 'Usage', // Savings plan prices are for committed usage, not the purchase\n ''\n )\n | extend SkuPriceIdv2 = strcat(case(x_SkuPriceType == 'Consumption', 'OD', x_SkuPriceType == 'ReservedInstance', 'RI', x_SkuPriceType == 'SavingsPlan', 'SP', 'XX'), substring(ChargeCategory, 0, 1), x_SkuTerm, '_', x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType, '_', x_SkuTier, x_SkuOfferId)\n | extend x_BillingAccountId = iff(BillingAccountId startswith '/', split(BillingAccountId, '/')[-1], coalesce(BillingAccountId, EnrollmentNumber))\n | extend x_BillingProfileId = iff(BillingProfileId startswith '/', split(BillingProfileId, '/')[-1], coalesce(BillingProfileId, EnrollmentNumber))\n | extend tmp_SavingsPlanKey = strcat(x_SkuMeterId, x_SkuProductId, x_SkuId, x_SkuTier, x_SkuOfferId)\n //\n // Get latest ingested row based on the unique ID\n | extend x_IngestionTime = ingestion_time()\n );\n //\n // Meters for reservations and savings plans to identify commitment eligibility\n let riMeters = prices | where x_SkuPriceType == 'ReservedInstance' | distinct x_SkuMeterId;\n let spMeters = prices | where x_SkuPriceType == 'SavingsPlan' | distinct x_SkuMeterId;\n //\n // Copy list/base/contracted prices from on-demand SKUs\n prices\n | where x_SkuPriceType == 'SavingsPlan'\n // If we use join, specify the shuffle key\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter hint.strategy=shuffle (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | lookup kind=leftouter (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | extend ListUnitPrice = coalesce(ListUnitPrice, ListUnitPrice1)\n | extend ContractedUnitPrice = coalesce(ContractedUnitPrice, ContractedUnitPrice1)\n | extend x_BaseUnitPrice = coalesce(x_BaseUnitPrice, x_BaseUnitPrice1)\n | project-away ListUnitPrice1, ContractedUnitPrice1, x_BaseUnitPrice1, tmp_SavingsPlanKey\n | union ((prices | where x_SkuPriceType != 'SavingsPlan'))\n //\n // Set CommitmentDiscountCategory for reuse\n | extend CommitmentDiscountCategory = case(\n x_SkuPriceType == 'ReservedInstance', 'Usage',\n x_SkuPriceType == 'SavingsPlan', 'Spend',\n ''\n )\n //\n // Calculate commitment discount eligibility\n // TODO: Would a join be faster?\n // TODO: Check this to ensure it's correct\n | extend x_CommitmentDiscountSpendEligibility = iff(x_SkuMeterId in (riMeters) and x_SkuPriceType != 'ReservedInstance', 'Eligible', 'Not Eligible')\n | extend x_CommitmentDiscountUsageEligibility = iff(x_SkuMeterId in (spMeters), 'Eligible', 'Not Eligible')\n //\n // TODO: Implement x_CommitmentDiscountNormalizedRatio\n | extend x_CommitmentDiscountNormalizedRatio = real(null)\n //\n // Add PricingUnit and x_PricingBlockSize\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter (PricingUnits) on x_PricingUnitDescription | project-away x_PricingUnitDescription1\n | lookup kind=leftouter (PricingUnits) on x_PricingUnitDescription\n //\n | extend x_EffectiveUnitPrice = iff(x_SkuPriceType == 'SavingsPlan', UnitPrice, real(null)) // Savings plan prices are for the effective price, not the contracted price\n | extend x_EffectiveUnitPriceDiscount = ContractedUnitPrice - x_EffectiveUnitPrice\n | extend x_ContractedUnitPriceDiscount = ListUnitPrice - ContractedUnitPrice\n | extend x_TotalUnitPriceDiscount = ListUnitPrice - x_EffectiveUnitPrice\n | project\n BillingAccountId = tolower(case(\n BillingProfileId startswith '/', BillingProfileId,\n BillingAccountId startswith '/', BillingAccountId,\n strcat('/providers/microsoft.billing/billingaccounts/', x_BillingAccountId, iff(x_BillingProfileId == x_BillingAccountId, '', strcat('/billingprofiles/', x_BillingProfileId)))\n )),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName, x_BillingProfileId),\n BillingCurrency = coalesce(BillingCurrency, CurrencyCode, Currency), // Currency last as a fallback only\n ChargeCategory,\n CommitmentDiscountCategory,\n CommitmentDiscountType = case(\n x_SkuPriceType == 'ReservedInstance', 'Reservation',\n x_SkuPriceType == 'SavingsPlan', 'Savings plan',\n ''\n ),\n CommitmentDiscountUnit = case(\n isempty(CommitmentDiscountCategory), '',\n CommitmentDiscountCategory == 'Spend', PricingCurrency,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio == real(1), PricingUnit,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio > real(1), strcat('Normalized ', PricingUnit),\n ''\n ),\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory = case(\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed',\n ''\n ),\n PricingCurrency,\n PricingUnit,\n SkuId = coalesce(ProductId, ProductID),\n SkuMeter,\n SkuPriceId = strcat(x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType),\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement = case(\n strlen(x_BillingAccountId) > 32, 'MCA',\n strlen(x_BillingAccountId) < 32, 'EA',\n 'Unknown'\n ),\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent = 1.0 * x_ContractedUnitPriceDiscount / ListUnitPrice * 100,\n x_EffectivePeriodEnd = startofmonth(x_EffectivePeriodEnd + 1h),\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent = 1.0 * x_EffectiveUnitPriceDiscount / ContractedUnitPrice * 100,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingSubcategory = case(\n x_SkuPriceType == 'Consumption' and (x_SkuIncludedQuantity > 0 or x_SkuTier > 0), 'Tiered',\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed Spend',\n ''\n ),\n x_PricingUnitDescription,\n x_SkuDescription = Product,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName = coalesce(x_SourceName, 'Cost Management'),\n x_SourceProvider = coalesce(x_SourceProvider, 'Microsoft'),\n x_SourceType = coalesce(x_SourceType, 'PriceSheet'),\n x_SourceVersion = coalesce(x_SourceVersion, '2023-05-01'),\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent = 1.0 * x_TotalUnitPriceDiscount / ListUnitPrice * 100\n}\n\n// Prices_final_v1_2 table\n.create-merge table Prices_final_v1_2 (\n BillingAccountId: string,\n BillingAccountName: string,\n BillingCurrency: string,\n ChargeCategory: string,\n CommitmentDiscountCategory: string,\n CommitmentDiscountType: string,\n CommitmentDiscountUnit: string,\n ContractedUnitPrice: real,\n ListUnitPrice: real,\n PricingCategory: string,\n PricingCurrency: string, // Azure\n PricingUnit: string,\n SkuId: string,\n SkuMeter: string, // Azure\n SkuPriceId: string,\n SkuPriceIdv2: string, // Hubs add-on\n x_BaseUnitPrice: real, // Azure\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure MCA\n x_BillingProfileId: string, // Azure MCA\n x_CommitmentDiscountNormalizedRatio: real, // Hubs add-on\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_ContractedUnitPriceDiscount: real, // Hubs add-on\n x_ContractedUnitPriceDiscountPercent: real, // Hubs add-on\n x_EffectivePeriodEnd: datetime, // Azure\n x_EffectivePeriodStart: datetime, // Azure\n x_EffectiveUnitPrice: real, // Azure\n x_EffectiveUnitPriceDiscount: real, // Hubs add-on\n x_EffectiveUnitPriceDiscountPercent: real, // Hubs add-on\n x_IngestionTime: datetime, // Hubs add-on\n x_PricingBlockSize: real, // Hubs add-on\n x_PricingSubcategory: string, // Hubs add-on\n x_PricingUnitDescription: string, // Azure\n x_SkuDescription: string, // Azure\n x_SkuId: string, // Azure\n x_SkuIncludedQuantity: real, // Azure EA\n x_SkuMeterCategory: string, // Azure\n x_SkuMeterId: string, // Azure\n x_SkuMeterSubcategory: string, // Azure\n x_SkuMeterType: string, // Azure\n x_SkuPriceType: string, // Azure\n x_SkuProductId: string, // Azure\n x_SkuRegion: string, // Azure\n x_SkuServiceFamily: string, // Azure\n x_SkuOfferId: string, // Azure EA\n x_SkuPartNumber: string, // Azure EA\n x_SkuTerm: int, // Azure\n x_SkuTier: real, // Azure MCA\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_TotalUnitPriceDiscount: real, // Hubs add-on\n x_TotalUnitPriceDiscountPercent: real // Hubs add-on\n)\n\n// Update policy for Prices_raw -> Prices_final_v1_2\n.alter table Prices_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Prices_raw\",\n \"Query\": \"Prices_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Cost and usage |=================================================================================================\n// Supported versions:\n// - MS: 1.2-preview, 1.0, 1.0-preview(v1)\n// https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0\n// https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024\n// https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 \n// https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All costs transformed to FOCUS 1.2.', folder='Costs')\nCosts_transform_v1_2()\n{\n let checkString = (column: string, oldValue: string, newValue: string) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n let checkInt = (column: string, oldValue: int, newValue: int) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n let checkReal = (column: string, oldValue: real, newValue: real) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n Costs_raw\n //\n // Dedupe rows\n | extend x_IngestionTime = ingestion_time()\n | extend x_ChargeId = ''\n // TODO: Consider adding a unique charge ID per row\n // hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // // 1. Resource hierarchy (including resource name), highest to lowest\n // BillingAccountId,\n // x_InvoiceSectionId,\n // x_AccountOwnerId,\n // SubAccountId,\n // x_ResourceGroupName,\n // ResourceName,\n // // 2. Resource details\n // ResourceId,\n // RegionId,\n // Tags,\n // CommitmentDiscountId,\n // x_CostCenter,\n // // 4. Meter details\n // SkuPriceId,\n // x_SkuMeterId,\n // x_SkuPartNumber,\n // x_SkuOfferId,\n // x_SkuDetails,\n // // 5. Date\n // ChargePeriodStart\n // ))\n //\n // Identify data quality issues\n // TODO: Remove x_SourceChanges in v1_3 (or later)\n | extend x_SourceChanges = trim_end(',', strcat(\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based', 'InvalidChargeFrequency,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and EffectiveCost > 0, 'InvalidEffectiveCost,', ''),\n iff((isempty(ContractedCost) or ContractedCost == 0) and EffectiveCost != 0, 'MissingContractedCost,', ''),\n iff((isempty(ContractedUnitPrice) or ContractedUnitPrice == 0) and x_EffectiveUnitPrice != 0, 'MissingContractedUnitPrice,', ''),\n iff(ListCost < ContractedCost, 'ListCostLessThanContractedCost,', ''),\n iff(ContractedCost < EffectiveCost, 'ContractedCostLessThanEffectiveCost,', ''),\n iff((isempty(ListCost) or ListCost == 0) and (ContractedCost != 0 or EffectiveCost != 0), 'MissingListCost,', ''),\n iff((isempty(ListUnitPrice) or ListUnitPrice == 0) and (ContractedUnitPrice != 0 or x_EffectiveUnitPrice != 0), 'MissingListUnitPrice,', ''),\n iff((isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001)\n or (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001),\n 'XEffectiveUnitPriceRoundingError,', ''),\n iff(ConsumedQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingConsumedQuantity,', ''),\n iff(PricingQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingPricingQuantity,', ''),\n iff(isempty(ProviderName), 'MissingProviderName,', ''),\n iff(isempty(PublisherName), 'MissingPublisherName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceId), 'MissingResourceId,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceName), 'MissingResourceName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceType), 'MissingResourceType,', ''),\n iff(BilledCost > 0 and x_BilledUnitPrice == 0, 'MissingXBilledUnitPrice,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(x_ResourceType), 'MissingXResourceType,', ''),\n iff(PricingCategory == 'Standard' and isnotempty(CommitmentDiscountId) and ChargeCategory == 'Usage', 'PricingCategoryShouldBeCommitted,', ''),\n iff(x_SkuTerm == '1Year' or x_SkuTerm == '3Years' or x_SkuTerm == '5Years', 'SkuTermShouldBeAnInteger,', '')\n ))\n //\n // Handle provider columns that moved to FOCUS\n | extend PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency)\n //\n // Backup original prices/costs before the merge\n | extend old_ContractedCost = ContractedCost\n | extend old_ContractedUnitPrice = ContractedUnitPrice\n | extend old_ListCost = ListCost\n | extend old_ListUnitPrice = ListUnitPrice\n | extend old_x_EffectiveUnitPrice = x_EffectiveUnitPrice\n //\n // Fix columns needed in other changes\n | extend old_ProviderName = ProviderName, ProviderName = case(\n isnotempty(ProviderName), ProviderName,\n isnotempty(coalesce(x_CostCategories, x_Discount, x_Operation, x_ServiceCode, x_UsageType)), 'AWS',\n isnotempty(coalesce(tostring(UsageAmount), tostring(x_Cost), x_Credits, x_CostType, tostring(x_CurrencyConversionRate), tostring(x_ExportTime), x_Project, x_ServiceId)), 'GCP',\n isnotempty(coalesce(x_BillingProfileId, x_InvoiceSectionId)), 'Microsoft',\n ''\n )\n //\n // Identify source\n | extend x_SourceName = coalesce(x_SourceName, iff(isnotempty(x_BillingProfileId), 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(isnotempty(x_BillingProfileId), 'FocusCost', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, case(\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)) and isempty(SkuPriceDetails) and isnotempty(x_SkuDetails), '1.2-preview',\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)), '1.2',\n isnotempty(coalesce(ChargeClass, CommitmentDiscountStatus, tostring(ConsumedQuantity), ConsumedUnit, tostring(ContractedCost), tostring(ContractedUnitPrice), RegionId, RegionName)), '1.0',\n isnotempty(coalesce(ChargeSubcategory, Region, tostring(UsageQuantity), UsageUnit)), iff(ProviderName == 'Microsoft', '1.0-preview(v1)', '1.0-preview'),\n ''\n ))\n // Append version check error code\n | extend x_SourceChanges = iff(x_SourceVersion == '1.0', x_SourceChanges,\n strcat(x_SourceChanges, iff(isempty(x_SourceChanges), '', ','), iff(x_SourceVersion == '', 'UnknownFocusVersion', 'LegacyFocusVersion'))\n )\n //\n // Fix quantities\n | extend old_PricingQuantity = PricingQuantity, PricingQuantity = case(\n PricingQuantity != 0 or (EffectiveCost == 0 and BilledCost == 0), PricingQuantity,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(EffectiveCost) and EffectiveCost != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0, EffectiveCost / x_EffectiveUnitPrice,\n PricingQuantity\n )\n | extend old_ConsumedQuantity = ConsumedQuantity, ConsumedQuantity = case(\n isnotempty(ConsumedQuantity) and ConsumedQuantity != 0, ConsumedQuantity,\n ChargeCategory == 'Usage', PricingQuantity / coalesce(x_PricingBlockSize, real(1)),\n ConsumedQuantity\n )\n //\n // Populate missing prices -- mapping to on-demand prices requires meter ID and offer ID\n | extend tmp_MissingPrices = ProviderName == 'Microsoft'\n and (isempty(ListUnitPrice) or isempty(ContractedUnitPrice) or ListUnitPrice == 0 or ContractedUnitPrice == 0)\n and x_EffectiveUnitPrice != 0\n and not(CommitmentDiscountCategory == 'Spend' and CommitmentDiscountStatus == 'Unused')\n and isnotempty(strcat(x_SkuMeterId, x_SkuOfferId))\n | as allCosts\n | where tmp_MissingPrices\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(ChargePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | as costsWithMissingPrices\n | join kind=leftouter (\n Prices_final_v1_2\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(x_EffectivePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | where x_SkuPriceType == 'Consumption' and tmp_ReservationPriceLookupKey in ((costsWithMissingPrices | summarize by tmp_ReservationPriceLookupKey))\n | summarize ListUnitPrice = min(ListUnitPrice), ContractedUnitPrice = min(ContractedUnitPrice) by tmp_ReservationPriceLookupKey, x_PricingBlockSize, PricingUnit\n ) on tmp_ReservationPriceLookupKey\n //\n // Select the best price to use for each row\n | extend x_EffectiveUnitPrice = case(\n // If price is a rounding error away from the billed price, use the billed price\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001, x_BilledUnitPrice,\n // If price is a rounding error away from the contracted price, use the contracted price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001, ContractedUnitPrice,\n x_EffectiveUnitPrice\n )\n | extend ContractedUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ContractedUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ContractedUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // If billed price is available, assume the billed price is the same as contracted price to support aggregations\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, x_EffectiveUnitPrice,\n // Otherwise, assume the effective price is the same as contracted price to support aggregations\n x_EffectiveUnitPrice\n )\n | extend ListUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ListUnitPrice) and ListUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ListUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ListUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ListUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // Otherwise, assume the contracted price is the same as list price to support aggregations\n ContractedUnitPrice\n )\n // Calculate missing costs based on new prices -- If cost is already correct, keep that; if not and price is available, recalculate the cost; otherwise, keep the existing cost\n | extend ContractedCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ContractedCost) and ContractedCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedCost,\n // ContractedCost is 0 in all other scenarios...\n // If 0 and there's a billed cost and prices are the same, use BilledCost\n isnotempty(BilledCost) and BilledCost != 0 and ContractedUnitPrice == x_BilledUnitPrice, BilledCost,\n // If 0 and there's a billed cost and prices are the same, use EffectiveCost\n isnotempty(EffectiveCost) and EffectiveCost != 0 and ContractedUnitPrice == x_EffectiveUnitPrice, EffectiveCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0, ContractedUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume EffectiveCost\n isempty(ContractedUnitPrice) or ContractedUnitPrice == 0, EffectiveCost,\n // Fall back to the original value for any unhandled scenarios\n ContractedCost\n )\n | extend ListCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ListCost) and ListCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ListCost,\n // ListCost is 0 in all other scenarios...\n // If 0 and there's a contracted cost and prices are the same, use ContractedCost\n isnotempty(ContractedCost) and ContractedCost != 0 and ListUnitPrice == ContractedUnitPrice, ContractedCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ListUnitPrice) and ListUnitPrice != 0, ListUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume ContractedCost\n isempty(ListUnitPrice) or ListUnitPrice == 0, ContractedCost,\n // Fall back to the original value for any unhandled scenarios\n ListCost\n )\n // Merge the rest of the unmodified cost records and remove excess columns\n | union (allCosts | where not(tmp_MissingPrices))\n | project-away x_PricingBlockSize1, PricingUnit1, ListUnitPrice1, ContractedUnitPrice1, tmp_MissingPrices, tmp_ReservationPriceLookupKey, tmp_ReservationPriceLookupKey1\n //\n | extend SkuPriceDetails = parse_json(SkuPriceDetails)\n | extend Tags = parse_json(Tags)\n | extend x_SkuDetails = parse_json(x_SkuDetails)\n //\n // Handle FOCUS 1.0-preview\n | extend old_ChargeSubcategory = ChargeSubcategory\n | extend old_ChargeCategory = ChargeCategory, ChargeCategory = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Credit', 'Credit',\n ChargeSubcategory == 'Refund', 'Purchase', // We are assuming purchase refunds since we don't have data to indicate usage refunds\n ChargeCategory\n )\n | extend old_ChargeClass = ChargeClass, ChargeClass = case(ChargeSubcategory == 'Refund', 'Correction', ChargeClass)\n //\n // Populate CapacityReservationId when not specified\n | extend CapacityReservationId = coalesce(CapacityReservationId, tostring(coalesce(x_SkuDetails.VMCapacityReservationId, SkuPriceDetails.VMCapacityReservationId, SkuPriceDetails.x_VMCapacityReservationId)))\n | extend old_CapacityReservationStatus = CapacityReservationStatus, CapacityReservationStatus = case(\n isempty(CapacityReservationId), '',\n isnotempty(CapacityReservationStatus), CapacityReservationStatus,\n tolower(x_ResourceType) == 'microsoft.compute/capacityreservationgroups/capacityreservations', 'Unused',\n 'Used'\n )\n //\n // BUG: ChargeFrequency shows \"Usage-Based\" for monthly recurring savings plan purchases\n | extend old_ChargeFrequency = ChargeFrequency, ChargeFrequency = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based' and ProviderName == 'Microsoft' and x_SourceVersion startswith '1.0', 'Recurring', ChargeFrequency)\n //\n // Commitment discounts\n | extend x_CommitmentDiscountNormalizedRatio = case(\n // Calculate from CommitmentDiscountQuantity, if specified\n isnotempty(CommitmentDiscountQuantity) and CommitmentDiscountQuantity != 0, CommitmentDiscountQuantity / PricingQuantity / coalesce(x_PricingBlockSize, real(1)),\n // Not applicable\n isempty(CommitmentDiscountStatus), real(null),\n // Parse from SKU details if not specified explicitly\n toreal(coalesce(x_SkuDetails.RINormalizationRatio, SkuPriceDetails.RINormalizationRatio, SkuPriceDetails.x_RINormalizationRatio, dynamic(1)))\n )\n | extend old_CommitmentDiscountQuantity = CommitmentDiscountQuantity, CommitmentDiscountQuantity = case(\n // FOCUS 1.2\n isnotempty(CommitmentDiscountQuantity), CommitmentDiscountQuantity,\n // FOCUS 1.0-preview, 1.0\n isempty(CommitmentDiscountStatus), real(null),\n CommitmentDiscountCategory == 'Spend', EffectiveCost / coalesce(x_BillingExchangeRate, real(1)),\n CommitmentDiscountCategory == 'Usage' and isnotempty(x_CommitmentDiscountNormalizedRatio), PricingQuantity / coalesce(x_PricingBlockSize, real(1)) * x_CommitmentDiscountNormalizedRatio,\n real(null)\n )\n | extend old_CommitmentDiscountUnit = CommitmentDiscountUnit, CommitmentDiscountUnit = case(\n // FOCUS 1.2\n isnotempty(CommitmentDiscountUnit), CommitmentDiscountUnit,\n // FOCUS 1.0\n isempty(CommitmentDiscountQuantity), '',\n CommitmentDiscountCategory == 'Spend', PricingCurrency,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio == real(1), ConsumedUnit,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio > real(1), strcat('Normalized ', ConsumedUnit),\n ''\n )\n | extend old_CommitmentDiscountStatus = CommitmentDiscountStatus, CommitmentDiscountStatus = case(\n // FOCUS 1.0+\n isnotempty(CommitmentDiscountStatus), CommitmentDiscountStatus,\n // FOCUS 1.0-preview\n ChargeSubcategory == 'Used Commitment', 'Used',\n ChargeSubcategory == 'Unused Commitment', 'Unused',\n ''\n )\n | extend x_CommitmentDiscountUtilizationPotential = case(\n ChargeCategory == 'Purchase', real(0),\n ProviderName == 'Microsoft' and isnotempty(CommitmentDiscountCategory), EffectiveCost,\n CommitmentDiscountCategory == 'Usage', ConsumedQuantity,\n CommitmentDiscountCategory == 'Spend', EffectiveCost,\n real(0)\n )\n | extend x_CommitmentDiscountUtilizationAmount = iff(CommitmentDiscountStatus == 'Used', x_CommitmentDiscountUtilizationPotential, real(0))\n //\n // Pricing\n | extend old_x_AmortizationClass = x_AmortizationClass, x_AmortizationClass = case(\n // FOCUS 1.2\n isnotempty(x_AmortizationClass), x_AmortizationClass,\n // FOCUS 1.0-preview+\n ChargeCategory == 'Purchase' and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeCategory == 'Usage' and isnotempty(CommitmentDiscountId) and isnotempty(CommitmentDiscountStatus), 'Amortized Charge',\n ''\n )\n | extend old_PricingCategory = PricingCategory, PricingCategory = case(\n // FOCUS 1.0+\n isnotempty(PricingCategory), PricingCategory,\n // FOCUS 1.0-preview\n PricingCategory == 'On-Demand', 'Standard',\n PricingCategory == 'Commitment-Based', 'Committed',\n ''\n )\n //\n // Commitment discount utilization\n | extend x_CommitmentDiscountUtilizationPotential = case(\n ChargeCategory == 'Purchase', real(0),\n ProviderName == 'Microsoft' and isnotempty(CommitmentDiscountCategory), EffectiveCost,\n CommitmentDiscountCategory == 'Usage', ConsumedQuantity,\n CommitmentDiscountCategory == 'Spend', EffectiveCost,\n real(0)\n )\n | extend x_CommitmentDiscountUtilizationAmount = iff(CommitmentDiscountStatus == 'Used', x_CommitmentDiscountUtilizationPotential, real(0))\n //\n // BUG: Fix ContractedCost that has bad values\n | extend ContractedCost = iff(ProviderName == 'Microsoft' and isnotempty(PricingQuantity) and isnotempty(x_PricingBlockSize) and ContractedCost != ContractedUnitPrice * PricingQuantity, ContractedUnitPrice * PricingQuantity, ContractedCost)\n //\n // Handle FOCUS 1.0-preview UsageQuantity/Unit\n | extend ConsumedQuantity = iff(ChargeCategory == 'Usage', coalesce(ConsumedQuantity, UsageQuantity, UsageAmount), real(null))\n | extend old_ConsumedUnit = ConsumedUnit, ConsumedUnit = iff(ChargeCategory == 'Usage' and isnotempty(ConsumedQuantity), coalesce(ConsumedUnit, UsageUnit, 'Units'), '')\n //\n // Convert IDs to lowercase for consistency\n | extend BillingAccountId = tolower(BillingAccountId)\n | extend CommitmentDiscountId = tolower(CommitmentDiscountId)\n //\n // BUG: Remove EffectiveCost for commitment discount purchases\n | extend old_EffectiveCost = EffectiveCost, EffectiveCost = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), real(0), EffectiveCost)\n | extend old_x_EffectiveCostInUsd = x_EffectiveCostInUsd, x_EffectiveCostInUsd = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), real(0), x_EffectiveCostInUsd)\n //\n // Clean up resource columns\n | extend old_ResourceId = ResourceId, ResourceId = case(\n isnotempty(ResourceId), ResourceId,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), CommitmentDiscountId,\n ResourceId\n )\n | extend old_ResourceName = ResourceName, ResourceName = tolower(case(\n isnotempty(ResourceName), ResourceName,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountName), CommitmentDiscountName,\n isnotempty(ResourceId), parse_resourceid(ResourceId).ResourceName,\n ResourceName\n ))\n | extend old_x_ResourceType = x_ResourceType, x_ResourceType = case(\n isnotempty(x_ResourceType), x_ResourceType,\n isnotempty(ResourceId), parse_resourceid(ResourceId).x_ResourceType,\n x_ResourceType\n )\n | extend old_ResourceType = ResourceType, ResourceType = case(\n // Use existing resource type display name unless it's an internal resource type ID\n isnotempty(ResourceType) and tolower(ResourceType) != tolower(x_ResourceType) and ResourceType !contains '/', ResourceType,\n // Use CommitmentDiscountType for commitment discount purchases\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountType), CommitmentDiscountType,\n // Look up display name from internal type\n isnotempty(x_ResourceType), coalesce(tostring(resource_type(x_ResourceType).SingularDisplayName), ResourceType, x_ResourceType),\n ResourceType\n )\n //\n // Handle missing values\n | extend old_PublisherName = PublisherName, PublisherName = case(PublisherName == 'Microsoft Corporation', 'Microsoft', isnotempty(PublisherName), PublisherName, x_PublisherCategory == 'Cloud Provider', ProviderName, '')\n //\n // Handle FOCUS 1.0-preview Region column\n | extend old_Region = Region\n | extend old_RegionId = RegionId, RegionId = coalesce(RegionId, iff(ProviderName == 'Microsoft', replace_string(tolower(Region), ' ', ''), Region))\n | extend RegionName = coalesce(RegionName, Region)\n //\n // SKU properties\n | extend x_SkuCoreCount = toint(coalesce(SkuPriceDetails.CoreCount, SkuPriceDetails.x_VCPUs, x_SkuDetails.VCPUs, SkuPriceDetails.x_VCores, x_SkuDetails.VCores, SkuPriceDetails.x_vCores, x_SkuDetails.vCores))\n | extend x_SkuInstanceType = tostring(coalesce(SkuPriceDetails.InstanceType, SkuPriceDetails.x_ServiceType, x_SkuDetails.ServiceType, SkuPriceDetails.x_ServerSku, x_SkuDetails.ServerSku))\n | extend x_SkuOperatingSystem = case(\n isnotempty(SkuPriceDetails.OperatingSystem), SkuPriceDetails.OperatingSystem,\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Canonical', 'Linux',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL', 'Windows Server',\n x_SkuMeterSubcategory endswith ' Series Windows', 'Windows Server',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType)\n )\n | extend x_ConsumedCoreHours = iff(ConsumedUnit == 'Hours' and isnotempty(x_SkuCoreCount), x_SkuCoreCount * ConsumedQuantity, real(null))\n | extend SkuPriceDetails = case(\n // FOCUS 1.2\n isnotempty(SkuPriceDetails), SkuPriceDetails,\n // FOCUS 1.0-preview, 1.0\n parse_json(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(tostring(x_SkuDetails)\n // Prefix all keys with x_ first to avoid double-prefixing\n , @'([\\{,])\"', @'\\1\"x_')\n // CoreCount for number of CPUs/vCPUs/cores/vCores\n , @'\"x_(VCPUs|VCores|vCores)\":', @'\"CoreCount\":')\n // TODO: DiskMaxIops for disk I/O operations per second (IOPS)\n // TODO: DiskSpace for disk size in GiB\n // TODO: DiskType for the kind of disk (e.g., SSD, HDD, NVMe)\n // TODO: GpuCount for the number of GPUs\n // InstanceType for the resource size/SKU (e.g., ArmSkuName)\n , @'\"x_(ServerSku|ServiceType)\":', @'\"InstanceType\":')\n // TODO: InstanceSeries for the size family/series\n // TODO: MemorySize for the RAM in GiB\n // TODO: NetworkMaxIops for network I/O operations per second (IOPS)\n // TODO: NetworkMaxThroughput for network max throughput for data transfer in Mbps\n // OperatingSystem for the OS name\n , @'(\"x_ImageType\":\"Canonical\")', @'\\1,\"OperatingSystem\":\"Linux\"')\n , @'(\"x_ImageType\":\"Windows Server( BYOL)?\")', @'\\1,\"OperatingSystem\":\"Windows Server\"')\n , @'(\"x_ImageType\":(\"[^\"]+\"))', @'\\1,\"OperatingSystem\":\\2')\n // TODO: Redundancy for the level of redundancy (e.g., Local, Zonal, Global)\n // TODO: StorageClass for the tier of storage (e.g., Hot, Archive, Nearline)\n )\n )\n | extend SkuPriceDetails = iff(isempty(SkuPriceDetails.OperatingSystem) and isnotempty(x_SkuOperatingSystem),\n parse_json(replace_string(tostring(SkuPriceDetails), '}', strcat(@',\"OperatingSystem\":\"', x_SkuOperatingSystem, '\"}'))),\n SkuPriceDetails)\n //\n // Azure Hybrid Benefit\n | extend tmp_SqlAhb = tolower(coalesce(x_SkuDetails.AHB, SkuPriceDetails.x_AHB))\n | extend x_SkuLicenseType = case(\n ChargeCategory != 'Usage', '',\n x_SkuMeterCategory in ('Virtual Machines', 'Virtual Machine Licenses') and (x_SkuMeterSubcategory contains 'Windows' or coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL'), 'Windows Server',\n isnotempty(tmp_SqlAhb) or x_SkuMeterSubcategory == 'SQL Server Azure Hybrid Benefit', 'SQL Server',\n ''\n )\n | extend x_SkuLicenseStatus = case(\n isempty(x_SkuLicenseType), '',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL' or tmp_SqlAhb == 'true' or x_SkuMeterSubcategory contains 'Azure Hybrid Benefit', 'Enabled',\n (x_SkuMeterSubcategory contains 'Windows') or tmp_SqlAhb == 'false', 'Not Enabled',\n ''\n )\n | extend x_SkuLicenseQuantity = case(\n isempty(x_SkuCoreCount) or isempty(x_SkuLicenseType), int(null),\n x_SkuCoreCount <= 8, int(8),\n x_SkuCoreCount > 8, x_SkuCoreCount,\n int(null)\n )\n | extend x_SkuLicenseUnit = iff(isnotempty(x_SkuLicenseQuantity), 'Cores', '')\n //\n // Savings\n | extend x_CommitmentDiscountSavings = iff(isempty(ContractedCost) or ContractedCost == 0 or ContractedCost - EffectiveCost < 0.0001, real(0), ContractedCost - EffectiveCost)\n | extend x_NegotiatedDiscountSavings = iff(isempty(ListCost) or ListCost == 0 or ListCost - ContractedCost < 0.0001, real(0), ListCost - ContractedCost)\n | extend x_TotalSavings = iff(isempty(ListCost) or ListCost == 0 or ListCost - EffectiveCost < 0.0001, real(0), ListCost - EffectiveCost)\n | extend x_CommitmentDiscountPercent = iff(isempty(ContractedUnitPrice) or ContractedUnitPrice == 0 or ContractedUnitPrice - x_EffectiveUnitPrice < 0.0001, real(0), (ContractedUnitPrice - x_EffectiveUnitPrice) / ContractedUnitPrice)\n | extend x_NegotiatedDiscountPercent = iff(isempty(ListUnitPrice) or ListUnitPrice == 0 or ListUnitPrice - ContractedUnitPrice < 0.0001, real(0), (ListUnitPrice - ContractedUnitPrice) / ListUnitPrice)\n | extend x_TotalDiscountPercent = iff(isempty(ListUnitPrice) or ListUnitPrice == 0 or ListUnitPrice - x_EffectiveUnitPrice < 0.0001, real(0), (ListUnitPrice - x_EffectiveUnitPrice) / ListUnitPrice)\n //\n // Minor fixes\n | extend old_BillingPeriodEnd = BillingPeriodEnd, BillingPeriodEnd = startofmonth(BillingPeriodEnd)\n | extend old_BillingPeriodStart = BillingPeriodStart, BillingPeriodStart = startofmonth(BillingPeriodStart)\n //\n // Sort columns and apply final transforms\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId,\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd,\n BillingPeriodStart,\n CapacityReservationId,\n CapacityReservationStatus,\n ChargeCategory,\n ChargeClass,\n ChargeDescription,\n ChargeFrequency,\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId,\n CommitmentDiscountName,\n CommitmentDiscountQuantity,\n CommitmentDiscountStatus,\n CommitmentDiscountType,\n CommitmentDiscountUnit,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost = coalesce(ContractedCost, x_OnDemandCost, x_Cost),\n ContractedUnitPrice = coalesce(ContractedUnitPrice, x_OnDemandUnitPrice),\n EffectiveCost,\n InvoiceId = coalesce(InvoiceId, x_InvoiceId),\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory,\n PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency),\n PricingQuantity,\n PricingUnit,\n ProviderName,\n PublisherName,\n RegionId,\n RegionName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory, // TODO: Populate ServiceSubcategory from ServiceName when missing\n SkuId,\n SkuMeter = coalesce(SkuMeter, x_SkuMeterName),\n SkuPriceDetails,\n SkuPriceId,\n SubAccountId,\n SubAccountName = iff(isempty(SubAccountId), '', SubAccountName),\n SubAccountType,\n Tags,\n x_AccountId = iff(x_AccountId == '-2', '', x_AccountId),\n x_AccountName = iff(x_AccountId == '-2', '', x_AccountName),\n x_AccountOwnerId = iff(x_AccountId == '-2', '', x_AccountOwnerId),\n x_AmortizationClass,\n x_BilledCostInUsd,\n x_BilledUnitPrice,\n x_BillingAccountAgreement = case(\n ProviderName == 'Microsoft' and x_BillingAccountId == x_BillingProfileId, 'EA',\n ProviderName == 'Microsoft' and x_BillingAccountId != x_BillingProfileId, 'MCA',\n ProviderName\n ),\n x_BillingAccountId,\n x_BillingAccountName,\n x_BillingExchangeRate,\n x_BillingExchangeRateDate,\n x_BillingItemCode,\n x_BillingItemName,\n x_BillingProfileId,\n x_BillingProfileName,\n x_ChargeId,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountPercent,\n x_CommitmentDiscountSavings,\n x_CommitmentDiscountSpendEligibility = '', // TODO: Add x_CommitmentDiscountSpendEligibility for Costs\n x_CommitmentDiscountUsageEligibility = '', // TODO: Add x_CommitmentDiscountUsageEligibility for Costs\n x_CommitmentDiscountUtilizationAmount,\n x_CommitmentDiscountUtilizationPotential,\n x_CommodityCode,\n x_CommodityName,\n x_ComponentName,\n x_ComponentType,\n x_ConsumedCoreHours,\n x_ContractedCostInUsd = coalesce(x_ContractedCostInUsd, x_OnDemandCostInUsd),\n x_CostAllocationRuleName,\n x_CostCategories = parse_json(x_CostCategories),\n x_CostCenter,\n x_CostType,\n x_Credits = parse_json(x_Credits),\n x_CurrencyConversionRate,\n x_CustomerId,\n x_CustomerName,\n x_Discount = parse_json(x_Discount),\n x_EffectiveCostInUsd,\n x_EffectiveUnitPrice,\n x_ExportTime,\n x_IngestionTime,\n x_InstanceID,\n x_InvoiceIssuerId,\n x_InvoiceSectionId = case(\n x_InvoiceSectionId == '-2', '',\n x_InvoiceSectionId\n ),\n x_InvoiceSectionName = case(\n x_InvoiceSectionName == 'Unassigned', '',\n x_InvoiceSectionName\n ),\n x_ListCostInUsd,\n x_Location,\n x_NegotiatedDiscountPercent,\n x_NegotiatedDiscountSavings,\n x_Operation,\n x_OwnerAccountID,\n x_PartnerCreditApplied,\n x_PartnerCreditRate,\n x_PricingBlockSize,\n x_PricingSubcategory,\n x_PricingUnitDescription = iff(x_PricingUnitDescription == 'Unassigned', '', x_PricingUnitDescription),\n x_Project,\n x_PublisherCategory,\n x_PublisherId,\n x_ResellerId,\n x_ResellerName,\n x_ResourceGroupName = tolower(x_ResourceGroupName),\n x_ResourceType,\n x_ServiceCode,\n x_ServiceId,\n x_ServiceModel, // TODO: Populate from ServiceName when missing\n x_ServicePeriodEnd,\n x_ServicePeriodStart,\n x_SkuCoreCount,\n x_SkuDescription,\n x_SkuDetails,\n x_SkuInstanceType,\n x_SkuIsCreditEligible,\n x_SkuLicenseQuantity,\n x_SkuLicenseStatus,\n x_SkuLicenseType,\n x_SkuLicenseUnit,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterSubcategory,\n x_SkuOfferId,\n x_SkuOperatingSystem,\n x_SkuOrderId,\n x_SkuOrderName,\n x_SkuPartNumber,\n x_SkuPlanName,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuTerm,\n x_SkuTier,\n x_SourceChanges,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceValues = bag_merge(\n checkString('BillingPeriodEnd', old_BillingPeriodEnd, BillingPeriodEnd),\n checkString('BillingPeriodStart', old_BillingPeriodStart, BillingPeriodStart),\n checkString('CapacityReservationStatus', old_CapacityReservationStatus, CapacityReservationStatus),\n checkString('ChargeCategory', old_ChargeCategory, ChargeCategory),\n checkString('ChargeClass', old_ChargeClass, ChargeClass),\n checkString('ChargeSubcategory', old_ChargeSubcategory, ''), // Not included in final schema; use empty string\n checkString('ChargeFrequency', old_ChargeFrequency, ChargeFrequency),\n checkReal('CommitmentDiscountQuantity', old_CommitmentDiscountQuantity, CommitmentDiscountQuantity),\n checkString('CommitmentDiscountUnit', old_CommitmentDiscountUnit, CommitmentDiscountUnit),\n checkString('CommitmentDiscountStatus', old_CommitmentDiscountStatus, CommitmentDiscountStatus),\n checkReal('ConsumedQuantity', old_ConsumedQuantity, ConsumedQuantity),\n checkString('ConsumedUnit', old_ConsumedUnit, ConsumedUnit),\n checkReal('ContractedCost', old_ContractedCost, ContractedCost),\n checkReal('ContractedUnitPrice', old_ContractedUnitPrice, ContractedUnitPrice),\n checkReal('EffectiveCost', old_EffectiveCost, EffectiveCost),\n checkReal('ListCost', old_ListCost, ListCost),\n checkReal('ListUnitPrice', old_ListUnitPrice, ListUnitPrice),\n checkString('PricingCategory', old_PricingCategory, PricingCategory),\n checkReal('PricingQuantity', old_PricingQuantity, PricingQuantity),\n checkString('ProviderName', old_ProviderName, ProviderName),\n checkString('PublisherName', old_PublisherName, PublisherName),\n checkString('Region', old_Region, ''), // Not included in final schema; use empty string\n checkString('RegionId', old_RegionId, RegionId),\n checkString('ResourceId', old_ResourceId, ResourceId),\n checkString('ResourceName', old_ResourceName, ResourceName),\n checkString('ResourceType', old_ResourceType, ResourceType),\n checkString('x_AmortizationClass', old_x_AmortizationClass, x_AmortizationClass),\n checkReal('x_EffectiveCostInUsd', old_x_EffectiveCostInUsd, x_EffectiveCostInUsd),\n checkReal('x_EffectiveUnitPrice', old_x_EffectiveUnitPrice, x_EffectiveUnitPrice),\n checkString('x_ResourceType', old_x_ResourceType, x_ResourceType)\n ),\n x_SourceVersion,\n x_SubproductName,\n x_TotalDiscountPercent,\n x_TotalSavings,\n x_UsageType\n}\n\n// Costs_final_v1_2 table\n.create-merge table Costs_final_v1_2 (\n AvailabilityZone: string,\n BilledCost: real,\n BillingAccountId: string,\n BillingAccountName: string,\n BillingAccountType: string,\n BillingCurrency: string,\n BillingPeriodEnd: datetime,\n BillingPeriodStart: datetime,\n CapacityReservationId: string,\n CapacityReservationStatus: string,\n ChargeCategory: string,\n ChargeClass: string,\n ChargeDescription: string,\n ChargeFrequency: string,\n ChargePeriodEnd: datetime,\n ChargePeriodStart: datetime,\n CommitmentDiscountCategory: string,\n CommitmentDiscountId: string,\n CommitmentDiscountName: string,\n CommitmentDiscountQuantity: real,\n CommitmentDiscountStatus: string,\n CommitmentDiscountType: string,\n CommitmentDiscountUnit: string,\n ConsumedQuantity: real,\n ConsumedUnit: string,\n ContractedCost: real,\n ContractedUnitPrice: real,\n EffectiveCost: real,\n InvoiceId: string,\n InvoiceIssuerName: string,\n ListCost: real,\n ListUnitPrice: real,\n PricingCategory: string,\n PricingCurrency: string,\n PricingQuantity: real,\n PricingUnit: string,\n ProviderName: string,\n PublisherName: string,\n RegionId: string,\n RegionName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n ServiceCategory: string,\n ServiceName: string,\n ServiceSubcategory: string,\n SkuId: string,\n SkuMeter: string,\n SkuPriceDetails: dynamic,\n SkuPriceId: string,\n SubAccountId: string,\n SubAccountName: string,\n SubAccountType: string,\n Tags: dynamic,\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_AmortizationClass: string, // Azure 1.2-preview+\n x_BilledCostInUsd: real, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: real, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: real, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingItemCode: string, // Alibaba 1.0\n x_BillingItemName: string, // Alibaba 1.0\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_CommitmentDiscountNormalizedRatio: real, // Azure 1.2-preview+\n x_CommitmentDiscountPercent: real, // Hubs add-on\n x_CommitmentDiscountSavings: real, // Hubs add-on\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_CommitmentDiscountUtilizationAmount: real, // Hubs add-on\n x_CommitmentDiscountUtilizationPotential: real, // Hubs add-on\n x_CommodityCode: string, // Alibaba 1.0\n x_CommodityName: string, // Alibaba 1.0\n x_ComponentName: string, // Tencent 1.0\n x_ComponentType: string, // Tencent 1.0\n x_ConsumedCoreHours: real, // Hubs add-on\n x_ContractedCostInUsd: real, // Azure 1.0+\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: dynamic, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_CostType: string, // GCP Jan 2024\n x_Credits: dynamic, // GCP Jan 2024\n x_CurrencyConversionRate: real, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: dynamic, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: real, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: real, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024 / Tencent 1.0\n x_IngestionTime: datetime, // Hubs add-on\n x_InstanceID: string, // Alibaba 1.0\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: real, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_NegotiatedDiscountPercent:real, // Hubs add-on\n x_NegotiatedDiscountSavings:real, // Hubs add-on\n x_Operation: string, // AWS 1.0\n x_OwnerAccountID: string, // Tencent 1.0\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: real, // Azure 1.0-preview(v1)+\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServiceModel: string, // Azure 1.2-preview+\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuCoreCount: int, // Hubs add-on\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: dynamic, // Azure 1.0-preview(v1)+\n x_SkuInstanceType: string, // Hubs add-on\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuLicenseQuantity: int, // Hubs add-on\n x_SkuLicenseStatus: string, // Hubs add-on\n x_SkuLicenseType: string, // Hubs add-on\n x_SkuLicenseUnit: string, // Hubs add-on\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOperatingSystem: string, // Hubs add-on\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuPlanName: string, // Azure 1.2-preview+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceChanges: string, // Hubs add-on\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceValues: dynamic, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubproductName: string, // Tencent 1.0\n x_TotalDiscountPercent: real, // Hubs add-on\n x_TotalSavings: real, // Hubs add-on\n x_UsageType: string // AWS 1.0\n)\n\n// Update policy for Costs_raw -> Costs_final_v1_2 table\n.alter table Costs_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Costs_raw\",\n \"Query\": \"Costs_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Actual costs |===================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_transform_v1_2 function\n.create-or-alter function\nwith (docstring='ActualCost exports transformed to FOCUS 1.2.', folder='Costs')\nActualCosts_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n ActualCosts_raw\n | where ChargeType in ('Purchase', 'Refund') and isnotempty(ReservationId)\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: PublisherName, x_PublisherCategory, x_Environment\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory), take_any(ServiceSubcategory), take_any(x_ServiceModel) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodEnd = Date + 1d,\n ChargePeriodStart = Date,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SkuId = '',\n SkuMeter = MeterName,\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = iff(isempty(SubscriptionId), '', SubscriptionName),\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentType = '',\n x_ComponentName = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = '',\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel,\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for ActualCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": true,\n \"Source\": \"ActualCosts_raw\",\n \"Query\": \"ActualCosts_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Amortized costs |================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_transform_v1_2 function\n.create-or-alter function\nwith (docstring='ActualCost exports transformed to FOCUS 1.2.', folder='Costs')\nAmortizedCosts_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n AmortizedCosts_raw\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: PublisherName, x_PublisherCategory, x_Environment\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory), take_any(ServiceSubcategory), take_any(x_ServiceModel) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodEnd = Date + 1d,\n ChargePeriodStart = Date,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SkuId = '',\n SkuMeter = MeterName,\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = iff(isempty(SubscriptionId), '', SubscriptionName),\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentType = '',\n x_ComponentName = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = '',\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel,\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for AmortizedCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": true,\n \"Source\": \"AmortizedCosts_raw\",\n \"Query\": \"AmortizedCosts_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All commitment discount usage transformed to FOCUS 1.2. This includes reservationdeatils_raw.', folder='Commitment discounts')\nCommitmentDiscountUsage_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n CommitmentDiscountUsage_raw\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Handle resource columns\n | extend ResourceId = tolower(InstanceId)\n | extend tmp_ResourceDetails = parse_resourceid(ResourceId)\n | extend ResourceName = tostring(tmp_ResourceDetails.ResourceName)\n | extend SubAccountId = tostring(tmp_ResourceDetails.SubAccountId)\n | extend x_ResourceGroupName = tostring(tmp_ResourceDetails.x_ResourceGroupName)\n | extend x_ResourceType = tostring(tmp_ResourceDetails.x_ResourceType)\n | lookup kind=leftouter (ResourceTypes | distinct x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n | lookup kind=leftouter (Services | distinct x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n //\n // Sort columns and apply final transforms\n | project\n ChargePeriodEnd = UsageDate + 1d,\n ChargePeriodStart = UsageDate,\n CommitmentDiscountCategory = 'Usage',\n CommitmentDiscountId = tolower(strcat('/providers/microsoft.capacity/reservationorders/', ReservationOrderId, '/reservations/', ReservationId)),\n CommitmentDiscountQuantity = UsedHours * InstanceFlexibilityRatio,\n CommitmentDiscountType = 'Reservation',\n CommitmentDiscountUnit = case(\n InstanceFlexibilityRatio == 1, 'Hours',\n InstanceFlexibilityRatio != 1, 'Normalized Hours',\n ''\n ),\n ConsumedQuantity = UsedHours,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SubAccountId,\n x_CommitmentDiscountCommittedCount = TotalReservedQuantity,\n x_CommitmentDiscountCommittedAmount = ReservedHours,\n // TODO: Is this needed? -- x_CommitmentDiscountKind = Kind,\n x_CommitmentDiscountNormalizedGroup = iff(InstanceFlexibilityGroup == 'NA', '', InstanceFlexibilityGroup),\n x_CommitmentDiscountNormalizedRatio = InstanceFlexibilityRatio,\n x_IngestionTime = ingestion_time(),\n x_ResourceGroupName,\n x_ResourceType,\n // x_RowId = hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // CommitmentDiscountId,\n // ResourceId,\n // ChargePeriodStart\n // )),\n x_ServiceModel,\n x_SkuOrderId = ReservationOrderId,\n x_SkuSize = iff(SkuName == 'NA', '', SkuName),\n x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName)),\n x_SourceProvider = coalesce(x_SourceProvider, ProviderName),\n x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationDetails', '')),\n x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2024-03-01', ''))\n}\n\n// CommitmentDiscountUsage_final_v1_2 table\n.create-merge table CommitmentDiscountUsage_final_v1_2 (\n ChargePeriodEnd: datetime, // Hubs add-on\n ChargePeriodStart: datetime, // MS 2023-03-01\n CommitmentDiscountCategory: string, // Hubs add-on\n CommitmentDiscountId: string, // MS 2023-03-01\n CommitmentDiscountQuantity: real, // MS 2023-03-01\n CommitmentDiscountType: string, // Hubs add-on\n CommitmentDiscountUnit: string, // Hubs add-on\n ConsumedQuantity: real, // MS 2023-03-01\n ProviderName: string, // Hubs add-on\n ResourceId: string, // MS 2023-03-01\n ResourceName: string, // Hubs add-on\n ResourceType: string, // Hubs add-on\n ServiceCategory: string, // Hubs add-on\n ServiceName: string, // Hubs add-on\n ServiceSubcategory: string, // Hubs add-on\n SubAccountId: string, // Hubs add-on\n x_CommitmentDiscountCommittedCount: real, // MS 2023-03-01\n x_CommitmentDiscountCommittedAmount: real, // MS 2023-03-01\n x_CommitmentDiscountNormalizedGroup: string, // MS 2023-03-01\n x_CommitmentDiscountNormalizedRatio: real, // MS 2023-03-01\n x_IngestionTime: datetime, // Hubs add-on\n x_ResourceGroupName: string, // Hubs add-on\n x_ResourceType: string, // Hubs add-on\n x_ServiceModel: string, // Hubs add-on\n x_SkuOrderId: string, // MS 2023-03-01\n x_SkuSize: string, // MS 2023-03-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string // Hubs add-on\n)\n\n// Update policy for CommitmentDiscountUsage_raw -> CommitmentDiscountUsage_final_v1_2 table\n.alter table CommitmentDiscountUsage_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"CommitmentDiscountUsage_raw\",\n \"Query\": \"CommitmentDiscountUsage_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All recommendations transformed to FOCUS 1.2.', folder='Recommendations')\nRecommendations_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Recommendations_raw\n | extend x_IngestionTime = ingestion_time()\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationRecommendations', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Convert JSON cost columns to real\n | extend CostWithNoReservedInstances = case(isnotempty(CostWithNoReservedInstances), CostWithNoReservedInstances, isnotempty(CostWithNoReservedInstancesJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, CostWithNoReservedInstancesJson)), CostWithNoReservedInstances)\n | extend NetSavings = case(isnotempty(NetSavings), NetSavings, isnotempty(NetSavingsJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, NetSavingsJson)), NetSavings)\n | extend TotalCostWithReservedInstances = case(isnotempty(TotalCostWithReservedInstances), TotalCostWithReservedInstances, isnotempty(TotalCostWithReservedInstancesJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, TotalCostWithReservedInstancesJson)), TotalCostWithReservedInstances)\n //\n // Parse x_RecommendationDetails from JSON string (ARG queries serialize to string for Parquet compatibility)\n | extend x_RecommendationDetails = iff(gettype(x_RecommendationDetails) == 'string', parse_json(tostring(x_RecommendationDetails)), x_RecommendationDetails)\n //\n // Normalize x_RecommendationDetails keys to x_PascalCase (Advisor extendedProperties use camelCase)\n // Guard: inject a placeholder key so mv-apply doesn't drop rows with null/empty bags\n | extend x_RecommendationDetails = bag_merge(coalesce(x_RecommendationDetails, dynamic({})), bag_pack('__placeholder', ''))\n | mv-apply k = bag_keys(x_RecommendationDetails) on (\n where isnotempty(tostring(k)) and tostring(k) != '__placeholder'\n | extend newKey = iff(tostring(k) startswith 'x_', tostring(k), strcat('x_', toupper(substring(tostring(k), 0, 1)), substring(tostring(k), 1)))\n | summarize x_RecommendationDetails = make_bag(bag_pack(newKey, x_RecommendationDetails[tostring(k)]))\n )\n //\n // Build recommendation details\n | lookup kind=leftouter (Regions | summarize RegionName = make_set(RegionName)[0] by Location = RegionId) on Location\n | extend x_RecommendationDetails = case(\n // Use incoming x_RecommendationDetails first\n isnotempty(x_RecommendationDetails), x_RecommendationDetails,\n // Create one for reservation recommendations if needed\n x_SourceType == 'ReservationRecommendations', bag_pack(\n 'CommitmentDiscountNormalizedGroup', InstanceFlexibilityGroup,\n 'CommitmentDiscountNormalizedRatio', InstanceFlexibilityRatio,\n 'CommitmentDiscountNormalizedSize', NormalizedSize,\n 'CommitmentDiscountResourceType', ResourceType,\n 'CommitmentDiscountScope', Scope,\n 'LookbackPeriodDuration', case(\n LookBackPeriod matches regex @'^Last([0-9]+)Days$', replace_regex(LookBackPeriod, @'^Last([0-9]+)Days$', @'P\\1D'),\n LookBackPeriod matches regex @'^[0-9]+$', strcat('P', LookBackPeriod, 'D'),\n ''\n ),\n 'LookbackPeriodStart', FirstUsageDate,\n 'RecommendedQuantity', RecommendedQuantity,\n 'RecommendedQuantityNormalized', RecommendedQuantityNormalized,\n 'RegionId', Location,\n 'RegionName', RegionName,\n 'SkuMeterId', MeterId,\n 'SkuPriceDetails', SkuProperties,\n 'SkuSize', coalesce(SKU, SkuName),\n 'SkuTerm', isoMonths(Term)\n ),\n dynamic({})\n )\n //\n // Prefer specified date, then fall back to generating a date based on reservation recommendation lookback period, then validate to ensure it's not in the future\n | extend x_RecommendationDate = coalesce(x_RecommendationDate, FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d))\n | extend x_RecommendationDate = iff(x_RecommendationDate > now(), startofday(now()), x_RecommendationDate)\n //\n // Derive x_ResourceType from ResourceId\n | extend tmp_ResourceType = tostring(parse_resourceid(ResourceId).x_ResourceType)\n | extend x_RecommendationDetails = iff(isnotempty(tmp_ResourceType), bag_merge(bag_pack('x_ResourceType', tmp_ResourceType), x_RecommendationDetails), x_RecommendationDetails)\n //\n // Set ResourceType display name from x_ResourceType code\n | extend ResourceType = coalesce(ResourceType, tostring(resource_type(tmp_ResourceType).SingularDisplayName), tmp_ResourceType)\n //\n | project\n ProviderName,\n ResourceId = tolower(ResourceId), // Force lowercase for consistent grouping/filtering\n ResourceName = tolower(iff(tmp_ResourceType =~ 'microsoft.resources/subscriptions', coalesce(SubAccountName, ResourceName), ResourceName)), // Use subscription name for subscription-level recommendations\n ResourceType,\n SubAccountId = coalesce(SubAccountId, iff(isnotempty(SubscriptionId), strcat('/subscriptions/', SubscriptionId), '')),\n SubAccountName,\n x_EffectiveCostAfter = coalesce(x_EffectiveCostAfter, TotalCostWithReservedInstances),\n x_EffectiveCostBefore = coalesce(x_EffectiveCostBefore, CostWithNoReservedInstances),\n x_EffectiveCostSavings = coalesce(x_EffectiveCostSavings, NetSavings, toreal(x_RecommendationDetails.x_SavingsAmount), toreal(x_RecommendationDetails.x_AnnualSavingsAmount) / 12),\n x_IngestionTime,\n x_RecommendationCategory, // TODO: Set for reservation recommendations\n x_RecommendationDate,\n x_RecommendationDescription = coalesce(x_RecommendationDescription, tostring(x_RecommendationDetails.x_RecommendationSolution), tostring(x_RecommendationDetails.x_RecommendationSubCategory)),\n x_RecommendationDetails,\n x_RecommendationId = tolower(x_RecommendationId), // TODO: Set for reservation recommendations; force lowercase for consistent grouping/filtering\n x_ResourceGroupName = tolower(x_ResourceGroupName), // Force lowercase for consistent grouping/filtering\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n// Recommendations_final_v1_2 table\n.create-merge table Recommendations_final_v1_2 (\n ProviderName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n SubAccountId: string,\n SubAccountName: string,\n x_EffectiveCostAfter: real,\n x_EffectiveCostBefore: real,\n x_EffectiveCostSavings: real,\n x_IngestionTime: datetime,\n x_RecommendationCategory: string,\n x_RecommendationDate: datetime,\n x_RecommendationDescription: string,\n x_RecommendationDetails: dynamic,\n x_RecommendationId: string,\n x_ResourceGroupName: string,\n x_SourceName: string,\n x_SourceProvider: string,\n x_SourceType: string,\n x_SourceVersion: string\n)\n\n// Update policy for Recommendations_raw -> Recommendations_final_v1_2 table\n.alter table Recommendations_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Recommendations_raw\",\n \"Query\": \"Recommendations_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All transactions transformed to FOCUS 1.2.', folder='Transactions')\nTransactions_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Transactions_raw\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationTransactions', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Handle BillingPeriodStart/End\n | extend BillingMonth = tostring(BillingMonth)\n | extend BillingPeriodStart = iff(isempty(BillingMonth), datetime(null), todatetime(strcat(substring(BillingMonth, 0, 4), \"-\", substring(BillingMonth, 4, 2), \"-\", substring(BillingMonth, 6, 2))))\n | extend BillingPeriodEnd = iff(isempty(BillingMonth), datetime(null), startofmonth(endofmonth(BillingPeriodStart) + 1d))\n //\n // Sort columns and apply final transforms\n | project\n BilledCost = Amount,\n BillingAccountId = case(\n BillingProfileId startswith '/', BillingProfileId,\n isnotempty(CurrentEnrollmentId), strcat('/providers/Microsoft.Billing/billingAccounts/', CurrentEnrollmentId),\n isnotempty(BillingProfileId), strcat('/providers/Microsoft.Billing/billingProfiles/', BillingProfileId),\n ''\n ),\n BillingAccountName = coalesce(BillingProfileName, CurrentEnrollmentId),\n BillingCurrency = Currency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory = case(\n EventType in ('Cancel', 'Purchase', 'Refund'), 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = case(\n EventType == 'Cancel', 'Cancel', // FOCUS does not handle this scenario\n EventType == 'Refund', 'Correction',\n ''\n ),\n ChargeDescription = Description,\n ChargeFrequency = case(\n BillingFrequency == 'OneTime', 'One-Time',\n BillingFrequency == 'Recurring', 'Recurring',\n BillingFrequency\n ),\n ChargePeriodStart = EventDate,\n InvoiceId,\n PricingQuantity = Quantity,\n PricingUnit = 'Reservations',\n ProviderName,\n RegionId = Region,\n RegionName = Region,\n SubAccountId = iff(isempty(PurchasingSubscriptionGuid), '', strcat('/subscriptions/', PurchasingSubscriptionGuid)),\n SubAccountName = iff(isempty(PurchasingSubscriptionGuid), '', PurchasingSubscriptionName),\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerEmail,\n x_CostCenter = CostCenter,\n x_InvoiceNumber = Invoice,\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = coalesce(InvoiceSectionName, DepartmentName),\n x_IngestionTime = ingestion_time(),\n x_MonetaryCommitment = MonetaryCommitment,\n x_Overage = Overage,\n x_PurchasingBillingAccountId = PurchasingEnrollment,\n x_SkuOrderId = ReservationOrderId,\n x_SkuOrderName = ReservationOrderName,\n x_SkuSize = ArmSkuName,\n x_SkuTerm = isoMonths(Term),\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId = PurchasingSubscriptionGuid,\n x_TransactionType = EventType\n}\n\n// Transactions_final_v1_2 table\n.create-merge table Transactions_final_v1_2 (\n BilledCost: real, // MS CM EA+MCA 2023-05-01\n BillingAccountId: string, // MS CM EA+MCA 2023-05-01\n BillingAccountName: string, // MS CM EA+MCA 2023-05-01\n BillingCurrency: string, // MS CM EA+MCA 2023-05-01\n BillingPeriodEnd: datetime, // MS CM EA+MCA 2023-05-01\n BillingPeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n ChargeCategory: string, // Hubs add-on\n ChargeClass: string, // Hubs add-on\n ChargeDescription: string, // MS CM EA+MCA 2023-05-01\n ChargeFrequency: string, // MS CM EA+MCA 2023-05-01\n ChargePeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n InvoiceId: string, // MS CM MCA 2023-05-01\n PricingQuantity: real, // MS CM EA+MCA 2023-05-01\n PricingUnit: string, // Hubs add-on\n ProviderName: string, // Hubs add-on\n RegionId: string, // MS CM EA+MCA 2023-05-01\n RegionName: string, // MS CM EA+MCA 2023-05-01\n SubAccountId: string, // MS CM EA+MCA 2023-05-01\n SubAccountName: string, // MS CM EA+MCA 2023-05-01\n x_AccountName: string, // MS CM EA 2023-05-01\n x_AccountOwnerId: string, // MS CM EA 2023-05-01\n x_CostCenter: string, // MS CM EA 2023-05-01\n x_InvoiceNumber: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionId: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionName: string, // MS CM MCA 2023-05-01\n x_IngestionTime: datetime, // Hubs add-on\n x_MonetaryCommitment: real, // MS CM EA 2023-05-01\n x_Overage: real, // MS CM EA 2023-05-01\n x_PurchasingBillingAccountId: string, // MS CM EA 2023-05-01\n x_SkuOrderId: string, // MS CM EA+MCA 2023-05-01\n x_SkuOrderName: string, // MS CM EA+MCA 2023-05-01\n x_SkuSize: string, // MS CM EA+MCA 2023-05-01\n x_SkuTerm: int, // MS CM EA+MCA 2023-05-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubscriptionId: string, // MS CM EA+MCA 2023-05-01\n x_TransactionType: string // MS CM EA+MCA 2023-05-01\n)\n\n// Update policy for Transactions_raw -> Transactions_final_v1_2 table\n.alter table Transactions_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Transactions_raw\",\n \"Query\": \"Transactions_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n", + "$fxv#10": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// See known issues @ https://github.com/microsoft/finops-toolkit/issues/1111\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Prices |=========================================================================================================\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_transform_v1_2 function\n.create-or-alter function\nwith (docstring='Transforms Prices_raw into FOCUS 1.2.', folder='Prices')\nPrices_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n let prices = materialize(\n Prices_raw\n | extend PricingCurrency = coalesce(Currency, CurrencyCode) // CurrencyCode last as a fallback only\n | extend x_SkuId = coalesce(SkuId, SkuID)\n | extend x_SkuMeterId = coalesce(MeterId, MeterID)\n | extend x_SkuProductId = coalesce(ProductId, ProductID)\n | extend x_SkuTerm = isoMonths(Term)\n | project-rename\n SkuMeter = MeterName,\n x_BaseUnitPrice = BasePrice,\n x_EffectivePeriodEnd = EffectiveEndDate,\n x_EffectivePeriodStart = EffectiveStartDate,\n x_PricingUnitDescription = UnitOfMeasure,\n x_SkuIncludedQuantity = IncludedQuantity,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuMeterType = MeterType,\n x_SkuOfferId = OfferID,\n x_SkuPartNumber = PartNumber,\n x_SkuPriceType = PriceType,\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTier = TierMinimumUnits\n | extend ContractedUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', UnitPrice, real(null)) // UnitPrice for savings plan is not the on-demand unit price\n | extend ListUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', MarketPrice, real(null)) // MarketPrice for savings plan is not the list price\n | extend ChargeCategory = case(\n x_SkuPriceType == 'Consumption', 'Usage',\n x_SkuPriceType == 'ReservedInstance', 'Purchase',\n x_SkuPriceType == 'SavingsPlan', 'Usage', // Savings plan prices are for committed usage, not the purchase\n ''\n )\n | extend SkuPriceIdv2 = strcat(case(x_SkuPriceType == 'Consumption', 'OD', x_SkuPriceType == 'ReservedInstance', 'RI', x_SkuPriceType == 'SavingsPlan', 'SP', 'XX'), substring(ChargeCategory, 0, 1), x_SkuTerm, '_', x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType, '_', x_SkuTier, x_SkuOfferId)\n | extend x_BillingAccountId = iff(BillingAccountId startswith '/', split(BillingAccountId, '/')[-1], coalesce(BillingAccountId, EnrollmentNumber))\n | extend x_BillingProfileId = iff(BillingProfileId startswith '/', split(BillingProfileId, '/')[-1], coalesce(BillingProfileId, EnrollmentNumber))\n | extend tmp_SavingsPlanKey = strcat(x_SkuMeterId, x_SkuProductId, x_SkuId, x_SkuTier, x_SkuOfferId)\n //\n // Get latest ingested row based on the unique ID\n | extend x_IngestionTime = ingestion_time()\n );\n //\n // Meters for reservations and savings plans to identify commitment eligibility\n let riMeters = prices | where x_SkuPriceType == 'ReservedInstance' | distinct x_SkuMeterId;\n let spMeters = prices | where x_SkuPriceType == 'SavingsPlan' | distinct x_SkuMeterId;\n //\n // Copy list/base/contracted prices from on-demand SKUs\n prices\n | where x_SkuPriceType == 'SavingsPlan'\n // If we use join, specify the shuffle key\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter hint.strategy=shuffle (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | lookup kind=leftouter (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | extend ListUnitPrice = coalesce(ListUnitPrice, ListUnitPrice1)\n | extend ContractedUnitPrice = coalesce(ContractedUnitPrice, ContractedUnitPrice1)\n | extend x_BaseUnitPrice = coalesce(x_BaseUnitPrice, x_BaseUnitPrice1)\n | project-away ListUnitPrice1, ContractedUnitPrice1, x_BaseUnitPrice1, tmp_SavingsPlanKey\n | union ((prices | where x_SkuPriceType != 'SavingsPlan'))\n //\n // Set CommitmentDiscountCategory for reuse\n | extend CommitmentDiscountCategory = case(\n x_SkuPriceType == 'ReservedInstance', 'Usage',\n x_SkuPriceType == 'SavingsPlan', 'Spend',\n ''\n )\n //\n // Calculate commitment discount eligibility\n // TODO: Would a join be faster?\n // TODO: Check this to ensure it's correct\n | extend x_CommitmentDiscountSpendEligibility = iff(x_SkuMeterId in (riMeters) and x_SkuPriceType != 'ReservedInstance', 'Eligible', 'Not Eligible')\n | extend x_CommitmentDiscountUsageEligibility = iff(x_SkuMeterId in (spMeters), 'Eligible', 'Not Eligible')\n //\n // TODO: Implement x_CommitmentDiscountNormalizedRatio\n | extend x_CommitmentDiscountNormalizedRatio = real(null)\n //\n // Add PricingUnit and x_PricingBlockSize\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter (PricingUnits) on x_PricingUnitDescription | project-away x_PricingUnitDescription1\n | lookup kind=leftouter (PricingUnits) on x_PricingUnitDescription\n //\n | extend x_EffectiveUnitPrice = iff(x_SkuPriceType == 'SavingsPlan', UnitPrice, real(null)) // Savings plan prices are for the effective price, not the contracted price\n | extend x_EffectiveUnitPriceDiscount = ContractedUnitPrice - x_EffectiveUnitPrice\n | extend x_ContractedUnitPriceDiscount = ListUnitPrice - ContractedUnitPrice\n | extend x_TotalUnitPriceDiscount = ListUnitPrice - x_EffectiveUnitPrice\n | project\n BillingAccountId = tolower(case(\n BillingProfileId startswith '/', BillingProfileId,\n BillingAccountId startswith '/', BillingAccountId,\n strcat('/providers/microsoft.billing/billingaccounts/', x_BillingAccountId, iff(x_BillingProfileId == x_BillingAccountId, '', strcat('/billingprofiles/', x_BillingProfileId)))\n )),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName, x_BillingProfileId),\n BillingCurrency = coalesce(BillingCurrency, CurrencyCode, Currency), // Currency last as a fallback only\n ChargeCategory,\n CommitmentDiscountCategory,\n CommitmentDiscountType = case(\n x_SkuPriceType == 'ReservedInstance', 'Reservation',\n x_SkuPriceType == 'SavingsPlan', 'Savings plan',\n ''\n ),\n CommitmentDiscountUnit = case(\n isempty(CommitmentDiscountCategory), '',\n CommitmentDiscountCategory == 'Spend', PricingCurrency,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio == real(1), PricingUnit,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio > real(1), strcat('Normalized ', PricingUnit),\n ''\n ),\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory = case(\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed',\n ''\n ),\n PricingCurrency,\n PricingUnit,\n SkuId = coalesce(ProductId, ProductID),\n SkuMeter,\n SkuPriceId = strcat(x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType),\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement = case(\n strlen(x_BillingAccountId) > 32, 'MCA',\n strlen(x_BillingAccountId) < 32, 'EA',\n 'Unknown'\n ),\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent = 1.0 * x_ContractedUnitPriceDiscount / ListUnitPrice * 100,\n x_EffectivePeriodEnd = startofmonth(x_EffectivePeriodEnd + 1h),\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent = 1.0 * x_EffectiveUnitPriceDiscount / ContractedUnitPrice * 100,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingSubcategory = case(\n x_SkuPriceType == 'Consumption' and (x_SkuIncludedQuantity > 0 or x_SkuTier > 0), 'Tiered',\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed Spend',\n ''\n ),\n x_PricingUnitDescription,\n x_SkuDescription = Product,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName = coalesce(x_SourceName, 'Cost Management'),\n x_SourceProvider = coalesce(x_SourceProvider, 'Microsoft'),\n x_SourceType = coalesce(x_SourceType, 'PriceSheet'),\n x_SourceVersion = coalesce(x_SourceVersion, '2023-05-01'),\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent = 1.0 * x_TotalUnitPriceDiscount / ListUnitPrice * 100\n}\n\n// Prices_final_v1_2 table\n.create-merge table Prices_final_v1_2 (\n BillingAccountId: string,\n BillingAccountName: string,\n BillingCurrency: string,\n ChargeCategory: string,\n CommitmentDiscountCategory: string,\n CommitmentDiscountType: string,\n CommitmentDiscountUnit: string,\n ContractedUnitPrice: real,\n ListUnitPrice: real,\n PricingCategory: string,\n PricingCurrency: string, // Azure\n PricingUnit: string,\n SkuId: string,\n SkuMeter: string, // Azure\n SkuPriceId: string,\n SkuPriceIdv2: string, // Hubs add-on\n x_BaseUnitPrice: real, // Azure\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure MCA\n x_BillingProfileId: string, // Azure MCA\n x_CommitmentDiscountNormalizedRatio: real, // Hubs add-on\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_ContractedUnitPriceDiscount: real, // Hubs add-on\n x_ContractedUnitPriceDiscountPercent: real, // Hubs add-on\n x_EffectivePeriodEnd: datetime, // Azure\n x_EffectivePeriodStart: datetime, // Azure\n x_EffectiveUnitPrice: real, // Azure\n x_EffectiveUnitPriceDiscount: real, // Hubs add-on\n x_EffectiveUnitPriceDiscountPercent: real, // Hubs add-on\n x_IngestionTime: datetime, // Hubs add-on\n x_PricingBlockSize: real, // Hubs add-on\n x_PricingSubcategory: string, // Hubs add-on\n x_PricingUnitDescription: string, // Azure\n x_SkuDescription: string, // Azure\n x_SkuId: string, // Azure\n x_SkuIncludedQuantity: real, // Azure EA\n x_SkuMeterCategory: string, // Azure\n x_SkuMeterId: string, // Azure\n x_SkuMeterSubcategory: string, // Azure\n x_SkuMeterType: string, // Azure\n x_SkuPriceType: string, // Azure\n x_SkuProductId: string, // Azure\n x_SkuRegion: string, // Azure\n x_SkuServiceFamily: string, // Azure\n x_SkuOfferId: string, // Azure EA\n x_SkuPartNumber: string, // Azure EA\n x_SkuTerm: int, // Azure\n x_SkuTier: real, // Azure MCA\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_TotalUnitPriceDiscount: real, // Hubs add-on\n x_TotalUnitPriceDiscountPercent: real // Hubs add-on\n)\n\n// Update policy for Prices_raw -> Prices_final_v1_2\n.alter table Prices_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Prices_raw\",\n \"Query\": \"Prices_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Cost and usage |=================================================================================================\n// Supported versions:\n// - MS: 1.2-preview, 1.0, 1.0-preview(v1)\n// https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0\n// https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024\n// https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 \n// https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All costs transformed to FOCUS 1.2.', folder='Costs')\nCosts_transform_v1_2()\n{\n let checkString = (column: string, oldValue: string, newValue: string) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n let checkInt = (column: string, oldValue: int, newValue: int) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n let checkReal = (column: string, oldValue: real, newValue: real) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n Costs_raw\n //\n // Dedupe rows\n | extend x_IngestionTime = ingestion_time()\n | extend x_ChargeId = ''\n // TODO: Consider adding a unique charge ID per row\n // hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // // 1. Resource hierarchy (including resource name), highest to lowest\n // BillingAccountId,\n // x_InvoiceSectionId,\n // x_AccountOwnerId,\n // SubAccountId,\n // x_ResourceGroupName,\n // ResourceName,\n // // 2. Resource details\n // ResourceId,\n // RegionId,\n // Tags,\n // CommitmentDiscountId,\n // x_CostCenter,\n // // 4. Meter details\n // SkuPriceId,\n // x_SkuMeterId,\n // x_SkuPartNumber,\n // x_SkuOfferId,\n // x_SkuDetails,\n // // 5. Date\n // ChargePeriodStart\n // ))\n //\n // Identify data quality issues\n // TODO: Remove x_SourceChanges in v1_3 (or later)\n | extend x_SourceChanges = trim_end(',', strcat(\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based', 'InvalidChargeFrequency,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and EffectiveCost > 0, 'InvalidEffectiveCost,', ''),\n iff((isempty(ContractedCost) or ContractedCost == 0) and EffectiveCost != 0, 'MissingContractedCost,', ''),\n iff((isempty(ContractedUnitPrice) or ContractedUnitPrice == 0) and x_EffectiveUnitPrice != 0, 'MissingContractedUnitPrice,', ''),\n iff(ListCost < ContractedCost, 'ListCostLessThanContractedCost,', ''),\n iff(ContractedCost < EffectiveCost, 'ContractedCostLessThanEffectiveCost,', ''),\n iff((isempty(ListCost) or ListCost == 0) and (ContractedCost != 0 or EffectiveCost != 0), 'MissingListCost,', ''),\n iff((isempty(ListUnitPrice) or ListUnitPrice == 0) and (ContractedUnitPrice != 0 or x_EffectiveUnitPrice != 0), 'MissingListUnitPrice,', ''),\n iff((isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001)\n or (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001),\n 'XEffectiveUnitPriceRoundingError,', ''),\n iff(ConsumedQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingConsumedQuantity,', ''),\n iff(PricingQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingPricingQuantity,', ''),\n iff(isempty(ProviderName), 'MissingProviderName,', ''),\n iff(isempty(PublisherName), 'MissingPublisherName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceId), 'MissingResourceId,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceName), 'MissingResourceName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceType), 'MissingResourceType,', ''),\n iff(BilledCost > 0 and x_BilledUnitPrice == 0, 'MissingXBilledUnitPrice,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(x_ResourceType), 'MissingXResourceType,', ''),\n iff(PricingCategory == 'Standard' and isnotempty(CommitmentDiscountId) and ChargeCategory == 'Usage', 'PricingCategoryShouldBeCommitted,', ''),\n iff(x_SkuTerm == '1Year' or x_SkuTerm == '3Years' or x_SkuTerm == '5Years', 'SkuTermShouldBeAnInteger,', '')\n ))\n //\n // Handle provider columns that moved to FOCUS\n | extend PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency)\n //\n // Backup original prices/costs before the merge\n | extend old_ContractedCost = ContractedCost\n | extend old_ContractedUnitPrice = ContractedUnitPrice\n | extend old_ListCost = ListCost\n | extend old_ListUnitPrice = ListUnitPrice\n | extend old_x_EffectiveUnitPrice = x_EffectiveUnitPrice\n //\n // Fix columns needed in other changes\n | extend old_ProviderName = ProviderName, ProviderName = case(\n isnotempty(ProviderName), ProviderName,\n isnotempty(coalesce(x_CostCategories, x_Discount, x_Operation, x_ServiceCode, x_UsageType)), 'AWS',\n isnotempty(coalesce(tostring(UsageAmount), tostring(x_Cost), x_Credits, x_CostType, tostring(x_CurrencyConversionRate), tostring(x_ExportTime), x_Project, x_ServiceId)), 'GCP',\n isnotempty(coalesce(x_BillingProfileId, x_InvoiceSectionId)), 'Microsoft',\n ''\n )\n //\n // Identify source\n | extend x_SourceName = coalesce(x_SourceName, iff(isnotempty(x_BillingProfileId), 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(isnotempty(x_BillingProfileId), 'FocusCost', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, case(\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)) and isempty(SkuPriceDetails) and isnotempty(x_SkuDetails), '1.2-preview',\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)), '1.2',\n isnotempty(coalesce(ChargeClass, CommitmentDiscountStatus, tostring(ConsumedQuantity), ConsumedUnit, tostring(ContractedCost), tostring(ContractedUnitPrice), RegionId, RegionName)), '1.0',\n isnotempty(coalesce(ChargeSubcategory, Region, tostring(UsageQuantity), UsageUnit)), iff(ProviderName == 'Microsoft', '1.0-preview(v1)', '1.0-preview'),\n ''\n ))\n // Append version check error code\n | extend x_SourceChanges = iff(x_SourceVersion == '1.0', x_SourceChanges,\n strcat(x_SourceChanges, iff(isempty(x_SourceChanges), '', ','), iff(x_SourceVersion == '', 'UnknownFocusVersion', 'LegacyFocusVersion'))\n )\n //\n // Fix quantities\n | extend old_PricingQuantity = PricingQuantity, PricingQuantity = case(\n PricingQuantity != 0 or (EffectiveCost == 0 and BilledCost == 0), PricingQuantity,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(EffectiveCost) and EffectiveCost != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0, EffectiveCost / x_EffectiveUnitPrice,\n PricingQuantity\n )\n | extend old_ConsumedQuantity = ConsumedQuantity, ConsumedQuantity = case(\n isnotempty(ConsumedQuantity) and ConsumedQuantity != 0, ConsumedQuantity,\n ChargeCategory == 'Usage', PricingQuantity / coalesce(x_PricingBlockSize, real(1)),\n ConsumedQuantity\n )\n //\n // Populate missing prices -- mapping to on-demand prices requires meter ID and offer ID\n | extend tmp_MissingPrices = ProviderName == 'Microsoft'\n and (isempty(ListUnitPrice) or isempty(ContractedUnitPrice) or ListUnitPrice == 0 or ContractedUnitPrice == 0)\n and x_EffectiveUnitPrice != 0\n and not(CommitmentDiscountCategory == 'Spend' and CommitmentDiscountStatus == 'Unused')\n and isnotempty(x_SkuMeterId) and isnotempty(x_SkuOfferId)\n | as allCosts\n | where tmp_MissingPrices\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(ChargePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | as costsWithMissingPrices\n | join kind=leftouter (\n Prices_final_v1_2\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(x_EffectivePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | where x_SkuPriceType == 'Consumption' and tmp_ReservationPriceLookupKey in ((costsWithMissingPrices | summarize by tmp_ReservationPriceLookupKey))\n | summarize ListUnitPrice = min(ListUnitPrice), ContractedUnitPrice = min(ContractedUnitPrice) by tmp_ReservationPriceLookupKey, x_PricingBlockSize, PricingUnit\n ) on tmp_ReservationPriceLookupKey\n //\n // Select the best price to use for each row\n | extend x_EffectiveUnitPrice = case(\n // If price is a rounding error away from the billed price, use the billed price\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001, x_BilledUnitPrice,\n // If price is a rounding error away from the contracted price, use the contracted price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001, ContractedUnitPrice,\n x_EffectiveUnitPrice\n )\n | extend ContractedUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ContractedUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ContractedUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // If billed price is available, assume the billed price is the same as contracted price to support aggregations\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, x_EffectiveUnitPrice,\n // Otherwise, assume the effective price is the same as contracted price to support aggregations\n x_EffectiveUnitPrice\n )\n | extend ListUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ListUnitPrice) and ListUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ListUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ListUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ListUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // Otherwise, assume the contracted price is the same as list price to support aggregations\n ContractedUnitPrice\n )\n // Calculate missing costs based on new prices -- If cost is already correct, keep that; if not and price is available, recalculate the cost; otherwise, keep the existing cost\n | extend ContractedCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ContractedCost) and ContractedCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedCost,\n // ContractedCost is 0 in all other scenarios...\n // If 0 and there's a billed cost and prices are the same, use BilledCost\n isnotempty(BilledCost) and BilledCost != 0 and ContractedUnitPrice == x_BilledUnitPrice, BilledCost,\n // If 0 and there's a billed cost and prices are the same, use EffectiveCost\n isnotempty(EffectiveCost) and EffectiveCost != 0 and ContractedUnitPrice == x_EffectiveUnitPrice, EffectiveCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0, ContractedUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume EffectiveCost\n isempty(ContractedUnitPrice) or ContractedUnitPrice == 0, EffectiveCost,\n // Fall back to the original value for any unhandled scenarios\n ContractedCost\n )\n | extend ListCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ListCost) and ListCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ListCost,\n // ListCost is 0 in all other scenarios...\n // If 0 and there's a contracted cost and prices are the same, use ContractedCost\n isnotempty(ContractedCost) and ContractedCost != 0 and ListUnitPrice == ContractedUnitPrice, ContractedCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ListUnitPrice) and ListUnitPrice != 0, ListUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume ContractedCost\n isempty(ListUnitPrice) or ListUnitPrice == 0, ContractedCost,\n // Fall back to the original value for any unhandled scenarios\n ListCost\n )\n // Merge the rest of the unmodified cost records and remove excess columns\n | union (allCosts | where not(tmp_MissingPrices))\n | project-away x_PricingBlockSize1, PricingUnit1, ListUnitPrice1, ContractedUnitPrice1, tmp_MissingPrices, tmp_ReservationPriceLookupKey, tmp_ReservationPriceLookupKey1\n //\n | extend SkuPriceDetails = parse_json(SkuPriceDetails)\n | extend Tags = parse_json(Tags)\n | extend x_SkuDetails = parse_json(x_SkuDetails)\n //\n // Handle FOCUS 1.0-preview\n | extend old_ChargeSubcategory = ChargeSubcategory\n | extend old_ChargeCategory = ChargeCategory, ChargeCategory = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Credit', 'Credit',\n ChargeSubcategory == 'Refund', 'Purchase', // We are assuming purchase refunds since we don't have data to indicate usage refunds\n ChargeCategory\n )\n | extend old_ChargeClass = ChargeClass, ChargeClass = case(ChargeSubcategory == 'Refund', 'Correction', ChargeClass)\n //\n // Populate CapacityReservationId when not specified\n | extend CapacityReservationId = coalesce(CapacityReservationId, tostring(coalesce(x_SkuDetails.VMCapacityReservationId, SkuPriceDetails.VMCapacityReservationId, SkuPriceDetails.x_VMCapacityReservationId)))\n | extend old_CapacityReservationStatus = CapacityReservationStatus, CapacityReservationStatus = case(\n isempty(CapacityReservationId), '',\n isnotempty(CapacityReservationStatus), CapacityReservationStatus,\n tolower(x_ResourceType) == 'microsoft.compute/capacityreservationgroups/capacityreservations', 'Unused',\n 'Used'\n )\n //\n // BUG: ChargeFrequency shows \"Usage-Based\" for monthly recurring savings plan purchases\n | extend old_ChargeFrequency = ChargeFrequency, ChargeFrequency = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based' and ProviderName == 'Microsoft' and x_SourceVersion startswith '1.0', 'Recurring', ChargeFrequency)\n //\n // Commitment discounts\n | extend x_CommitmentDiscountNormalizedRatio = case(\n // Calculate from CommitmentDiscountQuantity, if specified\n isnotempty(CommitmentDiscountQuantity) and CommitmentDiscountQuantity != 0, CommitmentDiscountQuantity / PricingQuantity / coalesce(x_PricingBlockSize, real(1)),\n // Not applicable\n isempty(CommitmentDiscountStatus), real(null),\n // Parse from SKU details if not specified explicitly\n toreal(coalesce(x_SkuDetails.RINormalizationRatio, SkuPriceDetails.RINormalizationRatio, SkuPriceDetails.x_RINormalizationRatio, dynamic(1)))\n )\n | extend old_CommitmentDiscountQuantity = CommitmentDiscountQuantity, CommitmentDiscountQuantity = case(\n // FOCUS 1.2\n isnotempty(CommitmentDiscountQuantity), CommitmentDiscountQuantity,\n // FOCUS 1.0-preview, 1.0\n isempty(CommitmentDiscountStatus), real(null),\n CommitmentDiscountCategory == 'Spend', EffectiveCost / coalesce(x_BillingExchangeRate, real(1)),\n CommitmentDiscountCategory == 'Usage' and isnotempty(x_CommitmentDiscountNormalizedRatio), PricingQuantity / coalesce(x_PricingBlockSize, real(1)) * x_CommitmentDiscountNormalizedRatio,\n real(null)\n )\n | extend old_CommitmentDiscountUnit = CommitmentDiscountUnit, CommitmentDiscountUnit = case(\n // FOCUS 1.2\n isnotempty(CommitmentDiscountUnit), CommitmentDiscountUnit,\n // FOCUS 1.0\n isempty(CommitmentDiscountQuantity), '',\n CommitmentDiscountCategory == 'Spend', PricingCurrency,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio == real(1), ConsumedUnit,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio > real(1), strcat('Normalized ', ConsumedUnit),\n ''\n )\n | extend old_CommitmentDiscountStatus = CommitmentDiscountStatus, CommitmentDiscountStatus = case(\n // FOCUS 1.0+\n isnotempty(CommitmentDiscountStatus), CommitmentDiscountStatus,\n // FOCUS 1.0-preview\n ChargeSubcategory == 'Used Commitment', 'Used',\n ChargeSubcategory == 'Unused Commitment', 'Unused',\n ''\n )\n | extend x_CommitmentDiscountUtilizationPotential = case(\n ChargeCategory == 'Purchase', real(0),\n ProviderName == 'Microsoft' and isnotempty(CommitmentDiscountCategory), EffectiveCost,\n CommitmentDiscountCategory == 'Usage', ConsumedQuantity,\n CommitmentDiscountCategory == 'Spend', EffectiveCost,\n real(0)\n )\n | extend x_CommitmentDiscountUtilizationAmount = iff(CommitmentDiscountStatus == 'Used', x_CommitmentDiscountUtilizationPotential, real(0))\n //\n // Pricing\n | extend old_x_AmortizationClass = x_AmortizationClass, x_AmortizationClass = case(\n // FOCUS 1.2\n isnotempty(x_AmortizationClass), x_AmortizationClass,\n // FOCUS 1.0-preview+\n ChargeCategory == 'Purchase' and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeCategory == 'Usage' and isnotempty(CommitmentDiscountId) and isnotempty(CommitmentDiscountStatus), 'Amortized Charge',\n ''\n )\n | extend old_PricingCategory = PricingCategory, PricingCategory = case(\n // FOCUS 1.0+\n isnotempty(PricingCategory), PricingCategory,\n // FOCUS 1.0-preview\n PricingCategory == 'On-Demand', 'Standard',\n PricingCategory == 'Commitment-Based', 'Committed',\n ''\n )\n //\n // Commitment discount utilization\n | extend x_CommitmentDiscountUtilizationPotential = case(\n ChargeCategory == 'Purchase', real(0),\n ProviderName == 'Microsoft' and isnotempty(CommitmentDiscountCategory), EffectiveCost,\n CommitmentDiscountCategory == 'Usage', ConsumedQuantity,\n CommitmentDiscountCategory == 'Spend', EffectiveCost,\n real(0)\n )\n | extend x_CommitmentDiscountUtilizationAmount = iff(CommitmentDiscountStatus == 'Used', x_CommitmentDiscountUtilizationPotential, real(0))\n //\n // BUG: Fix ContractedCost that has bad values\n | extend ContractedCost = iff(ProviderName == 'Microsoft' and isnotempty(PricingQuantity) and isnotempty(x_PricingBlockSize) and ContractedCost != ContractedUnitPrice * PricingQuantity, ContractedUnitPrice * PricingQuantity, ContractedCost)\n //\n // Handle FOCUS 1.0-preview UsageQuantity/Unit\n | extend ConsumedQuantity = iff(ChargeCategory == 'Usage', coalesce(ConsumedQuantity, UsageQuantity, UsageAmount), real(null))\n | extend old_ConsumedUnit = ConsumedUnit, ConsumedUnit = iff(ChargeCategory == 'Usage' and isnotempty(ConsumedQuantity), coalesce(ConsumedUnit, UsageUnit, 'Units'), '')\n //\n // Convert IDs to lowercase for consistency\n | extend BillingAccountId = tolower(BillingAccountId)\n | extend CommitmentDiscountId = tolower(CommitmentDiscountId)\n //\n // BUG: Remove EffectiveCost for commitment discount purchases\n | extend old_EffectiveCost = EffectiveCost, EffectiveCost = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), real(0), EffectiveCost)\n | extend old_x_EffectiveCostInUsd = x_EffectiveCostInUsd, x_EffectiveCostInUsd = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), real(0), x_EffectiveCostInUsd)\n //\n // Clean up resource columns\n | extend old_ResourceId = ResourceId, ResourceId = case(\n isnotempty(ResourceId), ResourceId,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), CommitmentDiscountId,\n ResourceId\n )\n | extend old_ResourceName = ResourceName, ResourceName = tolower(case(\n isnotempty(ResourceName), ResourceName,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountName), CommitmentDiscountName,\n isnotempty(ResourceId), parse_resourceid(ResourceId).ResourceName,\n ResourceName\n ))\n | extend old_x_ResourceType = x_ResourceType, x_ResourceType = case(\n isnotempty(x_ResourceType), x_ResourceType,\n isnotempty(ResourceId), parse_resourceid(ResourceId).x_ResourceType,\n x_ResourceType\n )\n | extend old_ResourceType = ResourceType, ResourceType = case(\n // Use existing resource type display name unless it's an internal resource type ID\n isnotempty(ResourceType) and tolower(ResourceType) != tolower(x_ResourceType) and ResourceType !contains '/', ResourceType,\n // Use CommitmentDiscountType for commitment discount purchases\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountType), CommitmentDiscountType,\n // Look up display name from internal type\n isnotempty(x_ResourceType), coalesce(tostring(resource_type(x_ResourceType).SingularDisplayName), ResourceType, x_ResourceType),\n ResourceType\n )\n //\n // Handle missing values\n | extend old_PublisherName = PublisherName, PublisherName = case(PublisherName == 'Microsoft Corporation', 'Microsoft', isnotempty(PublisherName), PublisherName, x_PublisherCategory == 'Cloud Provider', ProviderName, '')\n //\n // Handle FOCUS 1.0-preview Region column\n | extend old_Region = Region\n | extend old_RegionId = RegionId, RegionId = coalesce(RegionId, iff(ProviderName == 'Microsoft', replace_string(tolower(Region), ' ', ''), Region))\n | extend RegionName = coalesce(RegionName, Region)\n //\n // SKU properties\n | extend x_SkuCoreCount = toint(coalesce(SkuPriceDetails.CoreCount, SkuPriceDetails.x_VCPUs, x_SkuDetails.VCPUs, SkuPriceDetails.x_VCores, x_SkuDetails.VCores, SkuPriceDetails.x_vCores, x_SkuDetails.vCores))\n | extend x_SkuInstanceType = tostring(coalesce(SkuPriceDetails.InstanceType, SkuPriceDetails.x_ServiceType, x_SkuDetails.ServiceType, SkuPriceDetails.x_ServerSku, x_SkuDetails.ServerSku))\n | extend x_SkuOperatingSystem = case(\n isnotempty(SkuPriceDetails.OperatingSystem), SkuPriceDetails.OperatingSystem,\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Canonical', 'Linux',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL', 'Windows Server',\n x_SkuMeterSubcategory endswith ' Series Windows', 'Windows Server',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType)\n )\n | extend x_ConsumedCoreHours = iff(ConsumedUnit == 'Hours' and isnotempty(x_SkuCoreCount), x_SkuCoreCount * ConsumedQuantity, real(null))\n | extend SkuPriceDetails = case(\n // FOCUS 1.2\n isnotempty(SkuPriceDetails), SkuPriceDetails,\n // FOCUS 1.0-preview, 1.0\n parse_json(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(tostring(x_SkuDetails)\n // Prefix all keys with x_ first to avoid double-prefixing\n , @'([\\{,])\"', @'\\1\"x_')\n // CoreCount for number of CPUs/vCPUs/cores/vCores\n , @'\"x_(VCPUs|VCores|vCores)\":', @'\"CoreCount\":')\n // TODO: DiskMaxIops for disk I/O operations per second (IOPS)\n // TODO: DiskSpace for disk size in GiB\n // TODO: DiskType for the kind of disk (e.g., SSD, HDD, NVMe)\n // TODO: GpuCount for the number of GPUs\n // InstanceType for the resource size/SKU (e.g., ArmSkuName)\n , @'\"x_(ServerSku|ServiceType)\":', @'\"InstanceType\":')\n // TODO: InstanceSeries for the size family/series\n // TODO: MemorySize for the RAM in GiB\n // TODO: NetworkMaxIops for network I/O operations per second (IOPS)\n // TODO: NetworkMaxThroughput for network max throughput for data transfer in Mbps\n // OperatingSystem for the OS name\n , @'(\"x_ImageType\":\"Canonical\")', @'\\1,\"OperatingSystem\":\"Linux\"')\n , @'(\"x_ImageType\":\"Windows Server( BYOL)?\")', @'\\1,\"OperatingSystem\":\"Windows Server\"')\n , @'(\"x_ImageType\":(\"[^\"]+\"))', @'\\1,\"OperatingSystem\":\\2')\n // TODO: Redundancy for the level of redundancy (e.g., Local, Zonal, Global)\n // TODO: StorageClass for the tier of storage (e.g., Hot, Archive, Nearline)\n )\n )\n | extend SkuPriceDetails = iff(isempty(SkuPriceDetails.OperatingSystem) and isnotempty(x_SkuOperatingSystem),\n parse_json(replace_string(tostring(SkuPriceDetails), '}', strcat(@',\"OperatingSystem\":\"', x_SkuOperatingSystem, '\"}'))),\n SkuPriceDetails)\n //\n // Azure Hybrid Benefit\n | extend tmp_SqlAhb = tolower(coalesce(x_SkuDetails.AHB, SkuPriceDetails.x_AHB))\n | extend x_SkuLicenseType = case(\n ChargeCategory != 'Usage', '',\n x_SkuMeterCategory in ('Virtual Machines', 'Virtual Machine Licenses') and (x_SkuMeterSubcategory contains 'Windows' or coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL'), 'Windows Server',\n isnotempty(tmp_SqlAhb) or x_SkuMeterSubcategory == 'SQL Server Azure Hybrid Benefit', 'SQL Server',\n ''\n )\n | extend x_SkuLicenseStatus = case(\n isempty(x_SkuLicenseType), '',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL' or tmp_SqlAhb == 'true' or x_SkuMeterSubcategory contains 'Azure Hybrid Benefit', 'Enabled',\n (x_SkuMeterSubcategory contains 'Windows') or tmp_SqlAhb == 'false', 'Not Enabled',\n ''\n )\n | extend x_SkuLicenseQuantity = case(\n isempty(x_SkuCoreCount) or isempty(x_SkuLicenseType), int(null),\n x_SkuCoreCount <= 8, int(8),\n x_SkuCoreCount > 8, x_SkuCoreCount,\n int(null)\n )\n | extend x_SkuLicenseUnit = iff(isnotempty(x_SkuLicenseQuantity), 'Cores', '')\n //\n // Savings\n | extend x_CommitmentDiscountSavings = iff(isempty(ContractedCost) or ContractedCost == 0 or ContractedCost - EffectiveCost < 0.0001, real(0), ContractedCost - EffectiveCost)\n | extend x_NegotiatedDiscountSavings = iff(isempty(ListCost) or ListCost == 0 or ListCost - ContractedCost < 0.0001, real(0), ListCost - ContractedCost)\n | extend x_TotalSavings = iff(isempty(ListCost) or ListCost == 0 or ListCost - EffectiveCost < 0.0001, real(0), ListCost - EffectiveCost)\n | extend x_CommitmentDiscountPercent = iff(isempty(ContractedUnitPrice) or ContractedUnitPrice == 0 or ContractedUnitPrice - x_EffectiveUnitPrice < 0.0001, real(0), (ContractedUnitPrice - x_EffectiveUnitPrice) / ContractedUnitPrice)\n | extend x_NegotiatedDiscountPercent = iff(isempty(ListUnitPrice) or ListUnitPrice == 0 or ListUnitPrice - ContractedUnitPrice < 0.0001, real(0), (ListUnitPrice - ContractedUnitPrice) / ListUnitPrice)\n | extend x_TotalDiscountPercent = iff(isempty(ListUnitPrice) or ListUnitPrice == 0 or ListUnitPrice - x_EffectiveUnitPrice < 0.0001, real(0), (ListUnitPrice - x_EffectiveUnitPrice) / ListUnitPrice)\n //\n // Minor fixes\n | extend old_BillingPeriodEnd = BillingPeriodEnd, BillingPeriodEnd = startofmonth(BillingPeriodEnd)\n | extend old_BillingPeriodStart = BillingPeriodStart, BillingPeriodStart = startofmonth(BillingPeriodStart)\n //\n // Sort columns and apply final transforms\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId,\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd,\n BillingPeriodStart,\n CapacityReservationId,\n CapacityReservationStatus,\n ChargeCategory,\n ChargeClass,\n ChargeDescription,\n ChargeFrequency,\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId,\n CommitmentDiscountName,\n CommitmentDiscountQuantity,\n CommitmentDiscountStatus,\n CommitmentDiscountType,\n CommitmentDiscountUnit,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost = coalesce(ContractedCost, x_OnDemandCost, x_Cost),\n ContractedUnitPrice = coalesce(ContractedUnitPrice, x_OnDemandUnitPrice),\n EffectiveCost,\n InvoiceId = coalesce(InvoiceId, x_InvoiceId),\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory,\n PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency),\n PricingQuantity,\n PricingUnit,\n ProviderName,\n PublisherName,\n RegionId,\n RegionName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory, // TODO: Populate ServiceSubcategory from ServiceName when missing\n SkuId,\n SkuMeter = coalesce(SkuMeter, x_SkuMeterName),\n SkuPriceDetails,\n SkuPriceId,\n SubAccountId,\n SubAccountName = iff(isempty(SubAccountId), '', SubAccountName),\n SubAccountType,\n Tags,\n x_AccountId = iff(x_AccountId == '-2', '', x_AccountId),\n x_AccountName = iff(x_AccountId == '-2', '', x_AccountName),\n x_AccountOwnerId = iff(x_AccountId == '-2', '', x_AccountOwnerId),\n x_AmortizationClass,\n x_BilledCostInUsd,\n x_BilledUnitPrice,\n x_BillingAccountAgreement = case(\n ProviderName == 'Microsoft' and x_BillingAccountId == x_BillingProfileId, 'EA',\n ProviderName == 'Microsoft' and x_BillingAccountId != x_BillingProfileId, 'MCA',\n ProviderName\n ),\n x_BillingAccountId,\n x_BillingAccountName,\n x_BillingExchangeRate,\n x_BillingExchangeRateDate,\n x_BillingItemCode,\n x_BillingItemName,\n x_BillingProfileId,\n x_BillingProfileName,\n x_ChargeId,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountPercent,\n x_CommitmentDiscountSavings,\n x_CommitmentDiscountSpendEligibility = '', // TODO: Add x_CommitmentDiscountSpendEligibility for Costs\n x_CommitmentDiscountUsageEligibility = '', // TODO: Add x_CommitmentDiscountUsageEligibility for Costs\n x_CommitmentDiscountUtilizationAmount,\n x_CommitmentDiscountUtilizationPotential,\n x_CommodityCode,\n x_CommodityName,\n x_ComponentName,\n x_ComponentType,\n x_ConsumedCoreHours,\n x_ContractedCostInUsd = coalesce(x_ContractedCostInUsd, x_OnDemandCostInUsd),\n x_CostAllocationRuleName,\n x_CostCategories = parse_json(x_CostCategories),\n x_CostCenter,\n x_CostType,\n x_Credits = parse_json(x_Credits),\n x_CurrencyConversionRate,\n x_CustomerId,\n x_CustomerName,\n x_Discount = parse_json(x_Discount),\n x_EffectiveCostInUsd,\n x_EffectiveUnitPrice,\n x_ExportTime,\n x_IngestionTime,\n x_InstanceID,\n x_InvoiceIssuerId,\n x_InvoiceSectionId = case(\n x_InvoiceSectionId == '-2', '',\n x_InvoiceSectionId\n ),\n x_InvoiceSectionName = case(\n x_InvoiceSectionName == 'Unassigned', '',\n x_InvoiceSectionName\n ),\n x_ListCostInUsd,\n x_Location,\n x_NegotiatedDiscountPercent,\n x_NegotiatedDiscountSavings,\n x_Operation,\n x_OwnerAccountID,\n x_PartnerCreditApplied,\n x_PartnerCreditRate,\n x_PricingBlockSize,\n x_PricingSubcategory,\n x_PricingUnitDescription = iff(x_PricingUnitDescription == 'Unassigned', '', x_PricingUnitDescription),\n x_Project,\n x_PublisherCategory,\n x_PublisherId,\n x_ResellerId,\n x_ResellerName,\n x_ResourceGroupName = tolower(x_ResourceGroupName),\n x_ResourceType,\n x_ServiceCode,\n x_ServiceId,\n x_ServiceModel, // TODO: Populate from ServiceName when missing\n x_ServicePeriodEnd,\n x_ServicePeriodStart,\n x_SkuCoreCount,\n x_SkuDescription,\n x_SkuDetails,\n x_SkuInstanceType,\n x_SkuIsCreditEligible,\n x_SkuLicenseQuantity,\n x_SkuLicenseStatus,\n x_SkuLicenseType,\n x_SkuLicenseUnit,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterSubcategory,\n x_SkuOfferId,\n x_SkuOperatingSystem,\n x_SkuOrderId,\n x_SkuOrderName,\n x_SkuPartNumber,\n x_SkuPlanName,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuTerm,\n x_SkuTier,\n x_SourceChanges,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceValues = bag_merge(\n checkString('BillingPeriodEnd', old_BillingPeriodEnd, BillingPeriodEnd),\n checkString('BillingPeriodStart', old_BillingPeriodStart, BillingPeriodStart),\n checkString('CapacityReservationStatus', old_CapacityReservationStatus, CapacityReservationStatus),\n checkString('ChargeCategory', old_ChargeCategory, ChargeCategory),\n checkString('ChargeClass', old_ChargeClass, ChargeClass),\n checkString('ChargeSubcategory', old_ChargeSubcategory, ''), // Not included in final schema; use empty string\n checkString('ChargeFrequency', old_ChargeFrequency, ChargeFrequency),\n checkReal('CommitmentDiscountQuantity', old_CommitmentDiscountQuantity, CommitmentDiscountQuantity),\n checkString('CommitmentDiscountUnit', old_CommitmentDiscountUnit, CommitmentDiscountUnit),\n checkString('CommitmentDiscountStatus', old_CommitmentDiscountStatus, CommitmentDiscountStatus),\n checkReal('ConsumedQuantity', old_ConsumedQuantity, ConsumedQuantity),\n checkString('ConsumedUnit', old_ConsumedUnit, ConsumedUnit),\n checkReal('ContractedCost', old_ContractedCost, ContractedCost),\n checkReal('ContractedUnitPrice', old_ContractedUnitPrice, ContractedUnitPrice),\n checkReal('EffectiveCost', old_EffectiveCost, EffectiveCost),\n checkReal('ListCost', old_ListCost, ListCost),\n checkReal('ListUnitPrice', old_ListUnitPrice, ListUnitPrice),\n checkString('PricingCategory', old_PricingCategory, PricingCategory),\n checkReal('PricingQuantity', old_PricingQuantity, PricingQuantity),\n checkString('ProviderName', old_ProviderName, ProviderName),\n checkString('PublisherName', old_PublisherName, PublisherName),\n checkString('Region', old_Region, ''), // Not included in final schema; use empty string\n checkString('RegionId', old_RegionId, RegionId),\n checkString('ResourceId', old_ResourceId, ResourceId),\n checkString('ResourceName', old_ResourceName, ResourceName),\n checkString('ResourceType', old_ResourceType, ResourceType),\n checkString('x_AmortizationClass', old_x_AmortizationClass, x_AmortizationClass),\n checkReal('x_EffectiveCostInUsd', old_x_EffectiveCostInUsd, x_EffectiveCostInUsd),\n checkReal('x_EffectiveUnitPrice', old_x_EffectiveUnitPrice, x_EffectiveUnitPrice),\n checkString('x_ResourceType', old_x_ResourceType, x_ResourceType)\n ),\n x_SourceVersion,\n x_SubproductName,\n x_TotalDiscountPercent,\n x_TotalSavings,\n x_UsageType\n}\n\n// Costs_final_v1_2 table\n.create-merge table Costs_final_v1_2 (\n AvailabilityZone: string,\n BilledCost: real,\n BillingAccountId: string,\n BillingAccountName: string,\n BillingAccountType: string,\n BillingCurrency: string,\n BillingPeriodEnd: datetime,\n BillingPeriodStart: datetime,\n CapacityReservationId: string,\n CapacityReservationStatus: string,\n ChargeCategory: string,\n ChargeClass: string,\n ChargeDescription: string,\n ChargeFrequency: string,\n ChargePeriodEnd: datetime,\n ChargePeriodStart: datetime,\n CommitmentDiscountCategory: string,\n CommitmentDiscountId: string,\n CommitmentDiscountName: string,\n CommitmentDiscountQuantity: real,\n CommitmentDiscountStatus: string,\n CommitmentDiscountType: string,\n CommitmentDiscountUnit: string,\n ConsumedQuantity: real,\n ConsumedUnit: string,\n ContractedCost: real,\n ContractedUnitPrice: real,\n EffectiveCost: real,\n InvoiceId: string,\n InvoiceIssuerName: string,\n ListCost: real,\n ListUnitPrice: real,\n PricingCategory: string,\n PricingCurrency: string,\n PricingQuantity: real,\n PricingUnit: string,\n ProviderName: string,\n PublisherName: string,\n RegionId: string,\n RegionName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n ServiceCategory: string,\n ServiceName: string,\n ServiceSubcategory: string,\n SkuId: string,\n SkuMeter: string,\n SkuPriceDetails: dynamic,\n SkuPriceId: string,\n SubAccountId: string,\n SubAccountName: string,\n SubAccountType: string,\n Tags: dynamic,\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_AmortizationClass: string, // Azure 1.2-preview+\n x_BilledCostInUsd: real, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: real, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: real, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingItemCode: string, // Alibaba 1.0\n x_BillingItemName: string, // Alibaba 1.0\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_CommitmentDiscountNormalizedRatio: real, // Azure 1.2-preview+\n x_CommitmentDiscountPercent: real, // Hubs add-on\n x_CommitmentDiscountSavings: real, // Hubs add-on\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_CommitmentDiscountUtilizationAmount: real, // Hubs add-on\n x_CommitmentDiscountUtilizationPotential: real, // Hubs add-on\n x_CommodityCode: string, // Alibaba 1.0\n x_CommodityName: string, // Alibaba 1.0\n x_ComponentName: string, // Tencent 1.0\n x_ComponentType: string, // Tencent 1.0\n x_ConsumedCoreHours: real, // Hubs add-on\n x_ContractedCostInUsd: real, // Azure 1.0+\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: dynamic, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_CostType: string, // GCP Jan 2024\n x_Credits: dynamic, // GCP Jan 2024\n x_CurrencyConversionRate: real, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: dynamic, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: real, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: real, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024 / Tencent 1.0\n x_IngestionTime: datetime, // Hubs add-on\n x_InstanceID: string, // Alibaba 1.0\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: real, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_NegotiatedDiscountPercent:real, // Hubs add-on\n x_NegotiatedDiscountSavings:real, // Hubs add-on\n x_Operation: string, // AWS 1.0\n x_OwnerAccountID: string, // Tencent 1.0\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: real, // Azure 1.0-preview(v1)+\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServiceModel: string, // Azure 1.2-preview+\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuCoreCount: int, // Hubs add-on\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: dynamic, // Azure 1.0-preview(v1)+\n x_SkuInstanceType: string, // Hubs add-on\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuLicenseQuantity: int, // Hubs add-on\n x_SkuLicenseStatus: string, // Hubs add-on\n x_SkuLicenseType: string, // Hubs add-on\n x_SkuLicenseUnit: string, // Hubs add-on\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOperatingSystem: string, // Hubs add-on\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuPlanName: string, // Azure 1.2-preview+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceChanges: string, // Hubs add-on\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceValues: dynamic, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubproductName: string, // Tencent 1.0\n x_TotalDiscountPercent: real, // Hubs add-on\n x_TotalSavings: real, // Hubs add-on\n x_UsageType: string // AWS 1.0\n)\n\n// Update policy for Costs_raw -> Costs_final_v1_2 table\n.alter table Costs_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Costs_raw\",\n \"Query\": \"Costs_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Actual costs |===================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_transform_v1_2 function\n.create-or-alter function\nwith (docstring='ActualCost exports transformed to FOCUS 1.2.', folder='Costs')\nActualCosts_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n ActualCosts_raw\n | where ChargeType in ('Purchase', 'Refund') and isnotempty(ReservationId)\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: PublisherName, x_PublisherCategory, x_Environment\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory), take_any(ServiceSubcategory), take_any(x_ServiceModel) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodEnd = Date + 1d,\n ChargePeriodStart = Date,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SkuId = '',\n SkuMeter = MeterName,\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = iff(isempty(SubscriptionId), '', SubscriptionName),\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentType = '',\n x_ComponentName = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = '',\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel,\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for ActualCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": true,\n \"Source\": \"ActualCosts_raw\",\n \"Query\": \"ActualCosts_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Amortized costs |================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_transform_v1_2 function\n.create-or-alter function\nwith (docstring='ActualCost exports transformed to FOCUS 1.2.', folder='Costs')\nAmortizedCosts_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n AmortizedCosts_raw\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: PublisherName, x_PublisherCategory, x_Environment\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory), take_any(ServiceSubcategory), take_any(x_ServiceModel) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodEnd = Date + 1d,\n ChargePeriodStart = Date,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SkuId = '',\n SkuMeter = MeterName,\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = iff(isempty(SubscriptionId), '', SubscriptionName),\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentType = '',\n x_ComponentName = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = '',\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel,\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for AmortizedCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": true,\n \"Source\": \"AmortizedCosts_raw\",\n \"Query\": \"AmortizedCosts_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All commitment discount usage transformed to FOCUS 1.2. This includes reservationdeatils_raw.', folder='Commitment discounts')\nCommitmentDiscountUsage_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n CommitmentDiscountUsage_raw\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Handle resource columns\n | extend ResourceId = tolower(InstanceId)\n | extend tmp_ResourceDetails = parse_resourceid(ResourceId)\n | extend ResourceName = tostring(tmp_ResourceDetails.ResourceName)\n | extend SubAccountId = tostring(tmp_ResourceDetails.SubAccountId)\n | extend x_ResourceGroupName = tostring(tmp_ResourceDetails.x_ResourceGroupName)\n | extend x_ResourceType = tostring(tmp_ResourceDetails.x_ResourceType)\n | lookup kind=leftouter (ResourceTypes | distinct x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n | lookup kind=leftouter (Services | distinct x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n //\n // Sort columns and apply final transforms\n | project\n ChargePeriodEnd = UsageDate + 1d,\n ChargePeriodStart = UsageDate,\n CommitmentDiscountCategory = 'Usage',\n CommitmentDiscountId = tolower(strcat('/providers/microsoft.capacity/reservationorders/', ReservationOrderId, '/reservations/', ReservationId)),\n CommitmentDiscountQuantity = UsedHours * InstanceFlexibilityRatio,\n CommitmentDiscountType = 'Reservation',\n CommitmentDiscountUnit = case(\n InstanceFlexibilityRatio == 1, 'Hours',\n InstanceFlexibilityRatio != 1, 'Normalized Hours',\n ''\n ),\n ConsumedQuantity = UsedHours,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SubAccountId,\n x_CommitmentDiscountCommittedCount = TotalReservedQuantity,\n x_CommitmentDiscountCommittedAmount = ReservedHours,\n // TODO: Is this needed? -- x_CommitmentDiscountKind = Kind,\n x_CommitmentDiscountNormalizedGroup = iff(InstanceFlexibilityGroup == 'NA', '', InstanceFlexibilityGroup),\n x_CommitmentDiscountNormalizedRatio = InstanceFlexibilityRatio,\n x_IngestionTime = ingestion_time(),\n x_ResourceGroupName,\n x_ResourceType,\n // x_RowId = hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // CommitmentDiscountId,\n // ResourceId,\n // ChargePeriodStart\n // )),\n x_ServiceModel,\n x_SkuOrderId = ReservationOrderId,\n x_SkuSize = iff(SkuName == 'NA', '', SkuName),\n x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName)),\n x_SourceProvider = coalesce(x_SourceProvider, ProviderName),\n x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationDetails', '')),\n x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2024-03-01', ''))\n}\n\n// CommitmentDiscountUsage_final_v1_2 table\n.create-merge table CommitmentDiscountUsage_final_v1_2 (\n ChargePeriodEnd: datetime, // Hubs add-on\n ChargePeriodStart: datetime, // MS 2023-03-01\n CommitmentDiscountCategory: string, // Hubs add-on\n CommitmentDiscountId: string, // MS 2023-03-01\n CommitmentDiscountQuantity: real, // MS 2023-03-01\n CommitmentDiscountType: string, // Hubs add-on\n CommitmentDiscountUnit: string, // Hubs add-on\n ConsumedQuantity: real, // MS 2023-03-01\n ProviderName: string, // Hubs add-on\n ResourceId: string, // MS 2023-03-01\n ResourceName: string, // Hubs add-on\n ResourceType: string, // Hubs add-on\n ServiceCategory: string, // Hubs add-on\n ServiceName: string, // Hubs add-on\n ServiceSubcategory: string, // Hubs add-on\n SubAccountId: string, // Hubs add-on\n x_CommitmentDiscountCommittedCount: real, // MS 2023-03-01\n x_CommitmentDiscountCommittedAmount: real, // MS 2023-03-01\n x_CommitmentDiscountNormalizedGroup: string, // MS 2023-03-01\n x_CommitmentDiscountNormalizedRatio: real, // MS 2023-03-01\n x_IngestionTime: datetime, // Hubs add-on\n x_ResourceGroupName: string, // Hubs add-on\n x_ResourceType: string, // Hubs add-on\n x_ServiceModel: string, // Hubs add-on\n x_SkuOrderId: string, // MS 2023-03-01\n x_SkuSize: string, // MS 2023-03-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string // Hubs add-on\n)\n\n// Update policy for CommitmentDiscountUsage_raw -> CommitmentDiscountUsage_final_v1_2 table\n.alter table CommitmentDiscountUsage_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"CommitmentDiscountUsage_raw\",\n \"Query\": \"CommitmentDiscountUsage_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All recommendations transformed to FOCUS 1.2.', folder='Recommendations')\nRecommendations_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Recommendations_raw\n | extend x_IngestionTime = ingestion_time()\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationRecommendations', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Convert JSON cost columns to real\n | extend CostWithNoReservedInstances = case(isnotempty(CostWithNoReservedInstances), CostWithNoReservedInstances, isnotempty(CostWithNoReservedInstancesJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, CostWithNoReservedInstancesJson)), CostWithNoReservedInstances)\n | extend NetSavings = case(isnotempty(NetSavings), NetSavings, isnotempty(NetSavingsJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, NetSavingsJson)), NetSavings)\n | extend TotalCostWithReservedInstances = case(isnotempty(TotalCostWithReservedInstances), TotalCostWithReservedInstances, isnotempty(TotalCostWithReservedInstancesJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, TotalCostWithReservedInstancesJson)), TotalCostWithReservedInstances)\n //\n // Parse x_RecommendationDetails from JSON string (ARG queries serialize to string for Parquet compatibility)\n | extend x_RecommendationDetails = iff(gettype(x_RecommendationDetails) == 'string', parse_json(tostring(x_RecommendationDetails)), x_RecommendationDetails)\n //\n // Normalize x_RecommendationDetails keys to x_PascalCase (Advisor extendedProperties use camelCase)\n // Guard: inject a placeholder key so mv-apply doesn't drop rows with null/empty bags\n | extend x_RecommendationDetails = bag_merge(coalesce(x_RecommendationDetails, dynamic({})), bag_pack('__placeholder', ''))\n | mv-apply k = bag_keys(x_RecommendationDetails) on (\n where isnotempty(tostring(k)) and tostring(k) != '__placeholder'\n | extend newKey = iff(tostring(k) startswith 'x_', tostring(k), strcat('x_', toupper(substring(tostring(k), 0, 1)), substring(tostring(k), 1)))\n | summarize x_RecommendationDetails = make_bag(bag_pack(newKey, x_RecommendationDetails[tostring(k)]))\n )\n //\n // Build recommendation details\n | lookup kind=leftouter (Regions | summarize RegionName = make_set(RegionName)[0] by Location = RegionId) on Location\n | extend x_RecommendationDetails = case(\n // Use incoming x_RecommendationDetails first\n isnotempty(x_RecommendationDetails), x_RecommendationDetails,\n // Create one for reservation recommendations if needed\n x_SourceType == 'ReservationRecommendations', bag_pack(\n 'CommitmentDiscountNormalizedGroup', InstanceFlexibilityGroup,\n 'CommitmentDiscountNormalizedRatio', InstanceFlexibilityRatio,\n 'CommitmentDiscountNormalizedSize', NormalizedSize,\n 'CommitmentDiscountResourceType', ResourceType,\n 'CommitmentDiscountScope', Scope,\n 'LookbackPeriodDuration', case(\n LookBackPeriod matches regex @'^Last([0-9]+)Days$', replace_regex(LookBackPeriod, @'^Last([0-9]+)Days$', @'P\\1D'),\n LookBackPeriod matches regex @'^[0-9]+$', strcat('P', LookBackPeriod, 'D'),\n ''\n ),\n 'LookbackPeriodStart', FirstUsageDate,\n 'RecommendedQuantity', RecommendedQuantity,\n 'RecommendedQuantityNormalized', RecommendedQuantityNormalized,\n 'RegionId', Location,\n 'RegionName', RegionName,\n 'SkuMeterId', MeterId,\n 'SkuPriceDetails', SkuProperties,\n 'SkuSize', coalesce(SKU, SkuName),\n 'SkuTerm', isoMonths(Term)\n ),\n dynamic({})\n )\n //\n // Prefer specified date, then fall back to generating a date based on reservation recommendation lookback period, then validate to ensure it's not in the future\n | extend x_RecommendationDate = coalesce(x_RecommendationDate, FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d))\n | extend x_RecommendationDate = iff(x_RecommendationDate > now(), startofday(now()), x_RecommendationDate)\n //\n // Derive x_ResourceType from ResourceId\n | extend tmp_ResourceType = tostring(parse_resourceid(ResourceId).x_ResourceType)\n | extend x_RecommendationDetails = iff(isnotempty(tmp_ResourceType), bag_merge(bag_pack('x_ResourceType', tmp_ResourceType), x_RecommendationDetails), x_RecommendationDetails)\n //\n // Set ResourceType display name from x_ResourceType code\n | extend ResourceType = coalesce(ResourceType, tostring(resource_type(tmp_ResourceType).SingularDisplayName), tmp_ResourceType)\n //\n | project\n ProviderName,\n ResourceId = tolower(ResourceId), // Force lowercase for consistent grouping/filtering\n ResourceName = tolower(iff(tmp_ResourceType =~ 'microsoft.resources/subscriptions', coalesce(SubAccountName, ResourceName), ResourceName)), // Use subscription name for subscription-level recommendations\n ResourceType,\n SubAccountId = coalesce(SubAccountId, iff(isnotempty(SubscriptionId), strcat('/subscriptions/', SubscriptionId), '')),\n SubAccountName,\n x_EffectiveCostAfter = coalesce(x_EffectiveCostAfter, TotalCostWithReservedInstances),\n x_EffectiveCostBefore = coalesce(x_EffectiveCostBefore, CostWithNoReservedInstances),\n x_EffectiveCostSavings = coalesce(x_EffectiveCostSavings, NetSavings, toreal(x_RecommendationDetails.x_SavingsAmount), toreal(x_RecommendationDetails.x_AnnualSavingsAmount) / 12),\n x_IngestionTime,\n x_RecommendationCategory, // TODO: Set for reservation recommendations\n x_RecommendationDate,\n x_RecommendationDescription = coalesce(x_RecommendationDescription, tostring(x_RecommendationDetails.x_RecommendationSolution), tostring(x_RecommendationDetails.x_RecommendationSubCategory)),\n x_RecommendationDetails,\n x_RecommendationId = tolower(x_RecommendationId), // TODO: Set for reservation recommendations; force lowercase for consistent grouping/filtering\n x_ResourceGroupName = tolower(x_ResourceGroupName), // Force lowercase for consistent grouping/filtering\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n// Recommendations_final_v1_2 table\n.create-merge table Recommendations_final_v1_2 (\n ProviderName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n SubAccountId: string,\n SubAccountName: string,\n x_EffectiveCostAfter: real,\n x_EffectiveCostBefore: real,\n x_EffectiveCostSavings: real,\n x_IngestionTime: datetime,\n x_RecommendationCategory: string,\n x_RecommendationDate: datetime,\n x_RecommendationDescription: string,\n x_RecommendationDetails: dynamic,\n x_RecommendationId: string,\n x_ResourceGroupName: string,\n x_SourceName: string,\n x_SourceProvider: string,\n x_SourceType: string,\n x_SourceVersion: string\n)\n\n// Update policy for Recommendations_raw -> Recommendations_final_v1_2 table\n.alter table Recommendations_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Recommendations_raw\",\n \"Query\": \"Recommendations_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All transactions transformed to FOCUS 1.2.', folder='Transactions')\nTransactions_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Transactions_raw\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationTransactions', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Handle BillingPeriodStart/End\n | extend BillingMonth = tostring(BillingMonth)\n | extend BillingPeriodStart = iff(isempty(BillingMonth), datetime(null), todatetime(strcat(substring(BillingMonth, 0, 4), \"-\", substring(BillingMonth, 4, 2), \"-\", substring(BillingMonth, 6, 2))))\n | extend BillingPeriodEnd = iff(isempty(BillingMonth), datetime(null), startofmonth(endofmonth(BillingPeriodStart) + 1d))\n //\n // Sort columns and apply final transforms\n | project\n BilledCost = Amount,\n BillingAccountId = case(\n BillingProfileId startswith '/', BillingProfileId,\n isnotempty(CurrentEnrollmentId), strcat('/providers/Microsoft.Billing/billingAccounts/', CurrentEnrollmentId),\n isnotempty(BillingProfileId), strcat('/providers/Microsoft.Billing/billingProfiles/', BillingProfileId),\n ''\n ),\n BillingAccountName = coalesce(BillingProfileName, CurrentEnrollmentId),\n BillingCurrency = Currency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory = case(\n EventType in ('Cancel', 'Purchase', 'Refund'), 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = case(\n EventType == 'Cancel', 'Cancel', // FOCUS does not handle this scenario\n EventType == 'Refund', 'Correction',\n ''\n ),\n ChargeDescription = Description,\n ChargeFrequency = case(\n BillingFrequency == 'OneTime', 'One-Time',\n BillingFrequency == 'Recurring', 'Recurring',\n BillingFrequency\n ),\n ChargePeriodStart = EventDate,\n InvoiceId,\n PricingQuantity = Quantity,\n PricingUnit = 'Reservations',\n ProviderName,\n RegionId = Region,\n RegionName = Region,\n SubAccountId = iff(isempty(PurchasingSubscriptionGuid), '', strcat('/subscriptions/', PurchasingSubscriptionGuid)),\n SubAccountName = iff(isempty(PurchasingSubscriptionGuid), '', PurchasingSubscriptionName),\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerEmail,\n x_CostCenter = CostCenter,\n x_InvoiceNumber = Invoice,\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = coalesce(InvoiceSectionName, DepartmentName),\n x_IngestionTime = ingestion_time(),\n x_MonetaryCommitment = MonetaryCommitment,\n x_Overage = Overage,\n x_PurchasingBillingAccountId = PurchasingEnrollment,\n x_SkuOrderId = ReservationOrderId,\n x_SkuOrderName = ReservationOrderName,\n x_SkuSize = ArmSkuName,\n x_SkuTerm = isoMonths(Term),\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId = PurchasingSubscriptionGuid,\n x_TransactionType = EventType\n}\n\n// Transactions_final_v1_2 table\n.create-merge table Transactions_final_v1_2 (\n BilledCost: real, // MS CM EA+MCA 2023-05-01\n BillingAccountId: string, // MS CM EA+MCA 2023-05-01\n BillingAccountName: string, // MS CM EA+MCA 2023-05-01\n BillingCurrency: string, // MS CM EA+MCA 2023-05-01\n BillingPeriodEnd: datetime, // MS CM EA+MCA 2023-05-01\n BillingPeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n ChargeCategory: string, // Hubs add-on\n ChargeClass: string, // Hubs add-on\n ChargeDescription: string, // MS CM EA+MCA 2023-05-01\n ChargeFrequency: string, // MS CM EA+MCA 2023-05-01\n ChargePeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n InvoiceId: string, // MS CM MCA 2023-05-01\n PricingQuantity: real, // MS CM EA+MCA 2023-05-01\n PricingUnit: string, // Hubs add-on\n ProviderName: string, // Hubs add-on\n RegionId: string, // MS CM EA+MCA 2023-05-01\n RegionName: string, // MS CM EA+MCA 2023-05-01\n SubAccountId: string, // MS CM EA+MCA 2023-05-01\n SubAccountName: string, // MS CM EA+MCA 2023-05-01\n x_AccountName: string, // MS CM EA 2023-05-01\n x_AccountOwnerId: string, // MS CM EA 2023-05-01\n x_CostCenter: string, // MS CM EA 2023-05-01\n x_InvoiceNumber: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionId: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionName: string, // MS CM MCA 2023-05-01\n x_IngestionTime: datetime, // Hubs add-on\n x_MonetaryCommitment: real, // MS CM EA 2023-05-01\n x_Overage: real, // MS CM EA 2023-05-01\n x_PurchasingBillingAccountId: string, // MS CM EA 2023-05-01\n x_SkuOrderId: string, // MS CM EA+MCA 2023-05-01\n x_SkuOrderName: string, // MS CM EA+MCA 2023-05-01\n x_SkuSize: string, // MS CM EA+MCA 2023-05-01\n x_SkuTerm: int, // MS CM EA+MCA 2023-05-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubscriptionId: string, // MS CM EA+MCA 2023-05-01\n x_TransactionType: string // MS CM EA+MCA 2023-05-01\n)\n\n// Update policy for Transactions_raw -> Transactions_final_v1_2 table\n.alter table Transactions_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Transactions_raw\",\n \"Query\": \"Transactions_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n", "$fxv#11": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Common utility functions\n//\n// TIP: Use Ctrl+K,Ctrl+0 to collapse all regions in VS Code\n//======================================================================================================================\n\n\n//===| Date functions |=================================================================================================\n\n// monthstring\n.create-or-alter function \nwith (docstring = @'Returns the name of the month for the specified date (e.g. Jan or January)', folder =@'Common') \nmonthstring(['date']: datetime, length: int = 9)\n{\n substring(dynamic(['January','February','March','April','May','June','July','August','September','October','November','December'])[getmonth(['date']) - 1], 0, length)\n}\n\n// datestring\n.create-or-alter function \nwith (docstring = @'Converts 2 dates into a simple, user-friendly date range (e.g. Jan 1-Jan 3)', folder =@'Common') \ndatestring(start: datetime, end: datetime = datetime('0001-01-01'))\n{\n let month = (d: datetime) { monthstring(d, 3) };\n let endDate = iff(end == datetime('0001-01-01'), start, end);\n let sameDate = startofday(start) == startofday(endDate);\n let sameMonth = startofmonth(start) == startofmonth(endDate);\n let sameYear = startofyear(start) == startofyear(endDate);\n let fullMonth = startofday(start) == startofmonth(start) and startofday(endDate) == startofday(endofmonth(endDate));\n let fullYear = startofday(start) == startofyear(start) and startofday(endDate) == startofday(endofyear(endDate));\n let currentYear = sameYear and startofyear(start) == startofyear(now());\n case(\n // Full year | yyyy (same year) / yyyy-yyyy (diff years)\n fullYear,\n strcat(getyear(start), iff(sameYear, '', strcat('-', getyear(endDate)))),\n // 1 full mo, same year | Mmm yyyy\n fullMonth and sameMonth and sameYear,\n strcat(month(start), ' ', getyear(start)),\n // 2+ full mo, same year | Mmm-Mmm (current year) / Mmm-Mmm yyyy (other year)\n fullMonth and sameYear,\n strcat(month(start), '-', month(endDate), iff(currentYear, '', strcat(' ', getyear(endDate)))),\n // Full mo, diff year | Mmm yyyy-Mmm yyyy\n fullMonth and not(sameYear),\n strcat(month(start), ' ', getyear(start), '-', month(endDate), ' ', getyear(endDate)),\n // Same date | Mmm d (current year) / Mmm d, yyyy (other year)\n sameDate,\n strcat(month(start), ' ', dayofmonth(start), iff(currentYear, '', strcat(', ', getyear(endDate)))),\n // 1 partial M, same Y | Mmm d-d (current year) / Mmm d-d, yyyy (other year)\n not(fullMonth) and sameMonth and sameYear,\n strcat(month(start), ' ', dayofmonth(start), '-', dayofmonth(endDate), iff(currentYear, '', strcat(' ', getyear(endDate)))),\n // 2+ partial M, same Y | Mmm d-Mmm d (current year) / Mmm d-Mmm d, yyyy (other year)\n not(fullMonth) and not(sameMonth) and sameYear,\n strcat(month(start), ' ', dayofmonth(start), '-', month(endDate), ' ', dayofmonth(endDate), iff(currentYear, '', strcat(', ', getyear(endDate)))),\n // All other cases | Mmm d, yyyy-Mmm d, yyyy\n strcat(month(start), ' ', dayofmonth(start), ', ', getyear(start), '-', month(endDate), ' ', dayofmonth(endDate), ', ', getyear(endDate))\n )\n}\n\n// daterange\n.create-or-alter function \nwith (docstring = @'DEPRECATED: Please use datestring(); function will be removed on or after the Jan 2026 release', folder =@'Common') \ndaterange(start: datetime, end: datetime = datetime('0001-01-01'))\n{\n datestring(start, end)\n}\n\n// monthsago\n.create-or-alter function \nwith (docstring = 'DEPRECATED: Please use startofmonth(now(), -<# of months>); function will be removed on or after the Jan 2026 release', folder = 'Common')\nmonthsago(months: int)\n{\n datetime_add('month', -months, startofmonth(now()))\n}\n\n\n//===| Number functions |===============================================================================================\n// NOTE: Must be defined before string converters\n\n// delta\n.create-or-alter function \nwith (docstring = @'Compares 2 values and returns the percentage change from oldval to newval', folder =@'Common') \ndelta(oldval: double, newval: double)\n{\n (newval - todouble(oldval))/oldval\n}\n\n// percentOfTotal\n// NOTE: Must be before percent() function\n.create-or-alter function \nwith (docstring = @'Calculates the percentage of each record based on a required Count column', folder =@'Common') \npercentOfTotal(t: (Count: long), tot: long)\n{\n let total = todouble(tot);\n t \n | extend Percent = round(Count / total * 100, 3) \n | order by Count desc\n}\n\n// percent\n.create-or-alter function \nwith (docstring = @'Calculates the percentage of each record based on a required Count column', folder =@'Common') \npercent(t: (Count: long))\n{\n let total = todouble(toscalar(t | summarize sum(Count)));\n percentOfTotal(t, total)\n}\n\n// plusminus\n.create-or-alter function \nwith (docstring = 'Shows a +/- sign based on the direction of the number', folder = 'Common')\nplusminus(val: string)\n{\n let neg = substring(val, 0, 1) == '-';\n iff(neg, val, strcat('+', val))\n}\n\n// updown\n.create-or-alter function \nwith (docstring = 'Shows an up/down arrow based on the direction of the number', folder = 'Common')\nupdown(val: string)\n{\n // TODO: Handle 0\n let neg = substring(val, 0, 1) == '-';\n iff(neg, strcat('↓', substring(val, 1)), strcat('↑', val))\n}\n\n\n//===| String functions |===============================================================================================\n\n// percentstring\n// NOTE: Must be defined before deltastring\n.create-or-alter function \nwith (docstring = 'Calculate a percentage and render as a string', folder = 'Common')\npercentstring(num: double, total: double = 1.0, places: int = 9)\n{\n let value = 1.0 * num / total * 100;\n strcat(case(\n places != 9, round(value, places),\n value < 10, round(value, 2),\n round(value, 1)\n ), '%')\n}\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// arraystring\n.create-or-alter function \nwith (docstring = 'Convert an array to a comma-delimited string', folder = 'Common')\narraystring(arr: dynamic)\n{\n replace_string(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(\n tostring(arr)\n , @'^\\[\"', '')\n , @'\"\\]$', '')\n , @'^, ', '')\n , @', $', '')\n , @'^\\[]$', '')\n , '\",\"', ', ')\n}\n\n// deltastring\n.create-or-alter function \nwith (docstring = 'Calculate a delta percentage and render as a string', folder = 'Common')\ndeltastring(oldval: double, newval: double, places: int = 1, useArrows: bool = false)\n{\n let d = delta(oldval, newval);\n strcat(case(useArrows and d > 0, '↑', useArrows and d < 0, '↓', d < 0, '-', ''), percentstring(abs(d), 1, places))\n}\n\n// diffstring\n.create-or-alter function \nwith (docstring = 'Calculate the difference and render as a string', folder = 'Common')\ndiffstring(oldval: double, newval: double, places: int = 1)\n{\n plusminus(round(newval - oldval, places))\n}\n\n// numberstring\n.create-or-alter function \nwith (docstring = 'Convert a number to a string', folder = 'Common')\nnumberstring(num: double, abbrev: bool = true)\n{\n replace_regex(case(\n num >= 10000000000000, strcat(round(1.0 * num / 1000000000000, 1), 'T'),\n num >= 1000000000000, strcat(round(1.0 * num / 1000000000000, 2), 'T'),\n num >= 10000000000, strcat(round(1.0 * num / 1000000000, 1), 'B'),\n num >= 1000000000, strcat(round(1.0 * num / 1000000000, 2), 'B'),\n num >= 10000000, strcat(round(1.0 * num / 1000000, 1), 'M'),\n num >= 1000000, strcat(round(1.0 * num / 1000000, 2), 'M'),\n num >= 10000, strcat(round(1.0 * num / 1000, 1), 'K'),\n // Kusto doesn't support back-refs yet -- num > 1000, replace_regex(tostring(num), @'(\\d)(?=(\\d{3})+\\.)', @'\\1,'), // See https://docs.microsoft.com/azure/data-explorer/kusto/query/re2-library\n num > 1000, replace_regex(tostring(num), @'([0-9]{3})$', @',\\1'), //num / 1000, ',', substring(tostring(num), 0) - (num / 1000 * 1000)),\n tostring(num)\n ), @'\\.0$', '')\n}\n\n\n//===| Other |==========================================================================================================\n\n// ifempty\n.create-or-alter function \nwith (docstring = 'Replaces an empty value with the specified default value', folder = 'Common')\nifempty(val: dynamic, defaultVal: dynamic)\n{\n iff(isempty(val), defaultVal, val)\n}\n", "$fxv#12": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Hub database / Open data functions\n// Wrap Ingestion database tables for easy access.\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n\n// PricingUnits\n.create-or-alter function\nwith (docstring = 'Gets pricing units from the FinOps toolkit PricingUnits open data.', folder = 'OpenData')\nPricingUnits()\n{\n database('Ingestion').PricingUnits\n}\n\n// Regions\n.create-or-alter function\nwith (docstring = 'Gets regions from the FinOps toolkit Regions open data.', folder = 'OpenData')\nRegion()\n{\n database('Ingestion').Regions\n}\n\n// ResourceTypes\n.create-or-alter function\nwith (docstring = 'Gets resource types from the FinOps toolkit ResourceTypes open data.', folder = 'OpenData')\nResourceType()\n{\n database('Ingestion').ResourceTypes\n}\n\n// Services\n.create-or-alter function\nwith (docstring = 'Gets services from the FinOps toolkit Services open data.', folder = 'OpenData')\nServices()\n{\n database('Ingestion').Services\n}\n", "$fxv#13": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Hub database / FOCUS 1.0 functions\n// Used for reporting with backward compatibility.\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n\n// CommitmentDiscountUsage_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all commitment discount usage records aligned to FOCUS 1.0.', folder = 'CommitmentDiscountUsage')\nCommitmentDiscountUsage_v1_0()\n{\n database('Ingestion').CommitmentDiscountUsage_final_v1_0\n | union (\n database('Ingestion').CommitmentDiscountUsage_final_v1_2\n // Convert real to decimal\n | extend\n CommitmentDiscountQuantity = todecimal(CommitmentDiscountQuantity),\n ConsumedQuantity = todecimal(ConsumedQuantity),\n x_CommitmentDiscountCommittedCount = todecimal(x_CommitmentDiscountCommittedCount),\n x_CommitmentDiscountCommittedAmount = todecimal(x_CommitmentDiscountCommittedAmount),\n x_CommitmentDiscountNormalizedRatio = todecimal(x_CommitmentDiscountNormalizedRatio)\n )\n | project\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId,\n CommitmentDiscountType,\n ConsumedQuantity,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SubAccountId,\n x_CommitmentDiscountCommittedCount,\n x_CommitmentDiscountCommittedAmount,\n x_CommitmentDiscountNormalizedGroup,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountQuantity,\n x_IngestionTime,\n x_ResourceGroupName,\n x_ResourceType,\n x_ServiceModel,\n x_SkuOrderId,\n x_SkuSize,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n\n// Costs_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all cost and usage records aligned to FOCUS 1.0.', folder = 'Costs')\nCosts_v1_0()\n{\n database('Ingestion').Costs_final_v1_0\n | union (\n database('Ingestion').Costs_final_v1_2\n // Convert real to decimal\n | extend\n BilledCost = todecimal(BilledCost),\n CommitmentDiscountQuantity = todecimal(CommitmentDiscountQuantity),\n ConsumedQuantity = todecimal(ConsumedQuantity),\n ContractedCost = todecimal(ContractedCost),\n ContractedUnitPrice = todecimal(ContractedUnitPrice),\n EffectiveCost = todecimal(EffectiveCost),\n ListCost = todecimal(ListCost),\n ListUnitPrice = todecimal(ListUnitPrice),\n PricingQuantity = todecimal(PricingQuantity),\n x_BilledCostInUsd = todecimal(x_BilledCostInUsd),\n x_BilledUnitPrice = todecimal(x_BilledUnitPrice),\n x_BillingExchangeRate = todecimal(x_BillingExchangeRate),\n x_CommitmentDiscountNormalizedRatio = todecimal(x_CommitmentDiscountNormalizedRatio),\n x_ContractedCostInUsd = todecimal(x_ContractedCostInUsd),\n x_CurrencyConversionRate = todecimal(x_CurrencyConversionRate),\n x_EffectiveCostInUsd = todecimal(x_EffectiveCostInUsd),\n x_EffectiveUnitPrice = todecimal(x_EffectiveUnitPrice),\n x_ListCostInUsd = todecimal(x_ListCostInUsd),\n x_PricingBlockSize = todecimal(x_PricingBlockSize)\n // Rename columns\n | project-rename\n x_InvoiceId = InvoiceId,\n x_PricingCurrency = PricingCurrency,\n x_SkuMeterName = SkuMeter\n // Generate historical x_SkuDetails format from SkuPriceDetails\n | extend x_SkuDetails = iff(isnotempty(x_SkuDetails), x_SkuDetails, parse_json(replace_regex(tostring(SkuPriceDetails), @'([\\{,])\"x_', @'\\1\"')))\n )\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId,\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory,\n ChargeClass,\n ChargeDescription,\n ChargeFrequency,\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId,\n CommitmentDiscountName,\n CommitmentDiscountStatus,\n CommitmentDiscountType,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost,\n ContractedUnitPrice,\n EffectiveCost,\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory,\n PricingQuantity,\n PricingUnit,\n ProviderName,\n PublisherName,\n RegionId,\n RegionName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SkuId,\n SkuPriceId,\n SubAccountId,\n SubAccountName,\n SubAccountType,\n Tags,\n x_AccountId,\n x_AccountName,\n x_AccountOwnerId,\n x_BilledCostInUsd,\n x_BilledUnitPrice,\n x_BillingAccountAgreement,\n x_BillingAccountId,\n x_BillingAccountName,\n x_BillingExchangeRate,\n x_BillingExchangeRateDate,\n x_BillingProfileId,\n x_BillingProfileName,\n x_ChargeId,\n x_ContractedCostInUsd,\n x_CostAllocationRuleName,\n x_CostCategories,\n x_CostCenter,\n x_Credits,\n x_CostType,\n x_CurrencyConversionRate,\n x_CustomerId,\n x_CustomerName,\n x_Discount,\n x_EffectiveCostInUsd,\n x_EffectiveUnitPrice,\n x_ExportTime,\n x_IngestionTime,\n x_InvoiceId,\n x_InvoiceIssuerId,\n x_InvoiceSectionId,\n x_InvoiceSectionName,\n x_ListCostInUsd,\n x_Location,\n x_Operation,\n x_PartnerCreditApplied,\n x_PartnerCreditRate,\n x_PricingBlockSize,\n x_PricingCurrency,\n x_PricingSubcategory,\n x_PricingUnitDescription,\n x_Project,\n x_PublisherCategory,\n x_PublisherId,\n x_ResellerId,\n x_ResellerName,\n x_ResourceGroupName,\n x_ResourceType,\n x_ServiceCode,\n x_ServiceId,\n x_ServicePeriodEnd,\n x_ServicePeriodStart,\n x_SkuDescription,\n x_SkuDetails,\n x_SkuIsCreditEligible,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterName,\n x_SkuMeterSubcategory,\n x_SkuOfferId,\n x_SkuOrderId,\n x_SkuOrderName,\n x_SkuPartNumber,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuTerm,\n x_SkuTier,\n x_SourceChanges,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_UsageType\n}\n\n\n// Prices_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all prices aligned to FOCUS 1.0.', folder = 'Prices')\nPrices_v1_0()\n{\n database('Ingestion').Prices_final_v1_0\n | union (\n database('Ingestion').Prices_final_v1_2\n // Convert real to decimal\n | extend\n ContractedUnitPrice = todecimal(ContractedUnitPrice),\n ListUnitPrice = todecimal(ListUnitPrice),\n x_BaseUnitPrice = todecimal(x_BaseUnitPrice),\n x_CommitmentDiscountNormalizedRatio = todecimal(x_CommitmentDiscountNormalizedRatio),\n x_ContractedUnitPriceDiscount = todecimal(x_ContractedUnitPriceDiscount),\n x_ContractedUnitPriceDiscountPercent = todecimal(x_ContractedUnitPriceDiscountPercent),\n x_EffectiveUnitPrice = todecimal(x_EffectiveUnitPrice),\n x_EffectiveUnitPriceDiscount = todecimal(x_EffectiveUnitPriceDiscount),\n x_EffectiveUnitPriceDiscountPercent = todecimal(x_EffectiveUnitPriceDiscountPercent),\n x_PricingBlockSize = todecimal(x_PricingBlockSize),\n x_SkuIncludedQuantity = todecimal(x_SkuIncludedQuantity),\n x_SkuTier = todecimal(x_SkuTier),\n x_TotalUnitPriceDiscount = todecimal(x_TotalUnitPriceDiscount),\n x_TotalUnitPriceDiscountPercent = todecimal(x_TotalUnitPriceDiscountPercent) \n // Rename columns\n | project-rename\n x_PricingCurrency = PricingCurrency,\n x_SkuMeterName = SkuMeter\n )\n | project\n BillingAccountId,\n BillingAccountName,\n BillingCurrency,\n ChargeCategory,\n CommitmentDiscountCategory,\n CommitmentDiscountType,\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory,\n PricingUnit,\n SkuId,\n SkuPriceId,\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement,\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent,\n x_EffectivePeriodEnd,\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingCurrency,\n x_PricingSubcategory,\n x_PricingUnitDescription,\n x_SkuDescription,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterName,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent\n}\n\n\n// Recommendations_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all recommendations aligned to FOCUS 1.0.', folder = 'Recommendations')\nRecommendations_v1_0()\n{\n database('Ingestion').Recommendations_final_v1_0\n | union (\n database('Ingestion').Recommendations_final_v1_2\n // Convert real to decimal\n | extend\n x_EffectiveCostAfter = todecimal(x_EffectiveCostAfter),\n x_EffectiveCostBefore = todecimal(x_EffectiveCostBefore),\n x_EffectiveCostSavings = todecimal(x_EffectiveCostSavings)\n )\n | project\n ProviderName,\n SubAccountId,\n x_IngestionTime,\n x_EffectiveCostAfter,\n x_EffectiveCostBefore,\n x_EffectiveCostSavings,\n x_RecommendationDate,\n x_RecommendationDetails,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n\n// Transactions_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all transactions aligned to FOCUS 1.0.', folder = 'Transactions')\nTransactions_v1_0()\n{\n database('Ingestion').Transactions_final_v1_0\n | union (\n database('Ingestion').Transactions_final_v1_2\n // Convert real to decimal\n | extend\n BilledCost = todecimal(BilledCost),\n PricingQuantity = todecimal(PricingQuantity),\n x_MonetaryCommitment = todecimal(x_MonetaryCommitment),\n x_Overage = todecimal(x_Overage)\n // Rename columns\n | project-rename\n x_InvoiceId = InvoiceId\n )\n | project\n BilledCost,\n BillingAccountId,\n BillingAccountName,\n BillingCurrency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory,\n ChargeClass,\n ChargeDescription,\n ChargeFrequency,\n ChargePeriodStart,\n PricingQuantity,\n PricingUnit,\n ProviderName,\n RegionId,\n RegionName,\n SubAccountId,\n SubAccountName,\n x_AccountName,\n x_AccountOwnerId,\n x_CostCenter,\n x_InvoiceId,\n x_InvoiceNumber,\n x_InvoiceSectionId,\n x_InvoiceSectionName,\n x_IngestionTime,\n x_MonetaryCommitment,\n x_Overage,\n x_PurchasingBillingAccountId,\n x_SkuOrderId,\n x_SkuOrderName,\n x_SkuSize,\n x_SkuTerm,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId,\n x_TransactionType\n}\n", @@ -18333,7 +18333,7 @@ "$fxv#6": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Common utility functions\n//\n// TIP: Use Ctrl+K,Ctrl+0 to collapse all regions in VS Code\n//======================================================================================================================\n\n\n//===| Date functions |=================================================================================================\n\n// monthstring\n.create-or-alter function \nwith (docstring = @'Returns the name of the month for the specified date (e.g. Jan or January)', folder =@'Common') \nmonthstring(['date']: datetime, length: int = 9)\n{\n substring(dynamic(['January','February','March','April','May','June','July','August','September','October','November','December'])[getmonth(['date']) - 1], 0, length)\n}\n\n// datestring\n.create-or-alter function \nwith (docstring = @'Converts 2 dates into a simple, user-friendly date range (e.g. Jan 1-Jan 3)', folder =@'Common') \ndatestring(start: datetime, end: datetime = datetime('0001-01-01'))\n{\n let month = (d: datetime) { monthstring(d, 3) };\n let endDate = iff(end == datetime('0001-01-01'), start, end);\n let sameDate = startofday(start) == startofday(endDate);\n let sameMonth = startofmonth(start) == startofmonth(endDate);\n let sameYear = startofyear(start) == startofyear(endDate);\n let fullMonth = startofday(start) == startofmonth(start) and startofday(endDate) == startofday(endofmonth(endDate));\n let fullYear = startofday(start) == startofyear(start) and startofday(endDate) == startofday(endofyear(endDate));\n let currentYear = sameYear and startofyear(start) == startofyear(now());\n case(\n // Full year | yyyy (same year) / yyyy-yyyy (diff years)\n fullYear,\n strcat(getyear(start), iff(sameYear, '', strcat('-', getyear(endDate)))),\n // 1 full mo, same year | Mmm yyyy\n fullMonth and sameMonth and sameYear,\n strcat(month(start), ' ', getyear(start)),\n // 2+ full mo, same year | Mmm-Mmm (current year) / Mmm-Mmm yyyy (other year)\n fullMonth and sameYear,\n strcat(month(start), '-', month(endDate), iff(currentYear, '', strcat(' ', getyear(endDate)))),\n // Full mo, diff year | Mmm yyyy-Mmm yyyy\n fullMonth and not(sameYear),\n strcat(month(start), ' ', getyear(start), '-', month(endDate), ' ', getyear(endDate)),\n // Same date | Mmm d (current year) / Mmm d, yyyy (other year)\n sameDate,\n strcat(month(start), ' ', dayofmonth(start), iff(currentYear, '', strcat(', ', getyear(endDate)))),\n // 1 partial M, same Y | Mmm d-d (current year) / Mmm d-d, yyyy (other year)\n not(fullMonth) and sameMonth and sameYear,\n strcat(month(start), ' ', dayofmonth(start), '-', dayofmonth(endDate), iff(currentYear, '', strcat(' ', getyear(endDate)))),\n // 2+ partial M, same Y | Mmm d-Mmm d (current year) / Mmm d-Mmm d, yyyy (other year)\n not(fullMonth) and not(sameMonth) and sameYear,\n strcat(month(start), ' ', dayofmonth(start), '-', month(endDate), ' ', dayofmonth(endDate), iff(currentYear, '', strcat(', ', getyear(endDate)))),\n // All other cases | Mmm d, yyyy-Mmm d, yyyy\n strcat(month(start), ' ', dayofmonth(start), ', ', getyear(start), '-', month(endDate), ' ', dayofmonth(endDate), ', ', getyear(endDate))\n )\n}\n\n// daterange\n.create-or-alter function \nwith (docstring = @'DEPRECATED: Please use datestring(); function will be removed on or after the Jan 2026 release', folder =@'Common') \ndaterange(start: datetime, end: datetime = datetime('0001-01-01'))\n{\n datestring(start, end)\n}\n\n// monthsago\n.create-or-alter function \nwith (docstring = 'DEPRECATED: Please use startofmonth(now(), -<# of months>); function will be removed on or after the Jan 2026 release', folder = 'Common')\nmonthsago(months: int)\n{\n datetime_add('month', -months, startofmonth(now()))\n}\n\n\n//===| Number functions |===============================================================================================\n// NOTE: Must be defined before string converters\n\n// delta\n.create-or-alter function \nwith (docstring = @'Compares 2 values and returns the percentage change from oldval to newval', folder =@'Common') \ndelta(oldval: double, newval: double)\n{\n (newval - todouble(oldval))/oldval\n}\n\n// percentOfTotal\n// NOTE: Must be before percent() function\n.create-or-alter function \nwith (docstring = @'Calculates the percentage of each record based on a required Count column', folder =@'Common') \npercentOfTotal(t: (Count: long), tot: long)\n{\n let total = todouble(tot);\n t \n | extend Percent = round(Count / total * 100, 3) \n | order by Count desc\n}\n\n// percent\n.create-or-alter function \nwith (docstring = @'Calculates the percentage of each record based on a required Count column', folder =@'Common') \npercent(t: (Count: long))\n{\n let total = todouble(toscalar(t | summarize sum(Count)));\n percentOfTotal(t, total)\n}\n\n// plusminus\n.create-or-alter function \nwith (docstring = 'Shows a +/- sign based on the direction of the number', folder = 'Common')\nplusminus(val: string)\n{\n let neg = substring(val, 0, 1) == '-';\n iff(neg, val, strcat('+', val))\n}\n\n// updown\n.create-or-alter function \nwith (docstring = 'Shows an up/down arrow based on the direction of the number', folder = 'Common')\nupdown(val: string)\n{\n // TODO: Handle 0\n let neg = substring(val, 0, 1) == '-';\n iff(neg, strcat('↓', substring(val, 1)), strcat('↑', val))\n}\n\n\n//===| String functions |===============================================================================================\n\n// percentstring\n// NOTE: Must be defined before deltastring\n.create-or-alter function \nwith (docstring = 'Calculate a percentage and render as a string', folder = 'Common')\npercentstring(num: double, total: double = 1.0, places: int = 9)\n{\n let value = 1.0 * num / total * 100;\n strcat(case(\n places != 9, round(value, places),\n value < 10, round(value, 2),\n round(value, 1)\n ), '%')\n}\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// arraystring\n.create-or-alter function \nwith (docstring = 'Convert an array to a comma-delimited string', folder = 'Common')\narraystring(arr: dynamic)\n{\n replace_string(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(\n tostring(arr)\n , @'^\\[\"', '')\n , @'\"\\]$', '')\n , @'^, ', '')\n , @', $', '')\n , @'^\\[]$', '')\n , '\",\"', ', ')\n}\n\n// deltastring\n.create-or-alter function \nwith (docstring = 'Calculate a delta percentage and render as a string', folder = 'Common')\ndeltastring(oldval: double, newval: double, places: int = 1, useArrows: bool = false)\n{\n let d = delta(oldval, newval);\n strcat(case(useArrows and d > 0, '↑', useArrows and d < 0, '↓', d < 0, '-', ''), percentstring(abs(d), 1, places))\n}\n\n// diffstring\n.create-or-alter function \nwith (docstring = 'Calculate the difference and render as a string', folder = 'Common')\ndiffstring(oldval: double, newval: double, places: int = 1)\n{\n plusminus(round(newval - oldval, places))\n}\n\n// numberstring\n.create-or-alter function \nwith (docstring = 'Convert a number to a string', folder = 'Common')\nnumberstring(num: double, abbrev: bool = true)\n{\n replace_regex(case(\n num >= 10000000000000, strcat(round(1.0 * num / 1000000000000, 1), 'T'),\n num >= 1000000000000, strcat(round(1.0 * num / 1000000000000, 2), 'T'),\n num >= 10000000000, strcat(round(1.0 * num / 1000000000, 1), 'B'),\n num >= 1000000000, strcat(round(1.0 * num / 1000000000, 2), 'B'),\n num >= 10000000, strcat(round(1.0 * num / 1000000, 1), 'M'),\n num >= 1000000, strcat(round(1.0 * num / 1000000, 2), 'M'),\n num >= 10000, strcat(round(1.0 * num / 1000, 1), 'K'),\n // Kusto doesn't support back-refs yet -- num > 1000, replace_regex(tostring(num), @'(\\d)(?=(\\d{3})+\\.)', @'\\1,'), // See https://docs.microsoft.com/azure/data-explorer/kusto/query/re2-library\n num > 1000, replace_regex(tostring(num), @'([0-9]{3})$', @',\\1'), //num / 1000, ',', substring(tostring(num), 0) - (num / 1000 * 1000)),\n tostring(num)\n ), @'\\.0$', '')\n}\n\n\n//===| Other |==========================================================================================================\n\n// ifempty\n.create-or-alter function \nwith (docstring = 'Replaces an empty value with the specified default value', folder = 'Common')\nifempty(val: dynamic, defaultVal: dynamic)\n{\n iff(isempty(val), defaultVal, val)\n}\n", "$fxv#7": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// Used for data ingestion, normalization, and cleansing.\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Settings |=======================================================================================================\n\n.create-merge table HubSettingsLog (\n version: string,\n scopes: dynamic,\n retention: dynamic\n)\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// HubSettings function\n.create-or-alter function\nwith (docstring='Gets the latest version of hub settings.', folder='Settings')\nHubSettings()\n{\n HubSettingsLog\n | extend timestamp = ingestion_time()\n | summarize arg_max(timestamp, *)\n}\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// HubScopes function\n.create-or-alter function\nwith (docstring='Gets the currently configured scopes.', folder='Settings')\nHubScopes()\n{\n HubSettings\n | project scopes\n | mv-expand scopes\n}\n\n\n//===| Open data |======================================================================================================\n\n// PricingUnits -- Create table if it doesn't exist\n.create-merge table PricingUnits ( ignore: string )\n\n// PricingUnits -- Remove all columns\n.alter table PricingUnits ( ignore: string )\n\n// PricingUnits -- Redefine all columns to change types\n.alter table PricingUnits (\n x_PricingUnitDescription: string,\n x_PricingBlockSize: real,\n PricingUnit: string\n)\n\n// Regions\n.create-merge table Regions(\n ResourceLocation: string,\n RegionId: string,\n RegionName: string\n)\n\n// ResourceTypes\n.create-merge table ResourceTypes(\n x_ResourceType: string,\n SingularDisplayName: string,\n PluralDisplayName: string,\n LowerSingularDisplayName: string,\n LowerPluralDisplayName: string,\n IsPreview: bool,\n Description: string,\n IconUri: string\n)\n\n// Services\n.create-merge table Services(\n x_ConsumedService: string,\n x_ResourceType: string,\n ServiceName: string,\n ServiceCategory: string,\n ServiceSubcategory: string,\n PublisherName: string,\n x_PublisherCategory: string,\n x_Environment: string,\n x_ServiceModel: string\n)\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// parse_resourceid\n.create-or-alter function\nwith (docstring = 'Parses an Azure resource ID to extract resource attributes like the name, type, resource group, and subaccount ID.', folder = 'Common')\nparse_resourceid(resourceId: string) {\n let ResourceId = tolower(resourceId);\n // let ResourceId = tolower('/providers/Microsoft.BillingBenefits/savingsPlanOrders/2d2e284b-0638-427e-b8c6-1b874d4f17c8/sp/xxx');\n let SubAccountId = tostring(extract('/subscriptions/[^/]+', 1, ResourceId));\n let x_ResourceGroupName = tostring(extract('/resourcegroups/[^/]+', 1, ResourceId));\n let tmp_ResourceId = iff(ResourceId !contains '/providers/' and ResourceId startswith '/subscriptions/', strcat('/providers/microsoft.resources', ResourceId), ResourceId);\n let providerPath = iff(tmp_ResourceId !contains '/providers/', '', tostring(split(tmp_ResourceId, '/providers/')[-1]));\n let x_ResourceProvider = iff(isempty(providerPath), '', split(providerPath, '/')[0]);\n let tmp_ResourceProviderPath = iff(isempty(providerPath), '', substring(providerPath, strlen(x_ResourceProvider) + 1));\n let segments = split(tmp_ResourceProviderPath, '/');\n let ResourceName = trim(@'/+', replace_string(strcat_array(array_iff(\n dynamic([false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true]),\n segments, dynamic([])), '/'), '//', '/'));\n let x_ResourceTypePath = trim(@'/+', replace_string(strcat_array(array_iff(\n dynamic([true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false]),\n segments, dynamic([])), '/'), '//', '/'));\n let xRT = iff(isempty(x_ResourceProvider) or isempty(x_ResourceTypePath), '', strcat(x_ResourceProvider, '/', x_ResourceTypePath));\n // TODO: Remove ResourceType in 0.9\n bag_pack('ResourceId', ResourceId, 'ResourceName', ResourceName, 'ResourceType', xRT, 'SubAccountId', SubAccountId, 'x_ResourceGroupName', x_ResourceGroupName, 'x_ResourceProvider', x_ResourceProvider, 'x_ResourceType', xRT)\n}\n", "$fxv#8": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// Used for data ingestion, normalization, and cleansing.\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| ActualCosts |====================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_raw table -- Create the table if it doesn't exist\n.create-merge table ActualCosts_raw ( ignore: string )\n\n// ActualCosts_raw table -- Remove all columns to allow changing column types\n.alter table ActualCosts_raw ( ignore: string )\n\n// ActualCosts_raw table -- Redefine all columns\n.alter table ActualCosts_raw (\n AccountName: string,\n AccountOwnerId: string,\n AdditionalInfo: string,\n AvailabilityZone: string,\n BillingAccountId: string, \n BillingAccountName: string,\n BillingCurrency: string,\n BillingPeriodEndDate: datetime,\n BillingPeriodStartDate: datetime,\n BillingProfileId: string,\n BillingProfileName: string,\n ChargeType: string,\n ConsumedService: string,\n CostCenter: string,\n Cost: real,\n Date: datetime,\n EffectivePrice: real,\n Frequency: string,\n InvoiceSection: string,\n InvoiceSectionId: string,\n IsAzureCreditEligible: bool,\n MeterCategory: string,\n MeterId: string,\n MeterName: string,\n MeterRegion: string,\n MeterSubCategory: string,\n OfferId: string,\n PartNumber: string,\n PlanName: string,\n Product: string,\n ProductOrderId: string,\n ProductOrderName: string,\n PublisherName: string,\n PublisherType: string,\n Quantity: real,\n ReservationId: string,\n ReservationName: string,\n ResourceGroup: string,\n ResourceId: string,\n ResourceLocation: string,\n ResourceName: string,\n ServiceFamily: string,\n ServiceInfo1: string,\n ServiceInfo2: string,\n SubscriptionId: string,\n SubscriptionName: string,\n Tags: string,\n Term: string,\n UnitOfMeasure: string,\n UnitPrice: real\n)\n\n// ActualCosts_raw ingestion mapping\n.create-or-alter table ActualCosts_raw ingestion parquet mapping \"ActualCosts_raw_mapping\"\n```\n[\n { \"Column\": \"AccountName\", \"Properties\": { \"Field\": \"AccountName\" } },\n { \"Column\": \"AccountOwnerId\", \"Properties\": { \"Field\": \"AccountOwnerId\" } },\n { \"Column\": \"AdditionalInfo\", \"Properties\": { \"Field\": \"AdditionalInfo\" } },\n { \"Column\": \"AvailabilityZone\", \"Properties\": { \"Field\": \"AvailabilityZone\" } },\n { \"Column\": \"BillingAccountId\", \"Properties\": { \"Field\": \"BillingAccountId\" } },\n { \"Column\": \"BillingAccountName\", \"Properties\": { \"Field\": \"BillingAccountName\" } },\n { \"Column\": \"BillingCurrency\", \"Properties\": { \"Field\": \"BillingCurrency\" } },\n { \"Column\": \"BillingPeriodEndDate\", \"Properties\": { \"Field\": \"BillingPeriodEndDate\" } },\n { \"Column\": \"BillingPeriodStartDate\", \"Properties\": { \"Field\": \"BillingPeriodStartDate\" } },\n { \"Column\": \"BillingProfileId\", \"Properties\": { \"Field\": \"BillingProfileId\" } },\n { \"Column\": \"BillingProfileName\", \"Properties\": { \"Field\": \"BillingProfileName\" } },\n { \"Column\": \"ChargeType\", \"Properties\": { \"Field\": \"ChargeType\" } },\n { \"Column\": \"ConsumedService\", \"Properties\": { \"Field\": \"ConsumedService\" } },\n { \"Column\": \"CostCenter\", \"Properties\": { \"Field\": \"CostCenter\" } },\n { \"Column\": \"Cost\", \"Properties\": { \"Field\": \"Cost\" } },\n { \"Column\": \"Date\", \"Properties\": { \"Field\": \"Date\" } },\n { \"Column\": \"EffectivePrice\", \"Properties\": { \"Field\": \"EffectivePrice\" } },\n { \"Column\": \"Frequency\", \"Properties\": { \"Field\": \"Frequency\" } },\n { \"Column\": \"InvoiceSection\", \"Properties\": { \"Field\": \"InvoiceSection\" } },\n { \"Column\": \"InvoiceSectionId\", \"Properties\": { \"Field\": \"InvoiceSectionId\" } },\n { \"Column\": \"IsAzureCreditEligible\", \"Properties\": { \"Field\": \"IsAzureCreditEligible\" } },\n { \"Column\": \"MeterCategory\", \"Properties\": { \"Field\": \"MeterCategory\" } },\n { \"Column\": \"MeterId\", \"Properties\": { \"Field\": \"MeterId\" } },\n { \"Column\": \"MeterName\", \"Properties\": { \"Field\": \"MeterName\" } },\n { \"Column\": \"MeterRegion\", \"Properties\": { \"Field\": \"MeterRegion\" } },\n { \"Column\": \"MeterSubCategory\", \"Properties\": { \"Field\": \"MeterSubCategory\" } },\n { \"Column\": \"OfferId\", \"Properties\": { \"Field\": \"OfferId\" } },\n { \"Column\": \"PartNumber\", \"Properties\": { \"Field\": \"PartNumber\" } },\n { \"Column\": \"PlanName\", \"Properties\": { \"Field\": \"PlanName\" } },\n { \"Column\": \"Product\", \"Properties\": { \"Field\": \"Product\" } },\n { \"Column\": \"ProductOrderId\", \"Properties\": { \"Field\": \"ProductOrderId\" } },\n { \"Column\": \"ProductOrderName\", \"Properties\": { \"Field\": \"ProductOrderName\" } },\n { \"Column\": \"PublisherName\", \"Properties\": { \"Field\": \"PublisherName\" } },\n { \"Column\": \"PublisherType\", \"Properties\": { \"Field\": \"PublisherType\" } },\n { \"Column\": \"Quantity\", \"Properties\": { \"Field\": \"Quantity\" } },\n { \"Column\": \"ReservationId\", \"Properties\": { \"Field\": \"ReservationId\" } },\n { \"Column\": \"ReservationName\", \"Properties\": { \"Field\": \"ReservationName\" } },\n { \"Column\": \"ResourceGroup\", \"Properties\": { \"Field\": \"ResourceGroup\" } },\n { \"Column\": \"ResourceId\", \"Properties\": { \"Field\": \"ResourceId\" } },\n { \"Column\": \"ResourceLocation\", \"Properties\": { \"Field\": \"ResourceLocation\" } },\n { \"Column\": \"ResourceName\", \"Properties\": { \"Field\": \"ResourceName\" } },\n { \"Column\": \"ServiceFamily\", \"Properties\": { \"Field\": \"ServiceFamily\" } },\n { \"Column\": \"ServiceInfo1\", \"Properties\": { \"Field\": \"ServiceInfo1\" } },\n { \"Column\": \"ServiceInfo2\", \"Properties\": { \"Field\": \"ServiceInfo2\" } },\n { \"Column\": \"SubscriptionId\", \"Properties\": { \"Field\": \"SubscriptionId\" } },\n { \"Column\": \"SubscriptionName\", \"Properties\": { \"Field\": \"SubscriptionName\" } },\n { \"Column\": \"Tags\", \"Properties\": { \"Field\": \"Tags\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"UnitOfMeasure\", \"Properties\": { \"Field\": \"UnitOfMeasure\" } },\n { \"Column\": \"UnitPrice\", \"Properties\": { \"Field\": \"UnitPrice\" } }\n]\n```\n\n// ActualCosts_raw retention policy (clear historical data)\n.alter-merge table ActualCosts_raw policy retention softdelete = 0d recoverability = disabled\n\n// ActualCosts_raw retention policy (set the user-defined retention period)\n.alter-merge table ActualCosts_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable ActualCosts_raw streaming ingestion (required for Fabric)\n.alter table ActualCosts_raw policy streamingingestion disable\n\n\n//===| AmortizedCosts |=================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_raw table -- Create the table if it doesn't exist\n.create-merge table AmortizedCosts_raw ( ignore: string )\n\n// AmortizedCosts_raw table -- Remove all columns to allow changing column types\n.alter table AmortizedCosts_raw ( ignore: string )\n\n// AmortizedCosts_raw table -- Redefine all columns\n.alter table AmortizedCosts_raw (\n AccountName: string,\n AccountOwnerId: string,\n AdditionalInfo: string,\n AvailabilityZone: string,\n BillingAccountId: string, \n BillingAccountName: string,\n BillingCurrency: string,\n BillingPeriodEndDate: datetime,\n BillingPeriodStartDate: datetime,\n BillingProfileId: string,\n BillingProfileName: string,\n ChargeType: string,\n ConsumedService: string,\n CostCenter: string,\n Cost: real,\n Date: datetime,\n EffectivePrice: real,\n Frequency: string,\n InvoiceSection: string,\n InvoiceSectionId: string,\n IsAzureCreditEligible: bool,\n MeterCategory: string,\n MeterId: string,\n MeterName: string,\n MeterRegion: string,\n MeterSubCategory: string,\n OfferId: string,\n PartNumber: string,\n PlanName: string,\n Product: string,\n ProductOrderId: string,\n ProductOrderName: string,\n PublisherName: string,\n PublisherType: string,\n Quantity: real,\n ReservationId: string,\n ReservationName: string,\n ResourceGroup: string,\n ResourceId: string,\n ResourceLocation: string,\n ResourceName: string,\n ServiceFamily: string,\n ServiceInfo1: string,\n ServiceInfo2: string,\n SubscriptionId: string,\n SubscriptionName: string,\n Tags: string,\n Term: string,\n UnitOfMeasure: string,\n UnitPrice: real\n)\n\n// AmortizedCosts_raw ingestion mapping\n.create-or-alter table AmortizedCosts_raw ingestion parquet mapping \"AmortizedCosts_raw_mapping\"\n```\n[\n { \"Column\": \"AccountName\", \"Properties\": { \"Field\": \"AccountName\" } },\n { \"Column\": \"AccountOwnerId\", \"Properties\": { \"Field\": \"AccountOwnerId\" } },\n { \"Column\": \"AdditionalInfo\", \"Properties\": { \"Field\": \"AdditionalInfo\" } },\n { \"Column\": \"AvailabilityZone\", \"Properties\": { \"Field\": \"AvailabilityZone\" } },\n { \"Column\": \"BillingAccountId\", \"Properties\": { \"Field\": \"BillingAccountId\" } },\n { \"Column\": \"BillingAccountName\", \"Properties\": { \"Field\": \"BillingAccountName\" } },\n { \"Column\": \"BillingCurrency\", \"Properties\": { \"Field\": \"BillingCurrency\" } },\n { \"Column\": \"BillingPeriodEndDate\", \"Properties\": { \"Field\": \"BillingPeriodEndDate\" } },\n { \"Column\": \"BillingPeriodStartDate\", \"Properties\": { \"Field\": \"BillingPeriodStartDate\" } },\n { \"Column\": \"BillingProfileId\", \"Properties\": { \"Field\": \"BillingProfileId\" } },\n { \"Column\": \"BillingProfileName\", \"Properties\": { \"Field\": \"BillingProfileName\" } },\n { \"Column\": \"ChargeType\", \"Properties\": { \"Field\": \"ChargeType\" } },\n { \"Column\": \"ConsumedService\", \"Properties\": { \"Field\": \"ConsumedService\" } },\n { \"Column\": \"CostCenter\", \"Properties\": { \"Field\": \"CostCenter\" } },\n { \"Column\": \"Cost\", \"Properties\": { \"Field\": \"Cost\" } },\n { \"Column\": \"Date\", \"Properties\": { \"Field\": \"Date\" } },\n { \"Column\": \"EffectivePrice\", \"Properties\": { \"Field\": \"EffectivePrice\" } },\n { \"Column\": \"Frequency\", \"Properties\": { \"Field\": \"Frequency\" } },\n { \"Column\": \"InvoiceSection\", \"Properties\": { \"Field\": \"InvoiceSection\" } },\n { \"Column\": \"InvoiceSectionId\", \"Properties\": { \"Field\": \"InvoiceSectionId\" } },\n { \"Column\": \"IsAzureCreditEligible\", \"Properties\": { \"Field\": \"IsAzureCreditEligible\" } },\n { \"Column\": \"MeterCategory\", \"Properties\": { \"Field\": \"MeterCategory\" } },\n { \"Column\": \"MeterId\", \"Properties\": { \"Field\": \"MeterId\" } },\n { \"Column\": \"MeterName\", \"Properties\": { \"Field\": \"MeterName\" } },\n { \"Column\": \"MeterRegion\", \"Properties\": { \"Field\": \"MeterRegion\" } },\n { \"Column\": \"MeterSubCategory\", \"Properties\": { \"Field\": \"MeterSubCategory\" } },\n { \"Column\": \"OfferId\", \"Properties\": { \"Field\": \"OfferId\" } },\n { \"Column\": \"PartNumber\", \"Properties\": { \"Field\": \"PartNumber\" } },\n { \"Column\": \"PlanName\", \"Properties\": { \"Field\": \"PlanName\" } },\n { \"Column\": \"Product\", \"Properties\": { \"Field\": \"Product\" } },\n { \"Column\": \"ProductOrderId\", \"Properties\": { \"Field\": \"ProductOrderId\" } },\n { \"Column\": \"ProductOrderName\", \"Properties\": { \"Field\": \"ProductOrderName\" } },\n { \"Column\": \"PublisherName\", \"Properties\": { \"Field\": \"PublisherName\" } },\n { \"Column\": \"PublisherType\", \"Properties\": { \"Field\": \"PublisherType\" } },\n { \"Column\": \"Quantity\", \"Properties\": { \"Field\": \"Quantity\" } },\n { \"Column\": \"ReservationId\", \"Properties\": { \"Field\": \"ReservationId\" } },\n { \"Column\": \"ReservationName\", \"Properties\": { \"Field\": \"ReservationName\" } },\n { \"Column\": \"ResourceGroup\", \"Properties\": { \"Field\": \"ResourceGroup\" } },\n { \"Column\": \"ResourceId\", \"Properties\": { \"Field\": \"ResourceId\" } },\n { \"Column\": \"ResourceLocation\", \"Properties\": { \"Field\": \"ResourceLocation\" } },\n { \"Column\": \"ResourceName\", \"Properties\": { \"Field\": \"ResourceName\" } },\n { \"Column\": \"ServiceFamily\", \"Properties\": { \"Field\": \"ServiceFamily\" } },\n { \"Column\": \"ServiceInfo1\", \"Properties\": { \"Field\": \"ServiceInfo1\" } },\n { \"Column\": \"ServiceInfo2\", \"Properties\": { \"Field\": \"ServiceInfo2\" } },\n { \"Column\": \"SubscriptionId\", \"Properties\": { \"Field\": \"SubscriptionId\" } },\n { \"Column\": \"SubscriptionName\", \"Properties\": { \"Field\": \"SubscriptionName\" } },\n { \"Column\": \"Tags\", \"Properties\": { \"Field\": \"Tags\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"UnitOfMeasure\", \"Properties\": { \"Field\": \"UnitOfMeasure\" } },\n { \"Column\": \"UnitPrice\", \"Properties\": { \"Field\": \"UnitPrice\" } }\n]\n```\n\n// AmortizedCosts_raw retention policy (clear historical data)\n.alter-merge table AmortizedCosts_raw policy retention softdelete = 0d recoverability = disabled\n\n// AmortizedCosts_raw retention policy (set the user-defined retention period)\n.alter-merge table AmortizedCosts_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable AmortizedCosts_raw streaming ingestion (required for Fabric)\n.alter table AmortizedCosts_raw policy streamingingestion disable\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_raw table -- Create the table if it doesn't exist\n.create-merge table CommitmentDiscountUsage_raw ( ignore: string )\n\n// CommitmentDiscountUsage_raw table -- Remove all columns to allow changing column types\n.alter table CommitmentDiscountUsage_raw ( ignore: string )\n\n// CommitmentDiscountUsage_raw table -- Redefine all columns\n.alter table CommitmentDiscountUsage_raw (\n InstanceFlexibilityGroup: string,\n InstanceFlexibilityRatio: real,\n InstanceId: string,\n Kind: string,\n ReservationId: string,\n ReservationOrderId: string,\n ReservedHours: real,\n SkuName: string,\n TotalReservedQuantity: real,\n UsageDate: datetime,\n UsedHours: real,\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string // Hubs v1_0+\n)\n\n// CommitmentDiscountUsage_raw ingestion mapping\n.create-or-alter table CommitmentDiscountUsage_raw ingestion parquet mapping \"CommitmentDiscountUsage_raw_mapping\"\n```\n[\n { \"Column\": \"InstanceFlexibilityGroup\", \"Properties\": { \"Field\": \"InstanceFlexibilityGroup\" } },\n { \"Column\": \"InstanceFlexibilityRatio\", \"Properties\": { \"Field\": \"InstanceFlexibilityRatio\" } },\n { \"Column\": \"InstanceId\", \"Properties\": { \"Field\": \"InstanceId\" } },\n { \"Column\": \"Kind\", \"Properties\": { \"Field\": \"Kind\" } },\n { \"Column\": \"ReservationId\", \"Properties\": { \"Field\": \"ReservationId\" } },\n { \"Column\": \"ReservationOrderId\", \"Properties\": { \"Field\": \"ReservationOrderId\" } },\n { \"Column\": \"ReservedHours\", \"Properties\": { \"Field\": \"ReservedHours\" } },\n { \"Column\": \"SkuName\", \"Properties\": { \"Field\": \"SkuName\" } },\n { \"Column\": \"TotalReservedQuantity\", \"Properties\": { \"Field\": \"TotalReservedQuantity\" } },\n { \"Column\": \"UsageDate\", \"Properties\": { \"Field\": \"UsageDate\" } },\n { \"Column\": \"UsedHours\", \"Properties\": { \"Field\": \"UsedHours\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } }\n]\n```\n\n// CommitmentDiscountUsage_raw retention policy (clear historical data)\n.alter-merge table CommitmentDiscountUsage_raw policy retention softdelete = 0d recoverability = disabled\n\n// CommitmentDiscountUsage_raw retention policy (set the user-defined retention period)\n.alter-merge table CommitmentDiscountUsage_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable CommitmentDiscountUsage_raw streaming ingestion (required for Fabric)\n.alter table CommitmentDiscountUsage_raw policy streamingingestion disable\n\n\n//===| Costs |==========================================================================================================\n// Supported versions:\n// - MS: 1.0, 1.0-preview(v1) -- See https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0 -- See https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024 -- See https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 -- See https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n// - Tencent: 1.0 -- See https://www.tencentcloud.com/document/product/555/67495 / https://www.tencentcloud.com/document/product/555/67496\n// - Alibaba: 1.0 -- See https://www.alibabacloud.com/help/en/user-center/user-guide/export-alibaba-cloud-standard-billing-focus\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_raw table -- Create the table if it doesn't exist\n.create-merge table Costs_raw ( ignore: string )\n\n// Costs_raw table -- Remove all columns to allow changing column types\n.alter table Costs_raw ( ignore: string )\n\n// Costs_raw table -- Redefine all columns\n.alter table Costs_raw (\n AvailabilityZone: string, // FOCUS 0.5+\n BilledCost: real, // FOCUS 0.5+\n BillingAccountId: string, // FOCUS 0.5+\n BillingAccountName: string, // FOCUS 0.5+\n BillingAccountType: string, // Azure 1.0-preview(v1)+\n BillingCurrency: string, // FOCUS 0.5+\n BillingPeriodEnd: datetime, // FOCUS 0.5+\n BillingPeriodStart: datetime, // FOCUS 0.5+\n CapacityReservationId: string, // FOCUS 1.1+\n CapacityReservationStatus: string, // FOCUS 1.1+\n ChargeCategory: string, // FOCUS 1.0-preview+\n ChargeClass: string, // FOCUS 1.0+\n ChargeDescription: string, // FOCUS 1.0+\n ChargeFrequency: string, // FOCUS 1.0+\n ChargePeriodEnd: datetime, // FOCUS 0.5+\n ChargePeriodStart: datetime, // FOCUS 0.5+\n ChargeSubcategory: string, // FOCUS 1.0-preview only\n CommitmentDiscountCategory: string, // FOCUS 1.0-preview+\n CommitmentDiscountId: string, // FOCUS 1.0-preview+\n CommitmentDiscountName: string, // FOCUS 1.0-preview+\n CommitmentDiscountQuantity: real, // FOCUS 1.1+\n CommitmentDiscountStatus: string, // FOCUS 1.0+\n CommitmentDiscountType: string, // FOCUS 1.0-preview+\n CommitmentDiscountUnit: string, // FOCUS 1.1+\n ConsumedQuantity: real, // FOCUS 1.0+\n ConsumedUnit: string, // FOCUS 1.0+\n ContractedCost: real, // FOCUS 1.0+\n ContractedUnitPrice: real, // FOCUS 1.0+\n EffectiveCost: real, // FOCUS 1.0-preview+\n InvoiceId: string, // FOCUS 1.2+\n InvoiceIssuerName: string, // FOCUS 0.5+\n ListCost: real, // FOCUS 1.0-preview+\n ListUnitPrice: real, // FOCUS 1.0-preview+\n PricingCategory: string, // FOCUS 1.0-preview+\n PricingCurrency: string, // FOCUS 1.2+\n PricingQuantity: real, // FOCUS 1.0-preview+\n PricingUnit: string, // FOCUS 1.0-preview+\n ProviderName: string, // FOCUS 0.5+\n PublisherName: string, // FOCUS 0.5+\n Region: string, // FOCUS 0.5-1.0-preview (deprecated)\n RegionId: string, // FOCUS 1.0+\n RegionName: string, // FOCUS 1.0+\n ResourceId: string, // FOCUS 0.5+\n ResourceName: string, // FOCUS 0.5+\n ResourceType: string, // FOCUS 1.0-preview+\n ServiceCategory: string, // FOCUS 0.5+\n ServiceName: string, // FOCUS 0.5+\n ServiceSubcategory: string, // FOCUS 1.1+\n SkuId: string, // FOCUS 1.0-preview+\n SkuMeter: string, // FOCUS 1.1+\n SkuPriceDetails: string, // FOCUS 1.1+\n SkuPriceId: string, // FOCUS 1.0-preview+\n SubAccountId: string, // FOCUS 0.5+\n SubAccountName: string, // FOCUS 0.5+\n SubAccountType: string, // Azure 1.0-preview(v1)+\n Tags: string, // FOCUS 1.0-preview+\n UsageAmount: real, // GCP Jan 2024 -- Removed Mar 2024 (UsageQuantity)\n UsageQuantity: real, // FOCUS 1.0-preview only\n UsageUnit: string, // FOCUS 1.0-preview only\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_AmortizationClass: string, // Azure 1.2-preview+\n x_BilledCostInUsd: real, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: real, // Azure 1.0-preview(v1)+\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: real, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingItemCode: string, // Alibaba 1.0+\n x_BillingItemName: string, // Alibaba 1.0+\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_CommodityCode: string, // Alibaba 1.0+\n x_CommodityName: string, // Alibaba 1.0+\n x_ComponentName: string, // Tencent 1.0+\n x_ComponentType: string, // Tencent 1.0+\n x_ContractedCostInUsd: real, // Azure 1.0+\n x_Cost: real, // GCP Jan 2024 -- Removed Jun 2024 (ContractedCost)\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: string, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_CostType: string, // GCP Jan 2024\n x_Credits: string, // GCP Jan 2024\n x_CurrencyConversionRate: real, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: string, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: real, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: real, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024 / Tencent 1.0+\n x_InstanceID: string, // Alibaba 1.0+\n x_InvoiceId: string, // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: real, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_OnDemandCost: real, // Azure 1.0-preview(v1) only\n x_OnDemandCostInUsd: real, // Azure 1.0-preview(v1) only\n x_OnDemandUnitPrice: real, // Azure 1.0-preview(v1) only\n x_Operation: string, // AWS 1.0\n x_OwnerAccountID: string, // Tencent 1.0+\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: real, // Azure 1.0-preview(v1)+\n x_PricingCurrency: string, // Azure 1.0-preview(v1)-1.0r2\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServiceModel: string, // Azure 1.2-preview+\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: string, // Azure 1.0-preview(v1)-1.2-preview\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterName: string, // Azure 1.0-preview(v1)-1.0r2\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuPlanName: string, // Azure 1.2-preview+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string, // Hubs v1_0+\n x_SubproductName: string, // Tencent 1.0+ // cSpell:ignore Subproduct\n x_UsageType: string // AWS 1.0\n)\n\n// Costs_raw ingestion mapping\n.create-or-alter table Costs_raw ingestion parquet mapping \"Costs_raw_mapping\"\n```\n[\n { \"Column\": \"AvailabilityZone\", \"Properties\": { \"Field\": \"AvailabilityZone\" } },\n { \"Column\": \"BilledCost\", \"Properties\": { \"Field\": \"BilledCost\" } },\n { \"Column\": \"BillingAccountId\", \"Properties\": { \"Field\": \"BillingAccountId\" } },\n { \"Column\": \"BillingAccountName\", \"Properties\": { \"Field\": \"BillingAccountName\" } },\n { \"Column\": \"BillingAccountType\", \"Properties\": { \"Field\": \"BillingAccountType\" } },\n { \"Column\": \"BillingCurrency\", \"Properties\": { \"Field\": \"BillingCurrency\" } },\n { \"Column\": \"BillingPeriodEnd\", \"Properties\": { \"Field\": \"BillingPeriodEnd\" } },\n { \"Column\": \"BillingPeriodStart\", \"Properties\": { \"Field\": \"BillingPeriodStart\" } },\n { \"Column\": \"CapacityReservationId\", \"Properties\": { \"Field\": \"CapacityReservationId\" } },\n { \"Column\": \"CapacityReservationStatus\", \"Properties\": { \"Field\": \"CapacityReservationStatus\" } },\n { \"Column\": \"ChargeCategory\", \"Properties\": { \"Field\": \"ChargeCategory\" } },\n { \"Column\": \"ChargeClass\", \"Properties\": { \"Field\": \"ChargeClass\" } },\n { \"Column\": \"ChargeDescription\", \"Properties\": { \"Field\": \"ChargeDescription\" } },\n { \"Column\": \"ChargeFrequency\", \"Properties\": { \"Field\": \"ChargeFrequency\" } },\n { \"Column\": \"ChargePeriodEnd\", \"Properties\": { \"Field\": \"ChargePeriodEnd\" } },\n { \"Column\": \"ChargePeriodStart\", \"Properties\": { \"Field\": \"ChargePeriodStart\" } },\n { \"Column\": \"ChargeSubcategory\", \"Properties\": { \"Field\": \"ChargeSubcategory\" } },\n { \"Column\": \"CommitmentDiscountCategory\", \"Properties\": { \"Field\": \"CommitmentDiscountCategory\" } },\n { \"Column\": \"CommitmentDiscountId\", \"Properties\": { \"Field\": \"CommitmentDiscountId\" } },\n { \"Column\": \"CommitmentDiscountName\", \"Properties\": { \"Field\": \"CommitmentDiscountName\" } },\n { \"Column\": \"CommitmentDiscountQuantity\", \"Properties\": { \"Field\": \"CommitmentDiscountQuantity\" } },\n { \"Column\": \"CommitmentDiscountStatus\", \"Properties\": { \"Field\": \"CommitmentDiscountStatus\" } },\n { \"Column\": \"CommitmentDiscountType\", \"Properties\": { \"Field\": \"CommitmentDiscountType\" } },\n { \"Column\": \"CommitmentDiscountUnit\", \"Properties\": { \"Field\": \"CommitmentDiscountUnit\" } },\n { \"Column\": \"ConsumedQuantity\", \"Properties\": { \"Field\": \"ConsumedQuantity\" } },\n { \"Column\": \"ConsumedUnit\", \"Properties\": { \"Field\": \"ConsumedUnit\" } },\n { \"Column\": \"ContractedCost\", \"Properties\": { \"Field\": \"ContractedCost\" } },\n { \"Column\": \"ContractedUnitPrice\", \"Properties\": { \"Field\": \"ContractedUnitPrice\" } },\n { \"Column\": \"EffectiveCost\", \"Properties\": { \"Field\": \"EffectiveCost\" } },\n { \"Column\": \"InvoiceId\", \"Properties\": { \"Field\": \"InvoiceId\" } },\n { \"Column\": \"InvoiceIssuerName\", \"Properties\": { \"Field\": \"InvoiceIssuerName\" } },\n { \"Column\": \"ListCost\", \"Properties\": { \"Field\": \"ListCost\" } },\n { \"Column\": \"ListUnitPrice\", \"Properties\": { \"Field\": \"ListUnitPrice\" } },\n { \"Column\": \"PricingCategory\", \"Properties\": { \"Field\": \"PricingCategory\" } },\n { \"Column\": \"PricingCurrency\", \"Properties\": { \"Field\": \"PricingCurrency\" } },\n { \"Column\": \"PricingQuantity\", \"Properties\": { \"Field\": \"PricingQuantity\" } },\n { \"Column\": \"PricingUnit\", \"Properties\": { \"Field\": \"PricingUnit\" } },\n { \"Column\": \"ProviderName\", \"Properties\": { \"Field\": \"ProviderName\" } },\n { \"Column\": \"PublisherName\", \"Properties\": { \"Field\": \"PublisherName\" } },\n { \"Column\": \"Region\", \"Properties\": { \"Field\": \"Region\" } },\n { \"Column\": \"RegionId\", \"Properties\": { \"Field\": \"RegionId\" } },\n { \"Column\": \"RegionName\", \"Properties\": { \"Field\": \"RegionName\" } },\n { \"Column\": \"ResourceId\", \"Properties\": { \"Field\": \"ResourceId\" } },\n { \"Column\": \"ResourceName\", \"Properties\": { \"Field\": \"ResourceName\" } },\n { \"Column\": \"ResourceType\", \"Properties\": { \"Field\": \"ResourceType\" } },\n { \"Column\": \"ServiceCategory\", \"Properties\": { \"Field\": \"ServiceCategory\" } },\n { \"Column\": \"ServiceName\", \"Properties\": { \"Field\": \"ServiceName\" } },\n { \"Column\": \"ServiceSubcategory\", \"Properties\": { \"Field\": \"ServiceSubcategory\" } },\n { \"Column\": \"SkuId\", \"Properties\": { \"Field\": \"SkuId\" } },\n { \"Column\": \"SkuMeter\", \"Properties\": { \"Field\": \"SkuMeter\" } },\n { \"Column\": \"SkuPriceDetails\", \"Properties\": { \"Field\": \"SkuPriceDetails\" } },\n { \"Column\": \"SkuPriceId\", \"Properties\": { \"Field\": \"SkuPriceId\" } },\n { \"Column\": \"SubAccountId\", \"Properties\": { \"Field\": \"SubAccountId\" } },\n { \"Column\": \"SubAccountName\", \"Properties\": { \"Field\": \"SubAccountName\" } },\n { \"Column\": \"SubAccountType\", \"Properties\": { \"Field\": \"SubAccountType\" } },\n { \"Column\": \"Tags\", \"Properties\": { \"Field\": \"Tags\" } },\n { \"Column\": \"UsageAmount\", \"Properties\": { \"Field\": \"UsageAmount\" } },\n { \"Column\": \"UsageQuantity\", \"Properties\": { \"Field\": \"UsageQuantity\" } },\n { \"Column\": \"UsageUnit\", \"Properties\": { \"Field\": \"UsageUnit\" } },\n { \"Column\": \"x_AccountId\", \"Properties\": { \"Field\": \"x_AccountId\" } },\n { \"Column\": \"x_AccountName\", \"Properties\": { \"Field\": \"x_AccountName\" } },\n { \"Column\": \"x_AccountOwnerId\", \"Properties\": { \"Field\": \"x_AccountOwnerId\" } },\n { \"Column\": \"x_AmortizationClass\", \"Properties\": { \"Field\": \"x_AmortizationClass\" } },\n { \"Column\": \"x_BilledCostInUsd\", \"Properties\": { \"Field\": \"x_BilledCostInUsd\" } },\n { \"Column\": \"x_BilledUnitPrice\", \"Properties\": { \"Field\": \"x_BilledUnitPrice\" } },\n { \"Column\": \"x_BillingAccountId\", \"Properties\": { \"Field\": \"x_BillingAccountId\" } },\n { \"Column\": \"x_BillingAccountName\", \"Properties\": { \"Field\": \"x_BillingAccountName\" } },\n { \"Column\": \"x_BillingExchangeRate\", \"Properties\": { \"Field\": \"x_BillingExchangeRate\" } },\n { \"Column\": \"x_BillingExchangeRateDate\", \"Properties\": { \"Field\": \"x_BillingExchangeRateDate\" } },\n { \"Column\": \"x_BillingItemCode\", \"Properties\": { \"Field\": \"x_BillingItemCode\" } },\n { \"Column\": \"x_BillingItemName\", \"Properties\": { \"Field\": \"x_BillingItemName\" } },\n { \"Column\": \"x_BillingProfileId\", \"Properties\": { \"Field\": \"x_BillingProfileId\" } },\n { \"Column\": \"x_BillingProfileName\", \"Properties\": { \"Field\": \"x_BillingProfileName\" } },\n { \"Column\": \"x_ChargeId\", \"Properties\": { \"Field\": \"x_ChargeId\" } },\n { \"Column\": \"x_ContractedCostInUsd\", \"Properties\": { \"Field\": \"x_ContractedCostInUsd\" } },\n { \"Column\": \"x_CommodityCode\", \"Properties\": { \"Field\": \"x_CommodityCode\" } },\n { \"Column\": \"x_CommodityName\", \"Properties\": { \"Field\": \"x_CommodityName\" } },\n { \"Column\": \"x_ComponentName\", \"Properties\": { \"Field\": \"x_ComponentName\" } },\n { \"Column\": \"x_ComponentType\", \"Properties\": { \"Field\": \"x_ComponentType\" } },\n { \"Column\": \"x_Cost\", \"Properties\": { \"Field\": \"x_Cost\" } },\n { \"Column\": \"x_CostAllocationRuleName\", \"Properties\": { \"Field\": \"x_CostAllocationRuleName\" } },\n { \"Column\": \"x_CostCategories\", \"Properties\": { \"Field\": \"x_CostCategories\" } },\n { \"Column\": \"x_CostCenter\", \"Properties\": { \"Field\": \"x_CostCenter\" } },\n { \"Column\": \"x_Credits\", \"Properties\": { \"Field\": \"x_Credits\" } },\n { \"Column\": \"x_CostType\", \"Properties\": { \"Field\": \"x_CostType\" } },\n { \"Column\": \"x_CurrencyConversionRate\", \"Properties\": { \"Field\": \"x_CurrencyConversionRate\" } },\n { \"Column\": \"x_CustomerId\", \"Properties\": { \"Field\": \"x_CustomerId\" } },\n { \"Column\": \"x_CustomerName\", \"Properties\": { \"Field\": \"x_CustomerName\" } },\n { \"Column\": \"x_Discount\", \"Properties\": { \"Field\": \"x_Discount\" } },\n { \"Column\": \"x_EffectiveCostInUsd\", \"Properties\": { \"Field\": \"x_EffectiveCostInUsd\" } },\n { \"Column\": \"x_EffectiveUnitPrice\", \"Properties\": { \"Field\": \"x_EffectiveUnitPrice\" } },\n { \"Column\": \"x_ExportTime\", \"Properties\": { \"Field\": \"x_ExportTime\" } },\n { \"Column\": \"x_InstanceID\", \"Properties\": { \"Field\": \"x_InstanceID\" } },\n { \"Column\": \"x_InvoiceId\", \"Properties\": { \"Field\": \"x_InvoiceId\" } },\n { \"Column\": \"x_InvoiceIssuerId\", \"Properties\": { \"Field\": \"x_InvoiceIssuerId\" } },\n { \"Column\": \"x_InvoiceSectionId\", \"Properties\": { \"Field\": \"x_InvoiceSectionId\" } },\n { \"Column\": \"x_InvoiceSectionName\", \"Properties\": { \"Field\": \"x_InvoiceSectionName\" } },\n { \"Column\": \"x_ListCostInUsd\", \"Properties\": { \"Field\": \"x_ListCostInUsd\" } },\n { \"Column\": \"x_Location\", \"Properties\": { \"Field\": \"x_Location\" } },\n { \"Column\": \"x_OnDemandCost\", \"Properties\": { \"Field\": \"x_OnDemandCost\" } },\n { \"Column\": \"x_OnDemandCostInUsd\", \"Properties\": { \"Field\": \"x_OnDemandCostInUsd\" } },\n { \"Column\": \"x_OnDemandUnitPrice\", \"Properties\": { \"Field\": \"x_OnDemandUnitPrice\" } },\n { \"Column\": \"x_Operation\", \"Properties\": { \"Field\": \"x_Operation\" } },\n { \"Column\": \"x_OwnerAccountID\", \"Properties\": { \"Field\": \"x_OwnerAccountID\" } },\n { \"Column\": \"x_PartnerCreditApplied\", \"Properties\": { \"Field\": \"x_PartnerCreditApplied\" } },\n { \"Column\": \"x_PartnerCreditRate\", \"Properties\": { \"Field\": \"x_PartnerCreditRate\" } },\n { \"Column\": \"x_PricingBlockSize\", \"Properties\": { \"Field\": \"x_PricingBlockSize\" } },\n { \"Column\": \"x_PricingCurrency\", \"Properties\": { \"Field\": \"x_PricingCurrency\" } },\n { \"Column\": \"x_PricingSubcategory\", \"Properties\": { \"Field\": \"x_PricingSubcategory\" } },\n { \"Column\": \"x_PricingUnitDescription\", \"Properties\": { \"Field\": \"x_PricingUnitDescription\" } },\n { \"Column\": \"x_Project\", \"Properties\": { \"Field\": \"x_Project\" } },\n { \"Column\": \"x_PublisherCategory\", \"Properties\": { \"Field\": \"x_PublisherCategory\" } },\n { \"Column\": \"x_PublisherId\", \"Properties\": { \"Field\": \"x_PublisherId\" } },\n { \"Column\": \"x_ResellerId\", \"Properties\": { \"Field\": \"x_ResellerId\" } },\n { \"Column\": \"x_ResellerName\", \"Properties\": { \"Field\": \"x_ResellerName\" } },\n { \"Column\": \"x_ResourceGroupName\", \"Properties\": { \"Field\": \"x_ResourceGroupName\" } },\n { \"Column\": \"x_ResourceType\", \"Properties\": { \"Field\": \"x_ResourceType\" } },\n { \"Column\": \"x_ServiceCode\", \"Properties\": { \"Field\": \"x_ServiceCode\" } },\n { \"Column\": \"x_ServiceId\", \"Properties\": { \"Field\": \"x_ServiceId\" } },\n { \"Column\": \"x_ServiceModel\", \"Properties\": { \"Field\": \"x_ServiceModel\" } },\n { \"Column\": \"x_ServicePeriodEnd\", \"Properties\": { \"Field\": \"x_ServicePeriodEnd\" } },\n { \"Column\": \"x_ServicePeriodStart\", \"Properties\": { \"Field\": \"x_ServicePeriodStart\" } },\n { \"Column\": \"x_SkuDescription\", \"Properties\": { \"Field\": \"x_SkuDescription\" } },\n { \"Column\": \"x_SkuDetails\", \"Properties\": { \"Field\": \"x_SkuDetails\" } },\n { \"Column\": \"x_SkuIsCreditEligible\", \"Properties\": { \"Field\": \"x_SkuIsCreditEligible\" } },\n { \"Column\": \"x_SkuMeterCategory\", \"Properties\": { \"Field\": \"x_SkuMeterCategory\" } },\n { \"Column\": \"x_SkuMeterId\", \"Properties\": { \"Field\": \"x_SkuMeterId\" } },\n { \"Column\": \"x_SkuMeterName\", \"Properties\": { \"Field\": \"x_SkuMeterName\" } },\n { \"Column\": \"x_SkuMeterSubcategory\", \"Properties\": { \"Field\": \"x_SkuMeterSubcategory\" } },\n { \"Column\": \"x_SkuOfferId\", \"Properties\": { \"Field\": \"x_SkuOfferId\" } },\n { \"Column\": \"x_SkuOrderId\", \"Properties\": { \"Field\": \"x_SkuOrderId\" } },\n { \"Column\": \"x_SkuOrderName\", \"Properties\": { \"Field\": \"x_SkuOrderName\" } },\n { \"Column\": \"x_SkuPartNumber\", \"Properties\": { \"Field\": \"x_SkuPartNumber\" } },\n { \"Column\": \"x_SkuPlanName\", \"Properties\": { \"Field\": \"x_SkuPlanName\" } },\n { \"Column\": \"x_SkuRegion\", \"Properties\": { \"Field\": \"x_SkuRegion\" } },\n { \"Column\": \"x_SkuServiceFamily\", \"Properties\": { \"Field\": \"x_SkuServiceFamily\" } },\n { \"Column\": \"x_SkuTerm\", \"Properties\": { \"Field\": \"x_SkuTerm\" } },\n { \"Column\": \"x_SkuTier\", \"Properties\": { \"Field\": \"x_SkuTier\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } },\n { \"Column\": \"x_SubproductName\", \"Properties\": { \"Field\": \"x_SubproductName\" } },\n { \"Column\": \"x_UsageType\", \"Properties\": { \"Field\": \"x_UsageType\" } }\n]\n```\n\n// Costs_raw retention policy (clear historical data)\n.alter-merge table Costs_raw policy retention softdelete = 0d recoverability = disabled\n\n// Costs_raw retention policy (set the user-defined retention period)\n.alter-merge table Costs_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable Costs_raw streaming ingestion (required for Fabric)\n.alter table Costs_raw policy streamingingestion disable\n\n\n//===| Prices |=========================================================================================================\n// NOTE: Must be before cost details.\n//\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_raw table -- Create the table if it doesn't exist\n.create-merge table Prices_raw ( ignore: string )\n\n// Prices_raw table -- Remove all columns to allow changing column types\n.alter table Prices_raw ( ignore: string )\n\n// Prices_raw table -- Redefine all columns\n.alter table Prices_raw (\n BasePrice: real, // Azure EA + MCA\n BillingAccountId: string, // Azure MCA\n BillingAccountName: string, // Azure MCA\n BillingCurrency: string, // Azure MCA\n BillingProfileId: string, // Azure MCA\n BillingProfileName: string, // Azure MCA\n Currency: string, // Azure MCA\n CurrencyCode: string, // Azure EA\n EffectiveEndDate: datetime, // Azure MCA\n EffectiveStartDate: datetime, // Azure EA + MCA\n EnrollmentNumber: string, // Azure EA\n IncludedQuantity: real, // Azure EA\n MarketPrice: real, // Azure EA + MCA\n MeterCategory: string, // Azure EA + MCA\n MeterId: string, // Azure MCA\n MeterID: string, // Azure EA\n MeterName: string, // Azure EA + MCA\n MeterRegion: string, // Azure EA + MCA\n MeterSubCategory: string, // Azure EA + MCA\n MeterType: string, // Azure EA + MCA\n OfferID: string, // Azure EA\n PartNumber: string, // Azure EA\n PriceType: string, // Azure EA + MCA\n Product: string, // Azure EA + MCA\n ProductId: string, // Azure MCA\n ProductID: string, // Azure EA\n ServiceFamily: string, // Azure EA + MCA\n SkuId: string, // Azure MCA\n SkuID: string, // Azure EA\n Term: string, // Azure EA + MCA\n TierMinimumUnits: real, // Azure MCA\n UnitOfMeasure: string, // Azure EA + MCA\n UnitPrice: real, // Azure EA + MCA\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string // Hubs v1_0+\n)\n\n// Prices_raw ingestion mapping\n.create-or-alter table Prices_raw ingestion parquet mapping \"Prices_raw_mapping\"\n```\n[\n { \"Column\": \"BasePrice\", \"Properties\": { \"Field\": \"BasePrice\" } },\n { \"Column\": \"BillingAccountId\", \"Properties\": { \"Field\": \"BillingAccountId\" } },\n { \"Column\": \"BillingAccountName\", \"Properties\": { \"Field\": \"BillingAccountName\" } },\n { \"Column\": \"BillingCurrency\", \"Properties\": { \"Field\": \"BillingCurrency\" } },\n { \"Column\": \"BillingProfileId\", \"Properties\": { \"Field\": \"BillingProfileId\" } },\n { \"Column\": \"BillingProfileName\", \"Properties\": { \"Field\": \"BillingProfileName\" } },\n { \"Column\": \"Currency\", \"Properties\": { \"Field\": \"Currency\" } },\n { \"Column\": \"CurrencyCode\", \"Properties\": { \"Field\": \"CurrencyCode\" } },\n { \"Column\": \"EffectiveEndDate\", \"Properties\": { \"Field\": \"EffectiveEndDate\" } },\n { \"Column\": \"EffectiveStartDate\", \"Properties\": { \"Field\": \"EffectiveStartDate\" } },\n { \"Column\": \"EnrollmentNumber\", \"Properties\": { \"Field\": \"EnrollmentNumber\" } },\n { \"Column\": \"IncludedQuantity\", \"Properties\": { \"Field\": \"IncludedQuantity\" } },\n { \"Column\": \"MarketPrice\", \"Properties\": { \"Field\": \"MarketPrice\" } },\n { \"Column\": \"MeterCategory\", \"Properties\": { \"Field\": \"MeterCategory\" } },\n { \"Column\": \"MeterId\", \"Properties\": { \"Field\": \"MeterId\" } },\n { \"Column\": \"MeterID\", \"Properties\": { \"Field\": \"MeterID\" } },\n { \"Column\": \"MeterName\", \"Properties\": { \"Field\": \"MeterName\" } },\n { \"Column\": \"MeterRegion\", \"Properties\": { \"Field\": \"MeterRegion\" } },\n { \"Column\": \"MeterSubCategory\", \"Properties\": { \"Field\": \"MeterSubCategory\" } },\n { \"Column\": \"MeterType\", \"Properties\": { \"Field\": \"MeterType\" } },\n { \"Column\": \"OfferID\", \"Properties\": { \"Field\": \"OfferID\" } },\n { \"Column\": \"PartNumber\", \"Properties\": { \"Field\": \"PartNumber\" } },\n { \"Column\": \"PriceType\", \"Properties\": { \"Field\": \"PriceType\" } },\n { \"Column\": \"Product\", \"Properties\": { \"Field\": \"Product\" } },\n { \"Column\": \"ProductId\", \"Properties\": { \"Field\": \"ProductId\" } },\n { \"Column\": \"ProductID\", \"Properties\": { \"Field\": \"ProductID\" } },\n { \"Column\": \"ServiceFamily\", \"Properties\": { \"Field\": \"ServiceFamily\" } },\n { \"Column\": \"SkuId\", \"Properties\": { \"Field\": \"SkuId\" } },\n { \"Column\": \"SkuID\", \"Properties\": { \"Field\": \"SkuID\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"TierMinimumUnits\", \"Properties\": { \"Field\": \"TierMinimumUnits\" } },\n { \"Column\": \"UnitOfMeasure\", \"Properties\": { \"Field\": \"UnitOfMeasure\" } },\n { \"Column\": \"UnitPrice\", \"Properties\": { \"Field\": \"UnitPrice\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } }\n]\n```\n\n// Prices_raw retention policy (clear historical data)\n.alter-merge table Prices_raw policy retention softdelete = 0d recoverability = disabled\n\n// Prices_raw retention policy (set the user-defined retention period)\n.alter-merge table Prices_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable Prices_raw streaming ingestion (required for Fabric)\n.alter table Prices_raw policy streamingingestion disable\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_raw table -- Create the table if it doesn't exist\n.create-merge table Recommendations_raw ( ignore: string )\n\n// Recommendations_raw table -- Remove all columns to allow changing column types\n.alter table Recommendations_raw ( ignore: string )\n\n// Recommendations_raw table -- Redefine all columns\n.alter table Recommendations_raw (\n CostWithNoReservedInstances: real, // MS CM EA resv reco 2024-05-01\n CostWithNoReservedInstancesJson: string, // MS CM MCA resv reco 2024-05-01 -- Renamed to remove spaces and flag as JSON\n FirstUsageDate: datetime, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n InstanceFlexibilityGroup: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n InstanceFlexibilityRatio: real, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n Location: string, // MS CM EA+MCA resv reco 2024-05-01\n LookBackPeriod: string, // MS CM EA+MCA resv reco 2024-05-01\n MeterId: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n NetSavings: real, // MS CM EA resv reco 2024-05-01\n NetSavingsJson: string, // MS CM MCA resv reco 2024-05-01 -- Renamed to remove spaces and flag as JSON\n NormalizedSize: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n ProviderName: string, // Hubs v1_2\n RecommendedQuantity: real, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n RecommendedQuantityNormalized: real, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n ResourceId: string, // Hubs v1_2\n ResourceName: string, // Hubs v1_2\n ResourceType: string, // Hubs v1_2, MS CM EA+MCA resv reco 2024-05-01\n Scope: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n SKU: string, // MS CM EA resv reco 2024-05-01\n SkuName: string, // MS CM MCA resv reco 2024-05-01 -- Renamed to remove spaces\n SkuProperties: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n SubAccountId: string, // Hubs v1_2\n SubAccountName: string, // Hubs v1_2\n SubscriptionId: string, // MS CM EA+MCA resv reco 2024-05-01\n Term: string, // MS CM EA+MCA resv reco 2024-05-01\n TotalCostWithReservedInstances: real, // MS CM EA resv reco 2024-05-01\n TotalCostWithReservedInstancesJson: string, // MS CM MCA resv reco 2024-05-01 -- Renamed to remove spaces and flag as JSON\n x_EffectiveCostAfter: real, // Hubs v1_2\n x_EffectiveCostBefore: real, // Hubs v1_2\n x_EffectiveCostSavings: real, // Hubs v1_2\n x_RecommendationCategory: string, // Hubs v1_2\n x_RecommendationDate: datetime, // Hubs v1_2\n x_RecommendationDescription: string, // Hubs v1_2\n x_RecommendationDetails: dynamic, // Hubs v1_2\n x_RecommendationId: string, // Hubs v1_2\n x_ResourceGroupName: string, // Hubs v1_2\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string // Hubs v1_0+\n)\n\n// Recommendations_raw ingestion mapping\n.create-or-alter table Recommendations_raw ingestion parquet mapping \"Recommendations_raw_mapping\"\n```\n[\n { \"Column\": \"CostWithNoReservedInstances\", \"Properties\": { \"Field\": \"CostWithNoReservedInstances\" } },\n { \"Column\": \"CostWithNoReservedInstancesJson\", \"Properties\": { \"Field\": \"CostWithNoReservedInstancesJson\" } },\n { \"Column\": \"FirstUsageDate\", \"Properties\": { \"Field\": \"FirstUsageDate\" } },\n { \"Column\": \"InstanceFlexibilityGroup\", \"Properties\": { \"Field\": \"InstanceFlexibilityGroup\" } },\n { \"Column\": \"InstanceFlexibilityRatio\", \"Properties\": { \"Field\": \"InstanceFlexibilityRatio\" } },\n { \"Column\": \"Location\", \"Properties\": { \"Field\": \"Location\" } },\n { \"Column\": \"LookBackPeriod\", \"Properties\": { \"Field\": \"LookBackPeriod\" } },\n { \"Column\": \"MeterId\", \"Properties\": { \"Field\": \"MeterId\" } },\n { \"Column\": \"NetSavings\", \"Properties\": { \"Field\": \"NetSavings\" } },\n { \"Column\": \"NetSavingsJson\", \"Properties\": { \"Field\": \"NetSavingsJson\" } },\n { \"Column\": \"NormalizedSize\", \"Properties\": { \"Field\": \"NormalizedSize\" } },\n { \"Column\": \"ProviderName\", \"Properties\": { \"Field\": \"ProviderName\" } },\n { \"Column\": \"RecommendedQuantity\", \"Properties\": { \"Field\": \"RecommendedQuantity\" } },\n { \"Column\": \"RecommendedQuantityNormalized\", \"Properties\": { \"Field\": \"RecommendedQuantityNormalized\" } },\n { \"Column\": \"ResourceId\", \"Properties\": { \"Field\": \"ResourceId\" } },\n { \"Column\": \"ResourceName\", \"Properties\": { \"Field\": \"ResourceName\" } },\n { \"Column\": \"ResourceType\", \"Properties\": { \"Field\": \"ResourceType\" } },\n { \"Column\": \"Scope\", \"Properties\": { \"Field\": \"Scope\" } },\n { \"Column\": \"SKU\", \"Properties\": { \"Field\": \"SKU\" } },\n { \"Column\": \"SkuName\", \"Properties\": { \"Field\": \"SkuName\" } },\n { \"Column\": \"SkuProperties\", \"Properties\": { \"Field\": \"SkuProperties\" } },\n { \"Column\": \"SubAccountId\", \"Properties\": { \"Field\": \"SubAccountId\" } },\n { \"Column\": \"SubAccountName\", \"Properties\": { \"Field\": \"SubAccountName\" } },\n { \"Column\": \"SubscriptionId\", \"Properties\": { \"Field\": \"SubscriptionId\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"TotalCostWithReservedInstances\", \"Properties\": { \"Field\": \"TotalCostWithReservedInstances\" } },\n { \"Column\": \"TotalCostWithReservedInstancesJson\", \"Properties\": { \"Field\": \"TotalCostWithReservedInstancesJson\" } },\n { \"Column\": \"x_EffectiveCostAfter\", \"Properties\": { \"Field\": \"x_EffectiveCostAfter\" } },\n { \"Column\": \"x_EffectiveCostBefore\", \"Properties\": { \"Field\": \"x_EffectiveCostBefore\" } },\n { \"Column\": \"x_EffectiveCostSavings\", \"Properties\": { \"Field\": \"x_EffectiveCostSavings\" } },\n { \"Column\": \"x_RecommendationCategory\", \"Properties\": { \"Field\": \"x_RecommendationCategory\" } },\n { \"Column\": \"x_RecommendationDate\", \"Properties\": { \"Field\": \"x_RecommendationDate\" } },\n { \"Column\": \"x_RecommendationDescription\", \"Properties\": { \"Field\": \"x_RecommendationDescription\" } },\n { \"Column\": \"x_RecommendationDetails\", \"Properties\": { \"Field\": \"x_RecommendationDetails\" } },\n { \"Column\": \"x_RecommendationId\", \"Properties\": { \"Field\": \"x_RecommendationId\" } },\n { \"Column\": \"x_ResourceGroupName\", \"Properties\": { \"Field\": \"x_ResourceGroupName\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } }\n]\n```\n\n// Recommendations_raw retention policy (clear historical data)\n.alter-merge table Recommendations_raw policy retention softdelete = 0d recoverability = disabled\n\n// Recommendations_raw retention policy (set the user-defined retention period)\n.alter-merge table Recommendations_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable Recommendations_raw streaming ingestion (required for Fabric)\n.alter table Recommendations_raw policy streamingingestion disable\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_raw table -- Create the table if it doesn't exist\n.create-merge table Transactions_raw ( ignore: string )\n\n// Transactions_raw table -- Remove all columns to allow changing column types\n.alter table Transactions_raw ( ignore: string )\n\n// Transactions_raw table -- Redefine all columns\n.alter table Transactions_raw (\n AccountName: string, // MS CM EA resv trans 2023-05-01\n AccountOwnerEmail: string, // MS CM EA resv trans 2023-05-01\n Amount: real, // MS CM EA+MCA resv trans 2023-05-01\n ArmSkuName: string, // MS CM EA+MCA resv trans 2023-05-01\n BillingFrequency: string, // MS CM EA+MCA resv trans 2023-05-01\n BillingMonth: string, // MS CM EA resv trans 2023-05-01\n BillingProfileId: string, // MS CM MCA resv trans 2023-05-01\n BillingProfileName: string, // MS CM MCA resv trans 2023-05-01\n CostCenter: string, // MS CM EA resv trans 2023-05-01\n Currency: string, // MS CM EA+MCA resv trans 2023-05-01\n CurrentEnrollmentId: string, // MS CM EA resv trans 2023-05-01\n DepartmentName: string, // MS CM EA resv trans 2023-05-01\n Description: string, // MS CM EA+MCA resv trans 2023-05-01\n EventDate: datetime, // MS CM EA+MCA resv trans 2023-05-01\n EventType: string, // MS CM EA+MCA resv trans 2023-05-01\n Invoice: string, // MS CM EA+MCA resv trans 2023-05-01\n InvoiceId: string, // MS CM EA+MCA resv trans 2023-05-01\n InvoiceSectionId: string, // MS CM MCA resv trans 2023-05-01\n InvoiceSectionName: string, // MS CM MCA resv trans 2023-05-01\n MonetaryCommitment: real, // MS CM EA resv trans 2023-05-01\n Overage: real, // MS CM EA resv trans 2023-05-01\n PurchasingEnrollment: string, // MS CM EA resv trans 2023-05-01\n PurchasingSubscriptionGuid: string, // MS CM EA+MCA resv trans 2023-05-01\n PurchasingSubscriptionName: string, // MS CM EA+MCA resv trans 2023-05-01\n Quantity: real, // MS CM EA+MCA resv trans 2023-05-01\n Region: string, // MS CM EA+MCA resv trans 2023-05-01\n ReservationOrderId: string, // MS CM EA+MCA resv trans 2023-05-01\n ReservationOrderName: string, // MS CM EA+MCA resv trans 2023-05-01\n Term: string, // MS CM EA+MCA resv trans 2023-05-01\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string // Hubs v1_0+\n)\n\n// Transactions_raw ingestion mapping\n.create-or-alter table Transactions_raw ingestion parquet mapping \"Transactions_raw_mapping\"\n```\n[\n { \"Column\": \"AccountName\", \"Properties\": { \"Field\": \"AccountName\" } },\n { \"Column\": \"AccountOwnerEmail\", \"Properties\": { \"Field\": \"AccountOwnerEmail\" } },\n { \"Column\": \"Amount\", \"Properties\": { \"Field\": \"Amount\" } },\n { \"Column\": \"ArmSkuName\", \"Properties\": { \"Field\": \"ArmSkuName\" } },\n { \"Column\": \"BillingFrequency\", \"Properties\": { \"Field\": \"BillingFrequency\" } },\n { \"Column\": \"BillingMonth\", \"Properties\": { \"Field\": \"BillingMonth\" } },\n { \"Column\": \"BillingProfileId\", \"Properties\": { \"Field\": \"BillingProfileId\" } },\n { \"Column\": \"BillingProfileName\", \"Properties\": { \"Field\": \"BillingProfileName\" } },\n { \"Column\": \"CostCenter\", \"Properties\": { \"Field\": \"CostCenter\" } },\n { \"Column\": \"Currency\", \"Properties\": { \"Field\": \"Currency\" } },\n { \"Column\": \"CurrentEnrollmentId\", \"Properties\": { \"Field\": \"CurrentEnrollmentId\" } },\n { \"Column\": \"DepartmentName\", \"Properties\": { \"Field\": \"DepartmentName\" } },\n { \"Column\": \"Description\", \"Properties\": { \"Field\": \"Description\" } },\n { \"Column\": \"EventDate\", \"Properties\": { \"Field\": \"EventDate\" } },\n { \"Column\": \"EventType\", \"Properties\": { \"Field\": \"EventType\" } },\n { \"Column\": \"Invoice\", \"Properties\": { \"Field\": \"Invoice\" } },\n { \"Column\": \"InvoiceId\", \"Properties\": { \"Field\": \"InvoiceId\" } },\n { \"Column\": \"InvoiceSectionId\", \"Properties\": { \"Field\": \"InvoiceSectionId\" } },\n { \"Column\": \"InvoiceSectionName\", \"Properties\": { \"Field\": \"InvoiceSectionName\" } },\n { \"Column\": \"MonetaryCommitment\", \"Properties\": { \"Field\": \"MonetaryCommitment\" } },\n { \"Column\": \"Overage\", \"Properties\": { \"Field\": \"Overage\" } },\n { \"Column\": \"PurchasingEnrollment\", \"Properties\": { \"Field\": \"PurchasingEnrollment\" } },\n { \"Column\": \"PurchasingSubscriptionGuid\", \"Properties\": { \"Field\": \"PurchasingSubscriptionGuid\" } },\n { \"Column\": \"PurchasingSubscriptionName\", \"Properties\": { \"Field\": \"PurchasingSubscriptionName\" } },\n { \"Column\": \"Quantity\", \"Properties\": { \"Field\": \"Quantity\" } },\n { \"Column\": \"Region\", \"Properties\": { \"Field\": \"Region\" } },\n { \"Column\": \"ReservationOrderId\", \"Properties\": { \"Field\": \"ReservationOrderId\" } },\n { \"Column\": \"ReservationOrderName\", \"Properties\": { \"Field\": \"ReservationOrderName\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } }\n]\n```\n\n// Transactions_raw retention policy (clear historical data)\n.alter-merge table Transactions_raw policy retention softdelete = 0d recoverability = disabled\n\n// Transactions_raw retention policy (set the user-defined retention period)\n.alter-merge table Transactions_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable Transactions_raw streaming ingestion (required for Fabric)\n.alter table Transactions_raw policy streamingingestion disable\n\n", - "$fxv#9": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// Used for data ingestion, normalization, and cleansing.\n// See known issues @ https://github.com/microsoft/finops-toolkit/issues/1111\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Prices |=========================================================================================================\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All prices transformed to FOCUS 1.0. Use Prices_transform_v1_2() instead.', folder='Prices')\nPrices_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n let prices = materialize(\n Prices_raw\n //\n // Change real to decimal\n | extend\n BasePrice = todecimal(BasePrice),\n IncludedQuantity = todecimal(IncludedQuantity),\n MarketPrice = todecimal(MarketPrice),\n TierMinimumUnits = todecimal(TierMinimumUnits),\n UnitPrice = todecimal(UnitPrice)\n //\n | extend x_SkuId = coalesce(SkuId, SkuID)\n | extend x_SkuMeterId = coalesce(MeterId, MeterID)\n | extend x_SkuProductId = coalesce(ProductId, ProductID)\n | extend x_SkuTerm = isoMonths(Term)\n | project-rename\n x_BaseUnitPrice = BasePrice,\n x_EffectivePeriodEnd = EffectiveEndDate,\n x_EffectivePeriodStart = EffectiveStartDate,\n x_PricingUnitDescription = UnitOfMeasure,\n x_SkuIncludedQuantity = IncludedQuantity,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuMeterType = MeterType,\n x_SkuOfferId = OfferID,\n x_SkuPartNumber = PartNumber,\n x_SkuPriceType = PriceType,\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTier = TierMinimumUnits\n | extend ContractedUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', UnitPrice, todecimal('')) // UnitPrice for savings plan is not the on-demand unit price\n | extend ListUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', MarketPrice, todecimal('')) // MarketPrice for savings plan is not the list price\n | extend ChargeCategory = case(\n x_SkuPriceType == 'Consumption', 'Usage',\n x_SkuPriceType == 'ReservedInstance', 'Purchase',\n x_SkuPriceType == 'SavingsPlan', 'Usage', // Savings plan prices are for committed usage, not the purchase\n ''\n )\n | extend SkuPriceIdv2 = strcat(case(x_SkuPriceType == 'Consumption', 'OD', x_SkuPriceType == 'ReservedInstance', 'RI', x_SkuPriceType == 'SavingsPlan', 'SP', 'XX'), substring(ChargeCategory, 0, 1), x_SkuTerm, '_', x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType, '_', x_SkuTier, x_SkuOfferId)\n | extend x_BillingAccountId = iff(BillingAccountId startswith '/', split(BillingAccountId, '/')[-1], coalesce(BillingAccountId, EnrollmentNumber))\n | extend x_BillingProfileId = iff(BillingProfileId startswith '/', split(BillingProfileId, '/')[-1], coalesce(BillingProfileId, EnrollmentNumber))\n | extend tmp_SavingsPlanKey = strcat(x_SkuMeterId, x_SkuProductId, x_SkuId, x_SkuTier, x_SkuOfferId)\n //\n // Get latest ingested row based on the unique ID\n | extend x_IngestionTime = ingestion_time()\n );\n //\n // Meters for reservations and savings plans to identify commitment eligibility\n let riMeters = prices | where x_SkuPriceType == 'ReservedInstance' | distinct x_SkuMeterId;\n let spMeters = prices | where x_SkuPriceType == 'SavingsPlan' | distinct x_SkuMeterId;\n //\n // Copy list/base/contracted prices from on-demand SKUs\n prices\n | where x_SkuPriceType == 'SavingsPlan'\n // If we use join, specify the shuffle key\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter hint.strategy=shuffle (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | lookup kind=leftouter (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | extend ListUnitPrice = coalesce(ListUnitPrice, ListUnitPrice1)\n | extend ContractedUnitPrice = coalesce(ContractedUnitPrice, ContractedUnitPrice1)\n | extend x_BaseUnitPrice = coalesce(x_BaseUnitPrice, x_BaseUnitPrice1)\n | project-away ListUnitPrice1, ContractedUnitPrice1, x_BaseUnitPrice1, tmp_SavingsPlanKey\n | union ((prices | where x_SkuPriceType != 'SavingsPlan'))\n //\n // Calculate commitment discount elgibility\n // TODO: Would a join be faster?\n | extend x_CommitmentDiscountSpendEligibility = iff(x_SkuMeterId in (riMeters) and x_SkuPriceType != 'ReservedInstance', 'Eligible', 'Not Eligible')\n | extend x_CommitmentDiscountUsageEligibility = iff(x_SkuMeterId in (spMeters), 'Eligible', 'Not Eligible')\n //\n // Add PricingUnit and x_PricingBlockSize\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter (PricingUnits) on x_PricingUnitDescription | project-away x_PricingUnitDescription1\n | lookup kind=leftouter (PricingUnits | extend x_PricingBlockSize = todecimal(x_PricingBlockSize)) on x_PricingUnitDescription\n //\n | extend x_EffectiveUnitPrice = iff(x_SkuPriceType == 'SavingsPlan', UnitPrice, todecimal('')) // Savings plan prices are for the effective price, not the contracted price\n | extend x_EffectiveUnitPriceDiscount = ContractedUnitPrice - x_EffectiveUnitPrice\n | extend x_ContractedUnitPriceDiscount = ListUnitPrice - ContractedUnitPrice\n | extend x_TotalUnitPriceDiscount = ListUnitPrice - x_EffectiveUnitPrice\n | project\n BillingAccountId = tolower(case(\n BillingProfileId startswith '/', BillingProfileId,\n BillingAccountId startswith '/', BillingAccountId,\n strcat('/providers/microsoft.billing/billingaccounts/', x_BillingAccountId, iff(x_BillingProfileId == x_BillingAccountId, '', strcat('/billingprofiles/', x_BillingProfileId)))\n )),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName, x_BillingProfileId),\n BillingCurrency = coalesce(BillingCurrency, CurrencyCode, Currency), // Currency last as a fallback only\n ChargeCategory,\n CommitmentDiscountCategory = case(\n x_SkuPriceType == 'ReservedInstance', 'Usage',\n x_SkuPriceType == 'SavingsPlan', 'Spend',\n ''\n ),\n CommitmentDiscountType = case(\n x_SkuPriceType == 'ReservedInstance', 'Reservation',\n x_SkuPriceType == 'SavingsPlan', 'Savings plan',\n ''\n ),\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory = case(\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed',\n ''\n ),\n PricingUnit,\n SkuId = coalesce(ProductId, ProductID),\n SkuPriceId = strcat(x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType),\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement = case(\n strlen(x_BillingAccountId) > 32, 'MCA',\n strlen(x_BillingAccountId) < 32, 'EA',\n 'Unknown'\n ),\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent = 1.0 * x_ContractedUnitPriceDiscount / ListUnitPrice * 100,\n x_EffectivePeriodEnd = startofmonth(x_EffectivePeriodEnd + 1h),\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent = 1.0 * x_EffectiveUnitPriceDiscount / ContractedUnitPrice * 100,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingCurrency = coalesce(Currency, CurrencyCode), // CurrencyCode last as a fallback only\n x_PricingSubcategory = case(\n x_SkuPriceType == 'Consumption' and (x_SkuIncludedQuantity > 0 or x_SkuTier > 0), 'Tiered',\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed Spend',\n ''\n ),\n x_PricingUnitDescription,\n x_SkuDescription = Product,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterName,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName = coalesce(x_SourceName, 'Cost Management'),\n x_SourceProvider = coalesce(x_SourceProvider, 'Microsoft'),\n x_SourceType = coalesce(x_SourceType, 'PriceSheet'),\n x_SourceVersion = coalesce(x_SourceVersion, '2023-05-01'),\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent = 1.0 * x_TotalUnitPriceDiscount / ListUnitPrice * 100\n}\n\n// Prices_final_v1_0 table\n.create-merge table Prices_final_v1_0 (\n BillingAccountId: string,\n BillingAccountName: string,\n BillingCurrency: string,\n ChargeCategory: string,\n CommitmentDiscountCategory: string,\n CommitmentDiscountType: string,\n ContractedUnitPrice: decimal,\n ListUnitPrice: decimal,\n PricingCategory: string,\n PricingUnit: string,\n SkuId: string,\n SkuPriceId: string,\n SkuPriceIdv2: string, // Hubs add-on\n x_BaseUnitPrice: decimal, // Azure\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure MCA\n x_BillingProfileId: string, // Azure MCA\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_ContractedUnitPriceDiscount: decimal, // Hubs add-on\n x_ContractedUnitPriceDiscountPercent: decimal, // Hubs add-on\n x_EffectivePeriodEnd: datetime, // Azure\n x_EffectivePeriodStart: datetime, // Azure\n x_EffectiveUnitPrice: decimal, // Azure\n x_EffectiveUnitPriceDiscount: decimal, // Hubs add-on\n x_EffectiveUnitPriceDiscountPercent: decimal, // Hubs add-on\n x_IngestionTime: datetime, // Hubs add-on\n x_PricingBlockSize: decimal, // Hubs add-on\n x_PricingCurrency: string, // Azure\n x_PricingSubcategory: string, // Hubs add-on\n x_PricingUnitDescription: string, // Azure\n x_SkuDescription: string, // Azure\n x_SkuId: string, // Azure\n x_SkuIncludedQuantity: decimal, // Azure EA\n x_SkuMeterCategory: string, // Azure\n x_SkuMeterId: string, // Azure\n x_SkuMeterName: string, // Azure\n x_SkuMeterSubcategory: string, // Azure\n x_SkuMeterType: string, // Azure\n x_SkuPriceType: string, // Azure\n x_SkuProductId: string, // Azure\n x_SkuRegion: string, // Azure\n x_SkuServiceFamily: string, // Azure\n x_SkuOfferId: string, // Azure EA\n x_SkuPartNumber: string, // Azure EA\n x_SkuTerm: int, // Azure\n x_SkuTier: decimal, // Azure MCA\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_TotalUnitPriceDiscount: decimal, // Hubs add-on\n x_TotalUnitPriceDiscountPercent: decimal // Hubs add-on\n)\n\n// Update policy for Prices_raw -> Prices_final_v1_0\n.alter table Prices_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Prices_raw\",\n \"Query\": \"Prices_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Cost and usage |=================================================================================================\n// Supported versions:\n// - MS: 1.0, 1.0-preview(v1) -- See https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0 -- See https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024 -- See https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 -- See https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All costs transformed to FOCUS 1.0. Use Costs_transform_v1_2() instead.', folder='Costs')\nCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n Costs_raw\n //\n // Change real to decimal\n | extend\n BilledCost = todecimal(BilledCost),\n CommitmentDiscountQuantity = todecimal(CommitmentDiscountQuantity),\n ConsumedQuantity = todecimal(ConsumedQuantity),\n ContractedCost = todecimal(ContractedCost),\n ContractedUnitPrice = todecimal(ContractedUnitPrice),\n EffectiveCost = todecimal(EffectiveCost),\n ListCost = todecimal(ListCost),\n ListUnitPrice = todecimal(ListUnitPrice),\n PricingQuantity = todecimal(PricingQuantity),\n UsageAmount = todecimal(UsageAmount),\n UsageQuantity = todecimal(UsageQuantity),\n x_BilledCostInUsd = todecimal(x_BilledCostInUsd),\n x_BilledUnitPrice = todecimal(x_BilledUnitPrice),\n x_BillingExchangeRate = todecimal(x_BillingExchangeRate),\n x_ContractedCostInUsd = todecimal(x_ContractedCostInUsd),\n x_Cost = todecimal(x_Cost),\n x_CurrencyConversionRate = todecimal(x_CurrencyConversionRate),\n x_EffectiveCostInUsd = todecimal(x_EffectiveCostInUsd),\n x_EffectiveUnitPrice = todecimal(x_EffectiveUnitPrice),\n x_ListCostInUsd = todecimal(x_ListCostInUsd),\n x_OnDemandCost = todecimal(x_OnDemandCost),\n x_OnDemandCostInUsd = todecimal(x_OnDemandCostInUsd),\n x_OnDemandUnitPrice = todecimal(x_OnDemandUnitPrice),\n x_PricingBlockSize = todecimal(x_PricingBlockSize)\n //\n // Dedupe rows\n | extend x_IngestionTime = ingestion_time()\n | extend x_ChargeId = ''\n // TODO: Consider adding a unique charge ID per row\n // hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // // 1. Resource hierarchy (including resource name), highest to lowest\n // BillingAccountId,\n // x_InvoiceSectionId,\n // x_AccountOwnerId,\n // SubAccountId,\n // x_ResourceGroupName,\n // ResourceName,\n // // 2. Resource details\n // ResourceId,\n // RegionId,\n // Tags,\n // CommitmentDiscountId,\n // x_CostCenter,\n // // 4. Meter details\n // SkuPriceId,\n // x_SkuMeterId,\n // x_SkuPartNumber,\n // x_SkuOfferId,\n // x_SkuDetails,\n // // 5. Date\n // ChargePeriodStart\n // ))\n //\n // Identify data quality issues\n | extend x_SourceChanges = trim_end(',', strcat(\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based', 'InvalidChargeFrequency,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and EffectiveCost > 0, 'InvalidEffectiveCost,', ''),\n iff((isempty(ContractedCost) or ContractedCost == 0) and EffectiveCost != 0, 'MissingContractedCost,', ''),\n iff((isempty(ContractedUnitPrice) or ContractedUnitPrice == 0) and x_EffectiveUnitPrice != 0, 'MissingContractedUnitPrice,', ''),\n iff(ListCost < ContractedCost, 'ListCostLessThanContractedCost,', ''),\n iff(ContractedCost < EffectiveCost, 'ContractedCostLessThanEffectiveCost,', ''),\n iff((isempty(ListCost) or ListCost == 0) and (ContractedCost != 0 or EffectiveCost != 0), 'MissingListCost,', ''),\n iff((isempty(ListUnitPrice) or ListUnitPrice == 0) and (ContractedUnitPrice != 0 or x_EffectiveUnitPrice != 0), 'MissingListUnitPrice,', ''),\n iff((isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001)\n or (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001),\n 'XEffectiveUnitPriceRoundingError,', ''),\n iff(ConsumedQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingConsumedQuantity,', ''),\n iff(PricingQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingPricingQuantity,', ''),\n iff(isempty(ProviderName), 'MissingProviderName,', ''),\n iff(isempty(PublisherName), 'MissingPublisherName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceId), 'MissingResourceId,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceName), 'MissingResourceName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceType), 'MissingResourceType,', ''),\n iff(BilledCost > 0 and x_BilledUnitPrice == 0, 'MissingXBilledUnitPrice,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(x_ResourceType), 'MissingXResourceType,', ''),\n iff(PricingCategory == 'Standard' and isnotempty(CommitmentDiscountId) and ChargeCategory == 'Usage', 'PricingCategoryShouldBeCommitted,', ''),\n iff(x_SkuTerm == '1Year' or x_SkuTerm == '3Years' or x_SkuTerm == '5Years', 'SkuTermShouldBeAnInteger,', '')\n ))\n //\n // Fix columns needed in other changes\n | extend ProviderName = case(\n isnotempty(ProviderName), ProviderName,\n isnotempty(coalesce(x_CostCategories, x_Discount, x_Operation, x_ServiceCode, x_UsageType)), 'AWS',\n isnotempty(coalesce(tostring(UsageAmount), tostring(x_Cost), x_Credits, x_CostType, tostring(x_CurrencyConversionRate), tostring(x_ExportTime), x_Project, x_ServiceId)), 'GCP',\n isnotempty(coalesce(x_BillingProfileId, x_InvoiceSectionId)), 'Microsoft',\n ''\n )\n //\n // Identify source\n | extend x_SourceName = coalesce(x_SourceName, iff(isnotempty(x_BillingProfileId), 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(isnotempty(x_BillingProfileId), 'FocusCost', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, case(\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)) and isempty(SkuPriceDetails) and isnotempty(x_SkuDetails), '1.2-preview',\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)), '1.2',\n isnotempty(coalesce(ChargeClass, CommitmentDiscountStatus, tostring(ConsumedQuantity), ConsumedUnit, tostring(ContractedCost), tostring(ContractedUnitPrice), RegionId, RegionName)), '1.0',\n isnotempty(coalesce(ChargeSubcategory, Region, tostring(UsageQuantity), UsageUnit)), iff(ProviderName == 'Microsoft', '1.0-preview(v1)', '1.0-preview'),\n ''\n ))\n // Append version check error code\n | extend x_SourceChanges = iff(x_SourceVersion == '1.0', x_SourceChanges,\n strcat(x_SourceChanges, iff(isempty(x_SourceChanges), '', ','), iff(x_SourceVersion == '', 'UnknownFocusVersion', 'LegacyFocusVersion'))\n )\n //\n // Fix quantities\n | extend PricingQuantity = case(\n PricingQuantity != 0 or (EffectiveCost == 0 and BilledCost == 0), PricingQuantity,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(EffectiveCost) and EffectiveCost != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0, EffectiveCost / x_EffectiveUnitPrice,\n PricingQuantity\n )\n | extend ConsumedQuantity = case(\n isnotempty(ConsumedQuantity) and ConsumedQuantity != 0, ConsumedQuantity,\n ChargeCategory == 'Usage', PricingQuantity / coalesce(x_PricingBlockSize, decimal(1)),\n ConsumedQuantity\n )\n //\n // Populate missing prices -- mapping to on-demand prices requires meter ID and offer ID\n | extend tmp_MissingPrices = ProviderName == 'Microsoft'\n and (ListUnitPrice == 0 or ContractedUnitPrice == 0)\n and x_EffectiveUnitPrice != 0\n and not(CommitmentDiscountCategory == 'Spend' and CommitmentDiscountStatus == 'Unused')\n and isnotempty(strcat(x_SkuMeterId, x_SkuOfferId))\n | as allCosts\n | where tmp_MissingPrices\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(ChargePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | as costsWithMissingPrices\n | join kind=leftouter (\n Prices_final_v1_0\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(x_EffectivePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | where x_SkuPriceType == 'Consumption' and tmp_ReservationPriceLookupKey in ((costsWithMissingPrices | summarize by tmp_ReservationPriceLookupKey))\n | summarize ListUnitPrice = min(ListUnitPrice), ContractedUnitPrice = min(ContractedUnitPrice) by tmp_ReservationPriceLookupKey, x_PricingBlockSize, PricingUnit\n ) on tmp_ReservationPriceLookupKey\n //\n // Select the best price to use for each row\n // TODO: Save values before changing -- | extend x_old_ContractedUnitPrice = ContractedUnitPrice, x_old_EffectiveUnitPrice = x_EffectiveUnitPrice, x_old_ListUnitPrice = ListUnitPrice, x_old_ListCost = ListCost, x_old_ContractedCost = ContractedCost\n | extend x_EffectiveUnitPrice = case(\n // If price is a rounding error away from the billed price, use the billed price\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001, x_BilledUnitPrice,\n // If price is a rounding error away from the contracted price, use the contracted price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001, ContractedUnitPrice,\n x_EffectiveUnitPrice\n )\n | extend ContractedUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ContractedUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ContractedUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // If billed price is available, assume the billed price is the same as contracted price to support aggregations\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, x_EffectiveUnitPrice,\n // Otherwise, assume the effective price is the same as contracted price to support aggregations\n x_EffectiveUnitPrice\n )\n | extend ListUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ListUnitPrice) and ListUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ListUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ListUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ListUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // Otherwise, assume the contracted price is the same as list price to support aggregations\n ContractedUnitPrice\n )\n // Calculate missing costs based on new prices -- If cost is already correct, keep that; if not and price is available, recalculate the cost; otherwise, keep the existing cost\n | extend ContractedCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ContractedCost) and ContractedCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedCost,\n // ContractedCost is 0 in all other scenarios...\n // If 0 and there's a billed cost and prices are the same, use BilledCost\n isnotempty(BilledCost) and BilledCost != 0 and ContractedUnitPrice == x_BilledUnitPrice, BilledCost,\n // If 0 and there's a billed cost and prices are the same, use EffectiveCost\n isnotempty(EffectiveCost) and EffectiveCost != 0 and ContractedUnitPrice == x_EffectiveUnitPrice, EffectiveCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0, ContractedUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume EffectiveCost\n isempty(ContractedUnitPrice) or ContractedUnitPrice == 0, EffectiveCost,\n // Fall back to the original value for any unhandled scenarios\n ContractedCost\n )\n | extend ListCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ListCost) and ListCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ListCost,\n // ListCost is 0 in all other scenarios...\n // If 0 and there's a contracted cost and prices are the same, use ContractedCost\n isnotempty(ContractedCost) and ContractedCost != 0 and ListUnitPrice == ContractedUnitPrice, ContractedCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ListUnitPrice) and ListUnitPrice != 0, ListUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume ContractedCost\n isempty(ListUnitPrice) or ListUnitPrice == 0, ContractedCost,\n // Fall back to the original value for any unhandled scenarios\n ListCost\n )\n // Merge the rest of the unmodified cost records and remove excess columns\n | union (allCosts | where not(tmp_MissingPrices))\n | project-away x_PricingBlockSize1, PricingUnit1, ListUnitPrice1, ContractedUnitPrice1, tmp_MissingPrices, tmp_ReservationPriceLookupKey, tmp_ReservationPriceLookupKey1\n //\n // BUG: Fix ContractedCost that has bad values\n | extend ContractedCost = iff(ProviderName == 'Microsoft' and isnotempty(PricingQuantity) and isnotempty(x_PricingBlockSize) and ContractedCost != ContractedUnitPrice * PricingQuantity, ContractedUnitPrice * PricingQuantity, ContractedCost)\n //\n // Handle FOCUS 1.0-preview UsageQuantity/Unit\n | extend ConsumedQuantity = iff(ChargeCategory == 'Usage', coalesce(ConsumedQuantity, UsageQuantity, UsageAmount), todecimal(''))\n | extend ConsumedUnit = iff(ChargeCategory == 'Usage' and isnotempty(ConsumedQuantity), coalesce(ConsumedUnit, UsageUnit, 'Units'), '')\n //\n // Convert IDs to lowercase for consistency\n | extend CommitmentDiscountId = tolower(CommitmentDiscountId)\n //\n // BUG: Remove EffectiveCost for commitment discount purchases\n | extend EffectiveCost = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), decimal(0), EffectiveCost)\n | extend x_EffectiveCostInUsd = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), decimal(0), x_EffectiveCostInUsd)\n //\n // Clean up resource columns\n | extend ResourceId = case(\n isnotempty(ResourceId), ResourceId,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), CommitmentDiscountId,\n ResourceId)\n | extend ResourceName = tolower(case(\n isnotempty(ResourceName), ResourceName,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountName), CommitmentDiscountName,\n isnotempty(ResourceId), parse_resourceid(ResourceId).ResourceName,\n ResourceName))\n | extend x_ResourceType = case(\n isnotempty(x_ResourceType), x_ResourceType,\n isnotempty(ResourceId), parse_resourceid(ResourceId).x_ResourceType,\n x_ResourceType)\n | extend ResourceType = case(\n // Use existing resource type display name unless it's an internal resource type ID\n isnotempty(ResourceType) and tolower(ResourceType) != tolower(x_ResourceType) and ResourceType !contains '/', ResourceType,\n // Use CommitmentDiscountType for commitment discount purchases\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountType), CommitmentDiscountType,\n // Look up display name from internal type\n isnotempty(x_ResourceType), coalesce(resource_type(x_ResourceType).SingularDisplayName, ResourceType, x_ResourceType),\n ResourceType)\n //\n // Sort columns and apply final transforms\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId = tolower(BillingAccountId),\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEnd),\n BillingPeriodStart = startofmonth(BillingPeriodStart),\n ChargeCategory = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Credit', 'Credit',\n ChargeSubcategory == 'Refund', 'Purchase', // We are assuming purchase refunds since we don't have data to indicate usage refunds\n ChargeCategory\n ),\n ChargeClass = case(ChargeSubcategory == 'Refund', 'Correction', ChargeClass),\n ChargeDescription,\n // BUG: ChargeFrequency shows \"Usage-Based\" for monthly recurring savings plan purchases\n ChargeFrequency = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based' and ProviderName == 'Microsoft' and x_SourceVersion startswith '1.0', 'Recurring', ChargeFrequency),\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId = tolower(CommitmentDiscountId),\n CommitmentDiscountName,\n CommitmentDiscountStatus = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Used Commitment', 'Used',\n ChargeSubcategory == 'Unused Commitment', 'Unused',\n CommitmentDiscountStatus\n ),\n CommitmentDiscountType,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost = coalesce(ContractedCost, x_OnDemandCost, x_Cost),\n ContractedUnitPrice = coalesce(ContractedUnitPrice, x_OnDemandUnitPrice),\n EffectiveCost,\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory = case(\n // Handle FOCUS 1.0-preview PricingCategory values\n PricingCategory == 'On-Demand', 'Standard',\n PricingCategory == 'Commitment-Based', 'Committed',\n PricingCategory\n ),\n PricingQuantity,\n PricingUnit,\n ProviderName,\n // Handle missing PublisherName values\n PublisherName = case(PublisherName == 'Microsoft Corporation', 'Microsoft', isnotempty(PublisherName), PublisherName, x_PublisherCategory == 'Cloud Provider', ProviderName, ''),\n // Handle FOCUS 1.0-preview Region column\n RegionId = coalesce(RegionId, iff(ProviderName == 'Microsoft', replace_string(tolower(Region), ' ', ''), Region)),\n RegionName = coalesce(RegionName, Region),\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SkuId,\n SkuPriceId,\n SubAccountId,\n SubAccountName,\n SubAccountType, // Azure 1.0-preview(v1)+\n Tags = parse_json(Tags),\n x_AccountId, // Azure 1.0-preview(v1)+\n x_AccountName, // Azure 1.0-preview(v1)+\n x_AccountOwnerId, // Azure 1.0-preview(v1)+\n x_BilledCostInUsd, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement = case(\n ProviderName == 'Microsoft' and x_BillingAccountId == x_BillingProfileId, 'EA',\n ProviderName == 'Microsoft' and x_BillingAccountId != x_BillingProfileId, 'MCA',\n ProviderName\n ), // Hubs add-on\n x_BillingAccountId, // Azure 1.0-preview(v1)+\n x_BillingAccountName, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate, // Azure 1.0-preview(v1)+\n x_BillingProfileId, // Azure 1.0-preview(v1)+\n x_BillingProfileName, // Azure 1.0-preview(v1)+\n x_ChargeId, // Azure 1.0-preview(v1) only\n x_ContractedCostInUsd = coalesce(x_ContractedCostInUsd, x_OnDemandCostInUsd), // Azure 1.0+\n x_CostAllocationRuleName, // Azure 1.0-preview(v1)+\n x_CostCategories = parse_json(x_CostCategories), // AWS 1.0 (JSON)\n x_CostCenter, // Azure 1.0-preview(v1)+\n x_Credits = parse_json(x_Credits), // GCP Jan 2024\n x_CostType, // GCP Jan 2024\n x_CurrencyConversionRate, // GCP Jun 2024\n x_CustomerId, // Azure 1.0-preview(v1)+\n x_CustomerName, // Azure 1.0-preview(v1)+\n x_Discount = parse_json(x_Discount), // AWS 1.0 (JSON)\n x_EffectiveCostInUsd, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice, // Azure 1.0-preview(v1)+\n x_ExportTime, // GCP Jan 2024\n x_IngestionTime, // Hubs add-on\n x_InvoiceId = coalesce(InvoiceId, x_InvoiceId), // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId = case( // Azure 1.0-preview(v1)+\n x_InvoiceSectionId == '-2', '',\n x_InvoiceSectionId\n ),\n x_InvoiceSectionName = case( // Azure 1.0-preview(v1)+\n x_InvoiceSectionName == 'Unassigned', '',\n x_InvoiceSectionName\n ),\n x_ListCostInUsd, // Azure 1.0-preview(v1)+\n x_Location, // GCP Jan 2024\n x_Operation, // AWS 1.0\n x_PartnerCreditApplied, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate, // Azure 1.0-preview(v1)+\n x_PricingBlockSize, // Azure 1.0-preview(v1)+\n x_PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency), // Azure 1.0-preview(v1)+\n x_PricingSubcategory, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription, // Azure 1.0-preview(v1)+\n x_Project, // GCP Jan 2024\n x_PublisherCategory, // Azure 1.0-preview(v1)+\n x_PublisherId, // Azure 1.0-preview(v1)+\n x_ResellerId, // Azure 1.0-preview(v1)+\n x_ResellerName, // Azure 1.0-preview(v1)+\n x_ResourceGroupName = tolower(x_ResourceGroupName), // Azure 1.0-preview(v1)+\n x_ResourceType, // Azure 1.0-preview(v1)+\n x_ServiceCode, // AWS 1.0\n x_ServiceId, // GCP Jan 2024\n x_ServicePeriodEnd, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart, // Azure 1.0-preview(v1)+\n x_SkuDescription, // Azure 1.0-preview(v1)+\n x_SkuDetails = parse_json(x_SkuDetails), // Azure 1.0-preview(v1)+\n x_SkuIsCreditEligible, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory, // Azure 1.0-preview(v1)+\n x_SkuMeterId, // Azure 1.0-preview(v1)+\n x_SkuMeterName = coalesce(SkuMeter, x_SkuMeterName), // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory, // Azure 1.0-preview(v1)+\n x_SkuOfferId, // Azure 1.0-preview(v1)+\n x_SkuOrderId, // Azure 1.0-preview(v1)+\n x_SkuOrderName, // Azure 1.0-preview(v1)+\n x_SkuPartNumber, // Azure 1.0-preview(v1)+\n x_SkuRegion, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily, // Azure 1.0-preview(v1)+\n x_SkuTerm, // Azure 1.0-preview(v1)+\n x_SkuTier, // Azure 1.0-preview(v1)+\n x_SourceChanges, // Hubs add-on\n x_SourceName, // Hubs add-on\n x_SourceProvider, // Hubs add-on\n x_SourceType, // Hubs add-on\n x_SourceVersion, // Hubs add-on\n x_UsageType // AWS 1.0\n}\n\n// Costs_final_v1_0 table\n.create-merge table Costs_final_v1_0 (\n AvailabilityZone: string,\n BilledCost: decimal,\n BillingAccountId: string,\n BillingAccountName: string,\n BillingAccountType: string, // Azure 1.0-preview(v1)+\n BillingCurrency: string,\n BillingPeriodEnd: datetime,\n BillingPeriodStart: datetime,\n ChargeCategory: string,\n ChargeClass: string,\n ChargeDescription: string,\n ChargeFrequency: string,\n ChargePeriodEnd: datetime,\n ChargePeriodStart: datetime,\n CommitmentDiscountCategory: string, // FOCUS 1.0-preview only\n CommitmentDiscountId: string,\n CommitmentDiscountName: string,\n CommitmentDiscountStatus: string,\n CommitmentDiscountType: string,\n ConsumedQuantity: decimal,\n ConsumedUnit: string,\n ContractedCost: decimal,\n ContractedUnitPrice: decimal,\n EffectiveCost: decimal,\n InvoiceIssuerName: string,\n ListCost: decimal,\n ListUnitPrice: decimal,\n PricingCategory: string,\n PricingQuantity: decimal,\n PricingUnit: string,\n ProviderName: string,\n PublisherName: string,\n RegionId: string,\n RegionName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n ServiceCategory: string,\n ServiceName: string,\n SkuId: string,\n SkuPriceId: string,\n SubAccountId: string,\n SubAccountName: string,\n SubAccountType: string,\n Tags: dynamic,\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_BilledCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: decimal, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: decimal, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_ContractedCostInUsd: decimal, // Azure 1.0+\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: dynamic, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_Credits: dynamic, // GCP Jan 2024\n x_CostType: string, // GCP Jan 2024\n x_CurrencyConversionRate: decimal, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: dynamic, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: decimal, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024\n x_IngestionTime: datetime, // Hubs add-on\n x_InvoiceId: string, // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_Operation: string, // AWS 1.0\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: decimal, // Azure 1.0-preview(v1)+\n x_PricingCurrency: string, // Azure 1.0-preview(v1)+\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: dynamic, // Azure 1.0-preview(v1)+\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterName: string, // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceChanges: string, // Hubs add-on\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_UsageType: string // AWS 1.0\n)\n\n// Update policy for Costs_raw -> Costs_final_v1_0 table\n.alter table Costs_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Costs_raw\",\n \"Query\": \"Costs_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Actual costs |===================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: ActualCost exports transformed to FOCUS 1.0. Use ActualCosts_transform_v1_2() instead.', folder='Costs')\nActualCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n // TODO: Transform actual costs to FOCUS 1.0 format\n ActualCosts_raw\n | where ChargeType in ('Purchase', 'Refund') and isnotempty(ReservationId)\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: ServiceSubcategory, PublisherName, x_PublisherCategory, x_Environment, x_ServiceModel\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodStart = Date,\n ChargePeriodEnd = Date + 1d,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = '',\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory = '',\n SkuId = '',\n SkuMeter = '',\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = SubscriptionName,\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentName = '',\n x_ComponentType = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel = '',\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for ActualCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": false,\n \"Source\": \"ActualCosts_raw\",\n \"Query\": \"ActualCosts_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Amortized costs |================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: ActualCost exports transformed to FOCUS 1.0. Use AmortizedCosts_transform_v1_2() instead.', folder='Costs')\nAmortizedCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n // TODO: Transform actual costs to FOCUS 1.0 format\n AmortizedCosts_raw\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: ServiceSubcategory, PublisherName, x_PublisherCategory, x_Environment, x_ServiceModel\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodStart = Date,\n ChargePeriodEnd = Date + 1d,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = '',\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory = '',\n SkuId = '',\n SkuMeter = '',\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = SubscriptionName,\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentName = '',\n x_ComponentType = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel = '',\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for AmortizedCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": false,\n \"Source\": \"AmortizedCosts_raw\",\n \"Query\": \"AmortizedCosts_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All commitment discount usage transformed to FOCUS 1.0. This includes reservationdeatils_raw. Use CommitmentDiscountUsage_transform_v1_2() instead.', folder='Commitment discounts')\nCommitmentDiscountUsage_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n CommitmentDiscountUsage_raw\n //\n // Change real to decimal\n | extend\n InstanceFlexibilityRatio = todecimal(InstanceFlexibilityRatio),\n ReservedHours = todecimal(ReservedHours),\n TotalReservedQuantity = todecimal(TotalReservedQuantity),\n UsedHours = todecimal(UsedHours)\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Handle resource columns\n | extend ResourceId = tolower(InstanceId)\n | extend tmp_ResourceDetails = parse_resourceid(ResourceId)\n | extend ResourceName = tostring(tmp_ResourceDetails.ResourceName)\n | extend SubAccountId = tostring(tmp_ResourceDetails.SubAccountId)\n | extend x_ResourceGroupName = tostring(tmp_ResourceDetails.x_ResourceGroupName)\n | extend x_ResourceType = tostring(tmp_ResourceDetails.x_ResourceType)\n | lookup kind=leftouter (ResourceTypes | distinct x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n | lookup kind=leftouter (Services | distinct x_ResourceType, ServiceName, ServiceCategory, x_ServiceModel) on x_ResourceType\n //\n // Sort columns and apply final transforms\n | project\n ChargePeriodEnd = UsageDate + 1d,\n ChargePeriodStart = UsageDate,\n CommitmentDiscountCategory = 'Usage',\n CommitmentDiscountId = tolower(strcat('/providers/microsoft.capacity/reservationorders/', ReservationOrderId, '/reservations/', ReservationId)),\n CommitmentDiscountType = 'Reservation',\n ConsumedQuantity = UsedHours,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SubAccountId,\n x_CommitmentDiscountCommittedCount = TotalReservedQuantity,\n x_CommitmentDiscountCommittedAmount = ReservedHours,\n // TODO: Is this needed? -- x_CommitmentDiscountKind = Kind,\n x_CommitmentDiscountNormalizedGroup = iff(InstanceFlexibilityGroup == 'NA', '', InstanceFlexibilityGroup),\n x_CommitmentDiscountNormalizedRatio = InstanceFlexibilityRatio,\n x_CommitmentDiscountQuantity = UsedHours * InstanceFlexibilityRatio,\n x_IngestionTime = ingestion_time(),\n x_ResourceGroupName,\n x_ResourceType,\n // x_RowId = hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // CommitmentDiscountId,\n // ResourceId,\n // ChargePeriodStart\n // )),\n x_ServiceModel,\n x_SkuOrderId = ReservationOrderId,\n x_SkuSize = iff(SkuName == 'NA', '', SkuName),\n x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName)),\n x_SourceProvider = coalesce(x_SourceProvider, ProviderName),\n x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationDetails', '')),\n x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2024-03-01', ''))\n}\n\n// CommitmentDiscountUsage_final_v1_0 table\n.create-merge table CommitmentDiscountUsage_final_v1_0 (\n ChargePeriodEnd: datetime, // Hubs add-on\n ChargePeriodStart: datetime, // MS 2023-03-01\n CommitmentDiscountCategory: string, // Hubs add-on\n CommitmentDiscountId: string, // MS 2023-03-01\n CommitmentDiscountType: string, // Hubs add-on\n ConsumedQuantity: decimal, // MS 2023-03-01\n ProviderName: string, // Hubs add-on\n ResourceId: string, // MS 2023-03-01\n ResourceName: string, // Hubs add-on\n ResourceType: string, // Hubs add-on\n ServiceCategory: string, // Hubs add-on\n ServiceName: string, // Hubs add-on\n SubAccountId: string, // Hubs add-on\n x_CommitmentDiscountCommittedCount: decimal, // MS 2023-03-01\n x_CommitmentDiscountCommittedAmount: decimal, // MS 2023-03-01\n x_CommitmentDiscountNormalizedGroup: string, // MS 2023-03-01\n x_CommitmentDiscountNormalizedRatio: decimal, // MS 2023-03-01\n x_CommitmentDiscountQuantity: decimal, // MS 2023-03-01\n x_IngestionTime: datetime, // Hubs add-on\n x_ResourceGroupName: string, // Hubs add-on\n x_ResourceType: string, // Hubs add-on\n x_ServiceModel: string, // Hubs add-on\n x_SkuOrderId: string, // MS 2023-03-01\n x_SkuSize: string, // MS 2023-03-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string // Hubs add-on\n)\n\n// Update policy for CommitmentDiscountUsage_raw -> CommitmentDiscountUsage_final_v1_0 table\n.alter table CommitmentDiscountUsage_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"CommitmentDiscountUsage_raw\",\n \"Query\": \"CommitmentDiscountUsage_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All recommendations transformed to FOCUS 1.0. Use Recommendations_transform_v1_2() instead.', folder='Recommendations')\nRecommendations_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Recommendations_raw\n //\n // Change real to decimal\n | extend\n CostWithNoReservedInstances = todecimal(CostWithNoReservedInstances),\n InstanceFlexibilityRatio = todecimal(InstanceFlexibilityRatio),\n NetSavings = todecimal(NetSavings),\n RecommendedQuantity = todecimal(RecommendedQuantity),\n RecommendedQuantityNormalized = todecimal(RecommendedQuantityNormalized),\n TotalCostWithReservedInstances = todecimal(TotalCostWithReservedInstances)\n //\n | extend x_IngestionTime = ingestion_time()\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationRecommendations', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Convert JSON cost columns to decimal\n | extend CostWithNoReservedInstances = case(isnotempty(CostWithNoReservedInstances), CostWithNoReservedInstances, isnotempty(CostWithNoReservedInstancesJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, CostWithNoReservedInstancesJson)), CostWithNoReservedInstances)\n | extend NetSavings = case(isnotempty(NetSavings), NetSavings, isnotempty(NetSavingsJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, NetSavingsJson)), NetSavings)\n | extend TotalCostWithReservedInstances = case(isnotempty(TotalCostWithReservedInstances), TotalCostWithReservedInstances, isnotempty(TotalCostWithReservedInstancesJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, TotalCostWithReservedInstancesJson)), TotalCostWithReservedInstances)\n //\n // Build recommendation details\n | lookup kind=leftouter (Regions | summarize RegionName = make_set(RegionName)[0] by Location = RegionId) on Location\n | extend x_RecommendationDetails = case(\n x_SourceType == 'ReservationRecommendations', bag_pack(\n 'CommitmentDiscountNormalizedGroup', InstanceFlexibilityGroup,\n 'CommitmentDiscountNormalizedRatio', InstanceFlexibilityRatio,\n 'CommitmentDiscountNormalizedSize', NormalizedSize,\n 'CommitmentDiscountResourceType', ResourceType,\n 'CommitmentDiscountScope', Scope,\n 'LookbackPeriodDuration', case(\n LookBackPeriod matches regex @'^Last([0-9]+)Days$', replace_regex(LookBackPeriod, @'^Last([0-9]+)Days$', @'P\\1D'),\n LookBackPeriod matches regex @'^[0-9]+$', strcat('P', LookBackPeriod, 'D'),\n ''\n ),\n 'LookbackPeriodStart', FirstUsageDate,\n 'RecommendedQuantity', RecommendedQuantity,\n 'RecommendedQuantityNormalized', RecommendedQuantityNormalized,\n 'RegionId', Location,\n 'RegionName', RegionName,\n 'SkuMeterId', MeterId,\n 'SkuPriceDetails', SkuProperties,\n 'SkuSize', coalesce(SKU, SkuName),\n 'SkuTerm', isoMonths(Term)\n ),\n dynamic({})\n )\n //\n // Sort columns and apply final transforms\n | extend x_RecommendationDate = FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d)\n | extend x_RecommendationDate = iff(x_RecommendationDate > now(), startofday(now()), x_RecommendationDate)\n | project\n ProviderName,\n SubAccountId = iff(isnotempty(SubscriptionId), strcat('/subscriptions/', SubscriptionId), ''),\n x_IngestionTime,\n x_EffectiveCostAfter = TotalCostWithReservedInstances,\n x_EffectiveCostBefore = CostWithNoReservedInstances,\n x_EffectiveCostSavings = NetSavings,\n x_RecommendationDate = FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d),\n x_RecommendationDetails,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n// Recommendations_final_v1_0 table\n.create-merge table Recommendations_final_v1_0 (\n ProviderName: string,\n SubAccountId: string,\n x_IngestionTime: datetime,\n x_EffectiveCostAfter: decimal,\n x_EffectiveCostBefore: decimal,\n x_EffectiveCostSavings: decimal,\n x_RecommendationDate: datetime,\n x_RecommendationDetails: dynamic,\n x_SourceName: string,\n x_SourceProvider: string,\n x_SourceType: string,\n x_SourceVersion: string\n)\n\n// Update policy for Recommendations_raw -> Recommendations_final_v1_0 table\n.alter table Recommendations_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Recommendations_raw\",\n \"Query\": \"Recommendations_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All transactions transformed to FOCUS 1.0. Use Transactions_transform_v1_2() instead.', folder='Transactions')\nTransactions_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Transactions_raw\n //\n // Change real to decimal\n | extend\n Amount = todecimal(Amount),\n MonetaryCommitment = todecimal(MonetaryCommitment),\n Overage = todecimal(Overage),\n Quantity = todecimal(Quantity)\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationTransactions', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Handle BillingPeriodStart/End\n | extend BillingMonth = tostring(BillingMonth)\n | extend BillingPeriodStart = iff(isempty(BillingMonth), datetime(null), todatetime(strcat(substring(BillingMonth, 0, 4), \"-\", substring(BillingMonth, 4, 2), \"-\", substring(BillingMonth, 6, 2))))\n | extend BillingPeriodEnd = iff(isempty(BillingMonth), datetime(null), startofmonth(endofmonth(BillingPeriodStart) + 1d))\n //\n // Sort columns and apply final transforms\n | project\n BilledCost = Amount,\n BillingAccountId = case(\n BillingProfileId startswith '/', BillingProfileId,\n isnotempty(CurrentEnrollmentId), strcat('/providers/Microsoft.Billing/billingAccounts/', CurrentEnrollmentId),\n isnotempty(BillingProfileId), strcat('/providers/Microsoft.Billing/billingProfiles/', BillingProfileId),\n ''\n ),\n BillingAccountName = coalesce(BillingProfileName, CurrentEnrollmentId),\n BillingCurrency = Currency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory = case(\n EventType in ('Cancel', 'Purchase', 'Refund'), 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = case(\n EventType == 'Cancel', 'Cancel', // FOCUS does not handle this scenario\n EventType == 'Refund', 'Correction',\n ''\n ),\n ChargeDescription = Description,\n ChargeFrequency = case(\n BillingFrequency == 'OneTime', 'One-Time',\n BillingFrequency == 'Recurring', 'Recurring',\n BillingFrequency\n ),\n ChargePeriodStart = EventDate,\n PricingQuantity = Quantity,\n PricingUnit = 'Reservations',\n ProviderName,\n RegionId = Region,\n RegionName = Region,\n SubAccountId = iff(isempty(PurchasingSubscriptionGuid), '', strcat('/subscriptions/', PurchasingSubscriptionGuid)),\n SubAccountName = iff(isempty(PurchasingSubscriptionGuid), '', PurchasingSubscriptionName),\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerEmail,\n x_CostCenter = CostCenter,\n x_InvoiceId = InvoiceId,\n x_InvoiceNumber = Invoice,\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = coalesce(InvoiceSectionName, DepartmentName),\n x_IngestionTime = ingestion_time(),\n x_MonetaryCommitment = MonetaryCommitment,\n x_Overage = Overage,\n x_PurchasingBillingAccountId = PurchasingEnrollment,\n x_SkuOrderId = ReservationOrderId,\n x_SkuOrderName = ReservationOrderName,\n x_SkuSize = ArmSkuName,\n x_SkuTerm = isoMonths(Term),\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId = PurchasingSubscriptionGuid,\n x_TransactionType = EventType\n}\n\n// Transactions_final_v1_0 table\n.create-merge table Transactions_final_v1_0 (\n BilledCost: decimal, // MS CM EA+MCA 2023-05-01\n BillingAccountId: string, // MS CM EA+MCA 2023-05-01\n BillingAccountName: string, // MS CM EA+MCA 2023-05-01\n BillingCurrency: string, // MS CM EA+MCA 2023-05-01\n BillingPeriodEnd: datetime, // MS CM EA+MCA 2023-05-01\n BillingPeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n ChargeCategory: string, // Hubs add-on\n ChargeClass: string, // Hubs add-on\n ChargeDescription: string, // MS CM EA+MCA 2023-05-01\n ChargeFrequency: string, // MS CM EA+MCA 2023-05-01\n ChargePeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n PricingQuantity: decimal, // MS CM EA+MCA 2023-05-01\n PricingUnit: string, // Hubs add-on\n ProviderName: string, // Hubs add-on\n RegionId: string, // MS CM EA+MCA 2023-05-01\n RegionName: string, // MS CM EA+MCA 2023-05-01\n SubAccountId: string, // MS CM EA+MCA 2023-05-01\n SubAccountName: string, // MS CM EA+MCA 2023-05-01\n x_AccountName: string, // MS CM EA 2023-05-01\n x_AccountOwnerId: string, // MS CM EA 2023-05-01\n x_CostCenter: string, // MS CM EA 2023-05-01\n x_InvoiceId: string, // MS CM MCA 2023-05-01\n x_InvoiceNumber: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionId: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionName: string, // MS CM MCA 2023-05-01\n x_IngestionTime: datetime, // Hubs add-on\n x_MonetaryCommitment: decimal, // MS CM EA 2023-05-01\n x_Overage: decimal, // MS CM EA 2023-05-01\n x_PurchasingBillingAccountId: string, // MS CM EA 2023-05-01\n x_SkuOrderId: string, // MS CM EA+MCA 2023-05-01\n x_SkuOrderName: string, // MS CM EA+MCA 2023-05-01\n x_SkuSize: string, // MS CM EA+MCA 2023-05-01\n x_SkuTerm: int, // MS CM EA+MCA 2023-05-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubscriptionId: string, // MS CM EA+MCA 2023-05-01\n x_TransactionType: string // MS CM EA+MCA 2023-05-01\n)\n\n// Update policy for Transactions_raw -> Transactions_final_v1_0 table\n.alter table Transactions_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Transactions_raw\",\n \"Query\": \"Transactions_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n", + "$fxv#9": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// Used for data ingestion, normalization, and cleansing.\n// See known issues @ https://github.com/microsoft/finops-toolkit/issues/1111\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Prices |=========================================================================================================\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All prices transformed to FOCUS 1.0. Use Prices_transform_v1_2() instead.', folder='Prices')\nPrices_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n let prices = materialize(\n Prices_raw\n //\n // Change real to decimal\n | extend\n BasePrice = todecimal(BasePrice),\n IncludedQuantity = todecimal(IncludedQuantity),\n MarketPrice = todecimal(MarketPrice),\n TierMinimumUnits = todecimal(TierMinimumUnits),\n UnitPrice = todecimal(UnitPrice)\n //\n | extend x_SkuId = coalesce(SkuId, SkuID)\n | extend x_SkuMeterId = coalesce(MeterId, MeterID)\n | extend x_SkuProductId = coalesce(ProductId, ProductID)\n | extend x_SkuTerm = isoMonths(Term)\n | project-rename\n x_BaseUnitPrice = BasePrice,\n x_EffectivePeriodEnd = EffectiveEndDate,\n x_EffectivePeriodStart = EffectiveStartDate,\n x_PricingUnitDescription = UnitOfMeasure,\n x_SkuIncludedQuantity = IncludedQuantity,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuMeterType = MeterType,\n x_SkuOfferId = OfferID,\n x_SkuPartNumber = PartNumber,\n x_SkuPriceType = PriceType,\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTier = TierMinimumUnits\n | extend ContractedUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', UnitPrice, todecimal('')) // UnitPrice for savings plan is not the on-demand unit price\n | extend ListUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', MarketPrice, todecimal('')) // MarketPrice for savings plan is not the list price\n | extend ChargeCategory = case(\n x_SkuPriceType == 'Consumption', 'Usage',\n x_SkuPriceType == 'ReservedInstance', 'Purchase',\n x_SkuPriceType == 'SavingsPlan', 'Usage', // Savings plan prices are for committed usage, not the purchase\n ''\n )\n | extend SkuPriceIdv2 = strcat(case(x_SkuPriceType == 'Consumption', 'OD', x_SkuPriceType == 'ReservedInstance', 'RI', x_SkuPriceType == 'SavingsPlan', 'SP', 'XX'), substring(ChargeCategory, 0, 1), x_SkuTerm, '_', x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType, '_', x_SkuTier, x_SkuOfferId)\n | extend x_BillingAccountId = iff(BillingAccountId startswith '/', split(BillingAccountId, '/')[-1], coalesce(BillingAccountId, EnrollmentNumber))\n | extend x_BillingProfileId = iff(BillingProfileId startswith '/', split(BillingProfileId, '/')[-1], coalesce(BillingProfileId, EnrollmentNumber))\n | extend tmp_SavingsPlanKey = strcat(x_SkuMeterId, x_SkuProductId, x_SkuId, x_SkuTier, x_SkuOfferId)\n //\n // Get latest ingested row based on the unique ID\n | extend x_IngestionTime = ingestion_time()\n );\n //\n // Meters for reservations and savings plans to identify commitment eligibility\n let riMeters = prices | where x_SkuPriceType == 'ReservedInstance' | distinct x_SkuMeterId;\n let spMeters = prices | where x_SkuPriceType == 'SavingsPlan' | distinct x_SkuMeterId;\n //\n // Copy list/base/contracted prices from on-demand SKUs\n prices\n | where x_SkuPriceType == 'SavingsPlan'\n // If we use join, specify the shuffle key\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter hint.strategy=shuffle (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | lookup kind=leftouter (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | extend ListUnitPrice = coalesce(ListUnitPrice, ListUnitPrice1)\n | extend ContractedUnitPrice = coalesce(ContractedUnitPrice, ContractedUnitPrice1)\n | extend x_BaseUnitPrice = coalesce(x_BaseUnitPrice, x_BaseUnitPrice1)\n | project-away ListUnitPrice1, ContractedUnitPrice1, x_BaseUnitPrice1, tmp_SavingsPlanKey\n | union ((prices | where x_SkuPriceType != 'SavingsPlan'))\n //\n // Calculate commitment discount elgibility\n // TODO: Would a join be faster?\n | extend x_CommitmentDiscountSpendEligibility = iff(x_SkuMeterId in (riMeters) and x_SkuPriceType != 'ReservedInstance', 'Eligible', 'Not Eligible')\n | extend x_CommitmentDiscountUsageEligibility = iff(x_SkuMeterId in (spMeters), 'Eligible', 'Not Eligible')\n //\n // Add PricingUnit and x_PricingBlockSize\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter (PricingUnits) on x_PricingUnitDescription | project-away x_PricingUnitDescription1\n | lookup kind=leftouter (PricingUnits | extend x_PricingBlockSize = todecimal(x_PricingBlockSize)) on x_PricingUnitDescription\n //\n | extend x_EffectiveUnitPrice = iff(x_SkuPriceType == 'SavingsPlan', UnitPrice, todecimal('')) // Savings plan prices are for the effective price, not the contracted price\n | extend x_EffectiveUnitPriceDiscount = ContractedUnitPrice - x_EffectiveUnitPrice\n | extend x_ContractedUnitPriceDiscount = ListUnitPrice - ContractedUnitPrice\n | extend x_TotalUnitPriceDiscount = ListUnitPrice - x_EffectiveUnitPrice\n | project\n BillingAccountId = tolower(case(\n BillingProfileId startswith '/', BillingProfileId,\n BillingAccountId startswith '/', BillingAccountId,\n strcat('/providers/microsoft.billing/billingaccounts/', x_BillingAccountId, iff(x_BillingProfileId == x_BillingAccountId, '', strcat('/billingprofiles/', x_BillingProfileId)))\n )),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName, x_BillingProfileId),\n BillingCurrency = coalesce(BillingCurrency, CurrencyCode, Currency), // Currency last as a fallback only\n ChargeCategory,\n CommitmentDiscountCategory = case(\n x_SkuPriceType == 'ReservedInstance', 'Usage',\n x_SkuPriceType == 'SavingsPlan', 'Spend',\n ''\n ),\n CommitmentDiscountType = case(\n x_SkuPriceType == 'ReservedInstance', 'Reservation',\n x_SkuPriceType == 'SavingsPlan', 'Savings plan',\n ''\n ),\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory = case(\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed',\n ''\n ),\n PricingUnit,\n SkuId = coalesce(ProductId, ProductID),\n SkuPriceId = strcat(x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType),\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement = case(\n strlen(x_BillingAccountId) > 32, 'MCA',\n strlen(x_BillingAccountId) < 32, 'EA',\n 'Unknown'\n ),\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent = 1.0 * x_ContractedUnitPriceDiscount / ListUnitPrice * 100,\n x_EffectivePeriodEnd = startofmonth(x_EffectivePeriodEnd + 1h),\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent = 1.0 * x_EffectiveUnitPriceDiscount / ContractedUnitPrice * 100,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingCurrency = coalesce(Currency, CurrencyCode), // CurrencyCode last as a fallback only\n x_PricingSubcategory = case(\n x_SkuPriceType == 'Consumption' and (x_SkuIncludedQuantity > 0 or x_SkuTier > 0), 'Tiered',\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed Spend',\n ''\n ),\n x_PricingUnitDescription,\n x_SkuDescription = Product,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterName,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName = coalesce(x_SourceName, 'Cost Management'),\n x_SourceProvider = coalesce(x_SourceProvider, 'Microsoft'),\n x_SourceType = coalesce(x_SourceType, 'PriceSheet'),\n x_SourceVersion = coalesce(x_SourceVersion, '2023-05-01'),\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent = 1.0 * x_TotalUnitPriceDiscount / ListUnitPrice * 100\n}\n\n// Prices_final_v1_0 table\n.create-merge table Prices_final_v1_0 (\n BillingAccountId: string,\n BillingAccountName: string,\n BillingCurrency: string,\n ChargeCategory: string,\n CommitmentDiscountCategory: string,\n CommitmentDiscountType: string,\n ContractedUnitPrice: decimal,\n ListUnitPrice: decimal,\n PricingCategory: string,\n PricingUnit: string,\n SkuId: string,\n SkuPriceId: string,\n SkuPriceIdv2: string, // Hubs add-on\n x_BaseUnitPrice: decimal, // Azure\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure MCA\n x_BillingProfileId: string, // Azure MCA\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_ContractedUnitPriceDiscount: decimal, // Hubs add-on\n x_ContractedUnitPriceDiscountPercent: decimal, // Hubs add-on\n x_EffectivePeriodEnd: datetime, // Azure\n x_EffectivePeriodStart: datetime, // Azure\n x_EffectiveUnitPrice: decimal, // Azure\n x_EffectiveUnitPriceDiscount: decimal, // Hubs add-on\n x_EffectiveUnitPriceDiscountPercent: decimal, // Hubs add-on\n x_IngestionTime: datetime, // Hubs add-on\n x_PricingBlockSize: decimal, // Hubs add-on\n x_PricingCurrency: string, // Azure\n x_PricingSubcategory: string, // Hubs add-on\n x_PricingUnitDescription: string, // Azure\n x_SkuDescription: string, // Azure\n x_SkuId: string, // Azure\n x_SkuIncludedQuantity: decimal, // Azure EA\n x_SkuMeterCategory: string, // Azure\n x_SkuMeterId: string, // Azure\n x_SkuMeterName: string, // Azure\n x_SkuMeterSubcategory: string, // Azure\n x_SkuMeterType: string, // Azure\n x_SkuPriceType: string, // Azure\n x_SkuProductId: string, // Azure\n x_SkuRegion: string, // Azure\n x_SkuServiceFamily: string, // Azure\n x_SkuOfferId: string, // Azure EA\n x_SkuPartNumber: string, // Azure EA\n x_SkuTerm: int, // Azure\n x_SkuTier: decimal, // Azure MCA\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_TotalUnitPriceDiscount: decimal, // Hubs add-on\n x_TotalUnitPriceDiscountPercent: decimal // Hubs add-on\n)\n\n// Update policy for Prices_raw -> Prices_final_v1_0\n.alter table Prices_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Prices_raw\",\n \"Query\": \"Prices_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Cost and usage |=================================================================================================\n// Supported versions:\n// - MS: 1.0, 1.0-preview(v1) -- See https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0 -- See https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024 -- See https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 -- See https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All costs transformed to FOCUS 1.0. Use Costs_transform_v1_2() instead.', folder='Costs')\nCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n Costs_raw\n //\n // Change real to decimal\n | extend\n BilledCost = todecimal(BilledCost),\n CommitmentDiscountQuantity = todecimal(CommitmentDiscountQuantity),\n ConsumedQuantity = todecimal(ConsumedQuantity),\n ContractedCost = todecimal(ContractedCost),\n ContractedUnitPrice = todecimal(ContractedUnitPrice),\n EffectiveCost = todecimal(EffectiveCost),\n ListCost = todecimal(ListCost),\n ListUnitPrice = todecimal(ListUnitPrice),\n PricingQuantity = todecimal(PricingQuantity),\n UsageAmount = todecimal(UsageAmount),\n UsageQuantity = todecimal(UsageQuantity),\n x_BilledCostInUsd = todecimal(x_BilledCostInUsd),\n x_BilledUnitPrice = todecimal(x_BilledUnitPrice),\n x_BillingExchangeRate = todecimal(x_BillingExchangeRate),\n x_ContractedCostInUsd = todecimal(x_ContractedCostInUsd),\n x_Cost = todecimal(x_Cost),\n x_CurrencyConversionRate = todecimal(x_CurrencyConversionRate),\n x_EffectiveCostInUsd = todecimal(x_EffectiveCostInUsd),\n x_EffectiveUnitPrice = todecimal(x_EffectiveUnitPrice),\n x_ListCostInUsd = todecimal(x_ListCostInUsd),\n x_OnDemandCost = todecimal(x_OnDemandCost),\n x_OnDemandCostInUsd = todecimal(x_OnDemandCostInUsd),\n x_OnDemandUnitPrice = todecimal(x_OnDemandUnitPrice),\n x_PricingBlockSize = todecimal(x_PricingBlockSize)\n //\n // Dedupe rows\n | extend x_IngestionTime = ingestion_time()\n | extend x_ChargeId = ''\n // TODO: Consider adding a unique charge ID per row\n // hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // // 1. Resource hierarchy (including resource name), highest to lowest\n // BillingAccountId,\n // x_InvoiceSectionId,\n // x_AccountOwnerId,\n // SubAccountId,\n // x_ResourceGroupName,\n // ResourceName,\n // // 2. Resource details\n // ResourceId,\n // RegionId,\n // Tags,\n // CommitmentDiscountId,\n // x_CostCenter,\n // // 4. Meter details\n // SkuPriceId,\n // x_SkuMeterId,\n // x_SkuPartNumber,\n // x_SkuOfferId,\n // x_SkuDetails,\n // // 5. Date\n // ChargePeriodStart\n // ))\n //\n // Identify data quality issues\n | extend x_SourceChanges = trim_end(',', strcat(\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based', 'InvalidChargeFrequency,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and EffectiveCost > 0, 'InvalidEffectiveCost,', ''),\n iff((isempty(ContractedCost) or ContractedCost == 0) and EffectiveCost != 0, 'MissingContractedCost,', ''),\n iff((isempty(ContractedUnitPrice) or ContractedUnitPrice == 0) and x_EffectiveUnitPrice != 0, 'MissingContractedUnitPrice,', ''),\n iff(ListCost < ContractedCost, 'ListCostLessThanContractedCost,', ''),\n iff(ContractedCost < EffectiveCost, 'ContractedCostLessThanEffectiveCost,', ''),\n iff((isempty(ListCost) or ListCost == 0) and (ContractedCost != 0 or EffectiveCost != 0), 'MissingListCost,', ''),\n iff((isempty(ListUnitPrice) or ListUnitPrice == 0) and (ContractedUnitPrice != 0 or x_EffectiveUnitPrice != 0), 'MissingListUnitPrice,', ''),\n iff((isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001)\n or (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001),\n 'XEffectiveUnitPriceRoundingError,', ''),\n iff(ConsumedQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingConsumedQuantity,', ''),\n iff(PricingQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingPricingQuantity,', ''),\n iff(isempty(ProviderName), 'MissingProviderName,', ''),\n iff(isempty(PublisherName), 'MissingPublisherName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceId), 'MissingResourceId,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceName), 'MissingResourceName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceType), 'MissingResourceType,', ''),\n iff(BilledCost > 0 and x_BilledUnitPrice == 0, 'MissingXBilledUnitPrice,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(x_ResourceType), 'MissingXResourceType,', ''),\n iff(PricingCategory == 'Standard' and isnotempty(CommitmentDiscountId) and ChargeCategory == 'Usage', 'PricingCategoryShouldBeCommitted,', ''),\n iff(x_SkuTerm == '1Year' or x_SkuTerm == '3Years' or x_SkuTerm == '5Years', 'SkuTermShouldBeAnInteger,', '')\n ))\n //\n // Fix columns needed in other changes\n | extend ProviderName = case(\n isnotempty(ProviderName), ProviderName,\n isnotempty(coalesce(x_CostCategories, x_Discount, x_Operation, x_ServiceCode, x_UsageType)), 'AWS',\n isnotempty(coalesce(tostring(UsageAmount), tostring(x_Cost), x_Credits, x_CostType, tostring(x_CurrencyConversionRate), tostring(x_ExportTime), x_Project, x_ServiceId)), 'GCP',\n isnotempty(coalesce(x_BillingProfileId, x_InvoiceSectionId)), 'Microsoft',\n ''\n )\n //\n // Identify source\n | extend x_SourceName = coalesce(x_SourceName, iff(isnotempty(x_BillingProfileId), 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(isnotempty(x_BillingProfileId), 'FocusCost', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, case(\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)) and isempty(SkuPriceDetails) and isnotempty(x_SkuDetails), '1.2-preview',\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)), '1.2',\n isnotempty(coalesce(ChargeClass, CommitmentDiscountStatus, tostring(ConsumedQuantity), ConsumedUnit, tostring(ContractedCost), tostring(ContractedUnitPrice), RegionId, RegionName)), '1.0',\n isnotempty(coalesce(ChargeSubcategory, Region, tostring(UsageQuantity), UsageUnit)), iff(ProviderName == 'Microsoft', '1.0-preview(v1)', '1.0-preview'),\n ''\n ))\n // Append version check error code\n | extend x_SourceChanges = iff(x_SourceVersion == '1.0', x_SourceChanges,\n strcat(x_SourceChanges, iff(isempty(x_SourceChanges), '', ','), iff(x_SourceVersion == '', 'UnknownFocusVersion', 'LegacyFocusVersion'))\n )\n //\n // Fix quantities\n | extend PricingQuantity = case(\n PricingQuantity != 0 or (EffectiveCost == 0 and BilledCost == 0), PricingQuantity,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(EffectiveCost) and EffectiveCost != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0, EffectiveCost / x_EffectiveUnitPrice,\n PricingQuantity\n )\n | extend ConsumedQuantity = case(\n isnotempty(ConsumedQuantity) and ConsumedQuantity != 0, ConsumedQuantity,\n ChargeCategory == 'Usage', PricingQuantity / coalesce(x_PricingBlockSize, decimal(1)),\n ConsumedQuantity\n )\n //\n // Populate missing prices -- mapping to on-demand prices requires meter ID and offer ID\n | extend tmp_MissingPrices = ProviderName == 'Microsoft'\n and (ListUnitPrice == 0 or ContractedUnitPrice == 0)\n and x_EffectiveUnitPrice != 0\n and not(CommitmentDiscountCategory == 'Spend' and CommitmentDiscountStatus == 'Unused')\n and isnotempty(x_SkuMeterId) and isnotempty(x_SkuOfferId)\n | as allCosts\n | where tmp_MissingPrices\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(ChargePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | as costsWithMissingPrices\n | join kind=leftouter (\n Prices_final_v1_0\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(x_EffectivePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | where x_SkuPriceType == 'Consumption' and tmp_ReservationPriceLookupKey in ((costsWithMissingPrices | summarize by tmp_ReservationPriceLookupKey))\n | summarize ListUnitPrice = min(ListUnitPrice), ContractedUnitPrice = min(ContractedUnitPrice) by tmp_ReservationPriceLookupKey, x_PricingBlockSize, PricingUnit\n ) on tmp_ReservationPriceLookupKey\n //\n // Select the best price to use for each row\n // TODO: Save values before changing -- | extend x_old_ContractedUnitPrice = ContractedUnitPrice, x_old_EffectiveUnitPrice = x_EffectiveUnitPrice, x_old_ListUnitPrice = ListUnitPrice, x_old_ListCost = ListCost, x_old_ContractedCost = ContractedCost\n | extend x_EffectiveUnitPrice = case(\n // If price is a rounding error away from the billed price, use the billed price\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001, x_BilledUnitPrice,\n // If price is a rounding error away from the contracted price, use the contracted price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001, ContractedUnitPrice,\n x_EffectiveUnitPrice\n )\n | extend ContractedUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ContractedUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ContractedUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // If billed price is available, assume the billed price is the same as contracted price to support aggregations\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, x_EffectiveUnitPrice,\n // Otherwise, assume the effective price is the same as contracted price to support aggregations\n x_EffectiveUnitPrice\n )\n | extend ListUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ListUnitPrice) and ListUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ListUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ListUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ListUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // Otherwise, assume the contracted price is the same as list price to support aggregations\n ContractedUnitPrice\n )\n // Calculate missing costs based on new prices -- If cost is already correct, keep that; if not and price is available, recalculate the cost; otherwise, keep the existing cost\n | extend ContractedCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ContractedCost) and ContractedCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedCost,\n // ContractedCost is 0 in all other scenarios...\n // If 0 and there's a billed cost and prices are the same, use BilledCost\n isnotempty(BilledCost) and BilledCost != 0 and ContractedUnitPrice == x_BilledUnitPrice, BilledCost,\n // If 0 and there's a billed cost and prices are the same, use EffectiveCost\n isnotempty(EffectiveCost) and EffectiveCost != 0 and ContractedUnitPrice == x_EffectiveUnitPrice, EffectiveCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0, ContractedUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume EffectiveCost\n isempty(ContractedUnitPrice) or ContractedUnitPrice == 0, EffectiveCost,\n // Fall back to the original value for any unhandled scenarios\n ContractedCost\n )\n | extend ListCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ListCost) and ListCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ListCost,\n // ListCost is 0 in all other scenarios...\n // If 0 and there's a contracted cost and prices are the same, use ContractedCost\n isnotempty(ContractedCost) and ContractedCost != 0 and ListUnitPrice == ContractedUnitPrice, ContractedCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ListUnitPrice) and ListUnitPrice != 0, ListUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume ContractedCost\n isempty(ListUnitPrice) or ListUnitPrice == 0, ContractedCost,\n // Fall back to the original value for any unhandled scenarios\n ListCost\n )\n // Merge the rest of the unmodified cost records and remove excess columns\n | union (allCosts | where not(tmp_MissingPrices))\n | project-away x_PricingBlockSize1, PricingUnit1, ListUnitPrice1, ContractedUnitPrice1, tmp_MissingPrices, tmp_ReservationPriceLookupKey, tmp_ReservationPriceLookupKey1\n //\n // BUG: Fix ContractedCost that has bad values\n | extend ContractedCost = iff(ProviderName == 'Microsoft' and isnotempty(PricingQuantity) and isnotempty(x_PricingBlockSize) and ContractedCost != ContractedUnitPrice * PricingQuantity, ContractedUnitPrice * PricingQuantity, ContractedCost)\n //\n // Handle FOCUS 1.0-preview UsageQuantity/Unit\n | extend ConsumedQuantity = iff(ChargeCategory == 'Usage', coalesce(ConsumedQuantity, UsageQuantity, UsageAmount), todecimal(''))\n | extend ConsumedUnit = iff(ChargeCategory == 'Usage' and isnotempty(ConsumedQuantity), coalesce(ConsumedUnit, UsageUnit, 'Units'), '')\n //\n // Convert IDs to lowercase for consistency\n | extend CommitmentDiscountId = tolower(CommitmentDiscountId)\n //\n // BUG: Remove EffectiveCost for commitment discount purchases\n | extend EffectiveCost = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), decimal(0), EffectiveCost)\n | extend x_EffectiveCostInUsd = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), decimal(0), x_EffectiveCostInUsd)\n //\n // Clean up resource columns\n | extend ResourceId = case(\n isnotempty(ResourceId), ResourceId,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), CommitmentDiscountId,\n ResourceId)\n | extend ResourceName = tolower(case(\n isnotempty(ResourceName), ResourceName,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountName), CommitmentDiscountName,\n isnotempty(ResourceId), parse_resourceid(ResourceId).ResourceName,\n ResourceName))\n | extend x_ResourceType = case(\n isnotempty(x_ResourceType), x_ResourceType,\n isnotempty(ResourceId), parse_resourceid(ResourceId).x_ResourceType,\n x_ResourceType)\n | extend ResourceType = case(\n // Use existing resource type display name unless it's an internal resource type ID\n isnotempty(ResourceType) and tolower(ResourceType) != tolower(x_ResourceType) and ResourceType !contains '/', ResourceType,\n // Use CommitmentDiscountType for commitment discount purchases\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountType), CommitmentDiscountType,\n // Look up display name from internal type\n isnotempty(x_ResourceType), coalesce(resource_type(x_ResourceType).SingularDisplayName, ResourceType, x_ResourceType),\n ResourceType)\n //\n // Sort columns and apply final transforms\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId = tolower(BillingAccountId),\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEnd),\n BillingPeriodStart = startofmonth(BillingPeriodStart),\n ChargeCategory = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Credit', 'Credit',\n ChargeSubcategory == 'Refund', 'Purchase', // We are assuming purchase refunds since we don't have data to indicate usage refunds\n ChargeCategory\n ),\n ChargeClass = case(ChargeSubcategory == 'Refund', 'Correction', ChargeClass),\n ChargeDescription,\n // BUG: ChargeFrequency shows \"Usage-Based\" for monthly recurring savings plan purchases\n ChargeFrequency = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based' and ProviderName == 'Microsoft' and x_SourceVersion startswith '1.0', 'Recurring', ChargeFrequency),\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId = tolower(CommitmentDiscountId),\n CommitmentDiscountName,\n CommitmentDiscountStatus = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Used Commitment', 'Used',\n ChargeSubcategory == 'Unused Commitment', 'Unused',\n CommitmentDiscountStatus\n ),\n CommitmentDiscountType,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost = coalesce(ContractedCost, x_OnDemandCost, x_Cost),\n ContractedUnitPrice = coalesce(ContractedUnitPrice, x_OnDemandUnitPrice),\n EffectiveCost,\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory = case(\n // Handle FOCUS 1.0-preview PricingCategory values\n PricingCategory == 'On-Demand', 'Standard',\n PricingCategory == 'Commitment-Based', 'Committed',\n PricingCategory\n ),\n PricingQuantity,\n PricingUnit,\n ProviderName,\n // Handle missing PublisherName values\n PublisherName = case(PublisherName == 'Microsoft Corporation', 'Microsoft', isnotempty(PublisherName), PublisherName, x_PublisherCategory == 'Cloud Provider', ProviderName, ''),\n // Handle FOCUS 1.0-preview Region column\n RegionId = coalesce(RegionId, iff(ProviderName == 'Microsoft', replace_string(tolower(Region), ' ', ''), Region)),\n RegionName = coalesce(RegionName, Region),\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SkuId,\n SkuPriceId,\n SubAccountId,\n SubAccountName,\n SubAccountType, // Azure 1.0-preview(v1)+\n Tags = parse_json(Tags),\n x_AccountId, // Azure 1.0-preview(v1)+\n x_AccountName, // Azure 1.0-preview(v1)+\n x_AccountOwnerId, // Azure 1.0-preview(v1)+\n x_BilledCostInUsd, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement = case(\n ProviderName == 'Microsoft' and x_BillingAccountId == x_BillingProfileId, 'EA',\n ProviderName == 'Microsoft' and x_BillingAccountId != x_BillingProfileId, 'MCA',\n ProviderName\n ), // Hubs add-on\n x_BillingAccountId, // Azure 1.0-preview(v1)+\n x_BillingAccountName, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate, // Azure 1.0-preview(v1)+\n x_BillingProfileId, // Azure 1.0-preview(v1)+\n x_BillingProfileName, // Azure 1.0-preview(v1)+\n x_ChargeId, // Azure 1.0-preview(v1) only\n x_ContractedCostInUsd = coalesce(x_ContractedCostInUsd, x_OnDemandCostInUsd), // Azure 1.0+\n x_CostAllocationRuleName, // Azure 1.0-preview(v1)+\n x_CostCategories = parse_json(x_CostCategories), // AWS 1.0 (JSON)\n x_CostCenter, // Azure 1.0-preview(v1)+\n x_Credits = parse_json(x_Credits), // GCP Jan 2024\n x_CostType, // GCP Jan 2024\n x_CurrencyConversionRate, // GCP Jun 2024\n x_CustomerId, // Azure 1.0-preview(v1)+\n x_CustomerName, // Azure 1.0-preview(v1)+\n x_Discount = parse_json(x_Discount), // AWS 1.0 (JSON)\n x_EffectiveCostInUsd, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice, // Azure 1.0-preview(v1)+\n x_ExportTime, // GCP Jan 2024\n x_IngestionTime, // Hubs add-on\n x_InvoiceId = coalesce(InvoiceId, x_InvoiceId), // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId = case( // Azure 1.0-preview(v1)+\n x_InvoiceSectionId == '-2', '',\n x_InvoiceSectionId\n ),\n x_InvoiceSectionName = case( // Azure 1.0-preview(v1)+\n x_InvoiceSectionName == 'Unassigned', '',\n x_InvoiceSectionName\n ),\n x_ListCostInUsd, // Azure 1.0-preview(v1)+\n x_Location, // GCP Jan 2024\n x_Operation, // AWS 1.0\n x_PartnerCreditApplied, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate, // Azure 1.0-preview(v1)+\n x_PricingBlockSize, // Azure 1.0-preview(v1)+\n x_PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency), // Azure 1.0-preview(v1)+\n x_PricingSubcategory, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription, // Azure 1.0-preview(v1)+\n x_Project, // GCP Jan 2024\n x_PublisherCategory, // Azure 1.0-preview(v1)+\n x_PublisherId, // Azure 1.0-preview(v1)+\n x_ResellerId, // Azure 1.0-preview(v1)+\n x_ResellerName, // Azure 1.0-preview(v1)+\n x_ResourceGroupName = tolower(x_ResourceGroupName), // Azure 1.0-preview(v1)+\n x_ResourceType, // Azure 1.0-preview(v1)+\n x_ServiceCode, // AWS 1.0\n x_ServiceId, // GCP Jan 2024\n x_ServicePeriodEnd, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart, // Azure 1.0-preview(v1)+\n x_SkuDescription, // Azure 1.0-preview(v1)+\n x_SkuDetails = parse_json(x_SkuDetails), // Azure 1.0-preview(v1)+\n x_SkuIsCreditEligible, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory, // Azure 1.0-preview(v1)+\n x_SkuMeterId, // Azure 1.0-preview(v1)+\n x_SkuMeterName = coalesce(SkuMeter, x_SkuMeterName), // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory, // Azure 1.0-preview(v1)+\n x_SkuOfferId, // Azure 1.0-preview(v1)+\n x_SkuOrderId, // Azure 1.0-preview(v1)+\n x_SkuOrderName, // Azure 1.0-preview(v1)+\n x_SkuPartNumber, // Azure 1.0-preview(v1)+\n x_SkuRegion, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily, // Azure 1.0-preview(v1)+\n x_SkuTerm, // Azure 1.0-preview(v1)+\n x_SkuTier, // Azure 1.0-preview(v1)+\n x_SourceChanges, // Hubs add-on\n x_SourceName, // Hubs add-on\n x_SourceProvider, // Hubs add-on\n x_SourceType, // Hubs add-on\n x_SourceVersion, // Hubs add-on\n x_UsageType // AWS 1.0\n}\n\n// Costs_final_v1_0 table\n.create-merge table Costs_final_v1_0 (\n AvailabilityZone: string,\n BilledCost: decimal,\n BillingAccountId: string,\n BillingAccountName: string,\n BillingAccountType: string, // Azure 1.0-preview(v1)+\n BillingCurrency: string,\n BillingPeriodEnd: datetime,\n BillingPeriodStart: datetime,\n ChargeCategory: string,\n ChargeClass: string,\n ChargeDescription: string,\n ChargeFrequency: string,\n ChargePeriodEnd: datetime,\n ChargePeriodStart: datetime,\n CommitmentDiscountCategory: string, // FOCUS 1.0-preview only\n CommitmentDiscountId: string,\n CommitmentDiscountName: string,\n CommitmentDiscountStatus: string,\n CommitmentDiscountType: string,\n ConsumedQuantity: decimal,\n ConsumedUnit: string,\n ContractedCost: decimal,\n ContractedUnitPrice: decimal,\n EffectiveCost: decimal,\n InvoiceIssuerName: string,\n ListCost: decimal,\n ListUnitPrice: decimal,\n PricingCategory: string,\n PricingQuantity: decimal,\n PricingUnit: string,\n ProviderName: string,\n PublisherName: string,\n RegionId: string,\n RegionName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n ServiceCategory: string,\n ServiceName: string,\n SkuId: string,\n SkuPriceId: string,\n SubAccountId: string,\n SubAccountName: string,\n SubAccountType: string,\n Tags: dynamic,\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_BilledCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: decimal, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: decimal, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_ContractedCostInUsd: decimal, // Azure 1.0+\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: dynamic, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_Credits: dynamic, // GCP Jan 2024\n x_CostType: string, // GCP Jan 2024\n x_CurrencyConversionRate: decimal, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: dynamic, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: decimal, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024\n x_IngestionTime: datetime, // Hubs add-on\n x_InvoiceId: string, // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_Operation: string, // AWS 1.0\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: decimal, // Azure 1.0-preview(v1)+\n x_PricingCurrency: string, // Azure 1.0-preview(v1)+\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: dynamic, // Azure 1.0-preview(v1)+\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterName: string, // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceChanges: string, // Hubs add-on\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_UsageType: string // AWS 1.0\n)\n\n// Update policy for Costs_raw -> Costs_final_v1_0 table\n.alter table Costs_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Costs_raw\",\n \"Query\": \"Costs_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Actual costs |===================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: ActualCost exports transformed to FOCUS 1.0. Use ActualCosts_transform_v1_2() instead.', folder='Costs')\nActualCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n // TODO: Transform actual costs to FOCUS 1.0 format\n ActualCosts_raw\n | where ChargeType in ('Purchase', 'Refund') and isnotempty(ReservationId)\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: ServiceSubcategory, PublisherName, x_PublisherCategory, x_Environment, x_ServiceModel\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodStart = Date,\n ChargePeriodEnd = Date + 1d,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = '',\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory = '',\n SkuId = '',\n SkuMeter = '',\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = SubscriptionName,\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentName = '',\n x_ComponentType = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel = '',\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for ActualCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": false,\n \"Source\": \"ActualCosts_raw\",\n \"Query\": \"ActualCosts_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Amortized costs |================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: ActualCost exports transformed to FOCUS 1.0. Use AmortizedCosts_transform_v1_2() instead.', folder='Costs')\nAmortizedCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n // TODO: Transform actual costs to FOCUS 1.0 format\n AmortizedCosts_raw\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: ServiceSubcategory, PublisherName, x_PublisherCategory, x_Environment, x_ServiceModel\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodStart = Date,\n ChargePeriodEnd = Date + 1d,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = '',\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory = '',\n SkuId = '',\n SkuMeter = '',\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = SubscriptionName,\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentName = '',\n x_ComponentType = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel = '',\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for AmortizedCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": false,\n \"Source\": \"AmortizedCosts_raw\",\n \"Query\": \"AmortizedCosts_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All commitment discount usage transformed to FOCUS 1.0. This includes reservationdeatils_raw. Use CommitmentDiscountUsage_transform_v1_2() instead.', folder='Commitment discounts')\nCommitmentDiscountUsage_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n CommitmentDiscountUsage_raw\n //\n // Change real to decimal\n | extend\n InstanceFlexibilityRatio = todecimal(InstanceFlexibilityRatio),\n ReservedHours = todecimal(ReservedHours),\n TotalReservedQuantity = todecimal(TotalReservedQuantity),\n UsedHours = todecimal(UsedHours)\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Handle resource columns\n | extend ResourceId = tolower(InstanceId)\n | extend tmp_ResourceDetails = parse_resourceid(ResourceId)\n | extend ResourceName = tostring(tmp_ResourceDetails.ResourceName)\n | extend SubAccountId = tostring(tmp_ResourceDetails.SubAccountId)\n | extend x_ResourceGroupName = tostring(tmp_ResourceDetails.x_ResourceGroupName)\n | extend x_ResourceType = tostring(tmp_ResourceDetails.x_ResourceType)\n | lookup kind=leftouter (ResourceTypes | distinct x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n | lookup kind=leftouter (Services | distinct x_ResourceType, ServiceName, ServiceCategory, x_ServiceModel) on x_ResourceType\n //\n // Sort columns and apply final transforms\n | project\n ChargePeriodEnd = UsageDate + 1d,\n ChargePeriodStart = UsageDate,\n CommitmentDiscountCategory = 'Usage',\n CommitmentDiscountId = tolower(strcat('/providers/microsoft.capacity/reservationorders/', ReservationOrderId, '/reservations/', ReservationId)),\n CommitmentDiscountType = 'Reservation',\n ConsumedQuantity = UsedHours,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SubAccountId,\n x_CommitmentDiscountCommittedCount = TotalReservedQuantity,\n x_CommitmentDiscountCommittedAmount = ReservedHours,\n // TODO: Is this needed? -- x_CommitmentDiscountKind = Kind,\n x_CommitmentDiscountNormalizedGroup = iff(InstanceFlexibilityGroup == 'NA', '', InstanceFlexibilityGroup),\n x_CommitmentDiscountNormalizedRatio = InstanceFlexibilityRatio,\n x_CommitmentDiscountQuantity = UsedHours * InstanceFlexibilityRatio,\n x_IngestionTime = ingestion_time(),\n x_ResourceGroupName,\n x_ResourceType,\n // x_RowId = hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // CommitmentDiscountId,\n // ResourceId,\n // ChargePeriodStart\n // )),\n x_ServiceModel,\n x_SkuOrderId = ReservationOrderId,\n x_SkuSize = iff(SkuName == 'NA', '', SkuName),\n x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName)),\n x_SourceProvider = coalesce(x_SourceProvider, ProviderName),\n x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationDetails', '')),\n x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2024-03-01', ''))\n}\n\n// CommitmentDiscountUsage_final_v1_0 table\n.create-merge table CommitmentDiscountUsage_final_v1_0 (\n ChargePeriodEnd: datetime, // Hubs add-on\n ChargePeriodStart: datetime, // MS 2023-03-01\n CommitmentDiscountCategory: string, // Hubs add-on\n CommitmentDiscountId: string, // MS 2023-03-01\n CommitmentDiscountType: string, // Hubs add-on\n ConsumedQuantity: decimal, // MS 2023-03-01\n ProviderName: string, // Hubs add-on\n ResourceId: string, // MS 2023-03-01\n ResourceName: string, // Hubs add-on\n ResourceType: string, // Hubs add-on\n ServiceCategory: string, // Hubs add-on\n ServiceName: string, // Hubs add-on\n SubAccountId: string, // Hubs add-on\n x_CommitmentDiscountCommittedCount: decimal, // MS 2023-03-01\n x_CommitmentDiscountCommittedAmount: decimal, // MS 2023-03-01\n x_CommitmentDiscountNormalizedGroup: string, // MS 2023-03-01\n x_CommitmentDiscountNormalizedRatio: decimal, // MS 2023-03-01\n x_CommitmentDiscountQuantity: decimal, // MS 2023-03-01\n x_IngestionTime: datetime, // Hubs add-on\n x_ResourceGroupName: string, // Hubs add-on\n x_ResourceType: string, // Hubs add-on\n x_ServiceModel: string, // Hubs add-on\n x_SkuOrderId: string, // MS 2023-03-01\n x_SkuSize: string, // MS 2023-03-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string // Hubs add-on\n)\n\n// Update policy for CommitmentDiscountUsage_raw -> CommitmentDiscountUsage_final_v1_0 table\n.alter table CommitmentDiscountUsage_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"CommitmentDiscountUsage_raw\",\n \"Query\": \"CommitmentDiscountUsage_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All recommendations transformed to FOCUS 1.0. Use Recommendations_transform_v1_2() instead.', folder='Recommendations')\nRecommendations_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Recommendations_raw\n //\n // Change real to decimal\n | extend\n CostWithNoReservedInstances = todecimal(CostWithNoReservedInstances),\n InstanceFlexibilityRatio = todecimal(InstanceFlexibilityRatio),\n NetSavings = todecimal(NetSavings),\n RecommendedQuantity = todecimal(RecommendedQuantity),\n RecommendedQuantityNormalized = todecimal(RecommendedQuantityNormalized),\n TotalCostWithReservedInstances = todecimal(TotalCostWithReservedInstances)\n //\n | extend x_IngestionTime = ingestion_time()\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationRecommendations', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Convert JSON cost columns to decimal\n | extend CostWithNoReservedInstances = case(isnotempty(CostWithNoReservedInstances), CostWithNoReservedInstances, isnotempty(CostWithNoReservedInstancesJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, CostWithNoReservedInstancesJson)), CostWithNoReservedInstances)\n | extend NetSavings = case(isnotempty(NetSavings), NetSavings, isnotempty(NetSavingsJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, NetSavingsJson)), NetSavings)\n | extend TotalCostWithReservedInstances = case(isnotempty(TotalCostWithReservedInstances), TotalCostWithReservedInstances, isnotempty(TotalCostWithReservedInstancesJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, TotalCostWithReservedInstancesJson)), TotalCostWithReservedInstances)\n //\n // Build recommendation details\n | lookup kind=leftouter (Regions | summarize RegionName = make_set(RegionName)[0] by Location = RegionId) on Location\n | extend x_RecommendationDetails = case(\n x_SourceType == 'ReservationRecommendations', bag_pack(\n 'CommitmentDiscountNormalizedGroup', InstanceFlexibilityGroup,\n 'CommitmentDiscountNormalizedRatio', InstanceFlexibilityRatio,\n 'CommitmentDiscountNormalizedSize', NormalizedSize,\n 'CommitmentDiscountResourceType', ResourceType,\n 'CommitmentDiscountScope', Scope,\n 'LookbackPeriodDuration', case(\n LookBackPeriod matches regex @'^Last([0-9]+)Days$', replace_regex(LookBackPeriod, @'^Last([0-9]+)Days$', @'P\\1D'),\n LookBackPeriod matches regex @'^[0-9]+$', strcat('P', LookBackPeriod, 'D'),\n ''\n ),\n 'LookbackPeriodStart', FirstUsageDate,\n 'RecommendedQuantity', RecommendedQuantity,\n 'RecommendedQuantityNormalized', RecommendedQuantityNormalized,\n 'RegionId', Location,\n 'RegionName', RegionName,\n 'SkuMeterId', MeterId,\n 'SkuPriceDetails', SkuProperties,\n 'SkuSize', coalesce(SKU, SkuName),\n 'SkuTerm', isoMonths(Term)\n ),\n dynamic({})\n )\n //\n // Sort columns and apply final transforms\n | extend x_RecommendationDate = FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d)\n | extend x_RecommendationDate = iff(x_RecommendationDate > now(), startofday(now()), x_RecommendationDate)\n | project\n ProviderName,\n SubAccountId = iff(isnotempty(SubscriptionId), strcat('/subscriptions/', SubscriptionId), ''),\n x_IngestionTime,\n x_EffectiveCostAfter = TotalCostWithReservedInstances,\n x_EffectiveCostBefore = CostWithNoReservedInstances,\n x_EffectiveCostSavings = NetSavings,\n x_RecommendationDate = FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d),\n x_RecommendationDetails,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n// Recommendations_final_v1_0 table\n.create-merge table Recommendations_final_v1_0 (\n ProviderName: string,\n SubAccountId: string,\n x_IngestionTime: datetime,\n x_EffectiveCostAfter: decimal,\n x_EffectiveCostBefore: decimal,\n x_EffectiveCostSavings: decimal,\n x_RecommendationDate: datetime,\n x_RecommendationDetails: dynamic,\n x_SourceName: string,\n x_SourceProvider: string,\n x_SourceType: string,\n x_SourceVersion: string\n)\n\n// Update policy for Recommendations_raw -> Recommendations_final_v1_0 table\n.alter table Recommendations_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Recommendations_raw\",\n \"Query\": \"Recommendations_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All transactions transformed to FOCUS 1.0. Use Transactions_transform_v1_2() instead.', folder='Transactions')\nTransactions_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Transactions_raw\n //\n // Change real to decimal\n | extend\n Amount = todecimal(Amount),\n MonetaryCommitment = todecimal(MonetaryCommitment),\n Overage = todecimal(Overage),\n Quantity = todecimal(Quantity)\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationTransactions', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Handle BillingPeriodStart/End\n | extend BillingMonth = tostring(BillingMonth)\n | extend BillingPeriodStart = iff(isempty(BillingMonth), datetime(null), todatetime(strcat(substring(BillingMonth, 0, 4), \"-\", substring(BillingMonth, 4, 2), \"-\", substring(BillingMonth, 6, 2))))\n | extend BillingPeriodEnd = iff(isempty(BillingMonth), datetime(null), startofmonth(endofmonth(BillingPeriodStart) + 1d))\n //\n // Sort columns and apply final transforms\n | project\n BilledCost = Amount,\n BillingAccountId = case(\n BillingProfileId startswith '/', BillingProfileId,\n isnotempty(CurrentEnrollmentId), strcat('/providers/Microsoft.Billing/billingAccounts/', CurrentEnrollmentId),\n isnotempty(BillingProfileId), strcat('/providers/Microsoft.Billing/billingProfiles/', BillingProfileId),\n ''\n ),\n BillingAccountName = coalesce(BillingProfileName, CurrentEnrollmentId),\n BillingCurrency = Currency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory = case(\n EventType in ('Cancel', 'Purchase', 'Refund'), 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = case(\n EventType == 'Cancel', 'Cancel', // FOCUS does not handle this scenario\n EventType == 'Refund', 'Correction',\n ''\n ),\n ChargeDescription = Description,\n ChargeFrequency = case(\n BillingFrequency == 'OneTime', 'One-Time',\n BillingFrequency == 'Recurring', 'Recurring',\n BillingFrequency\n ),\n ChargePeriodStart = EventDate,\n PricingQuantity = Quantity,\n PricingUnit = 'Reservations',\n ProviderName,\n RegionId = Region,\n RegionName = Region,\n SubAccountId = iff(isempty(PurchasingSubscriptionGuid), '', strcat('/subscriptions/', PurchasingSubscriptionGuid)),\n SubAccountName = iff(isempty(PurchasingSubscriptionGuid), '', PurchasingSubscriptionName),\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerEmail,\n x_CostCenter = CostCenter,\n x_InvoiceId = InvoiceId,\n x_InvoiceNumber = Invoice,\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = coalesce(InvoiceSectionName, DepartmentName),\n x_IngestionTime = ingestion_time(),\n x_MonetaryCommitment = MonetaryCommitment,\n x_Overage = Overage,\n x_PurchasingBillingAccountId = PurchasingEnrollment,\n x_SkuOrderId = ReservationOrderId,\n x_SkuOrderName = ReservationOrderName,\n x_SkuSize = ArmSkuName,\n x_SkuTerm = isoMonths(Term),\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId = PurchasingSubscriptionGuid,\n x_TransactionType = EventType\n}\n\n// Transactions_final_v1_0 table\n.create-merge table Transactions_final_v1_0 (\n BilledCost: decimal, // MS CM EA+MCA 2023-05-01\n BillingAccountId: string, // MS CM EA+MCA 2023-05-01\n BillingAccountName: string, // MS CM EA+MCA 2023-05-01\n BillingCurrency: string, // MS CM EA+MCA 2023-05-01\n BillingPeriodEnd: datetime, // MS CM EA+MCA 2023-05-01\n BillingPeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n ChargeCategory: string, // Hubs add-on\n ChargeClass: string, // Hubs add-on\n ChargeDescription: string, // MS CM EA+MCA 2023-05-01\n ChargeFrequency: string, // MS CM EA+MCA 2023-05-01\n ChargePeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n PricingQuantity: decimal, // MS CM EA+MCA 2023-05-01\n PricingUnit: string, // Hubs add-on\n ProviderName: string, // Hubs add-on\n RegionId: string, // MS CM EA+MCA 2023-05-01\n RegionName: string, // MS CM EA+MCA 2023-05-01\n SubAccountId: string, // MS CM EA+MCA 2023-05-01\n SubAccountName: string, // MS CM EA+MCA 2023-05-01\n x_AccountName: string, // MS CM EA 2023-05-01\n x_AccountOwnerId: string, // MS CM EA 2023-05-01\n x_CostCenter: string, // MS CM EA 2023-05-01\n x_InvoiceId: string, // MS CM MCA 2023-05-01\n x_InvoiceNumber: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionId: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionName: string, // MS CM MCA 2023-05-01\n x_IngestionTime: datetime, // Hubs add-on\n x_MonetaryCommitment: decimal, // MS CM EA 2023-05-01\n x_Overage: decimal, // MS CM EA 2023-05-01\n x_PurchasingBillingAccountId: string, // MS CM EA 2023-05-01\n x_SkuOrderId: string, // MS CM EA+MCA 2023-05-01\n x_SkuOrderName: string, // MS CM EA+MCA 2023-05-01\n x_SkuSize: string, // MS CM EA+MCA 2023-05-01\n x_SkuTerm: int, // MS CM EA+MCA 2023-05-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubscriptionId: string, // MS CM EA+MCA 2023-05-01\n x_TransactionType: string // MS CM EA+MCA 2023-05-01\n)\n\n// Update policy for Transactions_raw -> Transactions_final_v1_0 table\n.alter table Transactions_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Transactions_raw\",\n \"Query\": \"Transactions_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n", "HUB_DATA_EXPLORER": "hubDataExplorer", "HUB_DB": "Hub", "INGESTION_DB": "Ingestion", From 15a8bc10c11bb7fa250f51aaba0ef3fe85f3fa89 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 26 May 2026 06:49:59 +0000 Subject: [PATCH 4/6] Address PR feedback: revert deploy JSON edits and update changelog --- docs-mslearn/toolkit/changelog.md | 3 ++- docs/deploy/finops-hub-14.0.json | 4 ++-- docs/deploy/finops-hub-latest.json | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs-mslearn/toolkit/changelog.md b/docs-mslearn/toolkit/changelog.md index 66419e6ba..679fb934a 100644 --- a/docs-mslearn/toolkit/changelog.md +++ b/docs-mslearn/toolkit/changelog.md @@ -3,7 +3,7 @@ title: FinOps toolkit changelog description: Review the latest features and enhancements in the FinOps toolkit, including updates to FinOps hubs, Power BI reports, and more. author: MSBrett ms.author: brettwil -ms.date: 05/14/2026 +ms.date: 05/26/2026 ms.topic: reference ms.service: finops ms.subservice: finops-toolkit @@ -80,6 +80,7 @@ _Released April 2026_ - Fixed incorrect Azure China ADX DNS suffix (`kusto.chinacloudapi.cn` → `kusto.windows.cn`) ([#2081](https://github.com/microsoft/finops-toolkit/pull/2081)). - Fixed `createUiDefinition.json` storage URL validation to accept sovereign cloud storage suffixes ([#2081](https://github.com/microsoft/finops-toolkit/pull/2081)). - Fixed `gitapp.hub.com` typo in ADF linked service URL ([#2081](https://github.com/microsoft/finops-toolkit/pull/2081)). + - Fixed Data Factory ingestion memory pressure by replacing `isnotempty(strcat(x_SkuMeterId, x_SkuOfferId))` with separate `isnotempty()` checks in FinOps hub ingestion scripts so temporary concatenated strings are no longer allocated during emptiness filtering. - Fixed Init-DataFactory deployment script failing when an Event Grid subscription is already provisioning by checking subscription status before attempting subscribe/unsubscribe and polling separately for completion ([#1996](https://github.com/microsoft/finops-toolkit/issues/1996)). - Fixed `msexports_ExecuteETL` pipeline failing on empty export files by adding a row count check ([#1535](https://github.com/microsoft/finops-toolkit/issues/1535)). - Fixed Data Explorer dashboard cost and savings KPIs producing invalid sums in multi-billing-currency tenants by adding a Currency parameter that scopes tile queries to a single currency ([#2093](https://github.com/microsoft/finops-toolkit/issues/2093)). diff --git a/docs/deploy/finops-hub-14.0.json b/docs/deploy/finops-hub-14.0.json index f90016f65..f9d71a4ab 100644 --- a/docs/deploy/finops-hub-14.0.json +++ b/docs/deploy/finops-hub-14.0.json @@ -18320,7 +18320,7 @@ "variables": { "$fxv#0": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n.create-or-alter function \nwith (docstring = 'Return details about the specified ID.', folder = 'OpenData/Internal')\n_resource_type_1(id: string) {\n dynamic({\n \"arizeai.observabilityeval/organizations\": { \"SingularDisplayName\": \"Azure Native Arize AI Cloud Service\" }\n ,\"astronomer.astro/organizations\": { \"SingularDisplayName\": \"Astro Organization\" }\n ,\"citrix.services/xenappessentials\": { \"SingularDisplayName\": \"Citrix Virtual Apps Essentials\" }\n ,\"citrix.services/xendesktopessentials\": { \"SingularDisplayName\": \"Citrix Virtual Desktops Essentials\" }\n ,\"commvault.contentstore/cloudaccounts\": { \"SingularDisplayName\": \"Commvault Cloud Account\" }\n ,\"commvault.contentstore/cloudaccounts/plans\": { \"SingularDisplayName\": \"Commvault.ContentStore cloud accounts plan\" }\n ,\"commvault.contentstore/cloudaccounts/protectiongroups\": { \"SingularDisplayName\": \"Commvault.ContentStore cloud accounts protection group\" }\n ,\"commvault.contentstore/cloudaccounts/protectiongroups/protecteditems\": { \"SingularDisplayName\": \"Commvault.ContentStore cloud accounts protection groups protected item\" }\n ,\"commvault.contentstore/cloudaccounts/storages\": { \"SingularDisplayName\": \"Commvault.ContentStore cloud accounts storage\" }\n ,\"dell.storage/filesystems\": { \"SingularDisplayName\": \"Dell PowerScale\" }\n ,\"dynatrace.observability/monitors\": { \"SingularDisplayName\": \"Dynatrace\" }\n ,\"github.network/networksettings\": { \"SingularDisplayName\": \"GitHub.Network network setting\" }\n ,\"informatica.datamanagement/organizations\": { \"SingularDisplayName\": \"Informatica Organization\" }\n ,\"lambdatest.hyperexecute/organizations\": { \"SingularDisplayName\": \"Azure Native LambdaTest - HyperExecute Cloud Service\" }\n ,\"microsoft.aad/domainservices\": { \"SingularDisplayName\": \"Microsoft Entra Domain Services\" }\n ,\"microsoft.aadiam/diagnosticsettings\": { \"SingularDisplayName\": \"Microsoft.aadiam diagnostic setting\" }\n ,\"microsoft.aadiam/privatelinkforazuread\": { \"SingularDisplayName\": \"Private Link for Microsoft Entra ID\" }\n ,\"microsoft.advisor/advisorscore\": { \"SingularDisplayName\": \"Microsoft.Advisor advisor score\" }\n ,\"microsoft.advisor/assessments\": { \"SingularDisplayName\": \"Microsoft.Advisor assessment\" }\n ,\"microsoft.advisor/configurations\": { \"SingularDisplayName\": \"Microsoft.Advisor configuration\" }\n ,\"microsoft.advisor/generaterecommendations\": { \"SingularDisplayName\": \"Microsoft.Advisor generate recommendation\" }\n ,\"microsoft.advisor/metadata\": { \"SingularDisplayName\": \"Microsoft.Advisor metadata\" }\n ,\"microsoft.advisor/recommendations\": { \"SingularDisplayName\": \"Microsoft.Advisor recommendation\" }\n ,\"microsoft.advisor/recommendations/suppressions\": { \"SingularDisplayName\": \"Microsoft.Advisor recommendations suppression\" }\n ,\"microsoft.advisor/resiliencyreviews\": { \"SingularDisplayName\": \"Microsoft.Advisor resiliency review\" }\n ,\"microsoft.agfoodplatform/farmbeats\": { \"SingularDisplayName\": \"Azure Data Manager for Agriculture\" }\n ,\"microsoft.agfoodplatform/farmbeatsextensiondefinitions\": { \"SingularDisplayName\": \"Microsoft.AgFoodPlatform farm beats extension definition\" }\n ,\"microsoft.agfoodplatform/farmbeatssolutiondefinitions\": { \"SingularDisplayName\": \"Microsoft.AgFoodPlatform farm beats solution definition\" }\n ,\"microsoft.agricultureplatform/agriservices\": { \"SingularDisplayName\": \"Agriculture data solutions\" }\n ,\"microsoft.akshybrid/agentpools\": { \"SingularDisplayName\": \"Microsoft.AksHybrid agent pool\" }\n ,\"microsoft.akshybrid/provisionedclusters\": { \"SingularDisplayName\": \"Microsoft.AksHybrid provisioned cluster\" }\n ,\"microsoft.akshybrid/upgradeprofiles\": { \"SingularDisplayName\": \"Microsoft.AksHybrid upgrade profile\" }\n ,\"microsoft.alertsmanagement/actionrules\": { \"SingularDisplayName\": \"Alert processing rule\" }\n ,\"microsoft.alertsmanagement/alerts\": { \"SingularDisplayName\": \"Microsoft.AlertsManagement alert\" }\n ,\"microsoft.alertsmanagement/alerts/enrichments\": { \"SingularDisplayName\": \"Microsoft.AlertsManagement alerts enrichment\" }\n ,\"microsoft.alertsmanagement/prometheusrulegroups\": { \"SingularDisplayName\": \"Prometheus rule group\" }\n ,\"microsoft.alertsmanagement/smartdetectoralertrules\": { \"SingularDisplayName\": \"Smart detector alert rule\" }\n ,\"microsoft.alertsmanagement/smartgroups\": { \"SingularDisplayName\": \"Microsoft.AlertsManagement smart group\" }\n ,\"microsoft.alertsmanagement/tenantactivitylogalerts\": { \"SingularDisplayName\": \"Microsoft.AlertsManagement tenant activity log alert\" }\n ,\"microsoft.all/arcvirtualmachines\": { \"SingularDisplayName\": \"Azure Arc virtual machine\" }\n ,\"microsoft.all/hcivirtualmachines\": { \"SingularDisplayName\": \"Azure Local Virtual Machine - Azure Arc\" }\n ,\"microsoft.all/virtualmachines\": { \"SingularDisplayName\": \"Virtual machine\" }\n ,\"microsoft.analysisservices/servers\": { \"SingularDisplayName\": \"Analysis Services server\" }\n ,\"microsoft.anybuild/clusters\": { \"SingularDisplayName\": \"AnyBuild cluster\" }\n ,\"microsoft.apicenter/deletedservices\": { \"SingularDisplayName\": \"Microsoft.ApiCenter deleted service\" }\n ,\"microsoft.apicenter/services\": { \"SingularDisplayName\": \"API Center\" }\n ,\"microsoft.apicenter/services/workspaces\": { \"SingularDisplayName\": \"Workspace\" }\n ,\"microsoft.apimanagement/gateways\": { \"SingularDisplayName\": \"API Management gateway\" }\n ,\"microsoft.apimanagement/gateways/configconnections\": { \"SingularDisplayName\": \"Microsoft.ApiManagement gateways config connection\" }\n ,\"microsoft.apimanagement/service\": { \"SingularDisplayName\": \"API Management service\" }\n ,\"microsoft.apimanagement/service/workspaces\": { \"SingularDisplayName\": \"Workspace\" }\n ,\"microsoft.apisecurity/defendersettings\": { \"SingularDisplayName\": \"Microsoft.ApiSecurity defender setting\" }\n ,\"microsoft.app/agents\": { \"SingularDisplayName\": \"SRE Agent\" }\n ,\"microsoft.app/builders\": { \"SingularDisplayName\": \"Microsoft.App builder\" }\n ,\"microsoft.app/builders/builds\": { \"SingularDisplayName\": \"Microsoft.App builders build\" }\n ,\"microsoft.app/connectedenvironments\": { \"SingularDisplayName\": \"Container Apps Connected Environment\" }\n ,\"microsoft.app/containerapps\": { \"SingularDisplayName\": \"Container App\" }\n ,\"microsoft.app/jobs\": { \"SingularDisplayName\": \"Container App Job\" }\n ,\"microsoft.app/logicapps\": { \"SingularDisplayName\": \"Logic app\" }\n ,\"microsoft.app/logicapps/workflows\": { \"SingularDisplayName\": \"Logic app workflow\" }\n ,\"microsoft.app/managedenvironments\": { \"SingularDisplayName\": \"Container Apps Environment\" }\n ,\"microsoft.app/sessionpools\": { \"SingularDisplayName\": \"Container App Session Pool\" }\n ,\"microsoft.app/spaces\": { \"SingularDisplayName\": \"App Space\" }\n ,\"microsoft.appassessment/migrateprojects\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate project\" }\n ,\"microsoft.appassessment/migrateprojects/assessments\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects assessment\" }\n ,\"microsoft.appassessment/migrateprojects/assessments/assessedapplications\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects assessments assessed application\" }\n ,\"microsoft.appassessment/migrateprojects/assessments/assessedmachines\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects assessments assessed machine\" }\n ,\"microsoft.appassessment/migrateprojects/assessments/machinestoassess\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects assessments machines to asses\" }\n ,\"microsoft.appassessment/migrateprojects/sites\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects site\" }\n ,\"microsoft.appassessment/migrateprojects/sites/applianceconfigurations\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects sites appliance configuration\" }\n ,\"microsoft.appcomplianceautomation/reports\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation report\" }\n ,\"microsoft.appcomplianceautomation/reports/evidences\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports evidence\" }\n ,\"microsoft.appcomplianceautomation/reports/scopingconfigurations\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports scoping configuration\" }\n ,\"microsoft.appcomplianceautomation/reports/snapshots\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports snapshot\" }\n ,\"microsoft.appcomplianceautomation/reports/snapshots/controls\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports snapshots control\" }\n ,\"microsoft.appcomplianceautomation/reports/webhooks\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports webhook\" }\n ,\"microsoft.appconfiguration/configurationstores\": { \"SingularDisplayName\": \"App Configuration\" }\n ,\"microsoft.applicationmigration/discoveryhubs\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration discovery hub\" }\n ,\"microsoft.applicationmigration/discoveryhubs/applications\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration discovery hubs application\" }\n ,\"microsoft.applicationmigration/discoveryhubs/applications/members\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration discovery hubs applications member\" }\n ,\"microsoft.applicationmigration/pgsqlsites\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration pgsqlsite\" }\n ,\"microsoft.applicationmigration/pgsqlsites/agents\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration pgsqlsites agent\" }\n ,\"microsoft.applicationmigration/pgsqlsites/pgsqldatabases\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration pgsqlsites pgsqldatabase\" }\n ,\"microsoft.applicationmigration/pgsqlsites/pgsqlinstances\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration pgsqlsites pgsqlinstance\" }\n ,\"microsoft.appplatform/spring\": { \"SingularDisplayName\": \"Azure Spring Apps\" }\n ,\"microsoft.appsecurity/appprotectmanagedrulesetmanifests\": { \"SingularDisplayName\": \"Microsoft.AppSecurity app protect managed rule set manifest\" }\n ,\"microsoft.appsecurity/policies\": { \"SingularDisplayName\": \"App Protect Policy\" }\n ,\"microsoft.arc/all\": { \"SingularDisplayName\": \"Azure Arc enabled resource\" }\n ,\"microsoft.arc/allfairfax\": { \"SingularDisplayName\": \"Azure Arc enabled resource\" }\n ,\"microsoft.arc/kubernetesresources\": { \"SingularDisplayName\": \"Azure Arc Kubernetes cluster\" }\n ,\"microsoft.arc/kubernetesresourcesfairfax\": { \"SingularDisplayName\": \"Azure Arc Kubernetes cluster\" }\n ,\"microsoft.arcnetworking/arcnwloadbalancers\": { \"SingularDisplayName\": \"Microsoft.ArcNetworking arc nw load balancer\" }\n ,\"microsoft.aszlabhardware/labservers\": { \"SingularDisplayName\": \"Microsoft.AszLabHardware labserver\" }\n ,\"microsoft.aszlabhardware/reservations\": { \"SingularDisplayName\": \"Microsoft.AszLabHardware reservation\" }\n ,\"microsoft.aszlabhardware/reservations/servers\": { \"SingularDisplayName\": \"Microsoft.AszLabHardware reservations server\" }\n ,\"microsoft.aszlabhardware/servers\": { \"SingularDisplayName\": \"Microsoft.AszLabHardware server\" }\n ,\"microsoft.attestation/attestationproviders\": { \"SingularDisplayName\": \"Attestation provider\" }\n ,\"microsoft.authorization/accessreviewhistorydefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization access review history definition\" }\n ,\"microsoft.authorization/accessreviewscheduledefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization access review schedule definition\" }\n ,\"microsoft.authorization/accessreviewscheduledefinitions/instances\": { \"SingularDisplayName\": \"Microsoft.Authorization access review schedule definitions instance\" }\n ,\"microsoft.authorization/accessreviewscheduledefinitions/instances/decisions\": { \"SingularDisplayName\": \"Microsoft.Authorization access review schedule definitions instances decision\" }\n ,\"microsoft.authorization/accessreviewschedulesettings\": { \"SingularDisplayName\": \"Microsoft.Authorization access review schedule setting\" }\n ,\"microsoft.authorization/datapolicymanifests\": { \"SingularDisplayName\": \"Microsoft.Authorization data policy manifest\" }\n ,\"microsoft.authorization/denyassignments\": { \"SingularDisplayName\": \"Microsoft.Authorization deny assignment\" }\n ,\"microsoft.authorization/locks\": { \"SingularDisplayName\": \"Microsoft.Authorization lock\" }\n ,\"microsoft.authorization/policyassignments\": { \"SingularDisplayName\": \"Microsoft.Authorization policy assignment\" }\n ,\"microsoft.authorization/policydefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy definition\" }\n ,\"microsoft.authorization/policydefinitions/versions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy definitions version\" }\n ,\"microsoft.authorization/policyexemptions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy exemption\" }\n ,\"microsoft.authorization/policysetdefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy set definition\" }\n ,\"microsoft.authorization/policysetdefinitions/versions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy set definitions version\" }\n ,\"microsoft.authorization/privatelinkassociations\": { \"SingularDisplayName\": \"Microsoft.Authorization private link association\" }\n ,\"microsoft.authorization/provideroperations\": { \"SingularDisplayName\": \"Microsoft.Authorization provider operation\" }\n ,\"microsoft.authorization/resourcemanagementprivatelinks\": { \"SingularDisplayName\": \"Resource management private link\" }\n ,\"microsoft.authorization/roleassignmentapprovals\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment approval\" }\n ,\"microsoft.authorization/roleassignmentapprovals/stages\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment approvals stage\" }\n ,\"microsoft.authorization/roleassignments\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment\" }\n ,\"microsoft.authorization/roleassignmentscheduleinstances\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment schedule instance\" }\n ,\"microsoft.authorization/roleassignmentschedulerequests\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment schedule request\" }\n ,\"microsoft.authorization/roleassignmentschedules\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment schedule\" }\n ,\"microsoft.authorization/roledefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization role definition\" }\n ,\"microsoft.authorization/roleeligibilityscheduleinstances\": { \"SingularDisplayName\": \"Microsoft.Authorization role eligibility schedule instance\" }\n ,\"microsoft.authorization/roleeligibilityschedulerequests\": { \"SingularDisplayName\": \"Microsoft.Authorization role eligibility schedule request\" }\n ,\"microsoft.authorization/roleeligibilityschedules\": { \"SingularDisplayName\": \"Microsoft.Authorization role eligibility schedule\" }\n ,\"microsoft.authorization/rolemanagementalertconfigurations\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alert configuration\" }\n ,\"microsoft.authorization/rolemanagementalertdefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alert definition\" }\n ,\"microsoft.authorization/rolemanagementalertoperations\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alert operation\" }\n ,\"microsoft.authorization/rolemanagementalerts\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alert\" }\n ,\"microsoft.authorization/rolemanagementalerts/alertincidents\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alerts alert incident\" }\n ,\"microsoft.authorization/rolemanagementpolicies\": { \"SingularDisplayName\": \"Microsoft.Authorization role management policy\" }\n ,\"microsoft.authorization/rolemanagementpolicyassignments\": { \"SingularDisplayName\": \"Microsoft.Authorization role management policy assignment\" }\n ,\"microsoft.automanage/bestpractices\": { \"SingularDisplayName\": \"Microsoft.Automanage best practice\" }\n ,\"microsoft.automanage/bestpractices/versions\": { \"SingularDisplayName\": \"Microsoft.Automanage best practices version\" }\n ,\"microsoft.automanage/configurationprofileassignments\": { \"SingularDisplayName\": \"Microsoft.Automanage configuration profile assignment\" }\n ,\"microsoft.automanage/configurationprofileassignments/reports\": { \"SingularDisplayName\": \"Microsoft.Automanage configuration profile assignments report\" }\n ,\"microsoft.automanage/configurationprofiles\": { \"SingularDisplayName\": \"Microsoft.Automanage configuration profile\" }\n ,\"microsoft.automanage/configurationprofiles/versions\": { \"SingularDisplayName\": \"Microsoft.Automanage configuration profiles version\" }\n ,\"microsoft.automanage/serviceprincipals\": { \"SingularDisplayName\": \"ServicePrincipals\" }\n ,\"microsoft.automation/automationaccounts\": { \"SingularDisplayName\": \"Automation account\" }\n ,\"microsoft.automation/automationaccounts/hybridrunbookworkergroups\": { \"SingularDisplayName\": \"Automation hybrid worker group\" }\n ,\"microsoft.automation/automationaccounts/runbooks\": { \"SingularDisplayName\": \"Automation runbook\" }\n ,\"microsoft.autonomousdevelopmentplatform/accounts\": { \"SingularDisplayName\": \"Microsoft.AutonomousDevelopmentPlatform account\" }\n ,\"microsoft.autonomousdevelopmentplatform/accounts/datapools\": { \"SingularDisplayName\": \"Microsoft.AutonomousDevelopmentPlatform accounts data pool\" }\n ,\"microsoft.autonomousdevelopmentplatform/workspaces\": { \"SingularDisplayName\": \"Microsoft.AutonomousDevelopmentPlatform workspace\" }\n ,\"microsoft.avs/privateclouds\": { \"SingularDisplayName\": \"Azure VMware Solution private cloud\" }\n ,\"microsoft.awsconnector/accessanalyzeranalyzers\": { \"SingularDisplayName\": \"Access Analyzer Analyzer\" }\n ,\"microsoft.awsconnector/acmcertificatesummaries\": { \"SingularDisplayName\": \"ACM Certificate Summary\" }\n ,\"microsoft.awsconnector/apigatewayrestapis\": { \"SingularDisplayName\": \"Api Gateway Rest Api\" }\n ,\"microsoft.awsconnector/apigatewaystages\": { \"SingularDisplayName\": \"Api Gateway Stage\" }\n ,\"microsoft.awsconnector/applicationautoscalingscalabletargets\": { \"SingularDisplayName\": \"Application Auto Scaling Scalable Target\" }\n ,\"microsoft.awsconnector/appsyncgraphqlapis\": { \"SingularDisplayName\": \"App Sync Graphql Api\" }\n ,\"microsoft.awsconnector/autoscalingautoscalinggroups\": { \"SingularDisplayName\": \"Auto Scaling Auto Scaling Group\" }\n ,\"microsoft.awsconnector/cloudformationstacks\": { \"SingularDisplayName\": \"Cloud Formation Stack\" }\n ,\"microsoft.awsconnector/cloudformationstacksets\": { \"SingularDisplayName\": \"Cloud Formation Stack Set\" }\n ,\"microsoft.awsconnector/cloudfrontdistributions\": { \"SingularDisplayName\": \"Cloud Front Distribution\" }\n ,\"microsoft.awsconnector/cloudtrailtrails\": { \"SingularDisplayName\": \"Cloud Trail Trail\" }\n ,\"microsoft.awsconnector/cloudwatchalarms\": { \"SingularDisplayName\": \"Cloud Watch Alarm\" }\n ,\"microsoft.awsconnector/codebuildprojects\": { \"SingularDisplayName\": \"Code Build Project\" }\n ,\"microsoft.awsconnector/codebuildsourcecredentialsinfos\": { \"SingularDisplayName\": \"Code Build Source Credentials Info\" }\n ,\"microsoft.awsconnector/configserviceconfigurationrecorders\": { \"SingularDisplayName\": \"Config Service Configuration Recorder\" }\n ,\"microsoft.awsconnector/configserviceconfigurationrecorderstatuses\": { \"SingularDisplayName\": \"Config Service Configuration Recorder Status\" }\n ,\"microsoft.awsconnector/configservicedeliverychannels\": { \"SingularDisplayName\": \"Config Service Delivery Channel\" }\n ,\"microsoft.awsconnector/databasemigrationservicereplicationinstances\": { \"SingularDisplayName\": \"Database Migration Service Replication Instance\" }\n ,\"microsoft.awsconnector/daxclusters\": { \"SingularDisplayName\": \"DAX Cluster\" }\n ,\"microsoft.awsconnector/dynamodbcontinuousbackupsdescriptions\": { \"SingularDisplayName\": \"Dynamo DB Continuous Backups Description\" }\n ,\"microsoft.awsconnector/dynamodbtables\": { \"SingularDisplayName\": \"Dynamo DB Table\" }\n ,\"microsoft.awsconnector/ec2accountattributes\": { \"SingularDisplayName\": \"EC2 Account Attribute\" }\n ,\"microsoft.awsconnector/ec2addresses\": { \"SingularDisplayName\": \"EC2 Address\" }\n ,\"microsoft.awsconnector/ec2flowlogs\": { \"SingularDisplayName\": \"EC2 Flow Log\" }\n ,\"microsoft.awsconnector/ec2images\": { \"SingularDisplayName\": \"EC2 Image\" }\n ,\"microsoft.awsconnector/ec2instances\": { \"SingularDisplayName\": \"Microsoft.AwsConnector ec2 instance\" }\n ,\"microsoft.awsconnector/ec2instancestatuses\": { \"SingularDisplayName\": \"EC2 Instance Status\" }\n ,\"microsoft.awsconnector/ec2ipams\": { \"SingularDisplayName\": \"EC2 Ipam\" }\n ,\"microsoft.awsconnector/ec2keypairs\": { \"SingularDisplayName\": \"EC2 Key Pair\" }\n ,\"microsoft.awsconnector/ec2networkacls\": { \"SingularDisplayName\": \"EC2 Network Acl\" }\n ,\"microsoft.awsconnector/ec2networkinterfaces\": { \"SingularDisplayName\": \"EC2 Network Interface\" }\n ,\"microsoft.awsconnector/ec2routetables\": { \"SingularDisplayName\": \"EC2 Route Table\" }\n ,\"microsoft.awsconnector/ec2securitygroups\": { \"SingularDisplayName\": \"EC2 Security Group\" }\n ,\"microsoft.awsconnector/ec2snapshots\": { \"SingularDisplayName\": \"EC2 Snapshot\" }\n ,\"microsoft.awsconnector/ec2subnets\": { \"SingularDisplayName\": \"EC2 Subnet\" }\n ,\"microsoft.awsconnector/ec2volumes\": { \"SingularDisplayName\": \"EC2 Volume\" }\n ,\"microsoft.awsconnector/ec2vpcendpoints\": { \"SingularDisplayName\": \"EC2 VPCEndpoint\" }\n ,\"microsoft.awsconnector/ec2vpcpeeringconnections\": { \"SingularDisplayName\": \"EC2 VPCPeering Connection\" }\n ,\"microsoft.awsconnector/ec2vpcs\": { \"SingularDisplayName\": \"EC2 VPC\" }\n ,\"microsoft.awsconnector/ecrimagedetails\": { \"SingularDisplayName\": \"ECR Image Detail\" }\n ,\"microsoft.awsconnector/ecrrepositories\": { \"SingularDisplayName\": \"ECR Repository\" }\n ,\"microsoft.awsconnector/ecsclusters\": { \"SingularDisplayName\": \"ECS Cluster\" }\n ,\"microsoft.awsconnector/ecsservices\": { \"SingularDisplayName\": \"ECS Service\" }\n ,\"microsoft.awsconnector/ecstaskdefinitions\": { \"SingularDisplayName\": \"ECS Task Definition\" }\n ,\"microsoft.awsconnector/efsfilesystems\": { \"SingularDisplayName\": \"EFS File System\" }\n ,\"microsoft.awsconnector/efsmounttargets\": { \"SingularDisplayName\": \"EFS Mount Target\" }\n ,\"microsoft.awsconnector/eksnodegroups\": { \"SingularDisplayName\": \"EKS Nodegroup\" }\n ,\"microsoft.awsconnector/elasticbeanstalkapplications\": { \"SingularDisplayName\": \"Elastic Beanstalk Application\" }\n ,\"microsoft.awsconnector/elasticbeanstalkconfigurationtemplates\": { \"SingularDisplayName\": \"Elastic Beanstalk Configuration Template\" }\n ,\"microsoft.awsconnector/elasticbeanstalkenvironments\": { \"SingularDisplayName\": \"Elastic Beanstalk Environment\" }\n ,\"microsoft.awsconnector/elasticloadbalancingv2listeners\": { \"SingularDisplayName\": \"Elastic Load Balancing V2 Listener\" }\n ,\"microsoft.awsconnector/elasticloadbalancingv2loadbalancers\": { \"SingularDisplayName\": \"Elastic Load Balancing V2 Load Balancer\" }\n ,\"microsoft.awsconnector/elasticloadbalancingv2targetgroups\": { \"SingularDisplayName\": \"Elastic Load Balancing V2 Target Group\" }\n ,\"microsoft.awsconnector/elasticloadbalancingv2targethealthdescriptions\": { \"SingularDisplayName\": \"Elastic Load Balancing v2 Target Health Description\" }\n ,\"microsoft.awsconnector/elasticsearchdomains\": { \"SingularDisplayName\": \"Elasticsearch Domain\" }\n ,\"microsoft.awsconnector/emrclusters\": { \"SingularDisplayName\": \"EMR Cluster\" }\n ,\"microsoft.awsconnector/guarddutydetectors\": { \"SingularDisplayName\": \"Guard Duty Detector\" }\n ,\"microsoft.awsconnector/iamaccesskeylastuseds\": { \"SingularDisplayName\": \"IAM Access Key Last Used\" }\n ,\"microsoft.awsconnector/iamaccesskeymetadata\": { \"SingularDisplayName\": \"IAM Access Key Metadata\" }\n ,\"microsoft.awsconnector/iamgroups\": { \"SingularDisplayName\": \"IAM Group\" }\n ,\"microsoft.awsconnector/iaminstanceprofiles\": { \"SingularDisplayName\": \"IAM Instance Profile\" }\n ,\"microsoft.awsconnector/iammanagedpolicies\": { \"SingularDisplayName\": \"IAM Managed Policy\" }\n ,\"microsoft.awsconnector/iammfadevices\": { \"SingularDisplayName\": \"IAM MFADevice\" }\n ,\"microsoft.awsconnector/iampasswordpolicies\": { \"SingularDisplayName\": \"IAM Password Policy\" }\n ,\"microsoft.awsconnector/iampolicyversions\": { \"SingularDisplayName\": \"IAM Policy Version\" }\n ,\"microsoft.awsconnector/iamroles\": { \"SingularDisplayName\": \"IAM Role\" }\n ,\"microsoft.awsconnector/iamservercertificates\": { \"SingularDisplayName\": \"IAM Server Certificate\" }\n ,\"microsoft.awsconnector/iamuserpolicies\": { \"SingularDisplayName\": \"IAM User Policy\" }\n ,\"microsoft.awsconnector/iamvirtualmfadevices\": { \"SingularDisplayName\": \"IAM Virtual MFADevice\" }\n ,\"microsoft.awsconnector/kmsaliases\": { \"SingularDisplayName\": \"KMS Alias\" }\n ,\"microsoft.awsconnector/kmskeys\": { \"SingularDisplayName\": \"KMS Key\" }\n ,\"microsoft.awsconnector/lambdafunctioncodelocations\": { \"SingularDisplayName\": \"Lambda Function Code Location\" }\n ,\"microsoft.awsconnector/lambdafunctionconfigurations\": { \"SingularDisplayName\": \"Microsoft.AwsConnector lambda function configuration\" }\n ,\"microsoft.awsconnector/lambdafunctions\": { \"SingularDisplayName\": \"Lambda Function\" }\n ,\"microsoft.awsconnector/licensemanagerlicenses\": { \"SingularDisplayName\": \"License Manager License\" }\n ,\"microsoft.awsconnector/lightsailbuckets\": { \"SingularDisplayName\": \"Lightsail Bucket\" }\n ,\"microsoft.awsconnector/lightsailinstances\": { \"SingularDisplayName\": \"Lightsail Instance\" }\n ,\"microsoft.awsconnector/logsloggroups\": { \"SingularDisplayName\": \"Logs Log Group\" }\n ,\"microsoft.awsconnector/logslogstreams\": { \"SingularDisplayName\": \"Logs Log Stream\" }\n ,\"microsoft.awsconnector/logsmetricfilters\": { \"SingularDisplayName\": \"Logs Metric Filter\" }\n ,\"microsoft.awsconnector/logssubscriptionfilters\": { \"SingularDisplayName\": \"Logs Subscription Filter\" }\n ,\"microsoft.awsconnector/macie2jobsummaries\": { \"SingularDisplayName\": \"Macie2 Job Summary\" }\n ,\"microsoft.awsconnector/macieallowlists\": { \"SingularDisplayName\": \"Macie Allow List\" }\n ,\"microsoft.awsconnector/networkfirewallfirewallpolicies\": { \"SingularDisplayName\": \"Network Firewall Firewall Policy\" }\n ,\"microsoft.awsconnector/networkfirewallfirewalls\": { \"SingularDisplayName\": \"Network Firewall Firewall\" }\n ,\"microsoft.awsconnector/networkfirewallrulegroups\": { \"SingularDisplayName\": \"Network Firewall Rule Group\" }\n ,\"microsoft.awsconnector/opensearchdomainstatuses\": { \"SingularDisplayName\": \"Open Search Domain Status\" }\n ,\"microsoft.awsconnector/opensearchservicedomains\": { \"SingularDisplayName\": \"Open Search Service Domain\" }\n ,\"microsoft.awsconnector/organizationsaccounts\": { \"SingularDisplayName\": \"Organizations Account\" }\n ,\"microsoft.awsconnector/organizationsorganizations\": { \"SingularDisplayName\": \"Organizations Organization\" }\n ,\"microsoft.awsconnector/rdsdbclusters\": { \"SingularDisplayName\": \"RDS DBCluster\" }\n ,\"microsoft.awsconnector/rdsdbinstances\": { \"SingularDisplayName\": \"RDS DBInstance\" }\n ,\"microsoft.awsconnector/rdsdbsnapshotattributesresults\": { \"SingularDisplayName\": \"RDS DBSnapshot Attributes Result\" }\n ,\"microsoft.awsconnector/rdsdbsnapshots\": { \"SingularDisplayName\": \"RDS DBSnapshot\" }\n ,\"microsoft.awsconnector/rdseventsubscriptions\": { \"SingularDisplayName\": \"RDS Event Subscription\" }\n ,\"microsoft.awsconnector/rdsexporttasks\": { \"SingularDisplayName\": \"RDS Export Task\" }\n ,\"microsoft.awsconnector/redshiftclusterparametergroups\": { \"SingularDisplayName\": \"Redshift Cluster Parameter Group\" }\n ,\"microsoft.awsconnector/redshiftclusters\": { \"SingularDisplayName\": \"Redshift Cluster\" }\n ,\"microsoft.awsconnector/route53domainsdomainsummaries\": { \"SingularDisplayName\": \"Route 53 Domains Domain Summary\" }\n ,\"microsoft.awsconnector/route53hostedzones\": { \"SingularDisplayName\": \"Route53 Hosted Zone\" }\n ,\"microsoft.awsconnector/route53resourcerecordsets\": { \"SingularDisplayName\": \"Route 53 Resource Record Set\" }\n ,\"microsoft.awsconnector/s3accesscontrolpolicies\": { \"SingularDisplayName\": \"S3 Access Control Policy\" }\n ,\"microsoft.awsconnector/s3accesspoints\": { \"SingularDisplayName\": \"S3 Access Point\" }\n ,\"microsoft.awsconnector/s3bucketpolicies\": { \"SingularDisplayName\": \"S3 Bucket Policy\" }\n ,\"microsoft.awsconnector/s3buckets\": { \"SingularDisplayName\": \"S3 Bucket\" }\n ,\"microsoft.awsconnector/s3controlmultiregionaccesspointpolicydocuments\": { \"SingularDisplayName\": \"S3 Control Multi Region Access Point Policy Document\" }\n ,\"microsoft.awsconnector/sagemakerapps\": { \"SingularDisplayName\": \"Sage Maker App\" }\n ,\"microsoft.awsconnector/sagemakerdevices\": { \"SingularDisplayName\": \"Sage Maker Device\" }\n ,\"microsoft.awsconnector/sagemakerimages\": { \"SingularDisplayName\": \"Sage Maker Image\" }\n ,\"microsoft.awsconnector/sagemakernotebookinstancesummaries\": { \"SingularDisplayName\": \"Sage Maker Notebook Instance Summary\" }\n ,\"microsoft.awsconnector/secretsmanagerresourcepolicies\": { \"SingularDisplayName\": \"Secrets Manager Resource Policy\" }\n ,\"microsoft.awsconnector/secretsmanagersecrets\": { \"SingularDisplayName\": \"Secrets Manager Secret\" }\n ,\"microsoft.awsconnector/snssubscriptions\": { \"SingularDisplayName\": \"SNS Subscription\" }\n ,\"microsoft.awsconnector/snstopics\": { \"SingularDisplayName\": \"SNS Topic\" }\n ,\"microsoft.awsconnector/sqsqueues\": { \"SingularDisplayName\": \"SQS Queue\" }\n ,\"microsoft.awsconnector/ssminstanceinformations\": { \"SingularDisplayName\": \"SSM Instance Information\" }\n ,\"microsoft.awsconnector/ssmparameters\": { \"SingularDisplayName\": \"SSM Parameter\" }\n ,\"microsoft.awsconnector/ssmresourcecompliancesummaryitems\": { \"SingularDisplayName\": \"SSM Resource Compliance Summary Item\" }\n ,\"microsoft.awsconnector/wafv2ipsets\": { \"SingularDisplayName\": \"WAFv2 IPSet\" }\n ,\"microsoft.awsconnector/wafv2loggingconfigurations\": { \"SingularDisplayName\": \"WAFv2 Logging Configuration\" }\n ,\"microsoft.awsconnector/wafv2webaclassociations\": { \"SingularDisplayName\": \"WAFv2 Web ACLAssociation\" }\n ,\"microsoft.awsconnector/wafwebaclsummaries\": { \"SingularDisplayName\": \"WAF Web ACLSummary\" }\n ,\"microsoft.azureactivedirectory/b2cdirectories\": { \"SingularDisplayName\": \"B2C tenant\" }\n ,\"microsoft.azureactivedirectory/ciamdirectories\": { \"SingularDisplayName\": \"External Configuration Tenant\" }\n ,\"microsoft.azureactivedirectory/guestusages\": { \"SingularDisplayName\": \"Guest Usage\" }\n ,\"microsoft.azurearcdata/datacontrollers\": { \"SingularDisplayName\": \"Azure Arc data controller\" }\n ,\"microsoft.azurearcdata/mysqlserver\": { \"SingularDisplayName\": \"MySql Server - Azure Arc\" }\n ,\"microsoft.azurearcdata/postgresinstances\": { \"SingularDisplayName\": \"PostgreSQL server ? Azure Arc\" }\n ,\"microsoft.azurearcdata/postgressqlserver\": { \"SingularDisplayName\": \"PostgresSql Server - Azure Arc\" }\n ,\"microsoft.azurearcdata/sqlmanagedinstances\": { \"SingularDisplayName\": \"SQL managed instance - Azure Arc\" }\n ,\"microsoft.azurearcdata/sqlserveresulicenses\": { \"SingularDisplayName\": \"SQL Server ESU license\" }\n ,\"microsoft.azurearcdata/sqlserverinstances\": { \"SingularDisplayName\": \"SQL Server - Azure Arc\" }\n ,\"microsoft.azurearcdata/sqlserverinstances/databases\": { \"SingularDisplayName\": \"SQL Server database - Azure Arc\" }\n ,\"microsoft.azurearcdata/sqlserverlicenses\": { \"SingularDisplayName\": \"SQL Server License\" }\n ,\"microsoft.azurebusinesscontinuity/deletedunifiedprotecteditems\": { \"SingularDisplayName\": \"Microsoft.AzureBusinessContinuity deleted unified protected item\" }\n ,\"microsoft.azurebusinesscontinuity/unifiedprotecteditems\": { \"SingularDisplayName\": \"Microsoft.AzureBusinessContinuity unified protected item\" }\n ,\"microsoft.azurecis/aadapplications\": { \"SingularDisplayName\": \"Microsoft.AzureCis AAD application\" }\n ,\"microsoft.azurecis/addressrecords\": { \"SingularDisplayName\": \"Microsoft.AzureCis address record\" }\n ,\"microsoft.azurecis/autopilotenvironments\": { \"SingularDisplayName\": \"Microsoft.AzureCis autopilot environment\" }\n ,\"microsoft.azurecis/autopilotmachinefunctions\": { \"SingularDisplayName\": \"Microsoft.AzureCis autopilot machine function\" }\n ,\"microsoft.azurecis/autopilotsoftwareloadbalancevirtualips\": { \"SingularDisplayName\": \"Microsoft.AzureCis auto pilot software load balance virtual IP\" }\n ,\"microsoft.azurecis/azcopies\": { \"SingularDisplayName\": \"Microsoft.AzureCis az copy\" }\n ,\"microsoft.azurecis/canonicalnamerecords\": { \"SingularDisplayName\": \"Microsoft.AzureCis canonical name record\" }\n ,\"microsoft.azurecis/dsmsallowlists\": { \"SingularDisplayName\": \"Microsoft.AzureCis ds msallowlist\" }\n ,\"microsoft.azurecis/dsmscertificates\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsms certificate\" }\n ,\"microsoft.azurecis/dsmsrootfolders\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsms root folder\" }\n ,\"microsoft.azurecis/dstsapplications\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsts application\" }\n ,\"microsoft.azurecis/dstsserviceaccounts\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsts service account\" }\n ,\"microsoft.azurecis/dstsserviceclientidentities\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsts service client identity\" }\n ,\"microsoft.azurecis/genericgenevaactions\": { \"SingularDisplayName\": \"Microsoft.AzureCis generic geneva action\" }\n ,\"microsoft.azurecis/plannedquotas\": { \"SingularDisplayName\": \"Microsoft.AzureCis planned quota\" }\n ,\"microsoft.azurecis/pointerrecords\": { \"SingularDisplayName\": \"Microsoft.AzureCis pointer record\" }\n ,\"microsoft.azurecis/publishconfigvalues\": { \"SingularDisplayName\": \"Microsoft.AzureCis publish config value\" }\n ,\"microsoft.azurecis/pushagentv2accounts\": { \"SingularDisplayName\": \"Microsoft.AzureCis push agent v2 account\" }\n ,\"microsoft.azurecis/servicerecords\": { \"SingularDisplayName\": \"Microsoft.AzureCis service record\" }\n ,\"microsoft.azurecis/sharedconfigvalues\": { \"SingularDisplayName\": \"Microsoft.AzureCis shared config value\" }\n ,\"microsoft.azurecloudmetadata/clouds\": { \"SingularDisplayName\": \"Microsoft.AzureCloudMetadata cloud\" }\n ,\"microsoft.azurecloudmetadata/clouds/geographies\": { \"SingularDisplayName\": \"Microsoft.AzureCloudMetadata clouds geography\" }\n ,\"microsoft.azurecloudmetadata/clouds/geographies/regions\": { \"SingularDisplayName\": \"Microsoft.AzureCloudMetadata clouds geographies region\" }\n ,\"microsoft.azuredatatransfer/connections\": { \"SingularDisplayName\": \"Connection\" }\n ,\"microsoft.azuredatatransfer/connections/flows\": { \"SingularDisplayName\": \"Flow\" }\n ,\"microsoft.azuredatatransfer/pipelines\": { \"SingularDisplayName\": \"Pipeline\" }\n ,\"microsoft.azurefleet/fleets\": { \"SingularDisplayName\": \"Compute Fleet\" }\n ,\"microsoft.azurefleet/fleetscomputehub\": { \"SingularDisplayName\": \"Compute Fleet\" }\n ,\"microsoft.azureimagetestingforlinux/jobs\": { \"SingularDisplayName\": \"Microsoft.AzureImageTestingForLinux job\" }\n ,\"microsoft.azureimagetestingforlinux/jobtemplates\": { \"SingularDisplayName\": \"Microsoft.AzureImageTestingForLinux job template\" }\n ,\"microsoft.azurelargeinstance/azurelargeinstances\": { \"SingularDisplayName\": \"Azure Large Instance\" }\n ,\"microsoft.azurelargeinstance/azurelargestorageinstances\": { \"SingularDisplayName\": \"Microsoft.AzureLargeInstance Azure large storage instance\" }\n ,\"microsoft.azurepercept/accounts\": { \"SingularDisplayName\": \"Microsoft.AzurePercept account\" }\n ,\"microsoft.azurepercept/accounts/devices\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts device\" }\n ,\"microsoft.azurepercept/accounts/devices/sensors\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts devices sensor\" }\n ,\"microsoft.azurepercept/accounts/sensors\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts sensor\" }\n ,\"microsoft.azurepercept/accounts/solutioninstances\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts solutioninstance\" }\n ,\"microsoft.azurepercept/accounts/solutions\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts solution\" }\n ,\"microsoft.azurepercept/accounts/targets\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts target\" }\n ,\"microsoft.azureplaywrightservice/accounts\": { \"SingularDisplayName\": \"Playwright Testing\" }\n ,\"microsoft.azurescan/scanningaccounts\": { \"SingularDisplayName\": \"ESRP Scan\" }\n ,\"microsoft.azuresphere/catalogs\": { \"SingularDisplayName\": \"Azure Sphere Catalog\" }\n ,\"microsoft.azurespherev2/catalogs\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalog\" }\n ,\"microsoft.azurespherev2/catalogs/artifacts\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs artifact\" }\n ,\"microsoft.azurespherev2/catalogs/certificates\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs certificate\" }\n ,\"microsoft.azurespherev2/catalogs/deviceregistrations\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs device registration\" }\n ,\"microsoft.azurespherev2/catalogs/provisioningpackages\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs provisioning package\" }\n ,\"microsoft.azurespherev2/catalogs/syndicationchannels\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs syndication channel\" }\n ,\"microsoft.azurespherev2/catalogs/syndicationchannels/deployments\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs syndication channels deployment\" }\n ,\"microsoft.azurespherev2/catalogs/updatepackages\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs update package\" }\n ,\"microsoft.azurestack/cloudmanifestfiles\": { \"SingularDisplayName\": \"Microsoft.AzureStack cloud manifest file\" }\n ,\"microsoft.azurestack/linkedsubscriptions\": { \"SingularDisplayName\": \"Microsoft.AzureStack linked subscription\" }\n ,\"microsoft.azurestack/registrations\": { \"SingularDisplayName\": \"Microsoft.AzureStack registration\" }\n ,\"microsoft.azurestack/registrations/customersubscriptions\": { \"SingularDisplayName\": \"Microsoft.AzureStack registrations customer subscription\" }\n ,\"microsoft.azurestack/registrations/products\": { \"SingularDisplayName\": \"Microsoft.AzureStack registrations product\" }\n ,\"microsoft.azurestackhci/clusters\": { \"SingularDisplayName\": \"Azure Local\" }\n ,\"microsoft.azurestackhci/clusters/updates/updateruns\": { \"SingularDisplayName\": \"Azure Local\" }\n ,\"microsoft.azurestackhci/clusters/updatesummaries\": { \"SingularDisplayName\": \"Azure Local\" }\n ,\"microsoft.azurestackhci/devicepools\": { \"SingularDisplayName\": \"Azure Stack\" }\n ,\"microsoft.azurestackhci/edgedevices\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI edge device\" }\n ,\"microsoft.azurestackhci/edgedevices/jobs\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI edge devices job\" }\n ,\"microsoft.azurestackhci/edgemachines\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI edge machine\" }\n ,\"microsoft.azurestackhci/edgemachines/jobs\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI edge machines job\" }\n ,\"microsoft.azurestackhci/edgenodepools\": { \"SingularDisplayName\": \"Azure Stack\" }\n ,\"microsoft.azurestackhci/galleryimages\": { \"SingularDisplayName\": \"Azure Local Gallery image\" }\n ,\"microsoft.azurestackhci/logicalnetworks\": { \"SingularDisplayName\": \"Azure Local Logical network\" }\n ,\"microsoft.azurestackhci/marketplacegalleryimages\": { \"SingularDisplayName\": \"Azure Local Marketplace Gallery image\" }\n ,\"microsoft.azurestackhci/networkinterfaces\": { \"SingularDisplayName\": \"Azure Local VM Network Interface\" }\n ,\"microsoft.azurestackhci/networksecuritygroups\": { \"SingularDisplayName\": \"Azure Local Network Security Group\" }\n ,\"microsoft.azurestackhci/networksecuritygroups/securityrules\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI network security groups security rule\" }\n ,\"microsoft.azurestackhci/storagecontainers\": { \"SingularDisplayName\": \"Azure Local Storage path\" }\n ,\"microsoft.azurestackhci/virtualharddisks\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual hard disk\" }\n ,\"microsoft.azurestackhci/virtualmachineinstances\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual machine instance\" }\n ,\"microsoft.azurestackhci/virtualmachineinstances/guestagents\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual machine instances guest agent\" }\n ,\"microsoft.azurestackhci/virtualmachineinstances/hybrididentitymetadata\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual machine instances hybrid identity metadata\" }\n ,\"microsoft.azurestackhci/virtualmachines\": { \"SingularDisplayName\": \"Azure Local virtual machine - Azure Arc\" }\n ,\"microsoft.azurestackhci/virtualnetworks\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual network\" }\n ,\"microsoft.backupsolutions/vmwareapplications\": { \"SingularDisplayName\": \"Microsoft.BackupSolutions vmware application\" }\n ,\"microsoft.bakeryhybrid/pies\": { \"SingularDisplayName\": \"Microsoft.BakeryHybrid py\" }\n ,\"microsoft.bakeryhybrid/pies/nestedresourcetype\": { \"SingularDisplayName\": \"Microsoft.BakeryHybrid pies nested resource type\" }\n ,\"microsoft.baremetal/baremetalconnections\": { \"SingularDisplayName\": \"Microsoft.BareMetal bare metal connection\" }\n ,\"microsoft.baremetal/crayservers\": { \"SingularDisplayName\": \"Cray Server\" }\n ,\"microsoft.baremetal/monitoringservers\": { \"SingularDisplayName\": \"Monitoring Server\" }\n ,\"microsoft.baremetal/peeringsettings\": { \"SingularDisplayName\": \"Microsoft.BareMetal peering setting\" }\n ,\"microsoft.baremetalinfrastructure/baremetalinstances\": { \"SingularDisplayName\": \"BareMetal Instance\" }\n ,\"microsoft.baremetalinfrastructure/baremetalstorageinstances\": { \"SingularDisplayName\": \"Microsoft.BareMetalInfrastructure bare metal storage instance\" }\n ,\"microsoft.batch/batchaccounts\": { \"SingularDisplayName\": \"Batch account\" }\n ,\"microsoft.billing/billingaccounts\": { \"SingularDisplayName\": \"Microsoft.Billing billing account\" }\n ,\"microsoft.billing/billingaccounts/agreements\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts agreement\" }\n ,\"microsoft.billing/billingaccounts/associatedtenants\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts associated tenant\" }\n ,\"microsoft.billing/billingaccounts/availablebalance\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts available balance\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profile\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/availablebalance\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles available balance\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles billing role definition\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles billing subscription\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/customers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles customer\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/customers/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles customers billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/customers/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles customers billing role definition\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/customers/transfers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles customers transfer\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/instructions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles instruction\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoices\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice section\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections billing role definition\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections billing subscription\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/products\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections product\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/transfers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections transfer\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/paymentmethodlinks\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles payment method link\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/policies\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles policy\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/transactions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles transaction\" }\n ,\"microsoft.billing/billingaccounts/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing role definition\" }\n ,\"microsoft.billing/billingaccounts/billingsubscriptionaliases\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing subscription aliase\" }\n ,\"microsoft.billing/billingaccounts/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing subscription\" }\n ,\"microsoft.billing/billingaccounts/billingsubscriptions/invoices\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing subscriptions invoice\" }\n ,\"microsoft.billing/billingaccounts/customers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts customer\" }\n ,\"microsoft.billing/billingaccounts/customers/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts customers billing subscription\" }\n ,\"microsoft.billing/billingaccounts/customers/policies\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts customers policy\" }\n ,\"microsoft.billing/billingaccounts/customers/products\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts customers product\" }\n ,\"microsoft.billing/billingaccounts/departments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts department\" }\n ,\"microsoft.billing/billingaccounts/departments/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts departments billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/departments/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts departments billing role definition\" }\n ,\"microsoft.billing/billingaccounts/departments/enrollmentaccounts\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts departments enrollment account\" }\n ,\"microsoft.billing/billingaccounts/enrollmentaccounts\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts enrollment account\" }\n ,\"microsoft.billing/billingaccounts/enrollmentaccounts/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts enrollment accounts billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/enrollmentaccounts/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts enrollment accounts billing role definition\" }\n ,\"microsoft.billing/billingaccounts/incentiveschedules\": { \"SingularDisplayName\": \"Incentive Schedule\" }\n ,\"microsoft.billing/billingaccounts/incentiveschedules/milestones\": { \"SingularDisplayName\": \"Milestone\" }\n ,\"microsoft.billing/billingaccounts/invoices\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice\" }\n ,\"microsoft.billing/billingaccounts/invoicesections\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice section\" }\n ,\"microsoft.billing/billingaccounts/invoicesections/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice sections billing subscription\" }\n ,\"microsoft.billing/billingaccounts/invoicesections/products\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice sections product\" }\n ,\"microsoft.billing/billingaccounts/invoicesections/transfers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice sections transfer\" }\n ,\"microsoft.billing/billingaccounts/lineofcredit\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts line of credit\" }\n ,\"microsoft.billing/billingaccounts/migrations\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts migration\" }\n ,\"microsoft.billing/billingaccounts/paymentmethods\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts payment method\" }\n ,\"microsoft.billing/billingaccounts/policies\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts policy\" }\n ,\"microsoft.billing/billingaccounts/products\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts product\" }\n ,\"microsoft.billing/billingaccounts/reservationorders\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts reservation order\" }\n ,\"microsoft.billing/billingaccounts/reservationorders/reservations\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts reservation orders reservation\" }\n ,\"microsoft.billing/billingaccounts/savingsplanorders\": { \"SingularDisplayName\": \"Savings plan order\" }\n ,\"microsoft.billing/billingaccounts/savingsplanorders/savingsplans\": { \"SingularDisplayName\": \"Savings plan\" }\n ,\"microsoft.billing/billingperiods\": { \"SingularDisplayName\": \"Microsoft.Billing billing period\" }\n ,\"microsoft.billing/billingproperty\": { \"SingularDisplayName\": \"Microsoft.Billing billing property\" }\n ,\"microsoft.billing/billingrequests\": { \"SingularDisplayName\": \"Microsoft.Billing billing request\" }\n ,\"microsoft.billing/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing role assignment\" }\n ,\"microsoft.billing/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing role definition\" }\n ,\"microsoft.billing/enrollmentaccounts\": { \"SingularDisplayName\": \"Microsoft.Billing enrollment account\" }\n ,\"microsoft.billing/paymentmethods\": { \"SingularDisplayName\": \"Microsoft.Billing payment method\" }\n ,\"microsoft.billing/policies\": { \"SingularDisplayName\": \"Microsoft.Billing policy\" }\n ,\"microsoft.billing/promotions\": { \"SingularDisplayName\": \"Microsoft.Billing promotion\" }\n ,\"microsoft.billing/transfers\": { \"SingularDisplayName\": \"Microsoft.Billing transfer\" }\n ,\"microsoft.billingbenefits/credits\": { \"SingularDisplayName\": \"Credit\" }\n ,\"microsoft.billingbenefits/discounts\": { \"SingularDisplayName\": \"Discount\" }\n ,\"microsoft.billingbenefits/incentiveschedules\": { \"SingularDisplayName\": \"Incentive Schedule\" }\n ,\"microsoft.billingbenefits/incentiveschedules/milestones\": { \"SingularDisplayName\": \"Milestone\" }\n ,\"microsoft.billingbenefits/maccs\": { \"SingularDisplayName\": \"Microsoft Azure Consumption Commitment\" }\n ,\"microsoft.billingbenefits/reservationorderaliases\": { \"SingularDisplayName\": \"Microsoft.BillingBenefits reservation order aliase\" }\n ,\"microsoft.billingbenefits/savingsplanorderaliases\": { \"SingularDisplayName\": \"Microsoft.BillingBenefits savings plan order aliase\" }\n ,\"microsoft.billingbenefits/savingsplanorders\": { \"SingularDisplayName\": \"Savings plan order\" }\n ,\"microsoft.billingbenefits/savingsplanorders/savingsplans\": { \"SingularDisplayName\": \"Savings plan\" }\n ,\"microsoft.bing/accounts\": { \"SingularDisplayName\": \"Bing Resource\" }\n ,\"microsoft.blockchain/blockchainmembers\": { \"SingularDisplayName\": \"Microsoft.Blockchain blockchain member\" }\n ,\"microsoft.blockchain/blockchainmembers/transactionnodes\": { \"SingularDisplayName\": \"Microsoft.Blockchain blockchain members transaction node\" }\n ,\"microsoft.blockchaintokens/tokenservices\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token service\" }\n ,\"microsoft.blockchaintokens/tokenservices/blockchainnetworks\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token services blockchain network\" }\n ,\"microsoft.blockchaintokens/tokenservices/groups\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token services group\" }\n ,\"microsoft.blockchaintokens/tokenservices/groups/accounts\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token services groups account\" }\n ,\"microsoft.blockchaintokens/tokenservices/tokentemplates\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token services token template\" }\n ,\"microsoft.bluefin/instances\": { \"SingularDisplayName\": \"Microsoft.Bluefin instance\" }\n ,\"microsoft.bluefin/instances/datasets\": { \"SingularDisplayName\": \"Microsoft.Bluefin instances dataset\" }\n ,\"microsoft.bluefin/instances/pipelines\": { \"SingularDisplayName\": \"Microsoft.Bluefin instances pipeline\" }\n ,\"microsoft.blueprint/blueprintassignments\": { \"SingularDisplayName\": \"Microsoft.Blueprint blueprint assignment\" }\n ,\"microsoft.blueprint/blueprints\": { \"SingularDisplayName\": \"Microsoft.Blueprint blueprint\" }\n ,\"microsoft.blueprint/blueprints/artifacts\": { \"SingularDisplayName\": \"Microsoft.Blueprint blueprints artifact\" }\n ,\"microsoft.blueprint/blueprints/versions\": { \"SingularDisplayName\": \"Microsoft.Blueprint blueprints version\" }\n ,\"microsoft.botservice/botservices\": { \"SingularDisplayName\": \"Bot Service\" }\n ,\"microsoft.cache/redis\": { \"SingularDisplayName\": \"Redis cache\" }\n ,\"microsoft.cache/redisenterprise\": { \"SingularDisplayName\": \"Azure Managed Redis\" }\n ,\"microsoft.cache/redisenterprise/databases\": { \"SingularDisplayName\": \"Redis Enterprise database\" }\n ,\"microsoft.capacity/reservationorders\": { \"SingularDisplayName\": \"Reservation order\" }\n ,\"microsoft.capacity/reservationorders/reservations\": { \"SingularDisplayName\": \"Reservation\" }\n ,\"microsoft.cascade/sites\": { \"SingularDisplayName\": \"Microsoft.Cascade site\" }\n ,\"microsoft.cdn/cdnwebapplicationfirewallpolicies\": { \"SingularDisplayName\": \"Content Delivery Network WAF policy\" }\n ,\"microsoft.cdn/edgeactions\": { \"SingularDisplayName\": \"Edge Action\" }\n ,\"microsoft.cdn/profiles\": { \"SingularDisplayName\": \"Front Door and CDN profile\" }\n ,\"microsoft.cdn/profiles/afdendpoints\": { \"SingularDisplayName\": \"Endpoint\" }\n ,\"microsoft.cdn/profiles/afdendpoints/routes\": { \"SingularDisplayName\": \"Route\" }\n ,\"microsoft.cdn/profiles/customdomains\": { \"SingularDisplayName\": \"Custom domain\" }\n ,\"microsoft.cdn/profiles/endpoints\": { \"SingularDisplayName\": \"CDN endpoint\" }\n ,\"microsoft.cdn/profiles/endpoints/customdomains\": { \"SingularDisplayName\": \"CDN custom domain\" }\n ,\"microsoft.cdn/profiles/endpoints/origins\": { \"SingularDisplayName\": \"CDN origin\" }\n ,\"microsoft.cdn/profiles/origingroups\": { \"SingularDisplayName\": \"Origin group\" }\n ,\"microsoft.cdn/profiles/origingroups/origins\": { \"SingularDisplayName\": \"Origin\" }\n ,\"microsoft.cdn/profiles/rulesets\": { \"SingularDisplayName\": \"Rule set\" }\n ,\"microsoft.cdn/profiles/rulesets/rules\": { \"SingularDisplayName\": \"Rule\" }\n ,\"microsoft.cdn/profiles/secrets\": { \"SingularDisplayName\": \"Secret\" }\n ,\"microsoft.cdn/profiles/securitypolicies\": { \"SingularDisplayName\": \"Security policy\" }\n ,\"microsoft.certificateregistration/certificateorders\": { \"SingularDisplayName\": \"App Service certificate\" }\n ,\"microsoft.certify/testsuites\": { \"SingularDisplayName\": \"Microsoft.Certify test suite\" }\n ,\"microsoft.certify/validationjobs\": { \"SingularDisplayName\": \"Microsoft.Certify validation job\" }\n ,\"microsoft.changeanalysis/profile\": { \"SingularDisplayName\": \"Microsoft.ChangeAnalysis profile\" }\n ,\"microsoft.changesafety/changestates\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety change state\" }\n ,\"microsoft.changesafety/changestates/stageprogressions\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety change states stage progression\" }\n ,\"microsoft.changesafety/stagemaps\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety stage map\" }\n ,\"microsoft.changesafety/validations\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety validation\" }\n ,\"microsoft.changesafety/validators\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety validator\" }\n ,\"microsoft.changesafety/validators/versions\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety validators version\" }\n ,\"microsoft.chaos/experiments\": { \"SingularDisplayName\": \"Chaos Experiment\" }\n ,\"microsoft.chaos/privateaccesses\": { \"SingularDisplayName\": \"Agent Private Access\" }\n ,\"microsoft.chaos/targets\": { \"SingularDisplayName\": \"Microsoft.Chaos target\" }\n ,\"microsoft.chaos/targets/capabilities\": { \"SingularDisplayName\": \"Microsoft.Chaos targets capability\" }\n ,\"microsoft.classiccompute/domainnames\": { \"SingularDisplayName\": \"Cloud service (classic)\" }\n ,\"microsoft.classiccompute/domainnames/slots/roles\": { \"SingularDisplayName\": \"Cloud service role (classic)\" }\n ,\"microsoft.classiccompute/virtualmachines\": { \"SingularDisplayName\": \"Virtual machine (classic)\" }\n ,\"microsoft.classicnetwork/networksecuritygroups\": { \"SingularDisplayName\": \"Network security group (classic)\" }\n ,\"microsoft.classicnetwork/reservedips\": { \"SingularDisplayName\": \"Reserved IP address (classic)\" }\n ,\"microsoft.classicnetwork/virtualnetworks\": { \"SingularDisplayName\": \"Virtual network (classic)\" }\n })[tolower(id)]\n}\n", "$fxv#1": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n.create-or-alter function \nwith (docstring = 'Return details about the specified ID.', folder = 'OpenData/Internal')\n_resource_type_2(id: string) {\n dynamic({\n \"microsoft.classicstorage/storageaccounts\": { \"SingularDisplayName\": \"Storage account (classic)\" }\n ,\"microsoft.classicstorage/storageaccounts/disks\": { \"SingularDisplayName\": \"Disk (classic)\" }\n ,\"microsoft.classicstorage/storageaccounts/osimages\": { \"SingularDisplayName\": \"OS image (classic)\" }\n ,\"microsoft.classicstorage/storageaccounts/vmimages\": { \"SingularDisplayName\": \"VM image (classic)\" }\n ,\"microsoft.cleanroom/cleanrooms\": { \"SingularDisplayName\": \"Microsoft.CleanRoom cleanroom\" }\n ,\"microsoft.cleanroom/collaborations\": { \"SingularDisplayName\": \"Microsoft.CleanRoom collaboration\" }\n ,\"microsoft.cleanroom/collaborations/contracts\": { \"SingularDisplayName\": \"Microsoft.CleanRoom collaborations contract\" }\n ,\"microsoft.cleanroom/consortiums\": { \"SingularDisplayName\": \"Microsoft.CleanRoom consortium\" }\n ,\"microsoft.cleanroom/microservices\": { \"SingularDisplayName\": \"Microsoft.CleanRoom microservice\" }\n ,\"microsoft.cloud/hubs\": { \"SingularDisplayName\": \"FinOps hub\" }\n ,\"microsoft.clouddeviceplatform/delegatedidentities\": { \"SingularDisplayName\": \"Microsoft.CloudDevicePlatform delegated identity\" }\n ,\"microsoft.cloudhealth/healthmodels\": { \"SingularDisplayName\": \"Health Model\" }\n ,\"microsoft.cloudtest/accounts\": { \"SingularDisplayName\": \"CloudTest Account\" }\n ,\"microsoft.cloudtest/buildcaches\": { \"SingularDisplayName\": \"1ES Build Cache\" }\n ,\"microsoft.cloudtest/hostedpools\": { \"SingularDisplayName\": \"1ES Hosted Pool\" }\n ,\"microsoft.cloudtest/images\": { \"SingularDisplayName\": \"1ES Image\" }\n ,\"microsoft.cloudtest/pools\": { \"SingularDisplayName\": \"CloudTest Pool\" }\n ,\"microsoft.clusterstor/nodes\": { \"SingularDisplayName\": \"ClusterStor\" }\n ,\"microsoft.codesigning/codesigningaccounts\": { \"SingularDisplayName\": \"Trusted Signing Account\" }\n ,\"microsoft.codespaces/plans\": { \"SingularDisplayName\": \"Microsoft.Codespaces plan\" }\n ,\"microsoft.cognitiveservices/accounts\": { \"SingularDisplayName\": \"Azure AI Foundry\" }\n ,\"microsoft.cognitiveservices/accounts/projects\": { \"SingularDisplayName\": \"Azure AI Foundry project\" }\n ,\"microsoft.cognitiveservices/commitmentplans\": { \"SingularDisplayName\": \"Microsoft.CognitiveServices commitment plan\" }\n ,\"microsoft.cognitiveservices/commitmentplans/accountassociations\": { \"SingularDisplayName\": \"Microsoft.CognitiveServices commitment plans account association\" }\n ,\"microsoft.communication/communicationservices\": { \"SingularDisplayName\": \"Communication Service\" }\n ,\"microsoft.communication/emailservices\": { \"SingularDisplayName\": \"Email Communication Service\" }\n ,\"microsoft.communication/emailservices/domains\": { \"SingularDisplayName\": \"Email Communication Services Domain\" }\n ,\"microsoft.community/communitytrainings\": { \"SingularDisplayName\": \"Community Training\" }\n ,\"microsoft.compositesolutions/compositesolutiondefinitions\": { \"SingularDisplayName\": \"Microsoft.CompositeSolutions composite solution definition\" }\n ,\"microsoft.compositesolutions/compositesolutions\": { \"SingularDisplayName\": \"Microsoft.CompositeSolutions composite solution\" }\n ,\"microsoft.compute/availabilitysets\": { \"SingularDisplayName\": \"Availability set\" }\n ,\"microsoft.compute/capacityreservationgroups\": { \"SingularDisplayName\": \"Capacity Reservation Group\" }\n ,\"microsoft.compute/capacityreservationgroups/capacityreservations\": { \"SingularDisplayName\": \"Capacity reservation\" }\n ,\"microsoft.compute/capacityreservationgroupscomputehub\": { \"SingularDisplayName\": \"Capacity Reservation Group\" }\n ,\"microsoft.compute/cloudservices\": { \"SingularDisplayName\": \"Cloud service (extended support)\" }\n ,\"microsoft.compute/computefleetinstances\": { \"SingularDisplayName\": \"Instance\" }\n ,\"microsoft.compute/computefleetscalesets\": { \"SingularDisplayName\": \"Virtual machine scale set\" }\n ,\"microsoft.compute/diskaccesses\": { \"SingularDisplayName\": \"Disk Access\" }\n ,\"microsoft.compute/diskencryptionsets\": { \"SingularDisplayName\": \"Disk Encryption Set\" }\n ,\"microsoft.compute/disks\": { \"SingularDisplayName\": \"Disk\" }\n ,\"microsoft.compute/galleries\": { \"SingularDisplayName\": \"Azure compute gallery\" }\n ,\"microsoft.compute/galleries/applications\": { \"SingularDisplayName\": \"VM application definition\" }\n ,\"microsoft.compute/galleries/applications/versions\": { \"SingularDisplayName\": \"VM application version\" }\n ,\"microsoft.compute/galleries/images\": { \"SingularDisplayName\": \"VM image definition\" }\n ,\"microsoft.compute/galleries/images/versions\": { \"SingularDisplayName\": \"VM image version\" }\n ,\"microsoft.compute/galleries/imagescomputehub\": { \"SingularDisplayName\": \"VM image definition\" }\n ,\"microsoft.compute/hostgroups\": { \"SingularDisplayName\": \"Host group\" }\n ,\"microsoft.compute/hostgroups/hosts\": { \"SingularDisplayName\": \"Host\" }\n ,\"microsoft.compute/hostgroupscomputehub\": { \"SingularDisplayName\": \"Host group\" }\n ,\"microsoft.compute/images\": { \"SingularDisplayName\": \"Image\" }\n ,\"microsoft.compute/imagescomputehub\": { \"SingularDisplayName\": \"Image\" }\n ,\"microsoft.compute/locations/communitygalleries/images\": { \"SingularDisplayName\": \"Community image\" }\n ,\"microsoft.compute/locations/communitygalleries/imagescomputehub\": { \"SingularDisplayName\": \"Community image\" }\n ,\"microsoft.compute/proximityplacementgroups\": { \"SingularDisplayName\": \"Proximity placement group\" }\n ,\"microsoft.compute/proximityplacementgroupscomputehub\": { \"SingularDisplayName\": \"Proximity placement group\" }\n ,\"microsoft.compute/restorepointcollections\": { \"SingularDisplayName\": \"Restore Point Collection\" }\n ,\"microsoft.compute/restorepointcollections/restorepoints\": { \"SingularDisplayName\": \"Restore Point\" }\n ,\"microsoft.compute/snapshots\": { \"SingularDisplayName\": \"Snapshot\" }\n ,\"microsoft.compute/sshpublickeys\": { \"SingularDisplayName\": \"SSH key\" }\n ,\"microsoft.compute/standbypoolinstance\": { \"SingularDisplayName\": \"Standby pool\" }\n ,\"microsoft.compute/virtualmachinecomputehub\": { \"SingularDisplayName\": \"Virtual machine\" }\n ,\"microsoft.compute/virtualmachineflexinstances\": { \"SingularDisplayName\": \"Instance\" }\n ,\"microsoft.compute/virtualmachines\": { \"SingularDisplayName\": \"Virtual machine\" }\n ,\"microsoft.compute/virtualmachines/providers/guestconfigurationassignments\": { \"SingularDisplayName\": \"Guest Assignment\" }\n ,\"microsoft.compute/virtualmachinescalesets\": { \"SingularDisplayName\": \"Virtual machine scale set\" }\n ,\"microsoft.compute/virtualmachinescalesets/providers/guestconfigurationassignments\": { \"SingularDisplayName\": \"Guest Assignment\" }\n ,\"microsoft.compute/virtualmachinescalesets/virtualmachines\": { \"SingularDisplayName\": \"Virtual machine scale set instance\" }\n ,\"microsoft.compute/virtualmachinescalesets/virtualmachines/networkinterfaces/ipconfigurations/publicipaddresses\": { \"SingularDisplayName\": \"Public IP address\" }\n ,\"microsoft.compute/virtualmachinescalesetscomputehub\": { \"SingularDisplayName\": \"Virtual machine scale set\" }\n ,\"microsoft.computehub/advisorcost\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/advisoroperationalexcellence\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/advisorperformance\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/advisorreliability\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/advisorsecurity\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/all\": { \"SingularDisplayName\": \"All resources\" }\n ,\"microsoft.computehub/backup\": { \"SingularDisplayName\": \"Backup job\" }\n ,\"microsoft.computehub/computehubmain\": { \"SingularDisplayName\": \"Compute infrastructure\" }\n ,\"microsoft.computehub/healthevents\": { \"SingularDisplayName\": \"Health events\" }\n ,\"microsoft.computehub/linuxostype\": { \"SingularDisplayName\": \"Linux OS\" }\n ,\"microsoft.computehub/microsoftdefenderfreetrialsubscription\": { \"SingularDisplayName\": \"Microsoft defender\" }\n ,\"microsoft.computehub/microsoftdefenderstandardsubscription\": { \"SingularDisplayName\": \"Microsoft defender\" }\n ,\"microsoft.computehub/outages\": { \"SingularDisplayName\": \"Outages\" }\n ,\"microsoft.computehub/powerstatedeallocated\": { \"SingularDisplayName\": \"Power states\" }\n ,\"microsoft.computehub/powerstaterunning\": { \"SingularDisplayName\": \"Power states\" }\n ,\"microsoft.computehub/powerstatestopped\": { \"SingularDisplayName\": \"Power states\" }\n ,\"microsoft.computehub/provisioningstatefailedresources\": { \"SingularDisplayName\": \"Provisioning states\" }\n ,\"microsoft.computehub/provisioningstatesucceededresources\": { \"SingularDisplayName\": \"Provisioning states\" }\n ,\"microsoft.computehub/windowsostype\": { \"SingularDisplayName\": \"Windows OS\" }\n ,\"microsoft.computeschedule/autoactions\": { \"SingularDisplayName\": \"Automatic Action\" }\n ,\"microsoft.computeschedule/autoactions/occurrences\": { \"SingularDisplayName\": \"Microsoft.ComputeSchedule auto actions occurrence\" }\n ,\"microsoft.confidentialledger/ledgers\": { \"SingularDisplayName\": \"Confidential Ledger\" }\n ,\"microsoft.confidentialledger/managedccfs\": { \"SingularDisplayName\": \"Managed CCF App\" }\n ,\"microsoft.confluent/agreements\": { \"SingularDisplayName\": \"Microsoft.Confluent agreement\" }\n ,\"microsoft.confluent/organizations\": { \"SingularDisplayName\": \"Confluent organization\" }\n ,\"microsoft.connectedcache/cachenodes\": { \"SingularDisplayName\": \"Connected Cache for ISP\" }\n ,\"microsoft.connectedcache/enterprisecustomers\": { \"SingularDisplayName\": \"Connected Cache for Enterprise & Education\" }\n ,\"microsoft.connectedcache/enterprisemcccustomers\": { \"SingularDisplayName\": \"Connected Cache for Enterprise & Education\" }\n ,\"microsoft.connectedcache/enterprisemcccustomers/enterprisemcccachenodes\": { \"SingularDisplayName\": \"MCC CacheNode for Enterprise\" }\n ,\"microsoft.connectedcache/ispcustomers\": { \"SingularDisplayName\": \"Connected Cache for ISP\" }\n ,\"microsoft.connectedcredentials/credentials\": { \"SingularDisplayName\": \"Microsoft.ConnectedCredentials credential\" }\n ,\"microsoft.connectedvehicle/platformaccounts\": { \"SingularDisplayName\": \"Microsoft.ConnectedVehicle platform account\" }\n ,\"microsoft.connectedvmwarevsphere/clusters\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere cluster\" }\n ,\"microsoft.connectedvmwarevsphere/datastores\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere datastore\" }\n ,\"microsoft.connectedvmwarevsphere/hosts\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere host\" }\n ,\"microsoft.connectedvmwarevsphere/resourcepools\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere resource pool\" }\n ,\"microsoft.connectedvmwarevsphere/vcenters\": { \"SingularDisplayName\": \"VMware vCenter\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachineinstances\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual machine instance\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachineinstances/guestagents\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual machine instances guest agent\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachineinstances/hybrididentitymetadata\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual machine instances hybrid identity metadata\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachines\": { \"SingularDisplayName\": \"VMware + AVS virtual machine\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachines/providers/guestconfigurationassignments\": { \"SingularDisplayName\": \"Guest Assignment\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachinetemplates\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual machine template\" }\n ,\"microsoft.connectedvmwarevsphere/virtualnetworks\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual network\" }\n ,\"microsoft.consumption/budgets\": { \"SingularDisplayName\": \"Microsoft.Consumption budget\" }\n ,\"microsoft.consumption/credits\": { \"SingularDisplayName\": \"Microsoft.Consumption credit\" }\n ,\"microsoft.consumption/pricesheets\": { \"SingularDisplayName\": \"Microsoft.Consumption pricesheet\" }\n ,\"microsoft.containerinstance/containergroupprofiles\": { \"SingularDisplayName\": \"Microsoft.ContainerInstance container group profile\" }\n ,\"microsoft.containerinstance/containergroupprofiles/revisions\": { \"SingularDisplayName\": \"Microsoft.ContainerInstance container group profiles revision\" }\n ,\"microsoft.containerinstance/containergroups\": { \"SingularDisplayName\": \"Container instances\" }\n ,\"microsoft.containerinstance/ngroups\": { \"SingularDisplayName\": \"Microsoft.ContainerInstance ngroup\" }\n ,\"microsoft.containerregistry/registries\": { \"SingularDisplayName\": \"Container registry\" }\n ,\"microsoft.containerregistry/registries/replications\": { \"SingularDisplayName\": \"Container registry replication\" }\n ,\"microsoft.containerregistry/registries/scopemaps\": { \"SingularDisplayName\": \"Container registry scope map\" }\n ,\"microsoft.containerregistry/registries/tokens\": { \"SingularDisplayName\": \"Container registry token\" }\n ,\"microsoft.containerregistry/registries/webhooks\": { \"SingularDisplayName\": \"Container registry webhook\" }\n ,\"microsoft.containerservice/fleets\": { \"SingularDisplayName\": \"Kubernetes fleet manager\" }\n ,\"microsoft.containerservice/managedclusters\": { \"SingularDisplayName\": \"Kubernetes service\" }\n ,\"microsoft.containerservice/managedclusters/managednamespaces\": { \"SingularDisplayName\": \"Managed namespace\" }\n ,\"microsoft.containerservice/managedclusters/microsoft.kubernetesconfiguration/extensions\": { \"SingularDisplayName\": \"Kubernetes service extension\" }\n ,\"microsoft.containerservice/managedclusters/microsoft.kubernetesconfiguration/fluxconfigurations\": { \"SingularDisplayName\": \"GitOps configuration\" }\n ,\"microsoft.containerservice/managedclusters/microsoft.kubernetesconfiguration/namespaces\": { \"SingularDisplayName\": \"Kubernetes namespace\" }\n ,\"microsoft.containerservice/managedclusters/namespaces\": { \"SingularDisplayName\": \"Managed namespace\" }\n ,\"microsoft.containerservice/managedclustersnapshots\": { \"SingularDisplayName\": \"Microsoft.ContainerService managedclustersnapshot\" }\n ,\"microsoft.containerservice/snapshots\": { \"SingularDisplayName\": \"Microsoft.ContainerService snapshot\" }\n ,\"microsoft.containerstorage/pools\": { \"SingularDisplayName\": \"Container storage\" }\n ,\"microsoft.costmanagement/alerts\": { \"SingularDisplayName\": \"Microsoft.CostManagement alert\" }\n ,\"microsoft.costmanagement/budgets\": { \"SingularDisplayName\": \"Microsoft.CostManagement budget\" }\n ,\"microsoft.costmanagement/cloudconnectors\": { \"SingularDisplayName\": \"Microsoft.CostManagement cloud connector\" }\n ,\"microsoft.costmanagement/connectors\": { \"SingularDisplayName\": \"Microsoft.CostManagement connector\" }\n ,\"microsoft.costmanagement/costallocationrules\": { \"SingularDisplayName\": \"Microsoft.CostManagement cost allocation rule\" }\n ,\"microsoft.costmanagement/costdetailsoperationresults\": { \"SingularDisplayName\": \"Microsoft.CostManagement cost details operation result\" }\n ,\"microsoft.costmanagement/exports\": { \"SingularDisplayName\": \"Microsoft.CostManagement export\" }\n ,\"microsoft.costmanagement/externalbillingaccounts\": { \"SingularDisplayName\": \"Microsoft.CostManagement external billing account\" }\n ,\"microsoft.costmanagement/externalsubscriptions\": { \"SingularDisplayName\": \"Microsoft.CostManagement external subscription\" }\n ,\"microsoft.costmanagement/markuprules\": { \"SingularDisplayName\": \"Microsoft.CostManagement markup rule\" }\n ,\"microsoft.costmanagement/operationstatus\": { \"SingularDisplayName\": \"Microsoft.CostManagement operation statu\" }\n ,\"microsoft.costmanagement/reportconfigs\": { \"SingularDisplayName\": \"Microsoft.CostManagement reportconfig\" }\n ,\"microsoft.costmanagement/reports\": { \"SingularDisplayName\": \"Microsoft.CostManagement report\" }\n ,\"microsoft.costmanagement/scheduledactions\": { \"SingularDisplayName\": \"Microsoft.CostManagement scheduled action\" }\n ,\"microsoft.costmanagement/settings\": { \"SingularDisplayName\": \"Microsoft.CostManagement setting\" }\n ,\"microsoft.costmanagement/views\": { \"SingularDisplayName\": \"Microsoft.CostManagement view\" }\n ,\"microsoft.customerlockbox/requests\": { \"SingularDisplayName\": \"Microsoft.CustomerLockbox request\" }\n ,\"microsoft.customerlockbox/tenantoptedin\": { \"SingularDisplayName\": \"Microsoft.CustomerLockbox tenant opted in\" }\n ,\"microsoft.customproviders/associations\": { \"SingularDisplayName\": \"Microsoft.CustomProviders association\" }\n ,\"microsoft.customproviders/resourceproviders\": { \"SingularDisplayName\": \"Microsoft.CustomProviders resource provider\" }\n ,\"microsoft.dashboard/dashboards\": { \"SingularDisplayName\": \"Azure Monitor dashboards with Grafana\" }\n ,\"microsoft.dashboard/grafana\": { \"SingularDisplayName\": \"Azure Managed Grafana\" }\n ,\"microsoft.dataaccelerator/indexclusters\": { \"SingularDisplayName\": \"Microsoft.DataAccelerator index cluster\" }\n ,\"microsoft.databasefleetmanager/fleets\": { \"SingularDisplayName\": \"Database fleet manager\" }\n ,\"microsoft.databasefleetmanager/fleets/fleetspaces\": { \"SingularDisplayName\": \"Fleetspaces\" }\n ,\"microsoft.databasefleetmanager/fleets/fleetspaces/databases\": { \"SingularDisplayName\": \"Fleet managed database\" }\n ,\"microsoft.databasefleetmanager/fleets/tiers\": { \"SingularDisplayName\": \"tier\" }\n ,\"microsoft.databasewatcher/watchers\": { \"SingularDisplayName\": \"Database watcher\" }\n ,\"microsoft.databox/jobs\": { \"SingularDisplayName\": \"Azure Data Box\" }\n ,\"microsoft.databoxedge/databoxedgedevices\": { \"SingularDisplayName\": \"Azure Stack Edge / Data Box Gateway\" }\n ,\"microsoft.databricks/accessconnectors\": { \"SingularDisplayName\": \"Access Connector for Azure Databricks\" }\n ,\"microsoft.databricks/workspaces\": { \"SingularDisplayName\": \"Azure Databricks Service\" }\n ,\"microsoft.datacatalog/catalogs\": { \"SingularDisplayName\": \"Data catalog\" }\n ,\"microsoft.datacollaboration/workspaces\": { \"SingularDisplayName\": \"Project CI\" }\n ,\"microsoft.datadog/agreements\": { \"SingularDisplayName\": \"Microsoft.Datadog agreement\" }\n ,\"microsoft.datadog/monitors\": { \"SingularDisplayName\": \"Datadog\" }\n ,\"microsoft.datadog/subscriptionstatuses\": { \"SingularDisplayName\": \"Microsoft.Datadog subscription statuse\" }\n ,\"microsoft.datafactory/datafactories\": { \"SingularDisplayName\": \"Data factory\" }\n ,\"microsoft.datafactory/factories\": { \"SingularDisplayName\": \"Data factory (V2)\" }\n ,\"microsoft.datafactory/factories/pipelines\": { \"SingularDisplayName\": \"Data Factory pipeline\" }\n ,\"microsoft.datafactory/factories/triggers\": { \"SingularDisplayName\": \"Data Factory trigger\" }\n ,\"microsoft.datalakeanalytics/accounts\": { \"SingularDisplayName\": \"Data Lake Analytics account\" }\n ,\"microsoft.datalakestore/accounts\": { \"SingularDisplayName\": \"Data Lake Storage Gen1\" }\n ,\"microsoft.datamigration/databasemigrations\": { \"SingularDisplayName\": \"Microsoft.DataMigration database migration\" }\n ,\"microsoft.datamigration/migrationservices\": { \"SingularDisplayName\": \"Microsoft.DataMigration migration service\" }\n ,\"microsoft.datamigration/services\": { \"SingularDisplayName\": \"Azure Database Migration Service (classic)\" }\n ,\"microsoft.datamigration/services/projects\": { \"SingularDisplayName\": \"Azure Database Migration Project\" }\n ,\"microsoft.datamigration/sqlmigrationservices\": { \"SingularDisplayName\": \"Azure Database Migration Service\" }\n ,\"microsoft.dataprotection/backupvaults\": { \"SingularDisplayName\": \"Backup vault\" }\n ,\"microsoft.dataprotection/resourceguards\": { \"SingularDisplayName\": \"Resource Guard\" }\n ,\"microsoft.datareplication/replicationfabrics\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication fabric\" }\n ,\"microsoft.datareplication/replicationfabrics/fabricagents\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication fabrics fabric agent\" }\n ,\"microsoft.datareplication/replicationfabrics/fabricagents/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication fabrics fabric agents operation\" }\n ,\"microsoft.datareplication/replicationfabrics/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication fabrics operation\" }\n ,\"microsoft.datareplication/replicationvaults\": { \"SingularDisplayName\": \"Data replication vault\" }\n ,\"microsoft.datareplication/replicationvaults/alertsettings\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults alert setting\" }\n ,\"microsoft.datareplication/replicationvaults/events\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults event\" }\n ,\"microsoft.datareplication/replicationvaults/jobs\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults job\" }\n ,\"microsoft.datareplication/replicationvaults/jobs/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults jobs operation\" }\n ,\"microsoft.datareplication/replicationvaults/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults operation\" }\n ,\"microsoft.datareplication/replicationvaults/privateendpointconnectionproxies\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults private endpoint connection proxy\" }\n ,\"microsoft.datareplication/replicationvaults/privateendpointconnections\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults private endpoint connection\" }\n ,\"microsoft.datareplication/replicationvaults/privatelinkresources\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults private link resource\" }\n ,\"microsoft.datareplication/replicationvaults/protecteditems\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults protected item\" }\n ,\"microsoft.datareplication/replicationvaults/protecteditems/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults protected items operation\" }\n ,\"microsoft.datareplication/replicationvaults/protecteditems/recoverypoints\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults protected items recovery point\" }\n ,\"microsoft.datareplication/replicationvaults/replicationextensions\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults replication extension\" }\n ,\"microsoft.datareplication/replicationvaults/replicationextensions/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults replication extensions operation\" }\n ,\"microsoft.datareplication/replicationvaults/replicationpolicies\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults replication policy\" }\n ,\"microsoft.datareplication/replicationvaults/replicationpolicies/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults replication policies operation\" }\n ,\"microsoft.datashare/accounts\": { \"SingularDisplayName\": \"Data Share\" }\n ,\"microsoft.dbformariadb/servers\": { \"SingularDisplayName\": \"Azure Database for MariaDB server\" }\n ,\"microsoft.dbformysql/flexibleservers\": { \"SingularDisplayName\": \"Azure Database for MySQL flexible server\" }\n ,\"microsoft.dbformysql/servers\": { \"SingularDisplayName\": \"MySQL server\" }\n ,\"microsoft.dbforpostgresql/flexibleservers\": { \"SingularDisplayName\": \"Azure Database for PostgreSQL flexible server\" }\n ,\"microsoft.dbforpostgresql/servergroupsv2\": { \"SingularDisplayName\": \"Azure Cosmos DB for PostgreSQL Cluster\" }\n ,\"microsoft.dbforpostgresql/servers\": { \"SingularDisplayName\": \"PostgreSQL server\" }\n ,\"microsoft.delegatednetwork/controller\": { \"SingularDisplayName\": \"Microsoft.DelegatedNetwork controller\" }\n ,\"microsoft.delegatednetwork/delegatedsubnets\": { \"SingularDisplayName\": \"Microsoft.DelegatedNetwork delegated subnet\" }\n ,\"microsoft.delegatednetwork/orchestrators\": { \"SingularDisplayName\": \"Microsoft.DelegatedNetwork orchestrator\" }\n ,\"microsoft.dependencymap/maps\": { \"SingularDisplayName\": \"Microsoft.DependencyMap map\" }\n ,\"microsoft.dependencymap/maps/discoverysources\": { \"SingularDisplayName\": \"Microsoft.DependencyMap maps discovery source\" }\n ,\"microsoft.deploymentmanager/artifactsources\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager artifact source\" }\n ,\"microsoft.deploymentmanager/rollouts\": { \"SingularDisplayName\": \"Rollout\" }\n ,\"microsoft.deploymentmanager/servicetopologies\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager service topology\" }\n ,\"microsoft.deploymentmanager/servicetopologies/services\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager service topologies service\" }\n ,\"microsoft.deploymentmanager/servicetopologies/services/serviceunits\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager service topologies services service unit\" }\n ,\"microsoft.deploymentmanager/steps\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager step\" }\n ,\"microsoft.desktopvirtualization/appattachpackages\": { \"SingularDisplayName\": \"App attach package\" }\n ,\"microsoft.desktopvirtualization/applicationgroups\": { \"SingularDisplayName\": \"Application group\" }\n ,\"microsoft.desktopvirtualization/hostpools\": { \"SingularDisplayName\": \"Host pool\" }\n ,\"microsoft.desktopvirtualization/scalingplans\": { \"SingularDisplayName\": \"Scaling plan\" }\n ,\"microsoft.desktopvirtualization/workspaces\": { \"SingularDisplayName\": \"Workspace\" }\n ,\"microsoft.devai/instances\": { \"SingularDisplayName\": \"Microsoft.DevAI instance\" }\n ,\"microsoft.devai/instances/experiments\": { \"SingularDisplayName\": \"Microsoft.DevAI instances experiment\" }\n ,\"microsoft.devai/instances/sandboxes\": { \"SingularDisplayName\": \"Microsoft.DevAI instances sandbox\" }\n ,\"microsoft.devai/instances/sandboxes/experiments\": { \"SingularDisplayName\": \"Microsoft.DevAI instances sandboxes experiment\" }\n ,\"microsoft.devcenter/devcenters\": { \"SingularDisplayName\": \"Dev center\" }\n ,\"microsoft.devcenter/devcenters/devboxdefinitions\": { \"SingularDisplayName\": \"Dev Box definition\" }\n ,\"microsoft.devcenter/networkconnections\": { \"SingularDisplayName\": \"Network connection\" }\n ,\"microsoft.devcenter/plans\": { \"SingularDisplayName\": \"Dev center plan\" }\n ,\"microsoft.devcenter/projects\": { \"SingularDisplayName\": \"Project\" }\n ,\"microsoft.devcenter/projects/pools\": { \"SingularDisplayName\": \"Pool\" }\n ,\"microsoft.developmentwindows365/developmentcloudpcdelegatedmsis\": { \"SingularDisplayName\": \"Microsoft.DevelopmentWindows365 development cloud pc delegated msi\" }\n ,\"microsoft.devhub/iacprofiles\": { \"SingularDisplayName\": \"Infrastructure as Code Automation\" }\n ,\"microsoft.devhub/templates\": { \"SingularDisplayName\": \"Microsoft.DevHub template\" }\n ,\"microsoft.devhub/templates/versions\": { \"SingularDisplayName\": \"Microsoft.DevHub templates version\" }\n ,\"microsoft.devhub/workflows\": { \"SingularDisplayName\": \"Microsoft.DevHub workflow\" }\n ,\"microsoft.deviceonboarding/discoveryservices\": { \"SingularDisplayName\": \"Microsoft.DeviceOnboarding discovery service\" }\n ,\"microsoft.deviceonboarding/discoveryservices/ownershipvoucherpublickeys\": { \"SingularDisplayName\": \"Microsoft.DeviceOnboarding discovery services ownership voucher public key\" }\n ,\"microsoft.deviceonboarding/onboardingservices\": { \"SingularDisplayName\": \"Microsoft.DeviceOnboarding onboarding service\" }\n ,\"microsoft.deviceonboarding/onboardingservices/policies\": { \"SingularDisplayName\": \"Microsoft.DeviceOnboarding onboarding services policy\" }\n ,\"microsoft.deviceregistry/assetendpointprofiles\": { \"SingularDisplayName\": \"IoT Asset Endpoint Profile\" }\n ,\"microsoft.deviceregistry/assets\": { \"SingularDisplayName\": \"IoT Asset\" }\n ,\"microsoft.deviceregistry/billingcontainers\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry billing container\" }\n ,\"microsoft.deviceregistry/devices\": { \"SingularDisplayName\": \"IoT Device\" }\n ,\"microsoft.deviceregistry/discoveredassetendpointprofiles\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry discovered asset endpoint profile\" }\n ,\"microsoft.deviceregistry/discoveredassets\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry discovered asset\" }\n ,\"microsoft.deviceregistry/namespaces\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespace\" }\n ,\"microsoft.deviceregistry/namespaces/assetendpointprofiles\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces asset endpoint profile\" }\n ,\"microsoft.deviceregistry/namespaces/assets\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces asset\" }\n ,\"microsoft.deviceregistry/namespaces/devices\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces device\" }\n ,\"microsoft.deviceregistry/namespaces/discoveredassetendpointprofiles\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces discovered asset endpoint profile\" }\n ,\"microsoft.deviceregistry/namespaces/discoveredassets\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces discovered asset\" }\n ,\"microsoft.deviceregistry/schemaregistries\": { \"SingularDisplayName\": \"IoT Schema Registry\" }\n ,\"microsoft.deviceregistry/schemaregistries/schemas\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry schema registries schema\" }\n ,\"microsoft.deviceregistry/schemaregistries/schemas/schemaversions\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry schema registries schemas schema version\" }\n ,\"microsoft.devices/iothubs\": { \"SingularDisplayName\": \"IoT hub\" }\n ,\"microsoft.devices/provisioningservices\": { \"SingularDisplayName\": \"Azure IoT Hub Device Provisioning Service (DPS)\" }\n ,\"microsoft.deviceupdate/accounts\": { \"SingularDisplayName\": \"Device Update for IoT Hub\" }\n ,\"microsoft.deviceupdate/updateaccounts\": { \"SingularDisplayName\": \"Device Update Account\" }\n ,\"microsoft.deviceupdate/updateaccounts/activedeployments\": { \"SingularDisplayName\": \"Device Update Active Deployment\" }\n ,\"microsoft.deviceupdate/updateaccounts/agents\": { \"SingularDisplayName\": \"Device Update Agent\" }\n ,\"microsoft.deviceupdate/updateaccounts/deployments\": { \"SingularDisplayName\": \"Device Update Deployment\" }\n ,\"microsoft.deviceupdate/updateaccounts/deviceclasses\": { \"SingularDisplayName\": \"Device Update Device Class\" }\n ,\"microsoft.deviceupdate/updateaccounts/updates\": { \"SingularDisplayName\": \"Device Update\" }\n ,\"microsoft.devops/pipelines\": { \"SingularDisplayName\": \"Microsoft.DevOps pipeline\" }\n ,\"microsoft.devopsinfrastructure/pools\": { \"SingularDisplayName\": \"Managed DevOps Pool\" }\n ,\"microsoft.devspaces/controllers\": { \"SingularDisplayName\": \"Microsoft.DevSpaces controller\" }\n ,\"microsoft.devtestlab/labs\": { \"SingularDisplayName\": \"DevTest lab\" }\n ,\"microsoft.devtestlab/labs/virtualmachines\": { \"SingularDisplayName\": \"DevTest Lab virtual machine\" }\n ,\"microsoft.devtestlab/schedules\": { \"SingularDisplayName\": \"Microsoft.DevTestLab schedule\" }\n ,\"microsoft.devtunnels/tunnelplans\": { \"SingularDisplayName\": \"Dev Tunnels Domain\" }\n ,\"microsoft.diagnostics/apollo\": { \"SingularDisplayName\": \"Microsoft.Diagnostics apollo\" }\n ,\"microsoft.digitaltwins/digitaltwinsinstances\": { \"SingularDisplayName\": \"Azure Digital Twins\" }\n ,\"microsoft.discovery/agents\": { \"SingularDisplayName\": \"Microsoft Discovery Agent\" }\n ,\"microsoft.discovery/bookshelves\": { \"SingularDisplayName\": \"Microsoft Discovery Bookshelf\" }\n ,\"microsoft.discovery/datacontainers\": { \"SingularDisplayName\": \"Microsoft Discovery Data Container\" }\n ,\"microsoft.discovery/datacontainers/dataassets\": { \"SingularDisplayName\": \"Data asset\" }\n ,\"microsoft.discovery/models\": { \"SingularDisplayName\": \"Microsoft Discovery Model\" }\n ,\"microsoft.discovery/storages\": { \"SingularDisplayName\": \"Microsoft Discovery Storage\" }\n ,\"microsoft.discovery/supercomputers\": { \"SingularDisplayName\": \"Microsoft Discovery Supercomputer\" }\n ,\"microsoft.discovery/supercomputers/nodepools\": { \"SingularDisplayName\": \"Nodepool\" }\n ,\"microsoft.discovery/tools\": { \"SingularDisplayName\": \"Microsoft Discovery Tool\" }\n ,\"microsoft.discovery/workflows\": { \"SingularDisplayName\": \"Microsoft Discovery Workflow\" }\n ,\"microsoft.discovery/workspaces\": { \"SingularDisplayName\": \"Microsoft Discovery Workspace\" }\n ,\"microsoft.discovery/workspaces/projects\": { \"SingularDisplayName\": \"Microsoft Discovery Project\" }\n ,\"microsoft.documentdb/cassandraclusters\": { \"SingularDisplayName\": \"Azure Managed Instance for Apache Cassandra\" }\n ,\"microsoft.documentdb/databaseaccounts\": { \"SingularDisplayName\": \"Cosmos DB account\" }\n ,\"microsoft.documentdb/fleets\": { \"SingularDisplayName\": \"Azure Cosmos DB Fleet\" }\n ,\"microsoft.documentdb/fleetspacepotentialdatabaseaccounts\": { \"SingularDisplayName\": \"Potential Azure Cosmos DB account\" }\n ,\"microsoft.documentdb/fleetspacepotentialdatabaseaccountswithlocations\": { \"SingularDisplayName\": \"Potential Azure Cosmos DB account\" }\n ,\"microsoft.documentdb/mongoclusters\": { \"SingularDisplayName\": \"Azure Cosmos DB for MongoDB (vCore)\" }\n ,\"microsoft.documentdb/throughputpools\": { \"SingularDisplayName\": \"Microsoft.DocumentDB throughput pool\" }\n ,\"microsoft.documentdb/throughputpools/throughputpoolaccounts\": { \"SingularDisplayName\": \"Microsoft.DocumentDB throughput pools throughput pool account\" }\n ,\"microsoft.domainregistration/domains\": { \"SingularDisplayName\": \"App Service Domain\" }\n ,\"microsoft.domainregistration/topleveldomains\": { \"SingularDisplayName\": \"Microsoft.DomainRegistration top level domain\" }\n ,\"microsoft.durabletask/namespaces\": { \"SingularDisplayName\": \"Microsoft.DurableTask namespace\" }\n ,\"microsoft.durabletask/namespaces/taskhubs\": { \"SingularDisplayName\": \"Task Hub\" }\n ,\"microsoft.durabletask/schedulers\": { \"SingularDisplayName\": \"Durable Task Scheduler\" }\n ,\"microsoft.durabletask/schedulers/taskhubs\": { \"SingularDisplayName\": \"Task Hub\" }\n ,\"microsoft.dynamics365fraudprotection/instances\": { \"SingularDisplayName\": \"Microsoft.Dynamics365FraudProtection instance\" }\n ,\"microsoft.easm/workspaces\": { \"SingularDisplayName\": \"Microsoft Defender EASM\" }\n ,\"microsoft.edge/configurations\": { \"SingularDisplayName\": \"Site configuration\" }\n ,\"microsoft.edge/configurations/arcgatewayconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations arc gateway configuration\" }\n ,\"microsoft.edge/configurations/connectivityconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations connectivity configuration\" }\n ,\"microsoft.edge/configurations/dynamicconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations dynamic configuration\" }\n ,\"microsoft.edge/configurations/dynamicconfigurations/versions\": { \"SingularDisplayName\": \"Microsoft.Edge configurations dynamic configurations version\" }\n ,\"microsoft.edge/configurations/networkconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations network configuration\" }\n ,\"microsoft.edge/configurations/securityconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations security configuration\" }\n ,\"microsoft.edge/configurations/timeserverconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations time server configuration\" }\n ,\"microsoft.edge/connectivitystatuses\": { \"SingularDisplayName\": \"Microsoft.Edge connectivity statuse\" }\n ,\"microsoft.edge/disconnectedoperations\": { \"SingularDisplayName\": \"Azure Local - disconnected operations\" }\n ,\"microsoft.edge/siteawareresourcetypes\": { \"SingularDisplayName\": \"Microsoft.Edge site aware resource type\" }\n ,\"microsoft.edge/sites\": { \"SingularDisplayName\": \"Site manager - Azure Arc\" }\n ,\"microsoft.edge/updates\": { \"SingularDisplayName\": \"Microsoft.Edge update\" }\n ,\"microsoft.edgemarketplace/offers\": { \"SingularDisplayName\": \"Microsoft.EdgeMarketplace offer\" }\n ,\"microsoft.edgemarketplace/publishers\": { \"SingularDisplayName\": \"Microsoft.EdgeMarketplace publisher\" }\n ,\"microsoft.edgeorder/addresses\": { \"SingularDisplayName\": \"Azure Edge Hardware Center Address\" }\n ,\"microsoft.edgeorder/bootstrapconfigurations\": { \"SingularDisplayName\": \"Site Key\" }\n ,\"microsoft.edgeorder/orderitems\": { \"SingularDisplayName\": \"Azure Edge Hardware Center\" }\n ,\"microsoft.edgeorder/virtual_orderitems\": { \"SingularDisplayName\": \"Device\" }\n ,\"microsoft.edgezones/extendedzones\": { \"SingularDisplayName\": \"Microsoft.EdgeZones extended zone\" }\n ,\"microsoft.education/grants\": { \"SingularDisplayName\": \"Microsoft.Education grant\" }\n ,\"microsoft.education/labs\": { \"SingularDisplayName\": \"Microsoft.Education lab\" }\n ,\"microsoft.education/labs/joinrequests\": { \"SingularDisplayName\": \"Microsoft.Education labs join request\" }\n ,\"microsoft.education/labs/students\": { \"SingularDisplayName\": \"Microsoft.Education labs student\" }\n ,\"microsoft.education/studentlabs\": { \"SingularDisplayName\": \"Microsoft.Education student lab\" }\n ,\"microsoft.elastic/monitors\": { \"SingularDisplayName\": \"Elastic Cloud Resource\" }\n ,\"microsoft.elasticsan/elasticsans\": { \"SingularDisplayName\": \"Elastic SAN\" }\n ,\"microsoft.energydataplatform/energyservices\": { \"SingularDisplayName\": \"Microsoft.EnergyDataPlatform energy service\" }\n ,\"microsoft.enterpriseknowledgegraph/services\": { \"SingularDisplayName\": \"Microsoft.EnterpriseKnowledgeGraph service\" }\n ,\"microsoft.enterprisesupport/enterprisesupports\": { \"SingularDisplayName\": \"Microsoft.EnterpriseSupport enterprise support\" }\n ,\"microsoft.eventgrid/domains\": { \"SingularDisplayName\": \"Event Grid Domain\" }\n ,\"microsoft.eventgrid/domains/topics\": { \"SingularDisplayName\": \"Event Grid Domain Topic\" }\n ,\"microsoft.eventgrid/eventsubscriptions\": { \"SingularDisplayName\": \"Microsoft.EventGrid event subscription\" }\n ,\"microsoft.eventgrid/extensiontopics\": { \"SingularDisplayName\": \"Event Grid extension topic\" }\n ,\"microsoft.eventgrid/namespaces\": { \"SingularDisplayName\": \"Event Grid Namespace\" }\n ,\"microsoft.eventgrid/namespaces/topics\": { \"SingularDisplayName\": \"Event Grid Namespace Topic\" }\n ,\"microsoft.eventgrid/namespaces/topics/eventsubscriptions\": { \"SingularDisplayName\": \"Event Subscription\" }\n ,\"microsoft.eventgrid/namespaces/topicspaces\": { \"SingularDisplayName\": \"Event Grid Topic Space\" }\n ,\"microsoft.eventgrid/partnerconfigurations\": { \"SingularDisplayName\": \"Event Grid Partner Configuration\" }\n ,\"microsoft.eventgrid/partnerdestinations\": { \"SingularDisplayName\": \"Event Grid Partner Destination\" }\n ,\"microsoft.eventgrid/partnernamespaces\": { \"SingularDisplayName\": \"Event Grid Partner Namespace\" }\n ,\"microsoft.eventgrid/partnernamespaces/channels\": { \"SingularDisplayName\": \"Event Grid Channel\" }\n ,\"microsoft.eventgrid/partnerregistrations\": { \"SingularDisplayName\": \"Event Grid Partner Registration\" }\n ,\"microsoft.eventgrid/partnertopics\": { \"SingularDisplayName\": \"Event Grid Partner Topic\" }\n ,\"microsoft.eventgrid/systemtopics\": { \"SingularDisplayName\": \"Event Grid System Topic\" }\n ,\"microsoft.eventgrid/systemtopics/eventsubscriptions\": { \"SingularDisplayName\": \"Event Grid Subscriptions\" }\n ,\"microsoft.eventgrid/topics\": { \"SingularDisplayName\": \"Event Grid Topic\" }\n ,\"microsoft.eventgrid/topictypes\": { \"SingularDisplayName\": \"Microsoft.EventGrid topic type\" }\n ,\"microsoft.eventgrid/verifiedpartners\": { \"SingularDisplayName\": \"Microsoft.EventGrid verified partner\" }\n ,\"microsoft.eventhub/clusters\": { \"SingularDisplayName\": \"Event Hubs Cluster\" }\n ,\"microsoft.eventhub/namespaces\": { \"SingularDisplayName\": \"Event Hubs namespace\" }\n ,\"microsoft.eventhub/namespaces/disasterrecoveryconfigs\": { \"SingularDisplayName\": \"Event Hubs Geo-DR Alias\" }\n ,\"microsoft.eventhub/namespaces/eventhubs\": { \"SingularDisplayName\": \"Event Hubs Instance\" }\n ,\"microsoft.eventhub/namespaces/providers/diagnosticsettings\": { \"SingularDisplayName\": \"Diagnostic settings\" }\n ,\"microsoft.eventhub/namespaces/schemagroups\": { \"SingularDisplayName\": \"Schema Group\" }\n ,\"microsoft.experimentation/experimentworkspaces\": { \"SingularDisplayName\": \"Experiment Workspace\" }\n ,\"microsoft.extendedlocation/customlocations\": { \"SingularDisplayName\": \"Custom location\" }\n ,\"microsoft.fabric/capacities\": { \"SingularDisplayName\": \"Fabric Capacity\" }\n ,\"microsoft.fabric/privatelinkservicesforfabric\": { \"SingularDisplayName\": \"Microsoft.Fabric private link services for fabric\" }\n ,\"microsoft.fabric/privatelinkservicesforfabric/operationresults\": { \"SingularDisplayName\": \"Microsoft.Fabric private link services for fabric operation result\" }\n ,\"microsoft.fabric/privatelinkservicesforfabric/privateendpointconnections\": { \"SingularDisplayName\": \"Microsoft.Fabric private link services for fabric private endpoint connection\" }\n ,\"microsoft.fabric/privatelinkservicesforfabric/privatelinkresources\": { \"SingularDisplayName\": \"Microsoft.Fabric private link services for fabric private link resource\" }\n ,\"microsoft.fairfieldgardens/deviceprovisioningstates\": { \"SingularDisplayName\": \"Microsoft.FairfieldGardens device provisioning state\" }\n ,\"microsoft.fairfieldgardens/provisioningresources\": { \"SingularDisplayName\": \"Fairfield Gardens\" }\n ,\"microsoft.fairfieldgardens/provisioningresources/provisioningpolicies\": { \"SingularDisplayName\": \"Provisioning policy\" }\n ,\"microsoft.falcon/namespaces\": { \"SingularDisplayName\": \"Microsoft.Falcon namespace\" }\n ,\"microsoft.features/featureprovidernamespaces/featureconfigurations\": { \"SingularDisplayName\": \"Preview features\" }\n ,\"microsoft.fidalgo/devcenters\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenter\" }\n ,\"microsoft.fidalgo/devcenters/attachednetworks\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters attachednetwork\" }\n ,\"microsoft.fidalgo/devcenters/catalogs\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters catalog\" }\n ,\"microsoft.fidalgo/devcenters/catalogs/items\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters catalogs item\" }\n ,\"microsoft.fidalgo/devcenters/devboxdefinitions\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters devboxdefinition\" }\n ,\"microsoft.fidalgo/devcenters/environmenttypes\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters environment type\" }\n ,\"microsoft.fidalgo/devcenters/galleries\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters gallery\" }\n ,\"microsoft.fidalgo/devcenters/galleries/images\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters galleries image\" }\n ,\"microsoft.fidalgo/devcenters/galleries/images/versions\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters galleries images version\" }\n ,\"microsoft.fidalgo/devcenters/mappings\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters mapping\" }\n ,\"microsoft.fidalgo/machinedefinitions\": { \"SingularDisplayName\": \"Microsoft.Fidalgo machinedefinition\" }\n ,\"microsoft.fidalgo/networksettings\": { \"SingularDisplayName\": \"Microsoft.Fidalgo networksetting\" }\n ,\"microsoft.fidalgo/networksettings/healthchecks\": { \"SingularDisplayName\": \"Microsoft.Fidalgo networksettings healthcheck\" }\n ,\"microsoft.fidalgo/projects\": { \"SingularDisplayName\": \"Microsoft.Fidalgo project\" }\n ,\"microsoft.fidalgo/projects/attachednetworks\": { \"SingularDisplayName\": \"Microsoft.Fidalgo projects attachednetwork\" }\n ,\"microsoft.fidalgo/projects/devboxdefinitions\": { \"SingularDisplayName\": \"Microsoft.Fidalgo projects devboxdefinition\" }\n ,\"microsoft.fidalgo/projects/environments\": { \"SingularDisplayName\": \"Microsoft.Fidalgo projects environment\" }\n ,\"microsoft.fidalgo/projects/pools\": { \"SingularDisplayName\": \"Microsoft.Fidalgo projects pool\" }\n ,\"microsoft.fileshares/fileshares\": { \"SingularDisplayName\": \"File share\" }\n ,\"microsoft.fluidrelay/fluidrelayservers\": { \"SingularDisplayName\": \"Fluid Relay\" }\n ,\"microsoft.footprintmonitoring/profiles\": { \"SingularDisplayName\": \"Microsoft.FootprintMonitoring profile\" }\n ,\"microsoft.footprintmonitoring/profiles/experiments\": { \"SingularDisplayName\": \"Microsoft.FootprintMonitoring profiles experiment\" }\n ,\"microsoft.footprintmonitoring/profiles/measurementendpoints\": { \"SingularDisplayName\": \"Microsoft.FootprintMonitoring profiles measurement endpoint\" }\n ,\"microsoft.footprintmonitoring/profiles/measurementendpoints/conditions\": { \"SingularDisplayName\": \"Microsoft.FootprintMonitoring profiles measurement endpoints condition\" }\n ,\"microsoft.gallery/myareas/galleryitems\": { \"SingularDisplayName\": \"Template\" }\n ,\"microsoft.genomics/accounts\": { \"SingularDisplayName\": \"Genomics account\" }\n ,\"microsoft.graph/azureadapplication\": { \"SingularDisplayName\": \"Entra application\" }\n ,\"microsoft.graph/azureadapplicationprototype\": { \"SingularDisplayName\": \"Microsoft.Graph Azure ad application prototype\" }\n ,\"microsoft.graphservices/accounts\": { \"SingularDisplayName\": \"Metered API account\" }\n ,\"microsoft.guestconfiguration/guestconfigurationassignments\": { \"SingularDisplayName\": \"Microsoft.GuestConfiguration guest configuration assignment\" }\n ,\"microsoft.guestconfiguration/guestconfigurationassignments/reports\": { \"SingularDisplayName\": \"Microsoft.GuestConfiguration guest configuration assignments report\" }\n ,\"microsoft.hanaonazure/hanainstances\": { \"SingularDisplayName\": \"SAP HANA on Azure\" }\n ,\"microsoft.hanaonazure/sapmonitors\": { \"SingularDisplayName\": \"Azure Monitor for SAP Solutions (classic)\" }\n ,\"microsoft.hardware/orders\": { \"SingularDisplayName\": \"Microsoft.Hardware order\" }\n ,\"microsoft.hardwaresecuritymodules/cloudhsmclusters\": { \"SingularDisplayName\": \"Azure Cloud HSM\" }\n ,\"microsoft.hdinsight/clusterpools\": { \"SingularDisplayName\": \"Azure HDInsight on AKS cluster pool\" }\n ,\"microsoft.hdinsight/clusterpools/clusters\": { \"SingularDisplayName\": \"Azure HDInsight on AKS cluster\" }\n ,\"microsoft.hdinsight/clusterpools/clusters/instanceviews\": { \"SingularDisplayName\": \"Microsoft.HDInsight clusterpools clusters instance view\" }\n ,\"microsoft.hdinsight/clusters\": { \"SingularDisplayName\": \"HDInsight cluster\" }\n ,\"microsoft.healthbot/healthbots\": { \"SingularDisplayName\": \"Healthcare agent service\" }\n ,\"microsoft.healthcareapis/services\": { \"SingularDisplayName\": \"Azure API for FHIR\" }\n ,\"microsoft.healthcareapis/workspaces\": { \"SingularDisplayName\": \"Health Data Services workspace\" }\n ,\"microsoft.healthcareapis/workspaces/dicomservices\": { \"SingularDisplayName\": \"DICOM service\" }\n ,\"microsoft.healthcareapis/workspaces/fhirservices\": { \"SingularDisplayName\": \"FHIR service\" }\n ,\"microsoft.healthcareapis/workspaces/iotconnectors\": { \"SingularDisplayName\": \"MedTech service\" }\n ,\"microsoft.healthdataaiservices/deidservices\": { \"SingularDisplayName\": \"De-identification Service\" }\n ,\"microsoft.healthmodel/healthmodels\": { \"SingularDisplayName\": \"Health Model\" }\n ,\"microsoft.healthplatform/accounts\": { \"SingularDisplayName\": \"Microsoft.HealthPlatform account\" }\n ,\"microsoft.help/diagnostics\": { \"SingularDisplayName\": \"Microsoft.Help diagnostic\" }\n ,\"microsoft.help/selfhelp\": { \"SingularDisplayName\": \"Microsoft.Help self help\" }\n ,\"microsoft.help/simplifiedsolutions\": { \"SingularDisplayName\": \"Microsoft.Help simplified solution\" }\n ,\"microsoft.help/solutions\": { \"SingularDisplayName\": \"Microsoft.Help solution\" }\n ,\"microsoft.help/troubleshooters\": { \"SingularDisplayName\": \"Microsoft.Help troubleshooter\" }\n ,\"microsoft.hpcworkbench/instances\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instance\" }\n ,\"microsoft.hpcworkbench/instances/chambers\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chamber\" }\n ,\"microsoft.hpcworkbench/instances/chambers/accessprofiles\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers access profile\" }\n ,\"microsoft.hpcworkbench/instances/chambers/filerequests\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers file request\" }\n ,\"microsoft.hpcworkbench/instances/chambers/files\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers file\" }\n ,\"microsoft.hpcworkbench/instances/chambers/storages\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers storage\" }\n ,\"microsoft.hpcworkbench/instances/chambers/workloads\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers workload\" }\n ,\"microsoft.hpcworkbench/instances/consortiums\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances consortium\" }\n ,\"microsoft.hybridcloud/cloudconnections\": { \"SingularDisplayName\": \"Microsoft.HybridCloud cloud connection\" }\n ,\"microsoft.hybridcloud/cloudconnectors\": { \"SingularDisplayName\": \"Microsoft.HybridCloud cloud connector\" }\n ,\"microsoft.hybridcompute/arcgatewayassociatedresources\": { \"SingularDisplayName\": \"Arc gateway associated resource\" }\n ,\"microsoft.hybridcompute/arcserverwithwac\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/gateways\": { \"SingularDisplayName\": \"Arc gateway\" }\n ,\"microsoft.hybridcompute/licenses\": { \"SingularDisplayName\": \"Extended Security Updates - Windows Server 2012/R2\" }\n ,\"microsoft.hybridcompute/machines\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/machines/microsoft.awsconnector/ec2instances\": { \"SingularDisplayName\": \"Microsoft.AwsConnector ec2 instance\" }\n ,\"microsoft.hybridcompute/machines/microsoft.connectedvmwarevsphere/virtualmachineinstances\": { \"SingularDisplayName\": \"VMware + AVS virtual machine\" }\n ,\"microsoft.hybridcompute/machines/providers/guestconfigurationassignments\": { \"SingularDisplayName\": \"Guest Assignment\" }\n ,\"microsoft.hybridcompute/machinesesu\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/machinespaygo\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/machinessoftwareassurance\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/machinessovereign\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/privatelinkscopes\": { \"SingularDisplayName\": \"Azure Arc Private Link Scope\" }\n ,\"microsoft.hybridcompute/settings\": { \"SingularDisplayName\": \"Microsoft.HybridCompute setting\" }\n ,\"microsoft.hybridconnectivity/endpoints\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity endpoint\" }\n ,\"microsoft.hybridconnectivity/endpoints/serviceconfigurations\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity endpoints service configuration\" }\n ,\"microsoft.hybridconnectivity/publiccloudconnectors\": { \"SingularDisplayName\": \"Multicloud connector\" }\n ,\"microsoft.hybridconnectivity/solutionconfigurations\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity solution configuration\" }\n ,\"microsoft.hybridconnectivity/solutionconfigurations/inventory\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity solution configurations inventory\" }\n ,\"microsoft.hybridconnectivity/solutiontypes\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity solution type\" }\n ,\"microsoft.hybridcontainerservice/kubernetesversions\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService kubernetes version\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusterinstances\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService provisioned cluster instance\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusterinstances/agentpools\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService provisioned cluster instances agent pool\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusterinstances/hybrididentitymetadata\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService provisioned cluster instances hybrid identity metadata\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusterinstances/upgradeprofiles\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService provisioned cluster instances upgrade profile\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusters\": { \"SingularDisplayName\": \"Kubernetes hybrid - Azure Arc\" }\n ,\"microsoft.hybridcontainerservice/skus\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService SKU\" }\n ,\"microsoft.hybridcontainerservice/storagespaces\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService storage space\" }\n ,\"microsoft.hybridcontainerservice/virtualnetworks\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService virtual network\" }\n ,\"microsoft.hybriddata/datamanagers\": { \"SingularDisplayName\": \"Microsoft.HybridData data manager\" }\n ,\"microsoft.hybriddata/datamanagers/dataservices\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data service\" }\n ,\"microsoft.hybriddata/datamanagers/dataservices/jobdefinitions\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data services job definition\" }\n ,\"microsoft.hybriddata/datamanagers/dataservices/jobdefinitions/jobs\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data services job definitions job\" }\n ,\"microsoft.hybriddata/datamanagers/datastores\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data store\" }\n ,\"microsoft.hybriddata/datamanagers/datastoretypes\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data store type\" }\n ,\"microsoft.hybriddata/datamanagers/publickeys\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers public key\" }\n ,\"microsoft.hybridnetwork/configurationgroupvalues\": { \"SingularDisplayName\": \"Configuration Group Value\" }\n ,\"microsoft.hybridnetwork/devices\": { \"SingularDisplayName\": \"Azure Network Function Manager ? Device\" }\n ,\"microsoft.hybridnetwork/networkfunctions\": { \"SingularDisplayName\": \"Azure Network Function Manager ? Network Function\" }\n ,\"microsoft.hybridnetwork/proxypublishers\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publisher\" }\n ,\"microsoft.hybridnetwork/proxypublishers/artifactstores\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers artifact store\" }\n ,\"microsoft.hybridnetwork/proxypublishers/configurationgroupschemas\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers configuration group schema\" }\n ,\"microsoft.hybridnetwork/proxypublishers/networkfunctiondefinitiongroups\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers network function definition group\" }\n ,\"microsoft.hybridnetwork/proxypublishers/networkfunctiondefinitiongroups/networkfunctiondefinitionversions\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers network function definition groups network function definition version\" }\n ,\"microsoft.hybridnetwork/proxypublishers/networkservicedesigngroups\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers network service design group\" }\n ,\"microsoft.hybridnetwork/proxypublishers/networkservicedesigngroups/networkservicedesignversions\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers network service design groups network service design version\" }\n ,\"microsoft.hybridnetwork/publishers\": { \"SingularDisplayName\": \"Publisher\" }\n ,\"microsoft.hybridnetwork/publishers/artifactstores\": { \"SingularDisplayName\": \"Publisher Artifact Store\" }\n ,\"microsoft.hybridnetwork/publishers/artifactstores/artifactmanifests\": { \"SingularDisplayName\": \"Publisher Artifact Manifest\" }\n ,\"microsoft.hybridnetwork/publishers/configurationgroupschemas\": { \"SingularDisplayName\": \"Configuration Group Schema\" }\n ,\"microsoft.hybridnetwork/publishers/networkfunctiondefinitiongroups\": { \"SingularDisplayName\": \"Network Function Definition\" }\n ,\"microsoft.hybridnetwork/publishers/networkfunctiondefinitiongroups/networkfunctiondefinitionversions\": { \"SingularDisplayName\": \"Network Function Definition Version\" }\n ,\"microsoft.hybridnetwork/publishers/networkservicedesigngroups\": { \"SingularDisplayName\": \"Network Service Design\" }\n ,\"microsoft.hybridnetwork/publishers/networkservicedesigngroups/networkservicedesignversions\": { \"SingularDisplayName\": \"Network Service Design Version\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management container\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/rolloutsequences\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers rollout sequence\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/rollouttiers\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers rollout tier\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/updatespecifications\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers update specification\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/updatespecifications/rollouts\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers update specifications rollout\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/updatespecifications/rollouts/statuses\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers update specifications rollouts statuse\" }\n ,\"microsoft.hybridnetwork/sitenetworkservices\": { \"SingularDisplayName\": \"Site Network Service\" }\n ,\"microsoft.hybridnetwork/sites\": { \"SingularDisplayName\": \"Site\" }\n })[tolower(id)]\n}\n", - "$fxv#10": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// See known issues @ https://github.com/microsoft/finops-toolkit/issues/1111\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Prices |=========================================================================================================\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_transform_v1_2 function\n.create-or-alter function\nwith (docstring='Transforms Prices_raw into FOCUS 1.2.', folder='Prices')\nPrices_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n let prices = materialize(\n Prices_raw\n | extend PricingCurrency = coalesce(Currency, CurrencyCode) // CurrencyCode last as a fallback only\n | extend x_SkuId = coalesce(SkuId, SkuID)\n | extend x_SkuMeterId = coalesce(MeterId, MeterID)\n | extend x_SkuProductId = coalesce(ProductId, ProductID)\n | extend x_SkuTerm = isoMonths(Term)\n | project-rename\n SkuMeter = MeterName,\n x_BaseUnitPrice = BasePrice,\n x_EffectivePeriodEnd = EffectiveEndDate,\n x_EffectivePeriodStart = EffectiveStartDate,\n x_PricingUnitDescription = UnitOfMeasure,\n x_SkuIncludedQuantity = IncludedQuantity,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuMeterType = MeterType,\n x_SkuOfferId = OfferID,\n x_SkuPartNumber = PartNumber,\n x_SkuPriceType = PriceType,\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTier = TierMinimumUnits\n | extend ContractedUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', UnitPrice, real(null)) // UnitPrice for savings plan is not the on-demand unit price\n | extend ListUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', MarketPrice, real(null)) // MarketPrice for savings plan is not the list price\n | extend ChargeCategory = case(\n x_SkuPriceType == 'Consumption', 'Usage',\n x_SkuPriceType == 'ReservedInstance', 'Purchase',\n x_SkuPriceType == 'SavingsPlan', 'Usage', // Savings plan prices are for committed usage, not the purchase\n ''\n )\n | extend SkuPriceIdv2 = strcat(case(x_SkuPriceType == 'Consumption', 'OD', x_SkuPriceType == 'ReservedInstance', 'RI', x_SkuPriceType == 'SavingsPlan', 'SP', 'XX'), substring(ChargeCategory, 0, 1), x_SkuTerm, '_', x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType, '_', x_SkuTier, x_SkuOfferId)\n | extend x_BillingAccountId = iff(BillingAccountId startswith '/', split(BillingAccountId, '/')[-1], coalesce(BillingAccountId, EnrollmentNumber))\n | extend x_BillingProfileId = iff(BillingProfileId startswith '/', split(BillingProfileId, '/')[-1], coalesce(BillingProfileId, EnrollmentNumber))\n | extend tmp_SavingsPlanKey = strcat(x_SkuMeterId, x_SkuProductId, x_SkuId, x_SkuTier, x_SkuOfferId)\n //\n // Get latest ingested row based on the unique ID\n | extend x_IngestionTime = ingestion_time()\n );\n //\n // Meters for reservations and savings plans to identify commitment eligibility\n let riMeters = prices | where x_SkuPriceType == 'ReservedInstance' | distinct x_SkuMeterId;\n let spMeters = prices | where x_SkuPriceType == 'SavingsPlan' | distinct x_SkuMeterId;\n //\n // Copy list/base/contracted prices from on-demand SKUs\n prices\n | where x_SkuPriceType == 'SavingsPlan'\n // If we use join, specify the shuffle key\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter hint.strategy=shuffle (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | lookup kind=leftouter (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | extend ListUnitPrice = coalesce(ListUnitPrice, ListUnitPrice1)\n | extend ContractedUnitPrice = coalesce(ContractedUnitPrice, ContractedUnitPrice1)\n | extend x_BaseUnitPrice = coalesce(x_BaseUnitPrice, x_BaseUnitPrice1)\n | project-away ListUnitPrice1, ContractedUnitPrice1, x_BaseUnitPrice1, tmp_SavingsPlanKey\n | union ((prices | where x_SkuPriceType != 'SavingsPlan'))\n //\n // Set CommitmentDiscountCategory for reuse\n | extend CommitmentDiscountCategory = case(\n x_SkuPriceType == 'ReservedInstance', 'Usage',\n x_SkuPriceType == 'SavingsPlan', 'Spend',\n ''\n )\n //\n // Calculate commitment discount eligibility\n // TODO: Would a join be faster?\n // TODO: Check this to ensure it's correct\n | extend x_CommitmentDiscountSpendEligibility = iff(x_SkuMeterId in (riMeters) and x_SkuPriceType != 'ReservedInstance', 'Eligible', 'Not Eligible')\n | extend x_CommitmentDiscountUsageEligibility = iff(x_SkuMeterId in (spMeters), 'Eligible', 'Not Eligible')\n //\n // TODO: Implement x_CommitmentDiscountNormalizedRatio\n | extend x_CommitmentDiscountNormalizedRatio = real(null)\n //\n // Add PricingUnit and x_PricingBlockSize\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter (PricingUnits) on x_PricingUnitDescription | project-away x_PricingUnitDescription1\n | lookup kind=leftouter (PricingUnits) on x_PricingUnitDescription\n //\n | extend x_EffectiveUnitPrice = iff(x_SkuPriceType == 'SavingsPlan', UnitPrice, real(null)) // Savings plan prices are for the effective price, not the contracted price\n | extend x_EffectiveUnitPriceDiscount = ContractedUnitPrice - x_EffectiveUnitPrice\n | extend x_ContractedUnitPriceDiscount = ListUnitPrice - ContractedUnitPrice\n | extend x_TotalUnitPriceDiscount = ListUnitPrice - x_EffectiveUnitPrice\n | project\n BillingAccountId = tolower(case(\n BillingProfileId startswith '/', BillingProfileId,\n BillingAccountId startswith '/', BillingAccountId,\n strcat('/providers/microsoft.billing/billingaccounts/', x_BillingAccountId, iff(x_BillingProfileId == x_BillingAccountId, '', strcat('/billingprofiles/', x_BillingProfileId)))\n )),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName, x_BillingProfileId),\n BillingCurrency = coalesce(BillingCurrency, CurrencyCode, Currency), // Currency last as a fallback only\n ChargeCategory,\n CommitmentDiscountCategory,\n CommitmentDiscountType = case(\n x_SkuPriceType == 'ReservedInstance', 'Reservation',\n x_SkuPriceType == 'SavingsPlan', 'Savings plan',\n ''\n ),\n CommitmentDiscountUnit = case(\n isempty(CommitmentDiscountCategory), '',\n CommitmentDiscountCategory == 'Spend', PricingCurrency,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio == real(1), PricingUnit,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio > real(1), strcat('Normalized ', PricingUnit),\n ''\n ),\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory = case(\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed',\n ''\n ),\n PricingCurrency,\n PricingUnit,\n SkuId = coalesce(ProductId, ProductID),\n SkuMeter,\n SkuPriceId = strcat(x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType),\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement = case(\n strlen(x_BillingAccountId) > 32, 'MCA',\n strlen(x_BillingAccountId) < 32, 'EA',\n 'Unknown'\n ),\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent = 1.0 * x_ContractedUnitPriceDiscount / ListUnitPrice * 100,\n x_EffectivePeriodEnd = startofmonth(x_EffectivePeriodEnd + 1h),\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent = 1.0 * x_EffectiveUnitPriceDiscount / ContractedUnitPrice * 100,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingSubcategory = case(\n x_SkuPriceType == 'Consumption' and (x_SkuIncludedQuantity > 0 or x_SkuTier > 0), 'Tiered',\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed Spend',\n ''\n ),\n x_PricingUnitDescription,\n x_SkuDescription = Product,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName = coalesce(x_SourceName, 'Cost Management'),\n x_SourceProvider = coalesce(x_SourceProvider, 'Microsoft'),\n x_SourceType = coalesce(x_SourceType, 'PriceSheet'),\n x_SourceVersion = coalesce(x_SourceVersion, '2023-05-01'),\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent = 1.0 * x_TotalUnitPriceDiscount / ListUnitPrice * 100\n}\n\n// Prices_final_v1_2 table\n.create-merge table Prices_final_v1_2 (\n BillingAccountId: string,\n BillingAccountName: string,\n BillingCurrency: string,\n ChargeCategory: string,\n CommitmentDiscountCategory: string,\n CommitmentDiscountType: string,\n CommitmentDiscountUnit: string,\n ContractedUnitPrice: real,\n ListUnitPrice: real,\n PricingCategory: string,\n PricingCurrency: string, // Azure\n PricingUnit: string,\n SkuId: string,\n SkuMeter: string, // Azure\n SkuPriceId: string,\n SkuPriceIdv2: string, // Hubs add-on\n x_BaseUnitPrice: real, // Azure\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure MCA\n x_BillingProfileId: string, // Azure MCA\n x_CommitmentDiscountNormalizedRatio: real, // Hubs add-on\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_ContractedUnitPriceDiscount: real, // Hubs add-on\n x_ContractedUnitPriceDiscountPercent: real, // Hubs add-on\n x_EffectivePeriodEnd: datetime, // Azure\n x_EffectivePeriodStart: datetime, // Azure\n x_EffectiveUnitPrice: real, // Azure\n x_EffectiveUnitPriceDiscount: real, // Hubs add-on\n x_EffectiveUnitPriceDiscountPercent: real, // Hubs add-on\n x_IngestionTime: datetime, // Hubs add-on\n x_PricingBlockSize: real, // Hubs add-on\n x_PricingSubcategory: string, // Hubs add-on\n x_PricingUnitDescription: string, // Azure\n x_SkuDescription: string, // Azure\n x_SkuId: string, // Azure\n x_SkuIncludedQuantity: real, // Azure EA\n x_SkuMeterCategory: string, // Azure\n x_SkuMeterId: string, // Azure\n x_SkuMeterSubcategory: string, // Azure\n x_SkuMeterType: string, // Azure\n x_SkuPriceType: string, // Azure\n x_SkuProductId: string, // Azure\n x_SkuRegion: string, // Azure\n x_SkuServiceFamily: string, // Azure\n x_SkuOfferId: string, // Azure EA\n x_SkuPartNumber: string, // Azure EA\n x_SkuTerm: int, // Azure\n x_SkuTier: real, // Azure MCA\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_TotalUnitPriceDiscount: real, // Hubs add-on\n x_TotalUnitPriceDiscountPercent: real // Hubs add-on\n)\n\n// Update policy for Prices_raw -> Prices_final_v1_2\n.alter table Prices_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Prices_raw\",\n \"Query\": \"Prices_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Cost and usage |=================================================================================================\n// Supported versions:\n// - MS: 1.2-preview, 1.0, 1.0-preview(v1)\n// https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0\n// https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024\n// https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 \n// https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All costs transformed to FOCUS 1.2.', folder='Costs')\nCosts_transform_v1_2()\n{\n let checkString = (column: string, oldValue: string, newValue: string) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n let checkInt = (column: string, oldValue: int, newValue: int) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n let checkReal = (column: string, oldValue: real, newValue: real) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n Costs_raw\n //\n // Dedupe rows\n | extend x_IngestionTime = ingestion_time()\n | extend x_ChargeId = ''\n // TODO: Consider adding a unique charge ID per row\n // hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // // 1. Resource hierarchy (including resource name), highest to lowest\n // BillingAccountId,\n // x_InvoiceSectionId,\n // x_AccountOwnerId,\n // SubAccountId,\n // x_ResourceGroupName,\n // ResourceName,\n // // 2. Resource details\n // ResourceId,\n // RegionId,\n // Tags,\n // CommitmentDiscountId,\n // x_CostCenter,\n // // 4. Meter details\n // SkuPriceId,\n // x_SkuMeterId,\n // x_SkuPartNumber,\n // x_SkuOfferId,\n // x_SkuDetails,\n // // 5. Date\n // ChargePeriodStart\n // ))\n //\n // Identify data quality issues\n // TODO: Remove x_SourceChanges in v1_3 (or later)\n | extend x_SourceChanges = trim_end(',', strcat(\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based', 'InvalidChargeFrequency,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and EffectiveCost > 0, 'InvalidEffectiveCost,', ''),\n iff((isempty(ContractedCost) or ContractedCost == 0) and EffectiveCost != 0, 'MissingContractedCost,', ''),\n iff((isempty(ContractedUnitPrice) or ContractedUnitPrice == 0) and x_EffectiveUnitPrice != 0, 'MissingContractedUnitPrice,', ''),\n iff(ListCost < ContractedCost, 'ListCostLessThanContractedCost,', ''),\n iff(ContractedCost < EffectiveCost, 'ContractedCostLessThanEffectiveCost,', ''),\n iff((isempty(ListCost) or ListCost == 0) and (ContractedCost != 0 or EffectiveCost != 0), 'MissingListCost,', ''),\n iff((isempty(ListUnitPrice) or ListUnitPrice == 0) and (ContractedUnitPrice != 0 or x_EffectiveUnitPrice != 0), 'MissingListUnitPrice,', ''),\n iff((isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001)\n or (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001),\n 'XEffectiveUnitPriceRoundingError,', ''),\n iff(ConsumedQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingConsumedQuantity,', ''),\n iff(PricingQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingPricingQuantity,', ''),\n iff(isempty(ProviderName), 'MissingProviderName,', ''),\n iff(isempty(PublisherName), 'MissingPublisherName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceId), 'MissingResourceId,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceName), 'MissingResourceName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceType), 'MissingResourceType,', ''),\n iff(BilledCost > 0 and x_BilledUnitPrice == 0, 'MissingXBilledUnitPrice,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(x_ResourceType), 'MissingXResourceType,', ''),\n iff(PricingCategory == 'Standard' and isnotempty(CommitmentDiscountId) and ChargeCategory == 'Usage', 'PricingCategoryShouldBeCommitted,', ''),\n iff(x_SkuTerm == '1Year' or x_SkuTerm == '3Years' or x_SkuTerm == '5Years', 'SkuTermShouldBeAnInteger,', '')\n ))\n //\n // Handle provider columns that moved to FOCUS\n | extend PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency)\n //\n // Backup original prices/costs before the merge\n | extend old_ContractedCost = ContractedCost\n | extend old_ContractedUnitPrice = ContractedUnitPrice\n | extend old_ListCost = ListCost\n | extend old_ListUnitPrice = ListUnitPrice\n | extend old_x_EffectiveUnitPrice = x_EffectiveUnitPrice\n //\n // Fix columns needed in other changes\n | extend old_ProviderName = ProviderName, ProviderName = case(\n isnotempty(ProviderName), ProviderName,\n isnotempty(coalesce(x_CostCategories, x_Discount, x_Operation, x_ServiceCode, x_UsageType)), 'AWS',\n isnotempty(coalesce(tostring(UsageAmount), tostring(x_Cost), x_Credits, x_CostType, tostring(x_CurrencyConversionRate), tostring(x_ExportTime), x_Project, x_ServiceId)), 'GCP',\n isnotempty(coalesce(x_BillingProfileId, x_InvoiceSectionId)), 'Microsoft',\n ''\n )\n //\n // Identify source\n | extend x_SourceName = coalesce(x_SourceName, iff(isnotempty(x_BillingProfileId), 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(isnotempty(x_BillingProfileId), 'FocusCost', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, case(\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)) and isempty(SkuPriceDetails) and isnotempty(x_SkuDetails), '1.2-preview',\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)), '1.2',\n isnotempty(coalesce(ChargeClass, CommitmentDiscountStatus, tostring(ConsumedQuantity), ConsumedUnit, tostring(ContractedCost), tostring(ContractedUnitPrice), RegionId, RegionName)), '1.0',\n isnotempty(coalesce(ChargeSubcategory, Region, tostring(UsageQuantity), UsageUnit)), iff(ProviderName == 'Microsoft', '1.0-preview(v1)', '1.0-preview'),\n ''\n ))\n // Append version check error code\n | extend x_SourceChanges = iff(x_SourceVersion == '1.0', x_SourceChanges,\n strcat(x_SourceChanges, iff(isempty(x_SourceChanges), '', ','), iff(x_SourceVersion == '', 'UnknownFocusVersion', 'LegacyFocusVersion'))\n )\n //\n // Fix quantities\n | extend old_PricingQuantity = PricingQuantity, PricingQuantity = case(\n PricingQuantity != 0 or (EffectiveCost == 0 and BilledCost == 0), PricingQuantity,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(EffectiveCost) and EffectiveCost != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0, EffectiveCost / x_EffectiveUnitPrice,\n PricingQuantity\n )\n | extend old_ConsumedQuantity = ConsumedQuantity, ConsumedQuantity = case(\n isnotempty(ConsumedQuantity) and ConsumedQuantity != 0, ConsumedQuantity,\n ChargeCategory == 'Usage', PricingQuantity / coalesce(x_PricingBlockSize, real(1)),\n ConsumedQuantity\n )\n //\n // Populate missing prices -- mapping to on-demand prices requires meter ID and offer ID\n | extend tmp_MissingPrices = ProviderName == 'Microsoft'\n and (isempty(ListUnitPrice) or isempty(ContractedUnitPrice) or ListUnitPrice == 0 or ContractedUnitPrice == 0)\n and x_EffectiveUnitPrice != 0\n and not(CommitmentDiscountCategory == 'Spend' and CommitmentDiscountStatus == 'Unused')\n and isnotempty(x_SkuMeterId) and isnotempty(x_SkuOfferId)\n | as allCosts\n | where tmp_MissingPrices\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(ChargePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | as costsWithMissingPrices\n | join kind=leftouter (\n Prices_final_v1_2\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(x_EffectivePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | where x_SkuPriceType == 'Consumption' and tmp_ReservationPriceLookupKey in ((costsWithMissingPrices | summarize by tmp_ReservationPriceLookupKey))\n | summarize ListUnitPrice = min(ListUnitPrice), ContractedUnitPrice = min(ContractedUnitPrice) by tmp_ReservationPriceLookupKey, x_PricingBlockSize, PricingUnit\n ) on tmp_ReservationPriceLookupKey\n //\n // Select the best price to use for each row\n | extend x_EffectiveUnitPrice = case(\n // If price is a rounding error away from the billed price, use the billed price\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001, x_BilledUnitPrice,\n // If price is a rounding error away from the contracted price, use the contracted price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001, ContractedUnitPrice,\n x_EffectiveUnitPrice\n )\n | extend ContractedUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ContractedUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ContractedUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // If billed price is available, assume the billed price is the same as contracted price to support aggregations\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, x_EffectiveUnitPrice,\n // Otherwise, assume the effective price is the same as contracted price to support aggregations\n x_EffectiveUnitPrice\n )\n | extend ListUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ListUnitPrice) and ListUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ListUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ListUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ListUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // Otherwise, assume the contracted price is the same as list price to support aggregations\n ContractedUnitPrice\n )\n // Calculate missing costs based on new prices -- If cost is already correct, keep that; if not and price is available, recalculate the cost; otherwise, keep the existing cost\n | extend ContractedCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ContractedCost) and ContractedCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedCost,\n // ContractedCost is 0 in all other scenarios...\n // If 0 and there's a billed cost and prices are the same, use BilledCost\n isnotempty(BilledCost) and BilledCost != 0 and ContractedUnitPrice == x_BilledUnitPrice, BilledCost,\n // If 0 and there's a billed cost and prices are the same, use EffectiveCost\n isnotempty(EffectiveCost) and EffectiveCost != 0 and ContractedUnitPrice == x_EffectiveUnitPrice, EffectiveCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0, ContractedUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume EffectiveCost\n isempty(ContractedUnitPrice) or ContractedUnitPrice == 0, EffectiveCost,\n // Fall back to the original value for any unhandled scenarios\n ContractedCost\n )\n | extend ListCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ListCost) and ListCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ListCost,\n // ListCost is 0 in all other scenarios...\n // If 0 and there's a contracted cost and prices are the same, use ContractedCost\n isnotempty(ContractedCost) and ContractedCost != 0 and ListUnitPrice == ContractedUnitPrice, ContractedCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ListUnitPrice) and ListUnitPrice != 0, ListUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume ContractedCost\n isempty(ListUnitPrice) or ListUnitPrice == 0, ContractedCost,\n // Fall back to the original value for any unhandled scenarios\n ListCost\n )\n // Merge the rest of the unmodified cost records and remove excess columns\n | union (allCosts | where not(tmp_MissingPrices))\n | project-away x_PricingBlockSize1, PricingUnit1, ListUnitPrice1, ContractedUnitPrice1, tmp_MissingPrices, tmp_ReservationPriceLookupKey, tmp_ReservationPriceLookupKey1\n //\n | extend SkuPriceDetails = parse_json(SkuPriceDetails)\n | extend Tags = parse_json(Tags)\n | extend x_SkuDetails = parse_json(x_SkuDetails)\n //\n // Handle FOCUS 1.0-preview\n | extend old_ChargeSubcategory = ChargeSubcategory\n | extend old_ChargeCategory = ChargeCategory, ChargeCategory = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Credit', 'Credit',\n ChargeSubcategory == 'Refund', 'Purchase', // We are assuming purchase refunds since we don't have data to indicate usage refunds\n ChargeCategory\n )\n | extend old_ChargeClass = ChargeClass, ChargeClass = case(ChargeSubcategory == 'Refund', 'Correction', ChargeClass)\n //\n // Populate CapacityReservationId when not specified\n | extend CapacityReservationId = coalesce(CapacityReservationId, tostring(coalesce(x_SkuDetails.VMCapacityReservationId, SkuPriceDetails.VMCapacityReservationId, SkuPriceDetails.x_VMCapacityReservationId)))\n | extend old_CapacityReservationStatus = CapacityReservationStatus, CapacityReservationStatus = case(\n isempty(CapacityReservationId), '',\n isnotempty(CapacityReservationStatus), CapacityReservationStatus,\n tolower(x_ResourceType) == 'microsoft.compute/capacityreservationgroups/capacityreservations', 'Unused',\n 'Used'\n )\n //\n // BUG: ChargeFrequency shows \"Usage-Based\" for monthly recurring savings plan purchases\n | extend old_ChargeFrequency = ChargeFrequency, ChargeFrequency = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based' and ProviderName == 'Microsoft' and x_SourceVersion startswith '1.0', 'Recurring', ChargeFrequency)\n //\n // Commitment discounts\n | extend x_CommitmentDiscountNormalizedRatio = case(\n // Calculate from CommitmentDiscountQuantity, if specified\n isnotempty(CommitmentDiscountQuantity) and CommitmentDiscountQuantity != 0, CommitmentDiscountQuantity / PricingQuantity / coalesce(x_PricingBlockSize, real(1)),\n // Not applicable\n isempty(CommitmentDiscountStatus), real(null),\n // Parse from SKU details if not specified explicitly\n toreal(coalesce(x_SkuDetails.RINormalizationRatio, SkuPriceDetails.RINormalizationRatio, SkuPriceDetails.x_RINormalizationRatio, dynamic(1)))\n )\n | extend old_CommitmentDiscountQuantity = CommitmentDiscountQuantity, CommitmentDiscountQuantity = case(\n // FOCUS 1.2\n isnotempty(CommitmentDiscountQuantity), CommitmentDiscountQuantity,\n // FOCUS 1.0-preview, 1.0\n isempty(CommitmentDiscountStatus), real(null),\n CommitmentDiscountCategory == 'Spend', EffectiveCost / coalesce(x_BillingExchangeRate, real(1)),\n CommitmentDiscountCategory == 'Usage' and isnotempty(x_CommitmentDiscountNormalizedRatio), PricingQuantity / coalesce(x_PricingBlockSize, real(1)) * x_CommitmentDiscountNormalizedRatio,\n real(null)\n )\n | extend old_CommitmentDiscountUnit = CommitmentDiscountUnit, CommitmentDiscountUnit = case(\n // FOCUS 1.2\n isnotempty(CommitmentDiscountUnit), CommitmentDiscountUnit,\n // FOCUS 1.0\n isempty(CommitmentDiscountQuantity), '',\n CommitmentDiscountCategory == 'Spend', PricingCurrency,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio == real(1), ConsumedUnit,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio > real(1), strcat('Normalized ', ConsumedUnit),\n ''\n )\n | extend old_CommitmentDiscountStatus = CommitmentDiscountStatus, CommitmentDiscountStatus = case(\n // FOCUS 1.0+\n isnotempty(CommitmentDiscountStatus), CommitmentDiscountStatus,\n // FOCUS 1.0-preview\n ChargeSubcategory == 'Used Commitment', 'Used',\n ChargeSubcategory == 'Unused Commitment', 'Unused',\n ''\n )\n | extend x_CommitmentDiscountUtilizationPotential = case(\n ChargeCategory == 'Purchase', real(0),\n ProviderName == 'Microsoft' and isnotempty(CommitmentDiscountCategory), EffectiveCost,\n CommitmentDiscountCategory == 'Usage', ConsumedQuantity,\n CommitmentDiscountCategory == 'Spend', EffectiveCost,\n real(0)\n )\n | extend x_CommitmentDiscountUtilizationAmount = iff(CommitmentDiscountStatus == 'Used', x_CommitmentDiscountUtilizationPotential, real(0))\n //\n // Pricing\n | extend old_x_AmortizationClass = x_AmortizationClass, x_AmortizationClass = case(\n // FOCUS 1.2\n isnotempty(x_AmortizationClass), x_AmortizationClass,\n // FOCUS 1.0-preview+\n ChargeCategory == 'Purchase' and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeCategory == 'Usage' and isnotempty(CommitmentDiscountId) and isnotempty(CommitmentDiscountStatus), 'Amortized Charge',\n ''\n )\n | extend old_PricingCategory = PricingCategory, PricingCategory = case(\n // FOCUS 1.0+\n isnotempty(PricingCategory), PricingCategory,\n // FOCUS 1.0-preview\n PricingCategory == 'On-Demand', 'Standard',\n PricingCategory == 'Commitment-Based', 'Committed',\n ''\n )\n //\n // Commitment discount utilization\n | extend x_CommitmentDiscountUtilizationPotential = case(\n ChargeCategory == 'Purchase', real(0),\n ProviderName == 'Microsoft' and isnotempty(CommitmentDiscountCategory), EffectiveCost,\n CommitmentDiscountCategory == 'Usage', ConsumedQuantity,\n CommitmentDiscountCategory == 'Spend', EffectiveCost,\n real(0)\n )\n | extend x_CommitmentDiscountUtilizationAmount = iff(CommitmentDiscountStatus == 'Used', x_CommitmentDiscountUtilizationPotential, real(0))\n //\n // BUG: Fix ContractedCost that has bad values\n | extend ContractedCost = iff(ProviderName == 'Microsoft' and isnotempty(PricingQuantity) and isnotempty(x_PricingBlockSize) and ContractedCost != ContractedUnitPrice * PricingQuantity, ContractedUnitPrice * PricingQuantity, ContractedCost)\n //\n // Handle FOCUS 1.0-preview UsageQuantity/Unit\n | extend ConsumedQuantity = iff(ChargeCategory == 'Usage', coalesce(ConsumedQuantity, UsageQuantity, UsageAmount), real(null))\n | extend old_ConsumedUnit = ConsumedUnit, ConsumedUnit = iff(ChargeCategory == 'Usage' and isnotempty(ConsumedQuantity), coalesce(ConsumedUnit, UsageUnit, 'Units'), '')\n //\n // Convert IDs to lowercase for consistency\n | extend BillingAccountId = tolower(BillingAccountId)\n | extend CommitmentDiscountId = tolower(CommitmentDiscountId)\n //\n // BUG: Remove EffectiveCost for commitment discount purchases\n | extend old_EffectiveCost = EffectiveCost, EffectiveCost = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), real(0), EffectiveCost)\n | extend old_x_EffectiveCostInUsd = x_EffectiveCostInUsd, x_EffectiveCostInUsd = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), real(0), x_EffectiveCostInUsd)\n //\n // Clean up resource columns\n | extend old_ResourceId = ResourceId, ResourceId = case(\n isnotempty(ResourceId), ResourceId,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), CommitmentDiscountId,\n ResourceId\n )\n | extend old_ResourceName = ResourceName, ResourceName = tolower(case(\n isnotempty(ResourceName), ResourceName,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountName), CommitmentDiscountName,\n isnotempty(ResourceId), parse_resourceid(ResourceId).ResourceName,\n ResourceName\n ))\n | extend old_x_ResourceType = x_ResourceType, x_ResourceType = case(\n isnotempty(x_ResourceType), x_ResourceType,\n isnotempty(ResourceId), parse_resourceid(ResourceId).x_ResourceType,\n x_ResourceType\n )\n | extend old_ResourceType = ResourceType, ResourceType = case(\n // Use existing resource type display name unless it's an internal resource type ID\n isnotempty(ResourceType) and tolower(ResourceType) != tolower(x_ResourceType) and ResourceType !contains '/', ResourceType,\n // Use CommitmentDiscountType for commitment discount purchases\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountType), CommitmentDiscountType,\n // Look up display name from internal type\n isnotempty(x_ResourceType), coalesce(tostring(resource_type(x_ResourceType).SingularDisplayName), ResourceType, x_ResourceType),\n ResourceType\n )\n //\n // Handle missing values\n | extend old_PublisherName = PublisherName, PublisherName = case(PublisherName == 'Microsoft Corporation', 'Microsoft', isnotempty(PublisherName), PublisherName, x_PublisherCategory == 'Cloud Provider', ProviderName, '')\n //\n // Handle FOCUS 1.0-preview Region column\n | extend old_Region = Region\n | extend old_RegionId = RegionId, RegionId = coalesce(RegionId, iff(ProviderName == 'Microsoft', replace_string(tolower(Region), ' ', ''), Region))\n | extend RegionName = coalesce(RegionName, Region)\n //\n // SKU properties\n | extend x_SkuCoreCount = toint(coalesce(SkuPriceDetails.CoreCount, SkuPriceDetails.x_VCPUs, x_SkuDetails.VCPUs, SkuPriceDetails.x_VCores, x_SkuDetails.VCores, SkuPriceDetails.x_vCores, x_SkuDetails.vCores))\n | extend x_SkuInstanceType = tostring(coalesce(SkuPriceDetails.InstanceType, SkuPriceDetails.x_ServiceType, x_SkuDetails.ServiceType, SkuPriceDetails.x_ServerSku, x_SkuDetails.ServerSku))\n | extend x_SkuOperatingSystem = case(\n isnotempty(SkuPriceDetails.OperatingSystem), SkuPriceDetails.OperatingSystem,\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Canonical', 'Linux',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL', 'Windows Server',\n x_SkuMeterSubcategory endswith ' Series Windows', 'Windows Server',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType)\n )\n | extend x_ConsumedCoreHours = iff(ConsumedUnit == 'Hours' and isnotempty(x_SkuCoreCount), x_SkuCoreCount * ConsumedQuantity, real(null))\n | extend SkuPriceDetails = case(\n // FOCUS 1.2\n isnotempty(SkuPriceDetails), SkuPriceDetails,\n // FOCUS 1.0-preview, 1.0\n parse_json(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(tostring(x_SkuDetails)\n // Prefix all keys with x_ first to avoid double-prefixing\n , @'([\\{,])\"', @'\\1\"x_')\n // CoreCount for number of CPUs/vCPUs/cores/vCores\n , @'\"x_(VCPUs|VCores|vCores)\":', @'\"CoreCount\":')\n // TODO: DiskMaxIops for disk I/O operations per second (IOPS)\n // TODO: DiskSpace for disk size in GiB\n // TODO: DiskType for the kind of disk (e.g., SSD, HDD, NVMe)\n // TODO: GpuCount for the number of GPUs\n // InstanceType for the resource size/SKU (e.g., ArmSkuName)\n , @'\"x_(ServerSku|ServiceType)\":', @'\"InstanceType\":')\n // TODO: InstanceSeries for the size family/series\n // TODO: MemorySize for the RAM in GiB\n // TODO: NetworkMaxIops for network I/O operations per second (IOPS)\n // TODO: NetworkMaxThroughput for network max throughput for data transfer in Mbps\n // OperatingSystem for the OS name\n , @'(\"x_ImageType\":\"Canonical\")', @'\\1,\"OperatingSystem\":\"Linux\"')\n , @'(\"x_ImageType\":\"Windows Server( BYOL)?\")', @'\\1,\"OperatingSystem\":\"Windows Server\"')\n , @'(\"x_ImageType\":(\"[^\"]+\"))', @'\\1,\"OperatingSystem\":\\2')\n // TODO: Redundancy for the level of redundancy (e.g., Local, Zonal, Global)\n // TODO: StorageClass for the tier of storage (e.g., Hot, Archive, Nearline)\n )\n )\n | extend SkuPriceDetails = iff(isempty(SkuPriceDetails.OperatingSystem) and isnotempty(x_SkuOperatingSystem),\n parse_json(replace_string(tostring(SkuPriceDetails), '}', strcat(@',\"OperatingSystem\":\"', x_SkuOperatingSystem, '\"}'))),\n SkuPriceDetails)\n //\n // Azure Hybrid Benefit\n | extend tmp_SqlAhb = tolower(coalesce(x_SkuDetails.AHB, SkuPriceDetails.x_AHB))\n | extend x_SkuLicenseType = case(\n ChargeCategory != 'Usage', '',\n x_SkuMeterCategory in ('Virtual Machines', 'Virtual Machine Licenses') and (x_SkuMeterSubcategory contains 'Windows' or coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL'), 'Windows Server',\n isnotempty(tmp_SqlAhb) or x_SkuMeterSubcategory == 'SQL Server Azure Hybrid Benefit', 'SQL Server',\n ''\n )\n | extend x_SkuLicenseStatus = case(\n isempty(x_SkuLicenseType), '',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL' or tmp_SqlAhb == 'true' or x_SkuMeterSubcategory contains 'Azure Hybrid Benefit', 'Enabled',\n (x_SkuMeterSubcategory contains 'Windows') or tmp_SqlAhb == 'false', 'Not Enabled',\n ''\n )\n | extend x_SkuLicenseQuantity = case(\n isempty(x_SkuCoreCount) or isempty(x_SkuLicenseType), int(null),\n x_SkuCoreCount <= 8, int(8),\n x_SkuCoreCount > 8, x_SkuCoreCount,\n int(null)\n )\n | extend x_SkuLicenseUnit = iff(isnotempty(x_SkuLicenseQuantity), 'Cores', '')\n //\n // Savings\n | extend x_CommitmentDiscountSavings = iff(isempty(ContractedCost) or ContractedCost == 0 or ContractedCost - EffectiveCost < 0.0001, real(0), ContractedCost - EffectiveCost)\n | extend x_NegotiatedDiscountSavings = iff(isempty(ListCost) or ListCost == 0 or ListCost - ContractedCost < 0.0001, real(0), ListCost - ContractedCost)\n | extend x_TotalSavings = iff(isempty(ListCost) or ListCost == 0 or ListCost - EffectiveCost < 0.0001, real(0), ListCost - EffectiveCost)\n | extend x_CommitmentDiscountPercent = iff(isempty(ContractedUnitPrice) or ContractedUnitPrice == 0 or ContractedUnitPrice - x_EffectiveUnitPrice < 0.0001, real(0), (ContractedUnitPrice - x_EffectiveUnitPrice) / ContractedUnitPrice)\n | extend x_NegotiatedDiscountPercent = iff(isempty(ListUnitPrice) or ListUnitPrice == 0 or ListUnitPrice - ContractedUnitPrice < 0.0001, real(0), (ListUnitPrice - ContractedUnitPrice) / ListUnitPrice)\n | extend x_TotalDiscountPercent = iff(isempty(ListUnitPrice) or ListUnitPrice == 0 or ListUnitPrice - x_EffectiveUnitPrice < 0.0001, real(0), (ListUnitPrice - x_EffectiveUnitPrice) / ListUnitPrice)\n //\n // Minor fixes\n | extend old_BillingPeriodEnd = BillingPeriodEnd, BillingPeriodEnd = startofmonth(BillingPeriodEnd)\n | extend old_BillingPeriodStart = BillingPeriodStart, BillingPeriodStart = startofmonth(BillingPeriodStart)\n //\n // Sort columns and apply final transforms\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId,\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd,\n BillingPeriodStart,\n CapacityReservationId,\n CapacityReservationStatus,\n ChargeCategory,\n ChargeClass,\n ChargeDescription,\n ChargeFrequency,\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId,\n CommitmentDiscountName,\n CommitmentDiscountQuantity,\n CommitmentDiscountStatus,\n CommitmentDiscountType,\n CommitmentDiscountUnit,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost = coalesce(ContractedCost, x_OnDemandCost, x_Cost),\n ContractedUnitPrice = coalesce(ContractedUnitPrice, x_OnDemandUnitPrice),\n EffectiveCost,\n InvoiceId = coalesce(InvoiceId, x_InvoiceId),\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory,\n PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency),\n PricingQuantity,\n PricingUnit,\n ProviderName,\n PublisherName,\n RegionId,\n RegionName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory, // TODO: Populate ServiceSubcategory from ServiceName when missing\n SkuId,\n SkuMeter = coalesce(SkuMeter, x_SkuMeterName),\n SkuPriceDetails,\n SkuPriceId,\n SubAccountId,\n SubAccountName = iff(isempty(SubAccountId), '', SubAccountName),\n SubAccountType,\n Tags,\n x_AccountId = iff(x_AccountId == '-2', '', x_AccountId),\n x_AccountName = iff(x_AccountId == '-2', '', x_AccountName),\n x_AccountOwnerId = iff(x_AccountId == '-2', '', x_AccountOwnerId),\n x_AmortizationClass,\n x_BilledCostInUsd,\n x_BilledUnitPrice,\n x_BillingAccountAgreement = case(\n ProviderName == 'Microsoft' and x_BillingAccountId == x_BillingProfileId, 'EA',\n ProviderName == 'Microsoft' and x_BillingAccountId != x_BillingProfileId, 'MCA',\n ProviderName\n ),\n x_BillingAccountId,\n x_BillingAccountName,\n x_BillingExchangeRate,\n x_BillingExchangeRateDate,\n x_BillingItemCode,\n x_BillingItemName,\n x_BillingProfileId,\n x_BillingProfileName,\n x_ChargeId,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountPercent,\n x_CommitmentDiscountSavings,\n x_CommitmentDiscountSpendEligibility = '', // TODO: Add x_CommitmentDiscountSpendEligibility for Costs\n x_CommitmentDiscountUsageEligibility = '', // TODO: Add x_CommitmentDiscountUsageEligibility for Costs\n x_CommitmentDiscountUtilizationAmount,\n x_CommitmentDiscountUtilizationPotential,\n x_CommodityCode,\n x_CommodityName,\n x_ComponentName,\n x_ComponentType,\n x_ConsumedCoreHours,\n x_ContractedCostInUsd = coalesce(x_ContractedCostInUsd, x_OnDemandCostInUsd),\n x_CostAllocationRuleName,\n x_CostCategories = parse_json(x_CostCategories),\n x_CostCenter,\n x_CostType,\n x_Credits = parse_json(x_Credits),\n x_CurrencyConversionRate,\n x_CustomerId,\n x_CustomerName,\n x_Discount = parse_json(x_Discount),\n x_EffectiveCostInUsd,\n x_EffectiveUnitPrice,\n x_ExportTime,\n x_IngestionTime,\n x_InstanceID,\n x_InvoiceIssuerId,\n x_InvoiceSectionId = case(\n x_InvoiceSectionId == '-2', '',\n x_InvoiceSectionId\n ),\n x_InvoiceSectionName = case(\n x_InvoiceSectionName == 'Unassigned', '',\n x_InvoiceSectionName\n ),\n x_ListCostInUsd,\n x_Location,\n x_NegotiatedDiscountPercent,\n x_NegotiatedDiscountSavings,\n x_Operation,\n x_OwnerAccountID,\n x_PartnerCreditApplied,\n x_PartnerCreditRate,\n x_PricingBlockSize,\n x_PricingSubcategory,\n x_PricingUnitDescription = iff(x_PricingUnitDescription == 'Unassigned', '', x_PricingUnitDescription),\n x_Project,\n x_PublisherCategory,\n x_PublisherId,\n x_ResellerId,\n x_ResellerName,\n x_ResourceGroupName = tolower(x_ResourceGroupName),\n x_ResourceType,\n x_ServiceCode,\n x_ServiceId,\n x_ServiceModel, // TODO: Populate from ServiceName when missing\n x_ServicePeriodEnd,\n x_ServicePeriodStart,\n x_SkuCoreCount,\n x_SkuDescription,\n x_SkuDetails,\n x_SkuInstanceType,\n x_SkuIsCreditEligible,\n x_SkuLicenseQuantity,\n x_SkuLicenseStatus,\n x_SkuLicenseType,\n x_SkuLicenseUnit,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterSubcategory,\n x_SkuOfferId,\n x_SkuOperatingSystem,\n x_SkuOrderId,\n x_SkuOrderName,\n x_SkuPartNumber,\n x_SkuPlanName,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuTerm,\n x_SkuTier,\n x_SourceChanges,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceValues = bag_merge(\n checkString('BillingPeriodEnd', old_BillingPeriodEnd, BillingPeriodEnd),\n checkString('BillingPeriodStart', old_BillingPeriodStart, BillingPeriodStart),\n checkString('CapacityReservationStatus', old_CapacityReservationStatus, CapacityReservationStatus),\n checkString('ChargeCategory', old_ChargeCategory, ChargeCategory),\n checkString('ChargeClass', old_ChargeClass, ChargeClass),\n checkString('ChargeSubcategory', old_ChargeSubcategory, ''), // Not included in final schema; use empty string\n checkString('ChargeFrequency', old_ChargeFrequency, ChargeFrequency),\n checkReal('CommitmentDiscountQuantity', old_CommitmentDiscountQuantity, CommitmentDiscountQuantity),\n checkString('CommitmentDiscountUnit', old_CommitmentDiscountUnit, CommitmentDiscountUnit),\n checkString('CommitmentDiscountStatus', old_CommitmentDiscountStatus, CommitmentDiscountStatus),\n checkReal('ConsumedQuantity', old_ConsumedQuantity, ConsumedQuantity),\n checkString('ConsumedUnit', old_ConsumedUnit, ConsumedUnit),\n checkReal('ContractedCost', old_ContractedCost, ContractedCost),\n checkReal('ContractedUnitPrice', old_ContractedUnitPrice, ContractedUnitPrice),\n checkReal('EffectiveCost', old_EffectiveCost, EffectiveCost),\n checkReal('ListCost', old_ListCost, ListCost),\n checkReal('ListUnitPrice', old_ListUnitPrice, ListUnitPrice),\n checkString('PricingCategory', old_PricingCategory, PricingCategory),\n checkReal('PricingQuantity', old_PricingQuantity, PricingQuantity),\n checkString('ProviderName', old_ProviderName, ProviderName),\n checkString('PublisherName', old_PublisherName, PublisherName),\n checkString('Region', old_Region, ''), // Not included in final schema; use empty string\n checkString('RegionId', old_RegionId, RegionId),\n checkString('ResourceId', old_ResourceId, ResourceId),\n checkString('ResourceName', old_ResourceName, ResourceName),\n checkString('ResourceType', old_ResourceType, ResourceType),\n checkString('x_AmortizationClass', old_x_AmortizationClass, x_AmortizationClass),\n checkReal('x_EffectiveCostInUsd', old_x_EffectiveCostInUsd, x_EffectiveCostInUsd),\n checkReal('x_EffectiveUnitPrice', old_x_EffectiveUnitPrice, x_EffectiveUnitPrice),\n checkString('x_ResourceType', old_x_ResourceType, x_ResourceType)\n ),\n x_SourceVersion,\n x_SubproductName,\n x_TotalDiscountPercent,\n x_TotalSavings,\n x_UsageType\n}\n\n// Costs_final_v1_2 table\n.create-merge table Costs_final_v1_2 (\n AvailabilityZone: string,\n BilledCost: real,\n BillingAccountId: string,\n BillingAccountName: string,\n BillingAccountType: string,\n BillingCurrency: string,\n BillingPeriodEnd: datetime,\n BillingPeriodStart: datetime,\n CapacityReservationId: string,\n CapacityReservationStatus: string,\n ChargeCategory: string,\n ChargeClass: string,\n ChargeDescription: string,\n ChargeFrequency: string,\n ChargePeriodEnd: datetime,\n ChargePeriodStart: datetime,\n CommitmentDiscountCategory: string,\n CommitmentDiscountId: string,\n CommitmentDiscountName: string,\n CommitmentDiscountQuantity: real,\n CommitmentDiscountStatus: string,\n CommitmentDiscountType: string,\n CommitmentDiscountUnit: string,\n ConsumedQuantity: real,\n ConsumedUnit: string,\n ContractedCost: real,\n ContractedUnitPrice: real,\n EffectiveCost: real,\n InvoiceId: string,\n InvoiceIssuerName: string,\n ListCost: real,\n ListUnitPrice: real,\n PricingCategory: string,\n PricingCurrency: string,\n PricingQuantity: real,\n PricingUnit: string,\n ProviderName: string,\n PublisherName: string,\n RegionId: string,\n RegionName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n ServiceCategory: string,\n ServiceName: string,\n ServiceSubcategory: string,\n SkuId: string,\n SkuMeter: string,\n SkuPriceDetails: dynamic,\n SkuPriceId: string,\n SubAccountId: string,\n SubAccountName: string,\n SubAccountType: string,\n Tags: dynamic,\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_AmortizationClass: string, // Azure 1.2-preview+\n x_BilledCostInUsd: real, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: real, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: real, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingItemCode: string, // Alibaba 1.0\n x_BillingItemName: string, // Alibaba 1.0\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_CommitmentDiscountNormalizedRatio: real, // Azure 1.2-preview+\n x_CommitmentDiscountPercent: real, // Hubs add-on\n x_CommitmentDiscountSavings: real, // Hubs add-on\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_CommitmentDiscountUtilizationAmount: real, // Hubs add-on\n x_CommitmentDiscountUtilizationPotential: real, // Hubs add-on\n x_CommodityCode: string, // Alibaba 1.0\n x_CommodityName: string, // Alibaba 1.0\n x_ComponentName: string, // Tencent 1.0\n x_ComponentType: string, // Tencent 1.0\n x_ConsumedCoreHours: real, // Hubs add-on\n x_ContractedCostInUsd: real, // Azure 1.0+\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: dynamic, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_CostType: string, // GCP Jan 2024\n x_Credits: dynamic, // GCP Jan 2024\n x_CurrencyConversionRate: real, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: dynamic, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: real, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: real, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024 / Tencent 1.0\n x_IngestionTime: datetime, // Hubs add-on\n x_InstanceID: string, // Alibaba 1.0\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: real, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_NegotiatedDiscountPercent:real, // Hubs add-on\n x_NegotiatedDiscountSavings:real, // Hubs add-on\n x_Operation: string, // AWS 1.0\n x_OwnerAccountID: string, // Tencent 1.0\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: real, // Azure 1.0-preview(v1)+\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServiceModel: string, // Azure 1.2-preview+\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuCoreCount: int, // Hubs add-on\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: dynamic, // Azure 1.0-preview(v1)+\n x_SkuInstanceType: string, // Hubs add-on\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuLicenseQuantity: int, // Hubs add-on\n x_SkuLicenseStatus: string, // Hubs add-on\n x_SkuLicenseType: string, // Hubs add-on\n x_SkuLicenseUnit: string, // Hubs add-on\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOperatingSystem: string, // Hubs add-on\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuPlanName: string, // Azure 1.2-preview+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceChanges: string, // Hubs add-on\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceValues: dynamic, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubproductName: string, // Tencent 1.0\n x_TotalDiscountPercent: real, // Hubs add-on\n x_TotalSavings: real, // Hubs add-on\n x_UsageType: string // AWS 1.0\n)\n\n// Update policy for Costs_raw -> Costs_final_v1_2 table\n.alter table Costs_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Costs_raw\",\n \"Query\": \"Costs_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Actual costs |===================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_transform_v1_2 function\n.create-or-alter function\nwith (docstring='ActualCost exports transformed to FOCUS 1.2.', folder='Costs')\nActualCosts_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n ActualCosts_raw\n | where ChargeType in ('Purchase', 'Refund') and isnotempty(ReservationId)\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: PublisherName, x_PublisherCategory, x_Environment\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory), take_any(ServiceSubcategory), take_any(x_ServiceModel) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodEnd = Date + 1d,\n ChargePeriodStart = Date,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SkuId = '',\n SkuMeter = MeterName,\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = iff(isempty(SubscriptionId), '', SubscriptionName),\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentType = '',\n x_ComponentName = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = '',\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel,\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for ActualCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": true,\n \"Source\": \"ActualCosts_raw\",\n \"Query\": \"ActualCosts_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Amortized costs |================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_transform_v1_2 function\n.create-or-alter function\nwith (docstring='ActualCost exports transformed to FOCUS 1.2.', folder='Costs')\nAmortizedCosts_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n AmortizedCosts_raw\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: PublisherName, x_PublisherCategory, x_Environment\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory), take_any(ServiceSubcategory), take_any(x_ServiceModel) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodEnd = Date + 1d,\n ChargePeriodStart = Date,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SkuId = '',\n SkuMeter = MeterName,\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = iff(isempty(SubscriptionId), '', SubscriptionName),\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentType = '',\n x_ComponentName = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = '',\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel,\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for AmortizedCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": true,\n \"Source\": \"AmortizedCosts_raw\",\n \"Query\": \"AmortizedCosts_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All commitment discount usage transformed to FOCUS 1.2. This includes reservationdeatils_raw.', folder='Commitment discounts')\nCommitmentDiscountUsage_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n CommitmentDiscountUsage_raw\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Handle resource columns\n | extend ResourceId = tolower(InstanceId)\n | extend tmp_ResourceDetails = parse_resourceid(ResourceId)\n | extend ResourceName = tostring(tmp_ResourceDetails.ResourceName)\n | extend SubAccountId = tostring(tmp_ResourceDetails.SubAccountId)\n | extend x_ResourceGroupName = tostring(tmp_ResourceDetails.x_ResourceGroupName)\n | extend x_ResourceType = tostring(tmp_ResourceDetails.x_ResourceType)\n | lookup kind=leftouter (ResourceTypes | distinct x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n | lookup kind=leftouter (Services | distinct x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n //\n // Sort columns and apply final transforms\n | project\n ChargePeriodEnd = UsageDate + 1d,\n ChargePeriodStart = UsageDate,\n CommitmentDiscountCategory = 'Usage',\n CommitmentDiscountId = tolower(strcat('/providers/microsoft.capacity/reservationorders/', ReservationOrderId, '/reservations/', ReservationId)),\n CommitmentDiscountQuantity = UsedHours * InstanceFlexibilityRatio,\n CommitmentDiscountType = 'Reservation',\n CommitmentDiscountUnit = case(\n InstanceFlexibilityRatio == 1, 'Hours',\n InstanceFlexibilityRatio != 1, 'Normalized Hours',\n ''\n ),\n ConsumedQuantity = UsedHours,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SubAccountId,\n x_CommitmentDiscountCommittedCount = TotalReservedQuantity,\n x_CommitmentDiscountCommittedAmount = ReservedHours,\n // TODO: Is this needed? -- x_CommitmentDiscountKind = Kind,\n x_CommitmentDiscountNormalizedGroup = iff(InstanceFlexibilityGroup == 'NA', '', InstanceFlexibilityGroup),\n x_CommitmentDiscountNormalizedRatio = InstanceFlexibilityRatio,\n x_IngestionTime = ingestion_time(),\n x_ResourceGroupName,\n x_ResourceType,\n // x_RowId = hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // CommitmentDiscountId,\n // ResourceId,\n // ChargePeriodStart\n // )),\n x_ServiceModel,\n x_SkuOrderId = ReservationOrderId,\n x_SkuSize = iff(SkuName == 'NA', '', SkuName),\n x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName)),\n x_SourceProvider = coalesce(x_SourceProvider, ProviderName),\n x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationDetails', '')),\n x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2024-03-01', ''))\n}\n\n// CommitmentDiscountUsage_final_v1_2 table\n.create-merge table CommitmentDiscountUsage_final_v1_2 (\n ChargePeriodEnd: datetime, // Hubs add-on\n ChargePeriodStart: datetime, // MS 2023-03-01\n CommitmentDiscountCategory: string, // Hubs add-on\n CommitmentDiscountId: string, // MS 2023-03-01\n CommitmentDiscountQuantity: real, // MS 2023-03-01\n CommitmentDiscountType: string, // Hubs add-on\n CommitmentDiscountUnit: string, // Hubs add-on\n ConsumedQuantity: real, // MS 2023-03-01\n ProviderName: string, // Hubs add-on\n ResourceId: string, // MS 2023-03-01\n ResourceName: string, // Hubs add-on\n ResourceType: string, // Hubs add-on\n ServiceCategory: string, // Hubs add-on\n ServiceName: string, // Hubs add-on\n ServiceSubcategory: string, // Hubs add-on\n SubAccountId: string, // Hubs add-on\n x_CommitmentDiscountCommittedCount: real, // MS 2023-03-01\n x_CommitmentDiscountCommittedAmount: real, // MS 2023-03-01\n x_CommitmentDiscountNormalizedGroup: string, // MS 2023-03-01\n x_CommitmentDiscountNormalizedRatio: real, // MS 2023-03-01\n x_IngestionTime: datetime, // Hubs add-on\n x_ResourceGroupName: string, // Hubs add-on\n x_ResourceType: string, // Hubs add-on\n x_ServiceModel: string, // Hubs add-on\n x_SkuOrderId: string, // MS 2023-03-01\n x_SkuSize: string, // MS 2023-03-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string // Hubs add-on\n)\n\n// Update policy for CommitmentDiscountUsage_raw -> CommitmentDiscountUsage_final_v1_2 table\n.alter table CommitmentDiscountUsage_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"CommitmentDiscountUsage_raw\",\n \"Query\": \"CommitmentDiscountUsage_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All recommendations transformed to FOCUS 1.2.', folder='Recommendations')\nRecommendations_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Recommendations_raw\n | extend x_IngestionTime = ingestion_time()\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationRecommendations', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Convert JSON cost columns to real\n | extend CostWithNoReservedInstances = case(isnotempty(CostWithNoReservedInstances), CostWithNoReservedInstances, isnotempty(CostWithNoReservedInstancesJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, CostWithNoReservedInstancesJson)), CostWithNoReservedInstances)\n | extend NetSavings = case(isnotempty(NetSavings), NetSavings, isnotempty(NetSavingsJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, NetSavingsJson)), NetSavings)\n | extend TotalCostWithReservedInstances = case(isnotempty(TotalCostWithReservedInstances), TotalCostWithReservedInstances, isnotempty(TotalCostWithReservedInstancesJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, TotalCostWithReservedInstancesJson)), TotalCostWithReservedInstances)\n //\n // Parse x_RecommendationDetails from JSON string (ARG queries serialize to string for Parquet compatibility)\n | extend x_RecommendationDetails = iff(gettype(x_RecommendationDetails) == 'string', parse_json(tostring(x_RecommendationDetails)), x_RecommendationDetails)\n //\n // Normalize x_RecommendationDetails keys to x_PascalCase (Advisor extendedProperties use camelCase)\n // Guard: inject a placeholder key so mv-apply doesn't drop rows with null/empty bags\n | extend x_RecommendationDetails = bag_merge(coalesce(x_RecommendationDetails, dynamic({})), bag_pack('__placeholder', ''))\n | mv-apply k = bag_keys(x_RecommendationDetails) on (\n where isnotempty(tostring(k)) and tostring(k) != '__placeholder'\n | extend newKey = iff(tostring(k) startswith 'x_', tostring(k), strcat('x_', toupper(substring(tostring(k), 0, 1)), substring(tostring(k), 1)))\n | summarize x_RecommendationDetails = make_bag(bag_pack(newKey, x_RecommendationDetails[tostring(k)]))\n )\n //\n // Build recommendation details\n | lookup kind=leftouter (Regions | summarize RegionName = make_set(RegionName)[0] by Location = RegionId) on Location\n | extend x_RecommendationDetails = case(\n // Use incoming x_RecommendationDetails first\n isnotempty(x_RecommendationDetails), x_RecommendationDetails,\n // Create one for reservation recommendations if needed\n x_SourceType == 'ReservationRecommendations', bag_pack(\n 'CommitmentDiscountNormalizedGroup', InstanceFlexibilityGroup,\n 'CommitmentDiscountNormalizedRatio', InstanceFlexibilityRatio,\n 'CommitmentDiscountNormalizedSize', NormalizedSize,\n 'CommitmentDiscountResourceType', ResourceType,\n 'CommitmentDiscountScope', Scope,\n 'LookbackPeriodDuration', case(\n LookBackPeriod matches regex @'^Last([0-9]+)Days$', replace_regex(LookBackPeriod, @'^Last([0-9]+)Days$', @'P\\1D'),\n LookBackPeriod matches regex @'^[0-9]+$', strcat('P', LookBackPeriod, 'D'),\n ''\n ),\n 'LookbackPeriodStart', FirstUsageDate,\n 'RecommendedQuantity', RecommendedQuantity,\n 'RecommendedQuantityNormalized', RecommendedQuantityNormalized,\n 'RegionId', Location,\n 'RegionName', RegionName,\n 'SkuMeterId', MeterId,\n 'SkuPriceDetails', SkuProperties,\n 'SkuSize', coalesce(SKU, SkuName),\n 'SkuTerm', isoMonths(Term)\n ),\n dynamic({})\n )\n //\n // Prefer specified date, then fall back to generating a date based on reservation recommendation lookback period, then validate to ensure it's not in the future\n | extend x_RecommendationDate = coalesce(x_RecommendationDate, FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d))\n | extend x_RecommendationDate = iff(x_RecommendationDate > now(), startofday(now()), x_RecommendationDate)\n //\n // Derive x_ResourceType from ResourceId\n | extend tmp_ResourceType = tostring(parse_resourceid(ResourceId).x_ResourceType)\n | extend x_RecommendationDetails = iff(isnotempty(tmp_ResourceType), bag_merge(bag_pack('x_ResourceType', tmp_ResourceType), x_RecommendationDetails), x_RecommendationDetails)\n //\n // Set ResourceType display name from x_ResourceType code\n | extend ResourceType = coalesce(ResourceType, tostring(resource_type(tmp_ResourceType).SingularDisplayName), tmp_ResourceType)\n //\n | project\n ProviderName,\n ResourceId = tolower(ResourceId), // Force lowercase for consistent grouping/filtering\n ResourceName = tolower(iff(tmp_ResourceType =~ 'microsoft.resources/subscriptions', coalesce(SubAccountName, ResourceName), ResourceName)), // Use subscription name for subscription-level recommendations\n ResourceType,\n SubAccountId = coalesce(SubAccountId, iff(isnotempty(SubscriptionId), strcat('/subscriptions/', SubscriptionId), '')),\n SubAccountName,\n x_EffectiveCostAfter = coalesce(x_EffectiveCostAfter, TotalCostWithReservedInstances),\n x_EffectiveCostBefore = coalesce(x_EffectiveCostBefore, CostWithNoReservedInstances),\n x_EffectiveCostSavings = coalesce(x_EffectiveCostSavings, NetSavings, toreal(x_RecommendationDetails.x_SavingsAmount), toreal(x_RecommendationDetails.x_AnnualSavingsAmount) / 12),\n x_IngestionTime,\n x_RecommendationCategory, // TODO: Set for reservation recommendations\n x_RecommendationDate,\n x_RecommendationDescription = coalesce(x_RecommendationDescription, tostring(x_RecommendationDetails.x_RecommendationSolution), tostring(x_RecommendationDetails.x_RecommendationSubCategory)),\n x_RecommendationDetails,\n x_RecommendationId = tolower(x_RecommendationId), // TODO: Set for reservation recommendations; force lowercase for consistent grouping/filtering\n x_ResourceGroupName = tolower(x_ResourceGroupName), // Force lowercase for consistent grouping/filtering\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n// Recommendations_final_v1_2 table\n.create-merge table Recommendations_final_v1_2 (\n ProviderName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n SubAccountId: string,\n SubAccountName: string,\n x_EffectiveCostAfter: real,\n x_EffectiveCostBefore: real,\n x_EffectiveCostSavings: real,\n x_IngestionTime: datetime,\n x_RecommendationCategory: string,\n x_RecommendationDate: datetime,\n x_RecommendationDescription: string,\n x_RecommendationDetails: dynamic,\n x_RecommendationId: string,\n x_ResourceGroupName: string,\n x_SourceName: string,\n x_SourceProvider: string,\n x_SourceType: string,\n x_SourceVersion: string\n)\n\n// Update policy for Recommendations_raw -> Recommendations_final_v1_2 table\n.alter table Recommendations_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Recommendations_raw\",\n \"Query\": \"Recommendations_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All transactions transformed to FOCUS 1.2.', folder='Transactions')\nTransactions_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Transactions_raw\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationTransactions', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Handle BillingPeriodStart/End\n | extend BillingMonth = tostring(BillingMonth)\n | extend BillingPeriodStart = iff(isempty(BillingMonth), datetime(null), todatetime(strcat(substring(BillingMonth, 0, 4), \"-\", substring(BillingMonth, 4, 2), \"-\", substring(BillingMonth, 6, 2))))\n | extend BillingPeriodEnd = iff(isempty(BillingMonth), datetime(null), startofmonth(endofmonth(BillingPeriodStart) + 1d))\n //\n // Sort columns and apply final transforms\n | project\n BilledCost = Amount,\n BillingAccountId = case(\n BillingProfileId startswith '/', BillingProfileId,\n isnotempty(CurrentEnrollmentId), strcat('/providers/Microsoft.Billing/billingAccounts/', CurrentEnrollmentId),\n isnotempty(BillingProfileId), strcat('/providers/Microsoft.Billing/billingProfiles/', BillingProfileId),\n ''\n ),\n BillingAccountName = coalesce(BillingProfileName, CurrentEnrollmentId),\n BillingCurrency = Currency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory = case(\n EventType in ('Cancel', 'Purchase', 'Refund'), 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = case(\n EventType == 'Cancel', 'Cancel', // FOCUS does not handle this scenario\n EventType == 'Refund', 'Correction',\n ''\n ),\n ChargeDescription = Description,\n ChargeFrequency = case(\n BillingFrequency == 'OneTime', 'One-Time',\n BillingFrequency == 'Recurring', 'Recurring',\n BillingFrequency\n ),\n ChargePeriodStart = EventDate,\n InvoiceId,\n PricingQuantity = Quantity,\n PricingUnit = 'Reservations',\n ProviderName,\n RegionId = Region,\n RegionName = Region,\n SubAccountId = iff(isempty(PurchasingSubscriptionGuid), '', strcat('/subscriptions/', PurchasingSubscriptionGuid)),\n SubAccountName = iff(isempty(PurchasingSubscriptionGuid), '', PurchasingSubscriptionName),\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerEmail,\n x_CostCenter = CostCenter,\n x_InvoiceNumber = Invoice,\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = coalesce(InvoiceSectionName, DepartmentName),\n x_IngestionTime = ingestion_time(),\n x_MonetaryCommitment = MonetaryCommitment,\n x_Overage = Overage,\n x_PurchasingBillingAccountId = PurchasingEnrollment,\n x_SkuOrderId = ReservationOrderId,\n x_SkuOrderName = ReservationOrderName,\n x_SkuSize = ArmSkuName,\n x_SkuTerm = isoMonths(Term),\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId = PurchasingSubscriptionGuid,\n x_TransactionType = EventType\n}\n\n// Transactions_final_v1_2 table\n.create-merge table Transactions_final_v1_2 (\n BilledCost: real, // MS CM EA+MCA 2023-05-01\n BillingAccountId: string, // MS CM EA+MCA 2023-05-01\n BillingAccountName: string, // MS CM EA+MCA 2023-05-01\n BillingCurrency: string, // MS CM EA+MCA 2023-05-01\n BillingPeriodEnd: datetime, // MS CM EA+MCA 2023-05-01\n BillingPeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n ChargeCategory: string, // Hubs add-on\n ChargeClass: string, // Hubs add-on\n ChargeDescription: string, // MS CM EA+MCA 2023-05-01\n ChargeFrequency: string, // MS CM EA+MCA 2023-05-01\n ChargePeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n InvoiceId: string, // MS CM MCA 2023-05-01\n PricingQuantity: real, // MS CM EA+MCA 2023-05-01\n PricingUnit: string, // Hubs add-on\n ProviderName: string, // Hubs add-on\n RegionId: string, // MS CM EA+MCA 2023-05-01\n RegionName: string, // MS CM EA+MCA 2023-05-01\n SubAccountId: string, // MS CM EA+MCA 2023-05-01\n SubAccountName: string, // MS CM EA+MCA 2023-05-01\n x_AccountName: string, // MS CM EA 2023-05-01\n x_AccountOwnerId: string, // MS CM EA 2023-05-01\n x_CostCenter: string, // MS CM EA 2023-05-01\n x_InvoiceNumber: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionId: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionName: string, // MS CM MCA 2023-05-01\n x_IngestionTime: datetime, // Hubs add-on\n x_MonetaryCommitment: real, // MS CM EA 2023-05-01\n x_Overage: real, // MS CM EA 2023-05-01\n x_PurchasingBillingAccountId: string, // MS CM EA 2023-05-01\n x_SkuOrderId: string, // MS CM EA+MCA 2023-05-01\n x_SkuOrderName: string, // MS CM EA+MCA 2023-05-01\n x_SkuSize: string, // MS CM EA+MCA 2023-05-01\n x_SkuTerm: int, // MS CM EA+MCA 2023-05-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubscriptionId: string, // MS CM EA+MCA 2023-05-01\n x_TransactionType: string // MS CM EA+MCA 2023-05-01\n)\n\n// Update policy for Transactions_raw -> Transactions_final_v1_2 table\n.alter table Transactions_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Transactions_raw\",\n \"Query\": \"Transactions_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n", + "$fxv#10": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// See known issues @ https://github.com/microsoft/finops-toolkit/issues/1111\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Prices |=========================================================================================================\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_transform_v1_2 function\n.create-or-alter function\nwith (docstring='Transforms Prices_raw into FOCUS 1.2.', folder='Prices')\nPrices_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n let prices = materialize(\n Prices_raw\n | extend PricingCurrency = coalesce(Currency, CurrencyCode) // CurrencyCode last as a fallback only\n | extend x_SkuId = coalesce(SkuId, SkuID)\n | extend x_SkuMeterId = coalesce(MeterId, MeterID)\n | extend x_SkuProductId = coalesce(ProductId, ProductID)\n | extend x_SkuTerm = isoMonths(Term)\n | project-rename\n SkuMeter = MeterName,\n x_BaseUnitPrice = BasePrice,\n x_EffectivePeriodEnd = EffectiveEndDate,\n x_EffectivePeriodStart = EffectiveStartDate,\n x_PricingUnitDescription = UnitOfMeasure,\n x_SkuIncludedQuantity = IncludedQuantity,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuMeterType = MeterType,\n x_SkuOfferId = OfferID,\n x_SkuPartNumber = PartNumber,\n x_SkuPriceType = PriceType,\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTier = TierMinimumUnits\n | extend ContractedUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', UnitPrice, real(null)) // UnitPrice for savings plan is not the on-demand unit price\n | extend ListUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', MarketPrice, real(null)) // MarketPrice for savings plan is not the list price\n | extend ChargeCategory = case(\n x_SkuPriceType == 'Consumption', 'Usage',\n x_SkuPriceType == 'ReservedInstance', 'Purchase',\n x_SkuPriceType == 'SavingsPlan', 'Usage', // Savings plan prices are for committed usage, not the purchase\n ''\n )\n | extend SkuPriceIdv2 = strcat(case(x_SkuPriceType == 'Consumption', 'OD', x_SkuPriceType == 'ReservedInstance', 'RI', x_SkuPriceType == 'SavingsPlan', 'SP', 'XX'), substring(ChargeCategory, 0, 1), x_SkuTerm, '_', x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType, '_', x_SkuTier, x_SkuOfferId)\n | extend x_BillingAccountId = iff(BillingAccountId startswith '/', split(BillingAccountId, '/')[-1], coalesce(BillingAccountId, EnrollmentNumber))\n | extend x_BillingProfileId = iff(BillingProfileId startswith '/', split(BillingProfileId, '/')[-1], coalesce(BillingProfileId, EnrollmentNumber))\n | extend tmp_SavingsPlanKey = strcat(x_SkuMeterId, x_SkuProductId, x_SkuId, x_SkuTier, x_SkuOfferId)\n //\n // Get latest ingested row based on the unique ID\n | extend x_IngestionTime = ingestion_time()\n );\n //\n // Meters for reservations and savings plans to identify commitment eligibility\n let riMeters = prices | where x_SkuPriceType == 'ReservedInstance' | distinct x_SkuMeterId;\n let spMeters = prices | where x_SkuPriceType == 'SavingsPlan' | distinct x_SkuMeterId;\n //\n // Copy list/base/contracted prices from on-demand SKUs\n prices\n | where x_SkuPriceType == 'SavingsPlan'\n // If we use join, specify the shuffle key\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter hint.strategy=shuffle (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | lookup kind=leftouter (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | extend ListUnitPrice = coalesce(ListUnitPrice, ListUnitPrice1)\n | extend ContractedUnitPrice = coalesce(ContractedUnitPrice, ContractedUnitPrice1)\n | extend x_BaseUnitPrice = coalesce(x_BaseUnitPrice, x_BaseUnitPrice1)\n | project-away ListUnitPrice1, ContractedUnitPrice1, x_BaseUnitPrice1, tmp_SavingsPlanKey\n | union ((prices | where x_SkuPriceType != 'SavingsPlan'))\n //\n // Set CommitmentDiscountCategory for reuse\n | extend CommitmentDiscountCategory = case(\n x_SkuPriceType == 'ReservedInstance', 'Usage',\n x_SkuPriceType == 'SavingsPlan', 'Spend',\n ''\n )\n //\n // Calculate commitment discount eligibility\n // TODO: Would a join be faster?\n // TODO: Check this to ensure it's correct\n | extend x_CommitmentDiscountSpendEligibility = iff(x_SkuMeterId in (riMeters) and x_SkuPriceType != 'ReservedInstance', 'Eligible', 'Not Eligible')\n | extend x_CommitmentDiscountUsageEligibility = iff(x_SkuMeterId in (spMeters), 'Eligible', 'Not Eligible')\n //\n // TODO: Implement x_CommitmentDiscountNormalizedRatio\n | extend x_CommitmentDiscountNormalizedRatio = real(null)\n //\n // Add PricingUnit and x_PricingBlockSize\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter (PricingUnits) on x_PricingUnitDescription | project-away x_PricingUnitDescription1\n | lookup kind=leftouter (PricingUnits) on x_PricingUnitDescription\n //\n | extend x_EffectiveUnitPrice = iff(x_SkuPriceType == 'SavingsPlan', UnitPrice, real(null)) // Savings plan prices are for the effective price, not the contracted price\n | extend x_EffectiveUnitPriceDiscount = ContractedUnitPrice - x_EffectiveUnitPrice\n | extend x_ContractedUnitPriceDiscount = ListUnitPrice - ContractedUnitPrice\n | extend x_TotalUnitPriceDiscount = ListUnitPrice - x_EffectiveUnitPrice\n | project\n BillingAccountId = tolower(case(\n BillingProfileId startswith '/', BillingProfileId,\n BillingAccountId startswith '/', BillingAccountId,\n strcat('/providers/microsoft.billing/billingaccounts/', x_BillingAccountId, iff(x_BillingProfileId == x_BillingAccountId, '', strcat('/billingprofiles/', x_BillingProfileId)))\n )),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName, x_BillingProfileId),\n BillingCurrency = coalesce(BillingCurrency, CurrencyCode, Currency), // Currency last as a fallback only\n ChargeCategory,\n CommitmentDiscountCategory,\n CommitmentDiscountType = case(\n x_SkuPriceType == 'ReservedInstance', 'Reservation',\n x_SkuPriceType == 'SavingsPlan', 'Savings plan',\n ''\n ),\n CommitmentDiscountUnit = case(\n isempty(CommitmentDiscountCategory), '',\n CommitmentDiscountCategory == 'Spend', PricingCurrency,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio == real(1), PricingUnit,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio > real(1), strcat('Normalized ', PricingUnit),\n ''\n ),\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory = case(\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed',\n ''\n ),\n PricingCurrency,\n PricingUnit,\n SkuId = coalesce(ProductId, ProductID),\n SkuMeter,\n SkuPriceId = strcat(x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType),\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement = case(\n strlen(x_BillingAccountId) > 32, 'MCA',\n strlen(x_BillingAccountId) < 32, 'EA',\n 'Unknown'\n ),\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent = 1.0 * x_ContractedUnitPriceDiscount / ListUnitPrice * 100,\n x_EffectivePeriodEnd = startofmonth(x_EffectivePeriodEnd + 1h),\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent = 1.0 * x_EffectiveUnitPriceDiscount / ContractedUnitPrice * 100,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingSubcategory = case(\n x_SkuPriceType == 'Consumption' and (x_SkuIncludedQuantity > 0 or x_SkuTier > 0), 'Tiered',\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed Spend',\n ''\n ),\n x_PricingUnitDescription,\n x_SkuDescription = Product,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName = coalesce(x_SourceName, 'Cost Management'),\n x_SourceProvider = coalesce(x_SourceProvider, 'Microsoft'),\n x_SourceType = coalesce(x_SourceType, 'PriceSheet'),\n x_SourceVersion = coalesce(x_SourceVersion, '2023-05-01'),\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent = 1.0 * x_TotalUnitPriceDiscount / ListUnitPrice * 100\n}\n\n// Prices_final_v1_2 table\n.create-merge table Prices_final_v1_2 (\n BillingAccountId: string,\n BillingAccountName: string,\n BillingCurrency: string,\n ChargeCategory: string,\n CommitmentDiscountCategory: string,\n CommitmentDiscountType: string,\n CommitmentDiscountUnit: string,\n ContractedUnitPrice: real,\n ListUnitPrice: real,\n PricingCategory: string,\n PricingCurrency: string, // Azure\n PricingUnit: string,\n SkuId: string,\n SkuMeter: string, // Azure\n SkuPriceId: string,\n SkuPriceIdv2: string, // Hubs add-on\n x_BaseUnitPrice: real, // Azure\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure MCA\n x_BillingProfileId: string, // Azure MCA\n x_CommitmentDiscountNormalizedRatio: real, // Hubs add-on\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_ContractedUnitPriceDiscount: real, // Hubs add-on\n x_ContractedUnitPriceDiscountPercent: real, // Hubs add-on\n x_EffectivePeriodEnd: datetime, // Azure\n x_EffectivePeriodStart: datetime, // Azure\n x_EffectiveUnitPrice: real, // Azure\n x_EffectiveUnitPriceDiscount: real, // Hubs add-on\n x_EffectiveUnitPriceDiscountPercent: real, // Hubs add-on\n x_IngestionTime: datetime, // Hubs add-on\n x_PricingBlockSize: real, // Hubs add-on\n x_PricingSubcategory: string, // Hubs add-on\n x_PricingUnitDescription: string, // Azure\n x_SkuDescription: string, // Azure\n x_SkuId: string, // Azure\n x_SkuIncludedQuantity: real, // Azure EA\n x_SkuMeterCategory: string, // Azure\n x_SkuMeterId: string, // Azure\n x_SkuMeterSubcategory: string, // Azure\n x_SkuMeterType: string, // Azure\n x_SkuPriceType: string, // Azure\n x_SkuProductId: string, // Azure\n x_SkuRegion: string, // Azure\n x_SkuServiceFamily: string, // Azure\n x_SkuOfferId: string, // Azure EA\n x_SkuPartNumber: string, // Azure EA\n x_SkuTerm: int, // Azure\n x_SkuTier: real, // Azure MCA\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_TotalUnitPriceDiscount: real, // Hubs add-on\n x_TotalUnitPriceDiscountPercent: real // Hubs add-on\n)\n\n// Update policy for Prices_raw -> Prices_final_v1_2\n.alter table Prices_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Prices_raw\",\n \"Query\": \"Prices_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Cost and usage |=================================================================================================\n// Supported versions:\n// - MS: 1.2-preview, 1.0, 1.0-preview(v1)\n// https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0\n// https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024\n// https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 \n// https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All costs transformed to FOCUS 1.2.', folder='Costs')\nCosts_transform_v1_2()\n{\n let checkString = (column: string, oldValue: string, newValue: string) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n let checkInt = (column: string, oldValue: int, newValue: int) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n let checkReal = (column: string, oldValue: real, newValue: real) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n Costs_raw\n //\n // Dedupe rows\n | extend x_IngestionTime = ingestion_time()\n | extend x_ChargeId = ''\n // TODO: Consider adding a unique charge ID per row\n // hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // // 1. Resource hierarchy (including resource name), highest to lowest\n // BillingAccountId,\n // x_InvoiceSectionId,\n // x_AccountOwnerId,\n // SubAccountId,\n // x_ResourceGroupName,\n // ResourceName,\n // // 2. Resource details\n // ResourceId,\n // RegionId,\n // Tags,\n // CommitmentDiscountId,\n // x_CostCenter,\n // // 4. Meter details\n // SkuPriceId,\n // x_SkuMeterId,\n // x_SkuPartNumber,\n // x_SkuOfferId,\n // x_SkuDetails,\n // // 5. Date\n // ChargePeriodStart\n // ))\n //\n // Identify data quality issues\n // TODO: Remove x_SourceChanges in v1_3 (or later)\n | extend x_SourceChanges = trim_end(',', strcat(\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based', 'InvalidChargeFrequency,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and EffectiveCost > 0, 'InvalidEffectiveCost,', ''),\n iff((isempty(ContractedCost) or ContractedCost == 0) and EffectiveCost != 0, 'MissingContractedCost,', ''),\n iff((isempty(ContractedUnitPrice) or ContractedUnitPrice == 0) and x_EffectiveUnitPrice != 0, 'MissingContractedUnitPrice,', ''),\n iff(ListCost < ContractedCost, 'ListCostLessThanContractedCost,', ''),\n iff(ContractedCost < EffectiveCost, 'ContractedCostLessThanEffectiveCost,', ''),\n iff((isempty(ListCost) or ListCost == 0) and (ContractedCost != 0 or EffectiveCost != 0), 'MissingListCost,', ''),\n iff((isempty(ListUnitPrice) or ListUnitPrice == 0) and (ContractedUnitPrice != 0 or x_EffectiveUnitPrice != 0), 'MissingListUnitPrice,', ''),\n iff((isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001)\n or (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001),\n 'XEffectiveUnitPriceRoundingError,', ''),\n iff(ConsumedQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingConsumedQuantity,', ''),\n iff(PricingQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingPricingQuantity,', ''),\n iff(isempty(ProviderName), 'MissingProviderName,', ''),\n iff(isempty(PublisherName), 'MissingPublisherName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceId), 'MissingResourceId,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceName), 'MissingResourceName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceType), 'MissingResourceType,', ''),\n iff(BilledCost > 0 and x_BilledUnitPrice == 0, 'MissingXBilledUnitPrice,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(x_ResourceType), 'MissingXResourceType,', ''),\n iff(PricingCategory == 'Standard' and isnotempty(CommitmentDiscountId) and ChargeCategory == 'Usage', 'PricingCategoryShouldBeCommitted,', ''),\n iff(x_SkuTerm == '1Year' or x_SkuTerm == '3Years' or x_SkuTerm == '5Years', 'SkuTermShouldBeAnInteger,', '')\n ))\n //\n // Handle provider columns that moved to FOCUS\n | extend PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency)\n //\n // Backup original prices/costs before the merge\n | extend old_ContractedCost = ContractedCost\n | extend old_ContractedUnitPrice = ContractedUnitPrice\n | extend old_ListCost = ListCost\n | extend old_ListUnitPrice = ListUnitPrice\n | extend old_x_EffectiveUnitPrice = x_EffectiveUnitPrice\n //\n // Fix columns needed in other changes\n | extend old_ProviderName = ProviderName, ProviderName = case(\n isnotempty(ProviderName), ProviderName,\n isnotempty(coalesce(x_CostCategories, x_Discount, x_Operation, x_ServiceCode, x_UsageType)), 'AWS',\n isnotempty(coalesce(tostring(UsageAmount), tostring(x_Cost), x_Credits, x_CostType, tostring(x_CurrencyConversionRate), tostring(x_ExportTime), x_Project, x_ServiceId)), 'GCP',\n isnotempty(coalesce(x_BillingProfileId, x_InvoiceSectionId)), 'Microsoft',\n ''\n )\n //\n // Identify source\n | extend x_SourceName = coalesce(x_SourceName, iff(isnotempty(x_BillingProfileId), 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(isnotempty(x_BillingProfileId), 'FocusCost', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, case(\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)) and isempty(SkuPriceDetails) and isnotempty(x_SkuDetails), '1.2-preview',\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)), '1.2',\n isnotempty(coalesce(ChargeClass, CommitmentDiscountStatus, tostring(ConsumedQuantity), ConsumedUnit, tostring(ContractedCost), tostring(ContractedUnitPrice), RegionId, RegionName)), '1.0',\n isnotempty(coalesce(ChargeSubcategory, Region, tostring(UsageQuantity), UsageUnit)), iff(ProviderName == 'Microsoft', '1.0-preview(v1)', '1.0-preview'),\n ''\n ))\n // Append version check error code\n | extend x_SourceChanges = iff(x_SourceVersion == '1.0', x_SourceChanges,\n strcat(x_SourceChanges, iff(isempty(x_SourceChanges), '', ','), iff(x_SourceVersion == '', 'UnknownFocusVersion', 'LegacyFocusVersion'))\n )\n //\n // Fix quantities\n | extend old_PricingQuantity = PricingQuantity, PricingQuantity = case(\n PricingQuantity != 0 or (EffectiveCost == 0 and BilledCost == 0), PricingQuantity,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(EffectiveCost) and EffectiveCost != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0, EffectiveCost / x_EffectiveUnitPrice,\n PricingQuantity\n )\n | extend old_ConsumedQuantity = ConsumedQuantity, ConsumedQuantity = case(\n isnotempty(ConsumedQuantity) and ConsumedQuantity != 0, ConsumedQuantity,\n ChargeCategory == 'Usage', PricingQuantity / coalesce(x_PricingBlockSize, real(1)),\n ConsumedQuantity\n )\n //\n // Populate missing prices -- mapping to on-demand prices requires meter ID and offer ID\n | extend tmp_MissingPrices = ProviderName == 'Microsoft'\n and (isempty(ListUnitPrice) or isempty(ContractedUnitPrice) or ListUnitPrice == 0 or ContractedUnitPrice == 0)\n and x_EffectiveUnitPrice != 0\n and not(CommitmentDiscountCategory == 'Spend' and CommitmentDiscountStatus == 'Unused')\n and isnotempty(strcat(x_SkuMeterId, x_SkuOfferId))\n | as allCosts\n | where tmp_MissingPrices\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(ChargePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | as costsWithMissingPrices\n | join kind=leftouter (\n Prices_final_v1_2\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(x_EffectivePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | where x_SkuPriceType == 'Consumption' and tmp_ReservationPriceLookupKey in ((costsWithMissingPrices | summarize by tmp_ReservationPriceLookupKey))\n | summarize ListUnitPrice = min(ListUnitPrice), ContractedUnitPrice = min(ContractedUnitPrice) by tmp_ReservationPriceLookupKey, x_PricingBlockSize, PricingUnit\n ) on tmp_ReservationPriceLookupKey\n //\n // Select the best price to use for each row\n | extend x_EffectiveUnitPrice = case(\n // If price is a rounding error away from the billed price, use the billed price\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001, x_BilledUnitPrice,\n // If price is a rounding error away from the contracted price, use the contracted price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001, ContractedUnitPrice,\n x_EffectiveUnitPrice\n )\n | extend ContractedUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ContractedUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ContractedUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // If billed price is available, assume the billed price is the same as contracted price to support aggregations\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, x_EffectiveUnitPrice,\n // Otherwise, assume the effective price is the same as contracted price to support aggregations\n x_EffectiveUnitPrice\n )\n | extend ListUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ListUnitPrice) and ListUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ListUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ListUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ListUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // Otherwise, assume the contracted price is the same as list price to support aggregations\n ContractedUnitPrice\n )\n // Calculate missing costs based on new prices -- If cost is already correct, keep that; if not and price is available, recalculate the cost; otherwise, keep the existing cost\n | extend ContractedCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ContractedCost) and ContractedCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedCost,\n // ContractedCost is 0 in all other scenarios...\n // If 0 and there's a billed cost and prices are the same, use BilledCost\n isnotempty(BilledCost) and BilledCost != 0 and ContractedUnitPrice == x_BilledUnitPrice, BilledCost,\n // If 0 and there's a billed cost and prices are the same, use EffectiveCost\n isnotempty(EffectiveCost) and EffectiveCost != 0 and ContractedUnitPrice == x_EffectiveUnitPrice, EffectiveCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0, ContractedUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume EffectiveCost\n isempty(ContractedUnitPrice) or ContractedUnitPrice == 0, EffectiveCost,\n // Fall back to the original value for any unhandled scenarios\n ContractedCost\n )\n | extend ListCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ListCost) and ListCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ListCost,\n // ListCost is 0 in all other scenarios...\n // If 0 and there's a contracted cost and prices are the same, use ContractedCost\n isnotempty(ContractedCost) and ContractedCost != 0 and ListUnitPrice == ContractedUnitPrice, ContractedCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ListUnitPrice) and ListUnitPrice != 0, ListUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume ContractedCost\n isempty(ListUnitPrice) or ListUnitPrice == 0, ContractedCost,\n // Fall back to the original value for any unhandled scenarios\n ListCost\n )\n // Merge the rest of the unmodified cost records and remove excess columns\n | union (allCosts | where not(tmp_MissingPrices))\n | project-away x_PricingBlockSize1, PricingUnit1, ListUnitPrice1, ContractedUnitPrice1, tmp_MissingPrices, tmp_ReservationPriceLookupKey, tmp_ReservationPriceLookupKey1\n //\n | extend SkuPriceDetails = parse_json(SkuPriceDetails)\n | extend Tags = parse_json(Tags)\n | extend x_SkuDetails = parse_json(x_SkuDetails)\n //\n // Handle FOCUS 1.0-preview\n | extend old_ChargeSubcategory = ChargeSubcategory\n | extend old_ChargeCategory = ChargeCategory, ChargeCategory = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Credit', 'Credit',\n ChargeSubcategory == 'Refund', 'Purchase', // We are assuming purchase refunds since we don't have data to indicate usage refunds\n ChargeCategory\n )\n | extend old_ChargeClass = ChargeClass, ChargeClass = case(ChargeSubcategory == 'Refund', 'Correction', ChargeClass)\n //\n // Populate CapacityReservationId when not specified\n | extend CapacityReservationId = coalesce(CapacityReservationId, tostring(coalesce(x_SkuDetails.VMCapacityReservationId, SkuPriceDetails.VMCapacityReservationId, SkuPriceDetails.x_VMCapacityReservationId)))\n | extend old_CapacityReservationStatus = CapacityReservationStatus, CapacityReservationStatus = case(\n isempty(CapacityReservationId), '',\n isnotempty(CapacityReservationStatus), CapacityReservationStatus,\n tolower(x_ResourceType) == 'microsoft.compute/capacityreservationgroups/capacityreservations', 'Unused',\n 'Used'\n )\n //\n // BUG: ChargeFrequency shows \"Usage-Based\" for monthly recurring savings plan purchases\n | extend old_ChargeFrequency = ChargeFrequency, ChargeFrequency = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based' and ProviderName == 'Microsoft' and x_SourceVersion startswith '1.0', 'Recurring', ChargeFrequency)\n //\n // Commitment discounts\n | extend x_CommitmentDiscountNormalizedRatio = case(\n // Calculate from CommitmentDiscountQuantity, if specified\n isnotempty(CommitmentDiscountQuantity) and CommitmentDiscountQuantity != 0, CommitmentDiscountQuantity / PricingQuantity / coalesce(x_PricingBlockSize, real(1)),\n // Not applicable\n isempty(CommitmentDiscountStatus), real(null),\n // Parse from SKU details if not specified explicitly\n toreal(coalesce(x_SkuDetails.RINormalizationRatio, SkuPriceDetails.RINormalizationRatio, SkuPriceDetails.x_RINormalizationRatio, dynamic(1)))\n )\n | extend old_CommitmentDiscountQuantity = CommitmentDiscountQuantity, CommitmentDiscountQuantity = case(\n // FOCUS 1.2\n isnotempty(CommitmentDiscountQuantity), CommitmentDiscountQuantity,\n // FOCUS 1.0-preview, 1.0\n isempty(CommitmentDiscountStatus), real(null),\n CommitmentDiscountCategory == 'Spend', EffectiveCost / coalesce(x_BillingExchangeRate, real(1)),\n CommitmentDiscountCategory == 'Usage' and isnotempty(x_CommitmentDiscountNormalizedRatio), PricingQuantity / coalesce(x_PricingBlockSize, real(1)) * x_CommitmentDiscountNormalizedRatio,\n real(null)\n )\n | extend old_CommitmentDiscountUnit = CommitmentDiscountUnit, CommitmentDiscountUnit = case(\n // FOCUS 1.2\n isnotempty(CommitmentDiscountUnit), CommitmentDiscountUnit,\n // FOCUS 1.0\n isempty(CommitmentDiscountQuantity), '',\n CommitmentDiscountCategory == 'Spend', PricingCurrency,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio == real(1), ConsumedUnit,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio > real(1), strcat('Normalized ', ConsumedUnit),\n ''\n )\n | extend old_CommitmentDiscountStatus = CommitmentDiscountStatus, CommitmentDiscountStatus = case(\n // FOCUS 1.0+\n isnotempty(CommitmentDiscountStatus), CommitmentDiscountStatus,\n // FOCUS 1.0-preview\n ChargeSubcategory == 'Used Commitment', 'Used',\n ChargeSubcategory == 'Unused Commitment', 'Unused',\n ''\n )\n | extend x_CommitmentDiscountUtilizationPotential = case(\n ChargeCategory == 'Purchase', real(0),\n ProviderName == 'Microsoft' and isnotempty(CommitmentDiscountCategory), EffectiveCost,\n CommitmentDiscountCategory == 'Usage', ConsumedQuantity,\n CommitmentDiscountCategory == 'Spend', EffectiveCost,\n real(0)\n )\n | extend x_CommitmentDiscountUtilizationAmount = iff(CommitmentDiscountStatus == 'Used', x_CommitmentDiscountUtilizationPotential, real(0))\n //\n // Pricing\n | extend old_x_AmortizationClass = x_AmortizationClass, x_AmortizationClass = case(\n // FOCUS 1.2\n isnotempty(x_AmortizationClass), x_AmortizationClass,\n // FOCUS 1.0-preview+\n ChargeCategory == 'Purchase' and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeCategory == 'Usage' and isnotempty(CommitmentDiscountId) and isnotempty(CommitmentDiscountStatus), 'Amortized Charge',\n ''\n )\n | extend old_PricingCategory = PricingCategory, PricingCategory = case(\n // FOCUS 1.0+\n isnotempty(PricingCategory), PricingCategory,\n // FOCUS 1.0-preview\n PricingCategory == 'On-Demand', 'Standard',\n PricingCategory == 'Commitment-Based', 'Committed',\n ''\n )\n //\n // Commitment discount utilization\n | extend x_CommitmentDiscountUtilizationPotential = case(\n ChargeCategory == 'Purchase', real(0),\n ProviderName == 'Microsoft' and isnotempty(CommitmentDiscountCategory), EffectiveCost,\n CommitmentDiscountCategory == 'Usage', ConsumedQuantity,\n CommitmentDiscountCategory == 'Spend', EffectiveCost,\n real(0)\n )\n | extend x_CommitmentDiscountUtilizationAmount = iff(CommitmentDiscountStatus == 'Used', x_CommitmentDiscountUtilizationPotential, real(0))\n //\n // BUG: Fix ContractedCost that has bad values\n | extend ContractedCost = iff(ProviderName == 'Microsoft' and isnotempty(PricingQuantity) and isnotempty(x_PricingBlockSize) and ContractedCost != ContractedUnitPrice * PricingQuantity, ContractedUnitPrice * PricingQuantity, ContractedCost)\n //\n // Handle FOCUS 1.0-preview UsageQuantity/Unit\n | extend ConsumedQuantity = iff(ChargeCategory == 'Usage', coalesce(ConsumedQuantity, UsageQuantity, UsageAmount), real(null))\n | extend old_ConsumedUnit = ConsumedUnit, ConsumedUnit = iff(ChargeCategory == 'Usage' and isnotempty(ConsumedQuantity), coalesce(ConsumedUnit, UsageUnit, 'Units'), '')\n //\n // Convert IDs to lowercase for consistency\n | extend BillingAccountId = tolower(BillingAccountId)\n | extend CommitmentDiscountId = tolower(CommitmentDiscountId)\n //\n // BUG: Remove EffectiveCost for commitment discount purchases\n | extend old_EffectiveCost = EffectiveCost, EffectiveCost = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), real(0), EffectiveCost)\n | extend old_x_EffectiveCostInUsd = x_EffectiveCostInUsd, x_EffectiveCostInUsd = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), real(0), x_EffectiveCostInUsd)\n //\n // Clean up resource columns\n | extend old_ResourceId = ResourceId, ResourceId = case(\n isnotempty(ResourceId), ResourceId,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), CommitmentDiscountId,\n ResourceId\n )\n | extend old_ResourceName = ResourceName, ResourceName = tolower(case(\n isnotempty(ResourceName), ResourceName,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountName), CommitmentDiscountName,\n isnotempty(ResourceId), parse_resourceid(ResourceId).ResourceName,\n ResourceName\n ))\n | extend old_x_ResourceType = x_ResourceType, x_ResourceType = case(\n isnotempty(x_ResourceType), x_ResourceType,\n isnotempty(ResourceId), parse_resourceid(ResourceId).x_ResourceType,\n x_ResourceType\n )\n | extend old_ResourceType = ResourceType, ResourceType = case(\n // Use existing resource type display name unless it's an internal resource type ID\n isnotempty(ResourceType) and tolower(ResourceType) != tolower(x_ResourceType) and ResourceType !contains '/', ResourceType,\n // Use CommitmentDiscountType for commitment discount purchases\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountType), CommitmentDiscountType,\n // Look up display name from internal type\n isnotempty(x_ResourceType), coalesce(tostring(resource_type(x_ResourceType).SingularDisplayName), ResourceType, x_ResourceType),\n ResourceType\n )\n //\n // Handle missing values\n | extend old_PublisherName = PublisherName, PublisherName = case(PublisherName == 'Microsoft Corporation', 'Microsoft', isnotempty(PublisherName), PublisherName, x_PublisherCategory == 'Cloud Provider', ProviderName, '')\n //\n // Handle FOCUS 1.0-preview Region column\n | extend old_Region = Region\n | extend old_RegionId = RegionId, RegionId = coalesce(RegionId, iff(ProviderName == 'Microsoft', replace_string(tolower(Region), ' ', ''), Region))\n | extend RegionName = coalesce(RegionName, Region)\n //\n // SKU properties\n | extend x_SkuCoreCount = toint(coalesce(SkuPriceDetails.CoreCount, SkuPriceDetails.x_VCPUs, x_SkuDetails.VCPUs, SkuPriceDetails.x_VCores, x_SkuDetails.VCores, SkuPriceDetails.x_vCores, x_SkuDetails.vCores))\n | extend x_SkuInstanceType = tostring(coalesce(SkuPriceDetails.InstanceType, SkuPriceDetails.x_ServiceType, x_SkuDetails.ServiceType, SkuPriceDetails.x_ServerSku, x_SkuDetails.ServerSku))\n | extend x_SkuOperatingSystem = case(\n isnotempty(SkuPriceDetails.OperatingSystem), SkuPriceDetails.OperatingSystem,\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Canonical', 'Linux',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL', 'Windows Server',\n x_SkuMeterSubcategory endswith ' Series Windows', 'Windows Server',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType)\n )\n | extend x_ConsumedCoreHours = iff(ConsumedUnit == 'Hours' and isnotempty(x_SkuCoreCount), x_SkuCoreCount * ConsumedQuantity, real(null))\n | extend SkuPriceDetails = case(\n // FOCUS 1.2\n isnotempty(SkuPriceDetails), SkuPriceDetails,\n // FOCUS 1.0-preview, 1.0\n parse_json(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(tostring(x_SkuDetails)\n // Prefix all keys with x_ first to avoid double-prefixing\n , @'([\\{,])\"', @'\\1\"x_')\n // CoreCount for number of CPUs/vCPUs/cores/vCores\n , @'\"x_(VCPUs|VCores|vCores)\":', @'\"CoreCount\":')\n // TODO: DiskMaxIops for disk I/O operations per second (IOPS)\n // TODO: DiskSpace for disk size in GiB\n // TODO: DiskType for the kind of disk (e.g., SSD, HDD, NVMe)\n // TODO: GpuCount for the number of GPUs\n // InstanceType for the resource size/SKU (e.g., ArmSkuName)\n , @'\"x_(ServerSku|ServiceType)\":', @'\"InstanceType\":')\n // TODO: InstanceSeries for the size family/series\n // TODO: MemorySize for the RAM in GiB\n // TODO: NetworkMaxIops for network I/O operations per second (IOPS)\n // TODO: NetworkMaxThroughput for network max throughput for data transfer in Mbps\n // OperatingSystem for the OS name\n , @'(\"x_ImageType\":\"Canonical\")', @'\\1,\"OperatingSystem\":\"Linux\"')\n , @'(\"x_ImageType\":\"Windows Server( BYOL)?\")', @'\\1,\"OperatingSystem\":\"Windows Server\"')\n , @'(\"x_ImageType\":(\"[^\"]+\"))', @'\\1,\"OperatingSystem\":\\2')\n // TODO: Redundancy for the level of redundancy (e.g., Local, Zonal, Global)\n // TODO: StorageClass for the tier of storage (e.g., Hot, Archive, Nearline)\n )\n )\n | extend SkuPriceDetails = iff(isempty(SkuPriceDetails.OperatingSystem) and isnotempty(x_SkuOperatingSystem),\n parse_json(replace_string(tostring(SkuPriceDetails), '}', strcat(@',\"OperatingSystem\":\"', x_SkuOperatingSystem, '\"}'))),\n SkuPriceDetails)\n //\n // Azure Hybrid Benefit\n | extend tmp_SqlAhb = tolower(coalesce(x_SkuDetails.AHB, SkuPriceDetails.x_AHB))\n | extend x_SkuLicenseType = case(\n ChargeCategory != 'Usage', '',\n x_SkuMeterCategory in ('Virtual Machines', 'Virtual Machine Licenses') and (x_SkuMeterSubcategory contains 'Windows' or coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL'), 'Windows Server',\n isnotempty(tmp_SqlAhb) or x_SkuMeterSubcategory == 'SQL Server Azure Hybrid Benefit', 'SQL Server',\n ''\n )\n | extend x_SkuLicenseStatus = case(\n isempty(x_SkuLicenseType), '',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL' or tmp_SqlAhb == 'true' or x_SkuMeterSubcategory contains 'Azure Hybrid Benefit', 'Enabled',\n (x_SkuMeterSubcategory contains 'Windows') or tmp_SqlAhb == 'false', 'Not Enabled',\n ''\n )\n | extend x_SkuLicenseQuantity = case(\n isempty(x_SkuCoreCount) or isempty(x_SkuLicenseType), int(null),\n x_SkuCoreCount <= 8, int(8),\n x_SkuCoreCount > 8, x_SkuCoreCount,\n int(null)\n )\n | extend x_SkuLicenseUnit = iff(isnotempty(x_SkuLicenseQuantity), 'Cores', '')\n //\n // Savings\n | extend x_CommitmentDiscountSavings = iff(isempty(ContractedCost) or ContractedCost == 0 or ContractedCost - EffectiveCost < 0.0001, real(0), ContractedCost - EffectiveCost)\n | extend x_NegotiatedDiscountSavings = iff(isempty(ListCost) or ListCost == 0 or ListCost - ContractedCost < 0.0001, real(0), ListCost - ContractedCost)\n | extend x_TotalSavings = iff(isempty(ListCost) or ListCost == 0 or ListCost - EffectiveCost < 0.0001, real(0), ListCost - EffectiveCost)\n | extend x_CommitmentDiscountPercent = iff(isempty(ContractedUnitPrice) or ContractedUnitPrice == 0 or ContractedUnitPrice - x_EffectiveUnitPrice < 0.0001, real(0), (ContractedUnitPrice - x_EffectiveUnitPrice) / ContractedUnitPrice)\n | extend x_NegotiatedDiscountPercent = iff(isempty(ListUnitPrice) or ListUnitPrice == 0 or ListUnitPrice - ContractedUnitPrice < 0.0001, real(0), (ListUnitPrice - ContractedUnitPrice) / ListUnitPrice)\n | extend x_TotalDiscountPercent = iff(isempty(ListUnitPrice) or ListUnitPrice == 0 or ListUnitPrice - x_EffectiveUnitPrice < 0.0001, real(0), (ListUnitPrice - x_EffectiveUnitPrice) / ListUnitPrice)\n //\n // Minor fixes\n | extend old_BillingPeriodEnd = BillingPeriodEnd, BillingPeriodEnd = startofmonth(BillingPeriodEnd)\n | extend old_BillingPeriodStart = BillingPeriodStart, BillingPeriodStart = startofmonth(BillingPeriodStart)\n //\n // Sort columns and apply final transforms\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId,\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd,\n BillingPeriodStart,\n CapacityReservationId,\n CapacityReservationStatus,\n ChargeCategory,\n ChargeClass,\n ChargeDescription,\n ChargeFrequency,\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId,\n CommitmentDiscountName,\n CommitmentDiscountQuantity,\n CommitmentDiscountStatus,\n CommitmentDiscountType,\n CommitmentDiscountUnit,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost = coalesce(ContractedCost, x_OnDemandCost, x_Cost),\n ContractedUnitPrice = coalesce(ContractedUnitPrice, x_OnDemandUnitPrice),\n EffectiveCost,\n InvoiceId = coalesce(InvoiceId, x_InvoiceId),\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory,\n PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency),\n PricingQuantity,\n PricingUnit,\n ProviderName,\n PublisherName,\n RegionId,\n RegionName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory, // TODO: Populate ServiceSubcategory from ServiceName when missing\n SkuId,\n SkuMeter = coalesce(SkuMeter, x_SkuMeterName),\n SkuPriceDetails,\n SkuPriceId,\n SubAccountId,\n SubAccountName = iff(isempty(SubAccountId), '', SubAccountName),\n SubAccountType,\n Tags,\n x_AccountId = iff(x_AccountId == '-2', '', x_AccountId),\n x_AccountName = iff(x_AccountId == '-2', '', x_AccountName),\n x_AccountOwnerId = iff(x_AccountId == '-2', '', x_AccountOwnerId),\n x_AmortizationClass,\n x_BilledCostInUsd,\n x_BilledUnitPrice,\n x_BillingAccountAgreement = case(\n ProviderName == 'Microsoft' and x_BillingAccountId == x_BillingProfileId, 'EA',\n ProviderName == 'Microsoft' and x_BillingAccountId != x_BillingProfileId, 'MCA',\n ProviderName\n ),\n x_BillingAccountId,\n x_BillingAccountName,\n x_BillingExchangeRate,\n x_BillingExchangeRateDate,\n x_BillingItemCode,\n x_BillingItemName,\n x_BillingProfileId,\n x_BillingProfileName,\n x_ChargeId,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountPercent,\n x_CommitmentDiscountSavings,\n x_CommitmentDiscountSpendEligibility = '', // TODO: Add x_CommitmentDiscountSpendEligibility for Costs\n x_CommitmentDiscountUsageEligibility = '', // TODO: Add x_CommitmentDiscountUsageEligibility for Costs\n x_CommitmentDiscountUtilizationAmount,\n x_CommitmentDiscountUtilizationPotential,\n x_CommodityCode,\n x_CommodityName,\n x_ComponentName,\n x_ComponentType,\n x_ConsumedCoreHours,\n x_ContractedCostInUsd = coalesce(x_ContractedCostInUsd, x_OnDemandCostInUsd),\n x_CostAllocationRuleName,\n x_CostCategories = parse_json(x_CostCategories),\n x_CostCenter,\n x_CostType,\n x_Credits = parse_json(x_Credits),\n x_CurrencyConversionRate,\n x_CustomerId,\n x_CustomerName,\n x_Discount = parse_json(x_Discount),\n x_EffectiveCostInUsd,\n x_EffectiveUnitPrice,\n x_ExportTime,\n x_IngestionTime,\n x_InstanceID,\n x_InvoiceIssuerId,\n x_InvoiceSectionId = case(\n x_InvoiceSectionId == '-2', '',\n x_InvoiceSectionId\n ),\n x_InvoiceSectionName = case(\n x_InvoiceSectionName == 'Unassigned', '',\n x_InvoiceSectionName\n ),\n x_ListCostInUsd,\n x_Location,\n x_NegotiatedDiscountPercent,\n x_NegotiatedDiscountSavings,\n x_Operation,\n x_OwnerAccountID,\n x_PartnerCreditApplied,\n x_PartnerCreditRate,\n x_PricingBlockSize,\n x_PricingSubcategory,\n x_PricingUnitDescription = iff(x_PricingUnitDescription == 'Unassigned', '', x_PricingUnitDescription),\n x_Project,\n x_PublisherCategory,\n x_PublisherId,\n x_ResellerId,\n x_ResellerName,\n x_ResourceGroupName = tolower(x_ResourceGroupName),\n x_ResourceType,\n x_ServiceCode,\n x_ServiceId,\n x_ServiceModel, // TODO: Populate from ServiceName when missing\n x_ServicePeriodEnd,\n x_ServicePeriodStart,\n x_SkuCoreCount,\n x_SkuDescription,\n x_SkuDetails,\n x_SkuInstanceType,\n x_SkuIsCreditEligible,\n x_SkuLicenseQuantity,\n x_SkuLicenseStatus,\n x_SkuLicenseType,\n x_SkuLicenseUnit,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterSubcategory,\n x_SkuOfferId,\n x_SkuOperatingSystem,\n x_SkuOrderId,\n x_SkuOrderName,\n x_SkuPartNumber,\n x_SkuPlanName,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuTerm,\n x_SkuTier,\n x_SourceChanges,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceValues = bag_merge(\n checkString('BillingPeriodEnd', old_BillingPeriodEnd, BillingPeriodEnd),\n checkString('BillingPeriodStart', old_BillingPeriodStart, BillingPeriodStart),\n checkString('CapacityReservationStatus', old_CapacityReservationStatus, CapacityReservationStatus),\n checkString('ChargeCategory', old_ChargeCategory, ChargeCategory),\n checkString('ChargeClass', old_ChargeClass, ChargeClass),\n checkString('ChargeSubcategory', old_ChargeSubcategory, ''), // Not included in final schema; use empty string\n checkString('ChargeFrequency', old_ChargeFrequency, ChargeFrequency),\n checkReal('CommitmentDiscountQuantity', old_CommitmentDiscountQuantity, CommitmentDiscountQuantity),\n checkString('CommitmentDiscountUnit', old_CommitmentDiscountUnit, CommitmentDiscountUnit),\n checkString('CommitmentDiscountStatus', old_CommitmentDiscountStatus, CommitmentDiscountStatus),\n checkReal('ConsumedQuantity', old_ConsumedQuantity, ConsumedQuantity),\n checkString('ConsumedUnit', old_ConsumedUnit, ConsumedUnit),\n checkReal('ContractedCost', old_ContractedCost, ContractedCost),\n checkReal('ContractedUnitPrice', old_ContractedUnitPrice, ContractedUnitPrice),\n checkReal('EffectiveCost', old_EffectiveCost, EffectiveCost),\n checkReal('ListCost', old_ListCost, ListCost),\n checkReal('ListUnitPrice', old_ListUnitPrice, ListUnitPrice),\n checkString('PricingCategory', old_PricingCategory, PricingCategory),\n checkReal('PricingQuantity', old_PricingQuantity, PricingQuantity),\n checkString('ProviderName', old_ProviderName, ProviderName),\n checkString('PublisherName', old_PublisherName, PublisherName),\n checkString('Region', old_Region, ''), // Not included in final schema; use empty string\n checkString('RegionId', old_RegionId, RegionId),\n checkString('ResourceId', old_ResourceId, ResourceId),\n checkString('ResourceName', old_ResourceName, ResourceName),\n checkString('ResourceType', old_ResourceType, ResourceType),\n checkString('x_AmortizationClass', old_x_AmortizationClass, x_AmortizationClass),\n checkReal('x_EffectiveCostInUsd', old_x_EffectiveCostInUsd, x_EffectiveCostInUsd),\n checkReal('x_EffectiveUnitPrice', old_x_EffectiveUnitPrice, x_EffectiveUnitPrice),\n checkString('x_ResourceType', old_x_ResourceType, x_ResourceType)\n ),\n x_SourceVersion,\n x_SubproductName,\n x_TotalDiscountPercent,\n x_TotalSavings,\n x_UsageType\n}\n\n// Costs_final_v1_2 table\n.create-merge table Costs_final_v1_2 (\n AvailabilityZone: string,\n BilledCost: real,\n BillingAccountId: string,\n BillingAccountName: string,\n BillingAccountType: string,\n BillingCurrency: string,\n BillingPeriodEnd: datetime,\n BillingPeriodStart: datetime,\n CapacityReservationId: string,\n CapacityReservationStatus: string,\n ChargeCategory: string,\n ChargeClass: string,\n ChargeDescription: string,\n ChargeFrequency: string,\n ChargePeriodEnd: datetime,\n ChargePeriodStart: datetime,\n CommitmentDiscountCategory: string,\n CommitmentDiscountId: string,\n CommitmentDiscountName: string,\n CommitmentDiscountQuantity: real,\n CommitmentDiscountStatus: string,\n CommitmentDiscountType: string,\n CommitmentDiscountUnit: string,\n ConsumedQuantity: real,\n ConsumedUnit: string,\n ContractedCost: real,\n ContractedUnitPrice: real,\n EffectiveCost: real,\n InvoiceId: string,\n InvoiceIssuerName: string,\n ListCost: real,\n ListUnitPrice: real,\n PricingCategory: string,\n PricingCurrency: string,\n PricingQuantity: real,\n PricingUnit: string,\n ProviderName: string,\n PublisherName: string,\n RegionId: string,\n RegionName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n ServiceCategory: string,\n ServiceName: string,\n ServiceSubcategory: string,\n SkuId: string,\n SkuMeter: string,\n SkuPriceDetails: dynamic,\n SkuPriceId: string,\n SubAccountId: string,\n SubAccountName: string,\n SubAccountType: string,\n Tags: dynamic,\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_AmortizationClass: string, // Azure 1.2-preview+\n x_BilledCostInUsd: real, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: real, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: real, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingItemCode: string, // Alibaba 1.0\n x_BillingItemName: string, // Alibaba 1.0\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_CommitmentDiscountNormalizedRatio: real, // Azure 1.2-preview+\n x_CommitmentDiscountPercent: real, // Hubs add-on\n x_CommitmentDiscountSavings: real, // Hubs add-on\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_CommitmentDiscountUtilizationAmount: real, // Hubs add-on\n x_CommitmentDiscountUtilizationPotential: real, // Hubs add-on\n x_CommodityCode: string, // Alibaba 1.0\n x_CommodityName: string, // Alibaba 1.0\n x_ComponentName: string, // Tencent 1.0\n x_ComponentType: string, // Tencent 1.0\n x_ConsumedCoreHours: real, // Hubs add-on\n x_ContractedCostInUsd: real, // Azure 1.0+\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: dynamic, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_CostType: string, // GCP Jan 2024\n x_Credits: dynamic, // GCP Jan 2024\n x_CurrencyConversionRate: real, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: dynamic, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: real, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: real, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024 / Tencent 1.0\n x_IngestionTime: datetime, // Hubs add-on\n x_InstanceID: string, // Alibaba 1.0\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: real, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_NegotiatedDiscountPercent:real, // Hubs add-on\n x_NegotiatedDiscountSavings:real, // Hubs add-on\n x_Operation: string, // AWS 1.0\n x_OwnerAccountID: string, // Tencent 1.0\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: real, // Azure 1.0-preview(v1)+\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServiceModel: string, // Azure 1.2-preview+\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuCoreCount: int, // Hubs add-on\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: dynamic, // Azure 1.0-preview(v1)+\n x_SkuInstanceType: string, // Hubs add-on\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuLicenseQuantity: int, // Hubs add-on\n x_SkuLicenseStatus: string, // Hubs add-on\n x_SkuLicenseType: string, // Hubs add-on\n x_SkuLicenseUnit: string, // Hubs add-on\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOperatingSystem: string, // Hubs add-on\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuPlanName: string, // Azure 1.2-preview+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceChanges: string, // Hubs add-on\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceValues: dynamic, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubproductName: string, // Tencent 1.0\n x_TotalDiscountPercent: real, // Hubs add-on\n x_TotalSavings: real, // Hubs add-on\n x_UsageType: string // AWS 1.0\n)\n\n// Update policy for Costs_raw -> Costs_final_v1_2 table\n.alter table Costs_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Costs_raw\",\n \"Query\": \"Costs_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Actual costs |===================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_transform_v1_2 function\n.create-or-alter function\nwith (docstring='ActualCost exports transformed to FOCUS 1.2.', folder='Costs')\nActualCosts_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n ActualCosts_raw\n | where ChargeType in ('Purchase', 'Refund') and isnotempty(ReservationId)\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: PublisherName, x_PublisherCategory, x_Environment\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory), take_any(ServiceSubcategory), take_any(x_ServiceModel) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodEnd = Date + 1d,\n ChargePeriodStart = Date,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SkuId = '',\n SkuMeter = MeterName,\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = iff(isempty(SubscriptionId), '', SubscriptionName),\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentType = '',\n x_ComponentName = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = '',\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel,\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for ActualCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": true,\n \"Source\": \"ActualCosts_raw\",\n \"Query\": \"ActualCosts_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Amortized costs |================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_transform_v1_2 function\n.create-or-alter function\nwith (docstring='ActualCost exports transformed to FOCUS 1.2.', folder='Costs')\nAmortizedCosts_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n AmortizedCosts_raw\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: PublisherName, x_PublisherCategory, x_Environment\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory), take_any(ServiceSubcategory), take_any(x_ServiceModel) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodEnd = Date + 1d,\n ChargePeriodStart = Date,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SkuId = '',\n SkuMeter = MeterName,\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = iff(isempty(SubscriptionId), '', SubscriptionName),\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentType = '',\n x_ComponentName = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = '',\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel,\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for AmortizedCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": true,\n \"Source\": \"AmortizedCosts_raw\",\n \"Query\": \"AmortizedCosts_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All commitment discount usage transformed to FOCUS 1.2. This includes reservationdeatils_raw.', folder='Commitment discounts')\nCommitmentDiscountUsage_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n CommitmentDiscountUsage_raw\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Handle resource columns\n | extend ResourceId = tolower(InstanceId)\n | extend tmp_ResourceDetails = parse_resourceid(ResourceId)\n | extend ResourceName = tostring(tmp_ResourceDetails.ResourceName)\n | extend SubAccountId = tostring(tmp_ResourceDetails.SubAccountId)\n | extend x_ResourceGroupName = tostring(tmp_ResourceDetails.x_ResourceGroupName)\n | extend x_ResourceType = tostring(tmp_ResourceDetails.x_ResourceType)\n | lookup kind=leftouter (ResourceTypes | distinct x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n | lookup kind=leftouter (Services | distinct x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n //\n // Sort columns and apply final transforms\n | project\n ChargePeriodEnd = UsageDate + 1d,\n ChargePeriodStart = UsageDate,\n CommitmentDiscountCategory = 'Usage',\n CommitmentDiscountId = tolower(strcat('/providers/microsoft.capacity/reservationorders/', ReservationOrderId, '/reservations/', ReservationId)),\n CommitmentDiscountQuantity = UsedHours * InstanceFlexibilityRatio,\n CommitmentDiscountType = 'Reservation',\n CommitmentDiscountUnit = case(\n InstanceFlexibilityRatio == 1, 'Hours',\n InstanceFlexibilityRatio != 1, 'Normalized Hours',\n ''\n ),\n ConsumedQuantity = UsedHours,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SubAccountId,\n x_CommitmentDiscountCommittedCount = TotalReservedQuantity,\n x_CommitmentDiscountCommittedAmount = ReservedHours,\n // TODO: Is this needed? -- x_CommitmentDiscountKind = Kind,\n x_CommitmentDiscountNormalizedGroup = iff(InstanceFlexibilityGroup == 'NA', '', InstanceFlexibilityGroup),\n x_CommitmentDiscountNormalizedRatio = InstanceFlexibilityRatio,\n x_IngestionTime = ingestion_time(),\n x_ResourceGroupName,\n x_ResourceType,\n // x_RowId = hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // CommitmentDiscountId,\n // ResourceId,\n // ChargePeriodStart\n // )),\n x_ServiceModel,\n x_SkuOrderId = ReservationOrderId,\n x_SkuSize = iff(SkuName == 'NA', '', SkuName),\n x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName)),\n x_SourceProvider = coalesce(x_SourceProvider, ProviderName),\n x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationDetails', '')),\n x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2024-03-01', ''))\n}\n\n// CommitmentDiscountUsage_final_v1_2 table\n.create-merge table CommitmentDiscountUsage_final_v1_2 (\n ChargePeriodEnd: datetime, // Hubs add-on\n ChargePeriodStart: datetime, // MS 2023-03-01\n CommitmentDiscountCategory: string, // Hubs add-on\n CommitmentDiscountId: string, // MS 2023-03-01\n CommitmentDiscountQuantity: real, // MS 2023-03-01\n CommitmentDiscountType: string, // Hubs add-on\n CommitmentDiscountUnit: string, // Hubs add-on\n ConsumedQuantity: real, // MS 2023-03-01\n ProviderName: string, // Hubs add-on\n ResourceId: string, // MS 2023-03-01\n ResourceName: string, // Hubs add-on\n ResourceType: string, // Hubs add-on\n ServiceCategory: string, // Hubs add-on\n ServiceName: string, // Hubs add-on\n ServiceSubcategory: string, // Hubs add-on\n SubAccountId: string, // Hubs add-on\n x_CommitmentDiscountCommittedCount: real, // MS 2023-03-01\n x_CommitmentDiscountCommittedAmount: real, // MS 2023-03-01\n x_CommitmentDiscountNormalizedGroup: string, // MS 2023-03-01\n x_CommitmentDiscountNormalizedRatio: real, // MS 2023-03-01\n x_IngestionTime: datetime, // Hubs add-on\n x_ResourceGroupName: string, // Hubs add-on\n x_ResourceType: string, // Hubs add-on\n x_ServiceModel: string, // Hubs add-on\n x_SkuOrderId: string, // MS 2023-03-01\n x_SkuSize: string, // MS 2023-03-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string // Hubs add-on\n)\n\n// Update policy for CommitmentDiscountUsage_raw -> CommitmentDiscountUsage_final_v1_2 table\n.alter table CommitmentDiscountUsage_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"CommitmentDiscountUsage_raw\",\n \"Query\": \"CommitmentDiscountUsage_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All recommendations transformed to FOCUS 1.2.', folder='Recommendations')\nRecommendations_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Recommendations_raw\n | extend x_IngestionTime = ingestion_time()\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationRecommendations', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Convert JSON cost columns to real\n | extend CostWithNoReservedInstances = case(isnotempty(CostWithNoReservedInstances), CostWithNoReservedInstances, isnotempty(CostWithNoReservedInstancesJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, CostWithNoReservedInstancesJson)), CostWithNoReservedInstances)\n | extend NetSavings = case(isnotempty(NetSavings), NetSavings, isnotempty(NetSavingsJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, NetSavingsJson)), NetSavings)\n | extend TotalCostWithReservedInstances = case(isnotempty(TotalCostWithReservedInstances), TotalCostWithReservedInstances, isnotempty(TotalCostWithReservedInstancesJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, TotalCostWithReservedInstancesJson)), TotalCostWithReservedInstances)\n //\n // Parse x_RecommendationDetails from JSON string (ARG queries serialize to string for Parquet compatibility)\n | extend x_RecommendationDetails = iff(gettype(x_RecommendationDetails) == 'string', parse_json(tostring(x_RecommendationDetails)), x_RecommendationDetails)\n //\n // Normalize x_RecommendationDetails keys to x_PascalCase (Advisor extendedProperties use camelCase)\n // Guard: inject a placeholder key so mv-apply doesn't drop rows with null/empty bags\n | extend x_RecommendationDetails = bag_merge(coalesce(x_RecommendationDetails, dynamic({})), bag_pack('__placeholder', ''))\n | mv-apply k = bag_keys(x_RecommendationDetails) on (\n where isnotempty(tostring(k)) and tostring(k) != '__placeholder'\n | extend newKey = iff(tostring(k) startswith 'x_', tostring(k), strcat('x_', toupper(substring(tostring(k), 0, 1)), substring(tostring(k), 1)))\n | summarize x_RecommendationDetails = make_bag(bag_pack(newKey, x_RecommendationDetails[tostring(k)]))\n )\n //\n // Build recommendation details\n | lookup kind=leftouter (Regions | summarize RegionName = make_set(RegionName)[0] by Location = RegionId) on Location\n | extend x_RecommendationDetails = case(\n // Use incoming x_RecommendationDetails first\n isnotempty(x_RecommendationDetails), x_RecommendationDetails,\n // Create one for reservation recommendations if needed\n x_SourceType == 'ReservationRecommendations', bag_pack(\n 'CommitmentDiscountNormalizedGroup', InstanceFlexibilityGroup,\n 'CommitmentDiscountNormalizedRatio', InstanceFlexibilityRatio,\n 'CommitmentDiscountNormalizedSize', NormalizedSize,\n 'CommitmentDiscountResourceType', ResourceType,\n 'CommitmentDiscountScope', Scope,\n 'LookbackPeriodDuration', case(\n LookBackPeriod matches regex @'^Last([0-9]+)Days$', replace_regex(LookBackPeriod, @'^Last([0-9]+)Days$', @'P\\1D'),\n LookBackPeriod matches regex @'^[0-9]+$', strcat('P', LookBackPeriod, 'D'),\n ''\n ),\n 'LookbackPeriodStart', FirstUsageDate,\n 'RecommendedQuantity', RecommendedQuantity,\n 'RecommendedQuantityNormalized', RecommendedQuantityNormalized,\n 'RegionId', Location,\n 'RegionName', RegionName,\n 'SkuMeterId', MeterId,\n 'SkuPriceDetails', SkuProperties,\n 'SkuSize', coalesce(SKU, SkuName),\n 'SkuTerm', isoMonths(Term)\n ),\n dynamic({})\n )\n //\n // Prefer specified date, then fall back to generating a date based on reservation recommendation lookback period, then validate to ensure it's not in the future\n | extend x_RecommendationDate = coalesce(x_RecommendationDate, FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d))\n | extend x_RecommendationDate = iff(x_RecommendationDate > now(), startofday(now()), x_RecommendationDate)\n //\n // Derive x_ResourceType from ResourceId\n | extend tmp_ResourceType = tostring(parse_resourceid(ResourceId).x_ResourceType)\n | extend x_RecommendationDetails = iff(isnotempty(tmp_ResourceType), bag_merge(bag_pack('x_ResourceType', tmp_ResourceType), x_RecommendationDetails), x_RecommendationDetails)\n //\n // Set ResourceType display name from x_ResourceType code\n | extend ResourceType = coalesce(ResourceType, tostring(resource_type(tmp_ResourceType).SingularDisplayName), tmp_ResourceType)\n //\n | project\n ProviderName,\n ResourceId = tolower(ResourceId), // Force lowercase for consistent grouping/filtering\n ResourceName = tolower(iff(tmp_ResourceType =~ 'microsoft.resources/subscriptions', coalesce(SubAccountName, ResourceName), ResourceName)), // Use subscription name for subscription-level recommendations\n ResourceType,\n SubAccountId = coalesce(SubAccountId, iff(isnotempty(SubscriptionId), strcat('/subscriptions/', SubscriptionId), '')),\n SubAccountName,\n x_EffectiveCostAfter = coalesce(x_EffectiveCostAfter, TotalCostWithReservedInstances),\n x_EffectiveCostBefore = coalesce(x_EffectiveCostBefore, CostWithNoReservedInstances),\n x_EffectiveCostSavings = coalesce(x_EffectiveCostSavings, NetSavings, toreal(x_RecommendationDetails.x_SavingsAmount), toreal(x_RecommendationDetails.x_AnnualSavingsAmount) / 12),\n x_IngestionTime,\n x_RecommendationCategory, // TODO: Set for reservation recommendations\n x_RecommendationDate,\n x_RecommendationDescription = coalesce(x_RecommendationDescription, tostring(x_RecommendationDetails.x_RecommendationSolution), tostring(x_RecommendationDetails.x_RecommendationSubCategory)),\n x_RecommendationDetails,\n x_RecommendationId = tolower(x_RecommendationId), // TODO: Set for reservation recommendations; force lowercase for consistent grouping/filtering\n x_ResourceGroupName = tolower(x_ResourceGroupName), // Force lowercase for consistent grouping/filtering\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n// Recommendations_final_v1_2 table\n.create-merge table Recommendations_final_v1_2 (\n ProviderName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n SubAccountId: string,\n SubAccountName: string,\n x_EffectiveCostAfter: real,\n x_EffectiveCostBefore: real,\n x_EffectiveCostSavings: real,\n x_IngestionTime: datetime,\n x_RecommendationCategory: string,\n x_RecommendationDate: datetime,\n x_RecommendationDescription: string,\n x_RecommendationDetails: dynamic,\n x_RecommendationId: string,\n x_ResourceGroupName: string,\n x_SourceName: string,\n x_SourceProvider: string,\n x_SourceType: string,\n x_SourceVersion: string\n)\n\n// Update policy for Recommendations_raw -> Recommendations_final_v1_2 table\n.alter table Recommendations_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Recommendations_raw\",\n \"Query\": \"Recommendations_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All transactions transformed to FOCUS 1.2.', folder='Transactions')\nTransactions_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Transactions_raw\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationTransactions', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Handle BillingPeriodStart/End\n | extend BillingMonth = tostring(BillingMonth)\n | extend BillingPeriodStart = iff(isempty(BillingMonth), datetime(null), todatetime(strcat(substring(BillingMonth, 0, 4), \"-\", substring(BillingMonth, 4, 2), \"-\", substring(BillingMonth, 6, 2))))\n | extend BillingPeriodEnd = iff(isempty(BillingMonth), datetime(null), startofmonth(endofmonth(BillingPeriodStart) + 1d))\n //\n // Sort columns and apply final transforms\n | project\n BilledCost = Amount,\n BillingAccountId = case(\n BillingProfileId startswith '/', BillingProfileId,\n isnotempty(CurrentEnrollmentId), strcat('/providers/Microsoft.Billing/billingAccounts/', CurrentEnrollmentId),\n isnotempty(BillingProfileId), strcat('/providers/Microsoft.Billing/billingProfiles/', BillingProfileId),\n ''\n ),\n BillingAccountName = coalesce(BillingProfileName, CurrentEnrollmentId),\n BillingCurrency = Currency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory = case(\n EventType in ('Cancel', 'Purchase', 'Refund'), 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = case(\n EventType == 'Cancel', 'Cancel', // FOCUS does not handle this scenario\n EventType == 'Refund', 'Correction',\n ''\n ),\n ChargeDescription = Description,\n ChargeFrequency = case(\n BillingFrequency == 'OneTime', 'One-Time',\n BillingFrequency == 'Recurring', 'Recurring',\n BillingFrequency\n ),\n ChargePeriodStart = EventDate,\n InvoiceId,\n PricingQuantity = Quantity,\n PricingUnit = 'Reservations',\n ProviderName,\n RegionId = Region,\n RegionName = Region,\n SubAccountId = iff(isempty(PurchasingSubscriptionGuid), '', strcat('/subscriptions/', PurchasingSubscriptionGuid)),\n SubAccountName = iff(isempty(PurchasingSubscriptionGuid), '', PurchasingSubscriptionName),\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerEmail,\n x_CostCenter = CostCenter,\n x_InvoiceNumber = Invoice,\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = coalesce(InvoiceSectionName, DepartmentName),\n x_IngestionTime = ingestion_time(),\n x_MonetaryCommitment = MonetaryCommitment,\n x_Overage = Overage,\n x_PurchasingBillingAccountId = PurchasingEnrollment,\n x_SkuOrderId = ReservationOrderId,\n x_SkuOrderName = ReservationOrderName,\n x_SkuSize = ArmSkuName,\n x_SkuTerm = isoMonths(Term),\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId = PurchasingSubscriptionGuid,\n x_TransactionType = EventType\n}\n\n// Transactions_final_v1_2 table\n.create-merge table Transactions_final_v1_2 (\n BilledCost: real, // MS CM EA+MCA 2023-05-01\n BillingAccountId: string, // MS CM EA+MCA 2023-05-01\n BillingAccountName: string, // MS CM EA+MCA 2023-05-01\n BillingCurrency: string, // MS CM EA+MCA 2023-05-01\n BillingPeriodEnd: datetime, // MS CM EA+MCA 2023-05-01\n BillingPeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n ChargeCategory: string, // Hubs add-on\n ChargeClass: string, // Hubs add-on\n ChargeDescription: string, // MS CM EA+MCA 2023-05-01\n ChargeFrequency: string, // MS CM EA+MCA 2023-05-01\n ChargePeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n InvoiceId: string, // MS CM MCA 2023-05-01\n PricingQuantity: real, // MS CM EA+MCA 2023-05-01\n PricingUnit: string, // Hubs add-on\n ProviderName: string, // Hubs add-on\n RegionId: string, // MS CM EA+MCA 2023-05-01\n RegionName: string, // MS CM EA+MCA 2023-05-01\n SubAccountId: string, // MS CM EA+MCA 2023-05-01\n SubAccountName: string, // MS CM EA+MCA 2023-05-01\n x_AccountName: string, // MS CM EA 2023-05-01\n x_AccountOwnerId: string, // MS CM EA 2023-05-01\n x_CostCenter: string, // MS CM EA 2023-05-01\n x_InvoiceNumber: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionId: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionName: string, // MS CM MCA 2023-05-01\n x_IngestionTime: datetime, // Hubs add-on\n x_MonetaryCommitment: real, // MS CM EA 2023-05-01\n x_Overage: real, // MS CM EA 2023-05-01\n x_PurchasingBillingAccountId: string, // MS CM EA 2023-05-01\n x_SkuOrderId: string, // MS CM EA+MCA 2023-05-01\n x_SkuOrderName: string, // MS CM EA+MCA 2023-05-01\n x_SkuSize: string, // MS CM EA+MCA 2023-05-01\n x_SkuTerm: int, // MS CM EA+MCA 2023-05-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubscriptionId: string, // MS CM EA+MCA 2023-05-01\n x_TransactionType: string // MS CM EA+MCA 2023-05-01\n)\n\n// Update policy for Transactions_raw -> Transactions_final_v1_2 table\n.alter table Transactions_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Transactions_raw\",\n \"Query\": \"Transactions_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n", "$fxv#11": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Common utility functions\n//\n// TIP: Use Ctrl+K,Ctrl+0 to collapse all regions in VS Code\n//======================================================================================================================\n\n\n//===| Date functions |=================================================================================================\n\n// monthstring\n.create-or-alter function \nwith (docstring = @'Returns the name of the month for the specified date (e.g. Jan or January)', folder =@'Common') \nmonthstring(['date']: datetime, length: int = 9)\n{\n substring(dynamic(['January','February','March','April','May','June','July','August','September','October','November','December'])[getmonth(['date']) - 1], 0, length)\n}\n\n// datestring\n.create-or-alter function \nwith (docstring = @'Converts 2 dates into a simple, user-friendly date range (e.g. Jan 1-Jan 3)', folder =@'Common') \ndatestring(start: datetime, end: datetime = datetime('0001-01-01'))\n{\n let month = (d: datetime) { monthstring(d, 3) };\n let endDate = iff(end == datetime('0001-01-01'), start, end);\n let sameDate = startofday(start) == startofday(endDate);\n let sameMonth = startofmonth(start) == startofmonth(endDate);\n let sameYear = startofyear(start) == startofyear(endDate);\n let fullMonth = startofday(start) == startofmonth(start) and startofday(endDate) == startofday(endofmonth(endDate));\n let fullYear = startofday(start) == startofyear(start) and startofday(endDate) == startofday(endofyear(endDate));\n let currentYear = sameYear and startofyear(start) == startofyear(now());\n case(\n // Full year | yyyy (same year) / yyyy-yyyy (diff years)\n fullYear,\n strcat(getyear(start), iff(sameYear, '', strcat('-', getyear(endDate)))),\n // 1 full mo, same year | Mmm yyyy\n fullMonth and sameMonth and sameYear,\n strcat(month(start), ' ', getyear(start)),\n // 2+ full mo, same year | Mmm-Mmm (current year) / Mmm-Mmm yyyy (other year)\n fullMonth and sameYear,\n strcat(month(start), '-', month(endDate), iff(currentYear, '', strcat(' ', getyear(endDate)))),\n // Full mo, diff year | Mmm yyyy-Mmm yyyy\n fullMonth and not(sameYear),\n strcat(month(start), ' ', getyear(start), '-', month(endDate), ' ', getyear(endDate)),\n // Same date | Mmm d (current year) / Mmm d, yyyy (other year)\n sameDate,\n strcat(month(start), ' ', dayofmonth(start), iff(currentYear, '', strcat(', ', getyear(endDate)))),\n // 1 partial M, same Y | Mmm d-d (current year) / Mmm d-d, yyyy (other year)\n not(fullMonth) and sameMonth and sameYear,\n strcat(month(start), ' ', dayofmonth(start), '-', dayofmonth(endDate), iff(currentYear, '', strcat(' ', getyear(endDate)))),\n // 2+ partial M, same Y | Mmm d-Mmm d (current year) / Mmm d-Mmm d, yyyy (other year)\n not(fullMonth) and not(sameMonth) and sameYear,\n strcat(month(start), ' ', dayofmonth(start), '-', month(endDate), ' ', dayofmonth(endDate), iff(currentYear, '', strcat(', ', getyear(endDate)))),\n // All other cases | Mmm d, yyyy-Mmm d, yyyy\n strcat(month(start), ' ', dayofmonth(start), ', ', getyear(start), '-', month(endDate), ' ', dayofmonth(endDate), ', ', getyear(endDate))\n )\n}\n\n// daterange\n.create-or-alter function \nwith (docstring = @'DEPRECATED: Please use datestring(); function will be removed on or after the Jan 2026 release', folder =@'Common') \ndaterange(start: datetime, end: datetime = datetime('0001-01-01'))\n{\n datestring(start, end)\n}\n\n// monthsago\n.create-or-alter function \nwith (docstring = 'DEPRECATED: Please use startofmonth(now(), -<# of months>); function will be removed on or after the Jan 2026 release', folder = 'Common')\nmonthsago(months: int)\n{\n datetime_add('month', -months, startofmonth(now()))\n}\n\n\n//===| Number functions |===============================================================================================\n// NOTE: Must be defined before string converters\n\n// delta\n.create-or-alter function \nwith (docstring = @'Compares 2 values and returns the percentage change from oldval to newval', folder =@'Common') \ndelta(oldval: double, newval: double)\n{\n (newval - todouble(oldval))/oldval\n}\n\n// percentOfTotal\n// NOTE: Must be before percent() function\n.create-or-alter function \nwith (docstring = @'Calculates the percentage of each record based on a required Count column', folder =@'Common') \npercentOfTotal(t: (Count: long), tot: long)\n{\n let total = todouble(tot);\n t \n | extend Percent = round(Count / total * 100, 3) \n | order by Count desc\n}\n\n// percent\n.create-or-alter function \nwith (docstring = @'Calculates the percentage of each record based on a required Count column', folder =@'Common') \npercent(t: (Count: long))\n{\n let total = todouble(toscalar(t | summarize sum(Count)));\n percentOfTotal(t, total)\n}\n\n// plusminus\n.create-or-alter function \nwith (docstring = 'Shows a +/- sign based on the direction of the number', folder = 'Common')\nplusminus(val: string)\n{\n let neg = substring(val, 0, 1) == '-';\n iff(neg, val, strcat('+', val))\n}\n\n// updown\n.create-or-alter function \nwith (docstring = 'Shows an up/down arrow based on the direction of the number', folder = 'Common')\nupdown(val: string)\n{\n // TODO: Handle 0\n let neg = substring(val, 0, 1) == '-';\n iff(neg, strcat('↓', substring(val, 1)), strcat('↑', val))\n}\n\n\n//===| String functions |===============================================================================================\n\n// percentstring\n// NOTE: Must be defined before deltastring\n.create-or-alter function \nwith (docstring = 'Calculate a percentage and render as a string', folder = 'Common')\npercentstring(num: double, total: double = 1.0, places: int = 9)\n{\n let value = 1.0 * num / total * 100;\n strcat(case(\n places != 9, round(value, places),\n value < 10, round(value, 2),\n round(value, 1)\n ), '%')\n}\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// arraystring\n.create-or-alter function \nwith (docstring = 'Convert an array to a comma-delimited string', folder = 'Common')\narraystring(arr: dynamic)\n{\n replace_string(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(\n tostring(arr)\n , @'^\\[\"', '')\n , @'\"\\]$', '')\n , @'^, ', '')\n , @', $', '')\n , @'^\\[]$', '')\n , '\",\"', ', ')\n}\n\n// deltastring\n.create-or-alter function \nwith (docstring = 'Calculate a delta percentage and render as a string', folder = 'Common')\ndeltastring(oldval: double, newval: double, places: int = 1, useArrows: bool = false)\n{\n let d = delta(oldval, newval);\n strcat(case(useArrows and d > 0, '↑', useArrows and d < 0, '↓', d < 0, '-', ''), percentstring(abs(d), 1, places))\n}\n\n// diffstring\n.create-or-alter function \nwith (docstring = 'Calculate the difference and render as a string', folder = 'Common')\ndiffstring(oldval: double, newval: double, places: int = 1)\n{\n plusminus(round(newval - oldval, places))\n}\n\n// numberstring\n.create-or-alter function \nwith (docstring = 'Convert a number to a string', folder = 'Common')\nnumberstring(num: double, abbrev: bool = true)\n{\n replace_regex(case(\n num >= 10000000000000, strcat(round(1.0 * num / 1000000000000, 1), 'T'),\n num >= 1000000000000, strcat(round(1.0 * num / 1000000000000, 2), 'T'),\n num >= 10000000000, strcat(round(1.0 * num / 1000000000, 1), 'B'),\n num >= 1000000000, strcat(round(1.0 * num / 1000000000, 2), 'B'),\n num >= 10000000, strcat(round(1.0 * num / 1000000, 1), 'M'),\n num >= 1000000, strcat(round(1.0 * num / 1000000, 2), 'M'),\n num >= 10000, strcat(round(1.0 * num / 1000, 1), 'K'),\n // Kusto doesn't support back-refs yet -- num > 1000, replace_regex(tostring(num), @'(\\d)(?=(\\d{3})+\\.)', @'\\1,'), // See https://docs.microsoft.com/azure/data-explorer/kusto/query/re2-library\n num > 1000, replace_regex(tostring(num), @'([0-9]{3})$', @',\\1'), //num / 1000, ',', substring(tostring(num), 0) - (num / 1000 * 1000)),\n tostring(num)\n ), @'\\.0$', '')\n}\n\n\n//===| Other |==========================================================================================================\n\n// ifempty\n.create-or-alter function \nwith (docstring = 'Replaces an empty value with the specified default value', folder = 'Common')\nifempty(val: dynamic, defaultVal: dynamic)\n{\n iff(isempty(val), defaultVal, val)\n}\n", "$fxv#12": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Hub database / Open data functions\n// Wrap Ingestion database tables for easy access.\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n\n// PricingUnits\n.create-or-alter function\nwith (docstring = 'Gets pricing units from the FinOps toolkit PricingUnits open data.', folder = 'OpenData')\nPricingUnits()\n{\n database('Ingestion').PricingUnits\n}\n\n// Regions\n.create-or-alter function\nwith (docstring = 'Gets regions from the FinOps toolkit Regions open data.', folder = 'OpenData')\nRegion()\n{\n database('Ingestion').Regions\n}\n\n// ResourceTypes\n.create-or-alter function\nwith (docstring = 'Gets resource types from the FinOps toolkit ResourceTypes open data.', folder = 'OpenData')\nResourceType()\n{\n database('Ingestion').ResourceTypes\n}\n\n// Services\n.create-or-alter function\nwith (docstring = 'Gets services from the FinOps toolkit Services open data.', folder = 'OpenData')\nServices()\n{\n database('Ingestion').Services\n}\n", "$fxv#13": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Hub database / FOCUS 1.0 functions\n// Used for reporting with backward compatibility.\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n\n// CommitmentDiscountUsage_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all commitment discount usage records aligned to FOCUS 1.0.', folder = 'CommitmentDiscountUsage')\nCommitmentDiscountUsage_v1_0()\n{\n database('Ingestion').CommitmentDiscountUsage_final_v1_0\n | union (\n database('Ingestion').CommitmentDiscountUsage_final_v1_2\n // Convert real to decimal\n | extend\n CommitmentDiscountQuantity = todecimal(CommitmentDiscountQuantity),\n ConsumedQuantity = todecimal(ConsumedQuantity),\n x_CommitmentDiscountCommittedCount = todecimal(x_CommitmentDiscountCommittedCount),\n x_CommitmentDiscountCommittedAmount = todecimal(x_CommitmentDiscountCommittedAmount),\n x_CommitmentDiscountNormalizedRatio = todecimal(x_CommitmentDiscountNormalizedRatio)\n )\n | project\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId,\n CommitmentDiscountType,\n ConsumedQuantity,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SubAccountId,\n x_CommitmentDiscountCommittedCount,\n x_CommitmentDiscountCommittedAmount,\n x_CommitmentDiscountNormalizedGroup,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountQuantity,\n x_IngestionTime,\n x_ResourceGroupName,\n x_ResourceType,\n x_ServiceModel,\n x_SkuOrderId,\n x_SkuSize,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n\n// Costs_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all cost and usage records aligned to FOCUS 1.0.', folder = 'Costs')\nCosts_v1_0()\n{\n database('Ingestion').Costs_final_v1_0\n | union (\n database('Ingestion').Costs_final_v1_2\n // Convert real to decimal\n | extend\n BilledCost = todecimal(BilledCost),\n CommitmentDiscountQuantity = todecimal(CommitmentDiscountQuantity),\n ConsumedQuantity = todecimal(ConsumedQuantity),\n ContractedCost = todecimal(ContractedCost),\n ContractedUnitPrice = todecimal(ContractedUnitPrice),\n EffectiveCost = todecimal(EffectiveCost),\n ListCost = todecimal(ListCost),\n ListUnitPrice = todecimal(ListUnitPrice),\n PricingQuantity = todecimal(PricingQuantity),\n x_BilledCostInUsd = todecimal(x_BilledCostInUsd),\n x_BilledUnitPrice = todecimal(x_BilledUnitPrice),\n x_BillingExchangeRate = todecimal(x_BillingExchangeRate),\n x_CommitmentDiscountNormalizedRatio = todecimal(x_CommitmentDiscountNormalizedRatio),\n x_ContractedCostInUsd = todecimal(x_ContractedCostInUsd),\n x_CurrencyConversionRate = todecimal(x_CurrencyConversionRate),\n x_EffectiveCostInUsd = todecimal(x_EffectiveCostInUsd),\n x_EffectiveUnitPrice = todecimal(x_EffectiveUnitPrice),\n x_ListCostInUsd = todecimal(x_ListCostInUsd),\n x_PricingBlockSize = todecimal(x_PricingBlockSize)\n // Rename columns\n | project-rename\n x_InvoiceId = InvoiceId,\n x_PricingCurrency = PricingCurrency,\n x_SkuMeterName = SkuMeter\n // Generate historical x_SkuDetails format from SkuPriceDetails\n | extend x_SkuDetails = iff(isnotempty(x_SkuDetails), x_SkuDetails, parse_json(replace_regex(tostring(SkuPriceDetails), @'([\\{,])\"x_', @'\\1\"')))\n )\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId,\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory,\n ChargeClass,\n ChargeDescription,\n ChargeFrequency,\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId,\n CommitmentDiscountName,\n CommitmentDiscountStatus,\n CommitmentDiscountType,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost,\n ContractedUnitPrice,\n EffectiveCost,\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory,\n PricingQuantity,\n PricingUnit,\n ProviderName,\n PublisherName,\n RegionId,\n RegionName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SkuId,\n SkuPriceId,\n SubAccountId,\n SubAccountName,\n SubAccountType,\n Tags,\n x_AccountId,\n x_AccountName,\n x_AccountOwnerId,\n x_BilledCostInUsd,\n x_BilledUnitPrice,\n x_BillingAccountAgreement,\n x_BillingAccountId,\n x_BillingAccountName,\n x_BillingExchangeRate,\n x_BillingExchangeRateDate,\n x_BillingProfileId,\n x_BillingProfileName,\n x_ChargeId,\n x_ContractedCostInUsd,\n x_CostAllocationRuleName,\n x_CostCategories,\n x_CostCenter,\n x_Credits,\n x_CostType,\n x_CurrencyConversionRate,\n x_CustomerId,\n x_CustomerName,\n x_Discount,\n x_EffectiveCostInUsd,\n x_EffectiveUnitPrice,\n x_ExportTime,\n x_IngestionTime,\n x_InvoiceId,\n x_InvoiceIssuerId,\n x_InvoiceSectionId,\n x_InvoiceSectionName,\n x_ListCostInUsd,\n x_Location,\n x_Operation,\n x_PartnerCreditApplied,\n x_PartnerCreditRate,\n x_PricingBlockSize,\n x_PricingCurrency,\n x_PricingSubcategory,\n x_PricingUnitDescription,\n x_Project,\n x_PublisherCategory,\n x_PublisherId,\n x_ResellerId,\n x_ResellerName,\n x_ResourceGroupName,\n x_ResourceType,\n x_ServiceCode,\n x_ServiceId,\n x_ServicePeriodEnd,\n x_ServicePeriodStart,\n x_SkuDescription,\n x_SkuDetails,\n x_SkuIsCreditEligible,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterName,\n x_SkuMeterSubcategory,\n x_SkuOfferId,\n x_SkuOrderId,\n x_SkuOrderName,\n x_SkuPartNumber,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuTerm,\n x_SkuTier,\n x_SourceChanges,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_UsageType\n}\n\n\n// Prices_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all prices aligned to FOCUS 1.0.', folder = 'Prices')\nPrices_v1_0()\n{\n database('Ingestion').Prices_final_v1_0\n | union (\n database('Ingestion').Prices_final_v1_2\n // Convert real to decimal\n | extend\n ContractedUnitPrice = todecimal(ContractedUnitPrice),\n ListUnitPrice = todecimal(ListUnitPrice),\n x_BaseUnitPrice = todecimal(x_BaseUnitPrice),\n x_CommitmentDiscountNormalizedRatio = todecimal(x_CommitmentDiscountNormalizedRatio),\n x_ContractedUnitPriceDiscount = todecimal(x_ContractedUnitPriceDiscount),\n x_ContractedUnitPriceDiscountPercent = todecimal(x_ContractedUnitPriceDiscountPercent),\n x_EffectiveUnitPrice = todecimal(x_EffectiveUnitPrice),\n x_EffectiveUnitPriceDiscount = todecimal(x_EffectiveUnitPriceDiscount),\n x_EffectiveUnitPriceDiscountPercent = todecimal(x_EffectiveUnitPriceDiscountPercent),\n x_PricingBlockSize = todecimal(x_PricingBlockSize),\n x_SkuIncludedQuantity = todecimal(x_SkuIncludedQuantity),\n x_SkuTier = todecimal(x_SkuTier),\n x_TotalUnitPriceDiscount = todecimal(x_TotalUnitPriceDiscount),\n x_TotalUnitPriceDiscountPercent = todecimal(x_TotalUnitPriceDiscountPercent) \n // Rename columns\n | project-rename\n x_PricingCurrency = PricingCurrency,\n x_SkuMeterName = SkuMeter\n )\n | project\n BillingAccountId,\n BillingAccountName,\n BillingCurrency,\n ChargeCategory,\n CommitmentDiscountCategory,\n CommitmentDiscountType,\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory,\n PricingUnit,\n SkuId,\n SkuPriceId,\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement,\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent,\n x_EffectivePeriodEnd,\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingCurrency,\n x_PricingSubcategory,\n x_PricingUnitDescription,\n x_SkuDescription,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterName,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent\n}\n\n\n// Recommendations_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all recommendations aligned to FOCUS 1.0.', folder = 'Recommendations')\nRecommendations_v1_0()\n{\n database('Ingestion').Recommendations_final_v1_0\n | union (\n database('Ingestion').Recommendations_final_v1_2\n // Convert real to decimal\n | extend\n x_EffectiveCostAfter = todecimal(x_EffectiveCostAfter),\n x_EffectiveCostBefore = todecimal(x_EffectiveCostBefore),\n x_EffectiveCostSavings = todecimal(x_EffectiveCostSavings)\n )\n | project\n ProviderName,\n SubAccountId,\n x_IngestionTime,\n x_EffectiveCostAfter,\n x_EffectiveCostBefore,\n x_EffectiveCostSavings,\n x_RecommendationDate,\n x_RecommendationDetails,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n\n// Transactions_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all transactions aligned to FOCUS 1.0.', folder = 'Transactions')\nTransactions_v1_0()\n{\n database('Ingestion').Transactions_final_v1_0\n | union (\n database('Ingestion').Transactions_final_v1_2\n // Convert real to decimal\n | extend\n BilledCost = todecimal(BilledCost),\n PricingQuantity = todecimal(PricingQuantity),\n x_MonetaryCommitment = todecimal(x_MonetaryCommitment),\n x_Overage = todecimal(x_Overage)\n // Rename columns\n | project-rename\n x_InvoiceId = InvoiceId\n )\n | project\n BilledCost,\n BillingAccountId,\n BillingAccountName,\n BillingCurrency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory,\n ChargeClass,\n ChargeDescription,\n ChargeFrequency,\n ChargePeriodStart,\n PricingQuantity,\n PricingUnit,\n ProviderName,\n RegionId,\n RegionName,\n SubAccountId,\n SubAccountName,\n x_AccountName,\n x_AccountOwnerId,\n x_CostCenter,\n x_InvoiceId,\n x_InvoiceNumber,\n x_InvoiceSectionId,\n x_InvoiceSectionName,\n x_IngestionTime,\n x_MonetaryCommitment,\n x_Overage,\n x_PurchasingBillingAccountId,\n x_SkuOrderId,\n x_SkuOrderName,\n x_SkuSize,\n x_SkuTerm,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId,\n x_TransactionType\n}\n", @@ -18333,7 +18333,7 @@ "$fxv#6": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Common utility functions\n//\n// TIP: Use Ctrl+K,Ctrl+0 to collapse all regions in VS Code\n//======================================================================================================================\n\n\n//===| Date functions |=================================================================================================\n\n// monthstring\n.create-or-alter function \nwith (docstring = @'Returns the name of the month for the specified date (e.g. Jan or January)', folder =@'Common') \nmonthstring(['date']: datetime, length: int = 9)\n{\n substring(dynamic(['January','February','March','April','May','June','July','August','September','October','November','December'])[getmonth(['date']) - 1], 0, length)\n}\n\n// datestring\n.create-or-alter function \nwith (docstring = @'Converts 2 dates into a simple, user-friendly date range (e.g. Jan 1-Jan 3)', folder =@'Common') \ndatestring(start: datetime, end: datetime = datetime('0001-01-01'))\n{\n let month = (d: datetime) { monthstring(d, 3) };\n let endDate = iff(end == datetime('0001-01-01'), start, end);\n let sameDate = startofday(start) == startofday(endDate);\n let sameMonth = startofmonth(start) == startofmonth(endDate);\n let sameYear = startofyear(start) == startofyear(endDate);\n let fullMonth = startofday(start) == startofmonth(start) and startofday(endDate) == startofday(endofmonth(endDate));\n let fullYear = startofday(start) == startofyear(start) and startofday(endDate) == startofday(endofyear(endDate));\n let currentYear = sameYear and startofyear(start) == startofyear(now());\n case(\n // Full year | yyyy (same year) / yyyy-yyyy (diff years)\n fullYear,\n strcat(getyear(start), iff(sameYear, '', strcat('-', getyear(endDate)))),\n // 1 full mo, same year | Mmm yyyy\n fullMonth and sameMonth and sameYear,\n strcat(month(start), ' ', getyear(start)),\n // 2+ full mo, same year | Mmm-Mmm (current year) / Mmm-Mmm yyyy (other year)\n fullMonth and sameYear,\n strcat(month(start), '-', month(endDate), iff(currentYear, '', strcat(' ', getyear(endDate)))),\n // Full mo, diff year | Mmm yyyy-Mmm yyyy\n fullMonth and not(sameYear),\n strcat(month(start), ' ', getyear(start), '-', month(endDate), ' ', getyear(endDate)),\n // Same date | Mmm d (current year) / Mmm d, yyyy (other year)\n sameDate,\n strcat(month(start), ' ', dayofmonth(start), iff(currentYear, '', strcat(', ', getyear(endDate)))),\n // 1 partial M, same Y | Mmm d-d (current year) / Mmm d-d, yyyy (other year)\n not(fullMonth) and sameMonth and sameYear,\n strcat(month(start), ' ', dayofmonth(start), '-', dayofmonth(endDate), iff(currentYear, '', strcat(' ', getyear(endDate)))),\n // 2+ partial M, same Y | Mmm d-Mmm d (current year) / Mmm d-Mmm d, yyyy (other year)\n not(fullMonth) and not(sameMonth) and sameYear,\n strcat(month(start), ' ', dayofmonth(start), '-', month(endDate), ' ', dayofmonth(endDate), iff(currentYear, '', strcat(', ', getyear(endDate)))),\n // All other cases | Mmm d, yyyy-Mmm d, yyyy\n strcat(month(start), ' ', dayofmonth(start), ', ', getyear(start), '-', month(endDate), ' ', dayofmonth(endDate), ', ', getyear(endDate))\n )\n}\n\n// daterange\n.create-or-alter function \nwith (docstring = @'DEPRECATED: Please use datestring(); function will be removed on or after the Jan 2026 release', folder =@'Common') \ndaterange(start: datetime, end: datetime = datetime('0001-01-01'))\n{\n datestring(start, end)\n}\n\n// monthsago\n.create-or-alter function \nwith (docstring = 'DEPRECATED: Please use startofmonth(now(), -<# of months>); function will be removed on or after the Jan 2026 release', folder = 'Common')\nmonthsago(months: int)\n{\n datetime_add('month', -months, startofmonth(now()))\n}\n\n\n//===| Number functions |===============================================================================================\n// NOTE: Must be defined before string converters\n\n// delta\n.create-or-alter function \nwith (docstring = @'Compares 2 values and returns the percentage change from oldval to newval', folder =@'Common') \ndelta(oldval: double, newval: double)\n{\n (newval - todouble(oldval))/oldval\n}\n\n// percentOfTotal\n// NOTE: Must be before percent() function\n.create-or-alter function \nwith (docstring = @'Calculates the percentage of each record based on a required Count column', folder =@'Common') \npercentOfTotal(t: (Count: long), tot: long)\n{\n let total = todouble(tot);\n t \n | extend Percent = round(Count / total * 100, 3) \n | order by Count desc\n}\n\n// percent\n.create-or-alter function \nwith (docstring = @'Calculates the percentage of each record based on a required Count column', folder =@'Common') \npercent(t: (Count: long))\n{\n let total = todouble(toscalar(t | summarize sum(Count)));\n percentOfTotal(t, total)\n}\n\n// plusminus\n.create-or-alter function \nwith (docstring = 'Shows a +/- sign based on the direction of the number', folder = 'Common')\nplusminus(val: string)\n{\n let neg = substring(val, 0, 1) == '-';\n iff(neg, val, strcat('+', val))\n}\n\n// updown\n.create-or-alter function \nwith (docstring = 'Shows an up/down arrow based on the direction of the number', folder = 'Common')\nupdown(val: string)\n{\n // TODO: Handle 0\n let neg = substring(val, 0, 1) == '-';\n iff(neg, strcat('↓', substring(val, 1)), strcat('↑', val))\n}\n\n\n//===| String functions |===============================================================================================\n\n// percentstring\n// NOTE: Must be defined before deltastring\n.create-or-alter function \nwith (docstring = 'Calculate a percentage and render as a string', folder = 'Common')\npercentstring(num: double, total: double = 1.0, places: int = 9)\n{\n let value = 1.0 * num / total * 100;\n strcat(case(\n places != 9, round(value, places),\n value < 10, round(value, 2),\n round(value, 1)\n ), '%')\n}\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// arraystring\n.create-or-alter function \nwith (docstring = 'Convert an array to a comma-delimited string', folder = 'Common')\narraystring(arr: dynamic)\n{\n replace_string(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(\n tostring(arr)\n , @'^\\[\"', '')\n , @'\"\\]$', '')\n , @'^, ', '')\n , @', $', '')\n , @'^\\[]$', '')\n , '\",\"', ', ')\n}\n\n// deltastring\n.create-or-alter function \nwith (docstring = 'Calculate a delta percentage and render as a string', folder = 'Common')\ndeltastring(oldval: double, newval: double, places: int = 1, useArrows: bool = false)\n{\n let d = delta(oldval, newval);\n strcat(case(useArrows and d > 0, '↑', useArrows and d < 0, '↓', d < 0, '-', ''), percentstring(abs(d), 1, places))\n}\n\n// diffstring\n.create-or-alter function \nwith (docstring = 'Calculate the difference and render as a string', folder = 'Common')\ndiffstring(oldval: double, newval: double, places: int = 1)\n{\n plusminus(round(newval - oldval, places))\n}\n\n// numberstring\n.create-or-alter function \nwith (docstring = 'Convert a number to a string', folder = 'Common')\nnumberstring(num: double, abbrev: bool = true)\n{\n replace_regex(case(\n num >= 10000000000000, strcat(round(1.0 * num / 1000000000000, 1), 'T'),\n num >= 1000000000000, strcat(round(1.0 * num / 1000000000000, 2), 'T'),\n num >= 10000000000, strcat(round(1.0 * num / 1000000000, 1), 'B'),\n num >= 1000000000, strcat(round(1.0 * num / 1000000000, 2), 'B'),\n num >= 10000000, strcat(round(1.0 * num / 1000000, 1), 'M'),\n num >= 1000000, strcat(round(1.0 * num / 1000000, 2), 'M'),\n num >= 10000, strcat(round(1.0 * num / 1000, 1), 'K'),\n // Kusto doesn't support back-refs yet -- num > 1000, replace_regex(tostring(num), @'(\\d)(?=(\\d{3})+\\.)', @'\\1,'), // See https://docs.microsoft.com/azure/data-explorer/kusto/query/re2-library\n num > 1000, replace_regex(tostring(num), @'([0-9]{3})$', @',\\1'), //num / 1000, ',', substring(tostring(num), 0) - (num / 1000 * 1000)),\n tostring(num)\n ), @'\\.0$', '')\n}\n\n\n//===| Other |==========================================================================================================\n\n// ifempty\n.create-or-alter function \nwith (docstring = 'Replaces an empty value with the specified default value', folder = 'Common')\nifempty(val: dynamic, defaultVal: dynamic)\n{\n iff(isempty(val), defaultVal, val)\n}\n", "$fxv#7": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// Used for data ingestion, normalization, and cleansing.\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Settings |=======================================================================================================\n\n.create-merge table HubSettingsLog (\n version: string,\n scopes: dynamic,\n retention: dynamic\n)\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// HubSettings function\n.create-or-alter function\nwith (docstring='Gets the latest version of hub settings.', folder='Settings')\nHubSettings()\n{\n HubSettingsLog\n | extend timestamp = ingestion_time()\n | summarize arg_max(timestamp, *)\n}\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// HubScopes function\n.create-or-alter function\nwith (docstring='Gets the currently configured scopes.', folder='Settings')\nHubScopes()\n{\n HubSettings\n | project scopes\n | mv-expand scopes\n}\n\n\n//===| Open data |======================================================================================================\n\n// PricingUnits -- Create table if it doesn't exist\n.create-merge table PricingUnits ( ignore: string )\n\n// PricingUnits -- Remove all columns\n.alter table PricingUnits ( ignore: string )\n\n// PricingUnits -- Redefine all columns to change types\n.alter table PricingUnits (\n x_PricingUnitDescription: string,\n x_PricingBlockSize: real,\n PricingUnit: string\n)\n\n// Regions\n.create-merge table Regions(\n ResourceLocation: string,\n RegionId: string,\n RegionName: string\n)\n\n// ResourceTypes\n.create-merge table ResourceTypes(\n x_ResourceType: string,\n SingularDisplayName: string,\n PluralDisplayName: string,\n LowerSingularDisplayName: string,\n LowerPluralDisplayName: string,\n IsPreview: bool,\n Description: string,\n IconUri: string\n)\n\n// Services\n.create-merge table Services(\n x_ConsumedService: string,\n x_ResourceType: string,\n ServiceName: string,\n ServiceCategory: string,\n ServiceSubcategory: string,\n PublisherName: string,\n x_PublisherCategory: string,\n x_Environment: string,\n x_ServiceModel: string\n)\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// parse_resourceid\n.create-or-alter function\nwith (docstring = 'Parses an Azure resource ID to extract resource attributes like the name, type, resource group, and subaccount ID.', folder = 'Common')\nparse_resourceid(resourceId: string) {\n let ResourceId = tolower(resourceId);\n // let ResourceId = tolower('/providers/Microsoft.BillingBenefits/savingsPlanOrders/2d2e284b-0638-427e-b8c6-1b874d4f17c8/sp/xxx');\n let SubAccountId = tostring(extract('/subscriptions/[^/]+', 1, ResourceId));\n let x_ResourceGroupName = tostring(extract('/resourcegroups/[^/]+', 1, ResourceId));\n let tmp_ResourceId = iff(ResourceId !contains '/providers/' and ResourceId startswith '/subscriptions/', strcat('/providers/microsoft.resources', ResourceId), ResourceId);\n let providerPath = iff(tmp_ResourceId !contains '/providers/', '', tostring(split(tmp_ResourceId, '/providers/')[-1]));\n let x_ResourceProvider = iff(isempty(providerPath), '', split(providerPath, '/')[0]);\n let tmp_ResourceProviderPath = iff(isempty(providerPath), '', substring(providerPath, strlen(x_ResourceProvider) + 1));\n let segments = split(tmp_ResourceProviderPath, '/');\n let ResourceName = trim(@'/+', replace_string(strcat_array(array_iff(\n dynamic([false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true]),\n segments, dynamic([])), '/'), '//', '/'));\n let x_ResourceTypePath = trim(@'/+', replace_string(strcat_array(array_iff(\n dynamic([true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false]),\n segments, dynamic([])), '/'), '//', '/'));\n let xRT = iff(isempty(x_ResourceProvider) or isempty(x_ResourceTypePath), '', strcat(x_ResourceProvider, '/', x_ResourceTypePath));\n // TODO: Remove ResourceType in 0.9\n bag_pack('ResourceId', ResourceId, 'ResourceName', ResourceName, 'ResourceType', xRT, 'SubAccountId', SubAccountId, 'x_ResourceGroupName', x_ResourceGroupName, 'x_ResourceProvider', x_ResourceProvider, 'x_ResourceType', xRT)\n}\n", "$fxv#8": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// Used for data ingestion, normalization, and cleansing.\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| ActualCosts |====================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_raw table -- Create the table if it doesn't exist\n.create-merge table ActualCosts_raw ( ignore: string )\n\n// ActualCosts_raw table -- Remove all columns to allow changing column types\n.alter table ActualCosts_raw ( ignore: string )\n\n// ActualCosts_raw table -- Redefine all columns\n.alter table ActualCosts_raw (\n AccountName: string,\n AccountOwnerId: string,\n AdditionalInfo: string,\n AvailabilityZone: string,\n BillingAccountId: string, \n BillingAccountName: string,\n BillingCurrency: string,\n BillingPeriodEndDate: datetime,\n BillingPeriodStartDate: datetime,\n BillingProfileId: string,\n BillingProfileName: string,\n ChargeType: string,\n ConsumedService: string,\n CostCenter: string,\n Cost: real,\n Date: datetime,\n EffectivePrice: real,\n Frequency: string,\n InvoiceSection: string,\n InvoiceSectionId: string,\n IsAzureCreditEligible: bool,\n MeterCategory: string,\n MeterId: string,\n MeterName: string,\n MeterRegion: string,\n MeterSubCategory: string,\n OfferId: string,\n PartNumber: string,\n PlanName: string,\n Product: string,\n ProductOrderId: string,\n ProductOrderName: string,\n PublisherName: string,\n PublisherType: string,\n Quantity: real,\n ReservationId: string,\n ReservationName: string,\n ResourceGroup: string,\n ResourceId: string,\n ResourceLocation: string,\n ResourceName: string,\n ServiceFamily: string,\n ServiceInfo1: string,\n ServiceInfo2: string,\n SubscriptionId: string,\n SubscriptionName: string,\n Tags: string,\n Term: string,\n UnitOfMeasure: string,\n UnitPrice: real\n)\n\n// ActualCosts_raw ingestion mapping\n.create-or-alter table ActualCosts_raw ingestion parquet mapping \"ActualCosts_raw_mapping\"\n```\n[\n { \"Column\": \"AccountName\", \"Properties\": { \"Field\": \"AccountName\" } },\n { \"Column\": \"AccountOwnerId\", \"Properties\": { \"Field\": \"AccountOwnerId\" } },\n { \"Column\": \"AdditionalInfo\", \"Properties\": { \"Field\": \"AdditionalInfo\" } },\n { \"Column\": \"AvailabilityZone\", \"Properties\": { \"Field\": \"AvailabilityZone\" } },\n { \"Column\": \"BillingAccountId\", \"Properties\": { \"Field\": \"BillingAccountId\" } },\n { \"Column\": \"BillingAccountName\", \"Properties\": { \"Field\": \"BillingAccountName\" } },\n { \"Column\": \"BillingCurrency\", \"Properties\": { \"Field\": \"BillingCurrency\" } },\n { \"Column\": \"BillingPeriodEndDate\", \"Properties\": { \"Field\": \"BillingPeriodEndDate\" } },\n { \"Column\": \"BillingPeriodStartDate\", \"Properties\": { \"Field\": \"BillingPeriodStartDate\" } },\n { \"Column\": \"BillingProfileId\", \"Properties\": { \"Field\": \"BillingProfileId\" } },\n { \"Column\": \"BillingProfileName\", \"Properties\": { \"Field\": \"BillingProfileName\" } },\n { \"Column\": \"ChargeType\", \"Properties\": { \"Field\": \"ChargeType\" } },\n { \"Column\": \"ConsumedService\", \"Properties\": { \"Field\": \"ConsumedService\" } },\n { \"Column\": \"CostCenter\", \"Properties\": { \"Field\": \"CostCenter\" } },\n { \"Column\": \"Cost\", \"Properties\": { \"Field\": \"Cost\" } },\n { \"Column\": \"Date\", \"Properties\": { \"Field\": \"Date\" } },\n { \"Column\": \"EffectivePrice\", \"Properties\": { \"Field\": \"EffectivePrice\" } },\n { \"Column\": \"Frequency\", \"Properties\": { \"Field\": \"Frequency\" } },\n { \"Column\": \"InvoiceSection\", \"Properties\": { \"Field\": \"InvoiceSection\" } },\n { \"Column\": \"InvoiceSectionId\", \"Properties\": { \"Field\": \"InvoiceSectionId\" } },\n { \"Column\": \"IsAzureCreditEligible\", \"Properties\": { \"Field\": \"IsAzureCreditEligible\" } },\n { \"Column\": \"MeterCategory\", \"Properties\": { \"Field\": \"MeterCategory\" } },\n { \"Column\": \"MeterId\", \"Properties\": { \"Field\": \"MeterId\" } },\n { \"Column\": \"MeterName\", \"Properties\": { \"Field\": \"MeterName\" } },\n { \"Column\": \"MeterRegion\", \"Properties\": { \"Field\": \"MeterRegion\" } },\n { \"Column\": \"MeterSubCategory\", \"Properties\": { \"Field\": \"MeterSubCategory\" } },\n { \"Column\": \"OfferId\", \"Properties\": { \"Field\": \"OfferId\" } },\n { \"Column\": \"PartNumber\", \"Properties\": { \"Field\": \"PartNumber\" } },\n { \"Column\": \"PlanName\", \"Properties\": { \"Field\": \"PlanName\" } },\n { \"Column\": \"Product\", \"Properties\": { \"Field\": \"Product\" } },\n { \"Column\": \"ProductOrderId\", \"Properties\": { \"Field\": \"ProductOrderId\" } },\n { \"Column\": \"ProductOrderName\", \"Properties\": { \"Field\": \"ProductOrderName\" } },\n { \"Column\": \"PublisherName\", \"Properties\": { \"Field\": \"PublisherName\" } },\n { \"Column\": \"PublisherType\", \"Properties\": { \"Field\": \"PublisherType\" } },\n { \"Column\": \"Quantity\", \"Properties\": { \"Field\": \"Quantity\" } },\n { \"Column\": \"ReservationId\", \"Properties\": { \"Field\": \"ReservationId\" } },\n { \"Column\": \"ReservationName\", \"Properties\": { \"Field\": \"ReservationName\" } },\n { \"Column\": \"ResourceGroup\", \"Properties\": { \"Field\": \"ResourceGroup\" } },\n { \"Column\": \"ResourceId\", \"Properties\": { \"Field\": \"ResourceId\" } },\n { \"Column\": \"ResourceLocation\", \"Properties\": { \"Field\": \"ResourceLocation\" } },\n { \"Column\": \"ResourceName\", \"Properties\": { \"Field\": \"ResourceName\" } },\n { \"Column\": \"ServiceFamily\", \"Properties\": { \"Field\": \"ServiceFamily\" } },\n { \"Column\": \"ServiceInfo1\", \"Properties\": { \"Field\": \"ServiceInfo1\" } },\n { \"Column\": \"ServiceInfo2\", \"Properties\": { \"Field\": \"ServiceInfo2\" } },\n { \"Column\": \"SubscriptionId\", \"Properties\": { \"Field\": \"SubscriptionId\" } },\n { \"Column\": \"SubscriptionName\", \"Properties\": { \"Field\": \"SubscriptionName\" } },\n { \"Column\": \"Tags\", \"Properties\": { \"Field\": \"Tags\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"UnitOfMeasure\", \"Properties\": { \"Field\": \"UnitOfMeasure\" } },\n { \"Column\": \"UnitPrice\", \"Properties\": { \"Field\": \"UnitPrice\" } }\n]\n```\n\n// ActualCosts_raw retention policy (clear historical data)\n.alter-merge table ActualCosts_raw policy retention softdelete = 0d recoverability = disabled\n\n// ActualCosts_raw retention policy (set the user-defined retention period)\n.alter-merge table ActualCosts_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable ActualCosts_raw streaming ingestion (required for Fabric)\n.alter table ActualCosts_raw policy streamingingestion disable\n\n\n//===| AmortizedCosts |=================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_raw table -- Create the table if it doesn't exist\n.create-merge table AmortizedCosts_raw ( ignore: string )\n\n// AmortizedCosts_raw table -- Remove all columns to allow changing column types\n.alter table AmortizedCosts_raw ( ignore: string )\n\n// AmortizedCosts_raw table -- Redefine all columns\n.alter table AmortizedCosts_raw (\n AccountName: string,\n AccountOwnerId: string,\n AdditionalInfo: string,\n AvailabilityZone: string,\n BillingAccountId: string, \n BillingAccountName: string,\n BillingCurrency: string,\n BillingPeriodEndDate: datetime,\n BillingPeriodStartDate: datetime,\n BillingProfileId: string,\n BillingProfileName: string,\n ChargeType: string,\n ConsumedService: string,\n CostCenter: string,\n Cost: real,\n Date: datetime,\n EffectivePrice: real,\n Frequency: string,\n InvoiceSection: string,\n InvoiceSectionId: string,\n IsAzureCreditEligible: bool,\n MeterCategory: string,\n MeterId: string,\n MeterName: string,\n MeterRegion: string,\n MeterSubCategory: string,\n OfferId: string,\n PartNumber: string,\n PlanName: string,\n Product: string,\n ProductOrderId: string,\n ProductOrderName: string,\n PublisherName: string,\n PublisherType: string,\n Quantity: real,\n ReservationId: string,\n ReservationName: string,\n ResourceGroup: string,\n ResourceId: string,\n ResourceLocation: string,\n ResourceName: string,\n ServiceFamily: string,\n ServiceInfo1: string,\n ServiceInfo2: string,\n SubscriptionId: string,\n SubscriptionName: string,\n Tags: string,\n Term: string,\n UnitOfMeasure: string,\n UnitPrice: real\n)\n\n// AmortizedCosts_raw ingestion mapping\n.create-or-alter table AmortizedCosts_raw ingestion parquet mapping \"AmortizedCosts_raw_mapping\"\n```\n[\n { \"Column\": \"AccountName\", \"Properties\": { \"Field\": \"AccountName\" } },\n { \"Column\": \"AccountOwnerId\", \"Properties\": { \"Field\": \"AccountOwnerId\" } },\n { \"Column\": \"AdditionalInfo\", \"Properties\": { \"Field\": \"AdditionalInfo\" } },\n { \"Column\": \"AvailabilityZone\", \"Properties\": { \"Field\": \"AvailabilityZone\" } },\n { \"Column\": \"BillingAccountId\", \"Properties\": { \"Field\": \"BillingAccountId\" } },\n { \"Column\": \"BillingAccountName\", \"Properties\": { \"Field\": \"BillingAccountName\" } },\n { \"Column\": \"BillingCurrency\", \"Properties\": { \"Field\": \"BillingCurrency\" } },\n { \"Column\": \"BillingPeriodEndDate\", \"Properties\": { \"Field\": \"BillingPeriodEndDate\" } },\n { \"Column\": \"BillingPeriodStartDate\", \"Properties\": { \"Field\": \"BillingPeriodStartDate\" } },\n { \"Column\": \"BillingProfileId\", \"Properties\": { \"Field\": \"BillingProfileId\" } },\n { \"Column\": \"BillingProfileName\", \"Properties\": { \"Field\": \"BillingProfileName\" } },\n { \"Column\": \"ChargeType\", \"Properties\": { \"Field\": \"ChargeType\" } },\n { \"Column\": \"ConsumedService\", \"Properties\": { \"Field\": \"ConsumedService\" } },\n { \"Column\": \"CostCenter\", \"Properties\": { \"Field\": \"CostCenter\" } },\n { \"Column\": \"Cost\", \"Properties\": { \"Field\": \"Cost\" } },\n { \"Column\": \"Date\", \"Properties\": { \"Field\": \"Date\" } },\n { \"Column\": \"EffectivePrice\", \"Properties\": { \"Field\": \"EffectivePrice\" } },\n { \"Column\": \"Frequency\", \"Properties\": { \"Field\": \"Frequency\" } },\n { \"Column\": \"InvoiceSection\", \"Properties\": { \"Field\": \"InvoiceSection\" } },\n { \"Column\": \"InvoiceSectionId\", \"Properties\": { \"Field\": \"InvoiceSectionId\" } },\n { \"Column\": \"IsAzureCreditEligible\", \"Properties\": { \"Field\": \"IsAzureCreditEligible\" } },\n { \"Column\": \"MeterCategory\", \"Properties\": { \"Field\": \"MeterCategory\" } },\n { \"Column\": \"MeterId\", \"Properties\": { \"Field\": \"MeterId\" } },\n { \"Column\": \"MeterName\", \"Properties\": { \"Field\": \"MeterName\" } },\n { \"Column\": \"MeterRegion\", \"Properties\": { \"Field\": \"MeterRegion\" } },\n { \"Column\": \"MeterSubCategory\", \"Properties\": { \"Field\": \"MeterSubCategory\" } },\n { \"Column\": \"OfferId\", \"Properties\": { \"Field\": \"OfferId\" } },\n { \"Column\": \"PartNumber\", \"Properties\": { \"Field\": \"PartNumber\" } },\n { \"Column\": \"PlanName\", \"Properties\": { \"Field\": \"PlanName\" } },\n { \"Column\": \"Product\", \"Properties\": { \"Field\": \"Product\" } },\n { \"Column\": \"ProductOrderId\", \"Properties\": { \"Field\": \"ProductOrderId\" } },\n { \"Column\": \"ProductOrderName\", \"Properties\": { \"Field\": \"ProductOrderName\" } },\n { \"Column\": \"PublisherName\", \"Properties\": { \"Field\": \"PublisherName\" } },\n { \"Column\": \"PublisherType\", \"Properties\": { \"Field\": \"PublisherType\" } },\n { \"Column\": \"Quantity\", \"Properties\": { \"Field\": \"Quantity\" } },\n { \"Column\": \"ReservationId\", \"Properties\": { \"Field\": \"ReservationId\" } },\n { \"Column\": \"ReservationName\", \"Properties\": { \"Field\": \"ReservationName\" } },\n { \"Column\": \"ResourceGroup\", \"Properties\": { \"Field\": \"ResourceGroup\" } },\n { \"Column\": \"ResourceId\", \"Properties\": { \"Field\": \"ResourceId\" } },\n { \"Column\": \"ResourceLocation\", \"Properties\": { \"Field\": \"ResourceLocation\" } },\n { \"Column\": \"ResourceName\", \"Properties\": { \"Field\": \"ResourceName\" } },\n { \"Column\": \"ServiceFamily\", \"Properties\": { \"Field\": \"ServiceFamily\" } },\n { \"Column\": \"ServiceInfo1\", \"Properties\": { \"Field\": \"ServiceInfo1\" } },\n { \"Column\": \"ServiceInfo2\", \"Properties\": { \"Field\": \"ServiceInfo2\" } },\n { \"Column\": \"SubscriptionId\", \"Properties\": { \"Field\": \"SubscriptionId\" } },\n { \"Column\": \"SubscriptionName\", \"Properties\": { \"Field\": \"SubscriptionName\" } },\n { \"Column\": \"Tags\", \"Properties\": { \"Field\": \"Tags\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"UnitOfMeasure\", \"Properties\": { \"Field\": \"UnitOfMeasure\" } },\n { \"Column\": \"UnitPrice\", \"Properties\": { \"Field\": \"UnitPrice\" } }\n]\n```\n\n// AmortizedCosts_raw retention policy (clear historical data)\n.alter-merge table AmortizedCosts_raw policy retention softdelete = 0d recoverability = disabled\n\n// AmortizedCosts_raw retention policy (set the user-defined retention period)\n.alter-merge table AmortizedCosts_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable AmortizedCosts_raw streaming ingestion (required for Fabric)\n.alter table AmortizedCosts_raw policy streamingingestion disable\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_raw table -- Create the table if it doesn't exist\n.create-merge table CommitmentDiscountUsage_raw ( ignore: string )\n\n// CommitmentDiscountUsage_raw table -- Remove all columns to allow changing column types\n.alter table CommitmentDiscountUsage_raw ( ignore: string )\n\n// CommitmentDiscountUsage_raw table -- Redefine all columns\n.alter table CommitmentDiscountUsage_raw (\n InstanceFlexibilityGroup: string,\n InstanceFlexibilityRatio: real,\n InstanceId: string,\n Kind: string,\n ReservationId: string,\n ReservationOrderId: string,\n ReservedHours: real,\n SkuName: string,\n TotalReservedQuantity: real,\n UsageDate: datetime,\n UsedHours: real,\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string // Hubs v1_0+\n)\n\n// CommitmentDiscountUsage_raw ingestion mapping\n.create-or-alter table CommitmentDiscountUsage_raw ingestion parquet mapping \"CommitmentDiscountUsage_raw_mapping\"\n```\n[\n { \"Column\": \"InstanceFlexibilityGroup\", \"Properties\": { \"Field\": \"InstanceFlexibilityGroup\" } },\n { \"Column\": \"InstanceFlexibilityRatio\", \"Properties\": { \"Field\": \"InstanceFlexibilityRatio\" } },\n { \"Column\": \"InstanceId\", \"Properties\": { \"Field\": \"InstanceId\" } },\n { \"Column\": \"Kind\", \"Properties\": { \"Field\": \"Kind\" } },\n { \"Column\": \"ReservationId\", \"Properties\": { \"Field\": \"ReservationId\" } },\n { \"Column\": \"ReservationOrderId\", \"Properties\": { \"Field\": \"ReservationOrderId\" } },\n { \"Column\": \"ReservedHours\", \"Properties\": { \"Field\": \"ReservedHours\" } },\n { \"Column\": \"SkuName\", \"Properties\": { \"Field\": \"SkuName\" } },\n { \"Column\": \"TotalReservedQuantity\", \"Properties\": { \"Field\": \"TotalReservedQuantity\" } },\n { \"Column\": \"UsageDate\", \"Properties\": { \"Field\": \"UsageDate\" } },\n { \"Column\": \"UsedHours\", \"Properties\": { \"Field\": \"UsedHours\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } }\n]\n```\n\n// CommitmentDiscountUsage_raw retention policy (clear historical data)\n.alter-merge table CommitmentDiscountUsage_raw policy retention softdelete = 0d recoverability = disabled\n\n// CommitmentDiscountUsage_raw retention policy (set the user-defined retention period)\n.alter-merge table CommitmentDiscountUsage_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable CommitmentDiscountUsage_raw streaming ingestion (required for Fabric)\n.alter table CommitmentDiscountUsage_raw policy streamingingestion disable\n\n\n//===| Costs |==========================================================================================================\n// Supported versions:\n// - MS: 1.0, 1.0-preview(v1) -- See https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0 -- See https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024 -- See https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 -- See https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n// - Tencent: 1.0 -- See https://www.tencentcloud.com/document/product/555/67495 / https://www.tencentcloud.com/document/product/555/67496\n// - Alibaba: 1.0 -- See https://www.alibabacloud.com/help/en/user-center/user-guide/export-alibaba-cloud-standard-billing-focus\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_raw table -- Create the table if it doesn't exist\n.create-merge table Costs_raw ( ignore: string )\n\n// Costs_raw table -- Remove all columns to allow changing column types\n.alter table Costs_raw ( ignore: string )\n\n// Costs_raw table -- Redefine all columns\n.alter table Costs_raw (\n AvailabilityZone: string, // FOCUS 0.5+\n BilledCost: real, // FOCUS 0.5+\n BillingAccountId: string, // FOCUS 0.5+\n BillingAccountName: string, // FOCUS 0.5+\n BillingAccountType: string, // Azure 1.0-preview(v1)+\n BillingCurrency: string, // FOCUS 0.5+\n BillingPeriodEnd: datetime, // FOCUS 0.5+\n BillingPeriodStart: datetime, // FOCUS 0.5+\n CapacityReservationId: string, // FOCUS 1.1+\n CapacityReservationStatus: string, // FOCUS 1.1+\n ChargeCategory: string, // FOCUS 1.0-preview+\n ChargeClass: string, // FOCUS 1.0+\n ChargeDescription: string, // FOCUS 1.0+\n ChargeFrequency: string, // FOCUS 1.0+\n ChargePeriodEnd: datetime, // FOCUS 0.5+\n ChargePeriodStart: datetime, // FOCUS 0.5+\n ChargeSubcategory: string, // FOCUS 1.0-preview only\n CommitmentDiscountCategory: string, // FOCUS 1.0-preview+\n CommitmentDiscountId: string, // FOCUS 1.0-preview+\n CommitmentDiscountName: string, // FOCUS 1.0-preview+\n CommitmentDiscountQuantity: real, // FOCUS 1.1+\n CommitmentDiscountStatus: string, // FOCUS 1.0+\n CommitmentDiscountType: string, // FOCUS 1.0-preview+\n CommitmentDiscountUnit: string, // FOCUS 1.1+\n ConsumedQuantity: real, // FOCUS 1.0+\n ConsumedUnit: string, // FOCUS 1.0+\n ContractedCost: real, // FOCUS 1.0+\n ContractedUnitPrice: real, // FOCUS 1.0+\n EffectiveCost: real, // FOCUS 1.0-preview+\n InvoiceId: string, // FOCUS 1.2+\n InvoiceIssuerName: string, // FOCUS 0.5+\n ListCost: real, // FOCUS 1.0-preview+\n ListUnitPrice: real, // FOCUS 1.0-preview+\n PricingCategory: string, // FOCUS 1.0-preview+\n PricingCurrency: string, // FOCUS 1.2+\n PricingQuantity: real, // FOCUS 1.0-preview+\n PricingUnit: string, // FOCUS 1.0-preview+\n ProviderName: string, // FOCUS 0.5+\n PublisherName: string, // FOCUS 0.5+\n Region: string, // FOCUS 0.5-1.0-preview (deprecated)\n RegionId: string, // FOCUS 1.0+\n RegionName: string, // FOCUS 1.0+\n ResourceId: string, // FOCUS 0.5+\n ResourceName: string, // FOCUS 0.5+\n ResourceType: string, // FOCUS 1.0-preview+\n ServiceCategory: string, // FOCUS 0.5+\n ServiceName: string, // FOCUS 0.5+\n ServiceSubcategory: string, // FOCUS 1.1+\n SkuId: string, // FOCUS 1.0-preview+\n SkuMeter: string, // FOCUS 1.1+\n SkuPriceDetails: string, // FOCUS 1.1+\n SkuPriceId: string, // FOCUS 1.0-preview+\n SubAccountId: string, // FOCUS 0.5+\n SubAccountName: string, // FOCUS 0.5+\n SubAccountType: string, // Azure 1.0-preview(v1)+\n Tags: string, // FOCUS 1.0-preview+\n UsageAmount: real, // GCP Jan 2024 -- Removed Mar 2024 (UsageQuantity)\n UsageQuantity: real, // FOCUS 1.0-preview only\n UsageUnit: string, // FOCUS 1.0-preview only\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_AmortizationClass: string, // Azure 1.2-preview+\n x_BilledCostInUsd: real, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: real, // Azure 1.0-preview(v1)+\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: real, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingItemCode: string, // Alibaba 1.0+\n x_BillingItemName: string, // Alibaba 1.0+\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_CommodityCode: string, // Alibaba 1.0+\n x_CommodityName: string, // Alibaba 1.0+\n x_ComponentName: string, // Tencent 1.0+\n x_ComponentType: string, // Tencent 1.0+\n x_ContractedCostInUsd: real, // Azure 1.0+\n x_Cost: real, // GCP Jan 2024 -- Removed Jun 2024 (ContractedCost)\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: string, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_CostType: string, // GCP Jan 2024\n x_Credits: string, // GCP Jan 2024\n x_CurrencyConversionRate: real, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: string, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: real, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: real, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024 / Tencent 1.0+\n x_InstanceID: string, // Alibaba 1.0+\n x_InvoiceId: string, // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: real, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_OnDemandCost: real, // Azure 1.0-preview(v1) only\n x_OnDemandCostInUsd: real, // Azure 1.0-preview(v1) only\n x_OnDemandUnitPrice: real, // Azure 1.0-preview(v1) only\n x_Operation: string, // AWS 1.0\n x_OwnerAccountID: string, // Tencent 1.0+\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: real, // Azure 1.0-preview(v1)+\n x_PricingCurrency: string, // Azure 1.0-preview(v1)-1.0r2\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServiceModel: string, // Azure 1.2-preview+\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: string, // Azure 1.0-preview(v1)-1.2-preview\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterName: string, // Azure 1.0-preview(v1)-1.0r2\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuPlanName: string, // Azure 1.2-preview+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string, // Hubs v1_0+\n x_SubproductName: string, // Tencent 1.0+ // cSpell:ignore Subproduct\n x_UsageType: string // AWS 1.0\n)\n\n// Costs_raw ingestion mapping\n.create-or-alter table Costs_raw ingestion parquet mapping \"Costs_raw_mapping\"\n```\n[\n { \"Column\": \"AvailabilityZone\", \"Properties\": { \"Field\": \"AvailabilityZone\" } },\n { \"Column\": \"BilledCost\", \"Properties\": { \"Field\": \"BilledCost\" } },\n { \"Column\": \"BillingAccountId\", \"Properties\": { \"Field\": \"BillingAccountId\" } },\n { \"Column\": \"BillingAccountName\", \"Properties\": { \"Field\": \"BillingAccountName\" } },\n { \"Column\": \"BillingAccountType\", \"Properties\": { \"Field\": \"BillingAccountType\" } },\n { \"Column\": \"BillingCurrency\", \"Properties\": { \"Field\": \"BillingCurrency\" } },\n { \"Column\": \"BillingPeriodEnd\", \"Properties\": { \"Field\": \"BillingPeriodEnd\" } },\n { \"Column\": \"BillingPeriodStart\", \"Properties\": { \"Field\": \"BillingPeriodStart\" } },\n { \"Column\": \"CapacityReservationId\", \"Properties\": { \"Field\": \"CapacityReservationId\" } },\n { \"Column\": \"CapacityReservationStatus\", \"Properties\": { \"Field\": \"CapacityReservationStatus\" } },\n { \"Column\": \"ChargeCategory\", \"Properties\": { \"Field\": \"ChargeCategory\" } },\n { \"Column\": \"ChargeClass\", \"Properties\": { \"Field\": \"ChargeClass\" } },\n { \"Column\": \"ChargeDescription\", \"Properties\": { \"Field\": \"ChargeDescription\" } },\n { \"Column\": \"ChargeFrequency\", \"Properties\": { \"Field\": \"ChargeFrequency\" } },\n { \"Column\": \"ChargePeriodEnd\", \"Properties\": { \"Field\": \"ChargePeriodEnd\" } },\n { \"Column\": \"ChargePeriodStart\", \"Properties\": { \"Field\": \"ChargePeriodStart\" } },\n { \"Column\": \"ChargeSubcategory\", \"Properties\": { \"Field\": \"ChargeSubcategory\" } },\n { \"Column\": \"CommitmentDiscountCategory\", \"Properties\": { \"Field\": \"CommitmentDiscountCategory\" } },\n { \"Column\": \"CommitmentDiscountId\", \"Properties\": { \"Field\": \"CommitmentDiscountId\" } },\n { \"Column\": \"CommitmentDiscountName\", \"Properties\": { \"Field\": \"CommitmentDiscountName\" } },\n { \"Column\": \"CommitmentDiscountQuantity\", \"Properties\": { \"Field\": \"CommitmentDiscountQuantity\" } },\n { \"Column\": \"CommitmentDiscountStatus\", \"Properties\": { \"Field\": \"CommitmentDiscountStatus\" } },\n { \"Column\": \"CommitmentDiscountType\", \"Properties\": { \"Field\": \"CommitmentDiscountType\" } },\n { \"Column\": \"CommitmentDiscountUnit\", \"Properties\": { \"Field\": \"CommitmentDiscountUnit\" } },\n { \"Column\": \"ConsumedQuantity\", \"Properties\": { \"Field\": \"ConsumedQuantity\" } },\n { \"Column\": \"ConsumedUnit\", \"Properties\": { \"Field\": \"ConsumedUnit\" } },\n { \"Column\": \"ContractedCost\", \"Properties\": { \"Field\": \"ContractedCost\" } },\n { \"Column\": \"ContractedUnitPrice\", \"Properties\": { \"Field\": \"ContractedUnitPrice\" } },\n { \"Column\": \"EffectiveCost\", \"Properties\": { \"Field\": \"EffectiveCost\" } },\n { \"Column\": \"InvoiceId\", \"Properties\": { \"Field\": \"InvoiceId\" } },\n { \"Column\": \"InvoiceIssuerName\", \"Properties\": { \"Field\": \"InvoiceIssuerName\" } },\n { \"Column\": \"ListCost\", \"Properties\": { \"Field\": \"ListCost\" } },\n { \"Column\": \"ListUnitPrice\", \"Properties\": { \"Field\": \"ListUnitPrice\" } },\n { \"Column\": \"PricingCategory\", \"Properties\": { \"Field\": \"PricingCategory\" } },\n { \"Column\": \"PricingCurrency\", \"Properties\": { \"Field\": \"PricingCurrency\" } },\n { \"Column\": \"PricingQuantity\", \"Properties\": { \"Field\": \"PricingQuantity\" } },\n { \"Column\": \"PricingUnit\", \"Properties\": { \"Field\": \"PricingUnit\" } },\n { \"Column\": \"ProviderName\", \"Properties\": { \"Field\": \"ProviderName\" } },\n { \"Column\": \"PublisherName\", \"Properties\": { \"Field\": \"PublisherName\" } },\n { \"Column\": \"Region\", \"Properties\": { \"Field\": \"Region\" } },\n { \"Column\": \"RegionId\", \"Properties\": { \"Field\": \"RegionId\" } },\n { \"Column\": \"RegionName\", \"Properties\": { \"Field\": \"RegionName\" } },\n { \"Column\": \"ResourceId\", \"Properties\": { \"Field\": \"ResourceId\" } },\n { \"Column\": \"ResourceName\", \"Properties\": { \"Field\": \"ResourceName\" } },\n { \"Column\": \"ResourceType\", \"Properties\": { \"Field\": \"ResourceType\" } },\n { \"Column\": \"ServiceCategory\", \"Properties\": { \"Field\": \"ServiceCategory\" } },\n { \"Column\": \"ServiceName\", \"Properties\": { \"Field\": \"ServiceName\" } },\n { \"Column\": \"ServiceSubcategory\", \"Properties\": { \"Field\": \"ServiceSubcategory\" } },\n { \"Column\": \"SkuId\", \"Properties\": { \"Field\": \"SkuId\" } },\n { \"Column\": \"SkuMeter\", \"Properties\": { \"Field\": \"SkuMeter\" } },\n { \"Column\": \"SkuPriceDetails\", \"Properties\": { \"Field\": \"SkuPriceDetails\" } },\n { \"Column\": \"SkuPriceId\", \"Properties\": { \"Field\": \"SkuPriceId\" } },\n { \"Column\": \"SubAccountId\", \"Properties\": { \"Field\": \"SubAccountId\" } },\n { \"Column\": \"SubAccountName\", \"Properties\": { \"Field\": \"SubAccountName\" } },\n { \"Column\": \"SubAccountType\", \"Properties\": { \"Field\": \"SubAccountType\" } },\n { \"Column\": \"Tags\", \"Properties\": { \"Field\": \"Tags\" } },\n { \"Column\": \"UsageAmount\", \"Properties\": { \"Field\": \"UsageAmount\" } },\n { \"Column\": \"UsageQuantity\", \"Properties\": { \"Field\": \"UsageQuantity\" } },\n { \"Column\": \"UsageUnit\", \"Properties\": { \"Field\": \"UsageUnit\" } },\n { \"Column\": \"x_AccountId\", \"Properties\": { \"Field\": \"x_AccountId\" } },\n { \"Column\": \"x_AccountName\", \"Properties\": { \"Field\": \"x_AccountName\" } },\n { \"Column\": \"x_AccountOwnerId\", \"Properties\": { \"Field\": \"x_AccountOwnerId\" } },\n { \"Column\": \"x_AmortizationClass\", \"Properties\": { \"Field\": \"x_AmortizationClass\" } },\n { \"Column\": \"x_BilledCostInUsd\", \"Properties\": { \"Field\": \"x_BilledCostInUsd\" } },\n { \"Column\": \"x_BilledUnitPrice\", \"Properties\": { \"Field\": \"x_BilledUnitPrice\" } },\n { \"Column\": \"x_BillingAccountId\", \"Properties\": { \"Field\": \"x_BillingAccountId\" } },\n { \"Column\": \"x_BillingAccountName\", \"Properties\": { \"Field\": \"x_BillingAccountName\" } },\n { \"Column\": \"x_BillingExchangeRate\", \"Properties\": { \"Field\": \"x_BillingExchangeRate\" } },\n { \"Column\": \"x_BillingExchangeRateDate\", \"Properties\": { \"Field\": \"x_BillingExchangeRateDate\" } },\n { \"Column\": \"x_BillingItemCode\", \"Properties\": { \"Field\": \"x_BillingItemCode\" } },\n { \"Column\": \"x_BillingItemName\", \"Properties\": { \"Field\": \"x_BillingItemName\" } },\n { \"Column\": \"x_BillingProfileId\", \"Properties\": { \"Field\": \"x_BillingProfileId\" } },\n { \"Column\": \"x_BillingProfileName\", \"Properties\": { \"Field\": \"x_BillingProfileName\" } },\n { \"Column\": \"x_ChargeId\", \"Properties\": { \"Field\": \"x_ChargeId\" } },\n { \"Column\": \"x_ContractedCostInUsd\", \"Properties\": { \"Field\": \"x_ContractedCostInUsd\" } },\n { \"Column\": \"x_CommodityCode\", \"Properties\": { \"Field\": \"x_CommodityCode\" } },\n { \"Column\": \"x_CommodityName\", \"Properties\": { \"Field\": \"x_CommodityName\" } },\n { \"Column\": \"x_ComponentName\", \"Properties\": { \"Field\": \"x_ComponentName\" } },\n { \"Column\": \"x_ComponentType\", \"Properties\": { \"Field\": \"x_ComponentType\" } },\n { \"Column\": \"x_Cost\", \"Properties\": { \"Field\": \"x_Cost\" } },\n { \"Column\": \"x_CostAllocationRuleName\", \"Properties\": { \"Field\": \"x_CostAllocationRuleName\" } },\n { \"Column\": \"x_CostCategories\", \"Properties\": { \"Field\": \"x_CostCategories\" } },\n { \"Column\": \"x_CostCenter\", \"Properties\": { \"Field\": \"x_CostCenter\" } },\n { \"Column\": \"x_Credits\", \"Properties\": { \"Field\": \"x_Credits\" } },\n { \"Column\": \"x_CostType\", \"Properties\": { \"Field\": \"x_CostType\" } },\n { \"Column\": \"x_CurrencyConversionRate\", \"Properties\": { \"Field\": \"x_CurrencyConversionRate\" } },\n { \"Column\": \"x_CustomerId\", \"Properties\": { \"Field\": \"x_CustomerId\" } },\n { \"Column\": \"x_CustomerName\", \"Properties\": { \"Field\": \"x_CustomerName\" } },\n { \"Column\": \"x_Discount\", \"Properties\": { \"Field\": \"x_Discount\" } },\n { \"Column\": \"x_EffectiveCostInUsd\", \"Properties\": { \"Field\": \"x_EffectiveCostInUsd\" } },\n { \"Column\": \"x_EffectiveUnitPrice\", \"Properties\": { \"Field\": \"x_EffectiveUnitPrice\" } },\n { \"Column\": \"x_ExportTime\", \"Properties\": { \"Field\": \"x_ExportTime\" } },\n { \"Column\": \"x_InstanceID\", \"Properties\": { \"Field\": \"x_InstanceID\" } },\n { \"Column\": \"x_InvoiceId\", \"Properties\": { \"Field\": \"x_InvoiceId\" } },\n { \"Column\": \"x_InvoiceIssuerId\", \"Properties\": { \"Field\": \"x_InvoiceIssuerId\" } },\n { \"Column\": \"x_InvoiceSectionId\", \"Properties\": { \"Field\": \"x_InvoiceSectionId\" } },\n { \"Column\": \"x_InvoiceSectionName\", \"Properties\": { \"Field\": \"x_InvoiceSectionName\" } },\n { \"Column\": \"x_ListCostInUsd\", \"Properties\": { \"Field\": \"x_ListCostInUsd\" } },\n { \"Column\": \"x_Location\", \"Properties\": { \"Field\": \"x_Location\" } },\n { \"Column\": \"x_OnDemandCost\", \"Properties\": { \"Field\": \"x_OnDemandCost\" } },\n { \"Column\": \"x_OnDemandCostInUsd\", \"Properties\": { \"Field\": \"x_OnDemandCostInUsd\" } },\n { \"Column\": \"x_OnDemandUnitPrice\", \"Properties\": { \"Field\": \"x_OnDemandUnitPrice\" } },\n { \"Column\": \"x_Operation\", \"Properties\": { \"Field\": \"x_Operation\" } },\n { \"Column\": \"x_OwnerAccountID\", \"Properties\": { \"Field\": \"x_OwnerAccountID\" } },\n { \"Column\": \"x_PartnerCreditApplied\", \"Properties\": { \"Field\": \"x_PartnerCreditApplied\" } },\n { \"Column\": \"x_PartnerCreditRate\", \"Properties\": { \"Field\": \"x_PartnerCreditRate\" } },\n { \"Column\": \"x_PricingBlockSize\", \"Properties\": { \"Field\": \"x_PricingBlockSize\" } },\n { \"Column\": \"x_PricingCurrency\", \"Properties\": { \"Field\": \"x_PricingCurrency\" } },\n { \"Column\": \"x_PricingSubcategory\", \"Properties\": { \"Field\": \"x_PricingSubcategory\" } },\n { \"Column\": \"x_PricingUnitDescription\", \"Properties\": { \"Field\": \"x_PricingUnitDescription\" } },\n { \"Column\": \"x_Project\", \"Properties\": { \"Field\": \"x_Project\" } },\n { \"Column\": \"x_PublisherCategory\", \"Properties\": { \"Field\": \"x_PublisherCategory\" } },\n { \"Column\": \"x_PublisherId\", \"Properties\": { \"Field\": \"x_PublisherId\" } },\n { \"Column\": \"x_ResellerId\", \"Properties\": { \"Field\": \"x_ResellerId\" } },\n { \"Column\": \"x_ResellerName\", \"Properties\": { \"Field\": \"x_ResellerName\" } },\n { \"Column\": \"x_ResourceGroupName\", \"Properties\": { \"Field\": \"x_ResourceGroupName\" } },\n { \"Column\": \"x_ResourceType\", \"Properties\": { \"Field\": \"x_ResourceType\" } },\n { \"Column\": \"x_ServiceCode\", \"Properties\": { \"Field\": \"x_ServiceCode\" } },\n { \"Column\": \"x_ServiceId\", \"Properties\": { \"Field\": \"x_ServiceId\" } },\n { \"Column\": \"x_ServiceModel\", \"Properties\": { \"Field\": \"x_ServiceModel\" } },\n { \"Column\": \"x_ServicePeriodEnd\", \"Properties\": { \"Field\": \"x_ServicePeriodEnd\" } },\n { \"Column\": \"x_ServicePeriodStart\", \"Properties\": { \"Field\": \"x_ServicePeriodStart\" } },\n { \"Column\": \"x_SkuDescription\", \"Properties\": { \"Field\": \"x_SkuDescription\" } },\n { \"Column\": \"x_SkuDetails\", \"Properties\": { \"Field\": \"x_SkuDetails\" } },\n { \"Column\": \"x_SkuIsCreditEligible\", \"Properties\": { \"Field\": \"x_SkuIsCreditEligible\" } },\n { \"Column\": \"x_SkuMeterCategory\", \"Properties\": { \"Field\": \"x_SkuMeterCategory\" } },\n { \"Column\": \"x_SkuMeterId\", \"Properties\": { \"Field\": \"x_SkuMeterId\" } },\n { \"Column\": \"x_SkuMeterName\", \"Properties\": { \"Field\": \"x_SkuMeterName\" } },\n { \"Column\": \"x_SkuMeterSubcategory\", \"Properties\": { \"Field\": \"x_SkuMeterSubcategory\" } },\n { \"Column\": \"x_SkuOfferId\", \"Properties\": { \"Field\": \"x_SkuOfferId\" } },\n { \"Column\": \"x_SkuOrderId\", \"Properties\": { \"Field\": \"x_SkuOrderId\" } },\n { \"Column\": \"x_SkuOrderName\", \"Properties\": { \"Field\": \"x_SkuOrderName\" } },\n { \"Column\": \"x_SkuPartNumber\", \"Properties\": { \"Field\": \"x_SkuPartNumber\" } },\n { \"Column\": \"x_SkuPlanName\", \"Properties\": { \"Field\": \"x_SkuPlanName\" } },\n { \"Column\": \"x_SkuRegion\", \"Properties\": { \"Field\": \"x_SkuRegion\" } },\n { \"Column\": \"x_SkuServiceFamily\", \"Properties\": { \"Field\": \"x_SkuServiceFamily\" } },\n { \"Column\": \"x_SkuTerm\", \"Properties\": { \"Field\": \"x_SkuTerm\" } },\n { \"Column\": \"x_SkuTier\", \"Properties\": { \"Field\": \"x_SkuTier\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } },\n { \"Column\": \"x_SubproductName\", \"Properties\": { \"Field\": \"x_SubproductName\" } },\n { \"Column\": \"x_UsageType\", \"Properties\": { \"Field\": \"x_UsageType\" } }\n]\n```\n\n// Costs_raw retention policy (clear historical data)\n.alter-merge table Costs_raw policy retention softdelete = 0d recoverability = disabled\n\n// Costs_raw retention policy (set the user-defined retention period)\n.alter-merge table Costs_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable Costs_raw streaming ingestion (required for Fabric)\n.alter table Costs_raw policy streamingingestion disable\n\n\n//===| Prices |=========================================================================================================\n// NOTE: Must be before cost details.\n//\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_raw table -- Create the table if it doesn't exist\n.create-merge table Prices_raw ( ignore: string )\n\n// Prices_raw table -- Remove all columns to allow changing column types\n.alter table Prices_raw ( ignore: string )\n\n// Prices_raw table -- Redefine all columns\n.alter table Prices_raw (\n BasePrice: real, // Azure EA + MCA\n BillingAccountId: string, // Azure MCA\n BillingAccountName: string, // Azure MCA\n BillingCurrency: string, // Azure MCA\n BillingProfileId: string, // Azure MCA\n BillingProfileName: string, // Azure MCA\n Currency: string, // Azure MCA\n CurrencyCode: string, // Azure EA\n EffectiveEndDate: datetime, // Azure MCA\n EffectiveStartDate: datetime, // Azure EA + MCA\n EnrollmentNumber: string, // Azure EA\n IncludedQuantity: real, // Azure EA\n MarketPrice: real, // Azure EA + MCA\n MeterCategory: string, // Azure EA + MCA\n MeterId: string, // Azure MCA\n MeterID: string, // Azure EA\n MeterName: string, // Azure EA + MCA\n MeterRegion: string, // Azure EA + MCA\n MeterSubCategory: string, // Azure EA + MCA\n MeterType: string, // Azure EA + MCA\n OfferID: string, // Azure EA\n PartNumber: string, // Azure EA\n PriceType: string, // Azure EA + MCA\n Product: string, // Azure EA + MCA\n ProductId: string, // Azure MCA\n ProductID: string, // Azure EA\n ServiceFamily: string, // Azure EA + MCA\n SkuId: string, // Azure MCA\n SkuID: string, // Azure EA\n Term: string, // Azure EA + MCA\n TierMinimumUnits: real, // Azure MCA\n UnitOfMeasure: string, // Azure EA + MCA\n UnitPrice: real, // Azure EA + MCA\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string // Hubs v1_0+\n)\n\n// Prices_raw ingestion mapping\n.create-or-alter table Prices_raw ingestion parquet mapping \"Prices_raw_mapping\"\n```\n[\n { \"Column\": \"BasePrice\", \"Properties\": { \"Field\": \"BasePrice\" } },\n { \"Column\": \"BillingAccountId\", \"Properties\": { \"Field\": \"BillingAccountId\" } },\n { \"Column\": \"BillingAccountName\", \"Properties\": { \"Field\": \"BillingAccountName\" } },\n { \"Column\": \"BillingCurrency\", \"Properties\": { \"Field\": \"BillingCurrency\" } },\n { \"Column\": \"BillingProfileId\", \"Properties\": { \"Field\": \"BillingProfileId\" } },\n { \"Column\": \"BillingProfileName\", \"Properties\": { \"Field\": \"BillingProfileName\" } },\n { \"Column\": \"Currency\", \"Properties\": { \"Field\": \"Currency\" } },\n { \"Column\": \"CurrencyCode\", \"Properties\": { \"Field\": \"CurrencyCode\" } },\n { \"Column\": \"EffectiveEndDate\", \"Properties\": { \"Field\": \"EffectiveEndDate\" } },\n { \"Column\": \"EffectiveStartDate\", \"Properties\": { \"Field\": \"EffectiveStartDate\" } },\n { \"Column\": \"EnrollmentNumber\", \"Properties\": { \"Field\": \"EnrollmentNumber\" } },\n { \"Column\": \"IncludedQuantity\", \"Properties\": { \"Field\": \"IncludedQuantity\" } },\n { \"Column\": \"MarketPrice\", \"Properties\": { \"Field\": \"MarketPrice\" } },\n { \"Column\": \"MeterCategory\", \"Properties\": { \"Field\": \"MeterCategory\" } },\n { \"Column\": \"MeterId\", \"Properties\": { \"Field\": \"MeterId\" } },\n { \"Column\": \"MeterID\", \"Properties\": { \"Field\": \"MeterID\" } },\n { \"Column\": \"MeterName\", \"Properties\": { \"Field\": \"MeterName\" } },\n { \"Column\": \"MeterRegion\", \"Properties\": { \"Field\": \"MeterRegion\" } },\n { \"Column\": \"MeterSubCategory\", \"Properties\": { \"Field\": \"MeterSubCategory\" } },\n { \"Column\": \"MeterType\", \"Properties\": { \"Field\": \"MeterType\" } },\n { \"Column\": \"OfferID\", \"Properties\": { \"Field\": \"OfferID\" } },\n { \"Column\": \"PartNumber\", \"Properties\": { \"Field\": \"PartNumber\" } },\n { \"Column\": \"PriceType\", \"Properties\": { \"Field\": \"PriceType\" } },\n { \"Column\": \"Product\", \"Properties\": { \"Field\": \"Product\" } },\n { \"Column\": \"ProductId\", \"Properties\": { \"Field\": \"ProductId\" } },\n { \"Column\": \"ProductID\", \"Properties\": { \"Field\": \"ProductID\" } },\n { \"Column\": \"ServiceFamily\", \"Properties\": { \"Field\": \"ServiceFamily\" } },\n { \"Column\": \"SkuId\", \"Properties\": { \"Field\": \"SkuId\" } },\n { \"Column\": \"SkuID\", \"Properties\": { \"Field\": \"SkuID\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"TierMinimumUnits\", \"Properties\": { \"Field\": \"TierMinimumUnits\" } },\n { \"Column\": \"UnitOfMeasure\", \"Properties\": { \"Field\": \"UnitOfMeasure\" } },\n { \"Column\": \"UnitPrice\", \"Properties\": { \"Field\": \"UnitPrice\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } }\n]\n```\n\n// Prices_raw retention policy (clear historical data)\n.alter-merge table Prices_raw policy retention softdelete = 0d recoverability = disabled\n\n// Prices_raw retention policy (set the user-defined retention period)\n.alter-merge table Prices_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable Prices_raw streaming ingestion (required for Fabric)\n.alter table Prices_raw policy streamingingestion disable\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_raw table -- Create the table if it doesn't exist\n.create-merge table Recommendations_raw ( ignore: string )\n\n// Recommendations_raw table -- Remove all columns to allow changing column types\n.alter table Recommendations_raw ( ignore: string )\n\n// Recommendations_raw table -- Redefine all columns\n.alter table Recommendations_raw (\n CostWithNoReservedInstances: real, // MS CM EA resv reco 2024-05-01\n CostWithNoReservedInstancesJson: string, // MS CM MCA resv reco 2024-05-01 -- Renamed to remove spaces and flag as JSON\n FirstUsageDate: datetime, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n InstanceFlexibilityGroup: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n InstanceFlexibilityRatio: real, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n Location: string, // MS CM EA+MCA resv reco 2024-05-01\n LookBackPeriod: string, // MS CM EA+MCA resv reco 2024-05-01\n MeterId: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n NetSavings: real, // MS CM EA resv reco 2024-05-01\n NetSavingsJson: string, // MS CM MCA resv reco 2024-05-01 -- Renamed to remove spaces and flag as JSON\n NormalizedSize: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n ProviderName: string, // Hubs v1_2\n RecommendedQuantity: real, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n RecommendedQuantityNormalized: real, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n ResourceId: string, // Hubs v1_2\n ResourceName: string, // Hubs v1_2\n ResourceType: string, // Hubs v1_2, MS CM EA+MCA resv reco 2024-05-01\n Scope: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n SKU: string, // MS CM EA resv reco 2024-05-01\n SkuName: string, // MS CM MCA resv reco 2024-05-01 -- Renamed to remove spaces\n SkuProperties: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n SubAccountId: string, // Hubs v1_2\n SubAccountName: string, // Hubs v1_2\n SubscriptionId: string, // MS CM EA+MCA resv reco 2024-05-01\n Term: string, // MS CM EA+MCA resv reco 2024-05-01\n TotalCostWithReservedInstances: real, // MS CM EA resv reco 2024-05-01\n TotalCostWithReservedInstancesJson: string, // MS CM MCA resv reco 2024-05-01 -- Renamed to remove spaces and flag as JSON\n x_EffectiveCostAfter: real, // Hubs v1_2\n x_EffectiveCostBefore: real, // Hubs v1_2\n x_EffectiveCostSavings: real, // Hubs v1_2\n x_RecommendationCategory: string, // Hubs v1_2\n x_RecommendationDate: datetime, // Hubs v1_2\n x_RecommendationDescription: string, // Hubs v1_2\n x_RecommendationDetails: dynamic, // Hubs v1_2\n x_RecommendationId: string, // Hubs v1_2\n x_ResourceGroupName: string, // Hubs v1_2\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string // Hubs v1_0+\n)\n\n// Recommendations_raw ingestion mapping\n.create-or-alter table Recommendations_raw ingestion parquet mapping \"Recommendations_raw_mapping\"\n```\n[\n { \"Column\": \"CostWithNoReservedInstances\", \"Properties\": { \"Field\": \"CostWithNoReservedInstances\" } },\n { \"Column\": \"CostWithNoReservedInstancesJson\", \"Properties\": { \"Field\": \"CostWithNoReservedInstancesJson\" } },\n { \"Column\": \"FirstUsageDate\", \"Properties\": { \"Field\": \"FirstUsageDate\" } },\n { \"Column\": \"InstanceFlexibilityGroup\", \"Properties\": { \"Field\": \"InstanceFlexibilityGroup\" } },\n { \"Column\": \"InstanceFlexibilityRatio\", \"Properties\": { \"Field\": \"InstanceFlexibilityRatio\" } },\n { \"Column\": \"Location\", \"Properties\": { \"Field\": \"Location\" } },\n { \"Column\": \"LookBackPeriod\", \"Properties\": { \"Field\": \"LookBackPeriod\" } },\n { \"Column\": \"MeterId\", \"Properties\": { \"Field\": \"MeterId\" } },\n { \"Column\": \"NetSavings\", \"Properties\": { \"Field\": \"NetSavings\" } },\n { \"Column\": \"NetSavingsJson\", \"Properties\": { \"Field\": \"NetSavingsJson\" } },\n { \"Column\": \"NormalizedSize\", \"Properties\": { \"Field\": \"NormalizedSize\" } },\n { \"Column\": \"ProviderName\", \"Properties\": { \"Field\": \"ProviderName\" } },\n { \"Column\": \"RecommendedQuantity\", \"Properties\": { \"Field\": \"RecommendedQuantity\" } },\n { \"Column\": \"RecommendedQuantityNormalized\", \"Properties\": { \"Field\": \"RecommendedQuantityNormalized\" } },\n { \"Column\": \"ResourceId\", \"Properties\": { \"Field\": \"ResourceId\" } },\n { \"Column\": \"ResourceName\", \"Properties\": { \"Field\": \"ResourceName\" } },\n { \"Column\": \"ResourceType\", \"Properties\": { \"Field\": \"ResourceType\" } },\n { \"Column\": \"Scope\", \"Properties\": { \"Field\": \"Scope\" } },\n { \"Column\": \"SKU\", \"Properties\": { \"Field\": \"SKU\" } },\n { \"Column\": \"SkuName\", \"Properties\": { \"Field\": \"SkuName\" } },\n { \"Column\": \"SkuProperties\", \"Properties\": { \"Field\": \"SkuProperties\" } },\n { \"Column\": \"SubAccountId\", \"Properties\": { \"Field\": \"SubAccountId\" } },\n { \"Column\": \"SubAccountName\", \"Properties\": { \"Field\": \"SubAccountName\" } },\n { \"Column\": \"SubscriptionId\", \"Properties\": { \"Field\": \"SubscriptionId\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"TotalCostWithReservedInstances\", \"Properties\": { \"Field\": \"TotalCostWithReservedInstances\" } },\n { \"Column\": \"TotalCostWithReservedInstancesJson\", \"Properties\": { \"Field\": \"TotalCostWithReservedInstancesJson\" } },\n { \"Column\": \"x_EffectiveCostAfter\", \"Properties\": { \"Field\": \"x_EffectiveCostAfter\" } },\n { \"Column\": \"x_EffectiveCostBefore\", \"Properties\": { \"Field\": \"x_EffectiveCostBefore\" } },\n { \"Column\": \"x_EffectiveCostSavings\", \"Properties\": { \"Field\": \"x_EffectiveCostSavings\" } },\n { \"Column\": \"x_RecommendationCategory\", \"Properties\": { \"Field\": \"x_RecommendationCategory\" } },\n { \"Column\": \"x_RecommendationDate\", \"Properties\": { \"Field\": \"x_RecommendationDate\" } },\n { \"Column\": \"x_RecommendationDescription\", \"Properties\": { \"Field\": \"x_RecommendationDescription\" } },\n { \"Column\": \"x_RecommendationDetails\", \"Properties\": { \"Field\": \"x_RecommendationDetails\" } },\n { \"Column\": \"x_RecommendationId\", \"Properties\": { \"Field\": \"x_RecommendationId\" } },\n { \"Column\": \"x_ResourceGroupName\", \"Properties\": { \"Field\": \"x_ResourceGroupName\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } }\n]\n```\n\n// Recommendations_raw retention policy (clear historical data)\n.alter-merge table Recommendations_raw policy retention softdelete = 0d recoverability = disabled\n\n// Recommendations_raw retention policy (set the user-defined retention period)\n.alter-merge table Recommendations_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable Recommendations_raw streaming ingestion (required for Fabric)\n.alter table Recommendations_raw policy streamingingestion disable\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_raw table -- Create the table if it doesn't exist\n.create-merge table Transactions_raw ( ignore: string )\n\n// Transactions_raw table -- Remove all columns to allow changing column types\n.alter table Transactions_raw ( ignore: string )\n\n// Transactions_raw table -- Redefine all columns\n.alter table Transactions_raw (\n AccountName: string, // MS CM EA resv trans 2023-05-01\n AccountOwnerEmail: string, // MS CM EA resv trans 2023-05-01\n Amount: real, // MS CM EA+MCA resv trans 2023-05-01\n ArmSkuName: string, // MS CM EA+MCA resv trans 2023-05-01\n BillingFrequency: string, // MS CM EA+MCA resv trans 2023-05-01\n BillingMonth: string, // MS CM EA resv trans 2023-05-01\n BillingProfileId: string, // MS CM MCA resv trans 2023-05-01\n BillingProfileName: string, // MS CM MCA resv trans 2023-05-01\n CostCenter: string, // MS CM EA resv trans 2023-05-01\n Currency: string, // MS CM EA+MCA resv trans 2023-05-01\n CurrentEnrollmentId: string, // MS CM EA resv trans 2023-05-01\n DepartmentName: string, // MS CM EA resv trans 2023-05-01\n Description: string, // MS CM EA+MCA resv trans 2023-05-01\n EventDate: datetime, // MS CM EA+MCA resv trans 2023-05-01\n EventType: string, // MS CM EA+MCA resv trans 2023-05-01\n Invoice: string, // MS CM EA+MCA resv trans 2023-05-01\n InvoiceId: string, // MS CM EA+MCA resv trans 2023-05-01\n InvoiceSectionId: string, // MS CM MCA resv trans 2023-05-01\n InvoiceSectionName: string, // MS CM MCA resv trans 2023-05-01\n MonetaryCommitment: real, // MS CM EA resv trans 2023-05-01\n Overage: real, // MS CM EA resv trans 2023-05-01\n PurchasingEnrollment: string, // MS CM EA resv trans 2023-05-01\n PurchasingSubscriptionGuid: string, // MS CM EA+MCA resv trans 2023-05-01\n PurchasingSubscriptionName: string, // MS CM EA+MCA resv trans 2023-05-01\n Quantity: real, // MS CM EA+MCA resv trans 2023-05-01\n Region: string, // MS CM EA+MCA resv trans 2023-05-01\n ReservationOrderId: string, // MS CM EA+MCA resv trans 2023-05-01\n ReservationOrderName: string, // MS CM EA+MCA resv trans 2023-05-01\n Term: string, // MS CM EA+MCA resv trans 2023-05-01\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string // Hubs v1_0+\n)\n\n// Transactions_raw ingestion mapping\n.create-or-alter table Transactions_raw ingestion parquet mapping \"Transactions_raw_mapping\"\n```\n[\n { \"Column\": \"AccountName\", \"Properties\": { \"Field\": \"AccountName\" } },\n { \"Column\": \"AccountOwnerEmail\", \"Properties\": { \"Field\": \"AccountOwnerEmail\" } },\n { \"Column\": \"Amount\", \"Properties\": { \"Field\": \"Amount\" } },\n { \"Column\": \"ArmSkuName\", \"Properties\": { \"Field\": \"ArmSkuName\" } },\n { \"Column\": \"BillingFrequency\", \"Properties\": { \"Field\": \"BillingFrequency\" } },\n { \"Column\": \"BillingMonth\", \"Properties\": { \"Field\": \"BillingMonth\" } },\n { \"Column\": \"BillingProfileId\", \"Properties\": { \"Field\": \"BillingProfileId\" } },\n { \"Column\": \"BillingProfileName\", \"Properties\": { \"Field\": \"BillingProfileName\" } },\n { \"Column\": \"CostCenter\", \"Properties\": { \"Field\": \"CostCenter\" } },\n { \"Column\": \"Currency\", \"Properties\": { \"Field\": \"Currency\" } },\n { \"Column\": \"CurrentEnrollmentId\", \"Properties\": { \"Field\": \"CurrentEnrollmentId\" } },\n { \"Column\": \"DepartmentName\", \"Properties\": { \"Field\": \"DepartmentName\" } },\n { \"Column\": \"Description\", \"Properties\": { \"Field\": \"Description\" } },\n { \"Column\": \"EventDate\", \"Properties\": { \"Field\": \"EventDate\" } },\n { \"Column\": \"EventType\", \"Properties\": { \"Field\": \"EventType\" } },\n { \"Column\": \"Invoice\", \"Properties\": { \"Field\": \"Invoice\" } },\n { \"Column\": \"InvoiceId\", \"Properties\": { \"Field\": \"InvoiceId\" } },\n { \"Column\": \"InvoiceSectionId\", \"Properties\": { \"Field\": \"InvoiceSectionId\" } },\n { \"Column\": \"InvoiceSectionName\", \"Properties\": { \"Field\": \"InvoiceSectionName\" } },\n { \"Column\": \"MonetaryCommitment\", \"Properties\": { \"Field\": \"MonetaryCommitment\" } },\n { \"Column\": \"Overage\", \"Properties\": { \"Field\": \"Overage\" } },\n { \"Column\": \"PurchasingEnrollment\", \"Properties\": { \"Field\": \"PurchasingEnrollment\" } },\n { \"Column\": \"PurchasingSubscriptionGuid\", \"Properties\": { \"Field\": \"PurchasingSubscriptionGuid\" } },\n { \"Column\": \"PurchasingSubscriptionName\", \"Properties\": { \"Field\": \"PurchasingSubscriptionName\" } },\n { \"Column\": \"Quantity\", \"Properties\": { \"Field\": \"Quantity\" } },\n { \"Column\": \"Region\", \"Properties\": { \"Field\": \"Region\" } },\n { \"Column\": \"ReservationOrderId\", \"Properties\": { \"Field\": \"ReservationOrderId\" } },\n { \"Column\": \"ReservationOrderName\", \"Properties\": { \"Field\": \"ReservationOrderName\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } }\n]\n```\n\n// Transactions_raw retention policy (clear historical data)\n.alter-merge table Transactions_raw policy retention softdelete = 0d recoverability = disabled\n\n// Transactions_raw retention policy (set the user-defined retention period)\n.alter-merge table Transactions_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable Transactions_raw streaming ingestion (required for Fabric)\n.alter table Transactions_raw policy streamingingestion disable\n\n", - "$fxv#9": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// Used for data ingestion, normalization, and cleansing.\n// See known issues @ https://github.com/microsoft/finops-toolkit/issues/1111\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Prices |=========================================================================================================\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All prices transformed to FOCUS 1.0. Use Prices_transform_v1_2() instead.', folder='Prices')\nPrices_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n let prices = materialize(\n Prices_raw\n //\n // Change real to decimal\n | extend\n BasePrice = todecimal(BasePrice),\n IncludedQuantity = todecimal(IncludedQuantity),\n MarketPrice = todecimal(MarketPrice),\n TierMinimumUnits = todecimal(TierMinimumUnits),\n UnitPrice = todecimal(UnitPrice)\n //\n | extend x_SkuId = coalesce(SkuId, SkuID)\n | extend x_SkuMeterId = coalesce(MeterId, MeterID)\n | extend x_SkuProductId = coalesce(ProductId, ProductID)\n | extend x_SkuTerm = isoMonths(Term)\n | project-rename\n x_BaseUnitPrice = BasePrice,\n x_EffectivePeriodEnd = EffectiveEndDate,\n x_EffectivePeriodStart = EffectiveStartDate,\n x_PricingUnitDescription = UnitOfMeasure,\n x_SkuIncludedQuantity = IncludedQuantity,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuMeterType = MeterType,\n x_SkuOfferId = OfferID,\n x_SkuPartNumber = PartNumber,\n x_SkuPriceType = PriceType,\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTier = TierMinimumUnits\n | extend ContractedUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', UnitPrice, todecimal('')) // UnitPrice for savings plan is not the on-demand unit price\n | extend ListUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', MarketPrice, todecimal('')) // MarketPrice for savings plan is not the list price\n | extend ChargeCategory = case(\n x_SkuPriceType == 'Consumption', 'Usage',\n x_SkuPriceType == 'ReservedInstance', 'Purchase',\n x_SkuPriceType == 'SavingsPlan', 'Usage', // Savings plan prices are for committed usage, not the purchase\n ''\n )\n | extend SkuPriceIdv2 = strcat(case(x_SkuPriceType == 'Consumption', 'OD', x_SkuPriceType == 'ReservedInstance', 'RI', x_SkuPriceType == 'SavingsPlan', 'SP', 'XX'), substring(ChargeCategory, 0, 1), x_SkuTerm, '_', x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType, '_', x_SkuTier, x_SkuOfferId)\n | extend x_BillingAccountId = iff(BillingAccountId startswith '/', split(BillingAccountId, '/')[-1], coalesce(BillingAccountId, EnrollmentNumber))\n | extend x_BillingProfileId = iff(BillingProfileId startswith '/', split(BillingProfileId, '/')[-1], coalesce(BillingProfileId, EnrollmentNumber))\n | extend tmp_SavingsPlanKey = strcat(x_SkuMeterId, x_SkuProductId, x_SkuId, x_SkuTier, x_SkuOfferId)\n //\n // Get latest ingested row based on the unique ID\n | extend x_IngestionTime = ingestion_time()\n );\n //\n // Meters for reservations and savings plans to identify commitment eligibility\n let riMeters = prices | where x_SkuPriceType == 'ReservedInstance' | distinct x_SkuMeterId;\n let spMeters = prices | where x_SkuPriceType == 'SavingsPlan' | distinct x_SkuMeterId;\n //\n // Copy list/base/contracted prices from on-demand SKUs\n prices\n | where x_SkuPriceType == 'SavingsPlan'\n // If we use join, specify the shuffle key\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter hint.strategy=shuffle (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | lookup kind=leftouter (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | extend ListUnitPrice = coalesce(ListUnitPrice, ListUnitPrice1)\n | extend ContractedUnitPrice = coalesce(ContractedUnitPrice, ContractedUnitPrice1)\n | extend x_BaseUnitPrice = coalesce(x_BaseUnitPrice, x_BaseUnitPrice1)\n | project-away ListUnitPrice1, ContractedUnitPrice1, x_BaseUnitPrice1, tmp_SavingsPlanKey\n | union ((prices | where x_SkuPriceType != 'SavingsPlan'))\n //\n // Calculate commitment discount elgibility\n // TODO: Would a join be faster?\n | extend x_CommitmentDiscountSpendEligibility = iff(x_SkuMeterId in (riMeters) and x_SkuPriceType != 'ReservedInstance', 'Eligible', 'Not Eligible')\n | extend x_CommitmentDiscountUsageEligibility = iff(x_SkuMeterId in (spMeters), 'Eligible', 'Not Eligible')\n //\n // Add PricingUnit and x_PricingBlockSize\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter (PricingUnits) on x_PricingUnitDescription | project-away x_PricingUnitDescription1\n | lookup kind=leftouter (PricingUnits | extend x_PricingBlockSize = todecimal(x_PricingBlockSize)) on x_PricingUnitDescription\n //\n | extend x_EffectiveUnitPrice = iff(x_SkuPriceType == 'SavingsPlan', UnitPrice, todecimal('')) // Savings plan prices are for the effective price, not the contracted price\n | extend x_EffectiveUnitPriceDiscount = ContractedUnitPrice - x_EffectiveUnitPrice\n | extend x_ContractedUnitPriceDiscount = ListUnitPrice - ContractedUnitPrice\n | extend x_TotalUnitPriceDiscount = ListUnitPrice - x_EffectiveUnitPrice\n | project\n BillingAccountId = tolower(case(\n BillingProfileId startswith '/', BillingProfileId,\n BillingAccountId startswith '/', BillingAccountId,\n strcat('/providers/microsoft.billing/billingaccounts/', x_BillingAccountId, iff(x_BillingProfileId == x_BillingAccountId, '', strcat('/billingprofiles/', x_BillingProfileId)))\n )),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName, x_BillingProfileId),\n BillingCurrency = coalesce(BillingCurrency, CurrencyCode, Currency), // Currency last as a fallback only\n ChargeCategory,\n CommitmentDiscountCategory = case(\n x_SkuPriceType == 'ReservedInstance', 'Usage',\n x_SkuPriceType == 'SavingsPlan', 'Spend',\n ''\n ),\n CommitmentDiscountType = case(\n x_SkuPriceType == 'ReservedInstance', 'Reservation',\n x_SkuPriceType == 'SavingsPlan', 'Savings plan',\n ''\n ),\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory = case(\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed',\n ''\n ),\n PricingUnit,\n SkuId = coalesce(ProductId, ProductID),\n SkuPriceId = strcat(x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType),\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement = case(\n strlen(x_BillingAccountId) > 32, 'MCA',\n strlen(x_BillingAccountId) < 32, 'EA',\n 'Unknown'\n ),\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent = 1.0 * x_ContractedUnitPriceDiscount / ListUnitPrice * 100,\n x_EffectivePeriodEnd = startofmonth(x_EffectivePeriodEnd + 1h),\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent = 1.0 * x_EffectiveUnitPriceDiscount / ContractedUnitPrice * 100,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingCurrency = coalesce(Currency, CurrencyCode), // CurrencyCode last as a fallback only\n x_PricingSubcategory = case(\n x_SkuPriceType == 'Consumption' and (x_SkuIncludedQuantity > 0 or x_SkuTier > 0), 'Tiered',\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed Spend',\n ''\n ),\n x_PricingUnitDescription,\n x_SkuDescription = Product,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterName,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName = coalesce(x_SourceName, 'Cost Management'),\n x_SourceProvider = coalesce(x_SourceProvider, 'Microsoft'),\n x_SourceType = coalesce(x_SourceType, 'PriceSheet'),\n x_SourceVersion = coalesce(x_SourceVersion, '2023-05-01'),\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent = 1.0 * x_TotalUnitPriceDiscount / ListUnitPrice * 100\n}\n\n// Prices_final_v1_0 table\n.create-merge table Prices_final_v1_0 (\n BillingAccountId: string,\n BillingAccountName: string,\n BillingCurrency: string,\n ChargeCategory: string,\n CommitmentDiscountCategory: string,\n CommitmentDiscountType: string,\n ContractedUnitPrice: decimal,\n ListUnitPrice: decimal,\n PricingCategory: string,\n PricingUnit: string,\n SkuId: string,\n SkuPriceId: string,\n SkuPriceIdv2: string, // Hubs add-on\n x_BaseUnitPrice: decimal, // Azure\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure MCA\n x_BillingProfileId: string, // Azure MCA\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_ContractedUnitPriceDiscount: decimal, // Hubs add-on\n x_ContractedUnitPriceDiscountPercent: decimal, // Hubs add-on\n x_EffectivePeriodEnd: datetime, // Azure\n x_EffectivePeriodStart: datetime, // Azure\n x_EffectiveUnitPrice: decimal, // Azure\n x_EffectiveUnitPriceDiscount: decimal, // Hubs add-on\n x_EffectiveUnitPriceDiscountPercent: decimal, // Hubs add-on\n x_IngestionTime: datetime, // Hubs add-on\n x_PricingBlockSize: decimal, // Hubs add-on\n x_PricingCurrency: string, // Azure\n x_PricingSubcategory: string, // Hubs add-on\n x_PricingUnitDescription: string, // Azure\n x_SkuDescription: string, // Azure\n x_SkuId: string, // Azure\n x_SkuIncludedQuantity: decimal, // Azure EA\n x_SkuMeterCategory: string, // Azure\n x_SkuMeterId: string, // Azure\n x_SkuMeterName: string, // Azure\n x_SkuMeterSubcategory: string, // Azure\n x_SkuMeterType: string, // Azure\n x_SkuPriceType: string, // Azure\n x_SkuProductId: string, // Azure\n x_SkuRegion: string, // Azure\n x_SkuServiceFamily: string, // Azure\n x_SkuOfferId: string, // Azure EA\n x_SkuPartNumber: string, // Azure EA\n x_SkuTerm: int, // Azure\n x_SkuTier: decimal, // Azure MCA\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_TotalUnitPriceDiscount: decimal, // Hubs add-on\n x_TotalUnitPriceDiscountPercent: decimal // Hubs add-on\n)\n\n// Update policy for Prices_raw -> Prices_final_v1_0\n.alter table Prices_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Prices_raw\",\n \"Query\": \"Prices_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Cost and usage |=================================================================================================\n// Supported versions:\n// - MS: 1.0, 1.0-preview(v1) -- See https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0 -- See https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024 -- See https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 -- See https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All costs transformed to FOCUS 1.0. Use Costs_transform_v1_2() instead.', folder='Costs')\nCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n Costs_raw\n //\n // Change real to decimal\n | extend\n BilledCost = todecimal(BilledCost),\n CommitmentDiscountQuantity = todecimal(CommitmentDiscountQuantity),\n ConsumedQuantity = todecimal(ConsumedQuantity),\n ContractedCost = todecimal(ContractedCost),\n ContractedUnitPrice = todecimal(ContractedUnitPrice),\n EffectiveCost = todecimal(EffectiveCost),\n ListCost = todecimal(ListCost),\n ListUnitPrice = todecimal(ListUnitPrice),\n PricingQuantity = todecimal(PricingQuantity),\n UsageAmount = todecimal(UsageAmount),\n UsageQuantity = todecimal(UsageQuantity),\n x_BilledCostInUsd = todecimal(x_BilledCostInUsd),\n x_BilledUnitPrice = todecimal(x_BilledUnitPrice),\n x_BillingExchangeRate = todecimal(x_BillingExchangeRate),\n x_ContractedCostInUsd = todecimal(x_ContractedCostInUsd),\n x_Cost = todecimal(x_Cost),\n x_CurrencyConversionRate = todecimal(x_CurrencyConversionRate),\n x_EffectiveCostInUsd = todecimal(x_EffectiveCostInUsd),\n x_EffectiveUnitPrice = todecimal(x_EffectiveUnitPrice),\n x_ListCostInUsd = todecimal(x_ListCostInUsd),\n x_OnDemandCost = todecimal(x_OnDemandCost),\n x_OnDemandCostInUsd = todecimal(x_OnDemandCostInUsd),\n x_OnDemandUnitPrice = todecimal(x_OnDemandUnitPrice),\n x_PricingBlockSize = todecimal(x_PricingBlockSize)\n //\n // Dedupe rows\n | extend x_IngestionTime = ingestion_time()\n | extend x_ChargeId = ''\n // TODO: Consider adding a unique charge ID per row\n // hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // // 1. Resource hierarchy (including resource name), highest to lowest\n // BillingAccountId,\n // x_InvoiceSectionId,\n // x_AccountOwnerId,\n // SubAccountId,\n // x_ResourceGroupName,\n // ResourceName,\n // // 2. Resource details\n // ResourceId,\n // RegionId,\n // Tags,\n // CommitmentDiscountId,\n // x_CostCenter,\n // // 4. Meter details\n // SkuPriceId,\n // x_SkuMeterId,\n // x_SkuPartNumber,\n // x_SkuOfferId,\n // x_SkuDetails,\n // // 5. Date\n // ChargePeriodStart\n // ))\n //\n // Identify data quality issues\n | extend x_SourceChanges = trim_end(',', strcat(\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based', 'InvalidChargeFrequency,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and EffectiveCost > 0, 'InvalidEffectiveCost,', ''),\n iff((isempty(ContractedCost) or ContractedCost == 0) and EffectiveCost != 0, 'MissingContractedCost,', ''),\n iff((isempty(ContractedUnitPrice) or ContractedUnitPrice == 0) and x_EffectiveUnitPrice != 0, 'MissingContractedUnitPrice,', ''),\n iff(ListCost < ContractedCost, 'ListCostLessThanContractedCost,', ''),\n iff(ContractedCost < EffectiveCost, 'ContractedCostLessThanEffectiveCost,', ''),\n iff((isempty(ListCost) or ListCost == 0) and (ContractedCost != 0 or EffectiveCost != 0), 'MissingListCost,', ''),\n iff((isempty(ListUnitPrice) or ListUnitPrice == 0) and (ContractedUnitPrice != 0 or x_EffectiveUnitPrice != 0), 'MissingListUnitPrice,', ''),\n iff((isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001)\n or (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001),\n 'XEffectiveUnitPriceRoundingError,', ''),\n iff(ConsumedQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingConsumedQuantity,', ''),\n iff(PricingQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingPricingQuantity,', ''),\n iff(isempty(ProviderName), 'MissingProviderName,', ''),\n iff(isempty(PublisherName), 'MissingPublisherName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceId), 'MissingResourceId,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceName), 'MissingResourceName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceType), 'MissingResourceType,', ''),\n iff(BilledCost > 0 and x_BilledUnitPrice == 0, 'MissingXBilledUnitPrice,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(x_ResourceType), 'MissingXResourceType,', ''),\n iff(PricingCategory == 'Standard' and isnotempty(CommitmentDiscountId) and ChargeCategory == 'Usage', 'PricingCategoryShouldBeCommitted,', ''),\n iff(x_SkuTerm == '1Year' or x_SkuTerm == '3Years' or x_SkuTerm == '5Years', 'SkuTermShouldBeAnInteger,', '')\n ))\n //\n // Fix columns needed in other changes\n | extend ProviderName = case(\n isnotempty(ProviderName), ProviderName,\n isnotempty(coalesce(x_CostCategories, x_Discount, x_Operation, x_ServiceCode, x_UsageType)), 'AWS',\n isnotempty(coalesce(tostring(UsageAmount), tostring(x_Cost), x_Credits, x_CostType, tostring(x_CurrencyConversionRate), tostring(x_ExportTime), x_Project, x_ServiceId)), 'GCP',\n isnotempty(coalesce(x_BillingProfileId, x_InvoiceSectionId)), 'Microsoft',\n ''\n )\n //\n // Identify source\n | extend x_SourceName = coalesce(x_SourceName, iff(isnotempty(x_BillingProfileId), 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(isnotempty(x_BillingProfileId), 'FocusCost', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, case(\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)) and isempty(SkuPriceDetails) and isnotempty(x_SkuDetails), '1.2-preview',\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)), '1.2',\n isnotempty(coalesce(ChargeClass, CommitmentDiscountStatus, tostring(ConsumedQuantity), ConsumedUnit, tostring(ContractedCost), tostring(ContractedUnitPrice), RegionId, RegionName)), '1.0',\n isnotempty(coalesce(ChargeSubcategory, Region, tostring(UsageQuantity), UsageUnit)), iff(ProviderName == 'Microsoft', '1.0-preview(v1)', '1.0-preview'),\n ''\n ))\n // Append version check error code\n | extend x_SourceChanges = iff(x_SourceVersion == '1.0', x_SourceChanges,\n strcat(x_SourceChanges, iff(isempty(x_SourceChanges), '', ','), iff(x_SourceVersion == '', 'UnknownFocusVersion', 'LegacyFocusVersion'))\n )\n //\n // Fix quantities\n | extend PricingQuantity = case(\n PricingQuantity != 0 or (EffectiveCost == 0 and BilledCost == 0), PricingQuantity,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(EffectiveCost) and EffectiveCost != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0, EffectiveCost / x_EffectiveUnitPrice,\n PricingQuantity\n )\n | extend ConsumedQuantity = case(\n isnotempty(ConsumedQuantity) and ConsumedQuantity != 0, ConsumedQuantity,\n ChargeCategory == 'Usage', PricingQuantity / coalesce(x_PricingBlockSize, decimal(1)),\n ConsumedQuantity\n )\n //\n // Populate missing prices -- mapping to on-demand prices requires meter ID and offer ID\n | extend tmp_MissingPrices = ProviderName == 'Microsoft'\n and (ListUnitPrice == 0 or ContractedUnitPrice == 0)\n and x_EffectiveUnitPrice != 0\n and not(CommitmentDiscountCategory == 'Spend' and CommitmentDiscountStatus == 'Unused')\n and isnotempty(x_SkuMeterId) and isnotempty(x_SkuOfferId)\n | as allCosts\n | where tmp_MissingPrices\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(ChargePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | as costsWithMissingPrices\n | join kind=leftouter (\n Prices_final_v1_0\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(x_EffectivePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | where x_SkuPriceType == 'Consumption' and tmp_ReservationPriceLookupKey in ((costsWithMissingPrices | summarize by tmp_ReservationPriceLookupKey))\n | summarize ListUnitPrice = min(ListUnitPrice), ContractedUnitPrice = min(ContractedUnitPrice) by tmp_ReservationPriceLookupKey, x_PricingBlockSize, PricingUnit\n ) on tmp_ReservationPriceLookupKey\n //\n // Select the best price to use for each row\n // TODO: Save values before changing -- | extend x_old_ContractedUnitPrice = ContractedUnitPrice, x_old_EffectiveUnitPrice = x_EffectiveUnitPrice, x_old_ListUnitPrice = ListUnitPrice, x_old_ListCost = ListCost, x_old_ContractedCost = ContractedCost\n | extend x_EffectiveUnitPrice = case(\n // If price is a rounding error away from the billed price, use the billed price\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001, x_BilledUnitPrice,\n // If price is a rounding error away from the contracted price, use the contracted price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001, ContractedUnitPrice,\n x_EffectiveUnitPrice\n )\n | extend ContractedUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ContractedUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ContractedUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // If billed price is available, assume the billed price is the same as contracted price to support aggregations\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, x_EffectiveUnitPrice,\n // Otherwise, assume the effective price is the same as contracted price to support aggregations\n x_EffectiveUnitPrice\n )\n | extend ListUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ListUnitPrice) and ListUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ListUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ListUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ListUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // Otherwise, assume the contracted price is the same as list price to support aggregations\n ContractedUnitPrice\n )\n // Calculate missing costs based on new prices -- If cost is already correct, keep that; if not and price is available, recalculate the cost; otherwise, keep the existing cost\n | extend ContractedCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ContractedCost) and ContractedCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedCost,\n // ContractedCost is 0 in all other scenarios...\n // If 0 and there's a billed cost and prices are the same, use BilledCost\n isnotempty(BilledCost) and BilledCost != 0 and ContractedUnitPrice == x_BilledUnitPrice, BilledCost,\n // If 0 and there's a billed cost and prices are the same, use EffectiveCost\n isnotempty(EffectiveCost) and EffectiveCost != 0 and ContractedUnitPrice == x_EffectiveUnitPrice, EffectiveCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0, ContractedUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume EffectiveCost\n isempty(ContractedUnitPrice) or ContractedUnitPrice == 0, EffectiveCost,\n // Fall back to the original value for any unhandled scenarios\n ContractedCost\n )\n | extend ListCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ListCost) and ListCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ListCost,\n // ListCost is 0 in all other scenarios...\n // If 0 and there's a contracted cost and prices are the same, use ContractedCost\n isnotempty(ContractedCost) and ContractedCost != 0 and ListUnitPrice == ContractedUnitPrice, ContractedCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ListUnitPrice) and ListUnitPrice != 0, ListUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume ContractedCost\n isempty(ListUnitPrice) or ListUnitPrice == 0, ContractedCost,\n // Fall back to the original value for any unhandled scenarios\n ListCost\n )\n // Merge the rest of the unmodified cost records and remove excess columns\n | union (allCosts | where not(tmp_MissingPrices))\n | project-away x_PricingBlockSize1, PricingUnit1, ListUnitPrice1, ContractedUnitPrice1, tmp_MissingPrices, tmp_ReservationPriceLookupKey, tmp_ReservationPriceLookupKey1\n //\n // BUG: Fix ContractedCost that has bad values\n | extend ContractedCost = iff(ProviderName == 'Microsoft' and isnotempty(PricingQuantity) and isnotempty(x_PricingBlockSize) and ContractedCost != ContractedUnitPrice * PricingQuantity, ContractedUnitPrice * PricingQuantity, ContractedCost)\n //\n // Handle FOCUS 1.0-preview UsageQuantity/Unit\n | extend ConsumedQuantity = iff(ChargeCategory == 'Usage', coalesce(ConsumedQuantity, UsageQuantity, UsageAmount), todecimal(''))\n | extend ConsumedUnit = iff(ChargeCategory == 'Usage' and isnotempty(ConsumedQuantity), coalesce(ConsumedUnit, UsageUnit, 'Units'), '')\n //\n // Convert IDs to lowercase for consistency\n | extend CommitmentDiscountId = tolower(CommitmentDiscountId)\n //\n // BUG: Remove EffectiveCost for commitment discount purchases\n | extend EffectiveCost = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), decimal(0), EffectiveCost)\n | extend x_EffectiveCostInUsd = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), decimal(0), x_EffectiveCostInUsd)\n //\n // Clean up resource columns\n | extend ResourceId = case(\n isnotempty(ResourceId), ResourceId,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), CommitmentDiscountId,\n ResourceId)\n | extend ResourceName = tolower(case(\n isnotempty(ResourceName), ResourceName,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountName), CommitmentDiscountName,\n isnotempty(ResourceId), parse_resourceid(ResourceId).ResourceName,\n ResourceName))\n | extend x_ResourceType = case(\n isnotempty(x_ResourceType), x_ResourceType,\n isnotempty(ResourceId), parse_resourceid(ResourceId).x_ResourceType,\n x_ResourceType)\n | extend ResourceType = case(\n // Use existing resource type display name unless it's an internal resource type ID\n isnotempty(ResourceType) and tolower(ResourceType) != tolower(x_ResourceType) and ResourceType !contains '/', ResourceType,\n // Use CommitmentDiscountType for commitment discount purchases\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountType), CommitmentDiscountType,\n // Look up display name from internal type\n isnotempty(x_ResourceType), coalesce(resource_type(x_ResourceType).SingularDisplayName, ResourceType, x_ResourceType),\n ResourceType)\n //\n // Sort columns and apply final transforms\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId = tolower(BillingAccountId),\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEnd),\n BillingPeriodStart = startofmonth(BillingPeriodStart),\n ChargeCategory = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Credit', 'Credit',\n ChargeSubcategory == 'Refund', 'Purchase', // We are assuming purchase refunds since we don't have data to indicate usage refunds\n ChargeCategory\n ),\n ChargeClass = case(ChargeSubcategory == 'Refund', 'Correction', ChargeClass),\n ChargeDescription,\n // BUG: ChargeFrequency shows \"Usage-Based\" for monthly recurring savings plan purchases\n ChargeFrequency = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based' and ProviderName == 'Microsoft' and x_SourceVersion startswith '1.0', 'Recurring', ChargeFrequency),\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId = tolower(CommitmentDiscountId),\n CommitmentDiscountName,\n CommitmentDiscountStatus = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Used Commitment', 'Used',\n ChargeSubcategory == 'Unused Commitment', 'Unused',\n CommitmentDiscountStatus\n ),\n CommitmentDiscountType,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost = coalesce(ContractedCost, x_OnDemandCost, x_Cost),\n ContractedUnitPrice = coalesce(ContractedUnitPrice, x_OnDemandUnitPrice),\n EffectiveCost,\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory = case(\n // Handle FOCUS 1.0-preview PricingCategory values\n PricingCategory == 'On-Demand', 'Standard',\n PricingCategory == 'Commitment-Based', 'Committed',\n PricingCategory\n ),\n PricingQuantity,\n PricingUnit,\n ProviderName,\n // Handle missing PublisherName values\n PublisherName = case(PublisherName == 'Microsoft Corporation', 'Microsoft', isnotempty(PublisherName), PublisherName, x_PublisherCategory == 'Cloud Provider', ProviderName, ''),\n // Handle FOCUS 1.0-preview Region column\n RegionId = coalesce(RegionId, iff(ProviderName == 'Microsoft', replace_string(tolower(Region), ' ', ''), Region)),\n RegionName = coalesce(RegionName, Region),\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SkuId,\n SkuPriceId,\n SubAccountId,\n SubAccountName,\n SubAccountType, // Azure 1.0-preview(v1)+\n Tags = parse_json(Tags),\n x_AccountId, // Azure 1.0-preview(v1)+\n x_AccountName, // Azure 1.0-preview(v1)+\n x_AccountOwnerId, // Azure 1.0-preview(v1)+\n x_BilledCostInUsd, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement = case(\n ProviderName == 'Microsoft' and x_BillingAccountId == x_BillingProfileId, 'EA',\n ProviderName == 'Microsoft' and x_BillingAccountId != x_BillingProfileId, 'MCA',\n ProviderName\n ), // Hubs add-on\n x_BillingAccountId, // Azure 1.0-preview(v1)+\n x_BillingAccountName, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate, // Azure 1.0-preview(v1)+\n x_BillingProfileId, // Azure 1.0-preview(v1)+\n x_BillingProfileName, // Azure 1.0-preview(v1)+\n x_ChargeId, // Azure 1.0-preview(v1) only\n x_ContractedCostInUsd = coalesce(x_ContractedCostInUsd, x_OnDemandCostInUsd), // Azure 1.0+\n x_CostAllocationRuleName, // Azure 1.0-preview(v1)+\n x_CostCategories = parse_json(x_CostCategories), // AWS 1.0 (JSON)\n x_CostCenter, // Azure 1.0-preview(v1)+\n x_Credits = parse_json(x_Credits), // GCP Jan 2024\n x_CostType, // GCP Jan 2024\n x_CurrencyConversionRate, // GCP Jun 2024\n x_CustomerId, // Azure 1.0-preview(v1)+\n x_CustomerName, // Azure 1.0-preview(v1)+\n x_Discount = parse_json(x_Discount), // AWS 1.0 (JSON)\n x_EffectiveCostInUsd, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice, // Azure 1.0-preview(v1)+\n x_ExportTime, // GCP Jan 2024\n x_IngestionTime, // Hubs add-on\n x_InvoiceId = coalesce(InvoiceId, x_InvoiceId), // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId = case( // Azure 1.0-preview(v1)+\n x_InvoiceSectionId == '-2', '',\n x_InvoiceSectionId\n ),\n x_InvoiceSectionName = case( // Azure 1.0-preview(v1)+\n x_InvoiceSectionName == 'Unassigned', '',\n x_InvoiceSectionName\n ),\n x_ListCostInUsd, // Azure 1.0-preview(v1)+\n x_Location, // GCP Jan 2024\n x_Operation, // AWS 1.0\n x_PartnerCreditApplied, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate, // Azure 1.0-preview(v1)+\n x_PricingBlockSize, // Azure 1.0-preview(v1)+\n x_PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency), // Azure 1.0-preview(v1)+\n x_PricingSubcategory, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription, // Azure 1.0-preview(v1)+\n x_Project, // GCP Jan 2024\n x_PublisherCategory, // Azure 1.0-preview(v1)+\n x_PublisherId, // Azure 1.0-preview(v1)+\n x_ResellerId, // Azure 1.0-preview(v1)+\n x_ResellerName, // Azure 1.0-preview(v1)+\n x_ResourceGroupName = tolower(x_ResourceGroupName), // Azure 1.0-preview(v1)+\n x_ResourceType, // Azure 1.0-preview(v1)+\n x_ServiceCode, // AWS 1.0\n x_ServiceId, // GCP Jan 2024\n x_ServicePeriodEnd, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart, // Azure 1.0-preview(v1)+\n x_SkuDescription, // Azure 1.0-preview(v1)+\n x_SkuDetails = parse_json(x_SkuDetails), // Azure 1.0-preview(v1)+\n x_SkuIsCreditEligible, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory, // Azure 1.0-preview(v1)+\n x_SkuMeterId, // Azure 1.0-preview(v1)+\n x_SkuMeterName = coalesce(SkuMeter, x_SkuMeterName), // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory, // Azure 1.0-preview(v1)+\n x_SkuOfferId, // Azure 1.0-preview(v1)+\n x_SkuOrderId, // Azure 1.0-preview(v1)+\n x_SkuOrderName, // Azure 1.0-preview(v1)+\n x_SkuPartNumber, // Azure 1.0-preview(v1)+\n x_SkuRegion, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily, // Azure 1.0-preview(v1)+\n x_SkuTerm, // Azure 1.0-preview(v1)+\n x_SkuTier, // Azure 1.0-preview(v1)+\n x_SourceChanges, // Hubs add-on\n x_SourceName, // Hubs add-on\n x_SourceProvider, // Hubs add-on\n x_SourceType, // Hubs add-on\n x_SourceVersion, // Hubs add-on\n x_UsageType // AWS 1.0\n}\n\n// Costs_final_v1_0 table\n.create-merge table Costs_final_v1_0 (\n AvailabilityZone: string,\n BilledCost: decimal,\n BillingAccountId: string,\n BillingAccountName: string,\n BillingAccountType: string, // Azure 1.0-preview(v1)+\n BillingCurrency: string,\n BillingPeriodEnd: datetime,\n BillingPeriodStart: datetime,\n ChargeCategory: string,\n ChargeClass: string,\n ChargeDescription: string,\n ChargeFrequency: string,\n ChargePeriodEnd: datetime,\n ChargePeriodStart: datetime,\n CommitmentDiscountCategory: string, // FOCUS 1.0-preview only\n CommitmentDiscountId: string,\n CommitmentDiscountName: string,\n CommitmentDiscountStatus: string,\n CommitmentDiscountType: string,\n ConsumedQuantity: decimal,\n ConsumedUnit: string,\n ContractedCost: decimal,\n ContractedUnitPrice: decimal,\n EffectiveCost: decimal,\n InvoiceIssuerName: string,\n ListCost: decimal,\n ListUnitPrice: decimal,\n PricingCategory: string,\n PricingQuantity: decimal,\n PricingUnit: string,\n ProviderName: string,\n PublisherName: string,\n RegionId: string,\n RegionName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n ServiceCategory: string,\n ServiceName: string,\n SkuId: string,\n SkuPriceId: string,\n SubAccountId: string,\n SubAccountName: string,\n SubAccountType: string,\n Tags: dynamic,\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_BilledCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: decimal, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: decimal, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_ContractedCostInUsd: decimal, // Azure 1.0+\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: dynamic, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_Credits: dynamic, // GCP Jan 2024\n x_CostType: string, // GCP Jan 2024\n x_CurrencyConversionRate: decimal, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: dynamic, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: decimal, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024\n x_IngestionTime: datetime, // Hubs add-on\n x_InvoiceId: string, // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_Operation: string, // AWS 1.0\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: decimal, // Azure 1.0-preview(v1)+\n x_PricingCurrency: string, // Azure 1.0-preview(v1)+\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: dynamic, // Azure 1.0-preview(v1)+\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterName: string, // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceChanges: string, // Hubs add-on\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_UsageType: string // AWS 1.0\n)\n\n// Update policy for Costs_raw -> Costs_final_v1_0 table\n.alter table Costs_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Costs_raw\",\n \"Query\": \"Costs_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Actual costs |===================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: ActualCost exports transformed to FOCUS 1.0. Use ActualCosts_transform_v1_2() instead.', folder='Costs')\nActualCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n // TODO: Transform actual costs to FOCUS 1.0 format\n ActualCosts_raw\n | where ChargeType in ('Purchase', 'Refund') and isnotempty(ReservationId)\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: ServiceSubcategory, PublisherName, x_PublisherCategory, x_Environment, x_ServiceModel\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodStart = Date,\n ChargePeriodEnd = Date + 1d,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = '',\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory = '',\n SkuId = '',\n SkuMeter = '',\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = SubscriptionName,\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentName = '',\n x_ComponentType = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel = '',\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for ActualCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": false,\n \"Source\": \"ActualCosts_raw\",\n \"Query\": \"ActualCosts_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Amortized costs |================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: ActualCost exports transformed to FOCUS 1.0. Use AmortizedCosts_transform_v1_2() instead.', folder='Costs')\nAmortizedCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n // TODO: Transform actual costs to FOCUS 1.0 format\n AmortizedCosts_raw\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: ServiceSubcategory, PublisherName, x_PublisherCategory, x_Environment, x_ServiceModel\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodStart = Date,\n ChargePeriodEnd = Date + 1d,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = '',\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory = '',\n SkuId = '',\n SkuMeter = '',\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = SubscriptionName,\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentName = '',\n x_ComponentType = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel = '',\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for AmortizedCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": false,\n \"Source\": \"AmortizedCosts_raw\",\n \"Query\": \"AmortizedCosts_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All commitment discount usage transformed to FOCUS 1.0. This includes reservationdeatils_raw. Use CommitmentDiscountUsage_transform_v1_2() instead.', folder='Commitment discounts')\nCommitmentDiscountUsage_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n CommitmentDiscountUsage_raw\n //\n // Change real to decimal\n | extend\n InstanceFlexibilityRatio = todecimal(InstanceFlexibilityRatio),\n ReservedHours = todecimal(ReservedHours),\n TotalReservedQuantity = todecimal(TotalReservedQuantity),\n UsedHours = todecimal(UsedHours)\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Handle resource columns\n | extend ResourceId = tolower(InstanceId)\n | extend tmp_ResourceDetails = parse_resourceid(ResourceId)\n | extend ResourceName = tostring(tmp_ResourceDetails.ResourceName)\n | extend SubAccountId = tostring(tmp_ResourceDetails.SubAccountId)\n | extend x_ResourceGroupName = tostring(tmp_ResourceDetails.x_ResourceGroupName)\n | extend x_ResourceType = tostring(tmp_ResourceDetails.x_ResourceType)\n | lookup kind=leftouter (ResourceTypes | distinct x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n | lookup kind=leftouter (Services | distinct x_ResourceType, ServiceName, ServiceCategory, x_ServiceModel) on x_ResourceType\n //\n // Sort columns and apply final transforms\n | project\n ChargePeriodEnd = UsageDate + 1d,\n ChargePeriodStart = UsageDate,\n CommitmentDiscountCategory = 'Usage',\n CommitmentDiscountId = tolower(strcat('/providers/microsoft.capacity/reservationorders/', ReservationOrderId, '/reservations/', ReservationId)),\n CommitmentDiscountType = 'Reservation',\n ConsumedQuantity = UsedHours,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SubAccountId,\n x_CommitmentDiscountCommittedCount = TotalReservedQuantity,\n x_CommitmentDiscountCommittedAmount = ReservedHours,\n // TODO: Is this needed? -- x_CommitmentDiscountKind = Kind,\n x_CommitmentDiscountNormalizedGroup = iff(InstanceFlexibilityGroup == 'NA', '', InstanceFlexibilityGroup),\n x_CommitmentDiscountNormalizedRatio = InstanceFlexibilityRatio,\n x_CommitmentDiscountQuantity = UsedHours * InstanceFlexibilityRatio,\n x_IngestionTime = ingestion_time(),\n x_ResourceGroupName,\n x_ResourceType,\n // x_RowId = hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // CommitmentDiscountId,\n // ResourceId,\n // ChargePeriodStart\n // )),\n x_ServiceModel,\n x_SkuOrderId = ReservationOrderId,\n x_SkuSize = iff(SkuName == 'NA', '', SkuName),\n x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName)),\n x_SourceProvider = coalesce(x_SourceProvider, ProviderName),\n x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationDetails', '')),\n x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2024-03-01', ''))\n}\n\n// CommitmentDiscountUsage_final_v1_0 table\n.create-merge table CommitmentDiscountUsage_final_v1_0 (\n ChargePeriodEnd: datetime, // Hubs add-on\n ChargePeriodStart: datetime, // MS 2023-03-01\n CommitmentDiscountCategory: string, // Hubs add-on\n CommitmentDiscountId: string, // MS 2023-03-01\n CommitmentDiscountType: string, // Hubs add-on\n ConsumedQuantity: decimal, // MS 2023-03-01\n ProviderName: string, // Hubs add-on\n ResourceId: string, // MS 2023-03-01\n ResourceName: string, // Hubs add-on\n ResourceType: string, // Hubs add-on\n ServiceCategory: string, // Hubs add-on\n ServiceName: string, // Hubs add-on\n SubAccountId: string, // Hubs add-on\n x_CommitmentDiscountCommittedCount: decimal, // MS 2023-03-01\n x_CommitmentDiscountCommittedAmount: decimal, // MS 2023-03-01\n x_CommitmentDiscountNormalizedGroup: string, // MS 2023-03-01\n x_CommitmentDiscountNormalizedRatio: decimal, // MS 2023-03-01\n x_CommitmentDiscountQuantity: decimal, // MS 2023-03-01\n x_IngestionTime: datetime, // Hubs add-on\n x_ResourceGroupName: string, // Hubs add-on\n x_ResourceType: string, // Hubs add-on\n x_ServiceModel: string, // Hubs add-on\n x_SkuOrderId: string, // MS 2023-03-01\n x_SkuSize: string, // MS 2023-03-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string // Hubs add-on\n)\n\n// Update policy for CommitmentDiscountUsage_raw -> CommitmentDiscountUsage_final_v1_0 table\n.alter table CommitmentDiscountUsage_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"CommitmentDiscountUsage_raw\",\n \"Query\": \"CommitmentDiscountUsage_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All recommendations transformed to FOCUS 1.0. Use Recommendations_transform_v1_2() instead.', folder='Recommendations')\nRecommendations_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Recommendations_raw\n //\n // Change real to decimal\n | extend\n CostWithNoReservedInstances = todecimal(CostWithNoReservedInstances),\n InstanceFlexibilityRatio = todecimal(InstanceFlexibilityRatio),\n NetSavings = todecimal(NetSavings),\n RecommendedQuantity = todecimal(RecommendedQuantity),\n RecommendedQuantityNormalized = todecimal(RecommendedQuantityNormalized),\n TotalCostWithReservedInstances = todecimal(TotalCostWithReservedInstances)\n //\n | extend x_IngestionTime = ingestion_time()\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationRecommendations', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Convert JSON cost columns to decimal\n | extend CostWithNoReservedInstances = case(isnotempty(CostWithNoReservedInstances), CostWithNoReservedInstances, isnotempty(CostWithNoReservedInstancesJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, CostWithNoReservedInstancesJson)), CostWithNoReservedInstances)\n | extend NetSavings = case(isnotempty(NetSavings), NetSavings, isnotempty(NetSavingsJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, NetSavingsJson)), NetSavings)\n | extend TotalCostWithReservedInstances = case(isnotempty(TotalCostWithReservedInstances), TotalCostWithReservedInstances, isnotempty(TotalCostWithReservedInstancesJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, TotalCostWithReservedInstancesJson)), TotalCostWithReservedInstances)\n //\n // Build recommendation details\n | lookup kind=leftouter (Regions | summarize RegionName = make_set(RegionName)[0] by Location = RegionId) on Location\n | extend x_RecommendationDetails = case(\n x_SourceType == 'ReservationRecommendations', bag_pack(\n 'CommitmentDiscountNormalizedGroup', InstanceFlexibilityGroup,\n 'CommitmentDiscountNormalizedRatio', InstanceFlexibilityRatio,\n 'CommitmentDiscountNormalizedSize', NormalizedSize,\n 'CommitmentDiscountResourceType', ResourceType,\n 'CommitmentDiscountScope', Scope,\n 'LookbackPeriodDuration', case(\n LookBackPeriod matches regex @'^Last([0-9]+)Days$', replace_regex(LookBackPeriod, @'^Last([0-9]+)Days$', @'P\\1D'),\n LookBackPeriod matches regex @'^[0-9]+$', strcat('P', LookBackPeriod, 'D'),\n ''\n ),\n 'LookbackPeriodStart', FirstUsageDate,\n 'RecommendedQuantity', RecommendedQuantity,\n 'RecommendedQuantityNormalized', RecommendedQuantityNormalized,\n 'RegionId', Location,\n 'RegionName', RegionName,\n 'SkuMeterId', MeterId,\n 'SkuPriceDetails', SkuProperties,\n 'SkuSize', coalesce(SKU, SkuName),\n 'SkuTerm', isoMonths(Term)\n ),\n dynamic({})\n )\n //\n // Sort columns and apply final transforms\n | extend x_RecommendationDate = FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d)\n | extend x_RecommendationDate = iff(x_RecommendationDate > now(), startofday(now()), x_RecommendationDate)\n | project\n ProviderName,\n SubAccountId = iff(isnotempty(SubscriptionId), strcat('/subscriptions/', SubscriptionId), ''),\n x_IngestionTime,\n x_EffectiveCostAfter = TotalCostWithReservedInstances,\n x_EffectiveCostBefore = CostWithNoReservedInstances,\n x_EffectiveCostSavings = NetSavings,\n x_RecommendationDate = FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d),\n x_RecommendationDetails,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n// Recommendations_final_v1_0 table\n.create-merge table Recommendations_final_v1_0 (\n ProviderName: string,\n SubAccountId: string,\n x_IngestionTime: datetime,\n x_EffectiveCostAfter: decimal,\n x_EffectiveCostBefore: decimal,\n x_EffectiveCostSavings: decimal,\n x_RecommendationDate: datetime,\n x_RecommendationDetails: dynamic,\n x_SourceName: string,\n x_SourceProvider: string,\n x_SourceType: string,\n x_SourceVersion: string\n)\n\n// Update policy for Recommendations_raw -> Recommendations_final_v1_0 table\n.alter table Recommendations_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Recommendations_raw\",\n \"Query\": \"Recommendations_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All transactions transformed to FOCUS 1.0. Use Transactions_transform_v1_2() instead.', folder='Transactions')\nTransactions_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Transactions_raw\n //\n // Change real to decimal\n | extend\n Amount = todecimal(Amount),\n MonetaryCommitment = todecimal(MonetaryCommitment),\n Overage = todecimal(Overage),\n Quantity = todecimal(Quantity)\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationTransactions', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Handle BillingPeriodStart/End\n | extend BillingMonth = tostring(BillingMonth)\n | extend BillingPeriodStart = iff(isempty(BillingMonth), datetime(null), todatetime(strcat(substring(BillingMonth, 0, 4), \"-\", substring(BillingMonth, 4, 2), \"-\", substring(BillingMonth, 6, 2))))\n | extend BillingPeriodEnd = iff(isempty(BillingMonth), datetime(null), startofmonth(endofmonth(BillingPeriodStart) + 1d))\n //\n // Sort columns and apply final transforms\n | project\n BilledCost = Amount,\n BillingAccountId = case(\n BillingProfileId startswith '/', BillingProfileId,\n isnotempty(CurrentEnrollmentId), strcat('/providers/Microsoft.Billing/billingAccounts/', CurrentEnrollmentId),\n isnotempty(BillingProfileId), strcat('/providers/Microsoft.Billing/billingProfiles/', BillingProfileId),\n ''\n ),\n BillingAccountName = coalesce(BillingProfileName, CurrentEnrollmentId),\n BillingCurrency = Currency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory = case(\n EventType in ('Cancel', 'Purchase', 'Refund'), 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = case(\n EventType == 'Cancel', 'Cancel', // FOCUS does not handle this scenario\n EventType == 'Refund', 'Correction',\n ''\n ),\n ChargeDescription = Description,\n ChargeFrequency = case(\n BillingFrequency == 'OneTime', 'One-Time',\n BillingFrequency == 'Recurring', 'Recurring',\n BillingFrequency\n ),\n ChargePeriodStart = EventDate,\n PricingQuantity = Quantity,\n PricingUnit = 'Reservations',\n ProviderName,\n RegionId = Region,\n RegionName = Region,\n SubAccountId = iff(isempty(PurchasingSubscriptionGuid), '', strcat('/subscriptions/', PurchasingSubscriptionGuid)),\n SubAccountName = iff(isempty(PurchasingSubscriptionGuid), '', PurchasingSubscriptionName),\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerEmail,\n x_CostCenter = CostCenter,\n x_InvoiceId = InvoiceId,\n x_InvoiceNumber = Invoice,\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = coalesce(InvoiceSectionName, DepartmentName),\n x_IngestionTime = ingestion_time(),\n x_MonetaryCommitment = MonetaryCommitment,\n x_Overage = Overage,\n x_PurchasingBillingAccountId = PurchasingEnrollment,\n x_SkuOrderId = ReservationOrderId,\n x_SkuOrderName = ReservationOrderName,\n x_SkuSize = ArmSkuName,\n x_SkuTerm = isoMonths(Term),\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId = PurchasingSubscriptionGuid,\n x_TransactionType = EventType\n}\n\n// Transactions_final_v1_0 table\n.create-merge table Transactions_final_v1_0 (\n BilledCost: decimal, // MS CM EA+MCA 2023-05-01\n BillingAccountId: string, // MS CM EA+MCA 2023-05-01\n BillingAccountName: string, // MS CM EA+MCA 2023-05-01\n BillingCurrency: string, // MS CM EA+MCA 2023-05-01\n BillingPeriodEnd: datetime, // MS CM EA+MCA 2023-05-01\n BillingPeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n ChargeCategory: string, // Hubs add-on\n ChargeClass: string, // Hubs add-on\n ChargeDescription: string, // MS CM EA+MCA 2023-05-01\n ChargeFrequency: string, // MS CM EA+MCA 2023-05-01\n ChargePeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n PricingQuantity: decimal, // MS CM EA+MCA 2023-05-01\n PricingUnit: string, // Hubs add-on\n ProviderName: string, // Hubs add-on\n RegionId: string, // MS CM EA+MCA 2023-05-01\n RegionName: string, // MS CM EA+MCA 2023-05-01\n SubAccountId: string, // MS CM EA+MCA 2023-05-01\n SubAccountName: string, // MS CM EA+MCA 2023-05-01\n x_AccountName: string, // MS CM EA 2023-05-01\n x_AccountOwnerId: string, // MS CM EA 2023-05-01\n x_CostCenter: string, // MS CM EA 2023-05-01\n x_InvoiceId: string, // MS CM MCA 2023-05-01\n x_InvoiceNumber: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionId: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionName: string, // MS CM MCA 2023-05-01\n x_IngestionTime: datetime, // Hubs add-on\n x_MonetaryCommitment: decimal, // MS CM EA 2023-05-01\n x_Overage: decimal, // MS CM EA 2023-05-01\n x_PurchasingBillingAccountId: string, // MS CM EA 2023-05-01\n x_SkuOrderId: string, // MS CM EA+MCA 2023-05-01\n x_SkuOrderName: string, // MS CM EA+MCA 2023-05-01\n x_SkuSize: string, // MS CM EA+MCA 2023-05-01\n x_SkuTerm: int, // MS CM EA+MCA 2023-05-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubscriptionId: string, // MS CM EA+MCA 2023-05-01\n x_TransactionType: string // MS CM EA+MCA 2023-05-01\n)\n\n// Update policy for Transactions_raw -> Transactions_final_v1_0 table\n.alter table Transactions_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Transactions_raw\",\n \"Query\": \"Transactions_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n", + "$fxv#9": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// Used for data ingestion, normalization, and cleansing.\n// See known issues @ https://github.com/microsoft/finops-toolkit/issues/1111\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Prices |=========================================================================================================\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All prices transformed to FOCUS 1.0. Use Prices_transform_v1_2() instead.', folder='Prices')\nPrices_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n let prices = materialize(\n Prices_raw\n //\n // Change real to decimal\n | extend\n BasePrice = todecimal(BasePrice),\n IncludedQuantity = todecimal(IncludedQuantity),\n MarketPrice = todecimal(MarketPrice),\n TierMinimumUnits = todecimal(TierMinimumUnits),\n UnitPrice = todecimal(UnitPrice)\n //\n | extend x_SkuId = coalesce(SkuId, SkuID)\n | extend x_SkuMeterId = coalesce(MeterId, MeterID)\n | extend x_SkuProductId = coalesce(ProductId, ProductID)\n | extend x_SkuTerm = isoMonths(Term)\n | project-rename\n x_BaseUnitPrice = BasePrice,\n x_EffectivePeriodEnd = EffectiveEndDate,\n x_EffectivePeriodStart = EffectiveStartDate,\n x_PricingUnitDescription = UnitOfMeasure,\n x_SkuIncludedQuantity = IncludedQuantity,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuMeterType = MeterType,\n x_SkuOfferId = OfferID,\n x_SkuPartNumber = PartNumber,\n x_SkuPriceType = PriceType,\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTier = TierMinimumUnits\n | extend ContractedUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', UnitPrice, todecimal('')) // UnitPrice for savings plan is not the on-demand unit price\n | extend ListUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', MarketPrice, todecimal('')) // MarketPrice for savings plan is not the list price\n | extend ChargeCategory = case(\n x_SkuPriceType == 'Consumption', 'Usage',\n x_SkuPriceType == 'ReservedInstance', 'Purchase',\n x_SkuPriceType == 'SavingsPlan', 'Usage', // Savings plan prices are for committed usage, not the purchase\n ''\n )\n | extend SkuPriceIdv2 = strcat(case(x_SkuPriceType == 'Consumption', 'OD', x_SkuPriceType == 'ReservedInstance', 'RI', x_SkuPriceType == 'SavingsPlan', 'SP', 'XX'), substring(ChargeCategory, 0, 1), x_SkuTerm, '_', x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType, '_', x_SkuTier, x_SkuOfferId)\n | extend x_BillingAccountId = iff(BillingAccountId startswith '/', split(BillingAccountId, '/')[-1], coalesce(BillingAccountId, EnrollmentNumber))\n | extend x_BillingProfileId = iff(BillingProfileId startswith '/', split(BillingProfileId, '/')[-1], coalesce(BillingProfileId, EnrollmentNumber))\n | extend tmp_SavingsPlanKey = strcat(x_SkuMeterId, x_SkuProductId, x_SkuId, x_SkuTier, x_SkuOfferId)\n //\n // Get latest ingested row based on the unique ID\n | extend x_IngestionTime = ingestion_time()\n );\n //\n // Meters for reservations and savings plans to identify commitment eligibility\n let riMeters = prices | where x_SkuPriceType == 'ReservedInstance' | distinct x_SkuMeterId;\n let spMeters = prices | where x_SkuPriceType == 'SavingsPlan' | distinct x_SkuMeterId;\n //\n // Copy list/base/contracted prices from on-demand SKUs\n prices\n | where x_SkuPriceType == 'SavingsPlan'\n // If we use join, specify the shuffle key\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter hint.strategy=shuffle (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | lookup kind=leftouter (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | extend ListUnitPrice = coalesce(ListUnitPrice, ListUnitPrice1)\n | extend ContractedUnitPrice = coalesce(ContractedUnitPrice, ContractedUnitPrice1)\n | extend x_BaseUnitPrice = coalesce(x_BaseUnitPrice, x_BaseUnitPrice1)\n | project-away ListUnitPrice1, ContractedUnitPrice1, x_BaseUnitPrice1, tmp_SavingsPlanKey\n | union ((prices | where x_SkuPriceType != 'SavingsPlan'))\n //\n // Calculate commitment discount elgibility\n // TODO: Would a join be faster?\n | extend x_CommitmentDiscountSpendEligibility = iff(x_SkuMeterId in (riMeters) and x_SkuPriceType != 'ReservedInstance', 'Eligible', 'Not Eligible')\n | extend x_CommitmentDiscountUsageEligibility = iff(x_SkuMeterId in (spMeters), 'Eligible', 'Not Eligible')\n //\n // Add PricingUnit and x_PricingBlockSize\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter (PricingUnits) on x_PricingUnitDescription | project-away x_PricingUnitDescription1\n | lookup kind=leftouter (PricingUnits | extend x_PricingBlockSize = todecimal(x_PricingBlockSize)) on x_PricingUnitDescription\n //\n | extend x_EffectiveUnitPrice = iff(x_SkuPriceType == 'SavingsPlan', UnitPrice, todecimal('')) // Savings plan prices are for the effective price, not the contracted price\n | extend x_EffectiveUnitPriceDiscount = ContractedUnitPrice - x_EffectiveUnitPrice\n | extend x_ContractedUnitPriceDiscount = ListUnitPrice - ContractedUnitPrice\n | extend x_TotalUnitPriceDiscount = ListUnitPrice - x_EffectiveUnitPrice\n | project\n BillingAccountId = tolower(case(\n BillingProfileId startswith '/', BillingProfileId,\n BillingAccountId startswith '/', BillingAccountId,\n strcat('/providers/microsoft.billing/billingaccounts/', x_BillingAccountId, iff(x_BillingProfileId == x_BillingAccountId, '', strcat('/billingprofiles/', x_BillingProfileId)))\n )),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName, x_BillingProfileId),\n BillingCurrency = coalesce(BillingCurrency, CurrencyCode, Currency), // Currency last as a fallback only\n ChargeCategory,\n CommitmentDiscountCategory = case(\n x_SkuPriceType == 'ReservedInstance', 'Usage',\n x_SkuPriceType == 'SavingsPlan', 'Spend',\n ''\n ),\n CommitmentDiscountType = case(\n x_SkuPriceType == 'ReservedInstance', 'Reservation',\n x_SkuPriceType == 'SavingsPlan', 'Savings plan',\n ''\n ),\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory = case(\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed',\n ''\n ),\n PricingUnit,\n SkuId = coalesce(ProductId, ProductID),\n SkuPriceId = strcat(x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType),\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement = case(\n strlen(x_BillingAccountId) > 32, 'MCA',\n strlen(x_BillingAccountId) < 32, 'EA',\n 'Unknown'\n ),\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent = 1.0 * x_ContractedUnitPriceDiscount / ListUnitPrice * 100,\n x_EffectivePeriodEnd = startofmonth(x_EffectivePeriodEnd + 1h),\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent = 1.0 * x_EffectiveUnitPriceDiscount / ContractedUnitPrice * 100,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingCurrency = coalesce(Currency, CurrencyCode), // CurrencyCode last as a fallback only\n x_PricingSubcategory = case(\n x_SkuPriceType == 'Consumption' and (x_SkuIncludedQuantity > 0 or x_SkuTier > 0), 'Tiered',\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed Spend',\n ''\n ),\n x_PricingUnitDescription,\n x_SkuDescription = Product,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterName,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName = coalesce(x_SourceName, 'Cost Management'),\n x_SourceProvider = coalesce(x_SourceProvider, 'Microsoft'),\n x_SourceType = coalesce(x_SourceType, 'PriceSheet'),\n x_SourceVersion = coalesce(x_SourceVersion, '2023-05-01'),\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent = 1.0 * x_TotalUnitPriceDiscount / ListUnitPrice * 100\n}\n\n// Prices_final_v1_0 table\n.create-merge table Prices_final_v1_0 (\n BillingAccountId: string,\n BillingAccountName: string,\n BillingCurrency: string,\n ChargeCategory: string,\n CommitmentDiscountCategory: string,\n CommitmentDiscountType: string,\n ContractedUnitPrice: decimal,\n ListUnitPrice: decimal,\n PricingCategory: string,\n PricingUnit: string,\n SkuId: string,\n SkuPriceId: string,\n SkuPriceIdv2: string, // Hubs add-on\n x_BaseUnitPrice: decimal, // Azure\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure MCA\n x_BillingProfileId: string, // Azure MCA\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_ContractedUnitPriceDiscount: decimal, // Hubs add-on\n x_ContractedUnitPriceDiscountPercent: decimal, // Hubs add-on\n x_EffectivePeriodEnd: datetime, // Azure\n x_EffectivePeriodStart: datetime, // Azure\n x_EffectiveUnitPrice: decimal, // Azure\n x_EffectiveUnitPriceDiscount: decimal, // Hubs add-on\n x_EffectiveUnitPriceDiscountPercent: decimal, // Hubs add-on\n x_IngestionTime: datetime, // Hubs add-on\n x_PricingBlockSize: decimal, // Hubs add-on\n x_PricingCurrency: string, // Azure\n x_PricingSubcategory: string, // Hubs add-on\n x_PricingUnitDescription: string, // Azure\n x_SkuDescription: string, // Azure\n x_SkuId: string, // Azure\n x_SkuIncludedQuantity: decimal, // Azure EA\n x_SkuMeterCategory: string, // Azure\n x_SkuMeterId: string, // Azure\n x_SkuMeterName: string, // Azure\n x_SkuMeterSubcategory: string, // Azure\n x_SkuMeterType: string, // Azure\n x_SkuPriceType: string, // Azure\n x_SkuProductId: string, // Azure\n x_SkuRegion: string, // Azure\n x_SkuServiceFamily: string, // Azure\n x_SkuOfferId: string, // Azure EA\n x_SkuPartNumber: string, // Azure EA\n x_SkuTerm: int, // Azure\n x_SkuTier: decimal, // Azure MCA\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_TotalUnitPriceDiscount: decimal, // Hubs add-on\n x_TotalUnitPriceDiscountPercent: decimal // Hubs add-on\n)\n\n// Update policy for Prices_raw -> Prices_final_v1_0\n.alter table Prices_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Prices_raw\",\n \"Query\": \"Prices_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Cost and usage |=================================================================================================\n// Supported versions:\n// - MS: 1.0, 1.0-preview(v1) -- See https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0 -- See https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024 -- See https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 -- See https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All costs transformed to FOCUS 1.0. Use Costs_transform_v1_2() instead.', folder='Costs')\nCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n Costs_raw\n //\n // Change real to decimal\n | extend\n BilledCost = todecimal(BilledCost),\n CommitmentDiscountQuantity = todecimal(CommitmentDiscountQuantity),\n ConsumedQuantity = todecimal(ConsumedQuantity),\n ContractedCost = todecimal(ContractedCost),\n ContractedUnitPrice = todecimal(ContractedUnitPrice),\n EffectiveCost = todecimal(EffectiveCost),\n ListCost = todecimal(ListCost),\n ListUnitPrice = todecimal(ListUnitPrice),\n PricingQuantity = todecimal(PricingQuantity),\n UsageAmount = todecimal(UsageAmount),\n UsageQuantity = todecimal(UsageQuantity),\n x_BilledCostInUsd = todecimal(x_BilledCostInUsd),\n x_BilledUnitPrice = todecimal(x_BilledUnitPrice),\n x_BillingExchangeRate = todecimal(x_BillingExchangeRate),\n x_ContractedCostInUsd = todecimal(x_ContractedCostInUsd),\n x_Cost = todecimal(x_Cost),\n x_CurrencyConversionRate = todecimal(x_CurrencyConversionRate),\n x_EffectiveCostInUsd = todecimal(x_EffectiveCostInUsd),\n x_EffectiveUnitPrice = todecimal(x_EffectiveUnitPrice),\n x_ListCostInUsd = todecimal(x_ListCostInUsd),\n x_OnDemandCost = todecimal(x_OnDemandCost),\n x_OnDemandCostInUsd = todecimal(x_OnDemandCostInUsd),\n x_OnDemandUnitPrice = todecimal(x_OnDemandUnitPrice),\n x_PricingBlockSize = todecimal(x_PricingBlockSize)\n //\n // Dedupe rows\n | extend x_IngestionTime = ingestion_time()\n | extend x_ChargeId = ''\n // TODO: Consider adding a unique charge ID per row\n // hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // // 1. Resource hierarchy (including resource name), highest to lowest\n // BillingAccountId,\n // x_InvoiceSectionId,\n // x_AccountOwnerId,\n // SubAccountId,\n // x_ResourceGroupName,\n // ResourceName,\n // // 2. Resource details\n // ResourceId,\n // RegionId,\n // Tags,\n // CommitmentDiscountId,\n // x_CostCenter,\n // // 4. Meter details\n // SkuPriceId,\n // x_SkuMeterId,\n // x_SkuPartNumber,\n // x_SkuOfferId,\n // x_SkuDetails,\n // // 5. Date\n // ChargePeriodStart\n // ))\n //\n // Identify data quality issues\n | extend x_SourceChanges = trim_end(',', strcat(\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based', 'InvalidChargeFrequency,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and EffectiveCost > 0, 'InvalidEffectiveCost,', ''),\n iff((isempty(ContractedCost) or ContractedCost == 0) and EffectiveCost != 0, 'MissingContractedCost,', ''),\n iff((isempty(ContractedUnitPrice) or ContractedUnitPrice == 0) and x_EffectiveUnitPrice != 0, 'MissingContractedUnitPrice,', ''),\n iff(ListCost < ContractedCost, 'ListCostLessThanContractedCost,', ''),\n iff(ContractedCost < EffectiveCost, 'ContractedCostLessThanEffectiveCost,', ''),\n iff((isempty(ListCost) or ListCost == 0) and (ContractedCost != 0 or EffectiveCost != 0), 'MissingListCost,', ''),\n iff((isempty(ListUnitPrice) or ListUnitPrice == 0) and (ContractedUnitPrice != 0 or x_EffectiveUnitPrice != 0), 'MissingListUnitPrice,', ''),\n iff((isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001)\n or (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001),\n 'XEffectiveUnitPriceRoundingError,', ''),\n iff(ConsumedQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingConsumedQuantity,', ''),\n iff(PricingQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingPricingQuantity,', ''),\n iff(isempty(ProviderName), 'MissingProviderName,', ''),\n iff(isempty(PublisherName), 'MissingPublisherName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceId), 'MissingResourceId,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceName), 'MissingResourceName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceType), 'MissingResourceType,', ''),\n iff(BilledCost > 0 and x_BilledUnitPrice == 0, 'MissingXBilledUnitPrice,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(x_ResourceType), 'MissingXResourceType,', ''),\n iff(PricingCategory == 'Standard' and isnotempty(CommitmentDiscountId) and ChargeCategory == 'Usage', 'PricingCategoryShouldBeCommitted,', ''),\n iff(x_SkuTerm == '1Year' or x_SkuTerm == '3Years' or x_SkuTerm == '5Years', 'SkuTermShouldBeAnInteger,', '')\n ))\n //\n // Fix columns needed in other changes\n | extend ProviderName = case(\n isnotempty(ProviderName), ProviderName,\n isnotempty(coalesce(x_CostCategories, x_Discount, x_Operation, x_ServiceCode, x_UsageType)), 'AWS',\n isnotempty(coalesce(tostring(UsageAmount), tostring(x_Cost), x_Credits, x_CostType, tostring(x_CurrencyConversionRate), tostring(x_ExportTime), x_Project, x_ServiceId)), 'GCP',\n isnotempty(coalesce(x_BillingProfileId, x_InvoiceSectionId)), 'Microsoft',\n ''\n )\n //\n // Identify source\n | extend x_SourceName = coalesce(x_SourceName, iff(isnotempty(x_BillingProfileId), 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(isnotempty(x_BillingProfileId), 'FocusCost', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, case(\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)) and isempty(SkuPriceDetails) and isnotempty(x_SkuDetails), '1.2-preview',\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)), '1.2',\n isnotempty(coalesce(ChargeClass, CommitmentDiscountStatus, tostring(ConsumedQuantity), ConsumedUnit, tostring(ContractedCost), tostring(ContractedUnitPrice), RegionId, RegionName)), '1.0',\n isnotempty(coalesce(ChargeSubcategory, Region, tostring(UsageQuantity), UsageUnit)), iff(ProviderName == 'Microsoft', '1.0-preview(v1)', '1.0-preview'),\n ''\n ))\n // Append version check error code\n | extend x_SourceChanges = iff(x_SourceVersion == '1.0', x_SourceChanges,\n strcat(x_SourceChanges, iff(isempty(x_SourceChanges), '', ','), iff(x_SourceVersion == '', 'UnknownFocusVersion', 'LegacyFocusVersion'))\n )\n //\n // Fix quantities\n | extend PricingQuantity = case(\n PricingQuantity != 0 or (EffectiveCost == 0 and BilledCost == 0), PricingQuantity,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(EffectiveCost) and EffectiveCost != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0, EffectiveCost / x_EffectiveUnitPrice,\n PricingQuantity\n )\n | extend ConsumedQuantity = case(\n isnotempty(ConsumedQuantity) and ConsumedQuantity != 0, ConsumedQuantity,\n ChargeCategory == 'Usage', PricingQuantity / coalesce(x_PricingBlockSize, decimal(1)),\n ConsumedQuantity\n )\n //\n // Populate missing prices -- mapping to on-demand prices requires meter ID and offer ID\n | extend tmp_MissingPrices = ProviderName == 'Microsoft'\n and (ListUnitPrice == 0 or ContractedUnitPrice == 0)\n and x_EffectiveUnitPrice != 0\n and not(CommitmentDiscountCategory == 'Spend' and CommitmentDiscountStatus == 'Unused')\n and isnotempty(strcat(x_SkuMeterId, x_SkuOfferId))\n | as allCosts\n | where tmp_MissingPrices\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(ChargePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | as costsWithMissingPrices\n | join kind=leftouter (\n Prices_final_v1_0\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(x_EffectivePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | where x_SkuPriceType == 'Consumption' and tmp_ReservationPriceLookupKey in ((costsWithMissingPrices | summarize by tmp_ReservationPriceLookupKey))\n | summarize ListUnitPrice = min(ListUnitPrice), ContractedUnitPrice = min(ContractedUnitPrice) by tmp_ReservationPriceLookupKey, x_PricingBlockSize, PricingUnit\n ) on tmp_ReservationPriceLookupKey\n //\n // Select the best price to use for each row\n // TODO: Save values before changing -- | extend x_old_ContractedUnitPrice = ContractedUnitPrice, x_old_EffectiveUnitPrice = x_EffectiveUnitPrice, x_old_ListUnitPrice = ListUnitPrice, x_old_ListCost = ListCost, x_old_ContractedCost = ContractedCost\n | extend x_EffectiveUnitPrice = case(\n // If price is a rounding error away from the billed price, use the billed price\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001, x_BilledUnitPrice,\n // If price is a rounding error away from the contracted price, use the contracted price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001, ContractedUnitPrice,\n x_EffectiveUnitPrice\n )\n | extend ContractedUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ContractedUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ContractedUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // If billed price is available, assume the billed price is the same as contracted price to support aggregations\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, x_EffectiveUnitPrice,\n // Otherwise, assume the effective price is the same as contracted price to support aggregations\n x_EffectiveUnitPrice\n )\n | extend ListUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ListUnitPrice) and ListUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ListUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ListUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ListUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // Otherwise, assume the contracted price is the same as list price to support aggregations\n ContractedUnitPrice\n )\n // Calculate missing costs based on new prices -- If cost is already correct, keep that; if not and price is available, recalculate the cost; otherwise, keep the existing cost\n | extend ContractedCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ContractedCost) and ContractedCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedCost,\n // ContractedCost is 0 in all other scenarios...\n // If 0 and there's a billed cost and prices are the same, use BilledCost\n isnotempty(BilledCost) and BilledCost != 0 and ContractedUnitPrice == x_BilledUnitPrice, BilledCost,\n // If 0 and there's a billed cost and prices are the same, use EffectiveCost\n isnotempty(EffectiveCost) and EffectiveCost != 0 and ContractedUnitPrice == x_EffectiveUnitPrice, EffectiveCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0, ContractedUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume EffectiveCost\n isempty(ContractedUnitPrice) or ContractedUnitPrice == 0, EffectiveCost,\n // Fall back to the original value for any unhandled scenarios\n ContractedCost\n )\n | extend ListCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ListCost) and ListCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ListCost,\n // ListCost is 0 in all other scenarios...\n // If 0 and there's a contracted cost and prices are the same, use ContractedCost\n isnotempty(ContractedCost) and ContractedCost != 0 and ListUnitPrice == ContractedUnitPrice, ContractedCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ListUnitPrice) and ListUnitPrice != 0, ListUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume ContractedCost\n isempty(ListUnitPrice) or ListUnitPrice == 0, ContractedCost,\n // Fall back to the original value for any unhandled scenarios\n ListCost\n )\n // Merge the rest of the unmodified cost records and remove excess columns\n | union (allCosts | where not(tmp_MissingPrices))\n | project-away x_PricingBlockSize1, PricingUnit1, ListUnitPrice1, ContractedUnitPrice1, tmp_MissingPrices, tmp_ReservationPriceLookupKey, tmp_ReservationPriceLookupKey1\n //\n // BUG: Fix ContractedCost that has bad values\n | extend ContractedCost = iff(ProviderName == 'Microsoft' and isnotempty(PricingQuantity) and isnotempty(x_PricingBlockSize) and ContractedCost != ContractedUnitPrice * PricingQuantity, ContractedUnitPrice * PricingQuantity, ContractedCost)\n //\n // Handle FOCUS 1.0-preview UsageQuantity/Unit\n | extend ConsumedQuantity = iff(ChargeCategory == 'Usage', coalesce(ConsumedQuantity, UsageQuantity, UsageAmount), todecimal(''))\n | extend ConsumedUnit = iff(ChargeCategory == 'Usage' and isnotempty(ConsumedQuantity), coalesce(ConsumedUnit, UsageUnit, 'Units'), '')\n //\n // Convert IDs to lowercase for consistency\n | extend CommitmentDiscountId = tolower(CommitmentDiscountId)\n //\n // BUG: Remove EffectiveCost for commitment discount purchases\n | extend EffectiveCost = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), decimal(0), EffectiveCost)\n | extend x_EffectiveCostInUsd = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), decimal(0), x_EffectiveCostInUsd)\n //\n // Clean up resource columns\n | extend ResourceId = case(\n isnotempty(ResourceId), ResourceId,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), CommitmentDiscountId,\n ResourceId)\n | extend ResourceName = tolower(case(\n isnotempty(ResourceName), ResourceName,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountName), CommitmentDiscountName,\n isnotempty(ResourceId), parse_resourceid(ResourceId).ResourceName,\n ResourceName))\n | extend x_ResourceType = case(\n isnotempty(x_ResourceType), x_ResourceType,\n isnotempty(ResourceId), parse_resourceid(ResourceId).x_ResourceType,\n x_ResourceType)\n | extend ResourceType = case(\n // Use existing resource type display name unless it's an internal resource type ID\n isnotempty(ResourceType) and tolower(ResourceType) != tolower(x_ResourceType) and ResourceType !contains '/', ResourceType,\n // Use CommitmentDiscountType for commitment discount purchases\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountType), CommitmentDiscountType,\n // Look up display name from internal type\n isnotempty(x_ResourceType), coalesce(resource_type(x_ResourceType).SingularDisplayName, ResourceType, x_ResourceType),\n ResourceType)\n //\n // Sort columns and apply final transforms\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId = tolower(BillingAccountId),\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEnd),\n BillingPeriodStart = startofmonth(BillingPeriodStart),\n ChargeCategory = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Credit', 'Credit',\n ChargeSubcategory == 'Refund', 'Purchase', // We are assuming purchase refunds since we don't have data to indicate usage refunds\n ChargeCategory\n ),\n ChargeClass = case(ChargeSubcategory == 'Refund', 'Correction', ChargeClass),\n ChargeDescription,\n // BUG: ChargeFrequency shows \"Usage-Based\" for monthly recurring savings plan purchases\n ChargeFrequency = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based' and ProviderName == 'Microsoft' and x_SourceVersion startswith '1.0', 'Recurring', ChargeFrequency),\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId = tolower(CommitmentDiscountId),\n CommitmentDiscountName,\n CommitmentDiscountStatus = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Used Commitment', 'Used',\n ChargeSubcategory == 'Unused Commitment', 'Unused',\n CommitmentDiscountStatus\n ),\n CommitmentDiscountType,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost = coalesce(ContractedCost, x_OnDemandCost, x_Cost),\n ContractedUnitPrice = coalesce(ContractedUnitPrice, x_OnDemandUnitPrice),\n EffectiveCost,\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory = case(\n // Handle FOCUS 1.0-preview PricingCategory values\n PricingCategory == 'On-Demand', 'Standard',\n PricingCategory == 'Commitment-Based', 'Committed',\n PricingCategory\n ),\n PricingQuantity,\n PricingUnit,\n ProviderName,\n // Handle missing PublisherName values\n PublisherName = case(PublisherName == 'Microsoft Corporation', 'Microsoft', isnotempty(PublisherName), PublisherName, x_PublisherCategory == 'Cloud Provider', ProviderName, ''),\n // Handle FOCUS 1.0-preview Region column\n RegionId = coalesce(RegionId, iff(ProviderName == 'Microsoft', replace_string(tolower(Region), ' ', ''), Region)),\n RegionName = coalesce(RegionName, Region),\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SkuId,\n SkuPriceId,\n SubAccountId,\n SubAccountName,\n SubAccountType, // Azure 1.0-preview(v1)+\n Tags = parse_json(Tags),\n x_AccountId, // Azure 1.0-preview(v1)+\n x_AccountName, // Azure 1.0-preview(v1)+\n x_AccountOwnerId, // Azure 1.0-preview(v1)+\n x_BilledCostInUsd, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement = case(\n ProviderName == 'Microsoft' and x_BillingAccountId == x_BillingProfileId, 'EA',\n ProviderName == 'Microsoft' and x_BillingAccountId != x_BillingProfileId, 'MCA',\n ProviderName\n ), // Hubs add-on\n x_BillingAccountId, // Azure 1.0-preview(v1)+\n x_BillingAccountName, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate, // Azure 1.0-preview(v1)+\n x_BillingProfileId, // Azure 1.0-preview(v1)+\n x_BillingProfileName, // Azure 1.0-preview(v1)+\n x_ChargeId, // Azure 1.0-preview(v1) only\n x_ContractedCostInUsd = coalesce(x_ContractedCostInUsd, x_OnDemandCostInUsd), // Azure 1.0+\n x_CostAllocationRuleName, // Azure 1.0-preview(v1)+\n x_CostCategories = parse_json(x_CostCategories), // AWS 1.0 (JSON)\n x_CostCenter, // Azure 1.0-preview(v1)+\n x_Credits = parse_json(x_Credits), // GCP Jan 2024\n x_CostType, // GCP Jan 2024\n x_CurrencyConversionRate, // GCP Jun 2024\n x_CustomerId, // Azure 1.0-preview(v1)+\n x_CustomerName, // Azure 1.0-preview(v1)+\n x_Discount = parse_json(x_Discount), // AWS 1.0 (JSON)\n x_EffectiveCostInUsd, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice, // Azure 1.0-preview(v1)+\n x_ExportTime, // GCP Jan 2024\n x_IngestionTime, // Hubs add-on\n x_InvoiceId = coalesce(InvoiceId, x_InvoiceId), // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId = case( // Azure 1.0-preview(v1)+\n x_InvoiceSectionId == '-2', '',\n x_InvoiceSectionId\n ),\n x_InvoiceSectionName = case( // Azure 1.0-preview(v1)+\n x_InvoiceSectionName == 'Unassigned', '',\n x_InvoiceSectionName\n ),\n x_ListCostInUsd, // Azure 1.0-preview(v1)+\n x_Location, // GCP Jan 2024\n x_Operation, // AWS 1.0\n x_PartnerCreditApplied, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate, // Azure 1.0-preview(v1)+\n x_PricingBlockSize, // Azure 1.0-preview(v1)+\n x_PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency), // Azure 1.0-preview(v1)+\n x_PricingSubcategory, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription, // Azure 1.0-preview(v1)+\n x_Project, // GCP Jan 2024\n x_PublisherCategory, // Azure 1.0-preview(v1)+\n x_PublisherId, // Azure 1.0-preview(v1)+\n x_ResellerId, // Azure 1.0-preview(v1)+\n x_ResellerName, // Azure 1.0-preview(v1)+\n x_ResourceGroupName = tolower(x_ResourceGroupName), // Azure 1.0-preview(v1)+\n x_ResourceType, // Azure 1.0-preview(v1)+\n x_ServiceCode, // AWS 1.0\n x_ServiceId, // GCP Jan 2024\n x_ServicePeriodEnd, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart, // Azure 1.0-preview(v1)+\n x_SkuDescription, // Azure 1.0-preview(v1)+\n x_SkuDetails = parse_json(x_SkuDetails), // Azure 1.0-preview(v1)+\n x_SkuIsCreditEligible, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory, // Azure 1.0-preview(v1)+\n x_SkuMeterId, // Azure 1.0-preview(v1)+\n x_SkuMeterName = coalesce(SkuMeter, x_SkuMeterName), // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory, // Azure 1.0-preview(v1)+\n x_SkuOfferId, // Azure 1.0-preview(v1)+\n x_SkuOrderId, // Azure 1.0-preview(v1)+\n x_SkuOrderName, // Azure 1.0-preview(v1)+\n x_SkuPartNumber, // Azure 1.0-preview(v1)+\n x_SkuRegion, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily, // Azure 1.0-preview(v1)+\n x_SkuTerm, // Azure 1.0-preview(v1)+\n x_SkuTier, // Azure 1.0-preview(v1)+\n x_SourceChanges, // Hubs add-on\n x_SourceName, // Hubs add-on\n x_SourceProvider, // Hubs add-on\n x_SourceType, // Hubs add-on\n x_SourceVersion, // Hubs add-on\n x_UsageType // AWS 1.0\n}\n\n// Costs_final_v1_0 table\n.create-merge table Costs_final_v1_0 (\n AvailabilityZone: string,\n BilledCost: decimal,\n BillingAccountId: string,\n BillingAccountName: string,\n BillingAccountType: string, // Azure 1.0-preview(v1)+\n BillingCurrency: string,\n BillingPeriodEnd: datetime,\n BillingPeriodStart: datetime,\n ChargeCategory: string,\n ChargeClass: string,\n ChargeDescription: string,\n ChargeFrequency: string,\n ChargePeriodEnd: datetime,\n ChargePeriodStart: datetime,\n CommitmentDiscountCategory: string, // FOCUS 1.0-preview only\n CommitmentDiscountId: string,\n CommitmentDiscountName: string,\n CommitmentDiscountStatus: string,\n CommitmentDiscountType: string,\n ConsumedQuantity: decimal,\n ConsumedUnit: string,\n ContractedCost: decimal,\n ContractedUnitPrice: decimal,\n EffectiveCost: decimal,\n InvoiceIssuerName: string,\n ListCost: decimal,\n ListUnitPrice: decimal,\n PricingCategory: string,\n PricingQuantity: decimal,\n PricingUnit: string,\n ProviderName: string,\n PublisherName: string,\n RegionId: string,\n RegionName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n ServiceCategory: string,\n ServiceName: string,\n SkuId: string,\n SkuPriceId: string,\n SubAccountId: string,\n SubAccountName: string,\n SubAccountType: string,\n Tags: dynamic,\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_BilledCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: decimal, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: decimal, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_ContractedCostInUsd: decimal, // Azure 1.0+\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: dynamic, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_Credits: dynamic, // GCP Jan 2024\n x_CostType: string, // GCP Jan 2024\n x_CurrencyConversionRate: decimal, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: dynamic, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: decimal, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024\n x_IngestionTime: datetime, // Hubs add-on\n x_InvoiceId: string, // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_Operation: string, // AWS 1.0\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: decimal, // Azure 1.0-preview(v1)+\n x_PricingCurrency: string, // Azure 1.0-preview(v1)+\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: dynamic, // Azure 1.0-preview(v1)+\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterName: string, // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceChanges: string, // Hubs add-on\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_UsageType: string // AWS 1.0\n)\n\n// Update policy for Costs_raw -> Costs_final_v1_0 table\n.alter table Costs_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Costs_raw\",\n \"Query\": \"Costs_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Actual costs |===================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: ActualCost exports transformed to FOCUS 1.0. Use ActualCosts_transform_v1_2() instead.', folder='Costs')\nActualCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n // TODO: Transform actual costs to FOCUS 1.0 format\n ActualCosts_raw\n | where ChargeType in ('Purchase', 'Refund') and isnotempty(ReservationId)\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: ServiceSubcategory, PublisherName, x_PublisherCategory, x_Environment, x_ServiceModel\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodStart = Date,\n ChargePeriodEnd = Date + 1d,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = '',\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory = '',\n SkuId = '',\n SkuMeter = '',\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = SubscriptionName,\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentName = '',\n x_ComponentType = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel = '',\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for ActualCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": false,\n \"Source\": \"ActualCosts_raw\",\n \"Query\": \"ActualCosts_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Amortized costs |================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: ActualCost exports transformed to FOCUS 1.0. Use AmortizedCosts_transform_v1_2() instead.', folder='Costs')\nAmortizedCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n // TODO: Transform actual costs to FOCUS 1.0 format\n AmortizedCosts_raw\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: ServiceSubcategory, PublisherName, x_PublisherCategory, x_Environment, x_ServiceModel\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodStart = Date,\n ChargePeriodEnd = Date + 1d,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = '',\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory = '',\n SkuId = '',\n SkuMeter = '',\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = SubscriptionName,\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentName = '',\n x_ComponentType = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel = '',\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for AmortizedCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": false,\n \"Source\": \"AmortizedCosts_raw\",\n \"Query\": \"AmortizedCosts_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All commitment discount usage transformed to FOCUS 1.0. This includes reservationdeatils_raw. Use CommitmentDiscountUsage_transform_v1_2() instead.', folder='Commitment discounts')\nCommitmentDiscountUsage_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n CommitmentDiscountUsage_raw\n //\n // Change real to decimal\n | extend\n InstanceFlexibilityRatio = todecimal(InstanceFlexibilityRatio),\n ReservedHours = todecimal(ReservedHours),\n TotalReservedQuantity = todecimal(TotalReservedQuantity),\n UsedHours = todecimal(UsedHours)\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Handle resource columns\n | extend ResourceId = tolower(InstanceId)\n | extend tmp_ResourceDetails = parse_resourceid(ResourceId)\n | extend ResourceName = tostring(tmp_ResourceDetails.ResourceName)\n | extend SubAccountId = tostring(tmp_ResourceDetails.SubAccountId)\n | extend x_ResourceGroupName = tostring(tmp_ResourceDetails.x_ResourceGroupName)\n | extend x_ResourceType = tostring(tmp_ResourceDetails.x_ResourceType)\n | lookup kind=leftouter (ResourceTypes | distinct x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n | lookup kind=leftouter (Services | distinct x_ResourceType, ServiceName, ServiceCategory, x_ServiceModel) on x_ResourceType\n //\n // Sort columns and apply final transforms\n | project\n ChargePeriodEnd = UsageDate + 1d,\n ChargePeriodStart = UsageDate,\n CommitmentDiscountCategory = 'Usage',\n CommitmentDiscountId = tolower(strcat('/providers/microsoft.capacity/reservationorders/', ReservationOrderId, '/reservations/', ReservationId)),\n CommitmentDiscountType = 'Reservation',\n ConsumedQuantity = UsedHours,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SubAccountId,\n x_CommitmentDiscountCommittedCount = TotalReservedQuantity,\n x_CommitmentDiscountCommittedAmount = ReservedHours,\n // TODO: Is this needed? -- x_CommitmentDiscountKind = Kind,\n x_CommitmentDiscountNormalizedGroup = iff(InstanceFlexibilityGroup == 'NA', '', InstanceFlexibilityGroup),\n x_CommitmentDiscountNormalizedRatio = InstanceFlexibilityRatio,\n x_CommitmentDiscountQuantity = UsedHours * InstanceFlexibilityRatio,\n x_IngestionTime = ingestion_time(),\n x_ResourceGroupName,\n x_ResourceType,\n // x_RowId = hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // CommitmentDiscountId,\n // ResourceId,\n // ChargePeriodStart\n // )),\n x_ServiceModel,\n x_SkuOrderId = ReservationOrderId,\n x_SkuSize = iff(SkuName == 'NA', '', SkuName),\n x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName)),\n x_SourceProvider = coalesce(x_SourceProvider, ProviderName),\n x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationDetails', '')),\n x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2024-03-01', ''))\n}\n\n// CommitmentDiscountUsage_final_v1_0 table\n.create-merge table CommitmentDiscountUsage_final_v1_0 (\n ChargePeriodEnd: datetime, // Hubs add-on\n ChargePeriodStart: datetime, // MS 2023-03-01\n CommitmentDiscountCategory: string, // Hubs add-on\n CommitmentDiscountId: string, // MS 2023-03-01\n CommitmentDiscountType: string, // Hubs add-on\n ConsumedQuantity: decimal, // MS 2023-03-01\n ProviderName: string, // Hubs add-on\n ResourceId: string, // MS 2023-03-01\n ResourceName: string, // Hubs add-on\n ResourceType: string, // Hubs add-on\n ServiceCategory: string, // Hubs add-on\n ServiceName: string, // Hubs add-on\n SubAccountId: string, // Hubs add-on\n x_CommitmentDiscountCommittedCount: decimal, // MS 2023-03-01\n x_CommitmentDiscountCommittedAmount: decimal, // MS 2023-03-01\n x_CommitmentDiscountNormalizedGroup: string, // MS 2023-03-01\n x_CommitmentDiscountNormalizedRatio: decimal, // MS 2023-03-01\n x_CommitmentDiscountQuantity: decimal, // MS 2023-03-01\n x_IngestionTime: datetime, // Hubs add-on\n x_ResourceGroupName: string, // Hubs add-on\n x_ResourceType: string, // Hubs add-on\n x_ServiceModel: string, // Hubs add-on\n x_SkuOrderId: string, // MS 2023-03-01\n x_SkuSize: string, // MS 2023-03-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string // Hubs add-on\n)\n\n// Update policy for CommitmentDiscountUsage_raw -> CommitmentDiscountUsage_final_v1_0 table\n.alter table CommitmentDiscountUsage_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"CommitmentDiscountUsage_raw\",\n \"Query\": \"CommitmentDiscountUsage_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All recommendations transformed to FOCUS 1.0. Use Recommendations_transform_v1_2() instead.', folder='Recommendations')\nRecommendations_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Recommendations_raw\n //\n // Change real to decimal\n | extend\n CostWithNoReservedInstances = todecimal(CostWithNoReservedInstances),\n InstanceFlexibilityRatio = todecimal(InstanceFlexibilityRatio),\n NetSavings = todecimal(NetSavings),\n RecommendedQuantity = todecimal(RecommendedQuantity),\n RecommendedQuantityNormalized = todecimal(RecommendedQuantityNormalized),\n TotalCostWithReservedInstances = todecimal(TotalCostWithReservedInstances)\n //\n | extend x_IngestionTime = ingestion_time()\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationRecommendations', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Convert JSON cost columns to decimal\n | extend CostWithNoReservedInstances = case(isnotempty(CostWithNoReservedInstances), CostWithNoReservedInstances, isnotempty(CostWithNoReservedInstancesJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, CostWithNoReservedInstancesJson)), CostWithNoReservedInstances)\n | extend NetSavings = case(isnotempty(NetSavings), NetSavings, isnotempty(NetSavingsJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, NetSavingsJson)), NetSavings)\n | extend TotalCostWithReservedInstances = case(isnotempty(TotalCostWithReservedInstances), TotalCostWithReservedInstances, isnotempty(TotalCostWithReservedInstancesJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, TotalCostWithReservedInstancesJson)), TotalCostWithReservedInstances)\n //\n // Build recommendation details\n | lookup kind=leftouter (Regions | summarize RegionName = make_set(RegionName)[0] by Location = RegionId) on Location\n | extend x_RecommendationDetails = case(\n x_SourceType == 'ReservationRecommendations', bag_pack(\n 'CommitmentDiscountNormalizedGroup', InstanceFlexibilityGroup,\n 'CommitmentDiscountNormalizedRatio', InstanceFlexibilityRatio,\n 'CommitmentDiscountNormalizedSize', NormalizedSize,\n 'CommitmentDiscountResourceType', ResourceType,\n 'CommitmentDiscountScope', Scope,\n 'LookbackPeriodDuration', case(\n LookBackPeriod matches regex @'^Last([0-9]+)Days$', replace_regex(LookBackPeriod, @'^Last([0-9]+)Days$', @'P\\1D'),\n LookBackPeriod matches regex @'^[0-9]+$', strcat('P', LookBackPeriod, 'D'),\n ''\n ),\n 'LookbackPeriodStart', FirstUsageDate,\n 'RecommendedQuantity', RecommendedQuantity,\n 'RecommendedQuantityNormalized', RecommendedQuantityNormalized,\n 'RegionId', Location,\n 'RegionName', RegionName,\n 'SkuMeterId', MeterId,\n 'SkuPriceDetails', SkuProperties,\n 'SkuSize', coalesce(SKU, SkuName),\n 'SkuTerm', isoMonths(Term)\n ),\n dynamic({})\n )\n //\n // Sort columns and apply final transforms\n | extend x_RecommendationDate = FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d)\n | extend x_RecommendationDate = iff(x_RecommendationDate > now(), startofday(now()), x_RecommendationDate)\n | project\n ProviderName,\n SubAccountId = iff(isnotempty(SubscriptionId), strcat('/subscriptions/', SubscriptionId), ''),\n x_IngestionTime,\n x_EffectiveCostAfter = TotalCostWithReservedInstances,\n x_EffectiveCostBefore = CostWithNoReservedInstances,\n x_EffectiveCostSavings = NetSavings,\n x_RecommendationDate = FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d),\n x_RecommendationDetails,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n// Recommendations_final_v1_0 table\n.create-merge table Recommendations_final_v1_0 (\n ProviderName: string,\n SubAccountId: string,\n x_IngestionTime: datetime,\n x_EffectiveCostAfter: decimal,\n x_EffectiveCostBefore: decimal,\n x_EffectiveCostSavings: decimal,\n x_RecommendationDate: datetime,\n x_RecommendationDetails: dynamic,\n x_SourceName: string,\n x_SourceProvider: string,\n x_SourceType: string,\n x_SourceVersion: string\n)\n\n// Update policy for Recommendations_raw -> Recommendations_final_v1_0 table\n.alter table Recommendations_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Recommendations_raw\",\n \"Query\": \"Recommendations_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All transactions transformed to FOCUS 1.0. Use Transactions_transform_v1_2() instead.', folder='Transactions')\nTransactions_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Transactions_raw\n //\n // Change real to decimal\n | extend\n Amount = todecimal(Amount),\n MonetaryCommitment = todecimal(MonetaryCommitment),\n Overage = todecimal(Overage),\n Quantity = todecimal(Quantity)\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationTransactions', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Handle BillingPeriodStart/End\n | extend BillingMonth = tostring(BillingMonth)\n | extend BillingPeriodStart = iff(isempty(BillingMonth), datetime(null), todatetime(strcat(substring(BillingMonth, 0, 4), \"-\", substring(BillingMonth, 4, 2), \"-\", substring(BillingMonth, 6, 2))))\n | extend BillingPeriodEnd = iff(isempty(BillingMonth), datetime(null), startofmonth(endofmonth(BillingPeriodStart) + 1d))\n //\n // Sort columns and apply final transforms\n | project\n BilledCost = Amount,\n BillingAccountId = case(\n BillingProfileId startswith '/', BillingProfileId,\n isnotempty(CurrentEnrollmentId), strcat('/providers/Microsoft.Billing/billingAccounts/', CurrentEnrollmentId),\n isnotempty(BillingProfileId), strcat('/providers/Microsoft.Billing/billingProfiles/', BillingProfileId),\n ''\n ),\n BillingAccountName = coalesce(BillingProfileName, CurrentEnrollmentId),\n BillingCurrency = Currency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory = case(\n EventType in ('Cancel', 'Purchase', 'Refund'), 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = case(\n EventType == 'Cancel', 'Cancel', // FOCUS does not handle this scenario\n EventType == 'Refund', 'Correction',\n ''\n ),\n ChargeDescription = Description,\n ChargeFrequency = case(\n BillingFrequency == 'OneTime', 'One-Time',\n BillingFrequency == 'Recurring', 'Recurring',\n BillingFrequency\n ),\n ChargePeriodStart = EventDate,\n PricingQuantity = Quantity,\n PricingUnit = 'Reservations',\n ProviderName,\n RegionId = Region,\n RegionName = Region,\n SubAccountId = iff(isempty(PurchasingSubscriptionGuid), '', strcat('/subscriptions/', PurchasingSubscriptionGuid)),\n SubAccountName = iff(isempty(PurchasingSubscriptionGuid), '', PurchasingSubscriptionName),\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerEmail,\n x_CostCenter = CostCenter,\n x_InvoiceId = InvoiceId,\n x_InvoiceNumber = Invoice,\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = coalesce(InvoiceSectionName, DepartmentName),\n x_IngestionTime = ingestion_time(),\n x_MonetaryCommitment = MonetaryCommitment,\n x_Overage = Overage,\n x_PurchasingBillingAccountId = PurchasingEnrollment,\n x_SkuOrderId = ReservationOrderId,\n x_SkuOrderName = ReservationOrderName,\n x_SkuSize = ArmSkuName,\n x_SkuTerm = isoMonths(Term),\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId = PurchasingSubscriptionGuid,\n x_TransactionType = EventType\n}\n\n// Transactions_final_v1_0 table\n.create-merge table Transactions_final_v1_0 (\n BilledCost: decimal, // MS CM EA+MCA 2023-05-01\n BillingAccountId: string, // MS CM EA+MCA 2023-05-01\n BillingAccountName: string, // MS CM EA+MCA 2023-05-01\n BillingCurrency: string, // MS CM EA+MCA 2023-05-01\n BillingPeriodEnd: datetime, // MS CM EA+MCA 2023-05-01\n BillingPeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n ChargeCategory: string, // Hubs add-on\n ChargeClass: string, // Hubs add-on\n ChargeDescription: string, // MS CM EA+MCA 2023-05-01\n ChargeFrequency: string, // MS CM EA+MCA 2023-05-01\n ChargePeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n PricingQuantity: decimal, // MS CM EA+MCA 2023-05-01\n PricingUnit: string, // Hubs add-on\n ProviderName: string, // Hubs add-on\n RegionId: string, // MS CM EA+MCA 2023-05-01\n RegionName: string, // MS CM EA+MCA 2023-05-01\n SubAccountId: string, // MS CM EA+MCA 2023-05-01\n SubAccountName: string, // MS CM EA+MCA 2023-05-01\n x_AccountName: string, // MS CM EA 2023-05-01\n x_AccountOwnerId: string, // MS CM EA 2023-05-01\n x_CostCenter: string, // MS CM EA 2023-05-01\n x_InvoiceId: string, // MS CM MCA 2023-05-01\n x_InvoiceNumber: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionId: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionName: string, // MS CM MCA 2023-05-01\n x_IngestionTime: datetime, // Hubs add-on\n x_MonetaryCommitment: decimal, // MS CM EA 2023-05-01\n x_Overage: decimal, // MS CM EA 2023-05-01\n x_PurchasingBillingAccountId: string, // MS CM EA 2023-05-01\n x_SkuOrderId: string, // MS CM EA+MCA 2023-05-01\n x_SkuOrderName: string, // MS CM EA+MCA 2023-05-01\n x_SkuSize: string, // MS CM EA+MCA 2023-05-01\n x_SkuTerm: int, // MS CM EA+MCA 2023-05-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubscriptionId: string, // MS CM EA+MCA 2023-05-01\n x_TransactionType: string // MS CM EA+MCA 2023-05-01\n)\n\n// Update policy for Transactions_raw -> Transactions_final_v1_0 table\n.alter table Transactions_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Transactions_raw\",\n \"Query\": \"Transactions_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n", "HUB_DATA_EXPLORER": "hubDataExplorer", "HUB_DB": "Hub", "INGESTION_DB": "Ingestion", diff --git a/docs/deploy/finops-hub-latest.json b/docs/deploy/finops-hub-latest.json index f90016f65..f9d71a4ab 100644 --- a/docs/deploy/finops-hub-latest.json +++ b/docs/deploy/finops-hub-latest.json @@ -18320,7 +18320,7 @@ "variables": { "$fxv#0": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n.create-or-alter function \nwith (docstring = 'Return details about the specified ID.', folder = 'OpenData/Internal')\n_resource_type_1(id: string) {\n dynamic({\n \"arizeai.observabilityeval/organizations\": { \"SingularDisplayName\": \"Azure Native Arize AI Cloud Service\" }\n ,\"astronomer.astro/organizations\": { \"SingularDisplayName\": \"Astro Organization\" }\n ,\"citrix.services/xenappessentials\": { \"SingularDisplayName\": \"Citrix Virtual Apps Essentials\" }\n ,\"citrix.services/xendesktopessentials\": { \"SingularDisplayName\": \"Citrix Virtual Desktops Essentials\" }\n ,\"commvault.contentstore/cloudaccounts\": { \"SingularDisplayName\": \"Commvault Cloud Account\" }\n ,\"commvault.contentstore/cloudaccounts/plans\": { \"SingularDisplayName\": \"Commvault.ContentStore cloud accounts plan\" }\n ,\"commvault.contentstore/cloudaccounts/protectiongroups\": { \"SingularDisplayName\": \"Commvault.ContentStore cloud accounts protection group\" }\n ,\"commvault.contentstore/cloudaccounts/protectiongroups/protecteditems\": { \"SingularDisplayName\": \"Commvault.ContentStore cloud accounts protection groups protected item\" }\n ,\"commvault.contentstore/cloudaccounts/storages\": { \"SingularDisplayName\": \"Commvault.ContentStore cloud accounts storage\" }\n ,\"dell.storage/filesystems\": { \"SingularDisplayName\": \"Dell PowerScale\" }\n ,\"dynatrace.observability/monitors\": { \"SingularDisplayName\": \"Dynatrace\" }\n ,\"github.network/networksettings\": { \"SingularDisplayName\": \"GitHub.Network network setting\" }\n ,\"informatica.datamanagement/organizations\": { \"SingularDisplayName\": \"Informatica Organization\" }\n ,\"lambdatest.hyperexecute/organizations\": { \"SingularDisplayName\": \"Azure Native LambdaTest - HyperExecute Cloud Service\" }\n ,\"microsoft.aad/domainservices\": { \"SingularDisplayName\": \"Microsoft Entra Domain Services\" }\n ,\"microsoft.aadiam/diagnosticsettings\": { \"SingularDisplayName\": \"Microsoft.aadiam diagnostic setting\" }\n ,\"microsoft.aadiam/privatelinkforazuread\": { \"SingularDisplayName\": \"Private Link for Microsoft Entra ID\" }\n ,\"microsoft.advisor/advisorscore\": { \"SingularDisplayName\": \"Microsoft.Advisor advisor score\" }\n ,\"microsoft.advisor/assessments\": { \"SingularDisplayName\": \"Microsoft.Advisor assessment\" }\n ,\"microsoft.advisor/configurations\": { \"SingularDisplayName\": \"Microsoft.Advisor configuration\" }\n ,\"microsoft.advisor/generaterecommendations\": { \"SingularDisplayName\": \"Microsoft.Advisor generate recommendation\" }\n ,\"microsoft.advisor/metadata\": { \"SingularDisplayName\": \"Microsoft.Advisor metadata\" }\n ,\"microsoft.advisor/recommendations\": { \"SingularDisplayName\": \"Microsoft.Advisor recommendation\" }\n ,\"microsoft.advisor/recommendations/suppressions\": { \"SingularDisplayName\": \"Microsoft.Advisor recommendations suppression\" }\n ,\"microsoft.advisor/resiliencyreviews\": { \"SingularDisplayName\": \"Microsoft.Advisor resiliency review\" }\n ,\"microsoft.agfoodplatform/farmbeats\": { \"SingularDisplayName\": \"Azure Data Manager for Agriculture\" }\n ,\"microsoft.agfoodplatform/farmbeatsextensiondefinitions\": { \"SingularDisplayName\": \"Microsoft.AgFoodPlatform farm beats extension definition\" }\n ,\"microsoft.agfoodplatform/farmbeatssolutiondefinitions\": { \"SingularDisplayName\": \"Microsoft.AgFoodPlatform farm beats solution definition\" }\n ,\"microsoft.agricultureplatform/agriservices\": { \"SingularDisplayName\": \"Agriculture data solutions\" }\n ,\"microsoft.akshybrid/agentpools\": { \"SingularDisplayName\": \"Microsoft.AksHybrid agent pool\" }\n ,\"microsoft.akshybrid/provisionedclusters\": { \"SingularDisplayName\": \"Microsoft.AksHybrid provisioned cluster\" }\n ,\"microsoft.akshybrid/upgradeprofiles\": { \"SingularDisplayName\": \"Microsoft.AksHybrid upgrade profile\" }\n ,\"microsoft.alertsmanagement/actionrules\": { \"SingularDisplayName\": \"Alert processing rule\" }\n ,\"microsoft.alertsmanagement/alerts\": { \"SingularDisplayName\": \"Microsoft.AlertsManagement alert\" }\n ,\"microsoft.alertsmanagement/alerts/enrichments\": { \"SingularDisplayName\": \"Microsoft.AlertsManagement alerts enrichment\" }\n ,\"microsoft.alertsmanagement/prometheusrulegroups\": { \"SingularDisplayName\": \"Prometheus rule group\" }\n ,\"microsoft.alertsmanagement/smartdetectoralertrules\": { \"SingularDisplayName\": \"Smart detector alert rule\" }\n ,\"microsoft.alertsmanagement/smartgroups\": { \"SingularDisplayName\": \"Microsoft.AlertsManagement smart group\" }\n ,\"microsoft.alertsmanagement/tenantactivitylogalerts\": { \"SingularDisplayName\": \"Microsoft.AlertsManagement tenant activity log alert\" }\n ,\"microsoft.all/arcvirtualmachines\": { \"SingularDisplayName\": \"Azure Arc virtual machine\" }\n ,\"microsoft.all/hcivirtualmachines\": { \"SingularDisplayName\": \"Azure Local Virtual Machine - Azure Arc\" }\n ,\"microsoft.all/virtualmachines\": { \"SingularDisplayName\": \"Virtual machine\" }\n ,\"microsoft.analysisservices/servers\": { \"SingularDisplayName\": \"Analysis Services server\" }\n ,\"microsoft.anybuild/clusters\": { \"SingularDisplayName\": \"AnyBuild cluster\" }\n ,\"microsoft.apicenter/deletedservices\": { \"SingularDisplayName\": \"Microsoft.ApiCenter deleted service\" }\n ,\"microsoft.apicenter/services\": { \"SingularDisplayName\": \"API Center\" }\n ,\"microsoft.apicenter/services/workspaces\": { \"SingularDisplayName\": \"Workspace\" }\n ,\"microsoft.apimanagement/gateways\": { \"SingularDisplayName\": \"API Management gateway\" }\n ,\"microsoft.apimanagement/gateways/configconnections\": { \"SingularDisplayName\": \"Microsoft.ApiManagement gateways config connection\" }\n ,\"microsoft.apimanagement/service\": { \"SingularDisplayName\": \"API Management service\" }\n ,\"microsoft.apimanagement/service/workspaces\": { \"SingularDisplayName\": \"Workspace\" }\n ,\"microsoft.apisecurity/defendersettings\": { \"SingularDisplayName\": \"Microsoft.ApiSecurity defender setting\" }\n ,\"microsoft.app/agents\": { \"SingularDisplayName\": \"SRE Agent\" }\n ,\"microsoft.app/builders\": { \"SingularDisplayName\": \"Microsoft.App builder\" }\n ,\"microsoft.app/builders/builds\": { \"SingularDisplayName\": \"Microsoft.App builders build\" }\n ,\"microsoft.app/connectedenvironments\": { \"SingularDisplayName\": \"Container Apps Connected Environment\" }\n ,\"microsoft.app/containerapps\": { \"SingularDisplayName\": \"Container App\" }\n ,\"microsoft.app/jobs\": { \"SingularDisplayName\": \"Container App Job\" }\n ,\"microsoft.app/logicapps\": { \"SingularDisplayName\": \"Logic app\" }\n ,\"microsoft.app/logicapps/workflows\": { \"SingularDisplayName\": \"Logic app workflow\" }\n ,\"microsoft.app/managedenvironments\": { \"SingularDisplayName\": \"Container Apps Environment\" }\n ,\"microsoft.app/sessionpools\": { \"SingularDisplayName\": \"Container App Session Pool\" }\n ,\"microsoft.app/spaces\": { \"SingularDisplayName\": \"App Space\" }\n ,\"microsoft.appassessment/migrateprojects\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate project\" }\n ,\"microsoft.appassessment/migrateprojects/assessments\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects assessment\" }\n ,\"microsoft.appassessment/migrateprojects/assessments/assessedapplications\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects assessments assessed application\" }\n ,\"microsoft.appassessment/migrateprojects/assessments/assessedmachines\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects assessments assessed machine\" }\n ,\"microsoft.appassessment/migrateprojects/assessments/machinestoassess\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects assessments machines to asses\" }\n ,\"microsoft.appassessment/migrateprojects/sites\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects site\" }\n ,\"microsoft.appassessment/migrateprojects/sites/applianceconfigurations\": { \"SingularDisplayName\": \"Microsoft.AppAssessment migrate projects sites appliance configuration\" }\n ,\"microsoft.appcomplianceautomation/reports\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation report\" }\n ,\"microsoft.appcomplianceautomation/reports/evidences\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports evidence\" }\n ,\"microsoft.appcomplianceautomation/reports/scopingconfigurations\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports scoping configuration\" }\n ,\"microsoft.appcomplianceautomation/reports/snapshots\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports snapshot\" }\n ,\"microsoft.appcomplianceautomation/reports/snapshots/controls\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports snapshots control\" }\n ,\"microsoft.appcomplianceautomation/reports/webhooks\": { \"SingularDisplayName\": \"Microsoft.AppComplianceAutomation reports webhook\" }\n ,\"microsoft.appconfiguration/configurationstores\": { \"SingularDisplayName\": \"App Configuration\" }\n ,\"microsoft.applicationmigration/discoveryhubs\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration discovery hub\" }\n ,\"microsoft.applicationmigration/discoveryhubs/applications\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration discovery hubs application\" }\n ,\"microsoft.applicationmigration/discoveryhubs/applications/members\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration discovery hubs applications member\" }\n ,\"microsoft.applicationmigration/pgsqlsites\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration pgsqlsite\" }\n ,\"microsoft.applicationmigration/pgsqlsites/agents\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration pgsqlsites agent\" }\n ,\"microsoft.applicationmigration/pgsqlsites/pgsqldatabases\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration pgsqlsites pgsqldatabase\" }\n ,\"microsoft.applicationmigration/pgsqlsites/pgsqlinstances\": { \"SingularDisplayName\": \"Microsoft.ApplicationMigration pgsqlsites pgsqlinstance\" }\n ,\"microsoft.appplatform/spring\": { \"SingularDisplayName\": \"Azure Spring Apps\" }\n ,\"microsoft.appsecurity/appprotectmanagedrulesetmanifests\": { \"SingularDisplayName\": \"Microsoft.AppSecurity app protect managed rule set manifest\" }\n ,\"microsoft.appsecurity/policies\": { \"SingularDisplayName\": \"App Protect Policy\" }\n ,\"microsoft.arc/all\": { \"SingularDisplayName\": \"Azure Arc enabled resource\" }\n ,\"microsoft.arc/allfairfax\": { \"SingularDisplayName\": \"Azure Arc enabled resource\" }\n ,\"microsoft.arc/kubernetesresources\": { \"SingularDisplayName\": \"Azure Arc Kubernetes cluster\" }\n ,\"microsoft.arc/kubernetesresourcesfairfax\": { \"SingularDisplayName\": \"Azure Arc Kubernetes cluster\" }\n ,\"microsoft.arcnetworking/arcnwloadbalancers\": { \"SingularDisplayName\": \"Microsoft.ArcNetworking arc nw load balancer\" }\n ,\"microsoft.aszlabhardware/labservers\": { \"SingularDisplayName\": \"Microsoft.AszLabHardware labserver\" }\n ,\"microsoft.aszlabhardware/reservations\": { \"SingularDisplayName\": \"Microsoft.AszLabHardware reservation\" }\n ,\"microsoft.aszlabhardware/reservations/servers\": { \"SingularDisplayName\": \"Microsoft.AszLabHardware reservations server\" }\n ,\"microsoft.aszlabhardware/servers\": { \"SingularDisplayName\": \"Microsoft.AszLabHardware server\" }\n ,\"microsoft.attestation/attestationproviders\": { \"SingularDisplayName\": \"Attestation provider\" }\n ,\"microsoft.authorization/accessreviewhistorydefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization access review history definition\" }\n ,\"microsoft.authorization/accessreviewscheduledefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization access review schedule definition\" }\n ,\"microsoft.authorization/accessreviewscheduledefinitions/instances\": { \"SingularDisplayName\": \"Microsoft.Authorization access review schedule definitions instance\" }\n ,\"microsoft.authorization/accessreviewscheduledefinitions/instances/decisions\": { \"SingularDisplayName\": \"Microsoft.Authorization access review schedule definitions instances decision\" }\n ,\"microsoft.authorization/accessreviewschedulesettings\": { \"SingularDisplayName\": \"Microsoft.Authorization access review schedule setting\" }\n ,\"microsoft.authorization/datapolicymanifests\": { \"SingularDisplayName\": \"Microsoft.Authorization data policy manifest\" }\n ,\"microsoft.authorization/denyassignments\": { \"SingularDisplayName\": \"Microsoft.Authorization deny assignment\" }\n ,\"microsoft.authorization/locks\": { \"SingularDisplayName\": \"Microsoft.Authorization lock\" }\n ,\"microsoft.authorization/policyassignments\": { \"SingularDisplayName\": \"Microsoft.Authorization policy assignment\" }\n ,\"microsoft.authorization/policydefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy definition\" }\n ,\"microsoft.authorization/policydefinitions/versions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy definitions version\" }\n ,\"microsoft.authorization/policyexemptions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy exemption\" }\n ,\"microsoft.authorization/policysetdefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy set definition\" }\n ,\"microsoft.authorization/policysetdefinitions/versions\": { \"SingularDisplayName\": \"Microsoft.Authorization policy set definitions version\" }\n ,\"microsoft.authorization/privatelinkassociations\": { \"SingularDisplayName\": \"Microsoft.Authorization private link association\" }\n ,\"microsoft.authorization/provideroperations\": { \"SingularDisplayName\": \"Microsoft.Authorization provider operation\" }\n ,\"microsoft.authorization/resourcemanagementprivatelinks\": { \"SingularDisplayName\": \"Resource management private link\" }\n ,\"microsoft.authorization/roleassignmentapprovals\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment approval\" }\n ,\"microsoft.authorization/roleassignmentapprovals/stages\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment approvals stage\" }\n ,\"microsoft.authorization/roleassignments\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment\" }\n ,\"microsoft.authorization/roleassignmentscheduleinstances\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment schedule instance\" }\n ,\"microsoft.authorization/roleassignmentschedulerequests\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment schedule request\" }\n ,\"microsoft.authorization/roleassignmentschedules\": { \"SingularDisplayName\": \"Microsoft.Authorization role assignment schedule\" }\n ,\"microsoft.authorization/roledefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization role definition\" }\n ,\"microsoft.authorization/roleeligibilityscheduleinstances\": { \"SingularDisplayName\": \"Microsoft.Authorization role eligibility schedule instance\" }\n ,\"microsoft.authorization/roleeligibilityschedulerequests\": { \"SingularDisplayName\": \"Microsoft.Authorization role eligibility schedule request\" }\n ,\"microsoft.authorization/roleeligibilityschedules\": { \"SingularDisplayName\": \"Microsoft.Authorization role eligibility schedule\" }\n ,\"microsoft.authorization/rolemanagementalertconfigurations\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alert configuration\" }\n ,\"microsoft.authorization/rolemanagementalertdefinitions\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alert definition\" }\n ,\"microsoft.authorization/rolemanagementalertoperations\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alert operation\" }\n ,\"microsoft.authorization/rolemanagementalerts\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alert\" }\n ,\"microsoft.authorization/rolemanagementalerts/alertincidents\": { \"SingularDisplayName\": \"Microsoft.Authorization role management alerts alert incident\" }\n ,\"microsoft.authorization/rolemanagementpolicies\": { \"SingularDisplayName\": \"Microsoft.Authorization role management policy\" }\n ,\"microsoft.authorization/rolemanagementpolicyassignments\": { \"SingularDisplayName\": \"Microsoft.Authorization role management policy assignment\" }\n ,\"microsoft.automanage/bestpractices\": { \"SingularDisplayName\": \"Microsoft.Automanage best practice\" }\n ,\"microsoft.automanage/bestpractices/versions\": { \"SingularDisplayName\": \"Microsoft.Automanage best practices version\" }\n ,\"microsoft.automanage/configurationprofileassignments\": { \"SingularDisplayName\": \"Microsoft.Automanage configuration profile assignment\" }\n ,\"microsoft.automanage/configurationprofileassignments/reports\": { \"SingularDisplayName\": \"Microsoft.Automanage configuration profile assignments report\" }\n ,\"microsoft.automanage/configurationprofiles\": { \"SingularDisplayName\": \"Microsoft.Automanage configuration profile\" }\n ,\"microsoft.automanage/configurationprofiles/versions\": { \"SingularDisplayName\": \"Microsoft.Automanage configuration profiles version\" }\n ,\"microsoft.automanage/serviceprincipals\": { \"SingularDisplayName\": \"ServicePrincipals\" }\n ,\"microsoft.automation/automationaccounts\": { \"SingularDisplayName\": \"Automation account\" }\n ,\"microsoft.automation/automationaccounts/hybridrunbookworkergroups\": { \"SingularDisplayName\": \"Automation hybrid worker group\" }\n ,\"microsoft.automation/automationaccounts/runbooks\": { \"SingularDisplayName\": \"Automation runbook\" }\n ,\"microsoft.autonomousdevelopmentplatform/accounts\": { \"SingularDisplayName\": \"Microsoft.AutonomousDevelopmentPlatform account\" }\n ,\"microsoft.autonomousdevelopmentplatform/accounts/datapools\": { \"SingularDisplayName\": \"Microsoft.AutonomousDevelopmentPlatform accounts data pool\" }\n ,\"microsoft.autonomousdevelopmentplatform/workspaces\": { \"SingularDisplayName\": \"Microsoft.AutonomousDevelopmentPlatform workspace\" }\n ,\"microsoft.avs/privateclouds\": { \"SingularDisplayName\": \"Azure VMware Solution private cloud\" }\n ,\"microsoft.awsconnector/accessanalyzeranalyzers\": { \"SingularDisplayName\": \"Access Analyzer Analyzer\" }\n ,\"microsoft.awsconnector/acmcertificatesummaries\": { \"SingularDisplayName\": \"ACM Certificate Summary\" }\n ,\"microsoft.awsconnector/apigatewayrestapis\": { \"SingularDisplayName\": \"Api Gateway Rest Api\" }\n ,\"microsoft.awsconnector/apigatewaystages\": { \"SingularDisplayName\": \"Api Gateway Stage\" }\n ,\"microsoft.awsconnector/applicationautoscalingscalabletargets\": { \"SingularDisplayName\": \"Application Auto Scaling Scalable Target\" }\n ,\"microsoft.awsconnector/appsyncgraphqlapis\": { \"SingularDisplayName\": \"App Sync Graphql Api\" }\n ,\"microsoft.awsconnector/autoscalingautoscalinggroups\": { \"SingularDisplayName\": \"Auto Scaling Auto Scaling Group\" }\n ,\"microsoft.awsconnector/cloudformationstacks\": { \"SingularDisplayName\": \"Cloud Formation Stack\" }\n ,\"microsoft.awsconnector/cloudformationstacksets\": { \"SingularDisplayName\": \"Cloud Formation Stack Set\" }\n ,\"microsoft.awsconnector/cloudfrontdistributions\": { \"SingularDisplayName\": \"Cloud Front Distribution\" }\n ,\"microsoft.awsconnector/cloudtrailtrails\": { \"SingularDisplayName\": \"Cloud Trail Trail\" }\n ,\"microsoft.awsconnector/cloudwatchalarms\": { \"SingularDisplayName\": \"Cloud Watch Alarm\" }\n ,\"microsoft.awsconnector/codebuildprojects\": { \"SingularDisplayName\": \"Code Build Project\" }\n ,\"microsoft.awsconnector/codebuildsourcecredentialsinfos\": { \"SingularDisplayName\": \"Code Build Source Credentials Info\" }\n ,\"microsoft.awsconnector/configserviceconfigurationrecorders\": { \"SingularDisplayName\": \"Config Service Configuration Recorder\" }\n ,\"microsoft.awsconnector/configserviceconfigurationrecorderstatuses\": { \"SingularDisplayName\": \"Config Service Configuration Recorder Status\" }\n ,\"microsoft.awsconnector/configservicedeliverychannels\": { \"SingularDisplayName\": \"Config Service Delivery Channel\" }\n ,\"microsoft.awsconnector/databasemigrationservicereplicationinstances\": { \"SingularDisplayName\": \"Database Migration Service Replication Instance\" }\n ,\"microsoft.awsconnector/daxclusters\": { \"SingularDisplayName\": \"DAX Cluster\" }\n ,\"microsoft.awsconnector/dynamodbcontinuousbackupsdescriptions\": { \"SingularDisplayName\": \"Dynamo DB Continuous Backups Description\" }\n ,\"microsoft.awsconnector/dynamodbtables\": { \"SingularDisplayName\": \"Dynamo DB Table\" }\n ,\"microsoft.awsconnector/ec2accountattributes\": { \"SingularDisplayName\": \"EC2 Account Attribute\" }\n ,\"microsoft.awsconnector/ec2addresses\": { \"SingularDisplayName\": \"EC2 Address\" }\n ,\"microsoft.awsconnector/ec2flowlogs\": { \"SingularDisplayName\": \"EC2 Flow Log\" }\n ,\"microsoft.awsconnector/ec2images\": { \"SingularDisplayName\": \"EC2 Image\" }\n ,\"microsoft.awsconnector/ec2instances\": { \"SingularDisplayName\": \"Microsoft.AwsConnector ec2 instance\" }\n ,\"microsoft.awsconnector/ec2instancestatuses\": { \"SingularDisplayName\": \"EC2 Instance Status\" }\n ,\"microsoft.awsconnector/ec2ipams\": { \"SingularDisplayName\": \"EC2 Ipam\" }\n ,\"microsoft.awsconnector/ec2keypairs\": { \"SingularDisplayName\": \"EC2 Key Pair\" }\n ,\"microsoft.awsconnector/ec2networkacls\": { \"SingularDisplayName\": \"EC2 Network Acl\" }\n ,\"microsoft.awsconnector/ec2networkinterfaces\": { \"SingularDisplayName\": \"EC2 Network Interface\" }\n ,\"microsoft.awsconnector/ec2routetables\": { \"SingularDisplayName\": \"EC2 Route Table\" }\n ,\"microsoft.awsconnector/ec2securitygroups\": { \"SingularDisplayName\": \"EC2 Security Group\" }\n ,\"microsoft.awsconnector/ec2snapshots\": { \"SingularDisplayName\": \"EC2 Snapshot\" }\n ,\"microsoft.awsconnector/ec2subnets\": { \"SingularDisplayName\": \"EC2 Subnet\" }\n ,\"microsoft.awsconnector/ec2volumes\": { \"SingularDisplayName\": \"EC2 Volume\" }\n ,\"microsoft.awsconnector/ec2vpcendpoints\": { \"SingularDisplayName\": \"EC2 VPCEndpoint\" }\n ,\"microsoft.awsconnector/ec2vpcpeeringconnections\": { \"SingularDisplayName\": \"EC2 VPCPeering Connection\" }\n ,\"microsoft.awsconnector/ec2vpcs\": { \"SingularDisplayName\": \"EC2 VPC\" }\n ,\"microsoft.awsconnector/ecrimagedetails\": { \"SingularDisplayName\": \"ECR Image Detail\" }\n ,\"microsoft.awsconnector/ecrrepositories\": { \"SingularDisplayName\": \"ECR Repository\" }\n ,\"microsoft.awsconnector/ecsclusters\": { \"SingularDisplayName\": \"ECS Cluster\" }\n ,\"microsoft.awsconnector/ecsservices\": { \"SingularDisplayName\": \"ECS Service\" }\n ,\"microsoft.awsconnector/ecstaskdefinitions\": { \"SingularDisplayName\": \"ECS Task Definition\" }\n ,\"microsoft.awsconnector/efsfilesystems\": { \"SingularDisplayName\": \"EFS File System\" }\n ,\"microsoft.awsconnector/efsmounttargets\": { \"SingularDisplayName\": \"EFS Mount Target\" }\n ,\"microsoft.awsconnector/eksnodegroups\": { \"SingularDisplayName\": \"EKS Nodegroup\" }\n ,\"microsoft.awsconnector/elasticbeanstalkapplications\": { \"SingularDisplayName\": \"Elastic Beanstalk Application\" }\n ,\"microsoft.awsconnector/elasticbeanstalkconfigurationtemplates\": { \"SingularDisplayName\": \"Elastic Beanstalk Configuration Template\" }\n ,\"microsoft.awsconnector/elasticbeanstalkenvironments\": { \"SingularDisplayName\": \"Elastic Beanstalk Environment\" }\n ,\"microsoft.awsconnector/elasticloadbalancingv2listeners\": { \"SingularDisplayName\": \"Elastic Load Balancing V2 Listener\" }\n ,\"microsoft.awsconnector/elasticloadbalancingv2loadbalancers\": { \"SingularDisplayName\": \"Elastic Load Balancing V2 Load Balancer\" }\n ,\"microsoft.awsconnector/elasticloadbalancingv2targetgroups\": { \"SingularDisplayName\": \"Elastic Load Balancing V2 Target Group\" }\n ,\"microsoft.awsconnector/elasticloadbalancingv2targethealthdescriptions\": { \"SingularDisplayName\": \"Elastic Load Balancing v2 Target Health Description\" }\n ,\"microsoft.awsconnector/elasticsearchdomains\": { \"SingularDisplayName\": \"Elasticsearch Domain\" }\n ,\"microsoft.awsconnector/emrclusters\": { \"SingularDisplayName\": \"EMR Cluster\" }\n ,\"microsoft.awsconnector/guarddutydetectors\": { \"SingularDisplayName\": \"Guard Duty Detector\" }\n ,\"microsoft.awsconnector/iamaccesskeylastuseds\": { \"SingularDisplayName\": \"IAM Access Key Last Used\" }\n ,\"microsoft.awsconnector/iamaccesskeymetadata\": { \"SingularDisplayName\": \"IAM Access Key Metadata\" }\n ,\"microsoft.awsconnector/iamgroups\": { \"SingularDisplayName\": \"IAM Group\" }\n ,\"microsoft.awsconnector/iaminstanceprofiles\": { \"SingularDisplayName\": \"IAM Instance Profile\" }\n ,\"microsoft.awsconnector/iammanagedpolicies\": { \"SingularDisplayName\": \"IAM Managed Policy\" }\n ,\"microsoft.awsconnector/iammfadevices\": { \"SingularDisplayName\": \"IAM MFADevice\" }\n ,\"microsoft.awsconnector/iampasswordpolicies\": { \"SingularDisplayName\": \"IAM Password Policy\" }\n ,\"microsoft.awsconnector/iampolicyversions\": { \"SingularDisplayName\": \"IAM Policy Version\" }\n ,\"microsoft.awsconnector/iamroles\": { \"SingularDisplayName\": \"IAM Role\" }\n ,\"microsoft.awsconnector/iamservercertificates\": { \"SingularDisplayName\": \"IAM Server Certificate\" }\n ,\"microsoft.awsconnector/iamuserpolicies\": { \"SingularDisplayName\": \"IAM User Policy\" }\n ,\"microsoft.awsconnector/iamvirtualmfadevices\": { \"SingularDisplayName\": \"IAM Virtual MFADevice\" }\n ,\"microsoft.awsconnector/kmsaliases\": { \"SingularDisplayName\": \"KMS Alias\" }\n ,\"microsoft.awsconnector/kmskeys\": { \"SingularDisplayName\": \"KMS Key\" }\n ,\"microsoft.awsconnector/lambdafunctioncodelocations\": { \"SingularDisplayName\": \"Lambda Function Code Location\" }\n ,\"microsoft.awsconnector/lambdafunctionconfigurations\": { \"SingularDisplayName\": \"Microsoft.AwsConnector lambda function configuration\" }\n ,\"microsoft.awsconnector/lambdafunctions\": { \"SingularDisplayName\": \"Lambda Function\" }\n ,\"microsoft.awsconnector/licensemanagerlicenses\": { \"SingularDisplayName\": \"License Manager License\" }\n ,\"microsoft.awsconnector/lightsailbuckets\": { \"SingularDisplayName\": \"Lightsail Bucket\" }\n ,\"microsoft.awsconnector/lightsailinstances\": { \"SingularDisplayName\": \"Lightsail Instance\" }\n ,\"microsoft.awsconnector/logsloggroups\": { \"SingularDisplayName\": \"Logs Log Group\" }\n ,\"microsoft.awsconnector/logslogstreams\": { \"SingularDisplayName\": \"Logs Log Stream\" }\n ,\"microsoft.awsconnector/logsmetricfilters\": { \"SingularDisplayName\": \"Logs Metric Filter\" }\n ,\"microsoft.awsconnector/logssubscriptionfilters\": { \"SingularDisplayName\": \"Logs Subscription Filter\" }\n ,\"microsoft.awsconnector/macie2jobsummaries\": { \"SingularDisplayName\": \"Macie2 Job Summary\" }\n ,\"microsoft.awsconnector/macieallowlists\": { \"SingularDisplayName\": \"Macie Allow List\" }\n ,\"microsoft.awsconnector/networkfirewallfirewallpolicies\": { \"SingularDisplayName\": \"Network Firewall Firewall Policy\" }\n ,\"microsoft.awsconnector/networkfirewallfirewalls\": { \"SingularDisplayName\": \"Network Firewall Firewall\" }\n ,\"microsoft.awsconnector/networkfirewallrulegroups\": { \"SingularDisplayName\": \"Network Firewall Rule Group\" }\n ,\"microsoft.awsconnector/opensearchdomainstatuses\": { \"SingularDisplayName\": \"Open Search Domain Status\" }\n ,\"microsoft.awsconnector/opensearchservicedomains\": { \"SingularDisplayName\": \"Open Search Service Domain\" }\n ,\"microsoft.awsconnector/organizationsaccounts\": { \"SingularDisplayName\": \"Organizations Account\" }\n ,\"microsoft.awsconnector/organizationsorganizations\": { \"SingularDisplayName\": \"Organizations Organization\" }\n ,\"microsoft.awsconnector/rdsdbclusters\": { \"SingularDisplayName\": \"RDS DBCluster\" }\n ,\"microsoft.awsconnector/rdsdbinstances\": { \"SingularDisplayName\": \"RDS DBInstance\" }\n ,\"microsoft.awsconnector/rdsdbsnapshotattributesresults\": { \"SingularDisplayName\": \"RDS DBSnapshot Attributes Result\" }\n ,\"microsoft.awsconnector/rdsdbsnapshots\": { \"SingularDisplayName\": \"RDS DBSnapshot\" }\n ,\"microsoft.awsconnector/rdseventsubscriptions\": { \"SingularDisplayName\": \"RDS Event Subscription\" }\n ,\"microsoft.awsconnector/rdsexporttasks\": { \"SingularDisplayName\": \"RDS Export Task\" }\n ,\"microsoft.awsconnector/redshiftclusterparametergroups\": { \"SingularDisplayName\": \"Redshift Cluster Parameter Group\" }\n ,\"microsoft.awsconnector/redshiftclusters\": { \"SingularDisplayName\": \"Redshift Cluster\" }\n ,\"microsoft.awsconnector/route53domainsdomainsummaries\": { \"SingularDisplayName\": \"Route 53 Domains Domain Summary\" }\n ,\"microsoft.awsconnector/route53hostedzones\": { \"SingularDisplayName\": \"Route53 Hosted Zone\" }\n ,\"microsoft.awsconnector/route53resourcerecordsets\": { \"SingularDisplayName\": \"Route 53 Resource Record Set\" }\n ,\"microsoft.awsconnector/s3accesscontrolpolicies\": { \"SingularDisplayName\": \"S3 Access Control Policy\" }\n ,\"microsoft.awsconnector/s3accesspoints\": { \"SingularDisplayName\": \"S3 Access Point\" }\n ,\"microsoft.awsconnector/s3bucketpolicies\": { \"SingularDisplayName\": \"S3 Bucket Policy\" }\n ,\"microsoft.awsconnector/s3buckets\": { \"SingularDisplayName\": \"S3 Bucket\" }\n ,\"microsoft.awsconnector/s3controlmultiregionaccesspointpolicydocuments\": { \"SingularDisplayName\": \"S3 Control Multi Region Access Point Policy Document\" }\n ,\"microsoft.awsconnector/sagemakerapps\": { \"SingularDisplayName\": \"Sage Maker App\" }\n ,\"microsoft.awsconnector/sagemakerdevices\": { \"SingularDisplayName\": \"Sage Maker Device\" }\n ,\"microsoft.awsconnector/sagemakerimages\": { \"SingularDisplayName\": \"Sage Maker Image\" }\n ,\"microsoft.awsconnector/sagemakernotebookinstancesummaries\": { \"SingularDisplayName\": \"Sage Maker Notebook Instance Summary\" }\n ,\"microsoft.awsconnector/secretsmanagerresourcepolicies\": { \"SingularDisplayName\": \"Secrets Manager Resource Policy\" }\n ,\"microsoft.awsconnector/secretsmanagersecrets\": { \"SingularDisplayName\": \"Secrets Manager Secret\" }\n ,\"microsoft.awsconnector/snssubscriptions\": { \"SingularDisplayName\": \"SNS Subscription\" }\n ,\"microsoft.awsconnector/snstopics\": { \"SingularDisplayName\": \"SNS Topic\" }\n ,\"microsoft.awsconnector/sqsqueues\": { \"SingularDisplayName\": \"SQS Queue\" }\n ,\"microsoft.awsconnector/ssminstanceinformations\": { \"SingularDisplayName\": \"SSM Instance Information\" }\n ,\"microsoft.awsconnector/ssmparameters\": { \"SingularDisplayName\": \"SSM Parameter\" }\n ,\"microsoft.awsconnector/ssmresourcecompliancesummaryitems\": { \"SingularDisplayName\": \"SSM Resource Compliance Summary Item\" }\n ,\"microsoft.awsconnector/wafv2ipsets\": { \"SingularDisplayName\": \"WAFv2 IPSet\" }\n ,\"microsoft.awsconnector/wafv2loggingconfigurations\": { \"SingularDisplayName\": \"WAFv2 Logging Configuration\" }\n ,\"microsoft.awsconnector/wafv2webaclassociations\": { \"SingularDisplayName\": \"WAFv2 Web ACLAssociation\" }\n ,\"microsoft.awsconnector/wafwebaclsummaries\": { \"SingularDisplayName\": \"WAF Web ACLSummary\" }\n ,\"microsoft.azureactivedirectory/b2cdirectories\": { \"SingularDisplayName\": \"B2C tenant\" }\n ,\"microsoft.azureactivedirectory/ciamdirectories\": { \"SingularDisplayName\": \"External Configuration Tenant\" }\n ,\"microsoft.azureactivedirectory/guestusages\": { \"SingularDisplayName\": \"Guest Usage\" }\n ,\"microsoft.azurearcdata/datacontrollers\": { \"SingularDisplayName\": \"Azure Arc data controller\" }\n ,\"microsoft.azurearcdata/mysqlserver\": { \"SingularDisplayName\": \"MySql Server - Azure Arc\" }\n ,\"microsoft.azurearcdata/postgresinstances\": { \"SingularDisplayName\": \"PostgreSQL server ? Azure Arc\" }\n ,\"microsoft.azurearcdata/postgressqlserver\": { \"SingularDisplayName\": \"PostgresSql Server - Azure Arc\" }\n ,\"microsoft.azurearcdata/sqlmanagedinstances\": { \"SingularDisplayName\": \"SQL managed instance - Azure Arc\" }\n ,\"microsoft.azurearcdata/sqlserveresulicenses\": { \"SingularDisplayName\": \"SQL Server ESU license\" }\n ,\"microsoft.azurearcdata/sqlserverinstances\": { \"SingularDisplayName\": \"SQL Server - Azure Arc\" }\n ,\"microsoft.azurearcdata/sqlserverinstances/databases\": { \"SingularDisplayName\": \"SQL Server database - Azure Arc\" }\n ,\"microsoft.azurearcdata/sqlserverlicenses\": { \"SingularDisplayName\": \"SQL Server License\" }\n ,\"microsoft.azurebusinesscontinuity/deletedunifiedprotecteditems\": { \"SingularDisplayName\": \"Microsoft.AzureBusinessContinuity deleted unified protected item\" }\n ,\"microsoft.azurebusinesscontinuity/unifiedprotecteditems\": { \"SingularDisplayName\": \"Microsoft.AzureBusinessContinuity unified protected item\" }\n ,\"microsoft.azurecis/aadapplications\": { \"SingularDisplayName\": \"Microsoft.AzureCis AAD application\" }\n ,\"microsoft.azurecis/addressrecords\": { \"SingularDisplayName\": \"Microsoft.AzureCis address record\" }\n ,\"microsoft.azurecis/autopilotenvironments\": { \"SingularDisplayName\": \"Microsoft.AzureCis autopilot environment\" }\n ,\"microsoft.azurecis/autopilotmachinefunctions\": { \"SingularDisplayName\": \"Microsoft.AzureCis autopilot machine function\" }\n ,\"microsoft.azurecis/autopilotsoftwareloadbalancevirtualips\": { \"SingularDisplayName\": \"Microsoft.AzureCis auto pilot software load balance virtual IP\" }\n ,\"microsoft.azurecis/azcopies\": { \"SingularDisplayName\": \"Microsoft.AzureCis az copy\" }\n ,\"microsoft.azurecis/canonicalnamerecords\": { \"SingularDisplayName\": \"Microsoft.AzureCis canonical name record\" }\n ,\"microsoft.azurecis/dsmsallowlists\": { \"SingularDisplayName\": \"Microsoft.AzureCis ds msallowlist\" }\n ,\"microsoft.azurecis/dsmscertificates\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsms certificate\" }\n ,\"microsoft.azurecis/dsmsrootfolders\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsms root folder\" }\n ,\"microsoft.azurecis/dstsapplications\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsts application\" }\n ,\"microsoft.azurecis/dstsserviceaccounts\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsts service account\" }\n ,\"microsoft.azurecis/dstsserviceclientidentities\": { \"SingularDisplayName\": \"Microsoft.AzureCis dsts service client identity\" }\n ,\"microsoft.azurecis/genericgenevaactions\": { \"SingularDisplayName\": \"Microsoft.AzureCis generic geneva action\" }\n ,\"microsoft.azurecis/plannedquotas\": { \"SingularDisplayName\": \"Microsoft.AzureCis planned quota\" }\n ,\"microsoft.azurecis/pointerrecords\": { \"SingularDisplayName\": \"Microsoft.AzureCis pointer record\" }\n ,\"microsoft.azurecis/publishconfigvalues\": { \"SingularDisplayName\": \"Microsoft.AzureCis publish config value\" }\n ,\"microsoft.azurecis/pushagentv2accounts\": { \"SingularDisplayName\": \"Microsoft.AzureCis push agent v2 account\" }\n ,\"microsoft.azurecis/servicerecords\": { \"SingularDisplayName\": \"Microsoft.AzureCis service record\" }\n ,\"microsoft.azurecis/sharedconfigvalues\": { \"SingularDisplayName\": \"Microsoft.AzureCis shared config value\" }\n ,\"microsoft.azurecloudmetadata/clouds\": { \"SingularDisplayName\": \"Microsoft.AzureCloudMetadata cloud\" }\n ,\"microsoft.azurecloudmetadata/clouds/geographies\": { \"SingularDisplayName\": \"Microsoft.AzureCloudMetadata clouds geography\" }\n ,\"microsoft.azurecloudmetadata/clouds/geographies/regions\": { \"SingularDisplayName\": \"Microsoft.AzureCloudMetadata clouds geographies region\" }\n ,\"microsoft.azuredatatransfer/connections\": { \"SingularDisplayName\": \"Connection\" }\n ,\"microsoft.azuredatatransfer/connections/flows\": { \"SingularDisplayName\": \"Flow\" }\n ,\"microsoft.azuredatatransfer/pipelines\": { \"SingularDisplayName\": \"Pipeline\" }\n ,\"microsoft.azurefleet/fleets\": { \"SingularDisplayName\": \"Compute Fleet\" }\n ,\"microsoft.azurefleet/fleetscomputehub\": { \"SingularDisplayName\": \"Compute Fleet\" }\n ,\"microsoft.azureimagetestingforlinux/jobs\": { \"SingularDisplayName\": \"Microsoft.AzureImageTestingForLinux job\" }\n ,\"microsoft.azureimagetestingforlinux/jobtemplates\": { \"SingularDisplayName\": \"Microsoft.AzureImageTestingForLinux job template\" }\n ,\"microsoft.azurelargeinstance/azurelargeinstances\": { \"SingularDisplayName\": \"Azure Large Instance\" }\n ,\"microsoft.azurelargeinstance/azurelargestorageinstances\": { \"SingularDisplayName\": \"Microsoft.AzureLargeInstance Azure large storage instance\" }\n ,\"microsoft.azurepercept/accounts\": { \"SingularDisplayName\": \"Microsoft.AzurePercept account\" }\n ,\"microsoft.azurepercept/accounts/devices\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts device\" }\n ,\"microsoft.azurepercept/accounts/devices/sensors\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts devices sensor\" }\n ,\"microsoft.azurepercept/accounts/sensors\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts sensor\" }\n ,\"microsoft.azurepercept/accounts/solutioninstances\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts solutioninstance\" }\n ,\"microsoft.azurepercept/accounts/solutions\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts solution\" }\n ,\"microsoft.azurepercept/accounts/targets\": { \"SingularDisplayName\": \"Microsoft.AzurePercept accounts target\" }\n ,\"microsoft.azureplaywrightservice/accounts\": { \"SingularDisplayName\": \"Playwright Testing\" }\n ,\"microsoft.azurescan/scanningaccounts\": { \"SingularDisplayName\": \"ESRP Scan\" }\n ,\"microsoft.azuresphere/catalogs\": { \"SingularDisplayName\": \"Azure Sphere Catalog\" }\n ,\"microsoft.azurespherev2/catalogs\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalog\" }\n ,\"microsoft.azurespherev2/catalogs/artifacts\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs artifact\" }\n ,\"microsoft.azurespherev2/catalogs/certificates\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs certificate\" }\n ,\"microsoft.azurespherev2/catalogs/deviceregistrations\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs device registration\" }\n ,\"microsoft.azurespherev2/catalogs/provisioningpackages\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs provisioning package\" }\n ,\"microsoft.azurespherev2/catalogs/syndicationchannels\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs syndication channel\" }\n ,\"microsoft.azurespherev2/catalogs/syndicationchannels/deployments\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs syndication channels deployment\" }\n ,\"microsoft.azurespherev2/catalogs/updatepackages\": { \"SingularDisplayName\": \"Microsoft.AzureSphereV2 catalogs update package\" }\n ,\"microsoft.azurestack/cloudmanifestfiles\": { \"SingularDisplayName\": \"Microsoft.AzureStack cloud manifest file\" }\n ,\"microsoft.azurestack/linkedsubscriptions\": { \"SingularDisplayName\": \"Microsoft.AzureStack linked subscription\" }\n ,\"microsoft.azurestack/registrations\": { \"SingularDisplayName\": \"Microsoft.AzureStack registration\" }\n ,\"microsoft.azurestack/registrations/customersubscriptions\": { \"SingularDisplayName\": \"Microsoft.AzureStack registrations customer subscription\" }\n ,\"microsoft.azurestack/registrations/products\": { \"SingularDisplayName\": \"Microsoft.AzureStack registrations product\" }\n ,\"microsoft.azurestackhci/clusters\": { \"SingularDisplayName\": \"Azure Local\" }\n ,\"microsoft.azurestackhci/clusters/updates/updateruns\": { \"SingularDisplayName\": \"Azure Local\" }\n ,\"microsoft.azurestackhci/clusters/updatesummaries\": { \"SingularDisplayName\": \"Azure Local\" }\n ,\"microsoft.azurestackhci/devicepools\": { \"SingularDisplayName\": \"Azure Stack\" }\n ,\"microsoft.azurestackhci/edgedevices\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI edge device\" }\n ,\"microsoft.azurestackhci/edgedevices/jobs\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI edge devices job\" }\n ,\"microsoft.azurestackhci/edgemachines\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI edge machine\" }\n ,\"microsoft.azurestackhci/edgemachines/jobs\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI edge machines job\" }\n ,\"microsoft.azurestackhci/edgenodepools\": { \"SingularDisplayName\": \"Azure Stack\" }\n ,\"microsoft.azurestackhci/galleryimages\": { \"SingularDisplayName\": \"Azure Local Gallery image\" }\n ,\"microsoft.azurestackhci/logicalnetworks\": { \"SingularDisplayName\": \"Azure Local Logical network\" }\n ,\"microsoft.azurestackhci/marketplacegalleryimages\": { \"SingularDisplayName\": \"Azure Local Marketplace Gallery image\" }\n ,\"microsoft.azurestackhci/networkinterfaces\": { \"SingularDisplayName\": \"Azure Local VM Network Interface\" }\n ,\"microsoft.azurestackhci/networksecuritygroups\": { \"SingularDisplayName\": \"Azure Local Network Security Group\" }\n ,\"microsoft.azurestackhci/networksecuritygroups/securityrules\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI network security groups security rule\" }\n ,\"microsoft.azurestackhci/storagecontainers\": { \"SingularDisplayName\": \"Azure Local Storage path\" }\n ,\"microsoft.azurestackhci/virtualharddisks\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual hard disk\" }\n ,\"microsoft.azurestackhci/virtualmachineinstances\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual machine instance\" }\n ,\"microsoft.azurestackhci/virtualmachineinstances/guestagents\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual machine instances guest agent\" }\n ,\"microsoft.azurestackhci/virtualmachineinstances/hybrididentitymetadata\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual machine instances hybrid identity metadata\" }\n ,\"microsoft.azurestackhci/virtualmachines\": { \"SingularDisplayName\": \"Azure Local virtual machine - Azure Arc\" }\n ,\"microsoft.azurestackhci/virtualnetworks\": { \"SingularDisplayName\": \"Microsoft.AzureStackHCI virtual network\" }\n ,\"microsoft.backupsolutions/vmwareapplications\": { \"SingularDisplayName\": \"Microsoft.BackupSolutions vmware application\" }\n ,\"microsoft.bakeryhybrid/pies\": { \"SingularDisplayName\": \"Microsoft.BakeryHybrid py\" }\n ,\"microsoft.bakeryhybrid/pies/nestedresourcetype\": { \"SingularDisplayName\": \"Microsoft.BakeryHybrid pies nested resource type\" }\n ,\"microsoft.baremetal/baremetalconnections\": { \"SingularDisplayName\": \"Microsoft.BareMetal bare metal connection\" }\n ,\"microsoft.baremetal/crayservers\": { \"SingularDisplayName\": \"Cray Server\" }\n ,\"microsoft.baremetal/monitoringservers\": { \"SingularDisplayName\": \"Monitoring Server\" }\n ,\"microsoft.baremetal/peeringsettings\": { \"SingularDisplayName\": \"Microsoft.BareMetal peering setting\" }\n ,\"microsoft.baremetalinfrastructure/baremetalinstances\": { \"SingularDisplayName\": \"BareMetal Instance\" }\n ,\"microsoft.baremetalinfrastructure/baremetalstorageinstances\": { \"SingularDisplayName\": \"Microsoft.BareMetalInfrastructure bare metal storage instance\" }\n ,\"microsoft.batch/batchaccounts\": { \"SingularDisplayName\": \"Batch account\" }\n ,\"microsoft.billing/billingaccounts\": { \"SingularDisplayName\": \"Microsoft.Billing billing account\" }\n ,\"microsoft.billing/billingaccounts/agreements\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts agreement\" }\n ,\"microsoft.billing/billingaccounts/associatedtenants\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts associated tenant\" }\n ,\"microsoft.billing/billingaccounts/availablebalance\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts available balance\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profile\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/availablebalance\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles available balance\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles billing role definition\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles billing subscription\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/customers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles customer\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/customers/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles customers billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/customers/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles customers billing role definition\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/customers/transfers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles customers transfer\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/instructions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles instruction\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoices\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice section\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections billing role definition\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections billing subscription\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/products\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections product\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/invoicesections/transfers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles invoice sections transfer\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/paymentmethodlinks\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles payment method link\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/policies\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles policy\" }\n ,\"microsoft.billing/billingaccounts/billingprofiles/transactions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing profiles transaction\" }\n ,\"microsoft.billing/billingaccounts/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing role definition\" }\n ,\"microsoft.billing/billingaccounts/billingsubscriptionaliases\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing subscription aliase\" }\n ,\"microsoft.billing/billingaccounts/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing subscription\" }\n ,\"microsoft.billing/billingaccounts/billingsubscriptions/invoices\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts billing subscriptions invoice\" }\n ,\"microsoft.billing/billingaccounts/customers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts customer\" }\n ,\"microsoft.billing/billingaccounts/customers/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts customers billing subscription\" }\n ,\"microsoft.billing/billingaccounts/customers/policies\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts customers policy\" }\n ,\"microsoft.billing/billingaccounts/customers/products\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts customers product\" }\n ,\"microsoft.billing/billingaccounts/departments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts department\" }\n ,\"microsoft.billing/billingaccounts/departments/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts departments billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/departments/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts departments billing role definition\" }\n ,\"microsoft.billing/billingaccounts/departments/enrollmentaccounts\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts departments enrollment account\" }\n ,\"microsoft.billing/billingaccounts/enrollmentaccounts\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts enrollment account\" }\n ,\"microsoft.billing/billingaccounts/enrollmentaccounts/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts enrollment accounts billing role assignment\" }\n ,\"microsoft.billing/billingaccounts/enrollmentaccounts/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts enrollment accounts billing role definition\" }\n ,\"microsoft.billing/billingaccounts/incentiveschedules\": { \"SingularDisplayName\": \"Incentive Schedule\" }\n ,\"microsoft.billing/billingaccounts/incentiveschedules/milestones\": { \"SingularDisplayName\": \"Milestone\" }\n ,\"microsoft.billing/billingaccounts/invoices\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice\" }\n ,\"microsoft.billing/billingaccounts/invoicesections\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice section\" }\n ,\"microsoft.billing/billingaccounts/invoicesections/billingsubscriptions\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice sections billing subscription\" }\n ,\"microsoft.billing/billingaccounts/invoicesections/products\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice sections product\" }\n ,\"microsoft.billing/billingaccounts/invoicesections/transfers\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts invoice sections transfer\" }\n ,\"microsoft.billing/billingaccounts/lineofcredit\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts line of credit\" }\n ,\"microsoft.billing/billingaccounts/migrations\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts migration\" }\n ,\"microsoft.billing/billingaccounts/paymentmethods\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts payment method\" }\n ,\"microsoft.billing/billingaccounts/policies\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts policy\" }\n ,\"microsoft.billing/billingaccounts/products\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts product\" }\n ,\"microsoft.billing/billingaccounts/reservationorders\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts reservation order\" }\n ,\"microsoft.billing/billingaccounts/reservationorders/reservations\": { \"SingularDisplayName\": \"Microsoft.Billing billing accounts reservation orders reservation\" }\n ,\"microsoft.billing/billingaccounts/savingsplanorders\": { \"SingularDisplayName\": \"Savings plan order\" }\n ,\"microsoft.billing/billingaccounts/savingsplanorders/savingsplans\": { \"SingularDisplayName\": \"Savings plan\" }\n ,\"microsoft.billing/billingperiods\": { \"SingularDisplayName\": \"Microsoft.Billing billing period\" }\n ,\"microsoft.billing/billingproperty\": { \"SingularDisplayName\": \"Microsoft.Billing billing property\" }\n ,\"microsoft.billing/billingrequests\": { \"SingularDisplayName\": \"Microsoft.Billing billing request\" }\n ,\"microsoft.billing/billingroleassignments\": { \"SingularDisplayName\": \"Microsoft.Billing billing role assignment\" }\n ,\"microsoft.billing/billingroledefinitions\": { \"SingularDisplayName\": \"Microsoft.Billing billing role definition\" }\n ,\"microsoft.billing/enrollmentaccounts\": { \"SingularDisplayName\": \"Microsoft.Billing enrollment account\" }\n ,\"microsoft.billing/paymentmethods\": { \"SingularDisplayName\": \"Microsoft.Billing payment method\" }\n ,\"microsoft.billing/policies\": { \"SingularDisplayName\": \"Microsoft.Billing policy\" }\n ,\"microsoft.billing/promotions\": { \"SingularDisplayName\": \"Microsoft.Billing promotion\" }\n ,\"microsoft.billing/transfers\": { \"SingularDisplayName\": \"Microsoft.Billing transfer\" }\n ,\"microsoft.billingbenefits/credits\": { \"SingularDisplayName\": \"Credit\" }\n ,\"microsoft.billingbenefits/discounts\": { \"SingularDisplayName\": \"Discount\" }\n ,\"microsoft.billingbenefits/incentiveschedules\": { \"SingularDisplayName\": \"Incentive Schedule\" }\n ,\"microsoft.billingbenefits/incentiveschedules/milestones\": { \"SingularDisplayName\": \"Milestone\" }\n ,\"microsoft.billingbenefits/maccs\": { \"SingularDisplayName\": \"Microsoft Azure Consumption Commitment\" }\n ,\"microsoft.billingbenefits/reservationorderaliases\": { \"SingularDisplayName\": \"Microsoft.BillingBenefits reservation order aliase\" }\n ,\"microsoft.billingbenefits/savingsplanorderaliases\": { \"SingularDisplayName\": \"Microsoft.BillingBenefits savings plan order aliase\" }\n ,\"microsoft.billingbenefits/savingsplanorders\": { \"SingularDisplayName\": \"Savings plan order\" }\n ,\"microsoft.billingbenefits/savingsplanorders/savingsplans\": { \"SingularDisplayName\": \"Savings plan\" }\n ,\"microsoft.bing/accounts\": { \"SingularDisplayName\": \"Bing Resource\" }\n ,\"microsoft.blockchain/blockchainmembers\": { \"SingularDisplayName\": \"Microsoft.Blockchain blockchain member\" }\n ,\"microsoft.blockchain/blockchainmembers/transactionnodes\": { \"SingularDisplayName\": \"Microsoft.Blockchain blockchain members transaction node\" }\n ,\"microsoft.blockchaintokens/tokenservices\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token service\" }\n ,\"microsoft.blockchaintokens/tokenservices/blockchainnetworks\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token services blockchain network\" }\n ,\"microsoft.blockchaintokens/tokenservices/groups\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token services group\" }\n ,\"microsoft.blockchaintokens/tokenservices/groups/accounts\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token services groups account\" }\n ,\"microsoft.blockchaintokens/tokenservices/tokentemplates\": { \"SingularDisplayName\": \"Microsoft.BlockchainTokens token services token template\" }\n ,\"microsoft.bluefin/instances\": { \"SingularDisplayName\": \"Microsoft.Bluefin instance\" }\n ,\"microsoft.bluefin/instances/datasets\": { \"SingularDisplayName\": \"Microsoft.Bluefin instances dataset\" }\n ,\"microsoft.bluefin/instances/pipelines\": { \"SingularDisplayName\": \"Microsoft.Bluefin instances pipeline\" }\n ,\"microsoft.blueprint/blueprintassignments\": { \"SingularDisplayName\": \"Microsoft.Blueprint blueprint assignment\" }\n ,\"microsoft.blueprint/blueprints\": { \"SingularDisplayName\": \"Microsoft.Blueprint blueprint\" }\n ,\"microsoft.blueprint/blueprints/artifacts\": { \"SingularDisplayName\": \"Microsoft.Blueprint blueprints artifact\" }\n ,\"microsoft.blueprint/blueprints/versions\": { \"SingularDisplayName\": \"Microsoft.Blueprint blueprints version\" }\n ,\"microsoft.botservice/botservices\": { \"SingularDisplayName\": \"Bot Service\" }\n ,\"microsoft.cache/redis\": { \"SingularDisplayName\": \"Redis cache\" }\n ,\"microsoft.cache/redisenterprise\": { \"SingularDisplayName\": \"Azure Managed Redis\" }\n ,\"microsoft.cache/redisenterprise/databases\": { \"SingularDisplayName\": \"Redis Enterprise database\" }\n ,\"microsoft.capacity/reservationorders\": { \"SingularDisplayName\": \"Reservation order\" }\n ,\"microsoft.capacity/reservationorders/reservations\": { \"SingularDisplayName\": \"Reservation\" }\n ,\"microsoft.cascade/sites\": { \"SingularDisplayName\": \"Microsoft.Cascade site\" }\n ,\"microsoft.cdn/cdnwebapplicationfirewallpolicies\": { \"SingularDisplayName\": \"Content Delivery Network WAF policy\" }\n ,\"microsoft.cdn/edgeactions\": { \"SingularDisplayName\": \"Edge Action\" }\n ,\"microsoft.cdn/profiles\": { \"SingularDisplayName\": \"Front Door and CDN profile\" }\n ,\"microsoft.cdn/profiles/afdendpoints\": { \"SingularDisplayName\": \"Endpoint\" }\n ,\"microsoft.cdn/profiles/afdendpoints/routes\": { \"SingularDisplayName\": \"Route\" }\n ,\"microsoft.cdn/profiles/customdomains\": { \"SingularDisplayName\": \"Custom domain\" }\n ,\"microsoft.cdn/profiles/endpoints\": { \"SingularDisplayName\": \"CDN endpoint\" }\n ,\"microsoft.cdn/profiles/endpoints/customdomains\": { \"SingularDisplayName\": \"CDN custom domain\" }\n ,\"microsoft.cdn/profiles/endpoints/origins\": { \"SingularDisplayName\": \"CDN origin\" }\n ,\"microsoft.cdn/profiles/origingroups\": { \"SingularDisplayName\": \"Origin group\" }\n ,\"microsoft.cdn/profiles/origingroups/origins\": { \"SingularDisplayName\": \"Origin\" }\n ,\"microsoft.cdn/profiles/rulesets\": { \"SingularDisplayName\": \"Rule set\" }\n ,\"microsoft.cdn/profiles/rulesets/rules\": { \"SingularDisplayName\": \"Rule\" }\n ,\"microsoft.cdn/profiles/secrets\": { \"SingularDisplayName\": \"Secret\" }\n ,\"microsoft.cdn/profiles/securitypolicies\": { \"SingularDisplayName\": \"Security policy\" }\n ,\"microsoft.certificateregistration/certificateorders\": { \"SingularDisplayName\": \"App Service certificate\" }\n ,\"microsoft.certify/testsuites\": { \"SingularDisplayName\": \"Microsoft.Certify test suite\" }\n ,\"microsoft.certify/validationjobs\": { \"SingularDisplayName\": \"Microsoft.Certify validation job\" }\n ,\"microsoft.changeanalysis/profile\": { \"SingularDisplayName\": \"Microsoft.ChangeAnalysis profile\" }\n ,\"microsoft.changesafety/changestates\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety change state\" }\n ,\"microsoft.changesafety/changestates/stageprogressions\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety change states stage progression\" }\n ,\"microsoft.changesafety/stagemaps\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety stage map\" }\n ,\"microsoft.changesafety/validations\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety validation\" }\n ,\"microsoft.changesafety/validators\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety validator\" }\n ,\"microsoft.changesafety/validators/versions\": { \"SingularDisplayName\": \"Microsoft.ChangeSafety validators version\" }\n ,\"microsoft.chaos/experiments\": { \"SingularDisplayName\": \"Chaos Experiment\" }\n ,\"microsoft.chaos/privateaccesses\": { \"SingularDisplayName\": \"Agent Private Access\" }\n ,\"microsoft.chaos/targets\": { \"SingularDisplayName\": \"Microsoft.Chaos target\" }\n ,\"microsoft.chaos/targets/capabilities\": { \"SingularDisplayName\": \"Microsoft.Chaos targets capability\" }\n ,\"microsoft.classiccompute/domainnames\": { \"SingularDisplayName\": \"Cloud service (classic)\" }\n ,\"microsoft.classiccompute/domainnames/slots/roles\": { \"SingularDisplayName\": \"Cloud service role (classic)\" }\n ,\"microsoft.classiccompute/virtualmachines\": { \"SingularDisplayName\": \"Virtual machine (classic)\" }\n ,\"microsoft.classicnetwork/networksecuritygroups\": { \"SingularDisplayName\": \"Network security group (classic)\" }\n ,\"microsoft.classicnetwork/reservedips\": { \"SingularDisplayName\": \"Reserved IP address (classic)\" }\n ,\"microsoft.classicnetwork/virtualnetworks\": { \"SingularDisplayName\": \"Virtual network (classic)\" }\n })[tolower(id)]\n}\n", "$fxv#1": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n.create-or-alter function \nwith (docstring = 'Return details about the specified ID.', folder = 'OpenData/Internal')\n_resource_type_2(id: string) {\n dynamic({\n \"microsoft.classicstorage/storageaccounts\": { \"SingularDisplayName\": \"Storage account (classic)\" }\n ,\"microsoft.classicstorage/storageaccounts/disks\": { \"SingularDisplayName\": \"Disk (classic)\" }\n ,\"microsoft.classicstorage/storageaccounts/osimages\": { \"SingularDisplayName\": \"OS image (classic)\" }\n ,\"microsoft.classicstorage/storageaccounts/vmimages\": { \"SingularDisplayName\": \"VM image (classic)\" }\n ,\"microsoft.cleanroom/cleanrooms\": { \"SingularDisplayName\": \"Microsoft.CleanRoom cleanroom\" }\n ,\"microsoft.cleanroom/collaborations\": { \"SingularDisplayName\": \"Microsoft.CleanRoom collaboration\" }\n ,\"microsoft.cleanroom/collaborations/contracts\": { \"SingularDisplayName\": \"Microsoft.CleanRoom collaborations contract\" }\n ,\"microsoft.cleanroom/consortiums\": { \"SingularDisplayName\": \"Microsoft.CleanRoom consortium\" }\n ,\"microsoft.cleanroom/microservices\": { \"SingularDisplayName\": \"Microsoft.CleanRoom microservice\" }\n ,\"microsoft.cloud/hubs\": { \"SingularDisplayName\": \"FinOps hub\" }\n ,\"microsoft.clouddeviceplatform/delegatedidentities\": { \"SingularDisplayName\": \"Microsoft.CloudDevicePlatform delegated identity\" }\n ,\"microsoft.cloudhealth/healthmodels\": { \"SingularDisplayName\": \"Health Model\" }\n ,\"microsoft.cloudtest/accounts\": { \"SingularDisplayName\": \"CloudTest Account\" }\n ,\"microsoft.cloudtest/buildcaches\": { \"SingularDisplayName\": \"1ES Build Cache\" }\n ,\"microsoft.cloudtest/hostedpools\": { \"SingularDisplayName\": \"1ES Hosted Pool\" }\n ,\"microsoft.cloudtest/images\": { \"SingularDisplayName\": \"1ES Image\" }\n ,\"microsoft.cloudtest/pools\": { \"SingularDisplayName\": \"CloudTest Pool\" }\n ,\"microsoft.clusterstor/nodes\": { \"SingularDisplayName\": \"ClusterStor\" }\n ,\"microsoft.codesigning/codesigningaccounts\": { \"SingularDisplayName\": \"Trusted Signing Account\" }\n ,\"microsoft.codespaces/plans\": { \"SingularDisplayName\": \"Microsoft.Codespaces plan\" }\n ,\"microsoft.cognitiveservices/accounts\": { \"SingularDisplayName\": \"Azure AI Foundry\" }\n ,\"microsoft.cognitiveservices/accounts/projects\": { \"SingularDisplayName\": \"Azure AI Foundry project\" }\n ,\"microsoft.cognitiveservices/commitmentplans\": { \"SingularDisplayName\": \"Microsoft.CognitiveServices commitment plan\" }\n ,\"microsoft.cognitiveservices/commitmentplans/accountassociations\": { \"SingularDisplayName\": \"Microsoft.CognitiveServices commitment plans account association\" }\n ,\"microsoft.communication/communicationservices\": { \"SingularDisplayName\": \"Communication Service\" }\n ,\"microsoft.communication/emailservices\": { \"SingularDisplayName\": \"Email Communication Service\" }\n ,\"microsoft.communication/emailservices/domains\": { \"SingularDisplayName\": \"Email Communication Services Domain\" }\n ,\"microsoft.community/communitytrainings\": { \"SingularDisplayName\": \"Community Training\" }\n ,\"microsoft.compositesolutions/compositesolutiondefinitions\": { \"SingularDisplayName\": \"Microsoft.CompositeSolutions composite solution definition\" }\n ,\"microsoft.compositesolutions/compositesolutions\": { \"SingularDisplayName\": \"Microsoft.CompositeSolutions composite solution\" }\n ,\"microsoft.compute/availabilitysets\": { \"SingularDisplayName\": \"Availability set\" }\n ,\"microsoft.compute/capacityreservationgroups\": { \"SingularDisplayName\": \"Capacity Reservation Group\" }\n ,\"microsoft.compute/capacityreservationgroups/capacityreservations\": { \"SingularDisplayName\": \"Capacity reservation\" }\n ,\"microsoft.compute/capacityreservationgroupscomputehub\": { \"SingularDisplayName\": \"Capacity Reservation Group\" }\n ,\"microsoft.compute/cloudservices\": { \"SingularDisplayName\": \"Cloud service (extended support)\" }\n ,\"microsoft.compute/computefleetinstances\": { \"SingularDisplayName\": \"Instance\" }\n ,\"microsoft.compute/computefleetscalesets\": { \"SingularDisplayName\": \"Virtual machine scale set\" }\n ,\"microsoft.compute/diskaccesses\": { \"SingularDisplayName\": \"Disk Access\" }\n ,\"microsoft.compute/diskencryptionsets\": { \"SingularDisplayName\": \"Disk Encryption Set\" }\n ,\"microsoft.compute/disks\": { \"SingularDisplayName\": \"Disk\" }\n ,\"microsoft.compute/galleries\": { \"SingularDisplayName\": \"Azure compute gallery\" }\n ,\"microsoft.compute/galleries/applications\": { \"SingularDisplayName\": \"VM application definition\" }\n ,\"microsoft.compute/galleries/applications/versions\": { \"SingularDisplayName\": \"VM application version\" }\n ,\"microsoft.compute/galleries/images\": { \"SingularDisplayName\": \"VM image definition\" }\n ,\"microsoft.compute/galleries/images/versions\": { \"SingularDisplayName\": \"VM image version\" }\n ,\"microsoft.compute/galleries/imagescomputehub\": { \"SingularDisplayName\": \"VM image definition\" }\n ,\"microsoft.compute/hostgroups\": { \"SingularDisplayName\": \"Host group\" }\n ,\"microsoft.compute/hostgroups/hosts\": { \"SingularDisplayName\": \"Host\" }\n ,\"microsoft.compute/hostgroupscomputehub\": { \"SingularDisplayName\": \"Host group\" }\n ,\"microsoft.compute/images\": { \"SingularDisplayName\": \"Image\" }\n ,\"microsoft.compute/imagescomputehub\": { \"SingularDisplayName\": \"Image\" }\n ,\"microsoft.compute/locations/communitygalleries/images\": { \"SingularDisplayName\": \"Community image\" }\n ,\"microsoft.compute/locations/communitygalleries/imagescomputehub\": { \"SingularDisplayName\": \"Community image\" }\n ,\"microsoft.compute/proximityplacementgroups\": { \"SingularDisplayName\": \"Proximity placement group\" }\n ,\"microsoft.compute/proximityplacementgroupscomputehub\": { \"SingularDisplayName\": \"Proximity placement group\" }\n ,\"microsoft.compute/restorepointcollections\": { \"SingularDisplayName\": \"Restore Point Collection\" }\n ,\"microsoft.compute/restorepointcollections/restorepoints\": { \"SingularDisplayName\": \"Restore Point\" }\n ,\"microsoft.compute/snapshots\": { \"SingularDisplayName\": \"Snapshot\" }\n ,\"microsoft.compute/sshpublickeys\": { \"SingularDisplayName\": \"SSH key\" }\n ,\"microsoft.compute/standbypoolinstance\": { \"SingularDisplayName\": \"Standby pool\" }\n ,\"microsoft.compute/virtualmachinecomputehub\": { \"SingularDisplayName\": \"Virtual machine\" }\n ,\"microsoft.compute/virtualmachineflexinstances\": { \"SingularDisplayName\": \"Instance\" }\n ,\"microsoft.compute/virtualmachines\": { \"SingularDisplayName\": \"Virtual machine\" }\n ,\"microsoft.compute/virtualmachines/providers/guestconfigurationassignments\": { \"SingularDisplayName\": \"Guest Assignment\" }\n ,\"microsoft.compute/virtualmachinescalesets\": { \"SingularDisplayName\": \"Virtual machine scale set\" }\n ,\"microsoft.compute/virtualmachinescalesets/providers/guestconfigurationassignments\": { \"SingularDisplayName\": \"Guest Assignment\" }\n ,\"microsoft.compute/virtualmachinescalesets/virtualmachines\": { \"SingularDisplayName\": \"Virtual machine scale set instance\" }\n ,\"microsoft.compute/virtualmachinescalesets/virtualmachines/networkinterfaces/ipconfigurations/publicipaddresses\": { \"SingularDisplayName\": \"Public IP address\" }\n ,\"microsoft.compute/virtualmachinescalesetscomputehub\": { \"SingularDisplayName\": \"Virtual machine scale set\" }\n ,\"microsoft.computehub/advisorcost\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/advisoroperationalexcellence\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/advisorperformance\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/advisorreliability\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/advisorsecurity\": { \"SingularDisplayName\": \"Recommendations\" }\n ,\"microsoft.computehub/all\": { \"SingularDisplayName\": \"All resources\" }\n ,\"microsoft.computehub/backup\": { \"SingularDisplayName\": \"Backup job\" }\n ,\"microsoft.computehub/computehubmain\": { \"SingularDisplayName\": \"Compute infrastructure\" }\n ,\"microsoft.computehub/healthevents\": { \"SingularDisplayName\": \"Health events\" }\n ,\"microsoft.computehub/linuxostype\": { \"SingularDisplayName\": \"Linux OS\" }\n ,\"microsoft.computehub/microsoftdefenderfreetrialsubscription\": { \"SingularDisplayName\": \"Microsoft defender\" }\n ,\"microsoft.computehub/microsoftdefenderstandardsubscription\": { \"SingularDisplayName\": \"Microsoft defender\" }\n ,\"microsoft.computehub/outages\": { \"SingularDisplayName\": \"Outages\" }\n ,\"microsoft.computehub/powerstatedeallocated\": { \"SingularDisplayName\": \"Power states\" }\n ,\"microsoft.computehub/powerstaterunning\": { \"SingularDisplayName\": \"Power states\" }\n ,\"microsoft.computehub/powerstatestopped\": { \"SingularDisplayName\": \"Power states\" }\n ,\"microsoft.computehub/provisioningstatefailedresources\": { \"SingularDisplayName\": \"Provisioning states\" }\n ,\"microsoft.computehub/provisioningstatesucceededresources\": { \"SingularDisplayName\": \"Provisioning states\" }\n ,\"microsoft.computehub/windowsostype\": { \"SingularDisplayName\": \"Windows OS\" }\n ,\"microsoft.computeschedule/autoactions\": { \"SingularDisplayName\": \"Automatic Action\" }\n ,\"microsoft.computeschedule/autoactions/occurrences\": { \"SingularDisplayName\": \"Microsoft.ComputeSchedule auto actions occurrence\" }\n ,\"microsoft.confidentialledger/ledgers\": { \"SingularDisplayName\": \"Confidential Ledger\" }\n ,\"microsoft.confidentialledger/managedccfs\": { \"SingularDisplayName\": \"Managed CCF App\" }\n ,\"microsoft.confluent/agreements\": { \"SingularDisplayName\": \"Microsoft.Confluent agreement\" }\n ,\"microsoft.confluent/organizations\": { \"SingularDisplayName\": \"Confluent organization\" }\n ,\"microsoft.connectedcache/cachenodes\": { \"SingularDisplayName\": \"Connected Cache for ISP\" }\n ,\"microsoft.connectedcache/enterprisecustomers\": { \"SingularDisplayName\": \"Connected Cache for Enterprise & Education\" }\n ,\"microsoft.connectedcache/enterprisemcccustomers\": { \"SingularDisplayName\": \"Connected Cache for Enterprise & Education\" }\n ,\"microsoft.connectedcache/enterprisemcccustomers/enterprisemcccachenodes\": { \"SingularDisplayName\": \"MCC CacheNode for Enterprise\" }\n ,\"microsoft.connectedcache/ispcustomers\": { \"SingularDisplayName\": \"Connected Cache for ISP\" }\n ,\"microsoft.connectedcredentials/credentials\": { \"SingularDisplayName\": \"Microsoft.ConnectedCredentials credential\" }\n ,\"microsoft.connectedvehicle/platformaccounts\": { \"SingularDisplayName\": \"Microsoft.ConnectedVehicle platform account\" }\n ,\"microsoft.connectedvmwarevsphere/clusters\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere cluster\" }\n ,\"microsoft.connectedvmwarevsphere/datastores\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere datastore\" }\n ,\"microsoft.connectedvmwarevsphere/hosts\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere host\" }\n ,\"microsoft.connectedvmwarevsphere/resourcepools\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere resource pool\" }\n ,\"microsoft.connectedvmwarevsphere/vcenters\": { \"SingularDisplayName\": \"VMware vCenter\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachineinstances\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual machine instance\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachineinstances/guestagents\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual machine instances guest agent\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachineinstances/hybrididentitymetadata\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual machine instances hybrid identity metadata\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachines\": { \"SingularDisplayName\": \"VMware + AVS virtual machine\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachines/providers/guestconfigurationassignments\": { \"SingularDisplayName\": \"Guest Assignment\" }\n ,\"microsoft.connectedvmwarevsphere/virtualmachinetemplates\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual machine template\" }\n ,\"microsoft.connectedvmwarevsphere/virtualnetworks\": { \"SingularDisplayName\": \"Microsoft.ConnectedVMwarevSphere virtual network\" }\n ,\"microsoft.consumption/budgets\": { \"SingularDisplayName\": \"Microsoft.Consumption budget\" }\n ,\"microsoft.consumption/credits\": { \"SingularDisplayName\": \"Microsoft.Consumption credit\" }\n ,\"microsoft.consumption/pricesheets\": { \"SingularDisplayName\": \"Microsoft.Consumption pricesheet\" }\n ,\"microsoft.containerinstance/containergroupprofiles\": { \"SingularDisplayName\": \"Microsoft.ContainerInstance container group profile\" }\n ,\"microsoft.containerinstance/containergroupprofiles/revisions\": { \"SingularDisplayName\": \"Microsoft.ContainerInstance container group profiles revision\" }\n ,\"microsoft.containerinstance/containergroups\": { \"SingularDisplayName\": \"Container instances\" }\n ,\"microsoft.containerinstance/ngroups\": { \"SingularDisplayName\": \"Microsoft.ContainerInstance ngroup\" }\n ,\"microsoft.containerregistry/registries\": { \"SingularDisplayName\": \"Container registry\" }\n ,\"microsoft.containerregistry/registries/replications\": { \"SingularDisplayName\": \"Container registry replication\" }\n ,\"microsoft.containerregistry/registries/scopemaps\": { \"SingularDisplayName\": \"Container registry scope map\" }\n ,\"microsoft.containerregistry/registries/tokens\": { \"SingularDisplayName\": \"Container registry token\" }\n ,\"microsoft.containerregistry/registries/webhooks\": { \"SingularDisplayName\": \"Container registry webhook\" }\n ,\"microsoft.containerservice/fleets\": { \"SingularDisplayName\": \"Kubernetes fleet manager\" }\n ,\"microsoft.containerservice/managedclusters\": { \"SingularDisplayName\": \"Kubernetes service\" }\n ,\"microsoft.containerservice/managedclusters/managednamespaces\": { \"SingularDisplayName\": \"Managed namespace\" }\n ,\"microsoft.containerservice/managedclusters/microsoft.kubernetesconfiguration/extensions\": { \"SingularDisplayName\": \"Kubernetes service extension\" }\n ,\"microsoft.containerservice/managedclusters/microsoft.kubernetesconfiguration/fluxconfigurations\": { \"SingularDisplayName\": \"GitOps configuration\" }\n ,\"microsoft.containerservice/managedclusters/microsoft.kubernetesconfiguration/namespaces\": { \"SingularDisplayName\": \"Kubernetes namespace\" }\n ,\"microsoft.containerservice/managedclusters/namespaces\": { \"SingularDisplayName\": \"Managed namespace\" }\n ,\"microsoft.containerservice/managedclustersnapshots\": { \"SingularDisplayName\": \"Microsoft.ContainerService managedclustersnapshot\" }\n ,\"microsoft.containerservice/snapshots\": { \"SingularDisplayName\": \"Microsoft.ContainerService snapshot\" }\n ,\"microsoft.containerstorage/pools\": { \"SingularDisplayName\": \"Container storage\" }\n ,\"microsoft.costmanagement/alerts\": { \"SingularDisplayName\": \"Microsoft.CostManagement alert\" }\n ,\"microsoft.costmanagement/budgets\": { \"SingularDisplayName\": \"Microsoft.CostManagement budget\" }\n ,\"microsoft.costmanagement/cloudconnectors\": { \"SingularDisplayName\": \"Microsoft.CostManagement cloud connector\" }\n ,\"microsoft.costmanagement/connectors\": { \"SingularDisplayName\": \"Microsoft.CostManagement connector\" }\n ,\"microsoft.costmanagement/costallocationrules\": { \"SingularDisplayName\": \"Microsoft.CostManagement cost allocation rule\" }\n ,\"microsoft.costmanagement/costdetailsoperationresults\": { \"SingularDisplayName\": \"Microsoft.CostManagement cost details operation result\" }\n ,\"microsoft.costmanagement/exports\": { \"SingularDisplayName\": \"Microsoft.CostManagement export\" }\n ,\"microsoft.costmanagement/externalbillingaccounts\": { \"SingularDisplayName\": \"Microsoft.CostManagement external billing account\" }\n ,\"microsoft.costmanagement/externalsubscriptions\": { \"SingularDisplayName\": \"Microsoft.CostManagement external subscription\" }\n ,\"microsoft.costmanagement/markuprules\": { \"SingularDisplayName\": \"Microsoft.CostManagement markup rule\" }\n ,\"microsoft.costmanagement/operationstatus\": { \"SingularDisplayName\": \"Microsoft.CostManagement operation statu\" }\n ,\"microsoft.costmanagement/reportconfigs\": { \"SingularDisplayName\": \"Microsoft.CostManagement reportconfig\" }\n ,\"microsoft.costmanagement/reports\": { \"SingularDisplayName\": \"Microsoft.CostManagement report\" }\n ,\"microsoft.costmanagement/scheduledactions\": { \"SingularDisplayName\": \"Microsoft.CostManagement scheduled action\" }\n ,\"microsoft.costmanagement/settings\": { \"SingularDisplayName\": \"Microsoft.CostManagement setting\" }\n ,\"microsoft.costmanagement/views\": { \"SingularDisplayName\": \"Microsoft.CostManagement view\" }\n ,\"microsoft.customerlockbox/requests\": { \"SingularDisplayName\": \"Microsoft.CustomerLockbox request\" }\n ,\"microsoft.customerlockbox/tenantoptedin\": { \"SingularDisplayName\": \"Microsoft.CustomerLockbox tenant opted in\" }\n ,\"microsoft.customproviders/associations\": { \"SingularDisplayName\": \"Microsoft.CustomProviders association\" }\n ,\"microsoft.customproviders/resourceproviders\": { \"SingularDisplayName\": \"Microsoft.CustomProviders resource provider\" }\n ,\"microsoft.dashboard/dashboards\": { \"SingularDisplayName\": \"Azure Monitor dashboards with Grafana\" }\n ,\"microsoft.dashboard/grafana\": { \"SingularDisplayName\": \"Azure Managed Grafana\" }\n ,\"microsoft.dataaccelerator/indexclusters\": { \"SingularDisplayName\": \"Microsoft.DataAccelerator index cluster\" }\n ,\"microsoft.databasefleetmanager/fleets\": { \"SingularDisplayName\": \"Database fleet manager\" }\n ,\"microsoft.databasefleetmanager/fleets/fleetspaces\": { \"SingularDisplayName\": \"Fleetspaces\" }\n ,\"microsoft.databasefleetmanager/fleets/fleetspaces/databases\": { \"SingularDisplayName\": \"Fleet managed database\" }\n ,\"microsoft.databasefleetmanager/fleets/tiers\": { \"SingularDisplayName\": \"tier\" }\n ,\"microsoft.databasewatcher/watchers\": { \"SingularDisplayName\": \"Database watcher\" }\n ,\"microsoft.databox/jobs\": { \"SingularDisplayName\": \"Azure Data Box\" }\n ,\"microsoft.databoxedge/databoxedgedevices\": { \"SingularDisplayName\": \"Azure Stack Edge / Data Box Gateway\" }\n ,\"microsoft.databricks/accessconnectors\": { \"SingularDisplayName\": \"Access Connector for Azure Databricks\" }\n ,\"microsoft.databricks/workspaces\": { \"SingularDisplayName\": \"Azure Databricks Service\" }\n ,\"microsoft.datacatalog/catalogs\": { \"SingularDisplayName\": \"Data catalog\" }\n ,\"microsoft.datacollaboration/workspaces\": { \"SingularDisplayName\": \"Project CI\" }\n ,\"microsoft.datadog/agreements\": { \"SingularDisplayName\": \"Microsoft.Datadog agreement\" }\n ,\"microsoft.datadog/monitors\": { \"SingularDisplayName\": \"Datadog\" }\n ,\"microsoft.datadog/subscriptionstatuses\": { \"SingularDisplayName\": \"Microsoft.Datadog subscription statuse\" }\n ,\"microsoft.datafactory/datafactories\": { \"SingularDisplayName\": \"Data factory\" }\n ,\"microsoft.datafactory/factories\": { \"SingularDisplayName\": \"Data factory (V2)\" }\n ,\"microsoft.datafactory/factories/pipelines\": { \"SingularDisplayName\": \"Data Factory pipeline\" }\n ,\"microsoft.datafactory/factories/triggers\": { \"SingularDisplayName\": \"Data Factory trigger\" }\n ,\"microsoft.datalakeanalytics/accounts\": { \"SingularDisplayName\": \"Data Lake Analytics account\" }\n ,\"microsoft.datalakestore/accounts\": { \"SingularDisplayName\": \"Data Lake Storage Gen1\" }\n ,\"microsoft.datamigration/databasemigrations\": { \"SingularDisplayName\": \"Microsoft.DataMigration database migration\" }\n ,\"microsoft.datamigration/migrationservices\": { \"SingularDisplayName\": \"Microsoft.DataMigration migration service\" }\n ,\"microsoft.datamigration/services\": { \"SingularDisplayName\": \"Azure Database Migration Service (classic)\" }\n ,\"microsoft.datamigration/services/projects\": { \"SingularDisplayName\": \"Azure Database Migration Project\" }\n ,\"microsoft.datamigration/sqlmigrationservices\": { \"SingularDisplayName\": \"Azure Database Migration Service\" }\n ,\"microsoft.dataprotection/backupvaults\": { \"SingularDisplayName\": \"Backup vault\" }\n ,\"microsoft.dataprotection/resourceguards\": { \"SingularDisplayName\": \"Resource Guard\" }\n ,\"microsoft.datareplication/replicationfabrics\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication fabric\" }\n ,\"microsoft.datareplication/replicationfabrics/fabricagents\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication fabrics fabric agent\" }\n ,\"microsoft.datareplication/replicationfabrics/fabricagents/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication fabrics fabric agents operation\" }\n ,\"microsoft.datareplication/replicationfabrics/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication fabrics operation\" }\n ,\"microsoft.datareplication/replicationvaults\": { \"SingularDisplayName\": \"Data replication vault\" }\n ,\"microsoft.datareplication/replicationvaults/alertsettings\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults alert setting\" }\n ,\"microsoft.datareplication/replicationvaults/events\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults event\" }\n ,\"microsoft.datareplication/replicationvaults/jobs\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults job\" }\n ,\"microsoft.datareplication/replicationvaults/jobs/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults jobs operation\" }\n ,\"microsoft.datareplication/replicationvaults/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults operation\" }\n ,\"microsoft.datareplication/replicationvaults/privateendpointconnectionproxies\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults private endpoint connection proxy\" }\n ,\"microsoft.datareplication/replicationvaults/privateendpointconnections\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults private endpoint connection\" }\n ,\"microsoft.datareplication/replicationvaults/privatelinkresources\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults private link resource\" }\n ,\"microsoft.datareplication/replicationvaults/protecteditems\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults protected item\" }\n ,\"microsoft.datareplication/replicationvaults/protecteditems/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults protected items operation\" }\n ,\"microsoft.datareplication/replicationvaults/protecteditems/recoverypoints\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults protected items recovery point\" }\n ,\"microsoft.datareplication/replicationvaults/replicationextensions\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults replication extension\" }\n ,\"microsoft.datareplication/replicationvaults/replicationextensions/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults replication extensions operation\" }\n ,\"microsoft.datareplication/replicationvaults/replicationpolicies\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults replication policy\" }\n ,\"microsoft.datareplication/replicationvaults/replicationpolicies/operations\": { \"SingularDisplayName\": \"Microsoft.DataReplication replication vaults replication policies operation\" }\n ,\"microsoft.datashare/accounts\": { \"SingularDisplayName\": \"Data Share\" }\n ,\"microsoft.dbformariadb/servers\": { \"SingularDisplayName\": \"Azure Database for MariaDB server\" }\n ,\"microsoft.dbformysql/flexibleservers\": { \"SingularDisplayName\": \"Azure Database for MySQL flexible server\" }\n ,\"microsoft.dbformysql/servers\": { \"SingularDisplayName\": \"MySQL server\" }\n ,\"microsoft.dbforpostgresql/flexibleservers\": { \"SingularDisplayName\": \"Azure Database for PostgreSQL flexible server\" }\n ,\"microsoft.dbforpostgresql/servergroupsv2\": { \"SingularDisplayName\": \"Azure Cosmos DB for PostgreSQL Cluster\" }\n ,\"microsoft.dbforpostgresql/servers\": { \"SingularDisplayName\": \"PostgreSQL server\" }\n ,\"microsoft.delegatednetwork/controller\": { \"SingularDisplayName\": \"Microsoft.DelegatedNetwork controller\" }\n ,\"microsoft.delegatednetwork/delegatedsubnets\": { \"SingularDisplayName\": \"Microsoft.DelegatedNetwork delegated subnet\" }\n ,\"microsoft.delegatednetwork/orchestrators\": { \"SingularDisplayName\": \"Microsoft.DelegatedNetwork orchestrator\" }\n ,\"microsoft.dependencymap/maps\": { \"SingularDisplayName\": \"Microsoft.DependencyMap map\" }\n ,\"microsoft.dependencymap/maps/discoverysources\": { \"SingularDisplayName\": \"Microsoft.DependencyMap maps discovery source\" }\n ,\"microsoft.deploymentmanager/artifactsources\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager artifact source\" }\n ,\"microsoft.deploymentmanager/rollouts\": { \"SingularDisplayName\": \"Rollout\" }\n ,\"microsoft.deploymentmanager/servicetopologies\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager service topology\" }\n ,\"microsoft.deploymentmanager/servicetopologies/services\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager service topologies service\" }\n ,\"microsoft.deploymentmanager/servicetopologies/services/serviceunits\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager service topologies services service unit\" }\n ,\"microsoft.deploymentmanager/steps\": { \"SingularDisplayName\": \"Microsoft.DeploymentManager step\" }\n ,\"microsoft.desktopvirtualization/appattachpackages\": { \"SingularDisplayName\": \"App attach package\" }\n ,\"microsoft.desktopvirtualization/applicationgroups\": { \"SingularDisplayName\": \"Application group\" }\n ,\"microsoft.desktopvirtualization/hostpools\": { \"SingularDisplayName\": \"Host pool\" }\n ,\"microsoft.desktopvirtualization/scalingplans\": { \"SingularDisplayName\": \"Scaling plan\" }\n ,\"microsoft.desktopvirtualization/workspaces\": { \"SingularDisplayName\": \"Workspace\" }\n ,\"microsoft.devai/instances\": { \"SingularDisplayName\": \"Microsoft.DevAI instance\" }\n ,\"microsoft.devai/instances/experiments\": { \"SingularDisplayName\": \"Microsoft.DevAI instances experiment\" }\n ,\"microsoft.devai/instances/sandboxes\": { \"SingularDisplayName\": \"Microsoft.DevAI instances sandbox\" }\n ,\"microsoft.devai/instances/sandboxes/experiments\": { \"SingularDisplayName\": \"Microsoft.DevAI instances sandboxes experiment\" }\n ,\"microsoft.devcenter/devcenters\": { \"SingularDisplayName\": \"Dev center\" }\n ,\"microsoft.devcenter/devcenters/devboxdefinitions\": { \"SingularDisplayName\": \"Dev Box definition\" }\n ,\"microsoft.devcenter/networkconnections\": { \"SingularDisplayName\": \"Network connection\" }\n ,\"microsoft.devcenter/plans\": { \"SingularDisplayName\": \"Dev center plan\" }\n ,\"microsoft.devcenter/projects\": { \"SingularDisplayName\": \"Project\" }\n ,\"microsoft.devcenter/projects/pools\": { \"SingularDisplayName\": \"Pool\" }\n ,\"microsoft.developmentwindows365/developmentcloudpcdelegatedmsis\": { \"SingularDisplayName\": \"Microsoft.DevelopmentWindows365 development cloud pc delegated msi\" }\n ,\"microsoft.devhub/iacprofiles\": { \"SingularDisplayName\": \"Infrastructure as Code Automation\" }\n ,\"microsoft.devhub/templates\": { \"SingularDisplayName\": \"Microsoft.DevHub template\" }\n ,\"microsoft.devhub/templates/versions\": { \"SingularDisplayName\": \"Microsoft.DevHub templates version\" }\n ,\"microsoft.devhub/workflows\": { \"SingularDisplayName\": \"Microsoft.DevHub workflow\" }\n ,\"microsoft.deviceonboarding/discoveryservices\": { \"SingularDisplayName\": \"Microsoft.DeviceOnboarding discovery service\" }\n ,\"microsoft.deviceonboarding/discoveryservices/ownershipvoucherpublickeys\": { \"SingularDisplayName\": \"Microsoft.DeviceOnboarding discovery services ownership voucher public key\" }\n ,\"microsoft.deviceonboarding/onboardingservices\": { \"SingularDisplayName\": \"Microsoft.DeviceOnboarding onboarding service\" }\n ,\"microsoft.deviceonboarding/onboardingservices/policies\": { \"SingularDisplayName\": \"Microsoft.DeviceOnboarding onboarding services policy\" }\n ,\"microsoft.deviceregistry/assetendpointprofiles\": { \"SingularDisplayName\": \"IoT Asset Endpoint Profile\" }\n ,\"microsoft.deviceregistry/assets\": { \"SingularDisplayName\": \"IoT Asset\" }\n ,\"microsoft.deviceregistry/billingcontainers\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry billing container\" }\n ,\"microsoft.deviceregistry/devices\": { \"SingularDisplayName\": \"IoT Device\" }\n ,\"microsoft.deviceregistry/discoveredassetendpointprofiles\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry discovered asset endpoint profile\" }\n ,\"microsoft.deviceregistry/discoveredassets\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry discovered asset\" }\n ,\"microsoft.deviceregistry/namespaces\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespace\" }\n ,\"microsoft.deviceregistry/namespaces/assetendpointprofiles\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces asset endpoint profile\" }\n ,\"microsoft.deviceregistry/namespaces/assets\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces asset\" }\n ,\"microsoft.deviceregistry/namespaces/devices\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces device\" }\n ,\"microsoft.deviceregistry/namespaces/discoveredassetendpointprofiles\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces discovered asset endpoint profile\" }\n ,\"microsoft.deviceregistry/namespaces/discoveredassets\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry namespaces discovered asset\" }\n ,\"microsoft.deviceregistry/schemaregistries\": { \"SingularDisplayName\": \"IoT Schema Registry\" }\n ,\"microsoft.deviceregistry/schemaregistries/schemas\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry schema registries schema\" }\n ,\"microsoft.deviceregistry/schemaregistries/schemas/schemaversions\": { \"SingularDisplayName\": \"Microsoft.DeviceRegistry schema registries schemas schema version\" }\n ,\"microsoft.devices/iothubs\": { \"SingularDisplayName\": \"IoT hub\" }\n ,\"microsoft.devices/provisioningservices\": { \"SingularDisplayName\": \"Azure IoT Hub Device Provisioning Service (DPS)\" }\n ,\"microsoft.deviceupdate/accounts\": { \"SingularDisplayName\": \"Device Update for IoT Hub\" }\n ,\"microsoft.deviceupdate/updateaccounts\": { \"SingularDisplayName\": \"Device Update Account\" }\n ,\"microsoft.deviceupdate/updateaccounts/activedeployments\": { \"SingularDisplayName\": \"Device Update Active Deployment\" }\n ,\"microsoft.deviceupdate/updateaccounts/agents\": { \"SingularDisplayName\": \"Device Update Agent\" }\n ,\"microsoft.deviceupdate/updateaccounts/deployments\": { \"SingularDisplayName\": \"Device Update Deployment\" }\n ,\"microsoft.deviceupdate/updateaccounts/deviceclasses\": { \"SingularDisplayName\": \"Device Update Device Class\" }\n ,\"microsoft.deviceupdate/updateaccounts/updates\": { \"SingularDisplayName\": \"Device Update\" }\n ,\"microsoft.devops/pipelines\": { \"SingularDisplayName\": \"Microsoft.DevOps pipeline\" }\n ,\"microsoft.devopsinfrastructure/pools\": { \"SingularDisplayName\": \"Managed DevOps Pool\" }\n ,\"microsoft.devspaces/controllers\": { \"SingularDisplayName\": \"Microsoft.DevSpaces controller\" }\n ,\"microsoft.devtestlab/labs\": { \"SingularDisplayName\": \"DevTest lab\" }\n ,\"microsoft.devtestlab/labs/virtualmachines\": { \"SingularDisplayName\": \"DevTest Lab virtual machine\" }\n ,\"microsoft.devtestlab/schedules\": { \"SingularDisplayName\": \"Microsoft.DevTestLab schedule\" }\n ,\"microsoft.devtunnels/tunnelplans\": { \"SingularDisplayName\": \"Dev Tunnels Domain\" }\n ,\"microsoft.diagnostics/apollo\": { \"SingularDisplayName\": \"Microsoft.Diagnostics apollo\" }\n ,\"microsoft.digitaltwins/digitaltwinsinstances\": { \"SingularDisplayName\": \"Azure Digital Twins\" }\n ,\"microsoft.discovery/agents\": { \"SingularDisplayName\": \"Microsoft Discovery Agent\" }\n ,\"microsoft.discovery/bookshelves\": { \"SingularDisplayName\": \"Microsoft Discovery Bookshelf\" }\n ,\"microsoft.discovery/datacontainers\": { \"SingularDisplayName\": \"Microsoft Discovery Data Container\" }\n ,\"microsoft.discovery/datacontainers/dataassets\": { \"SingularDisplayName\": \"Data asset\" }\n ,\"microsoft.discovery/models\": { \"SingularDisplayName\": \"Microsoft Discovery Model\" }\n ,\"microsoft.discovery/storages\": { \"SingularDisplayName\": \"Microsoft Discovery Storage\" }\n ,\"microsoft.discovery/supercomputers\": { \"SingularDisplayName\": \"Microsoft Discovery Supercomputer\" }\n ,\"microsoft.discovery/supercomputers/nodepools\": { \"SingularDisplayName\": \"Nodepool\" }\n ,\"microsoft.discovery/tools\": { \"SingularDisplayName\": \"Microsoft Discovery Tool\" }\n ,\"microsoft.discovery/workflows\": { \"SingularDisplayName\": \"Microsoft Discovery Workflow\" }\n ,\"microsoft.discovery/workspaces\": { \"SingularDisplayName\": \"Microsoft Discovery Workspace\" }\n ,\"microsoft.discovery/workspaces/projects\": { \"SingularDisplayName\": \"Microsoft Discovery Project\" }\n ,\"microsoft.documentdb/cassandraclusters\": { \"SingularDisplayName\": \"Azure Managed Instance for Apache Cassandra\" }\n ,\"microsoft.documentdb/databaseaccounts\": { \"SingularDisplayName\": \"Cosmos DB account\" }\n ,\"microsoft.documentdb/fleets\": { \"SingularDisplayName\": \"Azure Cosmos DB Fleet\" }\n ,\"microsoft.documentdb/fleetspacepotentialdatabaseaccounts\": { \"SingularDisplayName\": \"Potential Azure Cosmos DB account\" }\n ,\"microsoft.documentdb/fleetspacepotentialdatabaseaccountswithlocations\": { \"SingularDisplayName\": \"Potential Azure Cosmos DB account\" }\n ,\"microsoft.documentdb/mongoclusters\": { \"SingularDisplayName\": \"Azure Cosmos DB for MongoDB (vCore)\" }\n ,\"microsoft.documentdb/throughputpools\": { \"SingularDisplayName\": \"Microsoft.DocumentDB throughput pool\" }\n ,\"microsoft.documentdb/throughputpools/throughputpoolaccounts\": { \"SingularDisplayName\": \"Microsoft.DocumentDB throughput pools throughput pool account\" }\n ,\"microsoft.domainregistration/domains\": { \"SingularDisplayName\": \"App Service Domain\" }\n ,\"microsoft.domainregistration/topleveldomains\": { \"SingularDisplayName\": \"Microsoft.DomainRegistration top level domain\" }\n ,\"microsoft.durabletask/namespaces\": { \"SingularDisplayName\": \"Microsoft.DurableTask namespace\" }\n ,\"microsoft.durabletask/namespaces/taskhubs\": { \"SingularDisplayName\": \"Task Hub\" }\n ,\"microsoft.durabletask/schedulers\": { \"SingularDisplayName\": \"Durable Task Scheduler\" }\n ,\"microsoft.durabletask/schedulers/taskhubs\": { \"SingularDisplayName\": \"Task Hub\" }\n ,\"microsoft.dynamics365fraudprotection/instances\": { \"SingularDisplayName\": \"Microsoft.Dynamics365FraudProtection instance\" }\n ,\"microsoft.easm/workspaces\": { \"SingularDisplayName\": \"Microsoft Defender EASM\" }\n ,\"microsoft.edge/configurations\": { \"SingularDisplayName\": \"Site configuration\" }\n ,\"microsoft.edge/configurations/arcgatewayconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations arc gateway configuration\" }\n ,\"microsoft.edge/configurations/connectivityconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations connectivity configuration\" }\n ,\"microsoft.edge/configurations/dynamicconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations dynamic configuration\" }\n ,\"microsoft.edge/configurations/dynamicconfigurations/versions\": { \"SingularDisplayName\": \"Microsoft.Edge configurations dynamic configurations version\" }\n ,\"microsoft.edge/configurations/networkconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations network configuration\" }\n ,\"microsoft.edge/configurations/securityconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations security configuration\" }\n ,\"microsoft.edge/configurations/timeserverconfigurations\": { \"SingularDisplayName\": \"Microsoft.Edge configurations time server configuration\" }\n ,\"microsoft.edge/connectivitystatuses\": { \"SingularDisplayName\": \"Microsoft.Edge connectivity statuse\" }\n ,\"microsoft.edge/disconnectedoperations\": { \"SingularDisplayName\": \"Azure Local - disconnected operations\" }\n ,\"microsoft.edge/siteawareresourcetypes\": { \"SingularDisplayName\": \"Microsoft.Edge site aware resource type\" }\n ,\"microsoft.edge/sites\": { \"SingularDisplayName\": \"Site manager - Azure Arc\" }\n ,\"microsoft.edge/updates\": { \"SingularDisplayName\": \"Microsoft.Edge update\" }\n ,\"microsoft.edgemarketplace/offers\": { \"SingularDisplayName\": \"Microsoft.EdgeMarketplace offer\" }\n ,\"microsoft.edgemarketplace/publishers\": { \"SingularDisplayName\": \"Microsoft.EdgeMarketplace publisher\" }\n ,\"microsoft.edgeorder/addresses\": { \"SingularDisplayName\": \"Azure Edge Hardware Center Address\" }\n ,\"microsoft.edgeorder/bootstrapconfigurations\": { \"SingularDisplayName\": \"Site Key\" }\n ,\"microsoft.edgeorder/orderitems\": { \"SingularDisplayName\": \"Azure Edge Hardware Center\" }\n ,\"microsoft.edgeorder/virtual_orderitems\": { \"SingularDisplayName\": \"Device\" }\n ,\"microsoft.edgezones/extendedzones\": { \"SingularDisplayName\": \"Microsoft.EdgeZones extended zone\" }\n ,\"microsoft.education/grants\": { \"SingularDisplayName\": \"Microsoft.Education grant\" }\n ,\"microsoft.education/labs\": { \"SingularDisplayName\": \"Microsoft.Education lab\" }\n ,\"microsoft.education/labs/joinrequests\": { \"SingularDisplayName\": \"Microsoft.Education labs join request\" }\n ,\"microsoft.education/labs/students\": { \"SingularDisplayName\": \"Microsoft.Education labs student\" }\n ,\"microsoft.education/studentlabs\": { \"SingularDisplayName\": \"Microsoft.Education student lab\" }\n ,\"microsoft.elastic/monitors\": { \"SingularDisplayName\": \"Elastic Cloud Resource\" }\n ,\"microsoft.elasticsan/elasticsans\": { \"SingularDisplayName\": \"Elastic SAN\" }\n ,\"microsoft.energydataplatform/energyservices\": { \"SingularDisplayName\": \"Microsoft.EnergyDataPlatform energy service\" }\n ,\"microsoft.enterpriseknowledgegraph/services\": { \"SingularDisplayName\": \"Microsoft.EnterpriseKnowledgeGraph service\" }\n ,\"microsoft.enterprisesupport/enterprisesupports\": { \"SingularDisplayName\": \"Microsoft.EnterpriseSupport enterprise support\" }\n ,\"microsoft.eventgrid/domains\": { \"SingularDisplayName\": \"Event Grid Domain\" }\n ,\"microsoft.eventgrid/domains/topics\": { \"SingularDisplayName\": \"Event Grid Domain Topic\" }\n ,\"microsoft.eventgrid/eventsubscriptions\": { \"SingularDisplayName\": \"Microsoft.EventGrid event subscription\" }\n ,\"microsoft.eventgrid/extensiontopics\": { \"SingularDisplayName\": \"Event Grid extension topic\" }\n ,\"microsoft.eventgrid/namespaces\": { \"SingularDisplayName\": \"Event Grid Namespace\" }\n ,\"microsoft.eventgrid/namespaces/topics\": { \"SingularDisplayName\": \"Event Grid Namespace Topic\" }\n ,\"microsoft.eventgrid/namespaces/topics/eventsubscriptions\": { \"SingularDisplayName\": \"Event Subscription\" }\n ,\"microsoft.eventgrid/namespaces/topicspaces\": { \"SingularDisplayName\": \"Event Grid Topic Space\" }\n ,\"microsoft.eventgrid/partnerconfigurations\": { \"SingularDisplayName\": \"Event Grid Partner Configuration\" }\n ,\"microsoft.eventgrid/partnerdestinations\": { \"SingularDisplayName\": \"Event Grid Partner Destination\" }\n ,\"microsoft.eventgrid/partnernamespaces\": { \"SingularDisplayName\": \"Event Grid Partner Namespace\" }\n ,\"microsoft.eventgrid/partnernamespaces/channels\": { \"SingularDisplayName\": \"Event Grid Channel\" }\n ,\"microsoft.eventgrid/partnerregistrations\": { \"SingularDisplayName\": \"Event Grid Partner Registration\" }\n ,\"microsoft.eventgrid/partnertopics\": { \"SingularDisplayName\": \"Event Grid Partner Topic\" }\n ,\"microsoft.eventgrid/systemtopics\": { \"SingularDisplayName\": \"Event Grid System Topic\" }\n ,\"microsoft.eventgrid/systemtopics/eventsubscriptions\": { \"SingularDisplayName\": \"Event Grid Subscriptions\" }\n ,\"microsoft.eventgrid/topics\": { \"SingularDisplayName\": \"Event Grid Topic\" }\n ,\"microsoft.eventgrid/topictypes\": { \"SingularDisplayName\": \"Microsoft.EventGrid topic type\" }\n ,\"microsoft.eventgrid/verifiedpartners\": { \"SingularDisplayName\": \"Microsoft.EventGrid verified partner\" }\n ,\"microsoft.eventhub/clusters\": { \"SingularDisplayName\": \"Event Hubs Cluster\" }\n ,\"microsoft.eventhub/namespaces\": { \"SingularDisplayName\": \"Event Hubs namespace\" }\n ,\"microsoft.eventhub/namespaces/disasterrecoveryconfigs\": { \"SingularDisplayName\": \"Event Hubs Geo-DR Alias\" }\n ,\"microsoft.eventhub/namespaces/eventhubs\": { \"SingularDisplayName\": \"Event Hubs Instance\" }\n ,\"microsoft.eventhub/namespaces/providers/diagnosticsettings\": { \"SingularDisplayName\": \"Diagnostic settings\" }\n ,\"microsoft.eventhub/namespaces/schemagroups\": { \"SingularDisplayName\": \"Schema Group\" }\n ,\"microsoft.experimentation/experimentworkspaces\": { \"SingularDisplayName\": \"Experiment Workspace\" }\n ,\"microsoft.extendedlocation/customlocations\": { \"SingularDisplayName\": \"Custom location\" }\n ,\"microsoft.fabric/capacities\": { \"SingularDisplayName\": \"Fabric Capacity\" }\n ,\"microsoft.fabric/privatelinkservicesforfabric\": { \"SingularDisplayName\": \"Microsoft.Fabric private link services for fabric\" }\n ,\"microsoft.fabric/privatelinkservicesforfabric/operationresults\": { \"SingularDisplayName\": \"Microsoft.Fabric private link services for fabric operation result\" }\n ,\"microsoft.fabric/privatelinkservicesforfabric/privateendpointconnections\": { \"SingularDisplayName\": \"Microsoft.Fabric private link services for fabric private endpoint connection\" }\n ,\"microsoft.fabric/privatelinkservicesforfabric/privatelinkresources\": { \"SingularDisplayName\": \"Microsoft.Fabric private link services for fabric private link resource\" }\n ,\"microsoft.fairfieldgardens/deviceprovisioningstates\": { \"SingularDisplayName\": \"Microsoft.FairfieldGardens device provisioning state\" }\n ,\"microsoft.fairfieldgardens/provisioningresources\": { \"SingularDisplayName\": \"Fairfield Gardens\" }\n ,\"microsoft.fairfieldgardens/provisioningresources/provisioningpolicies\": { \"SingularDisplayName\": \"Provisioning policy\" }\n ,\"microsoft.falcon/namespaces\": { \"SingularDisplayName\": \"Microsoft.Falcon namespace\" }\n ,\"microsoft.features/featureprovidernamespaces/featureconfigurations\": { \"SingularDisplayName\": \"Preview features\" }\n ,\"microsoft.fidalgo/devcenters\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenter\" }\n ,\"microsoft.fidalgo/devcenters/attachednetworks\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters attachednetwork\" }\n ,\"microsoft.fidalgo/devcenters/catalogs\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters catalog\" }\n ,\"microsoft.fidalgo/devcenters/catalogs/items\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters catalogs item\" }\n ,\"microsoft.fidalgo/devcenters/devboxdefinitions\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters devboxdefinition\" }\n ,\"microsoft.fidalgo/devcenters/environmenttypes\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters environment type\" }\n ,\"microsoft.fidalgo/devcenters/galleries\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters gallery\" }\n ,\"microsoft.fidalgo/devcenters/galleries/images\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters galleries image\" }\n ,\"microsoft.fidalgo/devcenters/galleries/images/versions\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters galleries images version\" }\n ,\"microsoft.fidalgo/devcenters/mappings\": { \"SingularDisplayName\": \"Microsoft.Fidalgo devcenters mapping\" }\n ,\"microsoft.fidalgo/machinedefinitions\": { \"SingularDisplayName\": \"Microsoft.Fidalgo machinedefinition\" }\n ,\"microsoft.fidalgo/networksettings\": { \"SingularDisplayName\": \"Microsoft.Fidalgo networksetting\" }\n ,\"microsoft.fidalgo/networksettings/healthchecks\": { \"SingularDisplayName\": \"Microsoft.Fidalgo networksettings healthcheck\" }\n ,\"microsoft.fidalgo/projects\": { \"SingularDisplayName\": \"Microsoft.Fidalgo project\" }\n ,\"microsoft.fidalgo/projects/attachednetworks\": { \"SingularDisplayName\": \"Microsoft.Fidalgo projects attachednetwork\" }\n ,\"microsoft.fidalgo/projects/devboxdefinitions\": { \"SingularDisplayName\": \"Microsoft.Fidalgo projects devboxdefinition\" }\n ,\"microsoft.fidalgo/projects/environments\": { \"SingularDisplayName\": \"Microsoft.Fidalgo projects environment\" }\n ,\"microsoft.fidalgo/projects/pools\": { \"SingularDisplayName\": \"Microsoft.Fidalgo projects pool\" }\n ,\"microsoft.fileshares/fileshares\": { \"SingularDisplayName\": \"File share\" }\n ,\"microsoft.fluidrelay/fluidrelayservers\": { \"SingularDisplayName\": \"Fluid Relay\" }\n ,\"microsoft.footprintmonitoring/profiles\": { \"SingularDisplayName\": \"Microsoft.FootprintMonitoring profile\" }\n ,\"microsoft.footprintmonitoring/profiles/experiments\": { \"SingularDisplayName\": \"Microsoft.FootprintMonitoring profiles experiment\" }\n ,\"microsoft.footprintmonitoring/profiles/measurementendpoints\": { \"SingularDisplayName\": \"Microsoft.FootprintMonitoring profiles measurement endpoint\" }\n ,\"microsoft.footprintmonitoring/profiles/measurementendpoints/conditions\": { \"SingularDisplayName\": \"Microsoft.FootprintMonitoring profiles measurement endpoints condition\" }\n ,\"microsoft.gallery/myareas/galleryitems\": { \"SingularDisplayName\": \"Template\" }\n ,\"microsoft.genomics/accounts\": { \"SingularDisplayName\": \"Genomics account\" }\n ,\"microsoft.graph/azureadapplication\": { \"SingularDisplayName\": \"Entra application\" }\n ,\"microsoft.graph/azureadapplicationprototype\": { \"SingularDisplayName\": \"Microsoft.Graph Azure ad application prototype\" }\n ,\"microsoft.graphservices/accounts\": { \"SingularDisplayName\": \"Metered API account\" }\n ,\"microsoft.guestconfiguration/guestconfigurationassignments\": { \"SingularDisplayName\": \"Microsoft.GuestConfiguration guest configuration assignment\" }\n ,\"microsoft.guestconfiguration/guestconfigurationassignments/reports\": { \"SingularDisplayName\": \"Microsoft.GuestConfiguration guest configuration assignments report\" }\n ,\"microsoft.hanaonazure/hanainstances\": { \"SingularDisplayName\": \"SAP HANA on Azure\" }\n ,\"microsoft.hanaonazure/sapmonitors\": { \"SingularDisplayName\": \"Azure Monitor for SAP Solutions (classic)\" }\n ,\"microsoft.hardware/orders\": { \"SingularDisplayName\": \"Microsoft.Hardware order\" }\n ,\"microsoft.hardwaresecuritymodules/cloudhsmclusters\": { \"SingularDisplayName\": \"Azure Cloud HSM\" }\n ,\"microsoft.hdinsight/clusterpools\": { \"SingularDisplayName\": \"Azure HDInsight on AKS cluster pool\" }\n ,\"microsoft.hdinsight/clusterpools/clusters\": { \"SingularDisplayName\": \"Azure HDInsight on AKS cluster\" }\n ,\"microsoft.hdinsight/clusterpools/clusters/instanceviews\": { \"SingularDisplayName\": \"Microsoft.HDInsight clusterpools clusters instance view\" }\n ,\"microsoft.hdinsight/clusters\": { \"SingularDisplayName\": \"HDInsight cluster\" }\n ,\"microsoft.healthbot/healthbots\": { \"SingularDisplayName\": \"Healthcare agent service\" }\n ,\"microsoft.healthcareapis/services\": { \"SingularDisplayName\": \"Azure API for FHIR\" }\n ,\"microsoft.healthcareapis/workspaces\": { \"SingularDisplayName\": \"Health Data Services workspace\" }\n ,\"microsoft.healthcareapis/workspaces/dicomservices\": { \"SingularDisplayName\": \"DICOM service\" }\n ,\"microsoft.healthcareapis/workspaces/fhirservices\": { \"SingularDisplayName\": \"FHIR service\" }\n ,\"microsoft.healthcareapis/workspaces/iotconnectors\": { \"SingularDisplayName\": \"MedTech service\" }\n ,\"microsoft.healthdataaiservices/deidservices\": { \"SingularDisplayName\": \"De-identification Service\" }\n ,\"microsoft.healthmodel/healthmodels\": { \"SingularDisplayName\": \"Health Model\" }\n ,\"microsoft.healthplatform/accounts\": { \"SingularDisplayName\": \"Microsoft.HealthPlatform account\" }\n ,\"microsoft.help/diagnostics\": { \"SingularDisplayName\": \"Microsoft.Help diagnostic\" }\n ,\"microsoft.help/selfhelp\": { \"SingularDisplayName\": \"Microsoft.Help self help\" }\n ,\"microsoft.help/simplifiedsolutions\": { \"SingularDisplayName\": \"Microsoft.Help simplified solution\" }\n ,\"microsoft.help/solutions\": { \"SingularDisplayName\": \"Microsoft.Help solution\" }\n ,\"microsoft.help/troubleshooters\": { \"SingularDisplayName\": \"Microsoft.Help troubleshooter\" }\n ,\"microsoft.hpcworkbench/instances\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instance\" }\n ,\"microsoft.hpcworkbench/instances/chambers\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chamber\" }\n ,\"microsoft.hpcworkbench/instances/chambers/accessprofiles\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers access profile\" }\n ,\"microsoft.hpcworkbench/instances/chambers/filerequests\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers file request\" }\n ,\"microsoft.hpcworkbench/instances/chambers/files\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers file\" }\n ,\"microsoft.hpcworkbench/instances/chambers/storages\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers storage\" }\n ,\"microsoft.hpcworkbench/instances/chambers/workloads\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances chambers workload\" }\n ,\"microsoft.hpcworkbench/instances/consortiums\": { \"SingularDisplayName\": \"Microsoft.HpcWorkbench instances consortium\" }\n ,\"microsoft.hybridcloud/cloudconnections\": { \"SingularDisplayName\": \"Microsoft.HybridCloud cloud connection\" }\n ,\"microsoft.hybridcloud/cloudconnectors\": { \"SingularDisplayName\": \"Microsoft.HybridCloud cloud connector\" }\n ,\"microsoft.hybridcompute/arcgatewayassociatedresources\": { \"SingularDisplayName\": \"Arc gateway associated resource\" }\n ,\"microsoft.hybridcompute/arcserverwithwac\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/gateways\": { \"SingularDisplayName\": \"Arc gateway\" }\n ,\"microsoft.hybridcompute/licenses\": { \"SingularDisplayName\": \"Extended Security Updates - Windows Server 2012/R2\" }\n ,\"microsoft.hybridcompute/machines\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/machines/microsoft.awsconnector/ec2instances\": { \"SingularDisplayName\": \"Microsoft.AwsConnector ec2 instance\" }\n ,\"microsoft.hybridcompute/machines/microsoft.connectedvmwarevsphere/virtualmachineinstances\": { \"SingularDisplayName\": \"VMware + AVS virtual machine\" }\n ,\"microsoft.hybridcompute/machines/providers/guestconfigurationassignments\": { \"SingularDisplayName\": \"Guest Assignment\" }\n ,\"microsoft.hybridcompute/machinesesu\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/machinespaygo\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/machinessoftwareassurance\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/machinessovereign\": { \"SingularDisplayName\": \"Machine - Azure Arc\" }\n ,\"microsoft.hybridcompute/privatelinkscopes\": { \"SingularDisplayName\": \"Azure Arc Private Link Scope\" }\n ,\"microsoft.hybridcompute/settings\": { \"SingularDisplayName\": \"Microsoft.HybridCompute setting\" }\n ,\"microsoft.hybridconnectivity/endpoints\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity endpoint\" }\n ,\"microsoft.hybridconnectivity/endpoints/serviceconfigurations\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity endpoints service configuration\" }\n ,\"microsoft.hybridconnectivity/publiccloudconnectors\": { \"SingularDisplayName\": \"Multicloud connector\" }\n ,\"microsoft.hybridconnectivity/solutionconfigurations\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity solution configuration\" }\n ,\"microsoft.hybridconnectivity/solutionconfigurations/inventory\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity solution configurations inventory\" }\n ,\"microsoft.hybridconnectivity/solutiontypes\": { \"SingularDisplayName\": \"Microsoft.HybridConnectivity solution type\" }\n ,\"microsoft.hybridcontainerservice/kubernetesversions\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService kubernetes version\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusterinstances\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService provisioned cluster instance\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusterinstances/agentpools\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService provisioned cluster instances agent pool\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusterinstances/hybrididentitymetadata\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService provisioned cluster instances hybrid identity metadata\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusterinstances/upgradeprofiles\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService provisioned cluster instances upgrade profile\" }\n ,\"microsoft.hybridcontainerservice/provisionedclusters\": { \"SingularDisplayName\": \"Kubernetes hybrid - Azure Arc\" }\n ,\"microsoft.hybridcontainerservice/skus\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService SKU\" }\n ,\"microsoft.hybridcontainerservice/storagespaces\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService storage space\" }\n ,\"microsoft.hybridcontainerservice/virtualnetworks\": { \"SingularDisplayName\": \"Microsoft.HybridContainerService virtual network\" }\n ,\"microsoft.hybriddata/datamanagers\": { \"SingularDisplayName\": \"Microsoft.HybridData data manager\" }\n ,\"microsoft.hybriddata/datamanagers/dataservices\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data service\" }\n ,\"microsoft.hybriddata/datamanagers/dataservices/jobdefinitions\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data services job definition\" }\n ,\"microsoft.hybriddata/datamanagers/dataservices/jobdefinitions/jobs\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data services job definitions job\" }\n ,\"microsoft.hybriddata/datamanagers/datastores\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data store\" }\n ,\"microsoft.hybriddata/datamanagers/datastoretypes\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers data store type\" }\n ,\"microsoft.hybriddata/datamanagers/publickeys\": { \"SingularDisplayName\": \"Microsoft.HybridData data managers public key\" }\n ,\"microsoft.hybridnetwork/configurationgroupvalues\": { \"SingularDisplayName\": \"Configuration Group Value\" }\n ,\"microsoft.hybridnetwork/devices\": { \"SingularDisplayName\": \"Azure Network Function Manager ? Device\" }\n ,\"microsoft.hybridnetwork/networkfunctions\": { \"SingularDisplayName\": \"Azure Network Function Manager ? Network Function\" }\n ,\"microsoft.hybridnetwork/proxypublishers\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publisher\" }\n ,\"microsoft.hybridnetwork/proxypublishers/artifactstores\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers artifact store\" }\n ,\"microsoft.hybridnetwork/proxypublishers/configurationgroupschemas\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers configuration group schema\" }\n ,\"microsoft.hybridnetwork/proxypublishers/networkfunctiondefinitiongroups\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers network function definition group\" }\n ,\"microsoft.hybridnetwork/proxypublishers/networkfunctiondefinitiongroups/networkfunctiondefinitionversions\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers network function definition groups network function definition version\" }\n ,\"microsoft.hybridnetwork/proxypublishers/networkservicedesigngroups\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers network service design group\" }\n ,\"microsoft.hybridnetwork/proxypublishers/networkservicedesigngroups/networkservicedesignversions\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork proxy publishers network service design groups network service design version\" }\n ,\"microsoft.hybridnetwork/publishers\": { \"SingularDisplayName\": \"Publisher\" }\n ,\"microsoft.hybridnetwork/publishers/artifactstores\": { \"SingularDisplayName\": \"Publisher Artifact Store\" }\n ,\"microsoft.hybridnetwork/publishers/artifactstores/artifactmanifests\": { \"SingularDisplayName\": \"Publisher Artifact Manifest\" }\n ,\"microsoft.hybridnetwork/publishers/configurationgroupschemas\": { \"SingularDisplayName\": \"Configuration Group Schema\" }\n ,\"microsoft.hybridnetwork/publishers/networkfunctiondefinitiongroups\": { \"SingularDisplayName\": \"Network Function Definition\" }\n ,\"microsoft.hybridnetwork/publishers/networkfunctiondefinitiongroups/networkfunctiondefinitionversions\": { \"SingularDisplayName\": \"Network Function Definition Version\" }\n ,\"microsoft.hybridnetwork/publishers/networkservicedesigngroups\": { \"SingularDisplayName\": \"Network Service Design\" }\n ,\"microsoft.hybridnetwork/publishers/networkservicedesigngroups/networkservicedesignversions\": { \"SingularDisplayName\": \"Network Service Design Version\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management container\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/rolloutsequences\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers rollout sequence\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/rollouttiers\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers rollout tier\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/updatespecifications\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers update specification\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/updatespecifications/rollouts\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers update specifications rollout\" }\n ,\"microsoft.hybridnetwork/servicemanagementcontainers/updatespecifications/rollouts/statuses\": { \"SingularDisplayName\": \"Microsoft.HybridNetwork service management containers update specifications rollouts statuse\" }\n ,\"microsoft.hybridnetwork/sitenetworkservices\": { \"SingularDisplayName\": \"Site Network Service\" }\n ,\"microsoft.hybridnetwork/sites\": { \"SingularDisplayName\": \"Site\" }\n })[tolower(id)]\n}\n", - "$fxv#10": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// See known issues @ https://github.com/microsoft/finops-toolkit/issues/1111\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Prices |=========================================================================================================\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_transform_v1_2 function\n.create-or-alter function\nwith (docstring='Transforms Prices_raw into FOCUS 1.2.', folder='Prices')\nPrices_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n let prices = materialize(\n Prices_raw\n | extend PricingCurrency = coalesce(Currency, CurrencyCode) // CurrencyCode last as a fallback only\n | extend x_SkuId = coalesce(SkuId, SkuID)\n | extend x_SkuMeterId = coalesce(MeterId, MeterID)\n | extend x_SkuProductId = coalesce(ProductId, ProductID)\n | extend x_SkuTerm = isoMonths(Term)\n | project-rename\n SkuMeter = MeterName,\n x_BaseUnitPrice = BasePrice,\n x_EffectivePeriodEnd = EffectiveEndDate,\n x_EffectivePeriodStart = EffectiveStartDate,\n x_PricingUnitDescription = UnitOfMeasure,\n x_SkuIncludedQuantity = IncludedQuantity,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuMeterType = MeterType,\n x_SkuOfferId = OfferID,\n x_SkuPartNumber = PartNumber,\n x_SkuPriceType = PriceType,\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTier = TierMinimumUnits\n | extend ContractedUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', UnitPrice, real(null)) // UnitPrice for savings plan is not the on-demand unit price\n | extend ListUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', MarketPrice, real(null)) // MarketPrice for savings plan is not the list price\n | extend ChargeCategory = case(\n x_SkuPriceType == 'Consumption', 'Usage',\n x_SkuPriceType == 'ReservedInstance', 'Purchase',\n x_SkuPriceType == 'SavingsPlan', 'Usage', // Savings plan prices are for committed usage, not the purchase\n ''\n )\n | extend SkuPriceIdv2 = strcat(case(x_SkuPriceType == 'Consumption', 'OD', x_SkuPriceType == 'ReservedInstance', 'RI', x_SkuPriceType == 'SavingsPlan', 'SP', 'XX'), substring(ChargeCategory, 0, 1), x_SkuTerm, '_', x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType, '_', x_SkuTier, x_SkuOfferId)\n | extend x_BillingAccountId = iff(BillingAccountId startswith '/', split(BillingAccountId, '/')[-1], coalesce(BillingAccountId, EnrollmentNumber))\n | extend x_BillingProfileId = iff(BillingProfileId startswith '/', split(BillingProfileId, '/')[-1], coalesce(BillingProfileId, EnrollmentNumber))\n | extend tmp_SavingsPlanKey = strcat(x_SkuMeterId, x_SkuProductId, x_SkuId, x_SkuTier, x_SkuOfferId)\n //\n // Get latest ingested row based on the unique ID\n | extend x_IngestionTime = ingestion_time()\n );\n //\n // Meters for reservations and savings plans to identify commitment eligibility\n let riMeters = prices | where x_SkuPriceType == 'ReservedInstance' | distinct x_SkuMeterId;\n let spMeters = prices | where x_SkuPriceType == 'SavingsPlan' | distinct x_SkuMeterId;\n //\n // Copy list/base/contracted prices from on-demand SKUs\n prices\n | where x_SkuPriceType == 'SavingsPlan'\n // If we use join, specify the shuffle key\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter hint.strategy=shuffle (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | lookup kind=leftouter (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | extend ListUnitPrice = coalesce(ListUnitPrice, ListUnitPrice1)\n | extend ContractedUnitPrice = coalesce(ContractedUnitPrice, ContractedUnitPrice1)\n | extend x_BaseUnitPrice = coalesce(x_BaseUnitPrice, x_BaseUnitPrice1)\n | project-away ListUnitPrice1, ContractedUnitPrice1, x_BaseUnitPrice1, tmp_SavingsPlanKey\n | union ((prices | where x_SkuPriceType != 'SavingsPlan'))\n //\n // Set CommitmentDiscountCategory for reuse\n | extend CommitmentDiscountCategory = case(\n x_SkuPriceType == 'ReservedInstance', 'Usage',\n x_SkuPriceType == 'SavingsPlan', 'Spend',\n ''\n )\n //\n // Calculate commitment discount eligibility\n // TODO: Would a join be faster?\n // TODO: Check this to ensure it's correct\n | extend x_CommitmentDiscountSpendEligibility = iff(x_SkuMeterId in (riMeters) and x_SkuPriceType != 'ReservedInstance', 'Eligible', 'Not Eligible')\n | extend x_CommitmentDiscountUsageEligibility = iff(x_SkuMeterId in (spMeters), 'Eligible', 'Not Eligible')\n //\n // TODO: Implement x_CommitmentDiscountNormalizedRatio\n | extend x_CommitmentDiscountNormalizedRatio = real(null)\n //\n // Add PricingUnit and x_PricingBlockSize\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter (PricingUnits) on x_PricingUnitDescription | project-away x_PricingUnitDescription1\n | lookup kind=leftouter (PricingUnits) on x_PricingUnitDescription\n //\n | extend x_EffectiveUnitPrice = iff(x_SkuPriceType == 'SavingsPlan', UnitPrice, real(null)) // Savings plan prices are for the effective price, not the contracted price\n | extend x_EffectiveUnitPriceDiscount = ContractedUnitPrice - x_EffectiveUnitPrice\n | extend x_ContractedUnitPriceDiscount = ListUnitPrice - ContractedUnitPrice\n | extend x_TotalUnitPriceDiscount = ListUnitPrice - x_EffectiveUnitPrice\n | project\n BillingAccountId = tolower(case(\n BillingProfileId startswith '/', BillingProfileId,\n BillingAccountId startswith '/', BillingAccountId,\n strcat('/providers/microsoft.billing/billingaccounts/', x_BillingAccountId, iff(x_BillingProfileId == x_BillingAccountId, '', strcat('/billingprofiles/', x_BillingProfileId)))\n )),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName, x_BillingProfileId),\n BillingCurrency = coalesce(BillingCurrency, CurrencyCode, Currency), // Currency last as a fallback only\n ChargeCategory,\n CommitmentDiscountCategory,\n CommitmentDiscountType = case(\n x_SkuPriceType == 'ReservedInstance', 'Reservation',\n x_SkuPriceType == 'SavingsPlan', 'Savings plan',\n ''\n ),\n CommitmentDiscountUnit = case(\n isempty(CommitmentDiscountCategory), '',\n CommitmentDiscountCategory == 'Spend', PricingCurrency,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio == real(1), PricingUnit,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio > real(1), strcat('Normalized ', PricingUnit),\n ''\n ),\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory = case(\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed',\n ''\n ),\n PricingCurrency,\n PricingUnit,\n SkuId = coalesce(ProductId, ProductID),\n SkuMeter,\n SkuPriceId = strcat(x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType),\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement = case(\n strlen(x_BillingAccountId) > 32, 'MCA',\n strlen(x_BillingAccountId) < 32, 'EA',\n 'Unknown'\n ),\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent = 1.0 * x_ContractedUnitPriceDiscount / ListUnitPrice * 100,\n x_EffectivePeriodEnd = startofmonth(x_EffectivePeriodEnd + 1h),\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent = 1.0 * x_EffectiveUnitPriceDiscount / ContractedUnitPrice * 100,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingSubcategory = case(\n x_SkuPriceType == 'Consumption' and (x_SkuIncludedQuantity > 0 or x_SkuTier > 0), 'Tiered',\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed Spend',\n ''\n ),\n x_PricingUnitDescription,\n x_SkuDescription = Product,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName = coalesce(x_SourceName, 'Cost Management'),\n x_SourceProvider = coalesce(x_SourceProvider, 'Microsoft'),\n x_SourceType = coalesce(x_SourceType, 'PriceSheet'),\n x_SourceVersion = coalesce(x_SourceVersion, '2023-05-01'),\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent = 1.0 * x_TotalUnitPriceDiscount / ListUnitPrice * 100\n}\n\n// Prices_final_v1_2 table\n.create-merge table Prices_final_v1_2 (\n BillingAccountId: string,\n BillingAccountName: string,\n BillingCurrency: string,\n ChargeCategory: string,\n CommitmentDiscountCategory: string,\n CommitmentDiscountType: string,\n CommitmentDiscountUnit: string,\n ContractedUnitPrice: real,\n ListUnitPrice: real,\n PricingCategory: string,\n PricingCurrency: string, // Azure\n PricingUnit: string,\n SkuId: string,\n SkuMeter: string, // Azure\n SkuPriceId: string,\n SkuPriceIdv2: string, // Hubs add-on\n x_BaseUnitPrice: real, // Azure\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure MCA\n x_BillingProfileId: string, // Azure MCA\n x_CommitmentDiscountNormalizedRatio: real, // Hubs add-on\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_ContractedUnitPriceDiscount: real, // Hubs add-on\n x_ContractedUnitPriceDiscountPercent: real, // Hubs add-on\n x_EffectivePeriodEnd: datetime, // Azure\n x_EffectivePeriodStart: datetime, // Azure\n x_EffectiveUnitPrice: real, // Azure\n x_EffectiveUnitPriceDiscount: real, // Hubs add-on\n x_EffectiveUnitPriceDiscountPercent: real, // Hubs add-on\n x_IngestionTime: datetime, // Hubs add-on\n x_PricingBlockSize: real, // Hubs add-on\n x_PricingSubcategory: string, // Hubs add-on\n x_PricingUnitDescription: string, // Azure\n x_SkuDescription: string, // Azure\n x_SkuId: string, // Azure\n x_SkuIncludedQuantity: real, // Azure EA\n x_SkuMeterCategory: string, // Azure\n x_SkuMeterId: string, // Azure\n x_SkuMeterSubcategory: string, // Azure\n x_SkuMeterType: string, // Azure\n x_SkuPriceType: string, // Azure\n x_SkuProductId: string, // Azure\n x_SkuRegion: string, // Azure\n x_SkuServiceFamily: string, // Azure\n x_SkuOfferId: string, // Azure EA\n x_SkuPartNumber: string, // Azure EA\n x_SkuTerm: int, // Azure\n x_SkuTier: real, // Azure MCA\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_TotalUnitPriceDiscount: real, // Hubs add-on\n x_TotalUnitPriceDiscountPercent: real // Hubs add-on\n)\n\n// Update policy for Prices_raw -> Prices_final_v1_2\n.alter table Prices_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Prices_raw\",\n \"Query\": \"Prices_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Cost and usage |=================================================================================================\n// Supported versions:\n// - MS: 1.2-preview, 1.0, 1.0-preview(v1)\n// https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0\n// https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024\n// https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 \n// https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All costs transformed to FOCUS 1.2.', folder='Costs')\nCosts_transform_v1_2()\n{\n let checkString = (column: string, oldValue: string, newValue: string) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n let checkInt = (column: string, oldValue: int, newValue: int) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n let checkReal = (column: string, oldValue: real, newValue: real) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n Costs_raw\n //\n // Dedupe rows\n | extend x_IngestionTime = ingestion_time()\n | extend x_ChargeId = ''\n // TODO: Consider adding a unique charge ID per row\n // hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // // 1. Resource hierarchy (including resource name), highest to lowest\n // BillingAccountId,\n // x_InvoiceSectionId,\n // x_AccountOwnerId,\n // SubAccountId,\n // x_ResourceGroupName,\n // ResourceName,\n // // 2. Resource details\n // ResourceId,\n // RegionId,\n // Tags,\n // CommitmentDiscountId,\n // x_CostCenter,\n // // 4. Meter details\n // SkuPriceId,\n // x_SkuMeterId,\n // x_SkuPartNumber,\n // x_SkuOfferId,\n // x_SkuDetails,\n // // 5. Date\n // ChargePeriodStart\n // ))\n //\n // Identify data quality issues\n // TODO: Remove x_SourceChanges in v1_3 (or later)\n | extend x_SourceChanges = trim_end(',', strcat(\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based', 'InvalidChargeFrequency,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and EffectiveCost > 0, 'InvalidEffectiveCost,', ''),\n iff((isempty(ContractedCost) or ContractedCost == 0) and EffectiveCost != 0, 'MissingContractedCost,', ''),\n iff((isempty(ContractedUnitPrice) or ContractedUnitPrice == 0) and x_EffectiveUnitPrice != 0, 'MissingContractedUnitPrice,', ''),\n iff(ListCost < ContractedCost, 'ListCostLessThanContractedCost,', ''),\n iff(ContractedCost < EffectiveCost, 'ContractedCostLessThanEffectiveCost,', ''),\n iff((isempty(ListCost) or ListCost == 0) and (ContractedCost != 0 or EffectiveCost != 0), 'MissingListCost,', ''),\n iff((isempty(ListUnitPrice) or ListUnitPrice == 0) and (ContractedUnitPrice != 0 or x_EffectiveUnitPrice != 0), 'MissingListUnitPrice,', ''),\n iff((isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001)\n or (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001),\n 'XEffectiveUnitPriceRoundingError,', ''),\n iff(ConsumedQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingConsumedQuantity,', ''),\n iff(PricingQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingPricingQuantity,', ''),\n iff(isempty(ProviderName), 'MissingProviderName,', ''),\n iff(isempty(PublisherName), 'MissingPublisherName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceId), 'MissingResourceId,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceName), 'MissingResourceName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceType), 'MissingResourceType,', ''),\n iff(BilledCost > 0 and x_BilledUnitPrice == 0, 'MissingXBilledUnitPrice,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(x_ResourceType), 'MissingXResourceType,', ''),\n iff(PricingCategory == 'Standard' and isnotempty(CommitmentDiscountId) and ChargeCategory == 'Usage', 'PricingCategoryShouldBeCommitted,', ''),\n iff(x_SkuTerm == '1Year' or x_SkuTerm == '3Years' or x_SkuTerm == '5Years', 'SkuTermShouldBeAnInteger,', '')\n ))\n //\n // Handle provider columns that moved to FOCUS\n | extend PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency)\n //\n // Backup original prices/costs before the merge\n | extend old_ContractedCost = ContractedCost\n | extend old_ContractedUnitPrice = ContractedUnitPrice\n | extend old_ListCost = ListCost\n | extend old_ListUnitPrice = ListUnitPrice\n | extend old_x_EffectiveUnitPrice = x_EffectiveUnitPrice\n //\n // Fix columns needed in other changes\n | extend old_ProviderName = ProviderName, ProviderName = case(\n isnotempty(ProviderName), ProviderName,\n isnotempty(coalesce(x_CostCategories, x_Discount, x_Operation, x_ServiceCode, x_UsageType)), 'AWS',\n isnotempty(coalesce(tostring(UsageAmount), tostring(x_Cost), x_Credits, x_CostType, tostring(x_CurrencyConversionRate), tostring(x_ExportTime), x_Project, x_ServiceId)), 'GCP',\n isnotempty(coalesce(x_BillingProfileId, x_InvoiceSectionId)), 'Microsoft',\n ''\n )\n //\n // Identify source\n | extend x_SourceName = coalesce(x_SourceName, iff(isnotempty(x_BillingProfileId), 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(isnotempty(x_BillingProfileId), 'FocusCost', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, case(\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)) and isempty(SkuPriceDetails) and isnotempty(x_SkuDetails), '1.2-preview',\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)), '1.2',\n isnotempty(coalesce(ChargeClass, CommitmentDiscountStatus, tostring(ConsumedQuantity), ConsumedUnit, tostring(ContractedCost), tostring(ContractedUnitPrice), RegionId, RegionName)), '1.0',\n isnotempty(coalesce(ChargeSubcategory, Region, tostring(UsageQuantity), UsageUnit)), iff(ProviderName == 'Microsoft', '1.0-preview(v1)', '1.0-preview'),\n ''\n ))\n // Append version check error code\n | extend x_SourceChanges = iff(x_SourceVersion == '1.0', x_SourceChanges,\n strcat(x_SourceChanges, iff(isempty(x_SourceChanges), '', ','), iff(x_SourceVersion == '', 'UnknownFocusVersion', 'LegacyFocusVersion'))\n )\n //\n // Fix quantities\n | extend old_PricingQuantity = PricingQuantity, PricingQuantity = case(\n PricingQuantity != 0 or (EffectiveCost == 0 and BilledCost == 0), PricingQuantity,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(EffectiveCost) and EffectiveCost != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0, EffectiveCost / x_EffectiveUnitPrice,\n PricingQuantity\n )\n | extend old_ConsumedQuantity = ConsumedQuantity, ConsumedQuantity = case(\n isnotempty(ConsumedQuantity) and ConsumedQuantity != 0, ConsumedQuantity,\n ChargeCategory == 'Usage', PricingQuantity / coalesce(x_PricingBlockSize, real(1)),\n ConsumedQuantity\n )\n //\n // Populate missing prices -- mapping to on-demand prices requires meter ID and offer ID\n | extend tmp_MissingPrices = ProviderName == 'Microsoft'\n and (isempty(ListUnitPrice) or isempty(ContractedUnitPrice) or ListUnitPrice == 0 or ContractedUnitPrice == 0)\n and x_EffectiveUnitPrice != 0\n and not(CommitmentDiscountCategory == 'Spend' and CommitmentDiscountStatus == 'Unused')\n and isnotempty(x_SkuMeterId) and isnotempty(x_SkuOfferId)\n | as allCosts\n | where tmp_MissingPrices\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(ChargePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | as costsWithMissingPrices\n | join kind=leftouter (\n Prices_final_v1_2\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(x_EffectivePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | where x_SkuPriceType == 'Consumption' and tmp_ReservationPriceLookupKey in ((costsWithMissingPrices | summarize by tmp_ReservationPriceLookupKey))\n | summarize ListUnitPrice = min(ListUnitPrice), ContractedUnitPrice = min(ContractedUnitPrice) by tmp_ReservationPriceLookupKey, x_PricingBlockSize, PricingUnit\n ) on tmp_ReservationPriceLookupKey\n //\n // Select the best price to use for each row\n | extend x_EffectiveUnitPrice = case(\n // If price is a rounding error away from the billed price, use the billed price\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001, x_BilledUnitPrice,\n // If price is a rounding error away from the contracted price, use the contracted price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001, ContractedUnitPrice,\n x_EffectiveUnitPrice\n )\n | extend ContractedUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ContractedUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ContractedUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // If billed price is available, assume the billed price is the same as contracted price to support aggregations\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, x_EffectiveUnitPrice,\n // Otherwise, assume the effective price is the same as contracted price to support aggregations\n x_EffectiveUnitPrice\n )\n | extend ListUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ListUnitPrice) and ListUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ListUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ListUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ListUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // Otherwise, assume the contracted price is the same as list price to support aggregations\n ContractedUnitPrice\n )\n // Calculate missing costs based on new prices -- If cost is already correct, keep that; if not and price is available, recalculate the cost; otherwise, keep the existing cost\n | extend ContractedCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ContractedCost) and ContractedCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedCost,\n // ContractedCost is 0 in all other scenarios...\n // If 0 and there's a billed cost and prices are the same, use BilledCost\n isnotempty(BilledCost) and BilledCost != 0 and ContractedUnitPrice == x_BilledUnitPrice, BilledCost,\n // If 0 and there's a billed cost and prices are the same, use EffectiveCost\n isnotempty(EffectiveCost) and EffectiveCost != 0 and ContractedUnitPrice == x_EffectiveUnitPrice, EffectiveCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0, ContractedUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume EffectiveCost\n isempty(ContractedUnitPrice) or ContractedUnitPrice == 0, EffectiveCost,\n // Fall back to the original value for any unhandled scenarios\n ContractedCost\n )\n | extend ListCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ListCost) and ListCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ListCost,\n // ListCost is 0 in all other scenarios...\n // If 0 and there's a contracted cost and prices are the same, use ContractedCost\n isnotempty(ContractedCost) and ContractedCost != 0 and ListUnitPrice == ContractedUnitPrice, ContractedCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ListUnitPrice) and ListUnitPrice != 0, ListUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume ContractedCost\n isempty(ListUnitPrice) or ListUnitPrice == 0, ContractedCost,\n // Fall back to the original value for any unhandled scenarios\n ListCost\n )\n // Merge the rest of the unmodified cost records and remove excess columns\n | union (allCosts | where not(tmp_MissingPrices))\n | project-away x_PricingBlockSize1, PricingUnit1, ListUnitPrice1, ContractedUnitPrice1, tmp_MissingPrices, tmp_ReservationPriceLookupKey, tmp_ReservationPriceLookupKey1\n //\n | extend SkuPriceDetails = parse_json(SkuPriceDetails)\n | extend Tags = parse_json(Tags)\n | extend x_SkuDetails = parse_json(x_SkuDetails)\n //\n // Handle FOCUS 1.0-preview\n | extend old_ChargeSubcategory = ChargeSubcategory\n | extend old_ChargeCategory = ChargeCategory, ChargeCategory = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Credit', 'Credit',\n ChargeSubcategory == 'Refund', 'Purchase', // We are assuming purchase refunds since we don't have data to indicate usage refunds\n ChargeCategory\n )\n | extend old_ChargeClass = ChargeClass, ChargeClass = case(ChargeSubcategory == 'Refund', 'Correction', ChargeClass)\n //\n // Populate CapacityReservationId when not specified\n | extend CapacityReservationId = coalesce(CapacityReservationId, tostring(coalesce(x_SkuDetails.VMCapacityReservationId, SkuPriceDetails.VMCapacityReservationId, SkuPriceDetails.x_VMCapacityReservationId)))\n | extend old_CapacityReservationStatus = CapacityReservationStatus, CapacityReservationStatus = case(\n isempty(CapacityReservationId), '',\n isnotempty(CapacityReservationStatus), CapacityReservationStatus,\n tolower(x_ResourceType) == 'microsoft.compute/capacityreservationgroups/capacityreservations', 'Unused',\n 'Used'\n )\n //\n // BUG: ChargeFrequency shows \"Usage-Based\" for monthly recurring savings plan purchases\n | extend old_ChargeFrequency = ChargeFrequency, ChargeFrequency = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based' and ProviderName == 'Microsoft' and x_SourceVersion startswith '1.0', 'Recurring', ChargeFrequency)\n //\n // Commitment discounts\n | extend x_CommitmentDiscountNormalizedRatio = case(\n // Calculate from CommitmentDiscountQuantity, if specified\n isnotempty(CommitmentDiscountQuantity) and CommitmentDiscountQuantity != 0, CommitmentDiscountQuantity / PricingQuantity / coalesce(x_PricingBlockSize, real(1)),\n // Not applicable\n isempty(CommitmentDiscountStatus), real(null),\n // Parse from SKU details if not specified explicitly\n toreal(coalesce(x_SkuDetails.RINormalizationRatio, SkuPriceDetails.RINormalizationRatio, SkuPriceDetails.x_RINormalizationRatio, dynamic(1)))\n )\n | extend old_CommitmentDiscountQuantity = CommitmentDiscountQuantity, CommitmentDiscountQuantity = case(\n // FOCUS 1.2\n isnotempty(CommitmentDiscountQuantity), CommitmentDiscountQuantity,\n // FOCUS 1.0-preview, 1.0\n isempty(CommitmentDiscountStatus), real(null),\n CommitmentDiscountCategory == 'Spend', EffectiveCost / coalesce(x_BillingExchangeRate, real(1)),\n CommitmentDiscountCategory == 'Usage' and isnotempty(x_CommitmentDiscountNormalizedRatio), PricingQuantity / coalesce(x_PricingBlockSize, real(1)) * x_CommitmentDiscountNormalizedRatio,\n real(null)\n )\n | extend old_CommitmentDiscountUnit = CommitmentDiscountUnit, CommitmentDiscountUnit = case(\n // FOCUS 1.2\n isnotempty(CommitmentDiscountUnit), CommitmentDiscountUnit,\n // FOCUS 1.0\n isempty(CommitmentDiscountQuantity), '',\n CommitmentDiscountCategory == 'Spend', PricingCurrency,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio == real(1), ConsumedUnit,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio > real(1), strcat('Normalized ', ConsumedUnit),\n ''\n )\n | extend old_CommitmentDiscountStatus = CommitmentDiscountStatus, CommitmentDiscountStatus = case(\n // FOCUS 1.0+\n isnotempty(CommitmentDiscountStatus), CommitmentDiscountStatus,\n // FOCUS 1.0-preview\n ChargeSubcategory == 'Used Commitment', 'Used',\n ChargeSubcategory == 'Unused Commitment', 'Unused',\n ''\n )\n | extend x_CommitmentDiscountUtilizationPotential = case(\n ChargeCategory == 'Purchase', real(0),\n ProviderName == 'Microsoft' and isnotempty(CommitmentDiscountCategory), EffectiveCost,\n CommitmentDiscountCategory == 'Usage', ConsumedQuantity,\n CommitmentDiscountCategory == 'Spend', EffectiveCost,\n real(0)\n )\n | extend x_CommitmentDiscountUtilizationAmount = iff(CommitmentDiscountStatus == 'Used', x_CommitmentDiscountUtilizationPotential, real(0))\n //\n // Pricing\n | extend old_x_AmortizationClass = x_AmortizationClass, x_AmortizationClass = case(\n // FOCUS 1.2\n isnotempty(x_AmortizationClass), x_AmortizationClass,\n // FOCUS 1.0-preview+\n ChargeCategory == 'Purchase' and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeCategory == 'Usage' and isnotempty(CommitmentDiscountId) and isnotempty(CommitmentDiscountStatus), 'Amortized Charge',\n ''\n )\n | extend old_PricingCategory = PricingCategory, PricingCategory = case(\n // FOCUS 1.0+\n isnotempty(PricingCategory), PricingCategory,\n // FOCUS 1.0-preview\n PricingCategory == 'On-Demand', 'Standard',\n PricingCategory == 'Commitment-Based', 'Committed',\n ''\n )\n //\n // Commitment discount utilization\n | extend x_CommitmentDiscountUtilizationPotential = case(\n ChargeCategory == 'Purchase', real(0),\n ProviderName == 'Microsoft' and isnotempty(CommitmentDiscountCategory), EffectiveCost,\n CommitmentDiscountCategory == 'Usage', ConsumedQuantity,\n CommitmentDiscountCategory == 'Spend', EffectiveCost,\n real(0)\n )\n | extend x_CommitmentDiscountUtilizationAmount = iff(CommitmentDiscountStatus == 'Used', x_CommitmentDiscountUtilizationPotential, real(0))\n //\n // BUG: Fix ContractedCost that has bad values\n | extend ContractedCost = iff(ProviderName == 'Microsoft' and isnotempty(PricingQuantity) and isnotempty(x_PricingBlockSize) and ContractedCost != ContractedUnitPrice * PricingQuantity, ContractedUnitPrice * PricingQuantity, ContractedCost)\n //\n // Handle FOCUS 1.0-preview UsageQuantity/Unit\n | extend ConsumedQuantity = iff(ChargeCategory == 'Usage', coalesce(ConsumedQuantity, UsageQuantity, UsageAmount), real(null))\n | extend old_ConsumedUnit = ConsumedUnit, ConsumedUnit = iff(ChargeCategory == 'Usage' and isnotempty(ConsumedQuantity), coalesce(ConsumedUnit, UsageUnit, 'Units'), '')\n //\n // Convert IDs to lowercase for consistency\n | extend BillingAccountId = tolower(BillingAccountId)\n | extend CommitmentDiscountId = tolower(CommitmentDiscountId)\n //\n // BUG: Remove EffectiveCost for commitment discount purchases\n | extend old_EffectiveCost = EffectiveCost, EffectiveCost = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), real(0), EffectiveCost)\n | extend old_x_EffectiveCostInUsd = x_EffectiveCostInUsd, x_EffectiveCostInUsd = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), real(0), x_EffectiveCostInUsd)\n //\n // Clean up resource columns\n | extend old_ResourceId = ResourceId, ResourceId = case(\n isnotempty(ResourceId), ResourceId,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), CommitmentDiscountId,\n ResourceId\n )\n | extend old_ResourceName = ResourceName, ResourceName = tolower(case(\n isnotempty(ResourceName), ResourceName,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountName), CommitmentDiscountName,\n isnotempty(ResourceId), parse_resourceid(ResourceId).ResourceName,\n ResourceName\n ))\n | extend old_x_ResourceType = x_ResourceType, x_ResourceType = case(\n isnotempty(x_ResourceType), x_ResourceType,\n isnotempty(ResourceId), parse_resourceid(ResourceId).x_ResourceType,\n x_ResourceType\n )\n | extend old_ResourceType = ResourceType, ResourceType = case(\n // Use existing resource type display name unless it's an internal resource type ID\n isnotempty(ResourceType) and tolower(ResourceType) != tolower(x_ResourceType) and ResourceType !contains '/', ResourceType,\n // Use CommitmentDiscountType for commitment discount purchases\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountType), CommitmentDiscountType,\n // Look up display name from internal type\n isnotempty(x_ResourceType), coalesce(tostring(resource_type(x_ResourceType).SingularDisplayName), ResourceType, x_ResourceType),\n ResourceType\n )\n //\n // Handle missing values\n | extend old_PublisherName = PublisherName, PublisherName = case(PublisherName == 'Microsoft Corporation', 'Microsoft', isnotempty(PublisherName), PublisherName, x_PublisherCategory == 'Cloud Provider', ProviderName, '')\n //\n // Handle FOCUS 1.0-preview Region column\n | extend old_Region = Region\n | extend old_RegionId = RegionId, RegionId = coalesce(RegionId, iff(ProviderName == 'Microsoft', replace_string(tolower(Region), ' ', ''), Region))\n | extend RegionName = coalesce(RegionName, Region)\n //\n // SKU properties\n | extend x_SkuCoreCount = toint(coalesce(SkuPriceDetails.CoreCount, SkuPriceDetails.x_VCPUs, x_SkuDetails.VCPUs, SkuPriceDetails.x_VCores, x_SkuDetails.VCores, SkuPriceDetails.x_vCores, x_SkuDetails.vCores))\n | extend x_SkuInstanceType = tostring(coalesce(SkuPriceDetails.InstanceType, SkuPriceDetails.x_ServiceType, x_SkuDetails.ServiceType, SkuPriceDetails.x_ServerSku, x_SkuDetails.ServerSku))\n | extend x_SkuOperatingSystem = case(\n isnotempty(SkuPriceDetails.OperatingSystem), SkuPriceDetails.OperatingSystem,\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Canonical', 'Linux',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL', 'Windows Server',\n x_SkuMeterSubcategory endswith ' Series Windows', 'Windows Server',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType)\n )\n | extend x_ConsumedCoreHours = iff(ConsumedUnit == 'Hours' and isnotempty(x_SkuCoreCount), x_SkuCoreCount * ConsumedQuantity, real(null))\n | extend SkuPriceDetails = case(\n // FOCUS 1.2\n isnotempty(SkuPriceDetails), SkuPriceDetails,\n // FOCUS 1.0-preview, 1.0\n parse_json(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(tostring(x_SkuDetails)\n // Prefix all keys with x_ first to avoid double-prefixing\n , @'([\\{,])\"', @'\\1\"x_')\n // CoreCount for number of CPUs/vCPUs/cores/vCores\n , @'\"x_(VCPUs|VCores|vCores)\":', @'\"CoreCount\":')\n // TODO: DiskMaxIops for disk I/O operations per second (IOPS)\n // TODO: DiskSpace for disk size in GiB\n // TODO: DiskType for the kind of disk (e.g., SSD, HDD, NVMe)\n // TODO: GpuCount for the number of GPUs\n // InstanceType for the resource size/SKU (e.g., ArmSkuName)\n , @'\"x_(ServerSku|ServiceType)\":', @'\"InstanceType\":')\n // TODO: InstanceSeries for the size family/series\n // TODO: MemorySize for the RAM in GiB\n // TODO: NetworkMaxIops for network I/O operations per second (IOPS)\n // TODO: NetworkMaxThroughput for network max throughput for data transfer in Mbps\n // OperatingSystem for the OS name\n , @'(\"x_ImageType\":\"Canonical\")', @'\\1,\"OperatingSystem\":\"Linux\"')\n , @'(\"x_ImageType\":\"Windows Server( BYOL)?\")', @'\\1,\"OperatingSystem\":\"Windows Server\"')\n , @'(\"x_ImageType\":(\"[^\"]+\"))', @'\\1,\"OperatingSystem\":\\2')\n // TODO: Redundancy for the level of redundancy (e.g., Local, Zonal, Global)\n // TODO: StorageClass for the tier of storage (e.g., Hot, Archive, Nearline)\n )\n )\n | extend SkuPriceDetails = iff(isempty(SkuPriceDetails.OperatingSystem) and isnotempty(x_SkuOperatingSystem),\n parse_json(replace_string(tostring(SkuPriceDetails), '}', strcat(@',\"OperatingSystem\":\"', x_SkuOperatingSystem, '\"}'))),\n SkuPriceDetails)\n //\n // Azure Hybrid Benefit\n | extend tmp_SqlAhb = tolower(coalesce(x_SkuDetails.AHB, SkuPriceDetails.x_AHB))\n | extend x_SkuLicenseType = case(\n ChargeCategory != 'Usage', '',\n x_SkuMeterCategory in ('Virtual Machines', 'Virtual Machine Licenses') and (x_SkuMeterSubcategory contains 'Windows' or coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL'), 'Windows Server',\n isnotempty(tmp_SqlAhb) or x_SkuMeterSubcategory == 'SQL Server Azure Hybrid Benefit', 'SQL Server',\n ''\n )\n | extend x_SkuLicenseStatus = case(\n isempty(x_SkuLicenseType), '',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL' or tmp_SqlAhb == 'true' or x_SkuMeterSubcategory contains 'Azure Hybrid Benefit', 'Enabled',\n (x_SkuMeterSubcategory contains 'Windows') or tmp_SqlAhb == 'false', 'Not Enabled',\n ''\n )\n | extend x_SkuLicenseQuantity = case(\n isempty(x_SkuCoreCount) or isempty(x_SkuLicenseType), int(null),\n x_SkuCoreCount <= 8, int(8),\n x_SkuCoreCount > 8, x_SkuCoreCount,\n int(null)\n )\n | extend x_SkuLicenseUnit = iff(isnotempty(x_SkuLicenseQuantity), 'Cores', '')\n //\n // Savings\n | extend x_CommitmentDiscountSavings = iff(isempty(ContractedCost) or ContractedCost == 0 or ContractedCost - EffectiveCost < 0.0001, real(0), ContractedCost - EffectiveCost)\n | extend x_NegotiatedDiscountSavings = iff(isempty(ListCost) or ListCost == 0 or ListCost - ContractedCost < 0.0001, real(0), ListCost - ContractedCost)\n | extend x_TotalSavings = iff(isempty(ListCost) or ListCost == 0 or ListCost - EffectiveCost < 0.0001, real(0), ListCost - EffectiveCost)\n | extend x_CommitmentDiscountPercent = iff(isempty(ContractedUnitPrice) or ContractedUnitPrice == 0 or ContractedUnitPrice - x_EffectiveUnitPrice < 0.0001, real(0), (ContractedUnitPrice - x_EffectiveUnitPrice) / ContractedUnitPrice)\n | extend x_NegotiatedDiscountPercent = iff(isempty(ListUnitPrice) or ListUnitPrice == 0 or ListUnitPrice - ContractedUnitPrice < 0.0001, real(0), (ListUnitPrice - ContractedUnitPrice) / ListUnitPrice)\n | extend x_TotalDiscountPercent = iff(isempty(ListUnitPrice) or ListUnitPrice == 0 or ListUnitPrice - x_EffectiveUnitPrice < 0.0001, real(0), (ListUnitPrice - x_EffectiveUnitPrice) / ListUnitPrice)\n //\n // Minor fixes\n | extend old_BillingPeriodEnd = BillingPeriodEnd, BillingPeriodEnd = startofmonth(BillingPeriodEnd)\n | extend old_BillingPeriodStart = BillingPeriodStart, BillingPeriodStart = startofmonth(BillingPeriodStart)\n //\n // Sort columns and apply final transforms\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId,\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd,\n BillingPeriodStart,\n CapacityReservationId,\n CapacityReservationStatus,\n ChargeCategory,\n ChargeClass,\n ChargeDescription,\n ChargeFrequency,\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId,\n CommitmentDiscountName,\n CommitmentDiscountQuantity,\n CommitmentDiscountStatus,\n CommitmentDiscountType,\n CommitmentDiscountUnit,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost = coalesce(ContractedCost, x_OnDemandCost, x_Cost),\n ContractedUnitPrice = coalesce(ContractedUnitPrice, x_OnDemandUnitPrice),\n EffectiveCost,\n InvoiceId = coalesce(InvoiceId, x_InvoiceId),\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory,\n PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency),\n PricingQuantity,\n PricingUnit,\n ProviderName,\n PublisherName,\n RegionId,\n RegionName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory, // TODO: Populate ServiceSubcategory from ServiceName when missing\n SkuId,\n SkuMeter = coalesce(SkuMeter, x_SkuMeterName),\n SkuPriceDetails,\n SkuPriceId,\n SubAccountId,\n SubAccountName = iff(isempty(SubAccountId), '', SubAccountName),\n SubAccountType,\n Tags,\n x_AccountId = iff(x_AccountId == '-2', '', x_AccountId),\n x_AccountName = iff(x_AccountId == '-2', '', x_AccountName),\n x_AccountOwnerId = iff(x_AccountId == '-2', '', x_AccountOwnerId),\n x_AmortizationClass,\n x_BilledCostInUsd,\n x_BilledUnitPrice,\n x_BillingAccountAgreement = case(\n ProviderName == 'Microsoft' and x_BillingAccountId == x_BillingProfileId, 'EA',\n ProviderName == 'Microsoft' and x_BillingAccountId != x_BillingProfileId, 'MCA',\n ProviderName\n ),\n x_BillingAccountId,\n x_BillingAccountName,\n x_BillingExchangeRate,\n x_BillingExchangeRateDate,\n x_BillingItemCode,\n x_BillingItemName,\n x_BillingProfileId,\n x_BillingProfileName,\n x_ChargeId,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountPercent,\n x_CommitmentDiscountSavings,\n x_CommitmentDiscountSpendEligibility = '', // TODO: Add x_CommitmentDiscountSpendEligibility for Costs\n x_CommitmentDiscountUsageEligibility = '', // TODO: Add x_CommitmentDiscountUsageEligibility for Costs\n x_CommitmentDiscountUtilizationAmount,\n x_CommitmentDiscountUtilizationPotential,\n x_CommodityCode,\n x_CommodityName,\n x_ComponentName,\n x_ComponentType,\n x_ConsumedCoreHours,\n x_ContractedCostInUsd = coalesce(x_ContractedCostInUsd, x_OnDemandCostInUsd),\n x_CostAllocationRuleName,\n x_CostCategories = parse_json(x_CostCategories),\n x_CostCenter,\n x_CostType,\n x_Credits = parse_json(x_Credits),\n x_CurrencyConversionRate,\n x_CustomerId,\n x_CustomerName,\n x_Discount = parse_json(x_Discount),\n x_EffectiveCostInUsd,\n x_EffectiveUnitPrice,\n x_ExportTime,\n x_IngestionTime,\n x_InstanceID,\n x_InvoiceIssuerId,\n x_InvoiceSectionId = case(\n x_InvoiceSectionId == '-2', '',\n x_InvoiceSectionId\n ),\n x_InvoiceSectionName = case(\n x_InvoiceSectionName == 'Unassigned', '',\n x_InvoiceSectionName\n ),\n x_ListCostInUsd,\n x_Location,\n x_NegotiatedDiscountPercent,\n x_NegotiatedDiscountSavings,\n x_Operation,\n x_OwnerAccountID,\n x_PartnerCreditApplied,\n x_PartnerCreditRate,\n x_PricingBlockSize,\n x_PricingSubcategory,\n x_PricingUnitDescription = iff(x_PricingUnitDescription == 'Unassigned', '', x_PricingUnitDescription),\n x_Project,\n x_PublisherCategory,\n x_PublisherId,\n x_ResellerId,\n x_ResellerName,\n x_ResourceGroupName = tolower(x_ResourceGroupName),\n x_ResourceType,\n x_ServiceCode,\n x_ServiceId,\n x_ServiceModel, // TODO: Populate from ServiceName when missing\n x_ServicePeriodEnd,\n x_ServicePeriodStart,\n x_SkuCoreCount,\n x_SkuDescription,\n x_SkuDetails,\n x_SkuInstanceType,\n x_SkuIsCreditEligible,\n x_SkuLicenseQuantity,\n x_SkuLicenseStatus,\n x_SkuLicenseType,\n x_SkuLicenseUnit,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterSubcategory,\n x_SkuOfferId,\n x_SkuOperatingSystem,\n x_SkuOrderId,\n x_SkuOrderName,\n x_SkuPartNumber,\n x_SkuPlanName,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuTerm,\n x_SkuTier,\n x_SourceChanges,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceValues = bag_merge(\n checkString('BillingPeriodEnd', old_BillingPeriodEnd, BillingPeriodEnd),\n checkString('BillingPeriodStart', old_BillingPeriodStart, BillingPeriodStart),\n checkString('CapacityReservationStatus', old_CapacityReservationStatus, CapacityReservationStatus),\n checkString('ChargeCategory', old_ChargeCategory, ChargeCategory),\n checkString('ChargeClass', old_ChargeClass, ChargeClass),\n checkString('ChargeSubcategory', old_ChargeSubcategory, ''), // Not included in final schema; use empty string\n checkString('ChargeFrequency', old_ChargeFrequency, ChargeFrequency),\n checkReal('CommitmentDiscountQuantity', old_CommitmentDiscountQuantity, CommitmentDiscountQuantity),\n checkString('CommitmentDiscountUnit', old_CommitmentDiscountUnit, CommitmentDiscountUnit),\n checkString('CommitmentDiscountStatus', old_CommitmentDiscountStatus, CommitmentDiscountStatus),\n checkReal('ConsumedQuantity', old_ConsumedQuantity, ConsumedQuantity),\n checkString('ConsumedUnit', old_ConsumedUnit, ConsumedUnit),\n checkReal('ContractedCost', old_ContractedCost, ContractedCost),\n checkReal('ContractedUnitPrice', old_ContractedUnitPrice, ContractedUnitPrice),\n checkReal('EffectiveCost', old_EffectiveCost, EffectiveCost),\n checkReal('ListCost', old_ListCost, ListCost),\n checkReal('ListUnitPrice', old_ListUnitPrice, ListUnitPrice),\n checkString('PricingCategory', old_PricingCategory, PricingCategory),\n checkReal('PricingQuantity', old_PricingQuantity, PricingQuantity),\n checkString('ProviderName', old_ProviderName, ProviderName),\n checkString('PublisherName', old_PublisherName, PublisherName),\n checkString('Region', old_Region, ''), // Not included in final schema; use empty string\n checkString('RegionId', old_RegionId, RegionId),\n checkString('ResourceId', old_ResourceId, ResourceId),\n checkString('ResourceName', old_ResourceName, ResourceName),\n checkString('ResourceType', old_ResourceType, ResourceType),\n checkString('x_AmortizationClass', old_x_AmortizationClass, x_AmortizationClass),\n checkReal('x_EffectiveCostInUsd', old_x_EffectiveCostInUsd, x_EffectiveCostInUsd),\n checkReal('x_EffectiveUnitPrice', old_x_EffectiveUnitPrice, x_EffectiveUnitPrice),\n checkString('x_ResourceType', old_x_ResourceType, x_ResourceType)\n ),\n x_SourceVersion,\n x_SubproductName,\n x_TotalDiscountPercent,\n x_TotalSavings,\n x_UsageType\n}\n\n// Costs_final_v1_2 table\n.create-merge table Costs_final_v1_2 (\n AvailabilityZone: string,\n BilledCost: real,\n BillingAccountId: string,\n BillingAccountName: string,\n BillingAccountType: string,\n BillingCurrency: string,\n BillingPeriodEnd: datetime,\n BillingPeriodStart: datetime,\n CapacityReservationId: string,\n CapacityReservationStatus: string,\n ChargeCategory: string,\n ChargeClass: string,\n ChargeDescription: string,\n ChargeFrequency: string,\n ChargePeriodEnd: datetime,\n ChargePeriodStart: datetime,\n CommitmentDiscountCategory: string,\n CommitmentDiscountId: string,\n CommitmentDiscountName: string,\n CommitmentDiscountQuantity: real,\n CommitmentDiscountStatus: string,\n CommitmentDiscountType: string,\n CommitmentDiscountUnit: string,\n ConsumedQuantity: real,\n ConsumedUnit: string,\n ContractedCost: real,\n ContractedUnitPrice: real,\n EffectiveCost: real,\n InvoiceId: string,\n InvoiceIssuerName: string,\n ListCost: real,\n ListUnitPrice: real,\n PricingCategory: string,\n PricingCurrency: string,\n PricingQuantity: real,\n PricingUnit: string,\n ProviderName: string,\n PublisherName: string,\n RegionId: string,\n RegionName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n ServiceCategory: string,\n ServiceName: string,\n ServiceSubcategory: string,\n SkuId: string,\n SkuMeter: string,\n SkuPriceDetails: dynamic,\n SkuPriceId: string,\n SubAccountId: string,\n SubAccountName: string,\n SubAccountType: string,\n Tags: dynamic,\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_AmortizationClass: string, // Azure 1.2-preview+\n x_BilledCostInUsd: real, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: real, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: real, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingItemCode: string, // Alibaba 1.0\n x_BillingItemName: string, // Alibaba 1.0\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_CommitmentDiscountNormalizedRatio: real, // Azure 1.2-preview+\n x_CommitmentDiscountPercent: real, // Hubs add-on\n x_CommitmentDiscountSavings: real, // Hubs add-on\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_CommitmentDiscountUtilizationAmount: real, // Hubs add-on\n x_CommitmentDiscountUtilizationPotential: real, // Hubs add-on\n x_CommodityCode: string, // Alibaba 1.0\n x_CommodityName: string, // Alibaba 1.0\n x_ComponentName: string, // Tencent 1.0\n x_ComponentType: string, // Tencent 1.0\n x_ConsumedCoreHours: real, // Hubs add-on\n x_ContractedCostInUsd: real, // Azure 1.0+\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: dynamic, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_CostType: string, // GCP Jan 2024\n x_Credits: dynamic, // GCP Jan 2024\n x_CurrencyConversionRate: real, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: dynamic, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: real, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: real, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024 / Tencent 1.0\n x_IngestionTime: datetime, // Hubs add-on\n x_InstanceID: string, // Alibaba 1.0\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: real, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_NegotiatedDiscountPercent:real, // Hubs add-on\n x_NegotiatedDiscountSavings:real, // Hubs add-on\n x_Operation: string, // AWS 1.0\n x_OwnerAccountID: string, // Tencent 1.0\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: real, // Azure 1.0-preview(v1)+\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServiceModel: string, // Azure 1.2-preview+\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuCoreCount: int, // Hubs add-on\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: dynamic, // Azure 1.0-preview(v1)+\n x_SkuInstanceType: string, // Hubs add-on\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuLicenseQuantity: int, // Hubs add-on\n x_SkuLicenseStatus: string, // Hubs add-on\n x_SkuLicenseType: string, // Hubs add-on\n x_SkuLicenseUnit: string, // Hubs add-on\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOperatingSystem: string, // Hubs add-on\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuPlanName: string, // Azure 1.2-preview+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceChanges: string, // Hubs add-on\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceValues: dynamic, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubproductName: string, // Tencent 1.0\n x_TotalDiscountPercent: real, // Hubs add-on\n x_TotalSavings: real, // Hubs add-on\n x_UsageType: string // AWS 1.0\n)\n\n// Update policy for Costs_raw -> Costs_final_v1_2 table\n.alter table Costs_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Costs_raw\",\n \"Query\": \"Costs_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Actual costs |===================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_transform_v1_2 function\n.create-or-alter function\nwith (docstring='ActualCost exports transformed to FOCUS 1.2.', folder='Costs')\nActualCosts_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n ActualCosts_raw\n | where ChargeType in ('Purchase', 'Refund') and isnotempty(ReservationId)\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: PublisherName, x_PublisherCategory, x_Environment\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory), take_any(ServiceSubcategory), take_any(x_ServiceModel) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodEnd = Date + 1d,\n ChargePeriodStart = Date,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SkuId = '',\n SkuMeter = MeterName,\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = iff(isempty(SubscriptionId), '', SubscriptionName),\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentType = '',\n x_ComponentName = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = '',\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel,\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for ActualCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": true,\n \"Source\": \"ActualCosts_raw\",\n \"Query\": \"ActualCosts_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Amortized costs |================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_transform_v1_2 function\n.create-or-alter function\nwith (docstring='ActualCost exports transformed to FOCUS 1.2.', folder='Costs')\nAmortizedCosts_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n AmortizedCosts_raw\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: PublisherName, x_PublisherCategory, x_Environment\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory), take_any(ServiceSubcategory), take_any(x_ServiceModel) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodEnd = Date + 1d,\n ChargePeriodStart = Date,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SkuId = '',\n SkuMeter = MeterName,\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = iff(isempty(SubscriptionId), '', SubscriptionName),\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentType = '',\n x_ComponentName = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = '',\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel,\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for AmortizedCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": true,\n \"Source\": \"AmortizedCosts_raw\",\n \"Query\": \"AmortizedCosts_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All commitment discount usage transformed to FOCUS 1.2. This includes reservationdeatils_raw.', folder='Commitment discounts')\nCommitmentDiscountUsage_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n CommitmentDiscountUsage_raw\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Handle resource columns\n | extend ResourceId = tolower(InstanceId)\n | extend tmp_ResourceDetails = parse_resourceid(ResourceId)\n | extend ResourceName = tostring(tmp_ResourceDetails.ResourceName)\n | extend SubAccountId = tostring(tmp_ResourceDetails.SubAccountId)\n | extend x_ResourceGroupName = tostring(tmp_ResourceDetails.x_ResourceGroupName)\n | extend x_ResourceType = tostring(tmp_ResourceDetails.x_ResourceType)\n | lookup kind=leftouter (ResourceTypes | distinct x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n | lookup kind=leftouter (Services | distinct x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n //\n // Sort columns and apply final transforms\n | project\n ChargePeriodEnd = UsageDate + 1d,\n ChargePeriodStart = UsageDate,\n CommitmentDiscountCategory = 'Usage',\n CommitmentDiscountId = tolower(strcat('/providers/microsoft.capacity/reservationorders/', ReservationOrderId, '/reservations/', ReservationId)),\n CommitmentDiscountQuantity = UsedHours * InstanceFlexibilityRatio,\n CommitmentDiscountType = 'Reservation',\n CommitmentDiscountUnit = case(\n InstanceFlexibilityRatio == 1, 'Hours',\n InstanceFlexibilityRatio != 1, 'Normalized Hours',\n ''\n ),\n ConsumedQuantity = UsedHours,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SubAccountId,\n x_CommitmentDiscountCommittedCount = TotalReservedQuantity,\n x_CommitmentDiscountCommittedAmount = ReservedHours,\n // TODO: Is this needed? -- x_CommitmentDiscountKind = Kind,\n x_CommitmentDiscountNormalizedGroup = iff(InstanceFlexibilityGroup == 'NA', '', InstanceFlexibilityGroup),\n x_CommitmentDiscountNormalizedRatio = InstanceFlexibilityRatio,\n x_IngestionTime = ingestion_time(),\n x_ResourceGroupName,\n x_ResourceType,\n // x_RowId = hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // CommitmentDiscountId,\n // ResourceId,\n // ChargePeriodStart\n // )),\n x_ServiceModel,\n x_SkuOrderId = ReservationOrderId,\n x_SkuSize = iff(SkuName == 'NA', '', SkuName),\n x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName)),\n x_SourceProvider = coalesce(x_SourceProvider, ProviderName),\n x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationDetails', '')),\n x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2024-03-01', ''))\n}\n\n// CommitmentDiscountUsage_final_v1_2 table\n.create-merge table CommitmentDiscountUsage_final_v1_2 (\n ChargePeriodEnd: datetime, // Hubs add-on\n ChargePeriodStart: datetime, // MS 2023-03-01\n CommitmentDiscountCategory: string, // Hubs add-on\n CommitmentDiscountId: string, // MS 2023-03-01\n CommitmentDiscountQuantity: real, // MS 2023-03-01\n CommitmentDiscountType: string, // Hubs add-on\n CommitmentDiscountUnit: string, // Hubs add-on\n ConsumedQuantity: real, // MS 2023-03-01\n ProviderName: string, // Hubs add-on\n ResourceId: string, // MS 2023-03-01\n ResourceName: string, // Hubs add-on\n ResourceType: string, // Hubs add-on\n ServiceCategory: string, // Hubs add-on\n ServiceName: string, // Hubs add-on\n ServiceSubcategory: string, // Hubs add-on\n SubAccountId: string, // Hubs add-on\n x_CommitmentDiscountCommittedCount: real, // MS 2023-03-01\n x_CommitmentDiscountCommittedAmount: real, // MS 2023-03-01\n x_CommitmentDiscountNormalizedGroup: string, // MS 2023-03-01\n x_CommitmentDiscountNormalizedRatio: real, // MS 2023-03-01\n x_IngestionTime: datetime, // Hubs add-on\n x_ResourceGroupName: string, // Hubs add-on\n x_ResourceType: string, // Hubs add-on\n x_ServiceModel: string, // Hubs add-on\n x_SkuOrderId: string, // MS 2023-03-01\n x_SkuSize: string, // MS 2023-03-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string // Hubs add-on\n)\n\n// Update policy for CommitmentDiscountUsage_raw -> CommitmentDiscountUsage_final_v1_2 table\n.alter table CommitmentDiscountUsage_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"CommitmentDiscountUsage_raw\",\n \"Query\": \"CommitmentDiscountUsage_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All recommendations transformed to FOCUS 1.2.', folder='Recommendations')\nRecommendations_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Recommendations_raw\n | extend x_IngestionTime = ingestion_time()\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationRecommendations', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Convert JSON cost columns to real\n | extend CostWithNoReservedInstances = case(isnotempty(CostWithNoReservedInstances), CostWithNoReservedInstances, isnotempty(CostWithNoReservedInstancesJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, CostWithNoReservedInstancesJson)), CostWithNoReservedInstances)\n | extend NetSavings = case(isnotempty(NetSavings), NetSavings, isnotempty(NetSavingsJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, NetSavingsJson)), NetSavings)\n | extend TotalCostWithReservedInstances = case(isnotempty(TotalCostWithReservedInstances), TotalCostWithReservedInstances, isnotempty(TotalCostWithReservedInstancesJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, TotalCostWithReservedInstancesJson)), TotalCostWithReservedInstances)\n //\n // Parse x_RecommendationDetails from JSON string (ARG queries serialize to string for Parquet compatibility)\n | extend x_RecommendationDetails = iff(gettype(x_RecommendationDetails) == 'string', parse_json(tostring(x_RecommendationDetails)), x_RecommendationDetails)\n //\n // Normalize x_RecommendationDetails keys to x_PascalCase (Advisor extendedProperties use camelCase)\n // Guard: inject a placeholder key so mv-apply doesn't drop rows with null/empty bags\n | extend x_RecommendationDetails = bag_merge(coalesce(x_RecommendationDetails, dynamic({})), bag_pack('__placeholder', ''))\n | mv-apply k = bag_keys(x_RecommendationDetails) on (\n where isnotempty(tostring(k)) and tostring(k) != '__placeholder'\n | extend newKey = iff(tostring(k) startswith 'x_', tostring(k), strcat('x_', toupper(substring(tostring(k), 0, 1)), substring(tostring(k), 1)))\n | summarize x_RecommendationDetails = make_bag(bag_pack(newKey, x_RecommendationDetails[tostring(k)]))\n )\n //\n // Build recommendation details\n | lookup kind=leftouter (Regions | summarize RegionName = make_set(RegionName)[0] by Location = RegionId) on Location\n | extend x_RecommendationDetails = case(\n // Use incoming x_RecommendationDetails first\n isnotempty(x_RecommendationDetails), x_RecommendationDetails,\n // Create one for reservation recommendations if needed\n x_SourceType == 'ReservationRecommendations', bag_pack(\n 'CommitmentDiscountNormalizedGroup', InstanceFlexibilityGroup,\n 'CommitmentDiscountNormalizedRatio', InstanceFlexibilityRatio,\n 'CommitmentDiscountNormalizedSize', NormalizedSize,\n 'CommitmentDiscountResourceType', ResourceType,\n 'CommitmentDiscountScope', Scope,\n 'LookbackPeriodDuration', case(\n LookBackPeriod matches regex @'^Last([0-9]+)Days$', replace_regex(LookBackPeriod, @'^Last([0-9]+)Days$', @'P\\1D'),\n LookBackPeriod matches regex @'^[0-9]+$', strcat('P', LookBackPeriod, 'D'),\n ''\n ),\n 'LookbackPeriodStart', FirstUsageDate,\n 'RecommendedQuantity', RecommendedQuantity,\n 'RecommendedQuantityNormalized', RecommendedQuantityNormalized,\n 'RegionId', Location,\n 'RegionName', RegionName,\n 'SkuMeterId', MeterId,\n 'SkuPriceDetails', SkuProperties,\n 'SkuSize', coalesce(SKU, SkuName),\n 'SkuTerm', isoMonths(Term)\n ),\n dynamic({})\n )\n //\n // Prefer specified date, then fall back to generating a date based on reservation recommendation lookback period, then validate to ensure it's not in the future\n | extend x_RecommendationDate = coalesce(x_RecommendationDate, FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d))\n | extend x_RecommendationDate = iff(x_RecommendationDate > now(), startofday(now()), x_RecommendationDate)\n //\n // Derive x_ResourceType from ResourceId\n | extend tmp_ResourceType = tostring(parse_resourceid(ResourceId).x_ResourceType)\n | extend x_RecommendationDetails = iff(isnotempty(tmp_ResourceType), bag_merge(bag_pack('x_ResourceType', tmp_ResourceType), x_RecommendationDetails), x_RecommendationDetails)\n //\n // Set ResourceType display name from x_ResourceType code\n | extend ResourceType = coalesce(ResourceType, tostring(resource_type(tmp_ResourceType).SingularDisplayName), tmp_ResourceType)\n //\n | project\n ProviderName,\n ResourceId = tolower(ResourceId), // Force lowercase for consistent grouping/filtering\n ResourceName = tolower(iff(tmp_ResourceType =~ 'microsoft.resources/subscriptions', coalesce(SubAccountName, ResourceName), ResourceName)), // Use subscription name for subscription-level recommendations\n ResourceType,\n SubAccountId = coalesce(SubAccountId, iff(isnotempty(SubscriptionId), strcat('/subscriptions/', SubscriptionId), '')),\n SubAccountName,\n x_EffectiveCostAfter = coalesce(x_EffectiveCostAfter, TotalCostWithReservedInstances),\n x_EffectiveCostBefore = coalesce(x_EffectiveCostBefore, CostWithNoReservedInstances),\n x_EffectiveCostSavings = coalesce(x_EffectiveCostSavings, NetSavings, toreal(x_RecommendationDetails.x_SavingsAmount), toreal(x_RecommendationDetails.x_AnnualSavingsAmount) / 12),\n x_IngestionTime,\n x_RecommendationCategory, // TODO: Set for reservation recommendations\n x_RecommendationDate,\n x_RecommendationDescription = coalesce(x_RecommendationDescription, tostring(x_RecommendationDetails.x_RecommendationSolution), tostring(x_RecommendationDetails.x_RecommendationSubCategory)),\n x_RecommendationDetails,\n x_RecommendationId = tolower(x_RecommendationId), // TODO: Set for reservation recommendations; force lowercase for consistent grouping/filtering\n x_ResourceGroupName = tolower(x_ResourceGroupName), // Force lowercase for consistent grouping/filtering\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n// Recommendations_final_v1_2 table\n.create-merge table Recommendations_final_v1_2 (\n ProviderName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n SubAccountId: string,\n SubAccountName: string,\n x_EffectiveCostAfter: real,\n x_EffectiveCostBefore: real,\n x_EffectiveCostSavings: real,\n x_IngestionTime: datetime,\n x_RecommendationCategory: string,\n x_RecommendationDate: datetime,\n x_RecommendationDescription: string,\n x_RecommendationDetails: dynamic,\n x_RecommendationId: string,\n x_ResourceGroupName: string,\n x_SourceName: string,\n x_SourceProvider: string,\n x_SourceType: string,\n x_SourceVersion: string\n)\n\n// Update policy for Recommendations_raw -> Recommendations_final_v1_2 table\n.alter table Recommendations_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Recommendations_raw\",\n \"Query\": \"Recommendations_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All transactions transformed to FOCUS 1.2.', folder='Transactions')\nTransactions_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Transactions_raw\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationTransactions', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Handle BillingPeriodStart/End\n | extend BillingMonth = tostring(BillingMonth)\n | extend BillingPeriodStart = iff(isempty(BillingMonth), datetime(null), todatetime(strcat(substring(BillingMonth, 0, 4), \"-\", substring(BillingMonth, 4, 2), \"-\", substring(BillingMonth, 6, 2))))\n | extend BillingPeriodEnd = iff(isempty(BillingMonth), datetime(null), startofmonth(endofmonth(BillingPeriodStart) + 1d))\n //\n // Sort columns and apply final transforms\n | project\n BilledCost = Amount,\n BillingAccountId = case(\n BillingProfileId startswith '/', BillingProfileId,\n isnotempty(CurrentEnrollmentId), strcat('/providers/Microsoft.Billing/billingAccounts/', CurrentEnrollmentId),\n isnotempty(BillingProfileId), strcat('/providers/Microsoft.Billing/billingProfiles/', BillingProfileId),\n ''\n ),\n BillingAccountName = coalesce(BillingProfileName, CurrentEnrollmentId),\n BillingCurrency = Currency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory = case(\n EventType in ('Cancel', 'Purchase', 'Refund'), 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = case(\n EventType == 'Cancel', 'Cancel', // FOCUS does not handle this scenario\n EventType == 'Refund', 'Correction',\n ''\n ),\n ChargeDescription = Description,\n ChargeFrequency = case(\n BillingFrequency == 'OneTime', 'One-Time',\n BillingFrequency == 'Recurring', 'Recurring',\n BillingFrequency\n ),\n ChargePeriodStart = EventDate,\n InvoiceId,\n PricingQuantity = Quantity,\n PricingUnit = 'Reservations',\n ProviderName,\n RegionId = Region,\n RegionName = Region,\n SubAccountId = iff(isempty(PurchasingSubscriptionGuid), '', strcat('/subscriptions/', PurchasingSubscriptionGuid)),\n SubAccountName = iff(isempty(PurchasingSubscriptionGuid), '', PurchasingSubscriptionName),\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerEmail,\n x_CostCenter = CostCenter,\n x_InvoiceNumber = Invoice,\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = coalesce(InvoiceSectionName, DepartmentName),\n x_IngestionTime = ingestion_time(),\n x_MonetaryCommitment = MonetaryCommitment,\n x_Overage = Overage,\n x_PurchasingBillingAccountId = PurchasingEnrollment,\n x_SkuOrderId = ReservationOrderId,\n x_SkuOrderName = ReservationOrderName,\n x_SkuSize = ArmSkuName,\n x_SkuTerm = isoMonths(Term),\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId = PurchasingSubscriptionGuid,\n x_TransactionType = EventType\n}\n\n// Transactions_final_v1_2 table\n.create-merge table Transactions_final_v1_2 (\n BilledCost: real, // MS CM EA+MCA 2023-05-01\n BillingAccountId: string, // MS CM EA+MCA 2023-05-01\n BillingAccountName: string, // MS CM EA+MCA 2023-05-01\n BillingCurrency: string, // MS CM EA+MCA 2023-05-01\n BillingPeriodEnd: datetime, // MS CM EA+MCA 2023-05-01\n BillingPeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n ChargeCategory: string, // Hubs add-on\n ChargeClass: string, // Hubs add-on\n ChargeDescription: string, // MS CM EA+MCA 2023-05-01\n ChargeFrequency: string, // MS CM EA+MCA 2023-05-01\n ChargePeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n InvoiceId: string, // MS CM MCA 2023-05-01\n PricingQuantity: real, // MS CM EA+MCA 2023-05-01\n PricingUnit: string, // Hubs add-on\n ProviderName: string, // Hubs add-on\n RegionId: string, // MS CM EA+MCA 2023-05-01\n RegionName: string, // MS CM EA+MCA 2023-05-01\n SubAccountId: string, // MS CM EA+MCA 2023-05-01\n SubAccountName: string, // MS CM EA+MCA 2023-05-01\n x_AccountName: string, // MS CM EA 2023-05-01\n x_AccountOwnerId: string, // MS CM EA 2023-05-01\n x_CostCenter: string, // MS CM EA 2023-05-01\n x_InvoiceNumber: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionId: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionName: string, // MS CM MCA 2023-05-01\n x_IngestionTime: datetime, // Hubs add-on\n x_MonetaryCommitment: real, // MS CM EA 2023-05-01\n x_Overage: real, // MS CM EA 2023-05-01\n x_PurchasingBillingAccountId: string, // MS CM EA 2023-05-01\n x_SkuOrderId: string, // MS CM EA+MCA 2023-05-01\n x_SkuOrderName: string, // MS CM EA+MCA 2023-05-01\n x_SkuSize: string, // MS CM EA+MCA 2023-05-01\n x_SkuTerm: int, // MS CM EA+MCA 2023-05-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubscriptionId: string, // MS CM EA+MCA 2023-05-01\n x_TransactionType: string // MS CM EA+MCA 2023-05-01\n)\n\n// Update policy for Transactions_raw -> Transactions_final_v1_2 table\n.alter table Transactions_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Transactions_raw\",\n \"Query\": \"Transactions_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n", + "$fxv#10": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// See known issues @ https://github.com/microsoft/finops-toolkit/issues/1111\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Prices |=========================================================================================================\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_transform_v1_2 function\n.create-or-alter function\nwith (docstring='Transforms Prices_raw into FOCUS 1.2.', folder='Prices')\nPrices_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n let prices = materialize(\n Prices_raw\n | extend PricingCurrency = coalesce(Currency, CurrencyCode) // CurrencyCode last as a fallback only\n | extend x_SkuId = coalesce(SkuId, SkuID)\n | extend x_SkuMeterId = coalesce(MeterId, MeterID)\n | extend x_SkuProductId = coalesce(ProductId, ProductID)\n | extend x_SkuTerm = isoMonths(Term)\n | project-rename\n SkuMeter = MeterName,\n x_BaseUnitPrice = BasePrice,\n x_EffectivePeriodEnd = EffectiveEndDate,\n x_EffectivePeriodStart = EffectiveStartDate,\n x_PricingUnitDescription = UnitOfMeasure,\n x_SkuIncludedQuantity = IncludedQuantity,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuMeterType = MeterType,\n x_SkuOfferId = OfferID,\n x_SkuPartNumber = PartNumber,\n x_SkuPriceType = PriceType,\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTier = TierMinimumUnits\n | extend ContractedUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', UnitPrice, real(null)) // UnitPrice for savings plan is not the on-demand unit price\n | extend ListUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', MarketPrice, real(null)) // MarketPrice for savings plan is not the list price\n | extend ChargeCategory = case(\n x_SkuPriceType == 'Consumption', 'Usage',\n x_SkuPriceType == 'ReservedInstance', 'Purchase',\n x_SkuPriceType == 'SavingsPlan', 'Usage', // Savings plan prices are for committed usage, not the purchase\n ''\n )\n | extend SkuPriceIdv2 = strcat(case(x_SkuPriceType == 'Consumption', 'OD', x_SkuPriceType == 'ReservedInstance', 'RI', x_SkuPriceType == 'SavingsPlan', 'SP', 'XX'), substring(ChargeCategory, 0, 1), x_SkuTerm, '_', x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType, '_', x_SkuTier, x_SkuOfferId)\n | extend x_BillingAccountId = iff(BillingAccountId startswith '/', split(BillingAccountId, '/')[-1], coalesce(BillingAccountId, EnrollmentNumber))\n | extend x_BillingProfileId = iff(BillingProfileId startswith '/', split(BillingProfileId, '/')[-1], coalesce(BillingProfileId, EnrollmentNumber))\n | extend tmp_SavingsPlanKey = strcat(x_SkuMeterId, x_SkuProductId, x_SkuId, x_SkuTier, x_SkuOfferId)\n //\n // Get latest ingested row based on the unique ID\n | extend x_IngestionTime = ingestion_time()\n );\n //\n // Meters for reservations and savings plans to identify commitment eligibility\n let riMeters = prices | where x_SkuPriceType == 'ReservedInstance' | distinct x_SkuMeterId;\n let spMeters = prices | where x_SkuPriceType == 'SavingsPlan' | distinct x_SkuMeterId;\n //\n // Copy list/base/contracted prices from on-demand SKUs\n prices\n | where x_SkuPriceType == 'SavingsPlan'\n // If we use join, specify the shuffle key\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter hint.strategy=shuffle (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | lookup kind=leftouter (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | extend ListUnitPrice = coalesce(ListUnitPrice, ListUnitPrice1)\n | extend ContractedUnitPrice = coalesce(ContractedUnitPrice, ContractedUnitPrice1)\n | extend x_BaseUnitPrice = coalesce(x_BaseUnitPrice, x_BaseUnitPrice1)\n | project-away ListUnitPrice1, ContractedUnitPrice1, x_BaseUnitPrice1, tmp_SavingsPlanKey\n | union ((prices | where x_SkuPriceType != 'SavingsPlan'))\n //\n // Set CommitmentDiscountCategory for reuse\n | extend CommitmentDiscountCategory = case(\n x_SkuPriceType == 'ReservedInstance', 'Usage',\n x_SkuPriceType == 'SavingsPlan', 'Spend',\n ''\n )\n //\n // Calculate commitment discount eligibility\n // TODO: Would a join be faster?\n // TODO: Check this to ensure it's correct\n | extend x_CommitmentDiscountSpendEligibility = iff(x_SkuMeterId in (riMeters) and x_SkuPriceType != 'ReservedInstance', 'Eligible', 'Not Eligible')\n | extend x_CommitmentDiscountUsageEligibility = iff(x_SkuMeterId in (spMeters), 'Eligible', 'Not Eligible')\n //\n // TODO: Implement x_CommitmentDiscountNormalizedRatio\n | extend x_CommitmentDiscountNormalizedRatio = real(null)\n //\n // Add PricingUnit and x_PricingBlockSize\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter (PricingUnits) on x_PricingUnitDescription | project-away x_PricingUnitDescription1\n | lookup kind=leftouter (PricingUnits) on x_PricingUnitDescription\n //\n | extend x_EffectiveUnitPrice = iff(x_SkuPriceType == 'SavingsPlan', UnitPrice, real(null)) // Savings plan prices are for the effective price, not the contracted price\n | extend x_EffectiveUnitPriceDiscount = ContractedUnitPrice - x_EffectiveUnitPrice\n | extend x_ContractedUnitPriceDiscount = ListUnitPrice - ContractedUnitPrice\n | extend x_TotalUnitPriceDiscount = ListUnitPrice - x_EffectiveUnitPrice\n | project\n BillingAccountId = tolower(case(\n BillingProfileId startswith '/', BillingProfileId,\n BillingAccountId startswith '/', BillingAccountId,\n strcat('/providers/microsoft.billing/billingaccounts/', x_BillingAccountId, iff(x_BillingProfileId == x_BillingAccountId, '', strcat('/billingprofiles/', x_BillingProfileId)))\n )),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName, x_BillingProfileId),\n BillingCurrency = coalesce(BillingCurrency, CurrencyCode, Currency), // Currency last as a fallback only\n ChargeCategory,\n CommitmentDiscountCategory,\n CommitmentDiscountType = case(\n x_SkuPriceType == 'ReservedInstance', 'Reservation',\n x_SkuPriceType == 'SavingsPlan', 'Savings plan',\n ''\n ),\n CommitmentDiscountUnit = case(\n isempty(CommitmentDiscountCategory), '',\n CommitmentDiscountCategory == 'Spend', PricingCurrency,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio == real(1), PricingUnit,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio > real(1), strcat('Normalized ', PricingUnit),\n ''\n ),\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory = case(\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed',\n ''\n ),\n PricingCurrency,\n PricingUnit,\n SkuId = coalesce(ProductId, ProductID),\n SkuMeter,\n SkuPriceId = strcat(x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType),\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement = case(\n strlen(x_BillingAccountId) > 32, 'MCA',\n strlen(x_BillingAccountId) < 32, 'EA',\n 'Unknown'\n ),\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent = 1.0 * x_ContractedUnitPriceDiscount / ListUnitPrice * 100,\n x_EffectivePeriodEnd = startofmonth(x_EffectivePeriodEnd + 1h),\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent = 1.0 * x_EffectiveUnitPriceDiscount / ContractedUnitPrice * 100,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingSubcategory = case(\n x_SkuPriceType == 'Consumption' and (x_SkuIncludedQuantity > 0 or x_SkuTier > 0), 'Tiered',\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed Spend',\n ''\n ),\n x_PricingUnitDescription,\n x_SkuDescription = Product,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName = coalesce(x_SourceName, 'Cost Management'),\n x_SourceProvider = coalesce(x_SourceProvider, 'Microsoft'),\n x_SourceType = coalesce(x_SourceType, 'PriceSheet'),\n x_SourceVersion = coalesce(x_SourceVersion, '2023-05-01'),\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent = 1.0 * x_TotalUnitPriceDiscount / ListUnitPrice * 100\n}\n\n// Prices_final_v1_2 table\n.create-merge table Prices_final_v1_2 (\n BillingAccountId: string,\n BillingAccountName: string,\n BillingCurrency: string,\n ChargeCategory: string,\n CommitmentDiscountCategory: string,\n CommitmentDiscountType: string,\n CommitmentDiscountUnit: string,\n ContractedUnitPrice: real,\n ListUnitPrice: real,\n PricingCategory: string,\n PricingCurrency: string, // Azure\n PricingUnit: string,\n SkuId: string,\n SkuMeter: string, // Azure\n SkuPriceId: string,\n SkuPriceIdv2: string, // Hubs add-on\n x_BaseUnitPrice: real, // Azure\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure MCA\n x_BillingProfileId: string, // Azure MCA\n x_CommitmentDiscountNormalizedRatio: real, // Hubs add-on\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_ContractedUnitPriceDiscount: real, // Hubs add-on\n x_ContractedUnitPriceDiscountPercent: real, // Hubs add-on\n x_EffectivePeriodEnd: datetime, // Azure\n x_EffectivePeriodStart: datetime, // Azure\n x_EffectiveUnitPrice: real, // Azure\n x_EffectiveUnitPriceDiscount: real, // Hubs add-on\n x_EffectiveUnitPriceDiscountPercent: real, // Hubs add-on\n x_IngestionTime: datetime, // Hubs add-on\n x_PricingBlockSize: real, // Hubs add-on\n x_PricingSubcategory: string, // Hubs add-on\n x_PricingUnitDescription: string, // Azure\n x_SkuDescription: string, // Azure\n x_SkuId: string, // Azure\n x_SkuIncludedQuantity: real, // Azure EA\n x_SkuMeterCategory: string, // Azure\n x_SkuMeterId: string, // Azure\n x_SkuMeterSubcategory: string, // Azure\n x_SkuMeterType: string, // Azure\n x_SkuPriceType: string, // Azure\n x_SkuProductId: string, // Azure\n x_SkuRegion: string, // Azure\n x_SkuServiceFamily: string, // Azure\n x_SkuOfferId: string, // Azure EA\n x_SkuPartNumber: string, // Azure EA\n x_SkuTerm: int, // Azure\n x_SkuTier: real, // Azure MCA\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_TotalUnitPriceDiscount: real, // Hubs add-on\n x_TotalUnitPriceDiscountPercent: real // Hubs add-on\n)\n\n// Update policy for Prices_raw -> Prices_final_v1_2\n.alter table Prices_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Prices_raw\",\n \"Query\": \"Prices_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Cost and usage |=================================================================================================\n// Supported versions:\n// - MS: 1.2-preview, 1.0, 1.0-preview(v1)\n// https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0\n// https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024\n// https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 \n// https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All costs transformed to FOCUS 1.2.', folder='Costs')\nCosts_transform_v1_2()\n{\n let checkString = (column: string, oldValue: string, newValue: string) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n let checkInt = (column: string, oldValue: int, newValue: int) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n let checkReal = (column: string, oldValue: real, newValue: real) {\n iff(oldValue == newValue, dynamic({}), bag_pack(column, oldValue))\n };\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n Costs_raw\n //\n // Dedupe rows\n | extend x_IngestionTime = ingestion_time()\n | extend x_ChargeId = ''\n // TODO: Consider adding a unique charge ID per row\n // hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // // 1. Resource hierarchy (including resource name), highest to lowest\n // BillingAccountId,\n // x_InvoiceSectionId,\n // x_AccountOwnerId,\n // SubAccountId,\n // x_ResourceGroupName,\n // ResourceName,\n // // 2. Resource details\n // ResourceId,\n // RegionId,\n // Tags,\n // CommitmentDiscountId,\n // x_CostCenter,\n // // 4. Meter details\n // SkuPriceId,\n // x_SkuMeterId,\n // x_SkuPartNumber,\n // x_SkuOfferId,\n // x_SkuDetails,\n // // 5. Date\n // ChargePeriodStart\n // ))\n //\n // Identify data quality issues\n // TODO: Remove x_SourceChanges in v1_3 (or later)\n | extend x_SourceChanges = trim_end(',', strcat(\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based', 'InvalidChargeFrequency,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and EffectiveCost > 0, 'InvalidEffectiveCost,', ''),\n iff((isempty(ContractedCost) or ContractedCost == 0) and EffectiveCost != 0, 'MissingContractedCost,', ''),\n iff((isempty(ContractedUnitPrice) or ContractedUnitPrice == 0) and x_EffectiveUnitPrice != 0, 'MissingContractedUnitPrice,', ''),\n iff(ListCost < ContractedCost, 'ListCostLessThanContractedCost,', ''),\n iff(ContractedCost < EffectiveCost, 'ContractedCostLessThanEffectiveCost,', ''),\n iff((isempty(ListCost) or ListCost == 0) and (ContractedCost != 0 or EffectiveCost != 0), 'MissingListCost,', ''),\n iff((isempty(ListUnitPrice) or ListUnitPrice == 0) and (ContractedUnitPrice != 0 or x_EffectiveUnitPrice != 0), 'MissingListUnitPrice,', ''),\n iff((isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001)\n or (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001),\n 'XEffectiveUnitPriceRoundingError,', ''),\n iff(ConsumedQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingConsumedQuantity,', ''),\n iff(PricingQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingPricingQuantity,', ''),\n iff(isempty(ProviderName), 'MissingProviderName,', ''),\n iff(isempty(PublisherName), 'MissingPublisherName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceId), 'MissingResourceId,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceName), 'MissingResourceName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceType), 'MissingResourceType,', ''),\n iff(BilledCost > 0 and x_BilledUnitPrice == 0, 'MissingXBilledUnitPrice,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(x_ResourceType), 'MissingXResourceType,', ''),\n iff(PricingCategory == 'Standard' and isnotempty(CommitmentDiscountId) and ChargeCategory == 'Usage', 'PricingCategoryShouldBeCommitted,', ''),\n iff(x_SkuTerm == '1Year' or x_SkuTerm == '3Years' or x_SkuTerm == '5Years', 'SkuTermShouldBeAnInteger,', '')\n ))\n //\n // Handle provider columns that moved to FOCUS\n | extend PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency)\n //\n // Backup original prices/costs before the merge\n | extend old_ContractedCost = ContractedCost\n | extend old_ContractedUnitPrice = ContractedUnitPrice\n | extend old_ListCost = ListCost\n | extend old_ListUnitPrice = ListUnitPrice\n | extend old_x_EffectiveUnitPrice = x_EffectiveUnitPrice\n //\n // Fix columns needed in other changes\n | extend old_ProviderName = ProviderName, ProviderName = case(\n isnotempty(ProviderName), ProviderName,\n isnotempty(coalesce(x_CostCategories, x_Discount, x_Operation, x_ServiceCode, x_UsageType)), 'AWS',\n isnotempty(coalesce(tostring(UsageAmount), tostring(x_Cost), x_Credits, x_CostType, tostring(x_CurrencyConversionRate), tostring(x_ExportTime), x_Project, x_ServiceId)), 'GCP',\n isnotempty(coalesce(x_BillingProfileId, x_InvoiceSectionId)), 'Microsoft',\n ''\n )\n //\n // Identify source\n | extend x_SourceName = coalesce(x_SourceName, iff(isnotempty(x_BillingProfileId), 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(isnotempty(x_BillingProfileId), 'FocusCost', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, case(\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)) and isempty(SkuPriceDetails) and isnotempty(x_SkuDetails), '1.2-preview',\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)), '1.2',\n isnotempty(coalesce(ChargeClass, CommitmentDiscountStatus, tostring(ConsumedQuantity), ConsumedUnit, tostring(ContractedCost), tostring(ContractedUnitPrice), RegionId, RegionName)), '1.0',\n isnotempty(coalesce(ChargeSubcategory, Region, tostring(UsageQuantity), UsageUnit)), iff(ProviderName == 'Microsoft', '1.0-preview(v1)', '1.0-preview'),\n ''\n ))\n // Append version check error code\n | extend x_SourceChanges = iff(x_SourceVersion == '1.0', x_SourceChanges,\n strcat(x_SourceChanges, iff(isempty(x_SourceChanges), '', ','), iff(x_SourceVersion == '', 'UnknownFocusVersion', 'LegacyFocusVersion'))\n )\n //\n // Fix quantities\n | extend old_PricingQuantity = PricingQuantity, PricingQuantity = case(\n PricingQuantity != 0 or (EffectiveCost == 0 and BilledCost == 0), PricingQuantity,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(EffectiveCost) and EffectiveCost != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0, EffectiveCost / x_EffectiveUnitPrice,\n PricingQuantity\n )\n | extend old_ConsumedQuantity = ConsumedQuantity, ConsumedQuantity = case(\n isnotempty(ConsumedQuantity) and ConsumedQuantity != 0, ConsumedQuantity,\n ChargeCategory == 'Usage', PricingQuantity / coalesce(x_PricingBlockSize, real(1)),\n ConsumedQuantity\n )\n //\n // Populate missing prices -- mapping to on-demand prices requires meter ID and offer ID\n | extend tmp_MissingPrices = ProviderName == 'Microsoft'\n and (isempty(ListUnitPrice) or isempty(ContractedUnitPrice) or ListUnitPrice == 0 or ContractedUnitPrice == 0)\n and x_EffectiveUnitPrice != 0\n and not(CommitmentDiscountCategory == 'Spend' and CommitmentDiscountStatus == 'Unused')\n and isnotempty(strcat(x_SkuMeterId, x_SkuOfferId))\n | as allCosts\n | where tmp_MissingPrices\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(ChargePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | as costsWithMissingPrices\n | join kind=leftouter (\n Prices_final_v1_2\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(x_EffectivePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | where x_SkuPriceType == 'Consumption' and tmp_ReservationPriceLookupKey in ((costsWithMissingPrices | summarize by tmp_ReservationPriceLookupKey))\n | summarize ListUnitPrice = min(ListUnitPrice), ContractedUnitPrice = min(ContractedUnitPrice) by tmp_ReservationPriceLookupKey, x_PricingBlockSize, PricingUnit\n ) on tmp_ReservationPriceLookupKey\n //\n // Select the best price to use for each row\n | extend x_EffectiveUnitPrice = case(\n // If price is a rounding error away from the billed price, use the billed price\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001, x_BilledUnitPrice,\n // If price is a rounding error away from the contracted price, use the contracted price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001, ContractedUnitPrice,\n x_EffectiveUnitPrice\n )\n | extend ContractedUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ContractedUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ContractedUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // If billed price is available, assume the billed price is the same as contracted price to support aggregations\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, x_EffectiveUnitPrice,\n // Otherwise, assume the effective price is the same as contracted price to support aggregations\n x_EffectiveUnitPrice\n )\n | extend ListUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ListUnitPrice) and ListUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ListUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ListUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ListUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // Otherwise, assume the contracted price is the same as list price to support aggregations\n ContractedUnitPrice\n )\n // Calculate missing costs based on new prices -- If cost is already correct, keep that; if not and price is available, recalculate the cost; otherwise, keep the existing cost\n | extend ContractedCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ContractedCost) and ContractedCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedCost,\n // ContractedCost is 0 in all other scenarios...\n // If 0 and there's a billed cost and prices are the same, use BilledCost\n isnotempty(BilledCost) and BilledCost != 0 and ContractedUnitPrice == x_BilledUnitPrice, BilledCost,\n // If 0 and there's a billed cost and prices are the same, use EffectiveCost\n isnotempty(EffectiveCost) and EffectiveCost != 0 and ContractedUnitPrice == x_EffectiveUnitPrice, EffectiveCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0, ContractedUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume EffectiveCost\n isempty(ContractedUnitPrice) or ContractedUnitPrice == 0, EffectiveCost,\n // Fall back to the original value for any unhandled scenarios\n ContractedCost\n )\n | extend ListCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ListCost) and ListCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ListCost,\n // ListCost is 0 in all other scenarios...\n // If 0 and there's a contracted cost and prices are the same, use ContractedCost\n isnotempty(ContractedCost) and ContractedCost != 0 and ListUnitPrice == ContractedUnitPrice, ContractedCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ListUnitPrice) and ListUnitPrice != 0, ListUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume ContractedCost\n isempty(ListUnitPrice) or ListUnitPrice == 0, ContractedCost,\n // Fall back to the original value for any unhandled scenarios\n ListCost\n )\n // Merge the rest of the unmodified cost records and remove excess columns\n | union (allCosts | where not(tmp_MissingPrices))\n | project-away x_PricingBlockSize1, PricingUnit1, ListUnitPrice1, ContractedUnitPrice1, tmp_MissingPrices, tmp_ReservationPriceLookupKey, tmp_ReservationPriceLookupKey1\n //\n | extend SkuPriceDetails = parse_json(SkuPriceDetails)\n | extend Tags = parse_json(Tags)\n | extend x_SkuDetails = parse_json(x_SkuDetails)\n //\n // Handle FOCUS 1.0-preview\n | extend old_ChargeSubcategory = ChargeSubcategory\n | extend old_ChargeCategory = ChargeCategory, ChargeCategory = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Credit', 'Credit',\n ChargeSubcategory == 'Refund', 'Purchase', // We are assuming purchase refunds since we don't have data to indicate usage refunds\n ChargeCategory\n )\n | extend old_ChargeClass = ChargeClass, ChargeClass = case(ChargeSubcategory == 'Refund', 'Correction', ChargeClass)\n //\n // Populate CapacityReservationId when not specified\n | extend CapacityReservationId = coalesce(CapacityReservationId, tostring(coalesce(x_SkuDetails.VMCapacityReservationId, SkuPriceDetails.VMCapacityReservationId, SkuPriceDetails.x_VMCapacityReservationId)))\n | extend old_CapacityReservationStatus = CapacityReservationStatus, CapacityReservationStatus = case(\n isempty(CapacityReservationId), '',\n isnotempty(CapacityReservationStatus), CapacityReservationStatus,\n tolower(x_ResourceType) == 'microsoft.compute/capacityreservationgroups/capacityreservations', 'Unused',\n 'Used'\n )\n //\n // BUG: ChargeFrequency shows \"Usage-Based\" for monthly recurring savings plan purchases\n | extend old_ChargeFrequency = ChargeFrequency, ChargeFrequency = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based' and ProviderName == 'Microsoft' and x_SourceVersion startswith '1.0', 'Recurring', ChargeFrequency)\n //\n // Commitment discounts\n | extend x_CommitmentDiscountNormalizedRatio = case(\n // Calculate from CommitmentDiscountQuantity, if specified\n isnotempty(CommitmentDiscountQuantity) and CommitmentDiscountQuantity != 0, CommitmentDiscountQuantity / PricingQuantity / coalesce(x_PricingBlockSize, real(1)),\n // Not applicable\n isempty(CommitmentDiscountStatus), real(null),\n // Parse from SKU details if not specified explicitly\n toreal(coalesce(x_SkuDetails.RINormalizationRatio, SkuPriceDetails.RINormalizationRatio, SkuPriceDetails.x_RINormalizationRatio, dynamic(1)))\n )\n | extend old_CommitmentDiscountQuantity = CommitmentDiscountQuantity, CommitmentDiscountQuantity = case(\n // FOCUS 1.2\n isnotempty(CommitmentDiscountQuantity), CommitmentDiscountQuantity,\n // FOCUS 1.0-preview, 1.0\n isempty(CommitmentDiscountStatus), real(null),\n CommitmentDiscountCategory == 'Spend', EffectiveCost / coalesce(x_BillingExchangeRate, real(1)),\n CommitmentDiscountCategory == 'Usage' and isnotempty(x_CommitmentDiscountNormalizedRatio), PricingQuantity / coalesce(x_PricingBlockSize, real(1)) * x_CommitmentDiscountNormalizedRatio,\n real(null)\n )\n | extend old_CommitmentDiscountUnit = CommitmentDiscountUnit, CommitmentDiscountUnit = case(\n // FOCUS 1.2\n isnotempty(CommitmentDiscountUnit), CommitmentDiscountUnit,\n // FOCUS 1.0\n isempty(CommitmentDiscountQuantity), '',\n CommitmentDiscountCategory == 'Spend', PricingCurrency,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio == real(1), ConsumedUnit,\n CommitmentDiscountCategory == 'Usage' and x_CommitmentDiscountNormalizedRatio > real(1), strcat('Normalized ', ConsumedUnit),\n ''\n )\n | extend old_CommitmentDiscountStatus = CommitmentDiscountStatus, CommitmentDiscountStatus = case(\n // FOCUS 1.0+\n isnotempty(CommitmentDiscountStatus), CommitmentDiscountStatus,\n // FOCUS 1.0-preview\n ChargeSubcategory == 'Used Commitment', 'Used',\n ChargeSubcategory == 'Unused Commitment', 'Unused',\n ''\n )\n | extend x_CommitmentDiscountUtilizationPotential = case(\n ChargeCategory == 'Purchase', real(0),\n ProviderName == 'Microsoft' and isnotempty(CommitmentDiscountCategory), EffectiveCost,\n CommitmentDiscountCategory == 'Usage', ConsumedQuantity,\n CommitmentDiscountCategory == 'Spend', EffectiveCost,\n real(0)\n )\n | extend x_CommitmentDiscountUtilizationAmount = iff(CommitmentDiscountStatus == 'Used', x_CommitmentDiscountUtilizationPotential, real(0))\n //\n // Pricing\n | extend old_x_AmortizationClass = x_AmortizationClass, x_AmortizationClass = case(\n // FOCUS 1.2\n isnotempty(x_AmortizationClass), x_AmortizationClass,\n // FOCUS 1.0-preview+\n ChargeCategory == 'Purchase' and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeCategory == 'Usage' and isnotempty(CommitmentDiscountId) and isnotempty(CommitmentDiscountStatus), 'Amortized Charge',\n ''\n )\n | extend old_PricingCategory = PricingCategory, PricingCategory = case(\n // FOCUS 1.0+\n isnotempty(PricingCategory), PricingCategory,\n // FOCUS 1.0-preview\n PricingCategory == 'On-Demand', 'Standard',\n PricingCategory == 'Commitment-Based', 'Committed',\n ''\n )\n //\n // Commitment discount utilization\n | extend x_CommitmentDiscountUtilizationPotential = case(\n ChargeCategory == 'Purchase', real(0),\n ProviderName == 'Microsoft' and isnotempty(CommitmentDiscountCategory), EffectiveCost,\n CommitmentDiscountCategory == 'Usage', ConsumedQuantity,\n CommitmentDiscountCategory == 'Spend', EffectiveCost,\n real(0)\n )\n | extend x_CommitmentDiscountUtilizationAmount = iff(CommitmentDiscountStatus == 'Used', x_CommitmentDiscountUtilizationPotential, real(0))\n //\n // BUG: Fix ContractedCost that has bad values\n | extend ContractedCost = iff(ProviderName == 'Microsoft' and isnotempty(PricingQuantity) and isnotempty(x_PricingBlockSize) and ContractedCost != ContractedUnitPrice * PricingQuantity, ContractedUnitPrice * PricingQuantity, ContractedCost)\n //\n // Handle FOCUS 1.0-preview UsageQuantity/Unit\n | extend ConsumedQuantity = iff(ChargeCategory == 'Usage', coalesce(ConsumedQuantity, UsageQuantity, UsageAmount), real(null))\n | extend old_ConsumedUnit = ConsumedUnit, ConsumedUnit = iff(ChargeCategory == 'Usage' and isnotempty(ConsumedQuantity), coalesce(ConsumedUnit, UsageUnit, 'Units'), '')\n //\n // Convert IDs to lowercase for consistency\n | extend BillingAccountId = tolower(BillingAccountId)\n | extend CommitmentDiscountId = tolower(CommitmentDiscountId)\n //\n // BUG: Remove EffectiveCost for commitment discount purchases\n | extend old_EffectiveCost = EffectiveCost, EffectiveCost = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), real(0), EffectiveCost)\n | extend old_x_EffectiveCostInUsd = x_EffectiveCostInUsd, x_EffectiveCostInUsd = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), real(0), x_EffectiveCostInUsd)\n //\n // Clean up resource columns\n | extend old_ResourceId = ResourceId, ResourceId = case(\n isnotempty(ResourceId), ResourceId,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), CommitmentDiscountId,\n ResourceId\n )\n | extend old_ResourceName = ResourceName, ResourceName = tolower(case(\n isnotempty(ResourceName), ResourceName,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountName), CommitmentDiscountName,\n isnotempty(ResourceId), parse_resourceid(ResourceId).ResourceName,\n ResourceName\n ))\n | extend old_x_ResourceType = x_ResourceType, x_ResourceType = case(\n isnotempty(x_ResourceType), x_ResourceType,\n isnotempty(ResourceId), parse_resourceid(ResourceId).x_ResourceType,\n x_ResourceType\n )\n | extend old_ResourceType = ResourceType, ResourceType = case(\n // Use existing resource type display name unless it's an internal resource type ID\n isnotempty(ResourceType) and tolower(ResourceType) != tolower(x_ResourceType) and ResourceType !contains '/', ResourceType,\n // Use CommitmentDiscountType for commitment discount purchases\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountType), CommitmentDiscountType,\n // Look up display name from internal type\n isnotempty(x_ResourceType), coalesce(tostring(resource_type(x_ResourceType).SingularDisplayName), ResourceType, x_ResourceType),\n ResourceType\n )\n //\n // Handle missing values\n | extend old_PublisherName = PublisherName, PublisherName = case(PublisherName == 'Microsoft Corporation', 'Microsoft', isnotempty(PublisherName), PublisherName, x_PublisherCategory == 'Cloud Provider', ProviderName, '')\n //\n // Handle FOCUS 1.0-preview Region column\n | extend old_Region = Region\n | extend old_RegionId = RegionId, RegionId = coalesce(RegionId, iff(ProviderName == 'Microsoft', replace_string(tolower(Region), ' ', ''), Region))\n | extend RegionName = coalesce(RegionName, Region)\n //\n // SKU properties\n | extend x_SkuCoreCount = toint(coalesce(SkuPriceDetails.CoreCount, SkuPriceDetails.x_VCPUs, x_SkuDetails.VCPUs, SkuPriceDetails.x_VCores, x_SkuDetails.VCores, SkuPriceDetails.x_vCores, x_SkuDetails.vCores))\n | extend x_SkuInstanceType = tostring(coalesce(SkuPriceDetails.InstanceType, SkuPriceDetails.x_ServiceType, x_SkuDetails.ServiceType, SkuPriceDetails.x_ServerSku, x_SkuDetails.ServerSku))\n | extend x_SkuOperatingSystem = case(\n isnotempty(SkuPriceDetails.OperatingSystem), SkuPriceDetails.OperatingSystem,\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Canonical', 'Linux',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL', 'Windows Server',\n x_SkuMeterSubcategory endswith ' Series Windows', 'Windows Server',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType)\n )\n | extend x_ConsumedCoreHours = iff(ConsumedUnit == 'Hours' and isnotempty(x_SkuCoreCount), x_SkuCoreCount * ConsumedQuantity, real(null))\n | extend SkuPriceDetails = case(\n // FOCUS 1.2\n isnotempty(SkuPriceDetails), SkuPriceDetails,\n // FOCUS 1.0-preview, 1.0\n parse_json(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(tostring(x_SkuDetails)\n // Prefix all keys with x_ first to avoid double-prefixing\n , @'([\\{,])\"', @'\\1\"x_')\n // CoreCount for number of CPUs/vCPUs/cores/vCores\n , @'\"x_(VCPUs|VCores|vCores)\":', @'\"CoreCount\":')\n // TODO: DiskMaxIops for disk I/O operations per second (IOPS)\n // TODO: DiskSpace for disk size in GiB\n // TODO: DiskType for the kind of disk (e.g., SSD, HDD, NVMe)\n // TODO: GpuCount for the number of GPUs\n // InstanceType for the resource size/SKU (e.g., ArmSkuName)\n , @'\"x_(ServerSku|ServiceType)\":', @'\"InstanceType\":')\n // TODO: InstanceSeries for the size family/series\n // TODO: MemorySize for the RAM in GiB\n // TODO: NetworkMaxIops for network I/O operations per second (IOPS)\n // TODO: NetworkMaxThroughput for network max throughput for data transfer in Mbps\n // OperatingSystem for the OS name\n , @'(\"x_ImageType\":\"Canonical\")', @'\\1,\"OperatingSystem\":\"Linux\"')\n , @'(\"x_ImageType\":\"Windows Server( BYOL)?\")', @'\\1,\"OperatingSystem\":\"Windows Server\"')\n , @'(\"x_ImageType\":(\"[^\"]+\"))', @'\\1,\"OperatingSystem\":\\2')\n // TODO: Redundancy for the level of redundancy (e.g., Local, Zonal, Global)\n // TODO: StorageClass for the tier of storage (e.g., Hot, Archive, Nearline)\n )\n )\n | extend SkuPriceDetails = iff(isempty(SkuPriceDetails.OperatingSystem) and isnotempty(x_SkuOperatingSystem),\n parse_json(replace_string(tostring(SkuPriceDetails), '}', strcat(@',\"OperatingSystem\":\"', x_SkuOperatingSystem, '\"}'))),\n SkuPriceDetails)\n //\n // Azure Hybrid Benefit\n | extend tmp_SqlAhb = tolower(coalesce(x_SkuDetails.AHB, SkuPriceDetails.x_AHB))\n | extend x_SkuLicenseType = case(\n ChargeCategory != 'Usage', '',\n x_SkuMeterCategory in ('Virtual Machines', 'Virtual Machine Licenses') and (x_SkuMeterSubcategory contains 'Windows' or coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL'), 'Windows Server',\n isnotempty(tmp_SqlAhb) or x_SkuMeterSubcategory == 'SQL Server Azure Hybrid Benefit', 'SQL Server',\n ''\n )\n | extend x_SkuLicenseStatus = case(\n isempty(x_SkuLicenseType), '',\n coalesce(SkuPriceDetails.x_ImageType, x_SkuDetails.ImageType) == 'Windows Server BYOL' or tmp_SqlAhb == 'true' or x_SkuMeterSubcategory contains 'Azure Hybrid Benefit', 'Enabled',\n (x_SkuMeterSubcategory contains 'Windows') or tmp_SqlAhb == 'false', 'Not Enabled',\n ''\n )\n | extend x_SkuLicenseQuantity = case(\n isempty(x_SkuCoreCount) or isempty(x_SkuLicenseType), int(null),\n x_SkuCoreCount <= 8, int(8),\n x_SkuCoreCount > 8, x_SkuCoreCount,\n int(null)\n )\n | extend x_SkuLicenseUnit = iff(isnotempty(x_SkuLicenseQuantity), 'Cores', '')\n //\n // Savings\n | extend x_CommitmentDiscountSavings = iff(isempty(ContractedCost) or ContractedCost == 0 or ContractedCost - EffectiveCost < 0.0001, real(0), ContractedCost - EffectiveCost)\n | extend x_NegotiatedDiscountSavings = iff(isempty(ListCost) or ListCost == 0 or ListCost - ContractedCost < 0.0001, real(0), ListCost - ContractedCost)\n | extend x_TotalSavings = iff(isempty(ListCost) or ListCost == 0 or ListCost - EffectiveCost < 0.0001, real(0), ListCost - EffectiveCost)\n | extend x_CommitmentDiscountPercent = iff(isempty(ContractedUnitPrice) or ContractedUnitPrice == 0 or ContractedUnitPrice - x_EffectiveUnitPrice < 0.0001, real(0), (ContractedUnitPrice - x_EffectiveUnitPrice) / ContractedUnitPrice)\n | extend x_NegotiatedDiscountPercent = iff(isempty(ListUnitPrice) or ListUnitPrice == 0 or ListUnitPrice - ContractedUnitPrice < 0.0001, real(0), (ListUnitPrice - ContractedUnitPrice) / ListUnitPrice)\n | extend x_TotalDiscountPercent = iff(isempty(ListUnitPrice) or ListUnitPrice == 0 or ListUnitPrice - x_EffectiveUnitPrice < 0.0001, real(0), (ListUnitPrice - x_EffectiveUnitPrice) / ListUnitPrice)\n //\n // Minor fixes\n | extend old_BillingPeriodEnd = BillingPeriodEnd, BillingPeriodEnd = startofmonth(BillingPeriodEnd)\n | extend old_BillingPeriodStart = BillingPeriodStart, BillingPeriodStart = startofmonth(BillingPeriodStart)\n //\n // Sort columns and apply final transforms\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId,\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd,\n BillingPeriodStart,\n CapacityReservationId,\n CapacityReservationStatus,\n ChargeCategory,\n ChargeClass,\n ChargeDescription,\n ChargeFrequency,\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId,\n CommitmentDiscountName,\n CommitmentDiscountQuantity,\n CommitmentDiscountStatus,\n CommitmentDiscountType,\n CommitmentDiscountUnit,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost = coalesce(ContractedCost, x_OnDemandCost, x_Cost),\n ContractedUnitPrice = coalesce(ContractedUnitPrice, x_OnDemandUnitPrice),\n EffectiveCost,\n InvoiceId = coalesce(InvoiceId, x_InvoiceId),\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory,\n PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency),\n PricingQuantity,\n PricingUnit,\n ProviderName,\n PublisherName,\n RegionId,\n RegionName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory, // TODO: Populate ServiceSubcategory from ServiceName when missing\n SkuId,\n SkuMeter = coalesce(SkuMeter, x_SkuMeterName),\n SkuPriceDetails,\n SkuPriceId,\n SubAccountId,\n SubAccountName = iff(isempty(SubAccountId), '', SubAccountName),\n SubAccountType,\n Tags,\n x_AccountId = iff(x_AccountId == '-2', '', x_AccountId),\n x_AccountName = iff(x_AccountId == '-2', '', x_AccountName),\n x_AccountOwnerId = iff(x_AccountId == '-2', '', x_AccountOwnerId),\n x_AmortizationClass,\n x_BilledCostInUsd,\n x_BilledUnitPrice,\n x_BillingAccountAgreement = case(\n ProviderName == 'Microsoft' and x_BillingAccountId == x_BillingProfileId, 'EA',\n ProviderName == 'Microsoft' and x_BillingAccountId != x_BillingProfileId, 'MCA',\n ProviderName\n ),\n x_BillingAccountId,\n x_BillingAccountName,\n x_BillingExchangeRate,\n x_BillingExchangeRateDate,\n x_BillingItemCode,\n x_BillingItemName,\n x_BillingProfileId,\n x_BillingProfileName,\n x_ChargeId,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountPercent,\n x_CommitmentDiscountSavings,\n x_CommitmentDiscountSpendEligibility = '', // TODO: Add x_CommitmentDiscountSpendEligibility for Costs\n x_CommitmentDiscountUsageEligibility = '', // TODO: Add x_CommitmentDiscountUsageEligibility for Costs\n x_CommitmentDiscountUtilizationAmount,\n x_CommitmentDiscountUtilizationPotential,\n x_CommodityCode,\n x_CommodityName,\n x_ComponentName,\n x_ComponentType,\n x_ConsumedCoreHours,\n x_ContractedCostInUsd = coalesce(x_ContractedCostInUsd, x_OnDemandCostInUsd),\n x_CostAllocationRuleName,\n x_CostCategories = parse_json(x_CostCategories),\n x_CostCenter,\n x_CostType,\n x_Credits = parse_json(x_Credits),\n x_CurrencyConversionRate,\n x_CustomerId,\n x_CustomerName,\n x_Discount = parse_json(x_Discount),\n x_EffectiveCostInUsd,\n x_EffectiveUnitPrice,\n x_ExportTime,\n x_IngestionTime,\n x_InstanceID,\n x_InvoiceIssuerId,\n x_InvoiceSectionId = case(\n x_InvoiceSectionId == '-2', '',\n x_InvoiceSectionId\n ),\n x_InvoiceSectionName = case(\n x_InvoiceSectionName == 'Unassigned', '',\n x_InvoiceSectionName\n ),\n x_ListCostInUsd,\n x_Location,\n x_NegotiatedDiscountPercent,\n x_NegotiatedDiscountSavings,\n x_Operation,\n x_OwnerAccountID,\n x_PartnerCreditApplied,\n x_PartnerCreditRate,\n x_PricingBlockSize,\n x_PricingSubcategory,\n x_PricingUnitDescription = iff(x_PricingUnitDescription == 'Unassigned', '', x_PricingUnitDescription),\n x_Project,\n x_PublisherCategory,\n x_PublisherId,\n x_ResellerId,\n x_ResellerName,\n x_ResourceGroupName = tolower(x_ResourceGroupName),\n x_ResourceType,\n x_ServiceCode,\n x_ServiceId,\n x_ServiceModel, // TODO: Populate from ServiceName when missing\n x_ServicePeriodEnd,\n x_ServicePeriodStart,\n x_SkuCoreCount,\n x_SkuDescription,\n x_SkuDetails,\n x_SkuInstanceType,\n x_SkuIsCreditEligible,\n x_SkuLicenseQuantity,\n x_SkuLicenseStatus,\n x_SkuLicenseType,\n x_SkuLicenseUnit,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterSubcategory,\n x_SkuOfferId,\n x_SkuOperatingSystem,\n x_SkuOrderId,\n x_SkuOrderName,\n x_SkuPartNumber,\n x_SkuPlanName,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuTerm,\n x_SkuTier,\n x_SourceChanges,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceValues = bag_merge(\n checkString('BillingPeriodEnd', old_BillingPeriodEnd, BillingPeriodEnd),\n checkString('BillingPeriodStart', old_BillingPeriodStart, BillingPeriodStart),\n checkString('CapacityReservationStatus', old_CapacityReservationStatus, CapacityReservationStatus),\n checkString('ChargeCategory', old_ChargeCategory, ChargeCategory),\n checkString('ChargeClass', old_ChargeClass, ChargeClass),\n checkString('ChargeSubcategory', old_ChargeSubcategory, ''), // Not included in final schema; use empty string\n checkString('ChargeFrequency', old_ChargeFrequency, ChargeFrequency),\n checkReal('CommitmentDiscountQuantity', old_CommitmentDiscountQuantity, CommitmentDiscountQuantity),\n checkString('CommitmentDiscountUnit', old_CommitmentDiscountUnit, CommitmentDiscountUnit),\n checkString('CommitmentDiscountStatus', old_CommitmentDiscountStatus, CommitmentDiscountStatus),\n checkReal('ConsumedQuantity', old_ConsumedQuantity, ConsumedQuantity),\n checkString('ConsumedUnit', old_ConsumedUnit, ConsumedUnit),\n checkReal('ContractedCost', old_ContractedCost, ContractedCost),\n checkReal('ContractedUnitPrice', old_ContractedUnitPrice, ContractedUnitPrice),\n checkReal('EffectiveCost', old_EffectiveCost, EffectiveCost),\n checkReal('ListCost', old_ListCost, ListCost),\n checkReal('ListUnitPrice', old_ListUnitPrice, ListUnitPrice),\n checkString('PricingCategory', old_PricingCategory, PricingCategory),\n checkReal('PricingQuantity', old_PricingQuantity, PricingQuantity),\n checkString('ProviderName', old_ProviderName, ProviderName),\n checkString('PublisherName', old_PublisherName, PublisherName),\n checkString('Region', old_Region, ''), // Not included in final schema; use empty string\n checkString('RegionId', old_RegionId, RegionId),\n checkString('ResourceId', old_ResourceId, ResourceId),\n checkString('ResourceName', old_ResourceName, ResourceName),\n checkString('ResourceType', old_ResourceType, ResourceType),\n checkString('x_AmortizationClass', old_x_AmortizationClass, x_AmortizationClass),\n checkReal('x_EffectiveCostInUsd', old_x_EffectiveCostInUsd, x_EffectiveCostInUsd),\n checkReal('x_EffectiveUnitPrice', old_x_EffectiveUnitPrice, x_EffectiveUnitPrice),\n checkString('x_ResourceType', old_x_ResourceType, x_ResourceType)\n ),\n x_SourceVersion,\n x_SubproductName,\n x_TotalDiscountPercent,\n x_TotalSavings,\n x_UsageType\n}\n\n// Costs_final_v1_2 table\n.create-merge table Costs_final_v1_2 (\n AvailabilityZone: string,\n BilledCost: real,\n BillingAccountId: string,\n BillingAccountName: string,\n BillingAccountType: string,\n BillingCurrency: string,\n BillingPeriodEnd: datetime,\n BillingPeriodStart: datetime,\n CapacityReservationId: string,\n CapacityReservationStatus: string,\n ChargeCategory: string,\n ChargeClass: string,\n ChargeDescription: string,\n ChargeFrequency: string,\n ChargePeriodEnd: datetime,\n ChargePeriodStart: datetime,\n CommitmentDiscountCategory: string,\n CommitmentDiscountId: string,\n CommitmentDiscountName: string,\n CommitmentDiscountQuantity: real,\n CommitmentDiscountStatus: string,\n CommitmentDiscountType: string,\n CommitmentDiscountUnit: string,\n ConsumedQuantity: real,\n ConsumedUnit: string,\n ContractedCost: real,\n ContractedUnitPrice: real,\n EffectiveCost: real,\n InvoiceId: string,\n InvoiceIssuerName: string,\n ListCost: real,\n ListUnitPrice: real,\n PricingCategory: string,\n PricingCurrency: string,\n PricingQuantity: real,\n PricingUnit: string,\n ProviderName: string,\n PublisherName: string,\n RegionId: string,\n RegionName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n ServiceCategory: string,\n ServiceName: string,\n ServiceSubcategory: string,\n SkuId: string,\n SkuMeter: string,\n SkuPriceDetails: dynamic,\n SkuPriceId: string,\n SubAccountId: string,\n SubAccountName: string,\n SubAccountType: string,\n Tags: dynamic,\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_AmortizationClass: string, // Azure 1.2-preview+\n x_BilledCostInUsd: real, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: real, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: real, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingItemCode: string, // Alibaba 1.0\n x_BillingItemName: string, // Alibaba 1.0\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_CommitmentDiscountNormalizedRatio: real, // Azure 1.2-preview+\n x_CommitmentDiscountPercent: real, // Hubs add-on\n x_CommitmentDiscountSavings: real, // Hubs add-on\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_CommitmentDiscountUtilizationAmount: real, // Hubs add-on\n x_CommitmentDiscountUtilizationPotential: real, // Hubs add-on\n x_CommodityCode: string, // Alibaba 1.0\n x_CommodityName: string, // Alibaba 1.0\n x_ComponentName: string, // Tencent 1.0\n x_ComponentType: string, // Tencent 1.0\n x_ConsumedCoreHours: real, // Hubs add-on\n x_ContractedCostInUsd: real, // Azure 1.0+\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: dynamic, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_CostType: string, // GCP Jan 2024\n x_Credits: dynamic, // GCP Jan 2024\n x_CurrencyConversionRate: real, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: dynamic, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: real, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: real, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024 / Tencent 1.0\n x_IngestionTime: datetime, // Hubs add-on\n x_InstanceID: string, // Alibaba 1.0\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: real, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_NegotiatedDiscountPercent:real, // Hubs add-on\n x_NegotiatedDiscountSavings:real, // Hubs add-on\n x_Operation: string, // AWS 1.0\n x_OwnerAccountID: string, // Tencent 1.0\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: real, // Azure 1.0-preview(v1)+\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServiceModel: string, // Azure 1.2-preview+\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuCoreCount: int, // Hubs add-on\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: dynamic, // Azure 1.0-preview(v1)+\n x_SkuInstanceType: string, // Hubs add-on\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuLicenseQuantity: int, // Hubs add-on\n x_SkuLicenseStatus: string, // Hubs add-on\n x_SkuLicenseType: string, // Hubs add-on\n x_SkuLicenseUnit: string, // Hubs add-on\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOperatingSystem: string, // Hubs add-on\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuPlanName: string, // Azure 1.2-preview+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceChanges: string, // Hubs add-on\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceValues: dynamic, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubproductName: string, // Tencent 1.0\n x_TotalDiscountPercent: real, // Hubs add-on\n x_TotalSavings: real, // Hubs add-on\n x_UsageType: string // AWS 1.0\n)\n\n// Update policy for Costs_raw -> Costs_final_v1_2 table\n.alter table Costs_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Costs_raw\",\n \"Query\": \"Costs_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Actual costs |===================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_transform_v1_2 function\n.create-or-alter function\nwith (docstring='ActualCost exports transformed to FOCUS 1.2.', folder='Costs')\nActualCosts_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n ActualCosts_raw\n | where ChargeType in ('Purchase', 'Refund') and isnotempty(ReservationId)\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: PublisherName, x_PublisherCategory, x_Environment\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory), take_any(ServiceSubcategory), take_any(x_ServiceModel) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodEnd = Date + 1d,\n ChargePeriodStart = Date,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SkuId = '',\n SkuMeter = MeterName,\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = iff(isempty(SubscriptionId), '', SubscriptionName),\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentType = '',\n x_ComponentName = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = '',\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel,\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for ActualCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": true,\n \"Source\": \"ActualCosts_raw\",\n \"Query\": \"ActualCosts_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Amortized costs |================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_transform_v1_2 function\n.create-or-alter function\nwith (docstring='ActualCost exports transformed to FOCUS 1.2.', folder='Costs')\nAmortizedCosts_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n AmortizedCosts_raw\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: PublisherName, x_PublisherCategory, x_Environment\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory), take_any(ServiceSubcategory), take_any(x_ServiceModel) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodEnd = Date + 1d,\n ChargePeriodStart = Date,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SkuId = '',\n SkuMeter = MeterName,\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = iff(isempty(SubscriptionId), '', SubscriptionName),\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentType = '',\n x_ComponentName = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = '',\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel,\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for AmortizedCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": true,\n \"Source\": \"AmortizedCosts_raw\",\n \"Query\": \"AmortizedCosts_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All commitment discount usage transformed to FOCUS 1.2. This includes reservationdeatils_raw.', folder='Commitment discounts')\nCommitmentDiscountUsage_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n CommitmentDiscountUsage_raw\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Handle resource columns\n | extend ResourceId = tolower(InstanceId)\n | extend tmp_ResourceDetails = parse_resourceid(ResourceId)\n | extend ResourceName = tostring(tmp_ResourceDetails.ResourceName)\n | extend SubAccountId = tostring(tmp_ResourceDetails.SubAccountId)\n | extend x_ResourceGroupName = tostring(tmp_ResourceDetails.x_ResourceGroupName)\n | extend x_ResourceType = tostring(tmp_ResourceDetails.x_ResourceType)\n | lookup kind=leftouter (ResourceTypes | distinct x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n | lookup kind=leftouter (Services | distinct x_ResourceType, ServiceName, ServiceCategory, ServiceSubcategory, x_ServiceModel) on x_ResourceType\n //\n // Sort columns and apply final transforms\n | project\n ChargePeriodEnd = UsageDate + 1d,\n ChargePeriodStart = UsageDate,\n CommitmentDiscountCategory = 'Usage',\n CommitmentDiscountId = tolower(strcat('/providers/microsoft.capacity/reservationorders/', ReservationOrderId, '/reservations/', ReservationId)),\n CommitmentDiscountQuantity = UsedHours * InstanceFlexibilityRatio,\n CommitmentDiscountType = 'Reservation',\n CommitmentDiscountUnit = case(\n InstanceFlexibilityRatio == 1, 'Hours',\n InstanceFlexibilityRatio != 1, 'Normalized Hours',\n ''\n ),\n ConsumedQuantity = UsedHours,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory,\n SubAccountId,\n x_CommitmentDiscountCommittedCount = TotalReservedQuantity,\n x_CommitmentDiscountCommittedAmount = ReservedHours,\n // TODO: Is this needed? -- x_CommitmentDiscountKind = Kind,\n x_CommitmentDiscountNormalizedGroup = iff(InstanceFlexibilityGroup == 'NA', '', InstanceFlexibilityGroup),\n x_CommitmentDiscountNormalizedRatio = InstanceFlexibilityRatio,\n x_IngestionTime = ingestion_time(),\n x_ResourceGroupName,\n x_ResourceType,\n // x_RowId = hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // CommitmentDiscountId,\n // ResourceId,\n // ChargePeriodStart\n // )),\n x_ServiceModel,\n x_SkuOrderId = ReservationOrderId,\n x_SkuSize = iff(SkuName == 'NA', '', SkuName),\n x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName)),\n x_SourceProvider = coalesce(x_SourceProvider, ProviderName),\n x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationDetails', '')),\n x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2024-03-01', ''))\n}\n\n// CommitmentDiscountUsage_final_v1_2 table\n.create-merge table CommitmentDiscountUsage_final_v1_2 (\n ChargePeriodEnd: datetime, // Hubs add-on\n ChargePeriodStart: datetime, // MS 2023-03-01\n CommitmentDiscountCategory: string, // Hubs add-on\n CommitmentDiscountId: string, // MS 2023-03-01\n CommitmentDiscountQuantity: real, // MS 2023-03-01\n CommitmentDiscountType: string, // Hubs add-on\n CommitmentDiscountUnit: string, // Hubs add-on\n ConsumedQuantity: real, // MS 2023-03-01\n ProviderName: string, // Hubs add-on\n ResourceId: string, // MS 2023-03-01\n ResourceName: string, // Hubs add-on\n ResourceType: string, // Hubs add-on\n ServiceCategory: string, // Hubs add-on\n ServiceName: string, // Hubs add-on\n ServiceSubcategory: string, // Hubs add-on\n SubAccountId: string, // Hubs add-on\n x_CommitmentDiscountCommittedCount: real, // MS 2023-03-01\n x_CommitmentDiscountCommittedAmount: real, // MS 2023-03-01\n x_CommitmentDiscountNormalizedGroup: string, // MS 2023-03-01\n x_CommitmentDiscountNormalizedRatio: real, // MS 2023-03-01\n x_IngestionTime: datetime, // Hubs add-on\n x_ResourceGroupName: string, // Hubs add-on\n x_ResourceType: string, // Hubs add-on\n x_ServiceModel: string, // Hubs add-on\n x_SkuOrderId: string, // MS 2023-03-01\n x_SkuSize: string, // MS 2023-03-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string // Hubs add-on\n)\n\n// Update policy for CommitmentDiscountUsage_raw -> CommitmentDiscountUsage_final_v1_2 table\n.alter table CommitmentDiscountUsage_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"CommitmentDiscountUsage_raw\",\n \"Query\": \"CommitmentDiscountUsage_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All recommendations transformed to FOCUS 1.2.', folder='Recommendations')\nRecommendations_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Recommendations_raw\n | extend x_IngestionTime = ingestion_time()\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationRecommendations', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Convert JSON cost columns to real\n | extend CostWithNoReservedInstances = case(isnotempty(CostWithNoReservedInstances), CostWithNoReservedInstances, isnotempty(CostWithNoReservedInstancesJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, CostWithNoReservedInstancesJson)), CostWithNoReservedInstances)\n | extend NetSavings = case(isnotempty(NetSavings), NetSavings, isnotempty(NetSavingsJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, NetSavingsJson)), NetSavings)\n | extend TotalCostWithReservedInstances = case(isnotempty(TotalCostWithReservedInstances), TotalCostWithReservedInstances, isnotempty(TotalCostWithReservedInstancesJson), toreal(extract(@'\"value\":([0-9\\.]+)', 1, TotalCostWithReservedInstancesJson)), TotalCostWithReservedInstances)\n //\n // Parse x_RecommendationDetails from JSON string (ARG queries serialize to string for Parquet compatibility)\n | extend x_RecommendationDetails = iff(gettype(x_RecommendationDetails) == 'string', parse_json(tostring(x_RecommendationDetails)), x_RecommendationDetails)\n //\n // Normalize x_RecommendationDetails keys to x_PascalCase (Advisor extendedProperties use camelCase)\n // Guard: inject a placeholder key so mv-apply doesn't drop rows with null/empty bags\n | extend x_RecommendationDetails = bag_merge(coalesce(x_RecommendationDetails, dynamic({})), bag_pack('__placeholder', ''))\n | mv-apply k = bag_keys(x_RecommendationDetails) on (\n where isnotempty(tostring(k)) and tostring(k) != '__placeholder'\n | extend newKey = iff(tostring(k) startswith 'x_', tostring(k), strcat('x_', toupper(substring(tostring(k), 0, 1)), substring(tostring(k), 1)))\n | summarize x_RecommendationDetails = make_bag(bag_pack(newKey, x_RecommendationDetails[tostring(k)]))\n )\n //\n // Build recommendation details\n | lookup kind=leftouter (Regions | summarize RegionName = make_set(RegionName)[0] by Location = RegionId) on Location\n | extend x_RecommendationDetails = case(\n // Use incoming x_RecommendationDetails first\n isnotempty(x_RecommendationDetails), x_RecommendationDetails,\n // Create one for reservation recommendations if needed\n x_SourceType == 'ReservationRecommendations', bag_pack(\n 'CommitmentDiscountNormalizedGroup', InstanceFlexibilityGroup,\n 'CommitmentDiscountNormalizedRatio', InstanceFlexibilityRatio,\n 'CommitmentDiscountNormalizedSize', NormalizedSize,\n 'CommitmentDiscountResourceType', ResourceType,\n 'CommitmentDiscountScope', Scope,\n 'LookbackPeriodDuration', case(\n LookBackPeriod matches regex @'^Last([0-9]+)Days$', replace_regex(LookBackPeriod, @'^Last([0-9]+)Days$', @'P\\1D'),\n LookBackPeriod matches regex @'^[0-9]+$', strcat('P', LookBackPeriod, 'D'),\n ''\n ),\n 'LookbackPeriodStart', FirstUsageDate,\n 'RecommendedQuantity', RecommendedQuantity,\n 'RecommendedQuantityNormalized', RecommendedQuantityNormalized,\n 'RegionId', Location,\n 'RegionName', RegionName,\n 'SkuMeterId', MeterId,\n 'SkuPriceDetails', SkuProperties,\n 'SkuSize', coalesce(SKU, SkuName),\n 'SkuTerm', isoMonths(Term)\n ),\n dynamic({})\n )\n //\n // Prefer specified date, then fall back to generating a date based on reservation recommendation lookback period, then validate to ensure it's not in the future\n | extend x_RecommendationDate = coalesce(x_RecommendationDate, FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d))\n | extend x_RecommendationDate = iff(x_RecommendationDate > now(), startofday(now()), x_RecommendationDate)\n //\n // Derive x_ResourceType from ResourceId\n | extend tmp_ResourceType = tostring(parse_resourceid(ResourceId).x_ResourceType)\n | extend x_RecommendationDetails = iff(isnotempty(tmp_ResourceType), bag_merge(bag_pack('x_ResourceType', tmp_ResourceType), x_RecommendationDetails), x_RecommendationDetails)\n //\n // Set ResourceType display name from x_ResourceType code\n | extend ResourceType = coalesce(ResourceType, tostring(resource_type(tmp_ResourceType).SingularDisplayName), tmp_ResourceType)\n //\n | project\n ProviderName,\n ResourceId = tolower(ResourceId), // Force lowercase for consistent grouping/filtering\n ResourceName = tolower(iff(tmp_ResourceType =~ 'microsoft.resources/subscriptions', coalesce(SubAccountName, ResourceName), ResourceName)), // Use subscription name for subscription-level recommendations\n ResourceType,\n SubAccountId = coalesce(SubAccountId, iff(isnotempty(SubscriptionId), strcat('/subscriptions/', SubscriptionId), '')),\n SubAccountName,\n x_EffectiveCostAfter = coalesce(x_EffectiveCostAfter, TotalCostWithReservedInstances),\n x_EffectiveCostBefore = coalesce(x_EffectiveCostBefore, CostWithNoReservedInstances),\n x_EffectiveCostSavings = coalesce(x_EffectiveCostSavings, NetSavings, toreal(x_RecommendationDetails.x_SavingsAmount), toreal(x_RecommendationDetails.x_AnnualSavingsAmount) / 12),\n x_IngestionTime,\n x_RecommendationCategory, // TODO: Set for reservation recommendations\n x_RecommendationDate,\n x_RecommendationDescription = coalesce(x_RecommendationDescription, tostring(x_RecommendationDetails.x_RecommendationSolution), tostring(x_RecommendationDetails.x_RecommendationSubCategory)),\n x_RecommendationDetails,\n x_RecommendationId = tolower(x_RecommendationId), // TODO: Set for reservation recommendations; force lowercase for consistent grouping/filtering\n x_ResourceGroupName = tolower(x_ResourceGroupName), // Force lowercase for consistent grouping/filtering\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n// Recommendations_final_v1_2 table\n.create-merge table Recommendations_final_v1_2 (\n ProviderName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n SubAccountId: string,\n SubAccountName: string,\n x_EffectiveCostAfter: real,\n x_EffectiveCostBefore: real,\n x_EffectiveCostSavings: real,\n x_IngestionTime: datetime,\n x_RecommendationCategory: string,\n x_RecommendationDate: datetime,\n x_RecommendationDescription: string,\n x_RecommendationDetails: dynamic,\n x_RecommendationId: string,\n x_ResourceGroupName: string,\n x_SourceName: string,\n x_SourceProvider: string,\n x_SourceType: string,\n x_SourceVersion: string\n)\n\n// Update policy for Recommendations_raw -> Recommendations_final_v1_2 table\n.alter table Recommendations_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Recommendations_raw\",\n \"Query\": \"Recommendations_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_transform_v1_2 function\n.create-or-alter function\nwith (docstring='All transactions transformed to FOCUS 1.2.', folder='Transactions')\nTransactions_transform_v1_2()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', int(null),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Transactions_raw\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationTransactions', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Handle BillingPeriodStart/End\n | extend BillingMonth = tostring(BillingMonth)\n | extend BillingPeriodStart = iff(isempty(BillingMonth), datetime(null), todatetime(strcat(substring(BillingMonth, 0, 4), \"-\", substring(BillingMonth, 4, 2), \"-\", substring(BillingMonth, 6, 2))))\n | extend BillingPeriodEnd = iff(isempty(BillingMonth), datetime(null), startofmonth(endofmonth(BillingPeriodStart) + 1d))\n //\n // Sort columns and apply final transforms\n | project\n BilledCost = Amount,\n BillingAccountId = case(\n BillingProfileId startswith '/', BillingProfileId,\n isnotempty(CurrentEnrollmentId), strcat('/providers/Microsoft.Billing/billingAccounts/', CurrentEnrollmentId),\n isnotempty(BillingProfileId), strcat('/providers/Microsoft.Billing/billingProfiles/', BillingProfileId),\n ''\n ),\n BillingAccountName = coalesce(BillingProfileName, CurrentEnrollmentId),\n BillingCurrency = Currency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory = case(\n EventType in ('Cancel', 'Purchase', 'Refund'), 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = case(\n EventType == 'Cancel', 'Cancel', // FOCUS does not handle this scenario\n EventType == 'Refund', 'Correction',\n ''\n ),\n ChargeDescription = Description,\n ChargeFrequency = case(\n BillingFrequency == 'OneTime', 'One-Time',\n BillingFrequency == 'Recurring', 'Recurring',\n BillingFrequency\n ),\n ChargePeriodStart = EventDate,\n InvoiceId,\n PricingQuantity = Quantity,\n PricingUnit = 'Reservations',\n ProviderName,\n RegionId = Region,\n RegionName = Region,\n SubAccountId = iff(isempty(PurchasingSubscriptionGuid), '', strcat('/subscriptions/', PurchasingSubscriptionGuid)),\n SubAccountName = iff(isempty(PurchasingSubscriptionGuid), '', PurchasingSubscriptionName),\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerEmail,\n x_CostCenter = CostCenter,\n x_InvoiceNumber = Invoice,\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = coalesce(InvoiceSectionName, DepartmentName),\n x_IngestionTime = ingestion_time(),\n x_MonetaryCommitment = MonetaryCommitment,\n x_Overage = Overage,\n x_PurchasingBillingAccountId = PurchasingEnrollment,\n x_SkuOrderId = ReservationOrderId,\n x_SkuOrderName = ReservationOrderName,\n x_SkuSize = ArmSkuName,\n x_SkuTerm = isoMonths(Term),\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId = PurchasingSubscriptionGuid,\n x_TransactionType = EventType\n}\n\n// Transactions_final_v1_2 table\n.create-merge table Transactions_final_v1_2 (\n BilledCost: real, // MS CM EA+MCA 2023-05-01\n BillingAccountId: string, // MS CM EA+MCA 2023-05-01\n BillingAccountName: string, // MS CM EA+MCA 2023-05-01\n BillingCurrency: string, // MS CM EA+MCA 2023-05-01\n BillingPeriodEnd: datetime, // MS CM EA+MCA 2023-05-01\n BillingPeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n ChargeCategory: string, // Hubs add-on\n ChargeClass: string, // Hubs add-on\n ChargeDescription: string, // MS CM EA+MCA 2023-05-01\n ChargeFrequency: string, // MS CM EA+MCA 2023-05-01\n ChargePeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n InvoiceId: string, // MS CM MCA 2023-05-01\n PricingQuantity: real, // MS CM EA+MCA 2023-05-01\n PricingUnit: string, // Hubs add-on\n ProviderName: string, // Hubs add-on\n RegionId: string, // MS CM EA+MCA 2023-05-01\n RegionName: string, // MS CM EA+MCA 2023-05-01\n SubAccountId: string, // MS CM EA+MCA 2023-05-01\n SubAccountName: string, // MS CM EA+MCA 2023-05-01\n x_AccountName: string, // MS CM EA 2023-05-01\n x_AccountOwnerId: string, // MS CM EA 2023-05-01\n x_CostCenter: string, // MS CM EA 2023-05-01\n x_InvoiceNumber: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionId: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionName: string, // MS CM MCA 2023-05-01\n x_IngestionTime: datetime, // Hubs add-on\n x_MonetaryCommitment: real, // MS CM EA 2023-05-01\n x_Overage: real, // MS CM EA 2023-05-01\n x_PurchasingBillingAccountId: string, // MS CM EA 2023-05-01\n x_SkuOrderId: string, // MS CM EA+MCA 2023-05-01\n x_SkuOrderName: string, // MS CM EA+MCA 2023-05-01\n x_SkuSize: string, // MS CM EA+MCA 2023-05-01\n x_SkuTerm: int, // MS CM EA+MCA 2023-05-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubscriptionId: string, // MS CM EA+MCA 2023-05-01\n x_TransactionType: string // MS CM EA+MCA 2023-05-01\n)\n\n// Update policy for Transactions_raw -> Transactions_final_v1_2 table\n.alter table Transactions_final_v1_2 policy update\n```\n[{\n \"IsEnabled\": true,\n \"Source\": \"Transactions_raw\",\n \"Query\": \"Transactions_transform_v1_2()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n", "$fxv#11": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Common utility functions\n//\n// TIP: Use Ctrl+K,Ctrl+0 to collapse all regions in VS Code\n//======================================================================================================================\n\n\n//===| Date functions |=================================================================================================\n\n// monthstring\n.create-or-alter function \nwith (docstring = @'Returns the name of the month for the specified date (e.g. Jan or January)', folder =@'Common') \nmonthstring(['date']: datetime, length: int = 9)\n{\n substring(dynamic(['January','February','March','April','May','June','July','August','September','October','November','December'])[getmonth(['date']) - 1], 0, length)\n}\n\n// datestring\n.create-or-alter function \nwith (docstring = @'Converts 2 dates into a simple, user-friendly date range (e.g. Jan 1-Jan 3)', folder =@'Common') \ndatestring(start: datetime, end: datetime = datetime('0001-01-01'))\n{\n let month = (d: datetime) { monthstring(d, 3) };\n let endDate = iff(end == datetime('0001-01-01'), start, end);\n let sameDate = startofday(start) == startofday(endDate);\n let sameMonth = startofmonth(start) == startofmonth(endDate);\n let sameYear = startofyear(start) == startofyear(endDate);\n let fullMonth = startofday(start) == startofmonth(start) and startofday(endDate) == startofday(endofmonth(endDate));\n let fullYear = startofday(start) == startofyear(start) and startofday(endDate) == startofday(endofyear(endDate));\n let currentYear = sameYear and startofyear(start) == startofyear(now());\n case(\n // Full year | yyyy (same year) / yyyy-yyyy (diff years)\n fullYear,\n strcat(getyear(start), iff(sameYear, '', strcat('-', getyear(endDate)))),\n // 1 full mo, same year | Mmm yyyy\n fullMonth and sameMonth and sameYear,\n strcat(month(start), ' ', getyear(start)),\n // 2+ full mo, same year | Mmm-Mmm (current year) / Mmm-Mmm yyyy (other year)\n fullMonth and sameYear,\n strcat(month(start), '-', month(endDate), iff(currentYear, '', strcat(' ', getyear(endDate)))),\n // Full mo, diff year | Mmm yyyy-Mmm yyyy\n fullMonth and not(sameYear),\n strcat(month(start), ' ', getyear(start), '-', month(endDate), ' ', getyear(endDate)),\n // Same date | Mmm d (current year) / Mmm d, yyyy (other year)\n sameDate,\n strcat(month(start), ' ', dayofmonth(start), iff(currentYear, '', strcat(', ', getyear(endDate)))),\n // 1 partial M, same Y | Mmm d-d (current year) / Mmm d-d, yyyy (other year)\n not(fullMonth) and sameMonth and sameYear,\n strcat(month(start), ' ', dayofmonth(start), '-', dayofmonth(endDate), iff(currentYear, '', strcat(' ', getyear(endDate)))),\n // 2+ partial M, same Y | Mmm d-Mmm d (current year) / Mmm d-Mmm d, yyyy (other year)\n not(fullMonth) and not(sameMonth) and sameYear,\n strcat(month(start), ' ', dayofmonth(start), '-', month(endDate), ' ', dayofmonth(endDate), iff(currentYear, '', strcat(', ', getyear(endDate)))),\n // All other cases | Mmm d, yyyy-Mmm d, yyyy\n strcat(month(start), ' ', dayofmonth(start), ', ', getyear(start), '-', month(endDate), ' ', dayofmonth(endDate), ', ', getyear(endDate))\n )\n}\n\n// daterange\n.create-or-alter function \nwith (docstring = @'DEPRECATED: Please use datestring(); function will be removed on or after the Jan 2026 release', folder =@'Common') \ndaterange(start: datetime, end: datetime = datetime('0001-01-01'))\n{\n datestring(start, end)\n}\n\n// monthsago\n.create-or-alter function \nwith (docstring = 'DEPRECATED: Please use startofmonth(now(), -<# of months>); function will be removed on or after the Jan 2026 release', folder = 'Common')\nmonthsago(months: int)\n{\n datetime_add('month', -months, startofmonth(now()))\n}\n\n\n//===| Number functions |===============================================================================================\n// NOTE: Must be defined before string converters\n\n// delta\n.create-or-alter function \nwith (docstring = @'Compares 2 values and returns the percentage change from oldval to newval', folder =@'Common') \ndelta(oldval: double, newval: double)\n{\n (newval - todouble(oldval))/oldval\n}\n\n// percentOfTotal\n// NOTE: Must be before percent() function\n.create-or-alter function \nwith (docstring = @'Calculates the percentage of each record based on a required Count column', folder =@'Common') \npercentOfTotal(t: (Count: long), tot: long)\n{\n let total = todouble(tot);\n t \n | extend Percent = round(Count / total * 100, 3) \n | order by Count desc\n}\n\n// percent\n.create-or-alter function \nwith (docstring = @'Calculates the percentage of each record based on a required Count column', folder =@'Common') \npercent(t: (Count: long))\n{\n let total = todouble(toscalar(t | summarize sum(Count)));\n percentOfTotal(t, total)\n}\n\n// plusminus\n.create-or-alter function \nwith (docstring = 'Shows a +/- sign based on the direction of the number', folder = 'Common')\nplusminus(val: string)\n{\n let neg = substring(val, 0, 1) == '-';\n iff(neg, val, strcat('+', val))\n}\n\n// updown\n.create-or-alter function \nwith (docstring = 'Shows an up/down arrow based on the direction of the number', folder = 'Common')\nupdown(val: string)\n{\n // TODO: Handle 0\n let neg = substring(val, 0, 1) == '-';\n iff(neg, strcat('↓', substring(val, 1)), strcat('↑', val))\n}\n\n\n//===| String functions |===============================================================================================\n\n// percentstring\n// NOTE: Must be defined before deltastring\n.create-or-alter function \nwith (docstring = 'Calculate a percentage and render as a string', folder = 'Common')\npercentstring(num: double, total: double = 1.0, places: int = 9)\n{\n let value = 1.0 * num / total * 100;\n strcat(case(\n places != 9, round(value, places),\n value < 10, round(value, 2),\n round(value, 1)\n ), '%')\n}\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// arraystring\n.create-or-alter function \nwith (docstring = 'Convert an array to a comma-delimited string', folder = 'Common')\narraystring(arr: dynamic)\n{\n replace_string(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(\n tostring(arr)\n , @'^\\[\"', '')\n , @'\"\\]$', '')\n , @'^, ', '')\n , @', $', '')\n , @'^\\[]$', '')\n , '\",\"', ', ')\n}\n\n// deltastring\n.create-or-alter function \nwith (docstring = 'Calculate a delta percentage and render as a string', folder = 'Common')\ndeltastring(oldval: double, newval: double, places: int = 1, useArrows: bool = false)\n{\n let d = delta(oldval, newval);\n strcat(case(useArrows and d > 0, '↑', useArrows and d < 0, '↓', d < 0, '-', ''), percentstring(abs(d), 1, places))\n}\n\n// diffstring\n.create-or-alter function \nwith (docstring = 'Calculate the difference and render as a string', folder = 'Common')\ndiffstring(oldval: double, newval: double, places: int = 1)\n{\n plusminus(round(newval - oldval, places))\n}\n\n// numberstring\n.create-or-alter function \nwith (docstring = 'Convert a number to a string', folder = 'Common')\nnumberstring(num: double, abbrev: bool = true)\n{\n replace_regex(case(\n num >= 10000000000000, strcat(round(1.0 * num / 1000000000000, 1), 'T'),\n num >= 1000000000000, strcat(round(1.0 * num / 1000000000000, 2), 'T'),\n num >= 10000000000, strcat(round(1.0 * num / 1000000000, 1), 'B'),\n num >= 1000000000, strcat(round(1.0 * num / 1000000000, 2), 'B'),\n num >= 10000000, strcat(round(1.0 * num / 1000000, 1), 'M'),\n num >= 1000000, strcat(round(1.0 * num / 1000000, 2), 'M'),\n num >= 10000, strcat(round(1.0 * num / 1000, 1), 'K'),\n // Kusto doesn't support back-refs yet -- num > 1000, replace_regex(tostring(num), @'(\\d)(?=(\\d{3})+\\.)', @'\\1,'), // See https://docs.microsoft.com/azure/data-explorer/kusto/query/re2-library\n num > 1000, replace_regex(tostring(num), @'([0-9]{3})$', @',\\1'), //num / 1000, ',', substring(tostring(num), 0) - (num / 1000 * 1000)),\n tostring(num)\n ), @'\\.0$', '')\n}\n\n\n//===| Other |==========================================================================================================\n\n// ifempty\n.create-or-alter function \nwith (docstring = 'Replaces an empty value with the specified default value', folder = 'Common')\nifempty(val: dynamic, defaultVal: dynamic)\n{\n iff(isempty(val), defaultVal, val)\n}\n", "$fxv#12": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Hub database / Open data functions\n// Wrap Ingestion database tables for easy access.\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n\n// PricingUnits\n.create-or-alter function\nwith (docstring = 'Gets pricing units from the FinOps toolkit PricingUnits open data.', folder = 'OpenData')\nPricingUnits()\n{\n database('Ingestion').PricingUnits\n}\n\n// Regions\n.create-or-alter function\nwith (docstring = 'Gets regions from the FinOps toolkit Regions open data.', folder = 'OpenData')\nRegion()\n{\n database('Ingestion').Regions\n}\n\n// ResourceTypes\n.create-or-alter function\nwith (docstring = 'Gets resource types from the FinOps toolkit ResourceTypes open data.', folder = 'OpenData')\nResourceType()\n{\n database('Ingestion').ResourceTypes\n}\n\n// Services\n.create-or-alter function\nwith (docstring = 'Gets services from the FinOps toolkit Services open data.', folder = 'OpenData')\nServices()\n{\n database('Ingestion').Services\n}\n", "$fxv#13": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Hub database / FOCUS 1.0 functions\n// Used for reporting with backward compatibility.\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n\n// CommitmentDiscountUsage_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all commitment discount usage records aligned to FOCUS 1.0.', folder = 'CommitmentDiscountUsage')\nCommitmentDiscountUsage_v1_0()\n{\n database('Ingestion').CommitmentDiscountUsage_final_v1_0\n | union (\n database('Ingestion').CommitmentDiscountUsage_final_v1_2\n // Convert real to decimal\n | extend\n CommitmentDiscountQuantity = todecimal(CommitmentDiscountQuantity),\n ConsumedQuantity = todecimal(ConsumedQuantity),\n x_CommitmentDiscountCommittedCount = todecimal(x_CommitmentDiscountCommittedCount),\n x_CommitmentDiscountCommittedAmount = todecimal(x_CommitmentDiscountCommittedAmount),\n x_CommitmentDiscountNormalizedRatio = todecimal(x_CommitmentDiscountNormalizedRatio)\n )\n | project\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId,\n CommitmentDiscountType,\n ConsumedQuantity,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SubAccountId,\n x_CommitmentDiscountCommittedCount,\n x_CommitmentDiscountCommittedAmount,\n x_CommitmentDiscountNormalizedGroup,\n x_CommitmentDiscountNormalizedRatio,\n x_CommitmentDiscountQuantity,\n x_IngestionTime,\n x_ResourceGroupName,\n x_ResourceType,\n x_ServiceModel,\n x_SkuOrderId,\n x_SkuSize,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n\n// Costs_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all cost and usage records aligned to FOCUS 1.0.', folder = 'Costs')\nCosts_v1_0()\n{\n database('Ingestion').Costs_final_v1_0\n | union (\n database('Ingestion').Costs_final_v1_2\n // Convert real to decimal\n | extend\n BilledCost = todecimal(BilledCost),\n CommitmentDiscountQuantity = todecimal(CommitmentDiscountQuantity),\n ConsumedQuantity = todecimal(ConsumedQuantity),\n ContractedCost = todecimal(ContractedCost),\n ContractedUnitPrice = todecimal(ContractedUnitPrice),\n EffectiveCost = todecimal(EffectiveCost),\n ListCost = todecimal(ListCost),\n ListUnitPrice = todecimal(ListUnitPrice),\n PricingQuantity = todecimal(PricingQuantity),\n x_BilledCostInUsd = todecimal(x_BilledCostInUsd),\n x_BilledUnitPrice = todecimal(x_BilledUnitPrice),\n x_BillingExchangeRate = todecimal(x_BillingExchangeRate),\n x_CommitmentDiscountNormalizedRatio = todecimal(x_CommitmentDiscountNormalizedRatio),\n x_ContractedCostInUsd = todecimal(x_ContractedCostInUsd),\n x_CurrencyConversionRate = todecimal(x_CurrencyConversionRate),\n x_EffectiveCostInUsd = todecimal(x_EffectiveCostInUsd),\n x_EffectiveUnitPrice = todecimal(x_EffectiveUnitPrice),\n x_ListCostInUsd = todecimal(x_ListCostInUsd),\n x_PricingBlockSize = todecimal(x_PricingBlockSize)\n // Rename columns\n | project-rename\n x_InvoiceId = InvoiceId,\n x_PricingCurrency = PricingCurrency,\n x_SkuMeterName = SkuMeter\n // Generate historical x_SkuDetails format from SkuPriceDetails\n | extend x_SkuDetails = iff(isnotempty(x_SkuDetails), x_SkuDetails, parse_json(replace_regex(tostring(SkuPriceDetails), @'([\\{,])\"x_', @'\\1\"')))\n )\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId,\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory,\n ChargeClass,\n ChargeDescription,\n ChargeFrequency,\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId,\n CommitmentDiscountName,\n CommitmentDiscountStatus,\n CommitmentDiscountType,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost,\n ContractedUnitPrice,\n EffectiveCost,\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory,\n PricingQuantity,\n PricingUnit,\n ProviderName,\n PublisherName,\n RegionId,\n RegionName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SkuId,\n SkuPriceId,\n SubAccountId,\n SubAccountName,\n SubAccountType,\n Tags,\n x_AccountId,\n x_AccountName,\n x_AccountOwnerId,\n x_BilledCostInUsd,\n x_BilledUnitPrice,\n x_BillingAccountAgreement,\n x_BillingAccountId,\n x_BillingAccountName,\n x_BillingExchangeRate,\n x_BillingExchangeRateDate,\n x_BillingProfileId,\n x_BillingProfileName,\n x_ChargeId,\n x_ContractedCostInUsd,\n x_CostAllocationRuleName,\n x_CostCategories,\n x_CostCenter,\n x_Credits,\n x_CostType,\n x_CurrencyConversionRate,\n x_CustomerId,\n x_CustomerName,\n x_Discount,\n x_EffectiveCostInUsd,\n x_EffectiveUnitPrice,\n x_ExportTime,\n x_IngestionTime,\n x_InvoiceId,\n x_InvoiceIssuerId,\n x_InvoiceSectionId,\n x_InvoiceSectionName,\n x_ListCostInUsd,\n x_Location,\n x_Operation,\n x_PartnerCreditApplied,\n x_PartnerCreditRate,\n x_PricingBlockSize,\n x_PricingCurrency,\n x_PricingSubcategory,\n x_PricingUnitDescription,\n x_Project,\n x_PublisherCategory,\n x_PublisherId,\n x_ResellerId,\n x_ResellerName,\n x_ResourceGroupName,\n x_ResourceType,\n x_ServiceCode,\n x_ServiceId,\n x_ServicePeriodEnd,\n x_ServicePeriodStart,\n x_SkuDescription,\n x_SkuDetails,\n x_SkuIsCreditEligible,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterName,\n x_SkuMeterSubcategory,\n x_SkuOfferId,\n x_SkuOrderId,\n x_SkuOrderName,\n x_SkuPartNumber,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuTerm,\n x_SkuTier,\n x_SourceChanges,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_UsageType\n}\n\n\n// Prices_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all prices aligned to FOCUS 1.0.', folder = 'Prices')\nPrices_v1_0()\n{\n database('Ingestion').Prices_final_v1_0\n | union (\n database('Ingestion').Prices_final_v1_2\n // Convert real to decimal\n | extend\n ContractedUnitPrice = todecimal(ContractedUnitPrice),\n ListUnitPrice = todecimal(ListUnitPrice),\n x_BaseUnitPrice = todecimal(x_BaseUnitPrice),\n x_CommitmentDiscountNormalizedRatio = todecimal(x_CommitmentDiscountNormalizedRatio),\n x_ContractedUnitPriceDiscount = todecimal(x_ContractedUnitPriceDiscount),\n x_ContractedUnitPriceDiscountPercent = todecimal(x_ContractedUnitPriceDiscountPercent),\n x_EffectiveUnitPrice = todecimal(x_EffectiveUnitPrice),\n x_EffectiveUnitPriceDiscount = todecimal(x_EffectiveUnitPriceDiscount),\n x_EffectiveUnitPriceDiscountPercent = todecimal(x_EffectiveUnitPriceDiscountPercent),\n x_PricingBlockSize = todecimal(x_PricingBlockSize),\n x_SkuIncludedQuantity = todecimal(x_SkuIncludedQuantity),\n x_SkuTier = todecimal(x_SkuTier),\n x_TotalUnitPriceDiscount = todecimal(x_TotalUnitPriceDiscount),\n x_TotalUnitPriceDiscountPercent = todecimal(x_TotalUnitPriceDiscountPercent) \n // Rename columns\n | project-rename\n x_PricingCurrency = PricingCurrency,\n x_SkuMeterName = SkuMeter\n )\n | project\n BillingAccountId,\n BillingAccountName,\n BillingCurrency,\n ChargeCategory,\n CommitmentDiscountCategory,\n CommitmentDiscountType,\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory,\n PricingUnit,\n SkuId,\n SkuPriceId,\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement,\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent,\n x_EffectivePeriodEnd,\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingCurrency,\n x_PricingSubcategory,\n x_PricingUnitDescription,\n x_SkuDescription,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterName,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent\n}\n\n\n// Recommendations_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all recommendations aligned to FOCUS 1.0.', folder = 'Recommendations')\nRecommendations_v1_0()\n{\n database('Ingestion').Recommendations_final_v1_0\n | union (\n database('Ingestion').Recommendations_final_v1_2\n // Convert real to decimal\n | extend\n x_EffectiveCostAfter = todecimal(x_EffectiveCostAfter),\n x_EffectiveCostBefore = todecimal(x_EffectiveCostBefore),\n x_EffectiveCostSavings = todecimal(x_EffectiveCostSavings)\n )\n | project\n ProviderName,\n SubAccountId,\n x_IngestionTime,\n x_EffectiveCostAfter,\n x_EffectiveCostBefore,\n x_EffectiveCostSavings,\n x_RecommendationDate,\n x_RecommendationDetails,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n\n// Transactions_final_v1_0\n.create-or-alter function\nwith (docstring = 'Gets all transactions aligned to FOCUS 1.0.', folder = 'Transactions')\nTransactions_v1_0()\n{\n database('Ingestion').Transactions_final_v1_0\n | union (\n database('Ingestion').Transactions_final_v1_2\n // Convert real to decimal\n | extend\n BilledCost = todecimal(BilledCost),\n PricingQuantity = todecimal(PricingQuantity),\n x_MonetaryCommitment = todecimal(x_MonetaryCommitment),\n x_Overage = todecimal(x_Overage)\n // Rename columns\n | project-rename\n x_InvoiceId = InvoiceId\n )\n | project\n BilledCost,\n BillingAccountId,\n BillingAccountName,\n BillingCurrency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory,\n ChargeClass,\n ChargeDescription,\n ChargeFrequency,\n ChargePeriodStart,\n PricingQuantity,\n PricingUnit,\n ProviderName,\n RegionId,\n RegionName,\n SubAccountId,\n SubAccountName,\n x_AccountName,\n x_AccountOwnerId,\n x_CostCenter,\n x_InvoiceId,\n x_InvoiceNumber,\n x_InvoiceSectionId,\n x_InvoiceSectionName,\n x_IngestionTime,\n x_MonetaryCommitment,\n x_Overage,\n x_PurchasingBillingAccountId,\n x_SkuOrderId,\n x_SkuOrderName,\n x_SkuSize,\n x_SkuTerm,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId,\n x_TransactionType\n}\n", @@ -18333,7 +18333,7 @@ "$fxv#6": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Common utility functions\n//\n// TIP: Use Ctrl+K,Ctrl+0 to collapse all regions in VS Code\n//======================================================================================================================\n\n\n//===| Date functions |=================================================================================================\n\n// monthstring\n.create-or-alter function \nwith (docstring = @'Returns the name of the month for the specified date (e.g. Jan or January)', folder =@'Common') \nmonthstring(['date']: datetime, length: int = 9)\n{\n substring(dynamic(['January','February','March','April','May','June','July','August','September','October','November','December'])[getmonth(['date']) - 1], 0, length)\n}\n\n// datestring\n.create-or-alter function \nwith (docstring = @'Converts 2 dates into a simple, user-friendly date range (e.g. Jan 1-Jan 3)', folder =@'Common') \ndatestring(start: datetime, end: datetime = datetime('0001-01-01'))\n{\n let month = (d: datetime) { monthstring(d, 3) };\n let endDate = iff(end == datetime('0001-01-01'), start, end);\n let sameDate = startofday(start) == startofday(endDate);\n let sameMonth = startofmonth(start) == startofmonth(endDate);\n let sameYear = startofyear(start) == startofyear(endDate);\n let fullMonth = startofday(start) == startofmonth(start) and startofday(endDate) == startofday(endofmonth(endDate));\n let fullYear = startofday(start) == startofyear(start) and startofday(endDate) == startofday(endofyear(endDate));\n let currentYear = sameYear and startofyear(start) == startofyear(now());\n case(\n // Full year | yyyy (same year) / yyyy-yyyy (diff years)\n fullYear,\n strcat(getyear(start), iff(sameYear, '', strcat('-', getyear(endDate)))),\n // 1 full mo, same year | Mmm yyyy\n fullMonth and sameMonth and sameYear,\n strcat(month(start), ' ', getyear(start)),\n // 2+ full mo, same year | Mmm-Mmm (current year) / Mmm-Mmm yyyy (other year)\n fullMonth and sameYear,\n strcat(month(start), '-', month(endDate), iff(currentYear, '', strcat(' ', getyear(endDate)))),\n // Full mo, diff year | Mmm yyyy-Mmm yyyy\n fullMonth and not(sameYear),\n strcat(month(start), ' ', getyear(start), '-', month(endDate), ' ', getyear(endDate)),\n // Same date | Mmm d (current year) / Mmm d, yyyy (other year)\n sameDate,\n strcat(month(start), ' ', dayofmonth(start), iff(currentYear, '', strcat(', ', getyear(endDate)))),\n // 1 partial M, same Y | Mmm d-d (current year) / Mmm d-d, yyyy (other year)\n not(fullMonth) and sameMonth and sameYear,\n strcat(month(start), ' ', dayofmonth(start), '-', dayofmonth(endDate), iff(currentYear, '', strcat(' ', getyear(endDate)))),\n // 2+ partial M, same Y | Mmm d-Mmm d (current year) / Mmm d-Mmm d, yyyy (other year)\n not(fullMonth) and not(sameMonth) and sameYear,\n strcat(month(start), ' ', dayofmonth(start), '-', month(endDate), ' ', dayofmonth(endDate), iff(currentYear, '', strcat(', ', getyear(endDate)))),\n // All other cases | Mmm d, yyyy-Mmm d, yyyy\n strcat(month(start), ' ', dayofmonth(start), ', ', getyear(start), '-', month(endDate), ' ', dayofmonth(endDate), ', ', getyear(endDate))\n )\n}\n\n// daterange\n.create-or-alter function \nwith (docstring = @'DEPRECATED: Please use datestring(); function will be removed on or after the Jan 2026 release', folder =@'Common') \ndaterange(start: datetime, end: datetime = datetime('0001-01-01'))\n{\n datestring(start, end)\n}\n\n// monthsago\n.create-or-alter function \nwith (docstring = 'DEPRECATED: Please use startofmonth(now(), -<# of months>); function will be removed on or after the Jan 2026 release', folder = 'Common')\nmonthsago(months: int)\n{\n datetime_add('month', -months, startofmonth(now()))\n}\n\n\n//===| Number functions |===============================================================================================\n// NOTE: Must be defined before string converters\n\n// delta\n.create-or-alter function \nwith (docstring = @'Compares 2 values and returns the percentage change from oldval to newval', folder =@'Common') \ndelta(oldval: double, newval: double)\n{\n (newval - todouble(oldval))/oldval\n}\n\n// percentOfTotal\n// NOTE: Must be before percent() function\n.create-or-alter function \nwith (docstring = @'Calculates the percentage of each record based on a required Count column', folder =@'Common') \npercentOfTotal(t: (Count: long), tot: long)\n{\n let total = todouble(tot);\n t \n | extend Percent = round(Count / total * 100, 3) \n | order by Count desc\n}\n\n// percent\n.create-or-alter function \nwith (docstring = @'Calculates the percentage of each record based on a required Count column', folder =@'Common') \npercent(t: (Count: long))\n{\n let total = todouble(toscalar(t | summarize sum(Count)));\n percentOfTotal(t, total)\n}\n\n// plusminus\n.create-or-alter function \nwith (docstring = 'Shows a +/- sign based on the direction of the number', folder = 'Common')\nplusminus(val: string)\n{\n let neg = substring(val, 0, 1) == '-';\n iff(neg, val, strcat('+', val))\n}\n\n// updown\n.create-or-alter function \nwith (docstring = 'Shows an up/down arrow based on the direction of the number', folder = 'Common')\nupdown(val: string)\n{\n // TODO: Handle 0\n let neg = substring(val, 0, 1) == '-';\n iff(neg, strcat('↓', substring(val, 1)), strcat('↑', val))\n}\n\n\n//===| String functions |===============================================================================================\n\n// percentstring\n// NOTE: Must be defined before deltastring\n.create-or-alter function \nwith (docstring = 'Calculate a percentage and render as a string', folder = 'Common')\npercentstring(num: double, total: double = 1.0, places: int = 9)\n{\n let value = 1.0 * num / total * 100;\n strcat(case(\n places != 9, round(value, places),\n value < 10, round(value, 2),\n round(value, 1)\n ), '%')\n}\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// arraystring\n.create-or-alter function \nwith (docstring = 'Convert an array to a comma-delimited string', folder = 'Common')\narraystring(arr: dynamic)\n{\n replace_string(replace_regex(replace_regex(replace_regex(replace_regex(replace_regex(\n tostring(arr)\n , @'^\\[\"', '')\n , @'\"\\]$', '')\n , @'^, ', '')\n , @', $', '')\n , @'^\\[]$', '')\n , '\",\"', ', ')\n}\n\n// deltastring\n.create-or-alter function \nwith (docstring = 'Calculate a delta percentage and render as a string', folder = 'Common')\ndeltastring(oldval: double, newval: double, places: int = 1, useArrows: bool = false)\n{\n let d = delta(oldval, newval);\n strcat(case(useArrows and d > 0, '↑', useArrows and d < 0, '↓', d < 0, '-', ''), percentstring(abs(d), 1, places))\n}\n\n// diffstring\n.create-or-alter function \nwith (docstring = 'Calculate the difference and render as a string', folder = 'Common')\ndiffstring(oldval: double, newval: double, places: int = 1)\n{\n plusminus(round(newval - oldval, places))\n}\n\n// numberstring\n.create-or-alter function \nwith (docstring = 'Convert a number to a string', folder = 'Common')\nnumberstring(num: double, abbrev: bool = true)\n{\n replace_regex(case(\n num >= 10000000000000, strcat(round(1.0 * num / 1000000000000, 1), 'T'),\n num >= 1000000000000, strcat(round(1.0 * num / 1000000000000, 2), 'T'),\n num >= 10000000000, strcat(round(1.0 * num / 1000000000, 1), 'B'),\n num >= 1000000000, strcat(round(1.0 * num / 1000000000, 2), 'B'),\n num >= 10000000, strcat(round(1.0 * num / 1000000, 1), 'M'),\n num >= 1000000, strcat(round(1.0 * num / 1000000, 2), 'M'),\n num >= 10000, strcat(round(1.0 * num / 1000, 1), 'K'),\n // Kusto doesn't support back-refs yet -- num > 1000, replace_regex(tostring(num), @'(\\d)(?=(\\d{3})+\\.)', @'\\1,'), // See https://docs.microsoft.com/azure/data-explorer/kusto/query/re2-library\n num > 1000, replace_regex(tostring(num), @'([0-9]{3})$', @',\\1'), //num / 1000, ',', substring(tostring(num), 0) - (num / 1000 * 1000)),\n tostring(num)\n ), @'\\.0$', '')\n}\n\n\n//===| Other |==========================================================================================================\n\n// ifempty\n.create-or-alter function \nwith (docstring = 'Replaces an empty value with the specified default value', folder = 'Common')\nifempty(val: dynamic, defaultVal: dynamic)\n{\n iff(isempty(val), defaultVal, val)\n}\n", "$fxv#7": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// Used for data ingestion, normalization, and cleansing.\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Settings |=======================================================================================================\n\n.create-merge table HubSettingsLog (\n version: string,\n scopes: dynamic,\n retention: dynamic\n)\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// HubSettings function\n.create-or-alter function\nwith (docstring='Gets the latest version of hub settings.', folder='Settings')\nHubSettings()\n{\n HubSettingsLog\n | extend timestamp = ingestion_time()\n | summarize arg_max(timestamp, *)\n}\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// HubScopes function\n.create-or-alter function\nwith (docstring='Gets the currently configured scopes.', folder='Settings')\nHubScopes()\n{\n HubSettings\n | project scopes\n | mv-expand scopes\n}\n\n\n//===| Open data |======================================================================================================\n\n// PricingUnits -- Create table if it doesn't exist\n.create-merge table PricingUnits ( ignore: string )\n\n// PricingUnits -- Remove all columns\n.alter table PricingUnits ( ignore: string )\n\n// PricingUnits -- Redefine all columns to change types\n.alter table PricingUnits (\n x_PricingUnitDescription: string,\n x_PricingBlockSize: real,\n PricingUnit: string\n)\n\n// Regions\n.create-merge table Regions(\n ResourceLocation: string,\n RegionId: string,\n RegionName: string\n)\n\n// ResourceTypes\n.create-merge table ResourceTypes(\n x_ResourceType: string,\n SingularDisplayName: string,\n PluralDisplayName: string,\n LowerSingularDisplayName: string,\n LowerPluralDisplayName: string,\n IsPreview: bool,\n Description: string,\n IconUri: string\n)\n\n// Services\n.create-merge table Services(\n x_ConsumedService: string,\n x_ResourceType: string,\n ServiceName: string,\n ServiceCategory: string,\n ServiceSubcategory: string,\n PublisherName: string,\n x_PublisherCategory: string,\n x_Environment: string,\n x_ServiceModel: string\n)\n\n//----------------------------------------------------------------------------------------------------------------------\n\n// parse_resourceid\n.create-or-alter function\nwith (docstring = 'Parses an Azure resource ID to extract resource attributes like the name, type, resource group, and subaccount ID.', folder = 'Common')\nparse_resourceid(resourceId: string) {\n let ResourceId = tolower(resourceId);\n // let ResourceId = tolower('/providers/Microsoft.BillingBenefits/savingsPlanOrders/2d2e284b-0638-427e-b8c6-1b874d4f17c8/sp/xxx');\n let SubAccountId = tostring(extract('/subscriptions/[^/]+', 1, ResourceId));\n let x_ResourceGroupName = tostring(extract('/resourcegroups/[^/]+', 1, ResourceId));\n let tmp_ResourceId = iff(ResourceId !contains '/providers/' and ResourceId startswith '/subscriptions/', strcat('/providers/microsoft.resources', ResourceId), ResourceId);\n let providerPath = iff(tmp_ResourceId !contains '/providers/', '', tostring(split(tmp_ResourceId, '/providers/')[-1]));\n let x_ResourceProvider = iff(isempty(providerPath), '', split(providerPath, '/')[0]);\n let tmp_ResourceProviderPath = iff(isempty(providerPath), '', substring(providerPath, strlen(x_ResourceProvider) + 1));\n let segments = split(tmp_ResourceProviderPath, '/');\n let ResourceName = trim(@'/+', replace_string(strcat_array(array_iff(\n dynamic([false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true]),\n segments, dynamic([])), '/'), '//', '/'));\n let x_ResourceTypePath = trim(@'/+', replace_string(strcat_array(array_iff(\n dynamic([true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false]),\n segments, dynamic([])), '/'), '//', '/'));\n let xRT = iff(isempty(x_ResourceProvider) or isempty(x_ResourceTypePath), '', strcat(x_ResourceProvider, '/', x_ResourceTypePath));\n // TODO: Remove ResourceType in 0.9\n bag_pack('ResourceId', ResourceId, 'ResourceName', ResourceName, 'ResourceType', xRT, 'SubAccountId', SubAccountId, 'x_ResourceGroupName', x_ResourceGroupName, 'x_ResourceProvider', x_ResourceProvider, 'x_ResourceType', xRT)\n}\n", "$fxv#8": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// Used for data ingestion, normalization, and cleansing.\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| ActualCosts |====================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_raw table -- Create the table if it doesn't exist\n.create-merge table ActualCosts_raw ( ignore: string )\n\n// ActualCosts_raw table -- Remove all columns to allow changing column types\n.alter table ActualCosts_raw ( ignore: string )\n\n// ActualCosts_raw table -- Redefine all columns\n.alter table ActualCosts_raw (\n AccountName: string,\n AccountOwnerId: string,\n AdditionalInfo: string,\n AvailabilityZone: string,\n BillingAccountId: string, \n BillingAccountName: string,\n BillingCurrency: string,\n BillingPeriodEndDate: datetime,\n BillingPeriodStartDate: datetime,\n BillingProfileId: string,\n BillingProfileName: string,\n ChargeType: string,\n ConsumedService: string,\n CostCenter: string,\n Cost: real,\n Date: datetime,\n EffectivePrice: real,\n Frequency: string,\n InvoiceSection: string,\n InvoiceSectionId: string,\n IsAzureCreditEligible: bool,\n MeterCategory: string,\n MeterId: string,\n MeterName: string,\n MeterRegion: string,\n MeterSubCategory: string,\n OfferId: string,\n PartNumber: string,\n PlanName: string,\n Product: string,\n ProductOrderId: string,\n ProductOrderName: string,\n PublisherName: string,\n PublisherType: string,\n Quantity: real,\n ReservationId: string,\n ReservationName: string,\n ResourceGroup: string,\n ResourceId: string,\n ResourceLocation: string,\n ResourceName: string,\n ServiceFamily: string,\n ServiceInfo1: string,\n ServiceInfo2: string,\n SubscriptionId: string,\n SubscriptionName: string,\n Tags: string,\n Term: string,\n UnitOfMeasure: string,\n UnitPrice: real\n)\n\n// ActualCosts_raw ingestion mapping\n.create-or-alter table ActualCosts_raw ingestion parquet mapping \"ActualCosts_raw_mapping\"\n```\n[\n { \"Column\": \"AccountName\", \"Properties\": { \"Field\": \"AccountName\" } },\n { \"Column\": \"AccountOwnerId\", \"Properties\": { \"Field\": \"AccountOwnerId\" } },\n { \"Column\": \"AdditionalInfo\", \"Properties\": { \"Field\": \"AdditionalInfo\" } },\n { \"Column\": \"AvailabilityZone\", \"Properties\": { \"Field\": \"AvailabilityZone\" } },\n { \"Column\": \"BillingAccountId\", \"Properties\": { \"Field\": \"BillingAccountId\" } },\n { \"Column\": \"BillingAccountName\", \"Properties\": { \"Field\": \"BillingAccountName\" } },\n { \"Column\": \"BillingCurrency\", \"Properties\": { \"Field\": \"BillingCurrency\" } },\n { \"Column\": \"BillingPeriodEndDate\", \"Properties\": { \"Field\": \"BillingPeriodEndDate\" } },\n { \"Column\": \"BillingPeriodStartDate\", \"Properties\": { \"Field\": \"BillingPeriodStartDate\" } },\n { \"Column\": \"BillingProfileId\", \"Properties\": { \"Field\": \"BillingProfileId\" } },\n { \"Column\": \"BillingProfileName\", \"Properties\": { \"Field\": \"BillingProfileName\" } },\n { \"Column\": \"ChargeType\", \"Properties\": { \"Field\": \"ChargeType\" } },\n { \"Column\": \"ConsumedService\", \"Properties\": { \"Field\": \"ConsumedService\" } },\n { \"Column\": \"CostCenter\", \"Properties\": { \"Field\": \"CostCenter\" } },\n { \"Column\": \"Cost\", \"Properties\": { \"Field\": \"Cost\" } },\n { \"Column\": \"Date\", \"Properties\": { \"Field\": \"Date\" } },\n { \"Column\": \"EffectivePrice\", \"Properties\": { \"Field\": \"EffectivePrice\" } },\n { \"Column\": \"Frequency\", \"Properties\": { \"Field\": \"Frequency\" } },\n { \"Column\": \"InvoiceSection\", \"Properties\": { \"Field\": \"InvoiceSection\" } },\n { \"Column\": \"InvoiceSectionId\", \"Properties\": { \"Field\": \"InvoiceSectionId\" } },\n { \"Column\": \"IsAzureCreditEligible\", \"Properties\": { \"Field\": \"IsAzureCreditEligible\" } },\n { \"Column\": \"MeterCategory\", \"Properties\": { \"Field\": \"MeterCategory\" } },\n { \"Column\": \"MeterId\", \"Properties\": { \"Field\": \"MeterId\" } },\n { \"Column\": \"MeterName\", \"Properties\": { \"Field\": \"MeterName\" } },\n { \"Column\": \"MeterRegion\", \"Properties\": { \"Field\": \"MeterRegion\" } },\n { \"Column\": \"MeterSubCategory\", \"Properties\": { \"Field\": \"MeterSubCategory\" } },\n { \"Column\": \"OfferId\", \"Properties\": { \"Field\": \"OfferId\" } },\n { \"Column\": \"PartNumber\", \"Properties\": { \"Field\": \"PartNumber\" } },\n { \"Column\": \"PlanName\", \"Properties\": { \"Field\": \"PlanName\" } },\n { \"Column\": \"Product\", \"Properties\": { \"Field\": \"Product\" } },\n { \"Column\": \"ProductOrderId\", \"Properties\": { \"Field\": \"ProductOrderId\" } },\n { \"Column\": \"ProductOrderName\", \"Properties\": { \"Field\": \"ProductOrderName\" } },\n { \"Column\": \"PublisherName\", \"Properties\": { \"Field\": \"PublisherName\" } },\n { \"Column\": \"PublisherType\", \"Properties\": { \"Field\": \"PublisherType\" } },\n { \"Column\": \"Quantity\", \"Properties\": { \"Field\": \"Quantity\" } },\n { \"Column\": \"ReservationId\", \"Properties\": { \"Field\": \"ReservationId\" } },\n { \"Column\": \"ReservationName\", \"Properties\": { \"Field\": \"ReservationName\" } },\n { \"Column\": \"ResourceGroup\", \"Properties\": { \"Field\": \"ResourceGroup\" } },\n { \"Column\": \"ResourceId\", \"Properties\": { \"Field\": \"ResourceId\" } },\n { \"Column\": \"ResourceLocation\", \"Properties\": { \"Field\": \"ResourceLocation\" } },\n { \"Column\": \"ResourceName\", \"Properties\": { \"Field\": \"ResourceName\" } },\n { \"Column\": \"ServiceFamily\", \"Properties\": { \"Field\": \"ServiceFamily\" } },\n { \"Column\": \"ServiceInfo1\", \"Properties\": { \"Field\": \"ServiceInfo1\" } },\n { \"Column\": \"ServiceInfo2\", \"Properties\": { \"Field\": \"ServiceInfo2\" } },\n { \"Column\": \"SubscriptionId\", \"Properties\": { \"Field\": \"SubscriptionId\" } },\n { \"Column\": \"SubscriptionName\", \"Properties\": { \"Field\": \"SubscriptionName\" } },\n { \"Column\": \"Tags\", \"Properties\": { \"Field\": \"Tags\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"UnitOfMeasure\", \"Properties\": { \"Field\": \"UnitOfMeasure\" } },\n { \"Column\": \"UnitPrice\", \"Properties\": { \"Field\": \"UnitPrice\" } }\n]\n```\n\n// ActualCosts_raw retention policy (clear historical data)\n.alter-merge table ActualCosts_raw policy retention softdelete = 0d recoverability = disabled\n\n// ActualCosts_raw retention policy (set the user-defined retention period)\n.alter-merge table ActualCosts_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable ActualCosts_raw streaming ingestion (required for Fabric)\n.alter table ActualCosts_raw policy streamingingestion disable\n\n\n//===| AmortizedCosts |=================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_raw table -- Create the table if it doesn't exist\n.create-merge table AmortizedCosts_raw ( ignore: string )\n\n// AmortizedCosts_raw table -- Remove all columns to allow changing column types\n.alter table AmortizedCosts_raw ( ignore: string )\n\n// AmortizedCosts_raw table -- Redefine all columns\n.alter table AmortizedCosts_raw (\n AccountName: string,\n AccountOwnerId: string,\n AdditionalInfo: string,\n AvailabilityZone: string,\n BillingAccountId: string, \n BillingAccountName: string,\n BillingCurrency: string,\n BillingPeriodEndDate: datetime,\n BillingPeriodStartDate: datetime,\n BillingProfileId: string,\n BillingProfileName: string,\n ChargeType: string,\n ConsumedService: string,\n CostCenter: string,\n Cost: real,\n Date: datetime,\n EffectivePrice: real,\n Frequency: string,\n InvoiceSection: string,\n InvoiceSectionId: string,\n IsAzureCreditEligible: bool,\n MeterCategory: string,\n MeterId: string,\n MeterName: string,\n MeterRegion: string,\n MeterSubCategory: string,\n OfferId: string,\n PartNumber: string,\n PlanName: string,\n Product: string,\n ProductOrderId: string,\n ProductOrderName: string,\n PublisherName: string,\n PublisherType: string,\n Quantity: real,\n ReservationId: string,\n ReservationName: string,\n ResourceGroup: string,\n ResourceId: string,\n ResourceLocation: string,\n ResourceName: string,\n ServiceFamily: string,\n ServiceInfo1: string,\n ServiceInfo2: string,\n SubscriptionId: string,\n SubscriptionName: string,\n Tags: string,\n Term: string,\n UnitOfMeasure: string,\n UnitPrice: real\n)\n\n// AmortizedCosts_raw ingestion mapping\n.create-or-alter table AmortizedCosts_raw ingestion parquet mapping \"AmortizedCosts_raw_mapping\"\n```\n[\n { \"Column\": \"AccountName\", \"Properties\": { \"Field\": \"AccountName\" } },\n { \"Column\": \"AccountOwnerId\", \"Properties\": { \"Field\": \"AccountOwnerId\" } },\n { \"Column\": \"AdditionalInfo\", \"Properties\": { \"Field\": \"AdditionalInfo\" } },\n { \"Column\": \"AvailabilityZone\", \"Properties\": { \"Field\": \"AvailabilityZone\" } },\n { \"Column\": \"BillingAccountId\", \"Properties\": { \"Field\": \"BillingAccountId\" } },\n { \"Column\": \"BillingAccountName\", \"Properties\": { \"Field\": \"BillingAccountName\" } },\n { \"Column\": \"BillingCurrency\", \"Properties\": { \"Field\": \"BillingCurrency\" } },\n { \"Column\": \"BillingPeriodEndDate\", \"Properties\": { \"Field\": \"BillingPeriodEndDate\" } },\n { \"Column\": \"BillingPeriodStartDate\", \"Properties\": { \"Field\": \"BillingPeriodStartDate\" } },\n { \"Column\": \"BillingProfileId\", \"Properties\": { \"Field\": \"BillingProfileId\" } },\n { \"Column\": \"BillingProfileName\", \"Properties\": { \"Field\": \"BillingProfileName\" } },\n { \"Column\": \"ChargeType\", \"Properties\": { \"Field\": \"ChargeType\" } },\n { \"Column\": \"ConsumedService\", \"Properties\": { \"Field\": \"ConsumedService\" } },\n { \"Column\": \"CostCenter\", \"Properties\": { \"Field\": \"CostCenter\" } },\n { \"Column\": \"Cost\", \"Properties\": { \"Field\": \"Cost\" } },\n { \"Column\": \"Date\", \"Properties\": { \"Field\": \"Date\" } },\n { \"Column\": \"EffectivePrice\", \"Properties\": { \"Field\": \"EffectivePrice\" } },\n { \"Column\": \"Frequency\", \"Properties\": { \"Field\": \"Frequency\" } },\n { \"Column\": \"InvoiceSection\", \"Properties\": { \"Field\": \"InvoiceSection\" } },\n { \"Column\": \"InvoiceSectionId\", \"Properties\": { \"Field\": \"InvoiceSectionId\" } },\n { \"Column\": \"IsAzureCreditEligible\", \"Properties\": { \"Field\": \"IsAzureCreditEligible\" } },\n { \"Column\": \"MeterCategory\", \"Properties\": { \"Field\": \"MeterCategory\" } },\n { \"Column\": \"MeterId\", \"Properties\": { \"Field\": \"MeterId\" } },\n { \"Column\": \"MeterName\", \"Properties\": { \"Field\": \"MeterName\" } },\n { \"Column\": \"MeterRegion\", \"Properties\": { \"Field\": \"MeterRegion\" } },\n { \"Column\": \"MeterSubCategory\", \"Properties\": { \"Field\": \"MeterSubCategory\" } },\n { \"Column\": \"OfferId\", \"Properties\": { \"Field\": \"OfferId\" } },\n { \"Column\": \"PartNumber\", \"Properties\": { \"Field\": \"PartNumber\" } },\n { \"Column\": \"PlanName\", \"Properties\": { \"Field\": \"PlanName\" } },\n { \"Column\": \"Product\", \"Properties\": { \"Field\": \"Product\" } },\n { \"Column\": \"ProductOrderId\", \"Properties\": { \"Field\": \"ProductOrderId\" } },\n { \"Column\": \"ProductOrderName\", \"Properties\": { \"Field\": \"ProductOrderName\" } },\n { \"Column\": \"PublisherName\", \"Properties\": { \"Field\": \"PublisherName\" } },\n { \"Column\": \"PublisherType\", \"Properties\": { \"Field\": \"PublisherType\" } },\n { \"Column\": \"Quantity\", \"Properties\": { \"Field\": \"Quantity\" } },\n { \"Column\": \"ReservationId\", \"Properties\": { \"Field\": \"ReservationId\" } },\n { \"Column\": \"ReservationName\", \"Properties\": { \"Field\": \"ReservationName\" } },\n { \"Column\": \"ResourceGroup\", \"Properties\": { \"Field\": \"ResourceGroup\" } },\n { \"Column\": \"ResourceId\", \"Properties\": { \"Field\": \"ResourceId\" } },\n { \"Column\": \"ResourceLocation\", \"Properties\": { \"Field\": \"ResourceLocation\" } },\n { \"Column\": \"ResourceName\", \"Properties\": { \"Field\": \"ResourceName\" } },\n { \"Column\": \"ServiceFamily\", \"Properties\": { \"Field\": \"ServiceFamily\" } },\n { \"Column\": \"ServiceInfo1\", \"Properties\": { \"Field\": \"ServiceInfo1\" } },\n { \"Column\": \"ServiceInfo2\", \"Properties\": { \"Field\": \"ServiceInfo2\" } },\n { \"Column\": \"SubscriptionId\", \"Properties\": { \"Field\": \"SubscriptionId\" } },\n { \"Column\": \"SubscriptionName\", \"Properties\": { \"Field\": \"SubscriptionName\" } },\n { \"Column\": \"Tags\", \"Properties\": { \"Field\": \"Tags\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"UnitOfMeasure\", \"Properties\": { \"Field\": \"UnitOfMeasure\" } },\n { \"Column\": \"UnitPrice\", \"Properties\": { \"Field\": \"UnitPrice\" } }\n]\n```\n\n// AmortizedCosts_raw retention policy (clear historical data)\n.alter-merge table AmortizedCosts_raw policy retention softdelete = 0d recoverability = disabled\n\n// AmortizedCosts_raw retention policy (set the user-defined retention period)\n.alter-merge table AmortizedCosts_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable AmortizedCosts_raw streaming ingestion (required for Fabric)\n.alter table AmortizedCosts_raw policy streamingingestion disable\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_raw table -- Create the table if it doesn't exist\n.create-merge table CommitmentDiscountUsage_raw ( ignore: string )\n\n// CommitmentDiscountUsage_raw table -- Remove all columns to allow changing column types\n.alter table CommitmentDiscountUsage_raw ( ignore: string )\n\n// CommitmentDiscountUsage_raw table -- Redefine all columns\n.alter table CommitmentDiscountUsage_raw (\n InstanceFlexibilityGroup: string,\n InstanceFlexibilityRatio: real,\n InstanceId: string,\n Kind: string,\n ReservationId: string,\n ReservationOrderId: string,\n ReservedHours: real,\n SkuName: string,\n TotalReservedQuantity: real,\n UsageDate: datetime,\n UsedHours: real,\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string // Hubs v1_0+\n)\n\n// CommitmentDiscountUsage_raw ingestion mapping\n.create-or-alter table CommitmentDiscountUsage_raw ingestion parquet mapping \"CommitmentDiscountUsage_raw_mapping\"\n```\n[\n { \"Column\": \"InstanceFlexibilityGroup\", \"Properties\": { \"Field\": \"InstanceFlexibilityGroup\" } },\n { \"Column\": \"InstanceFlexibilityRatio\", \"Properties\": { \"Field\": \"InstanceFlexibilityRatio\" } },\n { \"Column\": \"InstanceId\", \"Properties\": { \"Field\": \"InstanceId\" } },\n { \"Column\": \"Kind\", \"Properties\": { \"Field\": \"Kind\" } },\n { \"Column\": \"ReservationId\", \"Properties\": { \"Field\": \"ReservationId\" } },\n { \"Column\": \"ReservationOrderId\", \"Properties\": { \"Field\": \"ReservationOrderId\" } },\n { \"Column\": \"ReservedHours\", \"Properties\": { \"Field\": \"ReservedHours\" } },\n { \"Column\": \"SkuName\", \"Properties\": { \"Field\": \"SkuName\" } },\n { \"Column\": \"TotalReservedQuantity\", \"Properties\": { \"Field\": \"TotalReservedQuantity\" } },\n { \"Column\": \"UsageDate\", \"Properties\": { \"Field\": \"UsageDate\" } },\n { \"Column\": \"UsedHours\", \"Properties\": { \"Field\": \"UsedHours\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } }\n]\n```\n\n// CommitmentDiscountUsage_raw retention policy (clear historical data)\n.alter-merge table CommitmentDiscountUsage_raw policy retention softdelete = 0d recoverability = disabled\n\n// CommitmentDiscountUsage_raw retention policy (set the user-defined retention period)\n.alter-merge table CommitmentDiscountUsage_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable CommitmentDiscountUsage_raw streaming ingestion (required for Fabric)\n.alter table CommitmentDiscountUsage_raw policy streamingingestion disable\n\n\n//===| Costs |==========================================================================================================\n// Supported versions:\n// - MS: 1.0, 1.0-preview(v1) -- See https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0 -- See https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024 -- See https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 -- See https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n// - Tencent: 1.0 -- See https://www.tencentcloud.com/document/product/555/67495 / https://www.tencentcloud.com/document/product/555/67496\n// - Alibaba: 1.0 -- See https://www.alibabacloud.com/help/en/user-center/user-guide/export-alibaba-cloud-standard-billing-focus\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_raw table -- Create the table if it doesn't exist\n.create-merge table Costs_raw ( ignore: string )\n\n// Costs_raw table -- Remove all columns to allow changing column types\n.alter table Costs_raw ( ignore: string )\n\n// Costs_raw table -- Redefine all columns\n.alter table Costs_raw (\n AvailabilityZone: string, // FOCUS 0.5+\n BilledCost: real, // FOCUS 0.5+\n BillingAccountId: string, // FOCUS 0.5+\n BillingAccountName: string, // FOCUS 0.5+\n BillingAccountType: string, // Azure 1.0-preview(v1)+\n BillingCurrency: string, // FOCUS 0.5+\n BillingPeriodEnd: datetime, // FOCUS 0.5+\n BillingPeriodStart: datetime, // FOCUS 0.5+\n CapacityReservationId: string, // FOCUS 1.1+\n CapacityReservationStatus: string, // FOCUS 1.1+\n ChargeCategory: string, // FOCUS 1.0-preview+\n ChargeClass: string, // FOCUS 1.0+\n ChargeDescription: string, // FOCUS 1.0+\n ChargeFrequency: string, // FOCUS 1.0+\n ChargePeriodEnd: datetime, // FOCUS 0.5+\n ChargePeriodStart: datetime, // FOCUS 0.5+\n ChargeSubcategory: string, // FOCUS 1.0-preview only\n CommitmentDiscountCategory: string, // FOCUS 1.0-preview+\n CommitmentDiscountId: string, // FOCUS 1.0-preview+\n CommitmentDiscountName: string, // FOCUS 1.0-preview+\n CommitmentDiscountQuantity: real, // FOCUS 1.1+\n CommitmentDiscountStatus: string, // FOCUS 1.0+\n CommitmentDiscountType: string, // FOCUS 1.0-preview+\n CommitmentDiscountUnit: string, // FOCUS 1.1+\n ConsumedQuantity: real, // FOCUS 1.0+\n ConsumedUnit: string, // FOCUS 1.0+\n ContractedCost: real, // FOCUS 1.0+\n ContractedUnitPrice: real, // FOCUS 1.0+\n EffectiveCost: real, // FOCUS 1.0-preview+\n InvoiceId: string, // FOCUS 1.2+\n InvoiceIssuerName: string, // FOCUS 0.5+\n ListCost: real, // FOCUS 1.0-preview+\n ListUnitPrice: real, // FOCUS 1.0-preview+\n PricingCategory: string, // FOCUS 1.0-preview+\n PricingCurrency: string, // FOCUS 1.2+\n PricingQuantity: real, // FOCUS 1.0-preview+\n PricingUnit: string, // FOCUS 1.0-preview+\n ProviderName: string, // FOCUS 0.5+\n PublisherName: string, // FOCUS 0.5+\n Region: string, // FOCUS 0.5-1.0-preview (deprecated)\n RegionId: string, // FOCUS 1.0+\n RegionName: string, // FOCUS 1.0+\n ResourceId: string, // FOCUS 0.5+\n ResourceName: string, // FOCUS 0.5+\n ResourceType: string, // FOCUS 1.0-preview+\n ServiceCategory: string, // FOCUS 0.5+\n ServiceName: string, // FOCUS 0.5+\n ServiceSubcategory: string, // FOCUS 1.1+\n SkuId: string, // FOCUS 1.0-preview+\n SkuMeter: string, // FOCUS 1.1+\n SkuPriceDetails: string, // FOCUS 1.1+\n SkuPriceId: string, // FOCUS 1.0-preview+\n SubAccountId: string, // FOCUS 0.5+\n SubAccountName: string, // FOCUS 0.5+\n SubAccountType: string, // Azure 1.0-preview(v1)+\n Tags: string, // FOCUS 1.0-preview+\n UsageAmount: real, // GCP Jan 2024 -- Removed Mar 2024 (UsageQuantity)\n UsageQuantity: real, // FOCUS 1.0-preview only\n UsageUnit: string, // FOCUS 1.0-preview only\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_AmortizationClass: string, // Azure 1.2-preview+\n x_BilledCostInUsd: real, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: real, // Azure 1.0-preview(v1)+\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: real, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingItemCode: string, // Alibaba 1.0+\n x_BillingItemName: string, // Alibaba 1.0+\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_CommodityCode: string, // Alibaba 1.0+\n x_CommodityName: string, // Alibaba 1.0+\n x_ComponentName: string, // Tencent 1.0+\n x_ComponentType: string, // Tencent 1.0+\n x_ContractedCostInUsd: real, // Azure 1.0+\n x_Cost: real, // GCP Jan 2024 -- Removed Jun 2024 (ContractedCost)\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: string, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_CostType: string, // GCP Jan 2024\n x_Credits: string, // GCP Jan 2024\n x_CurrencyConversionRate: real, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: string, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: real, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: real, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024 / Tencent 1.0+\n x_InstanceID: string, // Alibaba 1.0+\n x_InvoiceId: string, // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: real, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_OnDemandCost: real, // Azure 1.0-preview(v1) only\n x_OnDemandCostInUsd: real, // Azure 1.0-preview(v1) only\n x_OnDemandUnitPrice: real, // Azure 1.0-preview(v1) only\n x_Operation: string, // AWS 1.0\n x_OwnerAccountID: string, // Tencent 1.0+\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: real, // Azure 1.0-preview(v1)+\n x_PricingCurrency: string, // Azure 1.0-preview(v1)-1.0r2\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServiceModel: string, // Azure 1.2-preview+\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: string, // Azure 1.0-preview(v1)-1.2-preview\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterName: string, // Azure 1.0-preview(v1)-1.0r2\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuPlanName: string, // Azure 1.2-preview+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string, // Hubs v1_0+\n x_SubproductName: string, // Tencent 1.0+ // cSpell:ignore Subproduct\n x_UsageType: string // AWS 1.0\n)\n\n// Costs_raw ingestion mapping\n.create-or-alter table Costs_raw ingestion parquet mapping \"Costs_raw_mapping\"\n```\n[\n { \"Column\": \"AvailabilityZone\", \"Properties\": { \"Field\": \"AvailabilityZone\" } },\n { \"Column\": \"BilledCost\", \"Properties\": { \"Field\": \"BilledCost\" } },\n { \"Column\": \"BillingAccountId\", \"Properties\": { \"Field\": \"BillingAccountId\" } },\n { \"Column\": \"BillingAccountName\", \"Properties\": { \"Field\": \"BillingAccountName\" } },\n { \"Column\": \"BillingAccountType\", \"Properties\": { \"Field\": \"BillingAccountType\" } },\n { \"Column\": \"BillingCurrency\", \"Properties\": { \"Field\": \"BillingCurrency\" } },\n { \"Column\": \"BillingPeriodEnd\", \"Properties\": { \"Field\": \"BillingPeriodEnd\" } },\n { \"Column\": \"BillingPeriodStart\", \"Properties\": { \"Field\": \"BillingPeriodStart\" } },\n { \"Column\": \"CapacityReservationId\", \"Properties\": { \"Field\": \"CapacityReservationId\" } },\n { \"Column\": \"CapacityReservationStatus\", \"Properties\": { \"Field\": \"CapacityReservationStatus\" } },\n { \"Column\": \"ChargeCategory\", \"Properties\": { \"Field\": \"ChargeCategory\" } },\n { \"Column\": \"ChargeClass\", \"Properties\": { \"Field\": \"ChargeClass\" } },\n { \"Column\": \"ChargeDescription\", \"Properties\": { \"Field\": \"ChargeDescription\" } },\n { \"Column\": \"ChargeFrequency\", \"Properties\": { \"Field\": \"ChargeFrequency\" } },\n { \"Column\": \"ChargePeriodEnd\", \"Properties\": { \"Field\": \"ChargePeriodEnd\" } },\n { \"Column\": \"ChargePeriodStart\", \"Properties\": { \"Field\": \"ChargePeriodStart\" } },\n { \"Column\": \"ChargeSubcategory\", \"Properties\": { \"Field\": \"ChargeSubcategory\" } },\n { \"Column\": \"CommitmentDiscountCategory\", \"Properties\": { \"Field\": \"CommitmentDiscountCategory\" } },\n { \"Column\": \"CommitmentDiscountId\", \"Properties\": { \"Field\": \"CommitmentDiscountId\" } },\n { \"Column\": \"CommitmentDiscountName\", \"Properties\": { \"Field\": \"CommitmentDiscountName\" } },\n { \"Column\": \"CommitmentDiscountQuantity\", \"Properties\": { \"Field\": \"CommitmentDiscountQuantity\" } },\n { \"Column\": \"CommitmentDiscountStatus\", \"Properties\": { \"Field\": \"CommitmentDiscountStatus\" } },\n { \"Column\": \"CommitmentDiscountType\", \"Properties\": { \"Field\": \"CommitmentDiscountType\" } },\n { \"Column\": \"CommitmentDiscountUnit\", \"Properties\": { \"Field\": \"CommitmentDiscountUnit\" } },\n { \"Column\": \"ConsumedQuantity\", \"Properties\": { \"Field\": \"ConsumedQuantity\" } },\n { \"Column\": \"ConsumedUnit\", \"Properties\": { \"Field\": \"ConsumedUnit\" } },\n { \"Column\": \"ContractedCost\", \"Properties\": { \"Field\": \"ContractedCost\" } },\n { \"Column\": \"ContractedUnitPrice\", \"Properties\": { \"Field\": \"ContractedUnitPrice\" } },\n { \"Column\": \"EffectiveCost\", \"Properties\": { \"Field\": \"EffectiveCost\" } },\n { \"Column\": \"InvoiceId\", \"Properties\": { \"Field\": \"InvoiceId\" } },\n { \"Column\": \"InvoiceIssuerName\", \"Properties\": { \"Field\": \"InvoiceIssuerName\" } },\n { \"Column\": \"ListCost\", \"Properties\": { \"Field\": \"ListCost\" } },\n { \"Column\": \"ListUnitPrice\", \"Properties\": { \"Field\": \"ListUnitPrice\" } },\n { \"Column\": \"PricingCategory\", \"Properties\": { \"Field\": \"PricingCategory\" } },\n { \"Column\": \"PricingCurrency\", \"Properties\": { \"Field\": \"PricingCurrency\" } },\n { \"Column\": \"PricingQuantity\", \"Properties\": { \"Field\": \"PricingQuantity\" } },\n { \"Column\": \"PricingUnit\", \"Properties\": { \"Field\": \"PricingUnit\" } },\n { \"Column\": \"ProviderName\", \"Properties\": { \"Field\": \"ProviderName\" } },\n { \"Column\": \"PublisherName\", \"Properties\": { \"Field\": \"PublisherName\" } },\n { \"Column\": \"Region\", \"Properties\": { \"Field\": \"Region\" } },\n { \"Column\": \"RegionId\", \"Properties\": { \"Field\": \"RegionId\" } },\n { \"Column\": \"RegionName\", \"Properties\": { \"Field\": \"RegionName\" } },\n { \"Column\": \"ResourceId\", \"Properties\": { \"Field\": \"ResourceId\" } },\n { \"Column\": \"ResourceName\", \"Properties\": { \"Field\": \"ResourceName\" } },\n { \"Column\": \"ResourceType\", \"Properties\": { \"Field\": \"ResourceType\" } },\n { \"Column\": \"ServiceCategory\", \"Properties\": { \"Field\": \"ServiceCategory\" } },\n { \"Column\": \"ServiceName\", \"Properties\": { \"Field\": \"ServiceName\" } },\n { \"Column\": \"ServiceSubcategory\", \"Properties\": { \"Field\": \"ServiceSubcategory\" } },\n { \"Column\": \"SkuId\", \"Properties\": { \"Field\": \"SkuId\" } },\n { \"Column\": \"SkuMeter\", \"Properties\": { \"Field\": \"SkuMeter\" } },\n { \"Column\": \"SkuPriceDetails\", \"Properties\": { \"Field\": \"SkuPriceDetails\" } },\n { \"Column\": \"SkuPriceId\", \"Properties\": { \"Field\": \"SkuPriceId\" } },\n { \"Column\": \"SubAccountId\", \"Properties\": { \"Field\": \"SubAccountId\" } },\n { \"Column\": \"SubAccountName\", \"Properties\": { \"Field\": \"SubAccountName\" } },\n { \"Column\": \"SubAccountType\", \"Properties\": { \"Field\": \"SubAccountType\" } },\n { \"Column\": \"Tags\", \"Properties\": { \"Field\": \"Tags\" } },\n { \"Column\": \"UsageAmount\", \"Properties\": { \"Field\": \"UsageAmount\" } },\n { \"Column\": \"UsageQuantity\", \"Properties\": { \"Field\": \"UsageQuantity\" } },\n { \"Column\": \"UsageUnit\", \"Properties\": { \"Field\": \"UsageUnit\" } },\n { \"Column\": \"x_AccountId\", \"Properties\": { \"Field\": \"x_AccountId\" } },\n { \"Column\": \"x_AccountName\", \"Properties\": { \"Field\": \"x_AccountName\" } },\n { \"Column\": \"x_AccountOwnerId\", \"Properties\": { \"Field\": \"x_AccountOwnerId\" } },\n { \"Column\": \"x_AmortizationClass\", \"Properties\": { \"Field\": \"x_AmortizationClass\" } },\n { \"Column\": \"x_BilledCostInUsd\", \"Properties\": { \"Field\": \"x_BilledCostInUsd\" } },\n { \"Column\": \"x_BilledUnitPrice\", \"Properties\": { \"Field\": \"x_BilledUnitPrice\" } },\n { \"Column\": \"x_BillingAccountId\", \"Properties\": { \"Field\": \"x_BillingAccountId\" } },\n { \"Column\": \"x_BillingAccountName\", \"Properties\": { \"Field\": \"x_BillingAccountName\" } },\n { \"Column\": \"x_BillingExchangeRate\", \"Properties\": { \"Field\": \"x_BillingExchangeRate\" } },\n { \"Column\": \"x_BillingExchangeRateDate\", \"Properties\": { \"Field\": \"x_BillingExchangeRateDate\" } },\n { \"Column\": \"x_BillingItemCode\", \"Properties\": { \"Field\": \"x_BillingItemCode\" } },\n { \"Column\": \"x_BillingItemName\", \"Properties\": { \"Field\": \"x_BillingItemName\" } },\n { \"Column\": \"x_BillingProfileId\", \"Properties\": { \"Field\": \"x_BillingProfileId\" } },\n { \"Column\": \"x_BillingProfileName\", \"Properties\": { \"Field\": \"x_BillingProfileName\" } },\n { \"Column\": \"x_ChargeId\", \"Properties\": { \"Field\": \"x_ChargeId\" } },\n { \"Column\": \"x_ContractedCostInUsd\", \"Properties\": { \"Field\": \"x_ContractedCostInUsd\" } },\n { \"Column\": \"x_CommodityCode\", \"Properties\": { \"Field\": \"x_CommodityCode\" } },\n { \"Column\": \"x_CommodityName\", \"Properties\": { \"Field\": \"x_CommodityName\" } },\n { \"Column\": \"x_ComponentName\", \"Properties\": { \"Field\": \"x_ComponentName\" } },\n { \"Column\": \"x_ComponentType\", \"Properties\": { \"Field\": \"x_ComponentType\" } },\n { \"Column\": \"x_Cost\", \"Properties\": { \"Field\": \"x_Cost\" } },\n { \"Column\": \"x_CostAllocationRuleName\", \"Properties\": { \"Field\": \"x_CostAllocationRuleName\" } },\n { \"Column\": \"x_CostCategories\", \"Properties\": { \"Field\": \"x_CostCategories\" } },\n { \"Column\": \"x_CostCenter\", \"Properties\": { \"Field\": \"x_CostCenter\" } },\n { \"Column\": \"x_Credits\", \"Properties\": { \"Field\": \"x_Credits\" } },\n { \"Column\": \"x_CostType\", \"Properties\": { \"Field\": \"x_CostType\" } },\n { \"Column\": \"x_CurrencyConversionRate\", \"Properties\": { \"Field\": \"x_CurrencyConversionRate\" } },\n { \"Column\": \"x_CustomerId\", \"Properties\": { \"Field\": \"x_CustomerId\" } },\n { \"Column\": \"x_CustomerName\", \"Properties\": { \"Field\": \"x_CustomerName\" } },\n { \"Column\": \"x_Discount\", \"Properties\": { \"Field\": \"x_Discount\" } },\n { \"Column\": \"x_EffectiveCostInUsd\", \"Properties\": { \"Field\": \"x_EffectiveCostInUsd\" } },\n { \"Column\": \"x_EffectiveUnitPrice\", \"Properties\": { \"Field\": \"x_EffectiveUnitPrice\" } },\n { \"Column\": \"x_ExportTime\", \"Properties\": { \"Field\": \"x_ExportTime\" } },\n { \"Column\": \"x_InstanceID\", \"Properties\": { \"Field\": \"x_InstanceID\" } },\n { \"Column\": \"x_InvoiceId\", \"Properties\": { \"Field\": \"x_InvoiceId\" } },\n { \"Column\": \"x_InvoiceIssuerId\", \"Properties\": { \"Field\": \"x_InvoiceIssuerId\" } },\n { \"Column\": \"x_InvoiceSectionId\", \"Properties\": { \"Field\": \"x_InvoiceSectionId\" } },\n { \"Column\": \"x_InvoiceSectionName\", \"Properties\": { \"Field\": \"x_InvoiceSectionName\" } },\n { \"Column\": \"x_ListCostInUsd\", \"Properties\": { \"Field\": \"x_ListCostInUsd\" } },\n { \"Column\": \"x_Location\", \"Properties\": { \"Field\": \"x_Location\" } },\n { \"Column\": \"x_OnDemandCost\", \"Properties\": { \"Field\": \"x_OnDemandCost\" } },\n { \"Column\": \"x_OnDemandCostInUsd\", \"Properties\": { \"Field\": \"x_OnDemandCostInUsd\" } },\n { \"Column\": \"x_OnDemandUnitPrice\", \"Properties\": { \"Field\": \"x_OnDemandUnitPrice\" } },\n { \"Column\": \"x_Operation\", \"Properties\": { \"Field\": \"x_Operation\" } },\n { \"Column\": \"x_OwnerAccountID\", \"Properties\": { \"Field\": \"x_OwnerAccountID\" } },\n { \"Column\": \"x_PartnerCreditApplied\", \"Properties\": { \"Field\": \"x_PartnerCreditApplied\" } },\n { \"Column\": \"x_PartnerCreditRate\", \"Properties\": { \"Field\": \"x_PartnerCreditRate\" } },\n { \"Column\": \"x_PricingBlockSize\", \"Properties\": { \"Field\": \"x_PricingBlockSize\" } },\n { \"Column\": \"x_PricingCurrency\", \"Properties\": { \"Field\": \"x_PricingCurrency\" } },\n { \"Column\": \"x_PricingSubcategory\", \"Properties\": { \"Field\": \"x_PricingSubcategory\" } },\n { \"Column\": \"x_PricingUnitDescription\", \"Properties\": { \"Field\": \"x_PricingUnitDescription\" } },\n { \"Column\": \"x_Project\", \"Properties\": { \"Field\": \"x_Project\" } },\n { \"Column\": \"x_PublisherCategory\", \"Properties\": { \"Field\": \"x_PublisherCategory\" } },\n { \"Column\": \"x_PublisherId\", \"Properties\": { \"Field\": \"x_PublisherId\" } },\n { \"Column\": \"x_ResellerId\", \"Properties\": { \"Field\": \"x_ResellerId\" } },\n { \"Column\": \"x_ResellerName\", \"Properties\": { \"Field\": \"x_ResellerName\" } },\n { \"Column\": \"x_ResourceGroupName\", \"Properties\": { \"Field\": \"x_ResourceGroupName\" } },\n { \"Column\": \"x_ResourceType\", \"Properties\": { \"Field\": \"x_ResourceType\" } },\n { \"Column\": \"x_ServiceCode\", \"Properties\": { \"Field\": \"x_ServiceCode\" } },\n { \"Column\": \"x_ServiceId\", \"Properties\": { \"Field\": \"x_ServiceId\" } },\n { \"Column\": \"x_ServiceModel\", \"Properties\": { \"Field\": \"x_ServiceModel\" } },\n { \"Column\": \"x_ServicePeriodEnd\", \"Properties\": { \"Field\": \"x_ServicePeriodEnd\" } },\n { \"Column\": \"x_ServicePeriodStart\", \"Properties\": { \"Field\": \"x_ServicePeriodStart\" } },\n { \"Column\": \"x_SkuDescription\", \"Properties\": { \"Field\": \"x_SkuDescription\" } },\n { \"Column\": \"x_SkuDetails\", \"Properties\": { \"Field\": \"x_SkuDetails\" } },\n { \"Column\": \"x_SkuIsCreditEligible\", \"Properties\": { \"Field\": \"x_SkuIsCreditEligible\" } },\n { \"Column\": \"x_SkuMeterCategory\", \"Properties\": { \"Field\": \"x_SkuMeterCategory\" } },\n { \"Column\": \"x_SkuMeterId\", \"Properties\": { \"Field\": \"x_SkuMeterId\" } },\n { \"Column\": \"x_SkuMeterName\", \"Properties\": { \"Field\": \"x_SkuMeterName\" } },\n { \"Column\": \"x_SkuMeterSubcategory\", \"Properties\": { \"Field\": \"x_SkuMeterSubcategory\" } },\n { \"Column\": \"x_SkuOfferId\", \"Properties\": { \"Field\": \"x_SkuOfferId\" } },\n { \"Column\": \"x_SkuOrderId\", \"Properties\": { \"Field\": \"x_SkuOrderId\" } },\n { \"Column\": \"x_SkuOrderName\", \"Properties\": { \"Field\": \"x_SkuOrderName\" } },\n { \"Column\": \"x_SkuPartNumber\", \"Properties\": { \"Field\": \"x_SkuPartNumber\" } },\n { \"Column\": \"x_SkuPlanName\", \"Properties\": { \"Field\": \"x_SkuPlanName\" } },\n { \"Column\": \"x_SkuRegion\", \"Properties\": { \"Field\": \"x_SkuRegion\" } },\n { \"Column\": \"x_SkuServiceFamily\", \"Properties\": { \"Field\": \"x_SkuServiceFamily\" } },\n { \"Column\": \"x_SkuTerm\", \"Properties\": { \"Field\": \"x_SkuTerm\" } },\n { \"Column\": \"x_SkuTier\", \"Properties\": { \"Field\": \"x_SkuTier\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } },\n { \"Column\": \"x_SubproductName\", \"Properties\": { \"Field\": \"x_SubproductName\" } },\n { \"Column\": \"x_UsageType\", \"Properties\": { \"Field\": \"x_UsageType\" } }\n]\n```\n\n// Costs_raw retention policy (clear historical data)\n.alter-merge table Costs_raw policy retention softdelete = 0d recoverability = disabled\n\n// Costs_raw retention policy (set the user-defined retention period)\n.alter-merge table Costs_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable Costs_raw streaming ingestion (required for Fabric)\n.alter table Costs_raw policy streamingingestion disable\n\n\n//===| Prices |=========================================================================================================\n// NOTE: Must be before cost details.\n//\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_raw table -- Create the table if it doesn't exist\n.create-merge table Prices_raw ( ignore: string )\n\n// Prices_raw table -- Remove all columns to allow changing column types\n.alter table Prices_raw ( ignore: string )\n\n// Prices_raw table -- Redefine all columns\n.alter table Prices_raw (\n BasePrice: real, // Azure EA + MCA\n BillingAccountId: string, // Azure MCA\n BillingAccountName: string, // Azure MCA\n BillingCurrency: string, // Azure MCA\n BillingProfileId: string, // Azure MCA\n BillingProfileName: string, // Azure MCA\n Currency: string, // Azure MCA\n CurrencyCode: string, // Azure EA\n EffectiveEndDate: datetime, // Azure MCA\n EffectiveStartDate: datetime, // Azure EA + MCA\n EnrollmentNumber: string, // Azure EA\n IncludedQuantity: real, // Azure EA\n MarketPrice: real, // Azure EA + MCA\n MeterCategory: string, // Azure EA + MCA\n MeterId: string, // Azure MCA\n MeterID: string, // Azure EA\n MeterName: string, // Azure EA + MCA\n MeterRegion: string, // Azure EA + MCA\n MeterSubCategory: string, // Azure EA + MCA\n MeterType: string, // Azure EA + MCA\n OfferID: string, // Azure EA\n PartNumber: string, // Azure EA\n PriceType: string, // Azure EA + MCA\n Product: string, // Azure EA + MCA\n ProductId: string, // Azure MCA\n ProductID: string, // Azure EA\n ServiceFamily: string, // Azure EA + MCA\n SkuId: string, // Azure MCA\n SkuID: string, // Azure EA\n Term: string, // Azure EA + MCA\n TierMinimumUnits: real, // Azure MCA\n UnitOfMeasure: string, // Azure EA + MCA\n UnitPrice: real, // Azure EA + MCA\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string // Hubs v1_0+\n)\n\n// Prices_raw ingestion mapping\n.create-or-alter table Prices_raw ingestion parquet mapping \"Prices_raw_mapping\"\n```\n[\n { \"Column\": \"BasePrice\", \"Properties\": { \"Field\": \"BasePrice\" } },\n { \"Column\": \"BillingAccountId\", \"Properties\": { \"Field\": \"BillingAccountId\" } },\n { \"Column\": \"BillingAccountName\", \"Properties\": { \"Field\": \"BillingAccountName\" } },\n { \"Column\": \"BillingCurrency\", \"Properties\": { \"Field\": \"BillingCurrency\" } },\n { \"Column\": \"BillingProfileId\", \"Properties\": { \"Field\": \"BillingProfileId\" } },\n { \"Column\": \"BillingProfileName\", \"Properties\": { \"Field\": \"BillingProfileName\" } },\n { \"Column\": \"Currency\", \"Properties\": { \"Field\": \"Currency\" } },\n { \"Column\": \"CurrencyCode\", \"Properties\": { \"Field\": \"CurrencyCode\" } },\n { \"Column\": \"EffectiveEndDate\", \"Properties\": { \"Field\": \"EffectiveEndDate\" } },\n { \"Column\": \"EffectiveStartDate\", \"Properties\": { \"Field\": \"EffectiveStartDate\" } },\n { \"Column\": \"EnrollmentNumber\", \"Properties\": { \"Field\": \"EnrollmentNumber\" } },\n { \"Column\": \"IncludedQuantity\", \"Properties\": { \"Field\": \"IncludedQuantity\" } },\n { \"Column\": \"MarketPrice\", \"Properties\": { \"Field\": \"MarketPrice\" } },\n { \"Column\": \"MeterCategory\", \"Properties\": { \"Field\": \"MeterCategory\" } },\n { \"Column\": \"MeterId\", \"Properties\": { \"Field\": \"MeterId\" } },\n { \"Column\": \"MeterID\", \"Properties\": { \"Field\": \"MeterID\" } },\n { \"Column\": \"MeterName\", \"Properties\": { \"Field\": \"MeterName\" } },\n { \"Column\": \"MeterRegion\", \"Properties\": { \"Field\": \"MeterRegion\" } },\n { \"Column\": \"MeterSubCategory\", \"Properties\": { \"Field\": \"MeterSubCategory\" } },\n { \"Column\": \"MeterType\", \"Properties\": { \"Field\": \"MeterType\" } },\n { \"Column\": \"OfferID\", \"Properties\": { \"Field\": \"OfferID\" } },\n { \"Column\": \"PartNumber\", \"Properties\": { \"Field\": \"PartNumber\" } },\n { \"Column\": \"PriceType\", \"Properties\": { \"Field\": \"PriceType\" } },\n { \"Column\": \"Product\", \"Properties\": { \"Field\": \"Product\" } },\n { \"Column\": \"ProductId\", \"Properties\": { \"Field\": \"ProductId\" } },\n { \"Column\": \"ProductID\", \"Properties\": { \"Field\": \"ProductID\" } },\n { \"Column\": \"ServiceFamily\", \"Properties\": { \"Field\": \"ServiceFamily\" } },\n { \"Column\": \"SkuId\", \"Properties\": { \"Field\": \"SkuId\" } },\n { \"Column\": \"SkuID\", \"Properties\": { \"Field\": \"SkuID\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"TierMinimumUnits\", \"Properties\": { \"Field\": \"TierMinimumUnits\" } },\n { \"Column\": \"UnitOfMeasure\", \"Properties\": { \"Field\": \"UnitOfMeasure\" } },\n { \"Column\": \"UnitPrice\", \"Properties\": { \"Field\": \"UnitPrice\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } }\n]\n```\n\n// Prices_raw retention policy (clear historical data)\n.alter-merge table Prices_raw policy retention softdelete = 0d recoverability = disabled\n\n// Prices_raw retention policy (set the user-defined retention period)\n.alter-merge table Prices_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable Prices_raw streaming ingestion (required for Fabric)\n.alter table Prices_raw policy streamingingestion disable\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_raw table -- Create the table if it doesn't exist\n.create-merge table Recommendations_raw ( ignore: string )\n\n// Recommendations_raw table -- Remove all columns to allow changing column types\n.alter table Recommendations_raw ( ignore: string )\n\n// Recommendations_raw table -- Redefine all columns\n.alter table Recommendations_raw (\n CostWithNoReservedInstances: real, // MS CM EA resv reco 2024-05-01\n CostWithNoReservedInstancesJson: string, // MS CM MCA resv reco 2024-05-01 -- Renamed to remove spaces and flag as JSON\n FirstUsageDate: datetime, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n InstanceFlexibilityGroup: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n InstanceFlexibilityRatio: real, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n Location: string, // MS CM EA+MCA resv reco 2024-05-01\n LookBackPeriod: string, // MS CM EA+MCA resv reco 2024-05-01\n MeterId: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n NetSavings: real, // MS CM EA resv reco 2024-05-01\n NetSavingsJson: string, // MS CM MCA resv reco 2024-05-01 -- Renamed to remove spaces and flag as JSON\n NormalizedSize: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n ProviderName: string, // Hubs v1_2\n RecommendedQuantity: real, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n RecommendedQuantityNormalized: real, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n ResourceId: string, // Hubs v1_2\n ResourceName: string, // Hubs v1_2\n ResourceType: string, // Hubs v1_2, MS CM EA+MCA resv reco 2024-05-01\n Scope: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n SKU: string, // MS CM EA resv reco 2024-05-01\n SkuName: string, // MS CM MCA resv reco 2024-05-01 -- Renamed to remove spaces\n SkuProperties: string, // MS CM EA/MCA resv reco 2024-05-01 -- Renamed for MCA\n SubAccountId: string, // Hubs v1_2\n SubAccountName: string, // Hubs v1_2\n SubscriptionId: string, // MS CM EA+MCA resv reco 2024-05-01\n Term: string, // MS CM EA+MCA resv reco 2024-05-01\n TotalCostWithReservedInstances: real, // MS CM EA resv reco 2024-05-01\n TotalCostWithReservedInstancesJson: string, // MS CM MCA resv reco 2024-05-01 -- Renamed to remove spaces and flag as JSON\n x_EffectiveCostAfter: real, // Hubs v1_2\n x_EffectiveCostBefore: real, // Hubs v1_2\n x_EffectiveCostSavings: real, // Hubs v1_2\n x_RecommendationCategory: string, // Hubs v1_2\n x_RecommendationDate: datetime, // Hubs v1_2\n x_RecommendationDescription: string, // Hubs v1_2\n x_RecommendationDetails: dynamic, // Hubs v1_2\n x_RecommendationId: string, // Hubs v1_2\n x_ResourceGroupName: string, // Hubs v1_2\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string // Hubs v1_0+\n)\n\n// Recommendations_raw ingestion mapping\n.create-or-alter table Recommendations_raw ingestion parquet mapping \"Recommendations_raw_mapping\"\n```\n[\n { \"Column\": \"CostWithNoReservedInstances\", \"Properties\": { \"Field\": \"CostWithNoReservedInstances\" } },\n { \"Column\": \"CostWithNoReservedInstancesJson\", \"Properties\": { \"Field\": \"CostWithNoReservedInstancesJson\" } },\n { \"Column\": \"FirstUsageDate\", \"Properties\": { \"Field\": \"FirstUsageDate\" } },\n { \"Column\": \"InstanceFlexibilityGroup\", \"Properties\": { \"Field\": \"InstanceFlexibilityGroup\" } },\n { \"Column\": \"InstanceFlexibilityRatio\", \"Properties\": { \"Field\": \"InstanceFlexibilityRatio\" } },\n { \"Column\": \"Location\", \"Properties\": { \"Field\": \"Location\" } },\n { \"Column\": \"LookBackPeriod\", \"Properties\": { \"Field\": \"LookBackPeriod\" } },\n { \"Column\": \"MeterId\", \"Properties\": { \"Field\": \"MeterId\" } },\n { \"Column\": \"NetSavings\", \"Properties\": { \"Field\": \"NetSavings\" } },\n { \"Column\": \"NetSavingsJson\", \"Properties\": { \"Field\": \"NetSavingsJson\" } },\n { \"Column\": \"NormalizedSize\", \"Properties\": { \"Field\": \"NormalizedSize\" } },\n { \"Column\": \"ProviderName\", \"Properties\": { \"Field\": \"ProviderName\" } },\n { \"Column\": \"RecommendedQuantity\", \"Properties\": { \"Field\": \"RecommendedQuantity\" } },\n { \"Column\": \"RecommendedQuantityNormalized\", \"Properties\": { \"Field\": \"RecommendedQuantityNormalized\" } },\n { \"Column\": \"ResourceId\", \"Properties\": { \"Field\": \"ResourceId\" } },\n { \"Column\": \"ResourceName\", \"Properties\": { \"Field\": \"ResourceName\" } },\n { \"Column\": \"ResourceType\", \"Properties\": { \"Field\": \"ResourceType\" } },\n { \"Column\": \"Scope\", \"Properties\": { \"Field\": \"Scope\" } },\n { \"Column\": \"SKU\", \"Properties\": { \"Field\": \"SKU\" } },\n { \"Column\": \"SkuName\", \"Properties\": { \"Field\": \"SkuName\" } },\n { \"Column\": \"SkuProperties\", \"Properties\": { \"Field\": \"SkuProperties\" } },\n { \"Column\": \"SubAccountId\", \"Properties\": { \"Field\": \"SubAccountId\" } },\n { \"Column\": \"SubAccountName\", \"Properties\": { \"Field\": \"SubAccountName\" } },\n { \"Column\": \"SubscriptionId\", \"Properties\": { \"Field\": \"SubscriptionId\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"TotalCostWithReservedInstances\", \"Properties\": { \"Field\": \"TotalCostWithReservedInstances\" } },\n { \"Column\": \"TotalCostWithReservedInstancesJson\", \"Properties\": { \"Field\": \"TotalCostWithReservedInstancesJson\" } },\n { \"Column\": \"x_EffectiveCostAfter\", \"Properties\": { \"Field\": \"x_EffectiveCostAfter\" } },\n { \"Column\": \"x_EffectiveCostBefore\", \"Properties\": { \"Field\": \"x_EffectiveCostBefore\" } },\n { \"Column\": \"x_EffectiveCostSavings\", \"Properties\": { \"Field\": \"x_EffectiveCostSavings\" } },\n { \"Column\": \"x_RecommendationCategory\", \"Properties\": { \"Field\": \"x_RecommendationCategory\" } },\n { \"Column\": \"x_RecommendationDate\", \"Properties\": { \"Field\": \"x_RecommendationDate\" } },\n { \"Column\": \"x_RecommendationDescription\", \"Properties\": { \"Field\": \"x_RecommendationDescription\" } },\n { \"Column\": \"x_RecommendationDetails\", \"Properties\": { \"Field\": \"x_RecommendationDetails\" } },\n { \"Column\": \"x_RecommendationId\", \"Properties\": { \"Field\": \"x_RecommendationId\" } },\n { \"Column\": \"x_ResourceGroupName\", \"Properties\": { \"Field\": \"x_ResourceGroupName\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } }\n]\n```\n\n// Recommendations_raw retention policy (clear historical data)\n.alter-merge table Recommendations_raw policy retention softdelete = 0d recoverability = disabled\n\n// Recommendations_raw retention policy (set the user-defined retention period)\n.alter-merge table Recommendations_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable Recommendations_raw streaming ingestion (required for Fabric)\n.alter table Recommendations_raw policy streamingingestion disable\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_raw table -- Create the table if it doesn't exist\n.create-merge table Transactions_raw ( ignore: string )\n\n// Transactions_raw table -- Remove all columns to allow changing column types\n.alter table Transactions_raw ( ignore: string )\n\n// Transactions_raw table -- Redefine all columns\n.alter table Transactions_raw (\n AccountName: string, // MS CM EA resv trans 2023-05-01\n AccountOwnerEmail: string, // MS CM EA resv trans 2023-05-01\n Amount: real, // MS CM EA+MCA resv trans 2023-05-01\n ArmSkuName: string, // MS CM EA+MCA resv trans 2023-05-01\n BillingFrequency: string, // MS CM EA+MCA resv trans 2023-05-01\n BillingMonth: string, // MS CM EA resv trans 2023-05-01\n BillingProfileId: string, // MS CM MCA resv trans 2023-05-01\n BillingProfileName: string, // MS CM MCA resv trans 2023-05-01\n CostCenter: string, // MS CM EA resv trans 2023-05-01\n Currency: string, // MS CM EA+MCA resv trans 2023-05-01\n CurrentEnrollmentId: string, // MS CM EA resv trans 2023-05-01\n DepartmentName: string, // MS CM EA resv trans 2023-05-01\n Description: string, // MS CM EA+MCA resv trans 2023-05-01\n EventDate: datetime, // MS CM EA+MCA resv trans 2023-05-01\n EventType: string, // MS CM EA+MCA resv trans 2023-05-01\n Invoice: string, // MS CM EA+MCA resv trans 2023-05-01\n InvoiceId: string, // MS CM EA+MCA resv trans 2023-05-01\n InvoiceSectionId: string, // MS CM MCA resv trans 2023-05-01\n InvoiceSectionName: string, // MS CM MCA resv trans 2023-05-01\n MonetaryCommitment: real, // MS CM EA resv trans 2023-05-01\n Overage: real, // MS CM EA resv trans 2023-05-01\n PurchasingEnrollment: string, // MS CM EA resv trans 2023-05-01\n PurchasingSubscriptionGuid: string, // MS CM EA+MCA resv trans 2023-05-01\n PurchasingSubscriptionName: string, // MS CM EA+MCA resv trans 2023-05-01\n Quantity: real, // MS CM EA+MCA resv trans 2023-05-01\n Region: string, // MS CM EA+MCA resv trans 2023-05-01\n ReservationOrderId: string, // MS CM EA+MCA resv trans 2023-05-01\n ReservationOrderName: string, // MS CM EA+MCA resv trans 2023-05-01\n Term: string, // MS CM EA+MCA resv trans 2023-05-01\n x_SourceName: string, // Hubs v1_0+\n x_SourceProvider: string, // Hubs v1_0+\n x_SourceType: string, // Hubs v1_0+\n x_SourceVersion: string // Hubs v1_0+\n)\n\n// Transactions_raw ingestion mapping\n.create-or-alter table Transactions_raw ingestion parquet mapping \"Transactions_raw_mapping\"\n```\n[\n { \"Column\": \"AccountName\", \"Properties\": { \"Field\": \"AccountName\" } },\n { \"Column\": \"AccountOwnerEmail\", \"Properties\": { \"Field\": \"AccountOwnerEmail\" } },\n { \"Column\": \"Amount\", \"Properties\": { \"Field\": \"Amount\" } },\n { \"Column\": \"ArmSkuName\", \"Properties\": { \"Field\": \"ArmSkuName\" } },\n { \"Column\": \"BillingFrequency\", \"Properties\": { \"Field\": \"BillingFrequency\" } },\n { \"Column\": \"BillingMonth\", \"Properties\": { \"Field\": \"BillingMonth\" } },\n { \"Column\": \"BillingProfileId\", \"Properties\": { \"Field\": \"BillingProfileId\" } },\n { \"Column\": \"BillingProfileName\", \"Properties\": { \"Field\": \"BillingProfileName\" } },\n { \"Column\": \"CostCenter\", \"Properties\": { \"Field\": \"CostCenter\" } },\n { \"Column\": \"Currency\", \"Properties\": { \"Field\": \"Currency\" } },\n { \"Column\": \"CurrentEnrollmentId\", \"Properties\": { \"Field\": \"CurrentEnrollmentId\" } },\n { \"Column\": \"DepartmentName\", \"Properties\": { \"Field\": \"DepartmentName\" } },\n { \"Column\": \"Description\", \"Properties\": { \"Field\": \"Description\" } },\n { \"Column\": \"EventDate\", \"Properties\": { \"Field\": \"EventDate\" } },\n { \"Column\": \"EventType\", \"Properties\": { \"Field\": \"EventType\" } },\n { \"Column\": \"Invoice\", \"Properties\": { \"Field\": \"Invoice\" } },\n { \"Column\": \"InvoiceId\", \"Properties\": { \"Field\": \"InvoiceId\" } },\n { \"Column\": \"InvoiceSectionId\", \"Properties\": { \"Field\": \"InvoiceSectionId\" } },\n { \"Column\": \"InvoiceSectionName\", \"Properties\": { \"Field\": \"InvoiceSectionName\" } },\n { \"Column\": \"MonetaryCommitment\", \"Properties\": { \"Field\": \"MonetaryCommitment\" } },\n { \"Column\": \"Overage\", \"Properties\": { \"Field\": \"Overage\" } },\n { \"Column\": \"PurchasingEnrollment\", \"Properties\": { \"Field\": \"PurchasingEnrollment\" } },\n { \"Column\": \"PurchasingSubscriptionGuid\", \"Properties\": { \"Field\": \"PurchasingSubscriptionGuid\" } },\n { \"Column\": \"PurchasingSubscriptionName\", \"Properties\": { \"Field\": \"PurchasingSubscriptionName\" } },\n { \"Column\": \"Quantity\", \"Properties\": { \"Field\": \"Quantity\" } },\n { \"Column\": \"Region\", \"Properties\": { \"Field\": \"Region\" } },\n { \"Column\": \"ReservationOrderId\", \"Properties\": { \"Field\": \"ReservationOrderId\" } },\n { \"Column\": \"ReservationOrderName\", \"Properties\": { \"Field\": \"ReservationOrderName\" } },\n { \"Column\": \"Term\", \"Properties\": { \"Field\": \"Term\" } },\n { \"Column\": \"x_SourceName\", \"Properties\": { \"Field\": \"x_SourceName\" } },\n { \"Column\": \"x_SourceProvider\", \"Properties\": { \"Field\": \"x_SourceProvider\" } },\n { \"Column\": \"x_SourceType\", \"Properties\": { \"Field\": \"x_SourceType\" } },\n { \"Column\": \"x_SourceVersion\", \"Properties\": { \"Field\": \"x_SourceVersion\" } }\n]\n```\n\n// Transactions_raw retention policy (clear historical data)\n.alter-merge table Transactions_raw policy retention softdelete = 0d recoverability = disabled\n\n// Transactions_raw retention policy (set the user-defined retention period)\n.alter-merge table Transactions_raw policy retention softdelete = $$rawRetentionInDays$$d recoverability = disabled\n\n// Disable Transactions_raw streaming ingestion (required for Fabric)\n.alter table Transactions_raw policy streamingingestion disable\n\n", - "$fxv#9": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// Used for data ingestion, normalization, and cleansing.\n// See known issues @ https://github.com/microsoft/finops-toolkit/issues/1111\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Prices |=========================================================================================================\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All prices transformed to FOCUS 1.0. Use Prices_transform_v1_2() instead.', folder='Prices')\nPrices_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n let prices = materialize(\n Prices_raw\n //\n // Change real to decimal\n | extend\n BasePrice = todecimal(BasePrice),\n IncludedQuantity = todecimal(IncludedQuantity),\n MarketPrice = todecimal(MarketPrice),\n TierMinimumUnits = todecimal(TierMinimumUnits),\n UnitPrice = todecimal(UnitPrice)\n //\n | extend x_SkuId = coalesce(SkuId, SkuID)\n | extend x_SkuMeterId = coalesce(MeterId, MeterID)\n | extend x_SkuProductId = coalesce(ProductId, ProductID)\n | extend x_SkuTerm = isoMonths(Term)\n | project-rename\n x_BaseUnitPrice = BasePrice,\n x_EffectivePeriodEnd = EffectiveEndDate,\n x_EffectivePeriodStart = EffectiveStartDate,\n x_PricingUnitDescription = UnitOfMeasure,\n x_SkuIncludedQuantity = IncludedQuantity,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuMeterType = MeterType,\n x_SkuOfferId = OfferID,\n x_SkuPartNumber = PartNumber,\n x_SkuPriceType = PriceType,\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTier = TierMinimumUnits\n | extend ContractedUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', UnitPrice, todecimal('')) // UnitPrice for savings plan is not the on-demand unit price\n | extend ListUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', MarketPrice, todecimal('')) // MarketPrice for savings plan is not the list price\n | extend ChargeCategory = case(\n x_SkuPriceType == 'Consumption', 'Usage',\n x_SkuPriceType == 'ReservedInstance', 'Purchase',\n x_SkuPriceType == 'SavingsPlan', 'Usage', // Savings plan prices are for committed usage, not the purchase\n ''\n )\n | extend SkuPriceIdv2 = strcat(case(x_SkuPriceType == 'Consumption', 'OD', x_SkuPriceType == 'ReservedInstance', 'RI', x_SkuPriceType == 'SavingsPlan', 'SP', 'XX'), substring(ChargeCategory, 0, 1), x_SkuTerm, '_', x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType, '_', x_SkuTier, x_SkuOfferId)\n | extend x_BillingAccountId = iff(BillingAccountId startswith '/', split(BillingAccountId, '/')[-1], coalesce(BillingAccountId, EnrollmentNumber))\n | extend x_BillingProfileId = iff(BillingProfileId startswith '/', split(BillingProfileId, '/')[-1], coalesce(BillingProfileId, EnrollmentNumber))\n | extend tmp_SavingsPlanKey = strcat(x_SkuMeterId, x_SkuProductId, x_SkuId, x_SkuTier, x_SkuOfferId)\n //\n // Get latest ingested row based on the unique ID\n | extend x_IngestionTime = ingestion_time()\n );\n //\n // Meters for reservations and savings plans to identify commitment eligibility\n let riMeters = prices | where x_SkuPriceType == 'ReservedInstance' | distinct x_SkuMeterId;\n let spMeters = prices | where x_SkuPriceType == 'SavingsPlan' | distinct x_SkuMeterId;\n //\n // Copy list/base/contracted prices from on-demand SKUs\n prices\n | where x_SkuPriceType == 'SavingsPlan'\n // If we use join, specify the shuffle key\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter hint.strategy=shuffle (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | lookup kind=leftouter (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | extend ListUnitPrice = coalesce(ListUnitPrice, ListUnitPrice1)\n | extend ContractedUnitPrice = coalesce(ContractedUnitPrice, ContractedUnitPrice1)\n | extend x_BaseUnitPrice = coalesce(x_BaseUnitPrice, x_BaseUnitPrice1)\n | project-away ListUnitPrice1, ContractedUnitPrice1, x_BaseUnitPrice1, tmp_SavingsPlanKey\n | union ((prices | where x_SkuPriceType != 'SavingsPlan'))\n //\n // Calculate commitment discount elgibility\n // TODO: Would a join be faster?\n | extend x_CommitmentDiscountSpendEligibility = iff(x_SkuMeterId in (riMeters) and x_SkuPriceType != 'ReservedInstance', 'Eligible', 'Not Eligible')\n | extend x_CommitmentDiscountUsageEligibility = iff(x_SkuMeterId in (spMeters), 'Eligible', 'Not Eligible')\n //\n // Add PricingUnit and x_PricingBlockSize\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter (PricingUnits) on x_PricingUnitDescription | project-away x_PricingUnitDescription1\n | lookup kind=leftouter (PricingUnits | extend x_PricingBlockSize = todecimal(x_PricingBlockSize)) on x_PricingUnitDescription\n //\n | extend x_EffectiveUnitPrice = iff(x_SkuPriceType == 'SavingsPlan', UnitPrice, todecimal('')) // Savings plan prices are for the effective price, not the contracted price\n | extend x_EffectiveUnitPriceDiscount = ContractedUnitPrice - x_EffectiveUnitPrice\n | extend x_ContractedUnitPriceDiscount = ListUnitPrice - ContractedUnitPrice\n | extend x_TotalUnitPriceDiscount = ListUnitPrice - x_EffectiveUnitPrice\n | project\n BillingAccountId = tolower(case(\n BillingProfileId startswith '/', BillingProfileId,\n BillingAccountId startswith '/', BillingAccountId,\n strcat('/providers/microsoft.billing/billingaccounts/', x_BillingAccountId, iff(x_BillingProfileId == x_BillingAccountId, '', strcat('/billingprofiles/', x_BillingProfileId)))\n )),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName, x_BillingProfileId),\n BillingCurrency = coalesce(BillingCurrency, CurrencyCode, Currency), // Currency last as a fallback only\n ChargeCategory,\n CommitmentDiscountCategory = case(\n x_SkuPriceType == 'ReservedInstance', 'Usage',\n x_SkuPriceType == 'SavingsPlan', 'Spend',\n ''\n ),\n CommitmentDiscountType = case(\n x_SkuPriceType == 'ReservedInstance', 'Reservation',\n x_SkuPriceType == 'SavingsPlan', 'Savings plan',\n ''\n ),\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory = case(\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed',\n ''\n ),\n PricingUnit,\n SkuId = coalesce(ProductId, ProductID),\n SkuPriceId = strcat(x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType),\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement = case(\n strlen(x_BillingAccountId) > 32, 'MCA',\n strlen(x_BillingAccountId) < 32, 'EA',\n 'Unknown'\n ),\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent = 1.0 * x_ContractedUnitPriceDiscount / ListUnitPrice * 100,\n x_EffectivePeriodEnd = startofmonth(x_EffectivePeriodEnd + 1h),\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent = 1.0 * x_EffectiveUnitPriceDiscount / ContractedUnitPrice * 100,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingCurrency = coalesce(Currency, CurrencyCode), // CurrencyCode last as a fallback only\n x_PricingSubcategory = case(\n x_SkuPriceType == 'Consumption' and (x_SkuIncludedQuantity > 0 or x_SkuTier > 0), 'Tiered',\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed Spend',\n ''\n ),\n x_PricingUnitDescription,\n x_SkuDescription = Product,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterName,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName = coalesce(x_SourceName, 'Cost Management'),\n x_SourceProvider = coalesce(x_SourceProvider, 'Microsoft'),\n x_SourceType = coalesce(x_SourceType, 'PriceSheet'),\n x_SourceVersion = coalesce(x_SourceVersion, '2023-05-01'),\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent = 1.0 * x_TotalUnitPriceDiscount / ListUnitPrice * 100\n}\n\n// Prices_final_v1_0 table\n.create-merge table Prices_final_v1_0 (\n BillingAccountId: string,\n BillingAccountName: string,\n BillingCurrency: string,\n ChargeCategory: string,\n CommitmentDiscountCategory: string,\n CommitmentDiscountType: string,\n ContractedUnitPrice: decimal,\n ListUnitPrice: decimal,\n PricingCategory: string,\n PricingUnit: string,\n SkuId: string,\n SkuPriceId: string,\n SkuPriceIdv2: string, // Hubs add-on\n x_BaseUnitPrice: decimal, // Azure\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure MCA\n x_BillingProfileId: string, // Azure MCA\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_ContractedUnitPriceDiscount: decimal, // Hubs add-on\n x_ContractedUnitPriceDiscountPercent: decimal, // Hubs add-on\n x_EffectivePeriodEnd: datetime, // Azure\n x_EffectivePeriodStart: datetime, // Azure\n x_EffectiveUnitPrice: decimal, // Azure\n x_EffectiveUnitPriceDiscount: decimal, // Hubs add-on\n x_EffectiveUnitPriceDiscountPercent: decimal, // Hubs add-on\n x_IngestionTime: datetime, // Hubs add-on\n x_PricingBlockSize: decimal, // Hubs add-on\n x_PricingCurrency: string, // Azure\n x_PricingSubcategory: string, // Hubs add-on\n x_PricingUnitDescription: string, // Azure\n x_SkuDescription: string, // Azure\n x_SkuId: string, // Azure\n x_SkuIncludedQuantity: decimal, // Azure EA\n x_SkuMeterCategory: string, // Azure\n x_SkuMeterId: string, // Azure\n x_SkuMeterName: string, // Azure\n x_SkuMeterSubcategory: string, // Azure\n x_SkuMeterType: string, // Azure\n x_SkuPriceType: string, // Azure\n x_SkuProductId: string, // Azure\n x_SkuRegion: string, // Azure\n x_SkuServiceFamily: string, // Azure\n x_SkuOfferId: string, // Azure EA\n x_SkuPartNumber: string, // Azure EA\n x_SkuTerm: int, // Azure\n x_SkuTier: decimal, // Azure MCA\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_TotalUnitPriceDiscount: decimal, // Hubs add-on\n x_TotalUnitPriceDiscountPercent: decimal // Hubs add-on\n)\n\n// Update policy for Prices_raw -> Prices_final_v1_0\n.alter table Prices_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Prices_raw\",\n \"Query\": \"Prices_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Cost and usage |=================================================================================================\n// Supported versions:\n// - MS: 1.0, 1.0-preview(v1) -- See https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0 -- See https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024 -- See https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 -- See https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All costs transformed to FOCUS 1.0. Use Costs_transform_v1_2() instead.', folder='Costs')\nCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n Costs_raw\n //\n // Change real to decimal\n | extend\n BilledCost = todecimal(BilledCost),\n CommitmentDiscountQuantity = todecimal(CommitmentDiscountQuantity),\n ConsumedQuantity = todecimal(ConsumedQuantity),\n ContractedCost = todecimal(ContractedCost),\n ContractedUnitPrice = todecimal(ContractedUnitPrice),\n EffectiveCost = todecimal(EffectiveCost),\n ListCost = todecimal(ListCost),\n ListUnitPrice = todecimal(ListUnitPrice),\n PricingQuantity = todecimal(PricingQuantity),\n UsageAmount = todecimal(UsageAmount),\n UsageQuantity = todecimal(UsageQuantity),\n x_BilledCostInUsd = todecimal(x_BilledCostInUsd),\n x_BilledUnitPrice = todecimal(x_BilledUnitPrice),\n x_BillingExchangeRate = todecimal(x_BillingExchangeRate),\n x_ContractedCostInUsd = todecimal(x_ContractedCostInUsd),\n x_Cost = todecimal(x_Cost),\n x_CurrencyConversionRate = todecimal(x_CurrencyConversionRate),\n x_EffectiveCostInUsd = todecimal(x_EffectiveCostInUsd),\n x_EffectiveUnitPrice = todecimal(x_EffectiveUnitPrice),\n x_ListCostInUsd = todecimal(x_ListCostInUsd),\n x_OnDemandCost = todecimal(x_OnDemandCost),\n x_OnDemandCostInUsd = todecimal(x_OnDemandCostInUsd),\n x_OnDemandUnitPrice = todecimal(x_OnDemandUnitPrice),\n x_PricingBlockSize = todecimal(x_PricingBlockSize)\n //\n // Dedupe rows\n | extend x_IngestionTime = ingestion_time()\n | extend x_ChargeId = ''\n // TODO: Consider adding a unique charge ID per row\n // hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // // 1. Resource hierarchy (including resource name), highest to lowest\n // BillingAccountId,\n // x_InvoiceSectionId,\n // x_AccountOwnerId,\n // SubAccountId,\n // x_ResourceGroupName,\n // ResourceName,\n // // 2. Resource details\n // ResourceId,\n // RegionId,\n // Tags,\n // CommitmentDiscountId,\n // x_CostCenter,\n // // 4. Meter details\n // SkuPriceId,\n // x_SkuMeterId,\n // x_SkuPartNumber,\n // x_SkuOfferId,\n // x_SkuDetails,\n // // 5. Date\n // ChargePeriodStart\n // ))\n //\n // Identify data quality issues\n | extend x_SourceChanges = trim_end(',', strcat(\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based', 'InvalidChargeFrequency,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and EffectiveCost > 0, 'InvalidEffectiveCost,', ''),\n iff((isempty(ContractedCost) or ContractedCost == 0) and EffectiveCost != 0, 'MissingContractedCost,', ''),\n iff((isempty(ContractedUnitPrice) or ContractedUnitPrice == 0) and x_EffectiveUnitPrice != 0, 'MissingContractedUnitPrice,', ''),\n iff(ListCost < ContractedCost, 'ListCostLessThanContractedCost,', ''),\n iff(ContractedCost < EffectiveCost, 'ContractedCostLessThanEffectiveCost,', ''),\n iff((isempty(ListCost) or ListCost == 0) and (ContractedCost != 0 or EffectiveCost != 0), 'MissingListCost,', ''),\n iff((isempty(ListUnitPrice) or ListUnitPrice == 0) and (ContractedUnitPrice != 0 or x_EffectiveUnitPrice != 0), 'MissingListUnitPrice,', ''),\n iff((isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001)\n or (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001),\n 'XEffectiveUnitPriceRoundingError,', ''),\n iff(ConsumedQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingConsumedQuantity,', ''),\n iff(PricingQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingPricingQuantity,', ''),\n iff(isempty(ProviderName), 'MissingProviderName,', ''),\n iff(isempty(PublisherName), 'MissingPublisherName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceId), 'MissingResourceId,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceName), 'MissingResourceName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceType), 'MissingResourceType,', ''),\n iff(BilledCost > 0 and x_BilledUnitPrice == 0, 'MissingXBilledUnitPrice,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(x_ResourceType), 'MissingXResourceType,', ''),\n iff(PricingCategory == 'Standard' and isnotempty(CommitmentDiscountId) and ChargeCategory == 'Usage', 'PricingCategoryShouldBeCommitted,', ''),\n iff(x_SkuTerm == '1Year' or x_SkuTerm == '3Years' or x_SkuTerm == '5Years', 'SkuTermShouldBeAnInteger,', '')\n ))\n //\n // Fix columns needed in other changes\n | extend ProviderName = case(\n isnotempty(ProviderName), ProviderName,\n isnotempty(coalesce(x_CostCategories, x_Discount, x_Operation, x_ServiceCode, x_UsageType)), 'AWS',\n isnotempty(coalesce(tostring(UsageAmount), tostring(x_Cost), x_Credits, x_CostType, tostring(x_CurrencyConversionRate), tostring(x_ExportTime), x_Project, x_ServiceId)), 'GCP',\n isnotempty(coalesce(x_BillingProfileId, x_InvoiceSectionId)), 'Microsoft',\n ''\n )\n //\n // Identify source\n | extend x_SourceName = coalesce(x_SourceName, iff(isnotempty(x_BillingProfileId), 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(isnotempty(x_BillingProfileId), 'FocusCost', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, case(\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)) and isempty(SkuPriceDetails) and isnotempty(x_SkuDetails), '1.2-preview',\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)), '1.2',\n isnotempty(coalesce(ChargeClass, CommitmentDiscountStatus, tostring(ConsumedQuantity), ConsumedUnit, tostring(ContractedCost), tostring(ContractedUnitPrice), RegionId, RegionName)), '1.0',\n isnotempty(coalesce(ChargeSubcategory, Region, tostring(UsageQuantity), UsageUnit)), iff(ProviderName == 'Microsoft', '1.0-preview(v1)', '1.0-preview'),\n ''\n ))\n // Append version check error code\n | extend x_SourceChanges = iff(x_SourceVersion == '1.0', x_SourceChanges,\n strcat(x_SourceChanges, iff(isempty(x_SourceChanges), '', ','), iff(x_SourceVersion == '', 'UnknownFocusVersion', 'LegacyFocusVersion'))\n )\n //\n // Fix quantities\n | extend PricingQuantity = case(\n PricingQuantity != 0 or (EffectiveCost == 0 and BilledCost == 0), PricingQuantity,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(EffectiveCost) and EffectiveCost != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0, EffectiveCost / x_EffectiveUnitPrice,\n PricingQuantity\n )\n | extend ConsumedQuantity = case(\n isnotempty(ConsumedQuantity) and ConsumedQuantity != 0, ConsumedQuantity,\n ChargeCategory == 'Usage', PricingQuantity / coalesce(x_PricingBlockSize, decimal(1)),\n ConsumedQuantity\n )\n //\n // Populate missing prices -- mapping to on-demand prices requires meter ID and offer ID\n | extend tmp_MissingPrices = ProviderName == 'Microsoft'\n and (ListUnitPrice == 0 or ContractedUnitPrice == 0)\n and x_EffectiveUnitPrice != 0\n and not(CommitmentDiscountCategory == 'Spend' and CommitmentDiscountStatus == 'Unused')\n and isnotempty(x_SkuMeterId) and isnotempty(x_SkuOfferId)\n | as allCosts\n | where tmp_MissingPrices\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(ChargePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | as costsWithMissingPrices\n | join kind=leftouter (\n Prices_final_v1_0\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(x_EffectivePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | where x_SkuPriceType == 'Consumption' and tmp_ReservationPriceLookupKey in ((costsWithMissingPrices | summarize by tmp_ReservationPriceLookupKey))\n | summarize ListUnitPrice = min(ListUnitPrice), ContractedUnitPrice = min(ContractedUnitPrice) by tmp_ReservationPriceLookupKey, x_PricingBlockSize, PricingUnit\n ) on tmp_ReservationPriceLookupKey\n //\n // Select the best price to use for each row\n // TODO: Save values before changing -- | extend x_old_ContractedUnitPrice = ContractedUnitPrice, x_old_EffectiveUnitPrice = x_EffectiveUnitPrice, x_old_ListUnitPrice = ListUnitPrice, x_old_ListCost = ListCost, x_old_ContractedCost = ContractedCost\n | extend x_EffectiveUnitPrice = case(\n // If price is a rounding error away from the billed price, use the billed price\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001, x_BilledUnitPrice,\n // If price is a rounding error away from the contracted price, use the contracted price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001, ContractedUnitPrice,\n x_EffectiveUnitPrice\n )\n | extend ContractedUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ContractedUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ContractedUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // If billed price is available, assume the billed price is the same as contracted price to support aggregations\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, x_EffectiveUnitPrice,\n // Otherwise, assume the effective price is the same as contracted price to support aggregations\n x_EffectiveUnitPrice\n )\n | extend ListUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ListUnitPrice) and ListUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ListUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ListUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ListUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // Otherwise, assume the contracted price is the same as list price to support aggregations\n ContractedUnitPrice\n )\n // Calculate missing costs based on new prices -- If cost is already correct, keep that; if not and price is available, recalculate the cost; otherwise, keep the existing cost\n | extend ContractedCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ContractedCost) and ContractedCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedCost,\n // ContractedCost is 0 in all other scenarios...\n // If 0 and there's a billed cost and prices are the same, use BilledCost\n isnotempty(BilledCost) and BilledCost != 0 and ContractedUnitPrice == x_BilledUnitPrice, BilledCost,\n // If 0 and there's a billed cost and prices are the same, use EffectiveCost\n isnotempty(EffectiveCost) and EffectiveCost != 0 and ContractedUnitPrice == x_EffectiveUnitPrice, EffectiveCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0, ContractedUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume EffectiveCost\n isempty(ContractedUnitPrice) or ContractedUnitPrice == 0, EffectiveCost,\n // Fall back to the original value for any unhandled scenarios\n ContractedCost\n )\n | extend ListCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ListCost) and ListCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ListCost,\n // ListCost is 0 in all other scenarios...\n // If 0 and there's a contracted cost and prices are the same, use ContractedCost\n isnotempty(ContractedCost) and ContractedCost != 0 and ListUnitPrice == ContractedUnitPrice, ContractedCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ListUnitPrice) and ListUnitPrice != 0, ListUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume ContractedCost\n isempty(ListUnitPrice) or ListUnitPrice == 0, ContractedCost,\n // Fall back to the original value for any unhandled scenarios\n ListCost\n )\n // Merge the rest of the unmodified cost records and remove excess columns\n | union (allCosts | where not(tmp_MissingPrices))\n | project-away x_PricingBlockSize1, PricingUnit1, ListUnitPrice1, ContractedUnitPrice1, tmp_MissingPrices, tmp_ReservationPriceLookupKey, tmp_ReservationPriceLookupKey1\n //\n // BUG: Fix ContractedCost that has bad values\n | extend ContractedCost = iff(ProviderName == 'Microsoft' and isnotempty(PricingQuantity) and isnotempty(x_PricingBlockSize) and ContractedCost != ContractedUnitPrice * PricingQuantity, ContractedUnitPrice * PricingQuantity, ContractedCost)\n //\n // Handle FOCUS 1.0-preview UsageQuantity/Unit\n | extend ConsumedQuantity = iff(ChargeCategory == 'Usage', coalesce(ConsumedQuantity, UsageQuantity, UsageAmount), todecimal(''))\n | extend ConsumedUnit = iff(ChargeCategory == 'Usage' and isnotempty(ConsumedQuantity), coalesce(ConsumedUnit, UsageUnit, 'Units'), '')\n //\n // Convert IDs to lowercase for consistency\n | extend CommitmentDiscountId = tolower(CommitmentDiscountId)\n //\n // BUG: Remove EffectiveCost for commitment discount purchases\n | extend EffectiveCost = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), decimal(0), EffectiveCost)\n | extend x_EffectiveCostInUsd = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), decimal(0), x_EffectiveCostInUsd)\n //\n // Clean up resource columns\n | extend ResourceId = case(\n isnotempty(ResourceId), ResourceId,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), CommitmentDiscountId,\n ResourceId)\n | extend ResourceName = tolower(case(\n isnotempty(ResourceName), ResourceName,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountName), CommitmentDiscountName,\n isnotempty(ResourceId), parse_resourceid(ResourceId).ResourceName,\n ResourceName))\n | extend x_ResourceType = case(\n isnotempty(x_ResourceType), x_ResourceType,\n isnotempty(ResourceId), parse_resourceid(ResourceId).x_ResourceType,\n x_ResourceType)\n | extend ResourceType = case(\n // Use existing resource type display name unless it's an internal resource type ID\n isnotempty(ResourceType) and tolower(ResourceType) != tolower(x_ResourceType) and ResourceType !contains '/', ResourceType,\n // Use CommitmentDiscountType for commitment discount purchases\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountType), CommitmentDiscountType,\n // Look up display name from internal type\n isnotempty(x_ResourceType), coalesce(resource_type(x_ResourceType).SingularDisplayName, ResourceType, x_ResourceType),\n ResourceType)\n //\n // Sort columns and apply final transforms\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId = tolower(BillingAccountId),\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEnd),\n BillingPeriodStart = startofmonth(BillingPeriodStart),\n ChargeCategory = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Credit', 'Credit',\n ChargeSubcategory == 'Refund', 'Purchase', // We are assuming purchase refunds since we don't have data to indicate usage refunds\n ChargeCategory\n ),\n ChargeClass = case(ChargeSubcategory == 'Refund', 'Correction', ChargeClass),\n ChargeDescription,\n // BUG: ChargeFrequency shows \"Usage-Based\" for monthly recurring savings plan purchases\n ChargeFrequency = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based' and ProviderName == 'Microsoft' and x_SourceVersion startswith '1.0', 'Recurring', ChargeFrequency),\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId = tolower(CommitmentDiscountId),\n CommitmentDiscountName,\n CommitmentDiscountStatus = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Used Commitment', 'Used',\n ChargeSubcategory == 'Unused Commitment', 'Unused',\n CommitmentDiscountStatus\n ),\n CommitmentDiscountType,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost = coalesce(ContractedCost, x_OnDemandCost, x_Cost),\n ContractedUnitPrice = coalesce(ContractedUnitPrice, x_OnDemandUnitPrice),\n EffectiveCost,\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory = case(\n // Handle FOCUS 1.0-preview PricingCategory values\n PricingCategory == 'On-Demand', 'Standard',\n PricingCategory == 'Commitment-Based', 'Committed',\n PricingCategory\n ),\n PricingQuantity,\n PricingUnit,\n ProviderName,\n // Handle missing PublisherName values\n PublisherName = case(PublisherName == 'Microsoft Corporation', 'Microsoft', isnotempty(PublisherName), PublisherName, x_PublisherCategory == 'Cloud Provider', ProviderName, ''),\n // Handle FOCUS 1.0-preview Region column\n RegionId = coalesce(RegionId, iff(ProviderName == 'Microsoft', replace_string(tolower(Region), ' ', ''), Region)),\n RegionName = coalesce(RegionName, Region),\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SkuId,\n SkuPriceId,\n SubAccountId,\n SubAccountName,\n SubAccountType, // Azure 1.0-preview(v1)+\n Tags = parse_json(Tags),\n x_AccountId, // Azure 1.0-preview(v1)+\n x_AccountName, // Azure 1.0-preview(v1)+\n x_AccountOwnerId, // Azure 1.0-preview(v1)+\n x_BilledCostInUsd, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement = case(\n ProviderName == 'Microsoft' and x_BillingAccountId == x_BillingProfileId, 'EA',\n ProviderName == 'Microsoft' and x_BillingAccountId != x_BillingProfileId, 'MCA',\n ProviderName\n ), // Hubs add-on\n x_BillingAccountId, // Azure 1.0-preview(v1)+\n x_BillingAccountName, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate, // Azure 1.0-preview(v1)+\n x_BillingProfileId, // Azure 1.0-preview(v1)+\n x_BillingProfileName, // Azure 1.0-preview(v1)+\n x_ChargeId, // Azure 1.0-preview(v1) only\n x_ContractedCostInUsd = coalesce(x_ContractedCostInUsd, x_OnDemandCostInUsd), // Azure 1.0+\n x_CostAllocationRuleName, // Azure 1.0-preview(v1)+\n x_CostCategories = parse_json(x_CostCategories), // AWS 1.0 (JSON)\n x_CostCenter, // Azure 1.0-preview(v1)+\n x_Credits = parse_json(x_Credits), // GCP Jan 2024\n x_CostType, // GCP Jan 2024\n x_CurrencyConversionRate, // GCP Jun 2024\n x_CustomerId, // Azure 1.0-preview(v1)+\n x_CustomerName, // Azure 1.0-preview(v1)+\n x_Discount = parse_json(x_Discount), // AWS 1.0 (JSON)\n x_EffectiveCostInUsd, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice, // Azure 1.0-preview(v1)+\n x_ExportTime, // GCP Jan 2024\n x_IngestionTime, // Hubs add-on\n x_InvoiceId = coalesce(InvoiceId, x_InvoiceId), // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId = case( // Azure 1.0-preview(v1)+\n x_InvoiceSectionId == '-2', '',\n x_InvoiceSectionId\n ),\n x_InvoiceSectionName = case( // Azure 1.0-preview(v1)+\n x_InvoiceSectionName == 'Unassigned', '',\n x_InvoiceSectionName\n ),\n x_ListCostInUsd, // Azure 1.0-preview(v1)+\n x_Location, // GCP Jan 2024\n x_Operation, // AWS 1.0\n x_PartnerCreditApplied, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate, // Azure 1.0-preview(v1)+\n x_PricingBlockSize, // Azure 1.0-preview(v1)+\n x_PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency), // Azure 1.0-preview(v1)+\n x_PricingSubcategory, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription, // Azure 1.0-preview(v1)+\n x_Project, // GCP Jan 2024\n x_PublisherCategory, // Azure 1.0-preview(v1)+\n x_PublisherId, // Azure 1.0-preview(v1)+\n x_ResellerId, // Azure 1.0-preview(v1)+\n x_ResellerName, // Azure 1.0-preview(v1)+\n x_ResourceGroupName = tolower(x_ResourceGroupName), // Azure 1.0-preview(v1)+\n x_ResourceType, // Azure 1.0-preview(v1)+\n x_ServiceCode, // AWS 1.0\n x_ServiceId, // GCP Jan 2024\n x_ServicePeriodEnd, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart, // Azure 1.0-preview(v1)+\n x_SkuDescription, // Azure 1.0-preview(v1)+\n x_SkuDetails = parse_json(x_SkuDetails), // Azure 1.0-preview(v1)+\n x_SkuIsCreditEligible, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory, // Azure 1.0-preview(v1)+\n x_SkuMeterId, // Azure 1.0-preview(v1)+\n x_SkuMeterName = coalesce(SkuMeter, x_SkuMeterName), // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory, // Azure 1.0-preview(v1)+\n x_SkuOfferId, // Azure 1.0-preview(v1)+\n x_SkuOrderId, // Azure 1.0-preview(v1)+\n x_SkuOrderName, // Azure 1.0-preview(v1)+\n x_SkuPartNumber, // Azure 1.0-preview(v1)+\n x_SkuRegion, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily, // Azure 1.0-preview(v1)+\n x_SkuTerm, // Azure 1.0-preview(v1)+\n x_SkuTier, // Azure 1.0-preview(v1)+\n x_SourceChanges, // Hubs add-on\n x_SourceName, // Hubs add-on\n x_SourceProvider, // Hubs add-on\n x_SourceType, // Hubs add-on\n x_SourceVersion, // Hubs add-on\n x_UsageType // AWS 1.0\n}\n\n// Costs_final_v1_0 table\n.create-merge table Costs_final_v1_0 (\n AvailabilityZone: string,\n BilledCost: decimal,\n BillingAccountId: string,\n BillingAccountName: string,\n BillingAccountType: string, // Azure 1.0-preview(v1)+\n BillingCurrency: string,\n BillingPeriodEnd: datetime,\n BillingPeriodStart: datetime,\n ChargeCategory: string,\n ChargeClass: string,\n ChargeDescription: string,\n ChargeFrequency: string,\n ChargePeriodEnd: datetime,\n ChargePeriodStart: datetime,\n CommitmentDiscountCategory: string, // FOCUS 1.0-preview only\n CommitmentDiscountId: string,\n CommitmentDiscountName: string,\n CommitmentDiscountStatus: string,\n CommitmentDiscountType: string,\n ConsumedQuantity: decimal,\n ConsumedUnit: string,\n ContractedCost: decimal,\n ContractedUnitPrice: decimal,\n EffectiveCost: decimal,\n InvoiceIssuerName: string,\n ListCost: decimal,\n ListUnitPrice: decimal,\n PricingCategory: string,\n PricingQuantity: decimal,\n PricingUnit: string,\n ProviderName: string,\n PublisherName: string,\n RegionId: string,\n RegionName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n ServiceCategory: string,\n ServiceName: string,\n SkuId: string,\n SkuPriceId: string,\n SubAccountId: string,\n SubAccountName: string,\n SubAccountType: string,\n Tags: dynamic,\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_BilledCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: decimal, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: decimal, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_ContractedCostInUsd: decimal, // Azure 1.0+\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: dynamic, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_Credits: dynamic, // GCP Jan 2024\n x_CostType: string, // GCP Jan 2024\n x_CurrencyConversionRate: decimal, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: dynamic, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: decimal, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024\n x_IngestionTime: datetime, // Hubs add-on\n x_InvoiceId: string, // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_Operation: string, // AWS 1.0\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: decimal, // Azure 1.0-preview(v1)+\n x_PricingCurrency: string, // Azure 1.0-preview(v1)+\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: dynamic, // Azure 1.0-preview(v1)+\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterName: string, // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceChanges: string, // Hubs add-on\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_UsageType: string // AWS 1.0\n)\n\n// Update policy for Costs_raw -> Costs_final_v1_0 table\n.alter table Costs_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Costs_raw\",\n \"Query\": \"Costs_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Actual costs |===================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: ActualCost exports transformed to FOCUS 1.0. Use ActualCosts_transform_v1_2() instead.', folder='Costs')\nActualCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n // TODO: Transform actual costs to FOCUS 1.0 format\n ActualCosts_raw\n | where ChargeType in ('Purchase', 'Refund') and isnotempty(ReservationId)\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: ServiceSubcategory, PublisherName, x_PublisherCategory, x_Environment, x_ServiceModel\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodStart = Date,\n ChargePeriodEnd = Date + 1d,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = '',\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory = '',\n SkuId = '',\n SkuMeter = '',\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = SubscriptionName,\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentName = '',\n x_ComponentType = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel = '',\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for ActualCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": false,\n \"Source\": \"ActualCosts_raw\",\n \"Query\": \"ActualCosts_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Amortized costs |================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: ActualCost exports transformed to FOCUS 1.0. Use AmortizedCosts_transform_v1_2() instead.', folder='Costs')\nAmortizedCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n // TODO: Transform actual costs to FOCUS 1.0 format\n AmortizedCosts_raw\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: ServiceSubcategory, PublisherName, x_PublisherCategory, x_Environment, x_ServiceModel\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodStart = Date,\n ChargePeriodEnd = Date + 1d,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = '',\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory = '',\n SkuId = '',\n SkuMeter = '',\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = SubscriptionName,\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentName = '',\n x_ComponentType = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel = '',\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for AmortizedCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": false,\n \"Source\": \"AmortizedCosts_raw\",\n \"Query\": \"AmortizedCosts_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All commitment discount usage transformed to FOCUS 1.0. This includes reservationdeatils_raw. Use CommitmentDiscountUsage_transform_v1_2() instead.', folder='Commitment discounts')\nCommitmentDiscountUsage_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n CommitmentDiscountUsage_raw\n //\n // Change real to decimal\n | extend\n InstanceFlexibilityRatio = todecimal(InstanceFlexibilityRatio),\n ReservedHours = todecimal(ReservedHours),\n TotalReservedQuantity = todecimal(TotalReservedQuantity),\n UsedHours = todecimal(UsedHours)\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Handle resource columns\n | extend ResourceId = tolower(InstanceId)\n | extend tmp_ResourceDetails = parse_resourceid(ResourceId)\n | extend ResourceName = tostring(tmp_ResourceDetails.ResourceName)\n | extend SubAccountId = tostring(tmp_ResourceDetails.SubAccountId)\n | extend x_ResourceGroupName = tostring(tmp_ResourceDetails.x_ResourceGroupName)\n | extend x_ResourceType = tostring(tmp_ResourceDetails.x_ResourceType)\n | lookup kind=leftouter (ResourceTypes | distinct x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n | lookup kind=leftouter (Services | distinct x_ResourceType, ServiceName, ServiceCategory, x_ServiceModel) on x_ResourceType\n //\n // Sort columns and apply final transforms\n | project\n ChargePeriodEnd = UsageDate + 1d,\n ChargePeriodStart = UsageDate,\n CommitmentDiscountCategory = 'Usage',\n CommitmentDiscountId = tolower(strcat('/providers/microsoft.capacity/reservationorders/', ReservationOrderId, '/reservations/', ReservationId)),\n CommitmentDiscountType = 'Reservation',\n ConsumedQuantity = UsedHours,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SubAccountId,\n x_CommitmentDiscountCommittedCount = TotalReservedQuantity,\n x_CommitmentDiscountCommittedAmount = ReservedHours,\n // TODO: Is this needed? -- x_CommitmentDiscountKind = Kind,\n x_CommitmentDiscountNormalizedGroup = iff(InstanceFlexibilityGroup == 'NA', '', InstanceFlexibilityGroup),\n x_CommitmentDiscountNormalizedRatio = InstanceFlexibilityRatio,\n x_CommitmentDiscountQuantity = UsedHours * InstanceFlexibilityRatio,\n x_IngestionTime = ingestion_time(),\n x_ResourceGroupName,\n x_ResourceType,\n // x_RowId = hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // CommitmentDiscountId,\n // ResourceId,\n // ChargePeriodStart\n // )),\n x_ServiceModel,\n x_SkuOrderId = ReservationOrderId,\n x_SkuSize = iff(SkuName == 'NA', '', SkuName),\n x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName)),\n x_SourceProvider = coalesce(x_SourceProvider, ProviderName),\n x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationDetails', '')),\n x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2024-03-01', ''))\n}\n\n// CommitmentDiscountUsage_final_v1_0 table\n.create-merge table CommitmentDiscountUsage_final_v1_0 (\n ChargePeriodEnd: datetime, // Hubs add-on\n ChargePeriodStart: datetime, // MS 2023-03-01\n CommitmentDiscountCategory: string, // Hubs add-on\n CommitmentDiscountId: string, // MS 2023-03-01\n CommitmentDiscountType: string, // Hubs add-on\n ConsumedQuantity: decimal, // MS 2023-03-01\n ProviderName: string, // Hubs add-on\n ResourceId: string, // MS 2023-03-01\n ResourceName: string, // Hubs add-on\n ResourceType: string, // Hubs add-on\n ServiceCategory: string, // Hubs add-on\n ServiceName: string, // Hubs add-on\n SubAccountId: string, // Hubs add-on\n x_CommitmentDiscountCommittedCount: decimal, // MS 2023-03-01\n x_CommitmentDiscountCommittedAmount: decimal, // MS 2023-03-01\n x_CommitmentDiscountNormalizedGroup: string, // MS 2023-03-01\n x_CommitmentDiscountNormalizedRatio: decimal, // MS 2023-03-01\n x_CommitmentDiscountQuantity: decimal, // MS 2023-03-01\n x_IngestionTime: datetime, // Hubs add-on\n x_ResourceGroupName: string, // Hubs add-on\n x_ResourceType: string, // Hubs add-on\n x_ServiceModel: string, // Hubs add-on\n x_SkuOrderId: string, // MS 2023-03-01\n x_SkuSize: string, // MS 2023-03-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string // Hubs add-on\n)\n\n// Update policy for CommitmentDiscountUsage_raw -> CommitmentDiscountUsage_final_v1_0 table\n.alter table CommitmentDiscountUsage_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"CommitmentDiscountUsage_raw\",\n \"Query\": \"CommitmentDiscountUsage_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All recommendations transformed to FOCUS 1.0. Use Recommendations_transform_v1_2() instead.', folder='Recommendations')\nRecommendations_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Recommendations_raw\n //\n // Change real to decimal\n | extend\n CostWithNoReservedInstances = todecimal(CostWithNoReservedInstances),\n InstanceFlexibilityRatio = todecimal(InstanceFlexibilityRatio),\n NetSavings = todecimal(NetSavings),\n RecommendedQuantity = todecimal(RecommendedQuantity),\n RecommendedQuantityNormalized = todecimal(RecommendedQuantityNormalized),\n TotalCostWithReservedInstances = todecimal(TotalCostWithReservedInstances)\n //\n | extend x_IngestionTime = ingestion_time()\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationRecommendations', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Convert JSON cost columns to decimal\n | extend CostWithNoReservedInstances = case(isnotempty(CostWithNoReservedInstances), CostWithNoReservedInstances, isnotempty(CostWithNoReservedInstancesJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, CostWithNoReservedInstancesJson)), CostWithNoReservedInstances)\n | extend NetSavings = case(isnotempty(NetSavings), NetSavings, isnotempty(NetSavingsJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, NetSavingsJson)), NetSavings)\n | extend TotalCostWithReservedInstances = case(isnotempty(TotalCostWithReservedInstances), TotalCostWithReservedInstances, isnotempty(TotalCostWithReservedInstancesJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, TotalCostWithReservedInstancesJson)), TotalCostWithReservedInstances)\n //\n // Build recommendation details\n | lookup kind=leftouter (Regions | summarize RegionName = make_set(RegionName)[0] by Location = RegionId) on Location\n | extend x_RecommendationDetails = case(\n x_SourceType == 'ReservationRecommendations', bag_pack(\n 'CommitmentDiscountNormalizedGroup', InstanceFlexibilityGroup,\n 'CommitmentDiscountNormalizedRatio', InstanceFlexibilityRatio,\n 'CommitmentDiscountNormalizedSize', NormalizedSize,\n 'CommitmentDiscountResourceType', ResourceType,\n 'CommitmentDiscountScope', Scope,\n 'LookbackPeriodDuration', case(\n LookBackPeriod matches regex @'^Last([0-9]+)Days$', replace_regex(LookBackPeriod, @'^Last([0-9]+)Days$', @'P\\1D'),\n LookBackPeriod matches regex @'^[0-9]+$', strcat('P', LookBackPeriod, 'D'),\n ''\n ),\n 'LookbackPeriodStart', FirstUsageDate,\n 'RecommendedQuantity', RecommendedQuantity,\n 'RecommendedQuantityNormalized', RecommendedQuantityNormalized,\n 'RegionId', Location,\n 'RegionName', RegionName,\n 'SkuMeterId', MeterId,\n 'SkuPriceDetails', SkuProperties,\n 'SkuSize', coalesce(SKU, SkuName),\n 'SkuTerm', isoMonths(Term)\n ),\n dynamic({})\n )\n //\n // Sort columns and apply final transforms\n | extend x_RecommendationDate = FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d)\n | extend x_RecommendationDate = iff(x_RecommendationDate > now(), startofday(now()), x_RecommendationDate)\n | project\n ProviderName,\n SubAccountId = iff(isnotempty(SubscriptionId), strcat('/subscriptions/', SubscriptionId), ''),\n x_IngestionTime,\n x_EffectiveCostAfter = TotalCostWithReservedInstances,\n x_EffectiveCostBefore = CostWithNoReservedInstances,\n x_EffectiveCostSavings = NetSavings,\n x_RecommendationDate = FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d),\n x_RecommendationDetails,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n// Recommendations_final_v1_0 table\n.create-merge table Recommendations_final_v1_0 (\n ProviderName: string,\n SubAccountId: string,\n x_IngestionTime: datetime,\n x_EffectiveCostAfter: decimal,\n x_EffectiveCostBefore: decimal,\n x_EffectiveCostSavings: decimal,\n x_RecommendationDate: datetime,\n x_RecommendationDetails: dynamic,\n x_SourceName: string,\n x_SourceProvider: string,\n x_SourceType: string,\n x_SourceVersion: string\n)\n\n// Update policy for Recommendations_raw -> Recommendations_final_v1_0 table\n.alter table Recommendations_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Recommendations_raw\",\n \"Query\": \"Recommendations_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All transactions transformed to FOCUS 1.0. Use Transactions_transform_v1_2() instead.', folder='Transactions')\nTransactions_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Transactions_raw\n //\n // Change real to decimal\n | extend\n Amount = todecimal(Amount),\n MonetaryCommitment = todecimal(MonetaryCommitment),\n Overage = todecimal(Overage),\n Quantity = todecimal(Quantity)\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationTransactions', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Handle BillingPeriodStart/End\n | extend BillingMonth = tostring(BillingMonth)\n | extend BillingPeriodStart = iff(isempty(BillingMonth), datetime(null), todatetime(strcat(substring(BillingMonth, 0, 4), \"-\", substring(BillingMonth, 4, 2), \"-\", substring(BillingMonth, 6, 2))))\n | extend BillingPeriodEnd = iff(isempty(BillingMonth), datetime(null), startofmonth(endofmonth(BillingPeriodStart) + 1d))\n //\n // Sort columns and apply final transforms\n | project\n BilledCost = Amount,\n BillingAccountId = case(\n BillingProfileId startswith '/', BillingProfileId,\n isnotempty(CurrentEnrollmentId), strcat('/providers/Microsoft.Billing/billingAccounts/', CurrentEnrollmentId),\n isnotempty(BillingProfileId), strcat('/providers/Microsoft.Billing/billingProfiles/', BillingProfileId),\n ''\n ),\n BillingAccountName = coalesce(BillingProfileName, CurrentEnrollmentId),\n BillingCurrency = Currency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory = case(\n EventType in ('Cancel', 'Purchase', 'Refund'), 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = case(\n EventType == 'Cancel', 'Cancel', // FOCUS does not handle this scenario\n EventType == 'Refund', 'Correction',\n ''\n ),\n ChargeDescription = Description,\n ChargeFrequency = case(\n BillingFrequency == 'OneTime', 'One-Time',\n BillingFrequency == 'Recurring', 'Recurring',\n BillingFrequency\n ),\n ChargePeriodStart = EventDate,\n PricingQuantity = Quantity,\n PricingUnit = 'Reservations',\n ProviderName,\n RegionId = Region,\n RegionName = Region,\n SubAccountId = iff(isempty(PurchasingSubscriptionGuid), '', strcat('/subscriptions/', PurchasingSubscriptionGuid)),\n SubAccountName = iff(isempty(PurchasingSubscriptionGuid), '', PurchasingSubscriptionName),\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerEmail,\n x_CostCenter = CostCenter,\n x_InvoiceId = InvoiceId,\n x_InvoiceNumber = Invoice,\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = coalesce(InvoiceSectionName, DepartmentName),\n x_IngestionTime = ingestion_time(),\n x_MonetaryCommitment = MonetaryCommitment,\n x_Overage = Overage,\n x_PurchasingBillingAccountId = PurchasingEnrollment,\n x_SkuOrderId = ReservationOrderId,\n x_SkuOrderName = ReservationOrderName,\n x_SkuSize = ArmSkuName,\n x_SkuTerm = isoMonths(Term),\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId = PurchasingSubscriptionGuid,\n x_TransactionType = EventType\n}\n\n// Transactions_final_v1_0 table\n.create-merge table Transactions_final_v1_0 (\n BilledCost: decimal, // MS CM EA+MCA 2023-05-01\n BillingAccountId: string, // MS CM EA+MCA 2023-05-01\n BillingAccountName: string, // MS CM EA+MCA 2023-05-01\n BillingCurrency: string, // MS CM EA+MCA 2023-05-01\n BillingPeriodEnd: datetime, // MS CM EA+MCA 2023-05-01\n BillingPeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n ChargeCategory: string, // Hubs add-on\n ChargeClass: string, // Hubs add-on\n ChargeDescription: string, // MS CM EA+MCA 2023-05-01\n ChargeFrequency: string, // MS CM EA+MCA 2023-05-01\n ChargePeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n PricingQuantity: decimal, // MS CM EA+MCA 2023-05-01\n PricingUnit: string, // Hubs add-on\n ProviderName: string, // Hubs add-on\n RegionId: string, // MS CM EA+MCA 2023-05-01\n RegionName: string, // MS CM EA+MCA 2023-05-01\n SubAccountId: string, // MS CM EA+MCA 2023-05-01\n SubAccountName: string, // MS CM EA+MCA 2023-05-01\n x_AccountName: string, // MS CM EA 2023-05-01\n x_AccountOwnerId: string, // MS CM EA 2023-05-01\n x_CostCenter: string, // MS CM EA 2023-05-01\n x_InvoiceId: string, // MS CM MCA 2023-05-01\n x_InvoiceNumber: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionId: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionName: string, // MS CM MCA 2023-05-01\n x_IngestionTime: datetime, // Hubs add-on\n x_MonetaryCommitment: decimal, // MS CM EA 2023-05-01\n x_Overage: decimal, // MS CM EA 2023-05-01\n x_PurchasingBillingAccountId: string, // MS CM EA 2023-05-01\n x_SkuOrderId: string, // MS CM EA+MCA 2023-05-01\n x_SkuOrderName: string, // MS CM EA+MCA 2023-05-01\n x_SkuSize: string, // MS CM EA+MCA 2023-05-01\n x_SkuTerm: int, // MS CM EA+MCA 2023-05-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubscriptionId: string, // MS CM EA+MCA 2023-05-01\n x_TransactionType: string // MS CM EA+MCA 2023-05-01\n)\n\n// Update policy for Transactions_raw -> Transactions_final_v1_0 table\n.alter table Transactions_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Transactions_raw\",\n \"Query\": \"Transactions_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n", + "$fxv#9": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n//======================================================================================================================\n// Ingestion database\n// Used for data ingestion, normalization, and cleansing.\n// See known issues @ https://github.com/microsoft/finops-toolkit/issues/1111\n//======================================================================================================================\n\n// For allowed commands, see https://learn.microsoft.com/azure/data-explorer/database-script\n\n//===| Prices |=========================================================================================================\n// Supported versions:\n// - MS EA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-ea\n// - MS MCA 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/price-sheet-mca\n//======================================================================================================================\n\n// Prices_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All prices transformed to FOCUS 1.0. Use Prices_transform_v1_2() instead.', folder='Prices')\nPrices_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n let prices = materialize(\n Prices_raw\n //\n // Change real to decimal\n | extend\n BasePrice = todecimal(BasePrice),\n IncludedQuantity = todecimal(IncludedQuantity),\n MarketPrice = todecimal(MarketPrice),\n TierMinimumUnits = todecimal(TierMinimumUnits),\n UnitPrice = todecimal(UnitPrice)\n //\n | extend x_SkuId = coalesce(SkuId, SkuID)\n | extend x_SkuMeterId = coalesce(MeterId, MeterID)\n | extend x_SkuProductId = coalesce(ProductId, ProductID)\n | extend x_SkuTerm = isoMonths(Term)\n | project-rename\n x_BaseUnitPrice = BasePrice,\n x_EffectivePeriodEnd = EffectiveEndDate,\n x_EffectivePeriodStart = EffectiveStartDate,\n x_PricingUnitDescription = UnitOfMeasure,\n x_SkuIncludedQuantity = IncludedQuantity,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuMeterType = MeterType,\n x_SkuOfferId = OfferID,\n x_SkuPartNumber = PartNumber,\n x_SkuPriceType = PriceType,\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTier = TierMinimumUnits\n | extend ContractedUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', UnitPrice, todecimal('')) // UnitPrice for savings plan is not the on-demand unit price\n | extend ListUnitPrice = iff(x_SkuPriceType != 'SavingsPlan', MarketPrice, todecimal('')) // MarketPrice for savings plan is not the list price\n | extend ChargeCategory = case(\n x_SkuPriceType == 'Consumption', 'Usage',\n x_SkuPriceType == 'ReservedInstance', 'Purchase',\n x_SkuPriceType == 'SavingsPlan', 'Usage', // Savings plan prices are for committed usage, not the purchase\n ''\n )\n | extend SkuPriceIdv2 = strcat(case(x_SkuPriceType == 'Consumption', 'OD', x_SkuPriceType == 'ReservedInstance', 'RI', x_SkuPriceType == 'SavingsPlan', 'SP', 'XX'), substring(ChargeCategory, 0, 1), x_SkuTerm, '_', x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType, '_', x_SkuTier, x_SkuOfferId)\n | extend x_BillingAccountId = iff(BillingAccountId startswith '/', split(BillingAccountId, '/')[-1], coalesce(BillingAccountId, EnrollmentNumber))\n | extend x_BillingProfileId = iff(BillingProfileId startswith '/', split(BillingProfileId, '/')[-1], coalesce(BillingProfileId, EnrollmentNumber))\n | extend tmp_SavingsPlanKey = strcat(x_SkuMeterId, x_SkuProductId, x_SkuId, x_SkuTier, x_SkuOfferId)\n //\n // Get latest ingested row based on the unique ID\n | extend x_IngestionTime = ingestion_time()\n );\n //\n // Meters for reservations and savings plans to identify commitment eligibility\n let riMeters = prices | where x_SkuPriceType == 'ReservedInstance' | distinct x_SkuMeterId;\n let spMeters = prices | where x_SkuPriceType == 'SavingsPlan' | distinct x_SkuMeterId;\n //\n // Copy list/base/contracted prices from on-demand SKUs\n prices\n | where x_SkuPriceType == 'SavingsPlan'\n // If we use join, specify the shuffle key\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter hint.strategy=shuffle (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | lookup kind=leftouter (prices | where x_SkuPriceType == 'Consumption' | where x_SkuMeterId in (spMeters) | distinct tmp_SavingsPlanKey, ListUnitPrice, ContractedUnitPrice, x_BaseUnitPrice) on tmp_SavingsPlanKey\n | extend ListUnitPrice = coalesce(ListUnitPrice, ListUnitPrice1)\n | extend ContractedUnitPrice = coalesce(ContractedUnitPrice, ContractedUnitPrice1)\n | extend x_BaseUnitPrice = coalesce(x_BaseUnitPrice, x_BaseUnitPrice1)\n | project-away ListUnitPrice1, ContractedUnitPrice1, x_BaseUnitPrice1, tmp_SavingsPlanKey\n | union ((prices | where x_SkuPriceType != 'SavingsPlan'))\n //\n // Calculate commitment discount elgibility\n // TODO: Would a join be faster?\n | extend x_CommitmentDiscountSpendEligibility = iff(x_SkuMeterId in (riMeters) and x_SkuPriceType != 'ReservedInstance', 'Eligible', 'Not Eligible')\n | extend x_CommitmentDiscountUsageEligibility = iff(x_SkuMeterId in (spMeters), 'Eligible', 'Not Eligible')\n //\n // Add PricingUnit and x_PricingBlockSize\n // TODO: Compare join vs. lookup perf -- | join kind=leftouter (PricingUnits) on x_PricingUnitDescription | project-away x_PricingUnitDescription1\n | lookup kind=leftouter (PricingUnits | extend x_PricingBlockSize = todecimal(x_PricingBlockSize)) on x_PricingUnitDescription\n //\n | extend x_EffectiveUnitPrice = iff(x_SkuPriceType == 'SavingsPlan', UnitPrice, todecimal('')) // Savings plan prices are for the effective price, not the contracted price\n | extend x_EffectiveUnitPriceDiscount = ContractedUnitPrice - x_EffectiveUnitPrice\n | extend x_ContractedUnitPriceDiscount = ListUnitPrice - ContractedUnitPrice\n | extend x_TotalUnitPriceDiscount = ListUnitPrice - x_EffectiveUnitPrice\n | project\n BillingAccountId = tolower(case(\n BillingProfileId startswith '/', BillingProfileId,\n BillingAccountId startswith '/', BillingAccountId,\n strcat('/providers/microsoft.billing/billingaccounts/', x_BillingAccountId, iff(x_BillingProfileId == x_BillingAccountId, '', strcat('/billingprofiles/', x_BillingProfileId)))\n )),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName, x_BillingProfileId),\n BillingCurrency = coalesce(BillingCurrency, CurrencyCode, Currency), // Currency last as a fallback only\n ChargeCategory,\n CommitmentDiscountCategory = case(\n x_SkuPriceType == 'ReservedInstance', 'Usage',\n x_SkuPriceType == 'SavingsPlan', 'Spend',\n ''\n ),\n CommitmentDiscountType = case(\n x_SkuPriceType == 'ReservedInstance', 'Reservation',\n x_SkuPriceType == 'SavingsPlan', 'Savings plan',\n ''\n ),\n ContractedUnitPrice,\n ListUnitPrice,\n PricingCategory = case(\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed',\n ''\n ),\n PricingUnit,\n SkuId = coalesce(ProductId, ProductID),\n SkuPriceId = strcat(x_SkuProductId, '_', x_SkuId, '_', x_SkuMeterType),\n SkuPriceIdv2,\n x_BaseUnitPrice,\n x_BillingAccountAgreement = case(\n strlen(x_BillingAccountId) > 32, 'MCA',\n strlen(x_BillingAccountId) < 32, 'EA',\n 'Unknown'\n ),\n x_BillingAccountId,\n x_BillingProfileId,\n x_CommitmentDiscountSpendEligibility,\n x_CommitmentDiscountUsageEligibility,\n x_ContractedUnitPriceDiscount,\n x_ContractedUnitPriceDiscountPercent = 1.0 * x_ContractedUnitPriceDiscount / ListUnitPrice * 100,\n x_EffectivePeriodEnd = startofmonth(x_EffectivePeriodEnd + 1h),\n x_EffectivePeriodStart,\n x_EffectiveUnitPrice,\n x_EffectiveUnitPriceDiscount,\n x_EffectiveUnitPriceDiscountPercent = 1.0 * x_EffectiveUnitPriceDiscount / ContractedUnitPrice * 100,\n x_IngestionTime,\n x_PricingBlockSize,\n x_PricingCurrency = coalesce(Currency, CurrencyCode), // CurrencyCode last as a fallback only\n x_PricingSubcategory = case(\n x_SkuPriceType == 'Consumption' and (x_SkuIncludedQuantity > 0 or x_SkuTier > 0), 'Tiered',\n x_SkuPriceType == 'Consumption', 'Standard',\n x_SkuPriceType == 'ReservedInstance', 'Standard', // Reservation purchases are tracked as \"Standard\"\n x_SkuPriceType == 'SavingsPlan', 'Committed Spend',\n ''\n ),\n x_PricingUnitDescription,\n x_SkuDescription = Product,\n x_SkuId,\n x_SkuIncludedQuantity,\n x_SkuMeterCategory,\n x_SkuMeterId,\n x_SkuMeterName,\n x_SkuMeterSubcategory,\n x_SkuMeterType,\n x_SkuPriceType,\n x_SkuProductId,\n x_SkuRegion,\n x_SkuServiceFamily,\n x_SkuOfferId,\n x_SkuPartNumber,\n x_SkuTerm,\n x_SkuTier,\n x_SourceName = coalesce(x_SourceName, 'Cost Management'),\n x_SourceProvider = coalesce(x_SourceProvider, 'Microsoft'),\n x_SourceType = coalesce(x_SourceType, 'PriceSheet'),\n x_SourceVersion = coalesce(x_SourceVersion, '2023-05-01'),\n x_TotalUnitPriceDiscount,\n x_TotalUnitPriceDiscountPercent = 1.0 * x_TotalUnitPriceDiscount / ListUnitPrice * 100\n}\n\n// Prices_final_v1_0 table\n.create-merge table Prices_final_v1_0 (\n BillingAccountId: string,\n BillingAccountName: string,\n BillingCurrency: string,\n ChargeCategory: string,\n CommitmentDiscountCategory: string,\n CommitmentDiscountType: string,\n ContractedUnitPrice: decimal,\n ListUnitPrice: decimal,\n PricingCategory: string,\n PricingUnit: string,\n SkuId: string,\n SkuPriceId: string,\n SkuPriceIdv2: string, // Hubs add-on\n x_BaseUnitPrice: decimal, // Azure\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure MCA\n x_BillingProfileId: string, // Azure MCA\n x_CommitmentDiscountSpendEligibility: string, // Hubs add-on\n x_CommitmentDiscountUsageEligibility: string, // Hubs add-on\n x_ContractedUnitPriceDiscount: decimal, // Hubs add-on\n x_ContractedUnitPriceDiscountPercent: decimal, // Hubs add-on\n x_EffectivePeriodEnd: datetime, // Azure\n x_EffectivePeriodStart: datetime, // Azure\n x_EffectiveUnitPrice: decimal, // Azure\n x_EffectiveUnitPriceDiscount: decimal, // Hubs add-on\n x_EffectiveUnitPriceDiscountPercent: decimal, // Hubs add-on\n x_IngestionTime: datetime, // Hubs add-on\n x_PricingBlockSize: decimal, // Hubs add-on\n x_PricingCurrency: string, // Azure\n x_PricingSubcategory: string, // Hubs add-on\n x_PricingUnitDescription: string, // Azure\n x_SkuDescription: string, // Azure\n x_SkuId: string, // Azure\n x_SkuIncludedQuantity: decimal, // Azure EA\n x_SkuMeterCategory: string, // Azure\n x_SkuMeterId: string, // Azure\n x_SkuMeterName: string, // Azure\n x_SkuMeterSubcategory: string, // Azure\n x_SkuMeterType: string, // Azure\n x_SkuPriceType: string, // Azure\n x_SkuProductId: string, // Azure\n x_SkuRegion: string, // Azure\n x_SkuServiceFamily: string, // Azure\n x_SkuOfferId: string, // Azure EA\n x_SkuPartNumber: string, // Azure EA\n x_SkuTerm: int, // Azure\n x_SkuTier: decimal, // Azure MCA\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_TotalUnitPriceDiscount: decimal, // Hubs add-on\n x_TotalUnitPriceDiscountPercent: decimal // Hubs add-on\n)\n\n// Update policy for Prices_raw -> Prices_final_v1_0\n.alter table Prices_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Prices_raw\",\n \"Query\": \"Prices_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Cost and usage |=================================================================================================\n// Supported versions:\n// - MS: 1.0, 1.0-preview(v1) -- See https://aka.ms/costmgmt/exports/focus\n// - AWS: 1.0 -- See https://docs.aws.amazon.com/cur/latest/userguide/table-dictionary-focus-1-0-aws-columns.html\n// - GCP: Jan-Jun 2024 -- See https://cloud.google.com/resources/google-cloud-focus?e=48754805&hl=en\n// Links to (Aug 2024): https://services.google.com/fh/files/misc/focus_guide_v1.pdf\n// See also:\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/standard-usage\n// - https://cloud.google.com/billing/docs/how-to/export-data-bigquery-tables/detailed-usage\n// - OCI: 1.0 -- See https://docs.oracle.com/iaas/Content/Billing/Concepts/costusagereportsoverview.htm#costreports__focus-cost-report-schema\n//\n// Support for non-Azure data is limited to ingestion only. Data is not transformed across versions.\n//======================================================================================================================\n\n// Costs_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All costs transformed to FOCUS 1.0. Use Costs_transform_v1_2() instead.', folder='Costs')\nCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n Costs_raw\n //\n // Change real to decimal\n | extend\n BilledCost = todecimal(BilledCost),\n CommitmentDiscountQuantity = todecimal(CommitmentDiscountQuantity),\n ConsumedQuantity = todecimal(ConsumedQuantity),\n ContractedCost = todecimal(ContractedCost),\n ContractedUnitPrice = todecimal(ContractedUnitPrice),\n EffectiveCost = todecimal(EffectiveCost),\n ListCost = todecimal(ListCost),\n ListUnitPrice = todecimal(ListUnitPrice),\n PricingQuantity = todecimal(PricingQuantity),\n UsageAmount = todecimal(UsageAmount),\n UsageQuantity = todecimal(UsageQuantity),\n x_BilledCostInUsd = todecimal(x_BilledCostInUsd),\n x_BilledUnitPrice = todecimal(x_BilledUnitPrice),\n x_BillingExchangeRate = todecimal(x_BillingExchangeRate),\n x_ContractedCostInUsd = todecimal(x_ContractedCostInUsd),\n x_Cost = todecimal(x_Cost),\n x_CurrencyConversionRate = todecimal(x_CurrencyConversionRate),\n x_EffectiveCostInUsd = todecimal(x_EffectiveCostInUsd),\n x_EffectiveUnitPrice = todecimal(x_EffectiveUnitPrice),\n x_ListCostInUsd = todecimal(x_ListCostInUsd),\n x_OnDemandCost = todecimal(x_OnDemandCost),\n x_OnDemandCostInUsd = todecimal(x_OnDemandCostInUsd),\n x_OnDemandUnitPrice = todecimal(x_OnDemandUnitPrice),\n x_PricingBlockSize = todecimal(x_PricingBlockSize)\n //\n // Dedupe rows\n | extend x_IngestionTime = ingestion_time()\n | extend x_ChargeId = ''\n // TODO: Consider adding a unique charge ID per row\n // hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // // 1. Resource hierarchy (including resource name), highest to lowest\n // BillingAccountId,\n // x_InvoiceSectionId,\n // x_AccountOwnerId,\n // SubAccountId,\n // x_ResourceGroupName,\n // ResourceName,\n // // 2. Resource details\n // ResourceId,\n // RegionId,\n // Tags,\n // CommitmentDiscountId,\n // x_CostCenter,\n // // 4. Meter details\n // SkuPriceId,\n // x_SkuMeterId,\n // x_SkuPartNumber,\n // x_SkuOfferId,\n // x_SkuDetails,\n // // 5. Date\n // ChargePeriodStart\n // ))\n //\n // Identify data quality issues\n | extend x_SourceChanges = trim_end(',', strcat(\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based', 'InvalidChargeFrequency,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and EffectiveCost > 0, 'InvalidEffectiveCost,', ''),\n iff((isempty(ContractedCost) or ContractedCost == 0) and EffectiveCost != 0, 'MissingContractedCost,', ''),\n iff((isempty(ContractedUnitPrice) or ContractedUnitPrice == 0) and x_EffectiveUnitPrice != 0, 'MissingContractedUnitPrice,', ''),\n iff(ListCost < ContractedCost, 'ListCostLessThanContractedCost,', ''),\n iff(ContractedCost < EffectiveCost, 'ContractedCostLessThanEffectiveCost,', ''),\n iff((isempty(ListCost) or ListCost == 0) and (ContractedCost != 0 or EffectiveCost != 0), 'MissingListCost,', ''),\n iff((isempty(ListUnitPrice) or ListUnitPrice == 0) and (ContractedUnitPrice != 0 or x_EffectiveUnitPrice != 0), 'MissingListUnitPrice,', ''),\n iff((isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001)\n or (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001),\n 'XEffectiveUnitPriceRoundingError,', ''),\n iff(ConsumedQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingConsumedQuantity,', ''),\n iff(PricingQuantity == 0 and (EffectiveCost != 0 or BilledCost != 0), 'MissingPricingQuantity,', ''),\n iff(isempty(ProviderName), 'MissingProviderName,', ''),\n iff(isempty(PublisherName), 'MissingPublisherName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceId), 'MissingResourceId,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceName), 'MissingResourceName,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(ResourceType), 'MissingResourceType,', ''),\n iff(BilledCost > 0 and x_BilledUnitPrice == 0, 'MissingXBilledUnitPrice,', ''),\n iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and isempty(x_ResourceType), 'MissingXResourceType,', ''),\n iff(PricingCategory == 'Standard' and isnotempty(CommitmentDiscountId) and ChargeCategory == 'Usage', 'PricingCategoryShouldBeCommitted,', ''),\n iff(x_SkuTerm == '1Year' or x_SkuTerm == '3Years' or x_SkuTerm == '5Years', 'SkuTermShouldBeAnInteger,', '')\n ))\n //\n // Fix columns needed in other changes\n | extend ProviderName = case(\n isnotempty(ProviderName), ProviderName,\n isnotempty(coalesce(x_CostCategories, x_Discount, x_Operation, x_ServiceCode, x_UsageType)), 'AWS',\n isnotempty(coalesce(tostring(UsageAmount), tostring(x_Cost), x_Credits, x_CostType, tostring(x_CurrencyConversionRate), tostring(x_ExportTime), x_Project, x_ServiceId)), 'GCP',\n isnotempty(coalesce(x_BillingProfileId, x_InvoiceSectionId)), 'Microsoft',\n ''\n )\n //\n // Identify source\n | extend x_SourceName = coalesce(x_SourceName, iff(isnotempty(x_BillingProfileId), 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(isnotempty(x_BillingProfileId), 'FocusCost', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, case(\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)) and isempty(SkuPriceDetails) and isnotempty(x_SkuDetails), '1.2-preview',\n isnotempty(coalesce(InvoiceId, SkuMeter, PricingCurrency)), '1.2',\n isnotempty(coalesce(ChargeClass, CommitmentDiscountStatus, tostring(ConsumedQuantity), ConsumedUnit, tostring(ContractedCost), tostring(ContractedUnitPrice), RegionId, RegionName)), '1.0',\n isnotempty(coalesce(ChargeSubcategory, Region, tostring(UsageQuantity), UsageUnit)), iff(ProviderName == 'Microsoft', '1.0-preview(v1)', '1.0-preview'),\n ''\n ))\n // Append version check error code\n | extend x_SourceChanges = iff(x_SourceVersion == '1.0', x_SourceChanges,\n strcat(x_SourceChanges, iff(isempty(x_SourceChanges), '', ','), iff(x_SourceVersion == '', 'UnknownFocusVersion', 'LegacyFocusVersion'))\n )\n //\n // Fix quantities\n | extend PricingQuantity = case(\n PricingQuantity != 0 or (EffectiveCost == 0 and BilledCost == 0), PricingQuantity,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(BilledCost) and BilledCost != 0 and isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, BilledCost / x_BilledUnitPrice,\n PricingQuantity == 0 and isnotempty(EffectiveCost) and EffectiveCost != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0, EffectiveCost / x_EffectiveUnitPrice,\n PricingQuantity\n )\n | extend ConsumedQuantity = case(\n isnotempty(ConsumedQuantity) and ConsumedQuantity != 0, ConsumedQuantity,\n ChargeCategory == 'Usage', PricingQuantity / coalesce(x_PricingBlockSize, decimal(1)),\n ConsumedQuantity\n )\n //\n // Populate missing prices -- mapping to on-demand prices requires meter ID and offer ID\n | extend tmp_MissingPrices = ProviderName == 'Microsoft'\n and (ListUnitPrice == 0 or ContractedUnitPrice == 0)\n and x_EffectiveUnitPrice != 0\n and not(CommitmentDiscountCategory == 'Spend' and CommitmentDiscountStatus == 'Unused')\n and isnotempty(strcat(x_SkuMeterId, x_SkuOfferId))\n | as allCosts\n | where tmp_MissingPrices\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(ChargePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | as costsWithMissingPrices\n | join kind=leftouter (\n Prices_final_v1_0\n | extend tmp_ReservationPriceLookupKey = tolower(strcat(x_BillingProfileId, substring(x_EffectivePeriodStart, 0, 7), x_SkuMeterId, x_SkuOfferId))\n | where x_SkuPriceType == 'Consumption' and tmp_ReservationPriceLookupKey in ((costsWithMissingPrices | summarize by tmp_ReservationPriceLookupKey))\n | summarize ListUnitPrice = min(ListUnitPrice), ContractedUnitPrice = min(ContractedUnitPrice) by tmp_ReservationPriceLookupKey, x_PricingBlockSize, PricingUnit\n ) on tmp_ReservationPriceLookupKey\n //\n // Select the best price to use for each row\n // TODO: Save values before changing -- | extend x_old_ContractedUnitPrice = ContractedUnitPrice, x_old_EffectiveUnitPrice = x_EffectiveUnitPrice, x_old_ListUnitPrice = ListUnitPrice, x_old_ListCost = ListCost, x_old_ContractedCost = ContractedCost\n | extend x_EffectiveUnitPrice = case(\n // If price is a rounding error away from the billed price, use the billed price\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(x_BilledUnitPrice - x_EffectiveUnitPrice) < 0.0001, x_BilledUnitPrice,\n // If price is a rounding error away from the contracted price, use the contracted price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0 and isnotempty(x_EffectiveUnitPrice) and x_EffectiveUnitPrice != 0 and abs(ContractedUnitPrice - x_EffectiveUnitPrice) < 0.0001, ContractedUnitPrice,\n x_EffectiveUnitPrice\n )\n | extend ContractedUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ContractedUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ContractedUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // If billed price is available, assume the billed price is the same as contracted price to support aggregations\n isnotempty(x_BilledUnitPrice) and x_BilledUnitPrice != 0, x_EffectiveUnitPrice,\n // Otherwise, assume the effective price is the same as contracted price to support aggregations\n x_EffectiveUnitPrice\n )\n | extend ListUnitPrice = case(\n // If price is already correct, keep that\n (isnotempty(ListUnitPrice) and ListUnitPrice != 0) or (EffectiveCost == 0 and BilledCost == 0), ListUnitPrice,\n // If both prices use the same scale, use the new one\n PricingUnit == PricingUnit1 and x_PricingBlockSize == x_PricingBlockSize1, ListUnitPrice1 * x_BillingExchangeRate,\n // If prices are the same unit but not the same scale, use the new one but correct the scale\n PricingUnit == PricingUnit1 and x_PricingBlockSize != x_PricingBlockSize1 and isnotempty(x_PricingBlockSize) and isnotempty(x_PricingBlockSize1), ListUnitPrice1 * x_BillingExchangeRate / x_PricingBlockSize1 * x_PricingBlockSize,\n // Otherwise, assume the contracted price is the same as list price to support aggregations\n ContractedUnitPrice\n )\n // Calculate missing costs based on new prices -- If cost is already correct, keep that; if not and price is available, recalculate the cost; otherwise, keep the existing cost\n | extend ContractedCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ContractedCost) and ContractedCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ContractedCost,\n // ContractedCost is 0 in all other scenarios...\n // If 0 and there's a billed cost and prices are the same, use BilledCost\n isnotempty(BilledCost) and BilledCost != 0 and ContractedUnitPrice == x_BilledUnitPrice, BilledCost,\n // If 0 and there's a billed cost and prices are the same, use EffectiveCost\n isnotempty(EffectiveCost) and EffectiveCost != 0 and ContractedUnitPrice == x_EffectiveUnitPrice, EffectiveCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ContractedUnitPrice) and ContractedUnitPrice != 0, ContractedUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume EffectiveCost\n isempty(ContractedUnitPrice) or ContractedUnitPrice == 0, EffectiveCost,\n // Fall back to the original value for any unhandled scenarios\n ContractedCost\n )\n | extend ListCost = case(\n // If not set or there's no cost, keep the original value\n (isnotempty(ListCost) and ListCost != 0) or (EffectiveCost == 0 and BilledCost == 0), ListCost,\n // ListCost is 0 in all other scenarios...\n // If 0 and there's a contracted cost and prices are the same, use ContractedCost\n isnotempty(ContractedCost) and ContractedCost != 0 and ListUnitPrice == ContractedUnitPrice, ContractedCost,\n // If 0 and there's a price, calculate the cost based on the price\n isnotempty(ListUnitPrice) and ListUnitPrice != 0, ListUnitPrice * PricingQuantity,\n // If 0 and there's no price, assume ContractedCost\n isempty(ListUnitPrice) or ListUnitPrice == 0, ContractedCost,\n // Fall back to the original value for any unhandled scenarios\n ListCost\n )\n // Merge the rest of the unmodified cost records and remove excess columns\n | union (allCosts | where not(tmp_MissingPrices))\n | project-away x_PricingBlockSize1, PricingUnit1, ListUnitPrice1, ContractedUnitPrice1, tmp_MissingPrices, tmp_ReservationPriceLookupKey, tmp_ReservationPriceLookupKey1\n //\n // BUG: Fix ContractedCost that has bad values\n | extend ContractedCost = iff(ProviderName == 'Microsoft' and isnotempty(PricingQuantity) and isnotempty(x_PricingBlockSize) and ContractedCost != ContractedUnitPrice * PricingQuantity, ContractedUnitPrice * PricingQuantity, ContractedCost)\n //\n // Handle FOCUS 1.0-preview UsageQuantity/Unit\n | extend ConsumedQuantity = iff(ChargeCategory == 'Usage', coalesce(ConsumedQuantity, UsageQuantity, UsageAmount), todecimal(''))\n | extend ConsumedUnit = iff(ChargeCategory == 'Usage' and isnotempty(ConsumedQuantity), coalesce(ConsumedUnit, UsageUnit, 'Units'), '')\n //\n // Convert IDs to lowercase for consistency\n | extend CommitmentDiscountId = tolower(CommitmentDiscountId)\n //\n // BUG: Remove EffectiveCost for commitment discount purchases\n | extend EffectiveCost = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), decimal(0), EffectiveCost)\n | extend x_EffectiveCostInUsd = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), decimal(0), x_EffectiveCostInUsd)\n //\n // Clean up resource columns\n | extend ResourceId = case(\n isnotempty(ResourceId), ResourceId,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId), CommitmentDiscountId,\n ResourceId)\n | extend ResourceName = tolower(case(\n isnotempty(ResourceName), ResourceName,\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountName), CommitmentDiscountName,\n isnotempty(ResourceId), parse_resourceid(ResourceId).ResourceName,\n ResourceName))\n | extend x_ResourceType = case(\n isnotempty(x_ResourceType), x_ResourceType,\n isnotempty(ResourceId), parse_resourceid(ResourceId).x_ResourceType,\n x_ResourceType)\n | extend ResourceType = case(\n // Use existing resource type display name unless it's an internal resource type ID\n isnotempty(ResourceType) and tolower(ResourceType) != tolower(x_ResourceType) and ResourceType !contains '/', ResourceType,\n // Use CommitmentDiscountType for commitment discount purchases\n ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountType), CommitmentDiscountType,\n // Look up display name from internal type\n isnotempty(x_ResourceType), coalesce(resource_type(x_ResourceType).SingularDisplayName, ResourceType, x_ResourceType),\n ResourceType)\n //\n // Sort columns and apply final transforms\n | project\n AvailabilityZone,\n BilledCost,\n BillingAccountId = tolower(BillingAccountId),\n BillingAccountName,\n BillingAccountType,\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEnd),\n BillingPeriodStart = startofmonth(BillingPeriodStart),\n ChargeCategory = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Credit', 'Credit',\n ChargeSubcategory == 'Refund', 'Purchase', // We are assuming purchase refunds since we don't have data to indicate usage refunds\n ChargeCategory\n ),\n ChargeClass = case(ChargeSubcategory == 'Refund', 'Correction', ChargeClass),\n ChargeDescription,\n // BUG: ChargeFrequency shows \"Usage-Based\" for monthly recurring savings plan purchases\n ChargeFrequency = iff(ChargeCategory == 'Purchase' and isnotempty(CommitmentDiscountId) and ChargeFrequency == 'Usage-Based' and ProviderName == 'Microsoft' and x_SourceVersion startswith '1.0', 'Recurring', ChargeFrequency),\n ChargePeriodEnd,\n ChargePeriodStart,\n CommitmentDiscountCategory,\n CommitmentDiscountId = tolower(CommitmentDiscountId),\n CommitmentDiscountName,\n CommitmentDiscountStatus = case(\n // Handle FOCUS 1.0-preview ChargeSubcategory\n ChargeSubcategory == 'Used Commitment', 'Used',\n ChargeSubcategory == 'Unused Commitment', 'Unused',\n CommitmentDiscountStatus\n ),\n CommitmentDiscountType,\n ConsumedQuantity,\n ConsumedUnit,\n ContractedCost = coalesce(ContractedCost, x_OnDemandCost, x_Cost),\n ContractedUnitPrice = coalesce(ContractedUnitPrice, x_OnDemandUnitPrice),\n EffectiveCost,\n InvoiceIssuerName,\n ListCost,\n ListUnitPrice,\n PricingCategory = case(\n // Handle FOCUS 1.0-preview PricingCategory values\n PricingCategory == 'On-Demand', 'Standard',\n PricingCategory == 'Commitment-Based', 'Committed',\n PricingCategory\n ),\n PricingQuantity,\n PricingUnit,\n ProviderName,\n // Handle missing PublisherName values\n PublisherName = case(PublisherName == 'Microsoft Corporation', 'Microsoft', isnotempty(PublisherName), PublisherName, x_PublisherCategory == 'Cloud Provider', ProviderName, ''),\n // Handle FOCUS 1.0-preview Region column\n RegionId = coalesce(RegionId, iff(ProviderName == 'Microsoft', replace_string(tolower(Region), ' ', ''), Region)),\n RegionName = coalesce(RegionName, Region),\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SkuId,\n SkuPriceId,\n SubAccountId,\n SubAccountName,\n SubAccountType, // Azure 1.0-preview(v1)+\n Tags = parse_json(Tags),\n x_AccountId, // Azure 1.0-preview(v1)+\n x_AccountName, // Azure 1.0-preview(v1)+\n x_AccountOwnerId, // Azure 1.0-preview(v1)+\n x_BilledCostInUsd, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement = case(\n ProviderName == 'Microsoft' and x_BillingAccountId == x_BillingProfileId, 'EA',\n ProviderName == 'Microsoft' and x_BillingAccountId != x_BillingProfileId, 'MCA',\n ProviderName\n ), // Hubs add-on\n x_BillingAccountId, // Azure 1.0-preview(v1)+\n x_BillingAccountName, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate, // Azure 1.0-preview(v1)+\n x_BillingProfileId, // Azure 1.0-preview(v1)+\n x_BillingProfileName, // Azure 1.0-preview(v1)+\n x_ChargeId, // Azure 1.0-preview(v1) only\n x_ContractedCostInUsd = coalesce(x_ContractedCostInUsd, x_OnDemandCostInUsd), // Azure 1.0+\n x_CostAllocationRuleName, // Azure 1.0-preview(v1)+\n x_CostCategories = parse_json(x_CostCategories), // AWS 1.0 (JSON)\n x_CostCenter, // Azure 1.0-preview(v1)+\n x_Credits = parse_json(x_Credits), // GCP Jan 2024\n x_CostType, // GCP Jan 2024\n x_CurrencyConversionRate, // GCP Jun 2024\n x_CustomerId, // Azure 1.0-preview(v1)+\n x_CustomerName, // Azure 1.0-preview(v1)+\n x_Discount = parse_json(x_Discount), // AWS 1.0 (JSON)\n x_EffectiveCostInUsd, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice, // Azure 1.0-preview(v1)+\n x_ExportTime, // GCP Jan 2024\n x_IngestionTime, // Hubs add-on\n x_InvoiceId = coalesce(InvoiceId, x_InvoiceId), // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId = case( // Azure 1.0-preview(v1)+\n x_InvoiceSectionId == '-2', '',\n x_InvoiceSectionId\n ),\n x_InvoiceSectionName = case( // Azure 1.0-preview(v1)+\n x_InvoiceSectionName == 'Unassigned', '',\n x_InvoiceSectionName\n ),\n x_ListCostInUsd, // Azure 1.0-preview(v1)+\n x_Location, // GCP Jan 2024\n x_Operation, // AWS 1.0\n x_PartnerCreditApplied, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate, // Azure 1.0-preview(v1)+\n x_PricingBlockSize, // Azure 1.0-preview(v1)+\n x_PricingCurrency = coalesce(PricingCurrency, x_PricingCurrency), // Azure 1.0-preview(v1)+\n x_PricingSubcategory, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription, // Azure 1.0-preview(v1)+\n x_Project, // GCP Jan 2024\n x_PublisherCategory, // Azure 1.0-preview(v1)+\n x_PublisherId, // Azure 1.0-preview(v1)+\n x_ResellerId, // Azure 1.0-preview(v1)+\n x_ResellerName, // Azure 1.0-preview(v1)+\n x_ResourceGroupName = tolower(x_ResourceGroupName), // Azure 1.0-preview(v1)+\n x_ResourceType, // Azure 1.0-preview(v1)+\n x_ServiceCode, // AWS 1.0\n x_ServiceId, // GCP Jan 2024\n x_ServicePeriodEnd, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart, // Azure 1.0-preview(v1)+\n x_SkuDescription, // Azure 1.0-preview(v1)+\n x_SkuDetails = parse_json(x_SkuDetails), // Azure 1.0-preview(v1)+\n x_SkuIsCreditEligible, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory, // Azure 1.0-preview(v1)+\n x_SkuMeterId, // Azure 1.0-preview(v1)+\n x_SkuMeterName = coalesce(SkuMeter, x_SkuMeterName), // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory, // Azure 1.0-preview(v1)+\n x_SkuOfferId, // Azure 1.0-preview(v1)+\n x_SkuOrderId, // Azure 1.0-preview(v1)+\n x_SkuOrderName, // Azure 1.0-preview(v1)+\n x_SkuPartNumber, // Azure 1.0-preview(v1)+\n x_SkuRegion, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily, // Azure 1.0-preview(v1)+\n x_SkuTerm, // Azure 1.0-preview(v1)+\n x_SkuTier, // Azure 1.0-preview(v1)+\n x_SourceChanges, // Hubs add-on\n x_SourceName, // Hubs add-on\n x_SourceProvider, // Hubs add-on\n x_SourceType, // Hubs add-on\n x_SourceVersion, // Hubs add-on\n x_UsageType // AWS 1.0\n}\n\n// Costs_final_v1_0 table\n.create-merge table Costs_final_v1_0 (\n AvailabilityZone: string,\n BilledCost: decimal,\n BillingAccountId: string,\n BillingAccountName: string,\n BillingAccountType: string, // Azure 1.0-preview(v1)+\n BillingCurrency: string,\n BillingPeriodEnd: datetime,\n BillingPeriodStart: datetime,\n ChargeCategory: string,\n ChargeClass: string,\n ChargeDescription: string,\n ChargeFrequency: string,\n ChargePeriodEnd: datetime,\n ChargePeriodStart: datetime,\n CommitmentDiscountCategory: string, // FOCUS 1.0-preview only\n CommitmentDiscountId: string,\n CommitmentDiscountName: string,\n CommitmentDiscountStatus: string,\n CommitmentDiscountType: string,\n ConsumedQuantity: decimal,\n ConsumedUnit: string,\n ContractedCost: decimal,\n ContractedUnitPrice: decimal,\n EffectiveCost: decimal,\n InvoiceIssuerName: string,\n ListCost: decimal,\n ListUnitPrice: decimal,\n PricingCategory: string,\n PricingQuantity: decimal,\n PricingUnit: string,\n ProviderName: string,\n PublisherName: string,\n RegionId: string,\n RegionName: string,\n ResourceId: string,\n ResourceName: string,\n ResourceType: string,\n ServiceCategory: string,\n ServiceName: string,\n SkuId: string,\n SkuPriceId: string,\n SubAccountId: string,\n SubAccountName: string,\n SubAccountType: string,\n Tags: dynamic,\n x_AccountId: string, // Azure 1.0-preview(v1)+\n x_AccountName: string, // Azure 1.0-preview(v1)+\n x_AccountOwnerId: string, // Azure 1.0-preview(v1)+\n x_BilledCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_BilledUnitPrice: decimal, // Azure 1.0-preview(v1)+\n x_BillingAccountAgreement: string, // Hubs add-on\n x_BillingAccountId: string, // Azure 1.0-preview(v1)+\n x_BillingAccountName: string, // Azure 1.0-preview(v1)+\n x_BillingExchangeRate: decimal, // Azure 1.0-preview(v1)+\n x_BillingExchangeRateDate: datetime, // Azure 1.0-preview(v1)+\n x_BillingProfileId: string, // Azure 1.0-preview(v1)+\n x_BillingProfileName: string, // Azure 1.0-preview(v1)+\n x_ChargeId: string, // Azure 1.0-preview(v1) only\n x_ContractedCostInUsd: decimal, // Azure 1.0+\n x_CostAllocationRuleName: string, // Azure 1.0-preview(v1)+\n x_CostCategories: dynamic, // AWS 1.0 (JSON)\n x_CostCenter: string, // Azure 1.0-preview(v1)+\n x_Credits: dynamic, // GCP Jan 2024\n x_CostType: string, // GCP Jan 2024\n x_CurrencyConversionRate: decimal, // GCP Jun 2024\n x_CustomerId: string, // Azure 1.0-preview(v1)+\n x_CustomerName: string, // Azure 1.0-preview(v1)+\n x_Discount: dynamic, // AWS 1.0 (JSON)\n x_EffectiveCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_EffectiveUnitPrice: decimal, // Azure 1.0-preview(v1)+\n x_ExportTime: datetime, // GCP Jan 2024\n x_IngestionTime: datetime, // Hubs add-on\n x_InvoiceId: string, // Azure 1.0-preview(v1)+\n x_InvoiceIssuerId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionId: string, // Azure 1.0-preview(v1)+\n x_InvoiceSectionName: string, // Azure 1.0-preview(v1)+\n x_ListCostInUsd: decimal, // Azure 1.0-preview(v1)+\n x_Location: string, // GCP Jan 2024\n x_Operation: string, // AWS 1.0\n x_PartnerCreditApplied: string, // Azure 1.0-preview(v1)+\n x_PartnerCreditRate: string, // Azure 1.0-preview(v1)+\n x_PricingBlockSize: decimal, // Azure 1.0-preview(v1)+\n x_PricingCurrency: string, // Azure 1.0-preview(v1)+\n x_PricingSubcategory: string, // Azure 1.0-preview(v1)+\n x_PricingUnitDescription: string, // Azure 1.0-preview(v1)+\n x_Project: string, // GCP Jan 2024\n x_PublisherCategory: string, // Azure 1.0-preview(v1)+\n x_PublisherId: string, // Azure 1.0-preview(v1)+\n x_ResellerId: string, // Azure 1.0-preview(v1)+\n x_ResellerName: string, // Azure 1.0-preview(v1)+\n x_ResourceGroupName: string, // Azure 1.0-preview(v1)+\n x_ResourceType: string, // Azure 1.0-preview(v1)+\n x_ServiceCode: string, // AWS 1.0\n x_ServiceId: string, // GCP Jan 2024\n x_ServicePeriodEnd: datetime, // Azure 1.0-preview(v1)+\n x_ServicePeriodStart: datetime, // Azure 1.0-preview(v1)+\n x_SkuDescription: string, // Azure 1.0-preview(v1)+\n x_SkuDetails: dynamic, // Azure 1.0-preview(v1)+\n x_SkuIsCreditEligible: bool, // Azure 1.0-preview(v1)+\n x_SkuMeterCategory: string, // Azure 1.0-preview(v1)+\n x_SkuMeterId: string, // Azure 1.0-preview(v1)+\n x_SkuMeterName: string, // Azure 1.0-preview(v1)+\n x_SkuMeterSubcategory: string, // Azure 1.0-preview(v1)+\n x_SkuOfferId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderId: string, // Azure 1.0-preview(v1)+\n x_SkuOrderName: string, // Azure 1.0-preview(v1)+\n x_SkuPartNumber: string, // Azure 1.0-preview(v1)+\n x_SkuRegion: string, // Azure 1.0-preview(v1)+\n x_SkuServiceFamily: string, // Azure 1.0-preview(v1)+\n x_SkuTerm: int, // Azure 1.0-preview(v1)+\n x_SkuTier: string, // Azure 1.0-preview(v1)+\n x_SourceChanges: string, // Hubs add-on\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_UsageType: string // AWS 1.0\n)\n\n// Update policy for Costs_raw -> Costs_final_v1_0 table\n.alter table Costs_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Costs_raw\",\n \"Query\": \"Costs_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Actual costs |===================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// ActualCosts_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: ActualCost exports transformed to FOCUS 1.0. Use ActualCosts_transform_v1_2() instead.', folder='Costs')\nActualCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n // TODO: Transform actual costs to FOCUS 1.0 format\n ActualCosts_raw\n | where ChargeType in ('Purchase', 'Refund') and isnotempty(ReservationId)\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: ServiceSubcategory, PublisherName, x_PublisherCategory, x_Environment, x_ServiceModel\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodStart = Date,\n ChargePeriodEnd = Date + 1d,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = '',\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory = '',\n SkuId = '',\n SkuMeter = '',\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = SubscriptionName,\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentName = '',\n x_ComponentType = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel = '',\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for ActualCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": false,\n \"Source\": \"ActualCosts_raw\",\n \"Query\": \"ActualCosts_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Amortized costs |================================================================================================\n// Supported versions:\n// - C360-2025-04\n//======================================================================================================================\n\n// AmortizedCosts_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: ActualCost exports transformed to FOCUS 1.0. Use AmortizedCosts_transform_v1_2() instead.', folder='Costs')\nAmortizedCosts_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n // TODO: Transform actual costs to FOCUS 1.0 format\n AmortizedCosts_raw\n //\n //\n // !!! The rest of the query is reused for both the ActualCosts and AmortizedCosts queries -- Copy all changes in both transform functions !!!\n //\n //\n | extend x_AmortizationClass = case(\n ChargeType in ('Purchase', 'Refund') and (tolower(ResourceId) contains '/microsoft.capacity/reservationorders/' or tolower(ResourceId) contains '/microsoft.billingbenefits/savingsplanorders/'), 'Principal',\n ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', 'Amortized Charge',\n ''\n )\n | extend tmp_ResourceInfo = parse_resourceid(ResourceId)\n // TODO: PricingCategory needs to include savings plan usage and spot usage\n | extend PricingCategory = case(\n x_AmortizationClass == 'Amortized Charge', 'Committed',\n ChargeType in ('Usage', 'Purchase'), 'Standard',\n ''\n )\n | extend x_ResourceType = tostring(tmp_ResourceInfo.x_ResourceType)\n | project-rename\n PricingQuantity = Quantity,\n x_PricingUnitDescription = UnitOfMeasure\n | join kind=leftouter (PricingUnits) on x_PricingUnitDescription\n | join kind=leftouter (Regions) on ResourceLocation\n | join kind=leftouter (ResourceTypes | project x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n // TODO: Add the following in 1.2: ServiceSubcategory, PublisherName, x_PublisherCategory, x_Environment, x_ServiceModel\n | join kind=leftouter (Services | where isnotempty(x_ResourceType) | project x_ResourceType, ServiceName, ServiceCategory) on x_ResourceType\n | join kind=leftouter (Services | where isnotempty(x_ConsumedService) | summarize take_any(ServiceName), take_any(ServiceCategory) by ConsumedService = x_ConsumedService) on ConsumedService\n | extend CommitmentDiscountCategory = iff(isnotempty(ReservationId), 'Usage', '') // TODO: CommitmentDiscountCategory needs to handle savings plans\n | project\n AvailabilityZone = AvailabilityZone,\n BilledCost = iff(x_AmortizationClass == 'Amortized Charge', real(0), Cost),\n BillingAccountId = strcat('/providers/microsoft.billing/billingaccounts/', BillingAccountId, iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), '', strcat('/billingprofiles/', BillingProfileId))),\n BillingAccountName = coalesce(BillingProfileName, BillingAccountName),\n BillingAccountType = iff(BillingAccountId == BillingProfileId or isempty(BillingProfileId), 'Billing Profile', 'Billing Account'),\n BillingCurrency,\n BillingPeriodEnd = startofmonth(BillingPeriodEndDate, 1),\n BillingPeriodStart = startofmonth(BillingPeriodStartDate),\n CapacityReservationId = '',\n CapacityReservationStatus = '',\n ChargeCategory = case(\n ChargeType in ('Usage', 'Purchase', 'Credit', 'Tax'), ChargeType,\n ChargeType in ('UnusedReservation', 'UnusedSavingsPlan'), 'Usage',\n ChargeType == 'Refund', 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = iff(ChargeType == 'Refund', 'Correction', ''),\n ChargeDescription = Product,\n ChargeFrequency = case(\n Frequency == 'UsageBased', 'Usage-Based',\n Frequency == 'OneTime', 'One-Time',\n Frequency // \"Recurring\" and any fallback\n ),\n ChargePeriodStart = Date,\n ChargePeriodEnd = Date + 1d,\n ChargeSubcategory = '',\n // TODO: CommitmentDiscount* columns need to handle savings plans\n CommitmentDiscountCategory,\n CommitmentDiscountId = iff(isnotempty(ReservationId), strcat('/providers/microsoft.capacity/reservationorders/', ProductOrderId, '/reservations/', ReservationId), ''),\n CommitmentDiscountName = ReservationName,\n CommitmentDiscountQuantity = real(null),\n CommitmentDiscountStatus = case(\n isempty(ReservationId), '',\n isnotempty(ReservationId) and ChargeType == 'Usage', 'Used',\n ChargeType startswith 'Unused', 'Unused',\n 'Unused'\n ),\n CommitmentDiscountType = iff(isnotempty(ReservationId), 'Reservation', ''),\n CommitmentDiscountUnit = '',\n ConsumedQuantity = PricingQuantity * x_PricingBlockSize,\n ConsumedUnit = PricingUnit,\n ContractedCost = UnitPrice * PricingQuantity,\n ContractedUnitPrice = UnitPrice,\n EffectiveCost = iff(x_AmortizationClass == 'Principal', real(0), Cost),\n InvoiceId = '',\n InvoiceIssuerName = 'Microsoft',\n ListCost = real(null),\n ListUnitPrice = real(null),\n PricingCategory,\n PricingCurrency = '',\n PricingQuantity,\n PricingUnit,\n ProviderName = 'Microsoft',\n PublisherName = iff(PublisherType == 'Marketplace', PublisherName, 'Microsoft'),\n Region = '',\n RegionId,\n RegionName,\n ResourceId = tostring(tmp_ResourceInfo.ResourceId),\n ResourceName = tostring(tmp_ResourceInfo.ResourceName),\n ResourceType,\n ServiceCategory,\n ServiceName,\n ServiceSubcategory = '',\n SkuId = '',\n SkuMeter = '',\n SkuPriceDetails = '',\n SkuPriceId = '',\n SubAccountId = strcat('/subscriptions/', SubscriptionId),\n SubAccountName = SubscriptionName,\n SubAccountType = iff(isempty(SubscriptionId), '', 'Subscription'),\n Tags = iff(Tags startswith '{', Tags, strcat('{', Tags, '}')),\n UsageAmount = real(null),\n UsageQuantity = real(null),\n UsageUnit = '',\n x_AccountId = '',\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerId,\n x_AmortizationClass = '',\n x_BilledCostInUsd = real(null),\n x_BilledUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), UnitPrice),\n x_BillingAccountId = BillingAccountId,\n x_BillingAccountName = BillingAccountName,\n x_BillingExchangeRate = real(null),\n x_BillingExchangeRateDate = datetime(null),\n x_BillingProfileId = BillingProfileId,\n x_BillingProfileName = BillingProfileName,\n x_BillingItemCode = '',\n x_BillingItemName = '',\n x_ChargeId = '',\n x_CommodityCode = '',\n x_CommodityName = '',\n x_ComponentName = '',\n x_ComponentType = '',\n x_ContractedCostInUsd = real(null),\n x_Cost = real(null),\n x_CostAllocationRuleName = '',\n x_CostCategories = '',\n x_CostCenter = CostCenter,\n x_CostType = '',\n x_Credits = '',\n x_CurrencyConversionRate = real(null),\n x_CustomerId = '',\n x_CustomerName = '',\n x_Discount = '',\n x_EffectiveCostInUsd = real(null),\n x_EffectiveUnitPrice = iff(ChargeType == 'Usage' and isnotempty(ReservationId) and ChargeType != 'UnusedSavingsPlan', real(0), EffectivePrice),\n x_ExportTime = datetime(null),\n x_InstanceID = '',\n x_InvoiceId = '',\n x_InvoiceIssuerId = '',\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = InvoiceSection,\n x_ListCostInUsd = real(null),\n x_Location = '',\n x_OnDemandCost = real(null),\n x_OnDemandCostInUsd = real(null),\n x_OnDemandUnitPrice = real(null),\n x_Operation = '',\n x_OwnerAccountID = '',\n x_PartnerCreditApplied = '',\n x_PartnerCreditRate = '',\n x_PricingBlockSize,\n x_PricingCurrency = iff(BillingAccountId == BillingProfileId, BillingCurrency, ''),\n x_PricingSubcategory = case(\n // TODO: Add x_SkuTier when supported by C360 -- PricingCategory == 'Standard' and isnotempty(x_SkuTier), 'Tiered',\n PricingCategory == 'Standard', 'Standard',\n PricingCategory == 'Committed', strcat('Committed ', CommitmentDiscountCategory),\n PricingCategory == 'Dynamic', 'Spot',\n ''\n ),\n x_PricingUnitDescription,\n x_Project = '',\n x_PublisherCategory = iff(PublisherType == 'Marketplace', 'Vendor', 'Cloud Provider'),\n x_PublisherId = '',\n x_ResellerId = '',\n x_ResellerName = '',\n x_ResourceGroupName = ResourceGroup,\n x_ResourceType,\n x_ServiceCode = '',\n x_ServiceId = '',\n x_ServiceModel = '',\n x_ServicePeriodEnd = datetime(null),\n x_ServicePeriodStart = datetime(null),\n x_SkuDescription = Product,\n x_SkuDetails = iff(AdditionalInfo startswith '{', AdditionalInfo, strcat('{', AdditionalInfo, '}')),\n x_SkuIsCreditEligible = IsAzureCreditEligible,\n x_SkuMeterCategory = MeterCategory,\n x_SkuMeterId = MeterId,\n x_SkuMeterName = MeterName,\n x_SkuMeterSubcategory = MeterSubCategory,\n x_SkuOfferId = OfferId,\n x_SkuOrderId = ProductOrderId,\n x_SkuOrderName = ProductOrderName,\n x_SkuPartNumber = PartNumber,\n x_SkuPlanName = '',\n x_SkuRegion = MeterRegion,\n x_SkuServiceFamily = ServiceFamily,\n x_SkuTerm = toint(Term),\n x_SkuTier = '',\n x_SourceName = 'C360',\n x_SourceProvider = 'Microsoft',\n x_SourceType = 'ActualCost',\n x_SourceVersion = 'C360-2025-04',\n x_SubproductName = '',\n x_UsageType = ''\n}\n\n// Update policy for AmortizedCosts_raw -> Costs_raw table\n.alter table Costs_raw policy update\n``` \n[{\n \"IsEnabled\": false,\n \"Source\": \"AmortizedCosts_raw\",\n \"Query\": \"AmortizedCosts_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| CommitmentDiscountUsage |========================================================================================\n// Supported versions:\n// - MS EA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-ea\n// - MS MCA reservation details: 2023-03-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-details-mca\n//======================================================================================================================\n\n// CommitmentDiscountUsage_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All commitment discount usage transformed to FOCUS 1.0. This includes reservationdeatils_raw. Use CommitmentDiscountUsage_transform_v1_2() instead.', folder='Commitment discounts')\nCommitmentDiscountUsage_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n CommitmentDiscountUsage_raw\n //\n // Change real to decimal\n | extend\n InstanceFlexibilityRatio = todecimal(InstanceFlexibilityRatio),\n ReservedHours = todecimal(ReservedHours),\n TotalReservedQuantity = todecimal(TotalReservedQuantity),\n UsedHours = todecimal(UsedHours)\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Handle resource columns\n | extend ResourceId = tolower(InstanceId)\n | extend tmp_ResourceDetails = parse_resourceid(ResourceId)\n | extend ResourceName = tostring(tmp_ResourceDetails.ResourceName)\n | extend SubAccountId = tostring(tmp_ResourceDetails.SubAccountId)\n | extend x_ResourceGroupName = tostring(tmp_ResourceDetails.x_ResourceGroupName)\n | extend x_ResourceType = tostring(tmp_ResourceDetails.x_ResourceType)\n | lookup kind=leftouter (ResourceTypes | distinct x_ResourceType, ResourceType = SingularDisplayName) on x_ResourceType\n | lookup kind=leftouter (Services | distinct x_ResourceType, ServiceName, ServiceCategory, x_ServiceModel) on x_ResourceType\n //\n // Sort columns and apply final transforms\n | project\n ChargePeriodEnd = UsageDate + 1d,\n ChargePeriodStart = UsageDate,\n CommitmentDiscountCategory = 'Usage',\n CommitmentDiscountId = tolower(strcat('/providers/microsoft.capacity/reservationorders/', ReservationOrderId, '/reservations/', ReservationId)),\n CommitmentDiscountType = 'Reservation',\n ConsumedQuantity = UsedHours,\n ProviderName,\n ResourceId,\n ResourceName,\n ResourceType,\n ServiceCategory,\n ServiceName,\n SubAccountId,\n x_CommitmentDiscountCommittedCount = TotalReservedQuantity,\n x_CommitmentDiscountCommittedAmount = ReservedHours,\n // TODO: Is this needed? -- x_CommitmentDiscountKind = Kind,\n x_CommitmentDiscountNormalizedGroup = iff(InstanceFlexibilityGroup == 'NA', '', InstanceFlexibilityGroup),\n x_CommitmentDiscountNormalizedRatio = InstanceFlexibilityRatio,\n x_CommitmentDiscountQuantity = UsedHours * InstanceFlexibilityRatio,\n x_IngestionTime = ingestion_time(),\n x_ResourceGroupName,\n x_ResourceType,\n // x_RowId = hash_sha256(strcat(\n // // DO NOT CHANGE COLUMNS OR COLUMN ORDER\n // CommitmentDiscountId,\n // ResourceId,\n // ChargePeriodStart\n // )),\n x_ServiceModel,\n x_SkuOrderId = ReservationOrderId,\n x_SkuSize = iff(SkuName == 'NA', '', SkuName),\n x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName)),\n x_SourceProvider = coalesce(x_SourceProvider, ProviderName),\n x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationDetails', '')),\n x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2024-03-01', ''))\n}\n\n// CommitmentDiscountUsage_final_v1_0 table\n.create-merge table CommitmentDiscountUsage_final_v1_0 (\n ChargePeriodEnd: datetime, // Hubs add-on\n ChargePeriodStart: datetime, // MS 2023-03-01\n CommitmentDiscountCategory: string, // Hubs add-on\n CommitmentDiscountId: string, // MS 2023-03-01\n CommitmentDiscountType: string, // Hubs add-on\n ConsumedQuantity: decimal, // MS 2023-03-01\n ProviderName: string, // Hubs add-on\n ResourceId: string, // MS 2023-03-01\n ResourceName: string, // Hubs add-on\n ResourceType: string, // Hubs add-on\n ServiceCategory: string, // Hubs add-on\n ServiceName: string, // Hubs add-on\n SubAccountId: string, // Hubs add-on\n x_CommitmentDiscountCommittedCount: decimal, // MS 2023-03-01\n x_CommitmentDiscountCommittedAmount: decimal, // MS 2023-03-01\n x_CommitmentDiscountNormalizedGroup: string, // MS 2023-03-01\n x_CommitmentDiscountNormalizedRatio: decimal, // MS 2023-03-01\n x_CommitmentDiscountQuantity: decimal, // MS 2023-03-01\n x_IngestionTime: datetime, // Hubs add-on\n x_ResourceGroupName: string, // Hubs add-on\n x_ResourceType: string, // Hubs add-on\n x_ServiceModel: string, // Hubs add-on\n x_SkuOrderId: string, // MS 2023-03-01\n x_SkuSize: string, // MS 2023-03-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string // Hubs add-on\n)\n\n// Update policy for CommitmentDiscountUsage_raw -> CommitmentDiscountUsage_final_v1_0 table\n.alter table CommitmentDiscountUsage_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"CommitmentDiscountUsage_raw\",\n \"Query\": \"CommitmentDiscountUsage_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Recommendations |================================================================================================\n// Supported datasets/versions:\n// - MS CM EA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-ea\n// - MS CM MCA reservation recommendations: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-recommendations-mca\n//======================================================================================================================\n\n// Recommendations_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All recommendations transformed to FOCUS 1.0. Use Recommendations_transform_v1_2() instead.', folder='Recommendations')\nRecommendations_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Recommendations_raw\n //\n // Change real to decimal\n | extend\n CostWithNoReservedInstances = todecimal(CostWithNoReservedInstances),\n InstanceFlexibilityRatio = todecimal(InstanceFlexibilityRatio),\n NetSavings = todecimal(NetSavings),\n RecommendedQuantity = todecimal(RecommendedQuantity),\n RecommendedQuantityNormalized = todecimal(RecommendedQuantityNormalized),\n TotalCostWithReservedInstances = todecimal(TotalCostWithReservedInstances)\n //\n | extend x_IngestionTime = ingestion_time()\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationRecommendations', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Convert JSON cost columns to decimal\n | extend CostWithNoReservedInstances = case(isnotempty(CostWithNoReservedInstances), CostWithNoReservedInstances, isnotempty(CostWithNoReservedInstancesJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, CostWithNoReservedInstancesJson)), CostWithNoReservedInstances)\n | extend NetSavings = case(isnotempty(NetSavings), NetSavings, isnotempty(NetSavingsJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, NetSavingsJson)), NetSavings)\n | extend TotalCostWithReservedInstances = case(isnotempty(TotalCostWithReservedInstances), TotalCostWithReservedInstances, isnotempty(TotalCostWithReservedInstancesJson), todecimal(extract(@'\"value\":([0-9\\.]+)', 1, TotalCostWithReservedInstancesJson)), TotalCostWithReservedInstances)\n //\n // Build recommendation details\n | lookup kind=leftouter (Regions | summarize RegionName = make_set(RegionName)[0] by Location = RegionId) on Location\n | extend x_RecommendationDetails = case(\n x_SourceType == 'ReservationRecommendations', bag_pack(\n 'CommitmentDiscountNormalizedGroup', InstanceFlexibilityGroup,\n 'CommitmentDiscountNormalizedRatio', InstanceFlexibilityRatio,\n 'CommitmentDiscountNormalizedSize', NormalizedSize,\n 'CommitmentDiscountResourceType', ResourceType,\n 'CommitmentDiscountScope', Scope,\n 'LookbackPeriodDuration', case(\n LookBackPeriod matches regex @'^Last([0-9]+)Days$', replace_regex(LookBackPeriod, @'^Last([0-9]+)Days$', @'P\\1D'),\n LookBackPeriod matches regex @'^[0-9]+$', strcat('P', LookBackPeriod, 'D'),\n ''\n ),\n 'LookbackPeriodStart', FirstUsageDate,\n 'RecommendedQuantity', RecommendedQuantity,\n 'RecommendedQuantityNormalized', RecommendedQuantityNormalized,\n 'RegionId', Location,\n 'RegionName', RegionName,\n 'SkuMeterId', MeterId,\n 'SkuPriceDetails', SkuProperties,\n 'SkuSize', coalesce(SKU, SkuName),\n 'SkuTerm', isoMonths(Term)\n ),\n dynamic({})\n )\n //\n // Sort columns and apply final transforms\n | extend x_RecommendationDate = FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d)\n | extend x_RecommendationDate = iff(x_RecommendationDate > now(), startofday(now()), x_RecommendationDate)\n | project\n ProviderName,\n SubAccountId = iff(isnotempty(SubscriptionId), strcat('/subscriptions/', SubscriptionId), ''),\n x_IngestionTime,\n x_EffectiveCostAfter = TotalCostWithReservedInstances,\n x_EffectiveCostBefore = CostWithNoReservedInstances,\n x_EffectiveCostSavings = NetSavings,\n x_RecommendationDate = FirstUsageDate + (toint(extract(@'^P([0-9]+)D$', 1, tostring(x_RecommendationDetails.LookbackPeriodDuration))) * 1d),\n x_RecommendationDetails,\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion\n}\n\n// Recommendations_final_v1_0 table\n.create-merge table Recommendations_final_v1_0 (\n ProviderName: string,\n SubAccountId: string,\n x_IngestionTime: datetime,\n x_EffectiveCostAfter: decimal,\n x_EffectiveCostBefore: decimal,\n x_EffectiveCostSavings: decimal,\n x_RecommendationDate: datetime,\n x_RecommendationDetails: dynamic,\n x_SourceName: string,\n x_SourceProvider: string,\n x_SourceType: string,\n x_SourceVersion: string\n)\n\n// Update policy for Recommendations_raw -> Recommendations_final_v1_0 table\n.alter table Recommendations_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Recommendations_raw\",\n \"Query\": \"Recommendations_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n\n\n//===| Transactions |===================================================================================================\n// Supported versions:\n// - MS CM EA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-ea\n// - MS CM MCA reservation transactions: 2023-05-01 -- See https://learn.microsoft.com/azure/cost-management-billing/dataset-schema/reservation-transactions-mca\n//======================================================================================================================\n\n// Transactions_transform_v1_0 function\n.create-or-alter function\nwith (docstring='DEPRECATED: All transactions transformed to FOCUS 1.0. Use Transactions_transform_v1_2() instead.', folder='Transactions')\nTransactions_transform_v1_0()\n{\n // NOTE: All open issues and questions are tracked @ https://github.com/microsoft/finops-toolkit/issues/1111\n let isoMonths = (duration: string) {\n let number = toint(replace_regex(duration, @'[PMY]', ''));\n toint(case(\n duration == '', toint(''),\n duration endswith \"Y\", number * 12,\n duration endswith \"M\", number,\n -1\n ))\n };\n Transactions_raw\n //\n // Change real to decimal\n | extend\n Amount = todecimal(Amount),\n MonetaryCommitment = todecimal(MonetaryCommitment),\n Overage = todecimal(Overage),\n Quantity = todecimal(Quantity)\n //\n // Set ProviderName\n | extend ProviderName = 'Microsoft'\n //\n // Set source columns\n | extend x_SourceName = coalesce(x_SourceName, iff(ProviderName == 'Microsoft', 'Cost Management', ProviderName))\n | extend x_SourceProvider = coalesce(x_SourceProvider, ProviderName)\n | extend x_SourceType = coalesce(x_SourceType, iff(ProviderName == 'Microsoft', 'ReservationTransactions', ''))\n | extend x_SourceVersion = coalesce(x_SourceVersion, iff(ProviderName == 'Microsoft', '2023-05-01', ''))\n //\n // Handle BillingPeriodStart/End\n | extend BillingMonth = tostring(BillingMonth)\n | extend BillingPeriodStart = iff(isempty(BillingMonth), datetime(null), todatetime(strcat(substring(BillingMonth, 0, 4), \"-\", substring(BillingMonth, 4, 2), \"-\", substring(BillingMonth, 6, 2))))\n | extend BillingPeriodEnd = iff(isempty(BillingMonth), datetime(null), startofmonth(endofmonth(BillingPeriodStart) + 1d))\n //\n // Sort columns and apply final transforms\n | project\n BilledCost = Amount,\n BillingAccountId = case(\n BillingProfileId startswith '/', BillingProfileId,\n isnotempty(CurrentEnrollmentId), strcat('/providers/Microsoft.Billing/billingAccounts/', CurrentEnrollmentId),\n isnotempty(BillingProfileId), strcat('/providers/Microsoft.Billing/billingProfiles/', BillingProfileId),\n ''\n ),\n BillingAccountName = coalesce(BillingProfileName, CurrentEnrollmentId),\n BillingCurrency = Currency,\n BillingPeriodEnd,\n BillingPeriodStart,\n ChargeCategory = case(\n EventType in ('Cancel', 'Purchase', 'Refund'), 'Purchase',\n 'Adjustment'\n ),\n ChargeClass = case(\n EventType == 'Cancel', 'Cancel', // FOCUS does not handle this scenario\n EventType == 'Refund', 'Correction',\n ''\n ),\n ChargeDescription = Description,\n ChargeFrequency = case(\n BillingFrequency == 'OneTime', 'One-Time',\n BillingFrequency == 'Recurring', 'Recurring',\n BillingFrequency\n ),\n ChargePeriodStart = EventDate,\n PricingQuantity = Quantity,\n PricingUnit = 'Reservations',\n ProviderName,\n RegionId = Region,\n RegionName = Region,\n SubAccountId = iff(isempty(PurchasingSubscriptionGuid), '', strcat('/subscriptions/', PurchasingSubscriptionGuid)),\n SubAccountName = iff(isempty(PurchasingSubscriptionGuid), '', PurchasingSubscriptionName),\n x_AccountName = AccountName,\n x_AccountOwnerId = AccountOwnerEmail,\n x_CostCenter = CostCenter,\n x_InvoiceId = InvoiceId,\n x_InvoiceNumber = Invoice,\n x_InvoiceSectionId = InvoiceSectionId,\n x_InvoiceSectionName = coalesce(InvoiceSectionName, DepartmentName),\n x_IngestionTime = ingestion_time(),\n x_MonetaryCommitment = MonetaryCommitment,\n x_Overage = Overage,\n x_PurchasingBillingAccountId = PurchasingEnrollment,\n x_SkuOrderId = ReservationOrderId,\n x_SkuOrderName = ReservationOrderName,\n x_SkuSize = ArmSkuName,\n x_SkuTerm = isoMonths(Term),\n x_SourceName,\n x_SourceProvider,\n x_SourceType,\n x_SourceVersion,\n x_SubscriptionId = PurchasingSubscriptionGuid,\n x_TransactionType = EventType\n}\n\n// Transactions_final_v1_0 table\n.create-merge table Transactions_final_v1_0 (\n BilledCost: decimal, // MS CM EA+MCA 2023-05-01\n BillingAccountId: string, // MS CM EA+MCA 2023-05-01\n BillingAccountName: string, // MS CM EA+MCA 2023-05-01\n BillingCurrency: string, // MS CM EA+MCA 2023-05-01\n BillingPeriodEnd: datetime, // MS CM EA+MCA 2023-05-01\n BillingPeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n ChargeCategory: string, // Hubs add-on\n ChargeClass: string, // Hubs add-on\n ChargeDescription: string, // MS CM EA+MCA 2023-05-01\n ChargeFrequency: string, // MS CM EA+MCA 2023-05-01\n ChargePeriodStart: datetime, // MS CM EA+MCA 2023-05-01\n PricingQuantity: decimal, // MS CM EA+MCA 2023-05-01\n PricingUnit: string, // Hubs add-on\n ProviderName: string, // Hubs add-on\n RegionId: string, // MS CM EA+MCA 2023-05-01\n RegionName: string, // MS CM EA+MCA 2023-05-01\n SubAccountId: string, // MS CM EA+MCA 2023-05-01\n SubAccountName: string, // MS CM EA+MCA 2023-05-01\n x_AccountName: string, // MS CM EA 2023-05-01\n x_AccountOwnerId: string, // MS CM EA 2023-05-01\n x_CostCenter: string, // MS CM EA 2023-05-01\n x_InvoiceId: string, // MS CM MCA 2023-05-01\n x_InvoiceNumber: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionId: string, // MS CM MCA 2023-05-01\n x_InvoiceSectionName: string, // MS CM MCA 2023-05-01\n x_IngestionTime: datetime, // Hubs add-on\n x_MonetaryCommitment: decimal, // MS CM EA 2023-05-01\n x_Overage: decimal, // MS CM EA 2023-05-01\n x_PurchasingBillingAccountId: string, // MS CM EA 2023-05-01\n x_SkuOrderId: string, // MS CM EA+MCA 2023-05-01\n x_SkuOrderName: string, // MS CM EA+MCA 2023-05-01\n x_SkuSize: string, // MS CM EA+MCA 2023-05-01\n x_SkuTerm: int, // MS CM EA+MCA 2023-05-01\n x_SourceName: string, // Hubs add-on\n x_SourceProvider: string, // Hubs add-on\n x_SourceType: string, // Hubs add-on\n x_SourceVersion: string, // Hubs add-on\n x_SubscriptionId: string, // MS CM EA+MCA 2023-05-01\n x_TransactionType: string // MS CM EA+MCA 2023-05-01\n)\n\n// Update policy for Transactions_raw -> Transactions_final_v1_0 table\n.alter table Transactions_final_v1_0 policy update\n```\n[{\n \"IsEnabled\": false,\n \"Source\": \"Transactions_raw\",\n \"Query\": \"Transactions_transform_v1_0()\",\n \"IsTransactional\": true,\n \"PropagateIngestionProperties\": true\n}]\n```\n", "HUB_DATA_EXPLORER": "hubDataExplorer", "HUB_DB": "Hub", "INGESTION_DB": "Ingestion", From a62f59fe0f8b5b91d9da47c1a74beacb16cf4551 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 26 May 2026 06:51:14 +0000 Subject: [PATCH 5/6] Polish changelog entry wording per review feedback --- docs-mslearn/toolkit/changelog.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs-mslearn/toolkit/changelog.md b/docs-mslearn/toolkit/changelog.md index 679fb934a..997f27e8e 100644 --- a/docs-mslearn/toolkit/changelog.md +++ b/docs-mslearn/toolkit/changelog.md @@ -80,7 +80,8 @@ _Released April 2026_ - Fixed incorrect Azure China ADX DNS suffix (`kusto.chinacloudapi.cn` → `kusto.windows.cn`) ([#2081](https://github.com/microsoft/finops-toolkit/pull/2081)). - Fixed `createUiDefinition.json` storage URL validation to accept sovereign cloud storage suffixes ([#2081](https://github.com/microsoft/finops-toolkit/pull/2081)). - Fixed `gitapp.hub.com` typo in ADF linked service URL ([#2081](https://github.com/microsoft/finops-toolkit/pull/2081)). - - Fixed Data Factory ingestion memory pressure by replacing `isnotempty(strcat(x_SkuMeterId, x_SkuOfferId))` with separate `isnotempty()` checks in FinOps hub ingestion scripts so temporary concatenated strings are no longer allocated during emptiness filtering. + - Fixed Data Factory ingestion memory pressure during emptiness filtering. + - Replaced `isnotempty(strcat(x_SkuMeterId, x_SkuOfferId))` with separate `isnotempty()` checks in FinOps hub ingestion scripts to avoid temporary string allocation. - Fixed Init-DataFactory deployment script failing when an Event Grid subscription is already provisioning by checking subscription status before attempting subscribe/unsubscribe and polling separately for completion ([#1996](https://github.com/microsoft/finops-toolkit/issues/1996)). - Fixed `msexports_ExecuteETL` pipeline failing on empty export files by adding a row count check ([#1535](https://github.com/microsoft/finops-toolkit/issues/1535)). - Fixed Data Explorer dashboard cost and savings KPIs producing invalid sums in multi-billing-currency tenants by adding a Currency parameter that scopes tile queries to a single currency ([#2093](https://github.com/microsoft/finops-toolkit/issues/2093)). From 28d925d079d755f0ffa559a650b485920349f777 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 26 May 2026 07:01:42 +0000 Subject: [PATCH 6/6] Move ingestion memory fix changelog note to v15 --- docs-mslearn/toolkit/changelog.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs-mslearn/toolkit/changelog.md b/docs-mslearn/toolkit/changelog.md index e8adb30d6..e1df15c81 100644 --- a/docs-mslearn/toolkit/changelog.md +++ b/docs-mslearn/toolkit/changelog.md @@ -49,6 +49,9 @@ _Released June 2026_ - **Changed** - Added a callout to the `config_RunBackfillJob` backfill option clarifying that it isn't supported on Microsoft Customer Agreement (MCA) billing accounts or billing profiles ([#2113](https://github.com/microsoft/finops-toolkit/issues/2113)). +- **Fixed** + - Fixed Data Factory ingestion memory pressure during emptiness filtering. + - Replaced `isnotempty(strcat(x_SkuMeterId, x_SkuOfferId))` with separate `isnotempty()` checks in FinOps hub ingestion scripts to avoid temporary string allocation. > [!div class="nextstepaction"] @@ -90,8 +93,6 @@ _Released April 2026_ - Fixed incorrect Azure China ADX DNS suffix (`kusto.chinacloudapi.cn` → `kusto.windows.cn`) ([#2081](https://github.com/microsoft/finops-toolkit/pull/2081)). - Fixed `createUiDefinition.json` storage URL validation to accept sovereign cloud storage suffixes ([#2081](https://github.com/microsoft/finops-toolkit/pull/2081)). - Fixed `gitapp.hub.com` typo in ADF linked service URL ([#2081](https://github.com/microsoft/finops-toolkit/pull/2081)). - - Fixed Data Factory ingestion memory pressure during emptiness filtering. - - Replaced `isnotempty(strcat(x_SkuMeterId, x_SkuOfferId))` with separate `isnotempty()` checks in FinOps hub ingestion scripts to avoid temporary string allocation. - Fixed Init-DataFactory deployment script failing when an Event Grid subscription is already provisioning by checking subscription status before attempting subscribe/unsubscribe and polling separately for completion ([#1996](https://github.com/microsoft/finops-toolkit/issues/1996)). - Fixed `msexports_ExecuteETL` pipeline failing on empty export files by adding a row count check ([#1535](https://github.com/microsoft/finops-toolkit/issues/1535)). - Fixed Data Explorer dashboard cost and savings KPIs producing invalid sums in multi-billing-currency tenants by adding a Currency parameter that scopes tile queries to a single currency ([#2093](https://github.com/microsoft/finops-toolkit/issues/2093)).