Azure Monitor: Support metric namespaces fallback (#94722)

* Update display names

* Update multi-resource types

* Update default metric namespace list

* Initialise namespace list with fallback namespaces

* Add test

* Update test
This commit is contained in:
Andreas Christou 2024-10-22 13:24:54 +01:00 committed by GitHub
parent b1d846d7e8
commit 986bd2f9f8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 111 additions and 23 deletions

View File

@ -14,13 +14,13 @@ To programatically get the list, execute in the browser console:
Note: Validate that the output makes sense, the format of the page may change.
*/
export const resourceTypeDisplayNames: { [k: string]: string } = {
'microsoft.recoveryservices/vaults/backupfabrics/protectioncontainers/protecteditems': 'Backup Items',
'microsoft.resources/subscriptions': 'Subscriptions',
'microsoft.resources/subscriptions/resourcegroups': 'Resource groups',
'84codes.cloudamqp/servers': 'CloudAMQP',
'citrix.services/xenappessentials': 'Citrix Virtual Apps Essentials',
'citrix.services/xendesktopessentials': 'Citrix Virtual Desktops Essentials',
'dynatrace.observability/monitors': 'Dynatrace',
'github.enterprise/accounts': 'GitHub AE',
'livearena.broadcast/services': 'LiveArena Broadcast',
'mailjet.email/services': 'Mailjet Email Service',
'microsoft.aad/domainservices': 'Azure AD Domain Services',
'microsoft.aadiam/privatelinkforazuread': 'Private Link for Azure AD',
'microsoft.agfoodplatform/farmbeats': 'Azure FarmBeats',
@ -43,6 +43,7 @@ export const resourceTypeDisplayNames: { [k: string]: string } = {
'microsoft.azurearcdata/sqlserverinstances': 'SQL Server - Azure Arc',
'microsoft.azuredata/sqlserverregistrations': 'SQL Server registries',
'microsoft.azurepercept/accounts': 'Azure Percept accounts',
'microsoft.azurestack/registrations': 'Azure Stack Hubs',
'microsoft.azurestackhci/clusters': 'Azure Stack HCI',
'microsoft.azurestackhci/virtualmachines': 'Azure Stack HCI virtual machine - Azure Arc',
'microsoft.baremetal/crayservers': 'Cray Servers',
@ -50,11 +51,13 @@ export const resourceTypeDisplayNames: { [k: string]: string } = {
'microsoft.baremetalinfrastructure/baremetalinstances': 'BareMetal Instances',
'microsoft.batch/batchaccounts': 'Batch accounts',
'microsoft.bing/accounts': 'Bing Resources',
'microsoft.blockchain/blockchainmembers': 'Azure Blockchain Service',
'microsoft.blockchain/cordamembers': 'Corda',
'microsoft.botservice/botservices': 'Bot Services',
'microsoft.cache/redis': 'Azure Cache for Redis',
'microsoft.cache/redisenterprise': 'Redis Enterprise',
'microsoft.cdn/cdnwebapplicationfirewallpolicies': 'Content Delivery Network WAF policies',
'microsoft.cdn/profiles (front doors standard/premium': 'Preview)',
'microsoft.cdn/profiles': '(front doors standard/premium Preview)',
'microsoft.cdn/profiles/afdendpoints': 'Endpoints',
'microsoft.cdn/profiles/endpoints': 'Endpoints',
'microsoft.certificateregistration/certificateorders': 'App Service Certificates',
@ -70,6 +73,7 @@ export const resourceTypeDisplayNames: { [k: string]: string } = {
'microsoft.cloudtest/hostedpools': '1ES Hosted Pools',
'microsoft.cloudtest/images': 'CloudTest Images',
'microsoft.cloudtest/pools': 'CloudTest Pools',
'microsoft.cognition/syntheticsaccounts': 'Synthetics Accounts',
'microsoft.clusterstor/nodes': 'ClusterStors',
'microsoft.cognitiveservices/accounts': 'Cognitive Services',
'microsoft.compute/availabilitysets': 'Availability sets',
@ -195,12 +199,17 @@ export const resourceTypeDisplayNames: { [k: string]: string } = {
'microsoft.insights/webtests': 'Availability tests',
'microsoft.insights/workbooks': 'Azure Workbooks',
'microsoft.insights/workbooktemplates': 'Azure Workbook Templates',
'microsoft.intelligentitdigitaltwin/digitaltwins': 'Minervas',
'microsoft.intelligentitdigitaltwin/digitaltwins/assets': 'Assets',
'microsoft.intelligentitdigitaltwin/digitaltwins/executionplans': 'Deployments',
'microsoft.intelligentitdigitaltwin/digitaltwins/testplans': 'Suites',
'microsoft.intelligentitdigitaltwin/digitaltwins/tests': 'Scripts',
'microsoft.iotcentral/iotapps': 'IoT Central Applications',
'microsoft.keyvault/vaults': 'Key vaults',
'microsoft.kubernetes/connectedclusters': 'Kubernetes - Azure Arc',
'microsoft.kusto/clusters': 'Azure Data Explorer Clusters',
'microsoft.kusto/clusters/databases': 'Azure Data Explorer Databases',
'microsoft.labservices/labaccounts': 'Lab accounts',
'microsoft.labservices/labaccounts': 'Lab Services',
'microsoft.labservices/labplans': 'Lab plans',
'microsoft.labservices/labs': 'Labs',
'microsoft.loadtestservice/loadtests': 'Azure Load Testing',
@ -221,11 +230,13 @@ export const resourceTypeDisplayNames: { [k: string]: string } = {
'microsoft.managedidentity/userassignedidentities': 'Managed Identities',
'microsoft.maps/accounts': 'Azure Maps Accounts',
'microsoft.maps/accounts/creators': 'Azure Maps Creator Resources',
'microsoft.marketplaceapps/classicdevservices': 'Classic Dev Services',
'microsoft.media/mediaservices': 'Media Services',
'microsoft.media/mediaservices/liveevents': 'Live events',
'microsoft.media/mediaservices/streamingendpoints': 'Streaming Endpoints',
'microsoft.media/videoanalyzers': 'Video Analyzers',
'microsoft.migrate/projects': 'Migration projects',
'microsoft.mixedreality/holographicsbroadcastaccounts': 'Holographics Broadcast Accounts',
'microsoft.mixedreality/objectanchorsaccounts': 'Object Anchors Accounts',
'microsoft.mixedreality/objectunderstandingaccounts': 'Object Understanding Accounts',
'microsoft.mixedreality/remoterenderingaccounts': 'Remote Rendering Accounts',
@ -286,7 +297,7 @@ export const resourceTypeDisplayNames: { [k: string]: string } = {
'microsoft.network/virtualwans': 'Virtual WANs',
'microsoft.notificationhubs/namespaces': 'Notification Hub Namespaces',
'microsoft.notificationhubs/namespaces/notificationhubs': 'Notification Hubs',
'microsoft.openenergyplatform/energyservices': 'Project Oak Forest',
'microsoft.openenergyplatform/energyservices': 'Azure OpenEnergy',
'microsoft.openlogisticsplatform/workspaces': 'Open Supply Chain Platform',
'microsoft.operationalinsights/querypacks': 'Log Analytics query packs',
'microsoft.operationalinsights/workspaces': 'Log Analytics workspaces',
@ -298,28 +309,34 @@ export const resourceTypeDisplayNames: { [k: string]: string } = {
'microsoft.orbital/spacecrafts': 'Spacecrafts',
'microsoft.peering/peerings': 'Peerings',
'microsoft.peering/peeringservices': 'Peering Services',
'microsoft.playfab/playeraccountpools': 'PlayFab player account pools',
'microsoft.playfab/playeraccountpools': 'Player account pools',
'microsoft.playfab/titles': 'PlayFab titles',
'microsoft.portal/dashboards': 'Shared dashboards',
'microsoft.powerbidedicated/capacities': 'Power BI Embedded',
'microsoft.purview/accounts': 'Microsoft Purview accounts',
'microsoft.purview/accounts': 'Purview accounts',
'microsoft.quantum/workspaces': 'Quantum Workspaces',
'microsoft.recommendationsservice/accounts': 'Intelligent Recommendations Accounts',
'microsoft.recommendationsservice/accounts/modeling': 'Modeling',
'microsoft.recommendationsservice/accounts/serviceendpoints': 'Service Endpoints',
'microsoft.recoveryservices/vaults': 'Recovery Services vaults',
'microsoft.recoveryservices/vaults/backupfabrics/protectioncontainers/protecteditems': 'Backup Items',
'microsoft.redhatopenshift/openshiftclusters': 'Azure Red Hat OpenShift',
'microsoft.relay/namespaces': 'Relays',
'microsoft.resourceconnector/appliances': 'Resource bridges',
'microsoft.resourcegraph/queries': 'Resource Graph queries',
'microsoft.resources/deploymentscripts': 'Deployment Scripts',
'microsoft.resources/subscriptions': 'Subscriptions',
'microsoft.resources/subscriptions/resourcegroups': 'Resource groups',
'microsoft.resources/templatespecs': 'Template specs',
'microsoft.saas/applications': 'Software as a Service (classic)',
'microsoft.saas/resources': 'SaaS',
'microsoft.scheduler/jobcollections': 'Scheduler Job Collections',
'microsoft.scom/managedinstances': 'Aquila Instances',
'microsoft.scvmm/virtualmachines': 'SCVMM virtual machine - Azure Arc',
'microsoft.scvmm/vmmservers': 'SCVMM management servers',
'microsoft.search/searchservices': 'Search services',
'microsoft.security/insights/classification': 'Data Sensitivity Security Insights (Preview)',
'microsoft.security/locations/alerts': 'Security Alerts',
'microsoft.securitydetonation/chambers': 'Security Detonation Chambers',
'microsoft.servicebus/namespaces': 'Service Bus Namespaces',
'microsoft.servicefabric/clusters': 'Service Fabric clusters',
@ -385,7 +402,13 @@ export const resourceTypeDisplayNames: { [k: string]: string } = {
'microsoft.workloads/sapvirtualinstances/centralinstances': 'SAP central server instances',
'microsoft.workloads/sapvirtualinstances/databaseinstances': 'SAP database server instances',
'nginx.nginxplus/nginxdeployments': 'NGINX Deployment',
'providers.test/statefulibizaengines': 'VLCentral Help',
'paraleap.cloudmonix/services': 'CloudMonix',
'pokitdok.platform/services': 'PokitDok Platform',
'providers.test/statefulibizaengines': 'My Resources',
'ravenhq.db/databases': 'RavenHQ',
'raygun.crashreporting/apps': 'Raygun',
'sendgrid.email/accounts': 'SendGrid Accounts',
'trendmicro.deepsecurity/accounts': 'Deep Security SaaS',
'wandisco.fusion/fusiongroups': 'LiveData Planes',
'wandisco.fusion/fusiongroups/azurezones': 'Azure Zones',
'wandisco.fusion/fusiongroups/azurezones/plugins': 'Plugins',
@ -399,8 +422,6 @@ export const resourceTypeDisplayNames: { [k: string]: string } = {
'wandisco.fusion/migrators/metadatatargets': 'Metadata Targets',
'wandisco.fusion/migrators/pathmappings': 'Path Mappings',
'wandisco.fusion/migrators/targets': 'Targets',
'microsoft.security/insights/classification': 'Data Sensitivity Security Insights (Preview)',
'microsoft.security/locations/alerts': 'Security Alerts',
};
// This list has been manually written using the Azure Portal as the source.
@ -408,10 +429,14 @@ export const resourceTypeDisplayNames: { [k: string]: string } = {
// and go to Select a scope > Resource types > Multi-resource compatible (preview)
export const multiResourceCompatibleTypes: { [ns: string]: boolean } = {
'microsoft.cache/redis': true, // 'Azure Cache for Redis'
'microsoft.documentdb/mongoclusters': true, // 'Azure Cosmos DB for MongoDB'
'microsoft.dbforpostgresql/flexibleservers': true, // 'Azure Database for PostgreSQL flexible servers'
'microsoft.storagecache/amlfilesystems': true, // 'Lustre File Systems'
'microsoft.monitor/accounts': true, // Azure Monitor Workspaces
'microsoft.databoxedge/databoxedgedevices': true, // 'Azure Stack Edge / Data Box Gateway'
'microsoft.azurestackhci/clusters': true, // 'Azure Stack HCI'
'microsoft.dataprotection/backupvaults': true, // 'Backup vaults'
'microsoft.networkcloud/baremetalmachines': true, // 'Bare Metal Machines'
'microsoft.netapp/netappaccounts/capacitypools': true, // 'Capacity pools'
'microsoft.netapp/netappaccounts/capacitypools/volumes': true, // 'Capacity pool volumes'
'microsoft.network/networkwatchers/connectionmonitors': true, // 'Connection Monitors'
@ -430,6 +455,7 @@ export const resourceTypes = [
'microsoft.analysisservices/servers',
'microsoft.apimanagement/service',
'microsoft.app/containerapps',
'microsoft.app/jobs',
'microsoft.app/managedenvironments',
'microsoft.appconfiguration/configurationstores',
'microsoft.appplatform/spring',
@ -498,13 +524,16 @@ export const resourceTypes = [
'microsoft.dbforpostgresql/servergroupsv2',
'microsoft.dbforpostgresql/servers',
'microsoft.dbforpostgresql/serversv2',
'microsoft.devcenter/devcenters',
'microsoft.devices/iothubs',
'microsoft.devices/provisioningservices',
'microsoft.devopsinfrastructure/pools',
'microsoft.digitaltwins/digitaltwinsinstances',
'microsoft.documentdb/cassandraclusters',
'microsoft.documentdb/databaseaccounts',
'microsoft.documentdb/mongoclusters',
'microsoft.edgezones/edgezones',
'microsoft.elasticsan/elasticsans',
'microsoft.enterpriseknowledgegraph/services',
'microsoft.eventgrid/domains',
'microsoft.eventgrid/eventsubscriptions',
@ -528,6 +557,7 @@ export const resourceTypes = [
'microsoft.hybridnetwork/virtualnetworkfunctions',
'microsoft.insights/autoscalesettings',
'microsoft.insights/components',
'microsoft.insights/datacollectionrules',
'microsoft.iotcentral/iotapps',
'microsoft.iotspaces/graph',
'microsoft.keyvault/managedhsms',
@ -548,10 +578,13 @@ export const resourceTypes = [
'microsoft.media/mediaservices/liveevents',
'microsoft.media/mediaservices/streamingendpoints',
'microsoft.media/videoanalyzers',
'microsoft.messagingconnectors/connectors',
'microsoft.mixedreality/remoterenderingaccounts',
'microsoft.mixedreality/spatialanchorsaccounts',
'microsoft.mobilenetwork/mobilenetworks/sites',
'microsoft.mobilenetwork/packetcorecontrolplanes',
'microsoft.mobilenetwork/packetcorecontrolplanes/packetcoredataplanes',
'microsoft.mobilenetwork/radioaccessnetworks',
'microsoft.monitor/accounts',
'microsoft.netapp/netappaccounts/capacitypools',
'microsoft.netapp/netappaccounts/capacitypools/volumes',
@ -560,6 +593,7 @@ export const resourceTypes = [
'microsoft.network/bastionhosts',
'microsoft.network/connections',
'microsoft.network/dnsforwardingrulesets',
'microsoft.network/dnsresolverpolicies',
'microsoft.network/dnsresolvers',
'microsoft.network/dnszones',
'microsoft.network/expressroutecircuits',
@ -588,6 +622,7 @@ export const resourceTypes = [
'microsoft.network/vpngateways',
'microsoft.networkanalytics/dataconnectors',
'microsoft.networkcloud/baremetalmachines',
'microsoft.networkcloud/clustermanagers',
'microsoft.networkcloud/clusters',
'microsoft.networkcloud/storageappliances',
'microsoft.networkfunction/azuretrafficcollectors',
@ -621,6 +656,7 @@ export const resourceTypes = [
'microsoft.sql/servers/databases',
'microsoft.sql/servers/elasticpools',
'microsoft.sql/servers/jobagents',
'microsoft.storageactions/storagetasks',
'microsoft.storage/storageaccounts',
'microsoft.storage/storageaccounts/blobservices',
'microsoft.storage/storageaccounts/fileservices',
@ -653,6 +689,9 @@ export const resourceTypes = [
'microsoft.web/sites/slots',
'microsoft.web/staticsites',
'nginx.nginxplus/nginxdeployments',
'oracle.database/oracle.database/autonomousdatabases',
'oracle.database/oracle.database/cloudvmclusters',
'private.messagingconnectors/private.messagingconnectors/connectors',
'wandisco.fusion/migrators',
'wandisco.fusion/migrators/datatransferagents',
'wandisco.fusion/migrators/livedatamigrations',

View File

@ -331,8 +331,9 @@ describe('AzureMonitor ResourcePicker', () => {
expect(subscriptionCheckboxAfterClear).toBeInTheDocument();
});
it('should throw an error if no namespaces are found', async () => {
it('should not throw an error if no namespaces are found - fallback used', async () => {
const resourcePickerData = createMockResourcePickerData(['getResourceGroupsBySubscriptionId']);
resourcePickerData.postResource = jest.fn().mockResolvedValueOnce({ data: [] });
render(
<ResourcePicker
{...defaultProps}
@ -343,11 +344,8 @@ describe('AzureMonitor ResourcePicker', () => {
);
const subscriptionExpand = await screen.findByLabelText('Expand Primary Subscription');
await userEvent.click(subscriptionExpand);
const error = await screen.findByRole('alert');
expect(error).toHaveTextContent('An error occurred while requesting resources from Azure Monitor');
expect(error).toHaveTextContent(
'Unable to resolve a list of valid metric namespaces. Validate the datasource configuration is correct and required permissions have been granted for all subscriptions. Grafana requires at least the Reader role to be assigned.'
);
const error = await screen.queryByRole('alert');
expect(error).toBeNull();
});
it('display a row for a selected resource even if it is not part of the current rows', async () => {

View File

@ -5,6 +5,7 @@ import {
} from '../__mocks__/argResourcePickerResponse';
import createMockDatasource from '../__mocks__/datasource';
import { createMockInstanceSetttings } from '../__mocks__/instanceSettings';
import { resourceTypes } from '../azureMetadata';
import { ResourceRowType } from '../components/ResourcePicker/types';
import { AzureGraphResponse } from '../types';
@ -19,12 +20,14 @@ jest.mock('@grafana/runtime', () => ({
}),
}));
const createResourcePickerData = (responses: AzureGraphResponse[]) => {
const createResourcePickerData = (responses: AzureGraphResponse[], noNamespaces?: boolean) => {
const instanceSettings = createMockInstanceSetttings();
const mockDatasource = createMockDatasource();
mockDatasource.azureMonitorDatasource.getMetricNamespaces = jest
.fn()
.mockResolvedValueOnce([{ text: 'Microsoft.Storage/storageAccounts', value: 'Microsoft.Storage/storageAccounts' }]);
.mockResolvedValueOnce(
noNamespaces ? [] : [{ text: 'Microsoft.Storage/storageAccounts', value: 'Microsoft.Storage/storageAccounts' }]
);
const resourcePickerData = new ResourcePickerData(instanceSettings, mockDatasource.azureMonitorDatasource);
const postResource = jest.fn();
responses.forEach((res) => {
@ -354,6 +357,53 @@ describe('AzureMonitor resourcePickerData', () => {
uri: '/subscriptions/subId/resourceGroups/rgName/providers/Microsoft.Compute/virtualMachines/vmname',
});
});
it('metrics searches - fallback namespaces', async () => {
const mockSubscriptionsResponse = createMockARGSubscriptionResponse();
const mockResponse = {
data: [
{
id: '/subscriptions/subId/resourceGroups/rgName/providers/Microsoft.Compute/virtualMachines/vmname',
name: 'vmName',
type: 'microsoft.compute/virtualmachines',
resourceGroup: 'rgName',
subscriptionId: 'subId',
location: 'northeurope',
},
],
};
const { resourcePickerData, postResource, mockDatasource } = createResourcePickerData(
[mockSubscriptionsResponse, mockResponse],
true
);
await resourcePickerData.search('vmname', 'metrics');
expect(postResource).toHaveBeenCalledTimes(2);
expect(mockDatasource.azureMonitorDatasource.getMetricNamespaces).toHaveBeenCalledWith(
{
resourceUri: '/subscriptions/1',
},
false,
'westeurope'
);
expect(mockDatasource.azureMonitorDatasource.getMetricNamespaces).toHaveBeenCalledWith(
{
resourceUri: '/subscriptions/1',
},
false,
'eastus'
);
expect(mockDatasource.azureMonitorDatasource.getMetricNamespaces).toHaveBeenCalledWith(
{
resourceUri: '/subscriptions/1',
},
false,
'japaneast'
);
const secondCall = postResource.mock.calls[1];
const [_, postBody] = secondCall;
const namespaces = (postBody.query as string).match(/\((.*?)\)/)?.[0].split(',');
expect(namespaces?.length).toEqual(resourceTypes.length);
});
it('makes requests for logs searches', async () => {
const mockResponse = {
data: [

View File

@ -363,6 +363,11 @@ export default class ResourcePickerData extends DataSourceWithBackend<AzureMonit
reportInteraction('grafana_ds_azuremonitor_subscriptions_loaded', { subscriptions: subscriptions.length });
let supportedMetricNamespaces: Set<string> = new Set();
// Include a predefined set of metric namespaces as a fallback in the case the user cannot query subscriptions
resourceTypes.forEach((namespace) => {
supportedMetricNamespaces.add(`"${namespace}"`);
});
// We make use of these three regions as they *should* contain every possible namespace
const regions = ['westeurope', 'eastus', 'japaneast'];
const getNamespacesForRegion = async (region: string) => {
@ -390,10 +395,6 @@ export default class ResourcePickerData extends DataSourceWithBackend<AzureMonit
);
}
resourceTypes.forEach((namespace) => {
supportedMetricNamespaces.add(`"${namespace}"`);
});
this.supportedMetricNamespaces = Array.from(supportedMetricNamespaces).join(',');
}