bicepmoduleappconfigurationdashboard
Bicep Module for Azure App Configuration
Summary: This is a bicep module that deploys a dashboard to monitor Azure App Configurations.
Date: 9 January 2025
Check here for a previous post for modules on deploying and configuring an Azure App Configuration Store.
Bicep Module App Configuration Dashboard
The module below is the bicep module to deploy a dashboard to monitor an Azure App Configuration. The dashboard will display the following panels:
- A markdown panel with useful information and links to the Azure App Configuration documentation and monitoring.
- A panel showing an overview of the App Configurations in the subscription.
- A panel showing the usage of the App Configuration.
- A panel showing the most recent delete key-value operations and by who in the App Configuration.
- A panel showing the HTTP error codes in the App Configuration.
/* DESCRIPTION Deploys a dashboard for monitoring app configuration LINKS: - Resource: https://learn.microsoft.com/en-us/azure/templates/microsoft.portal/dashboards */ targetScope = 'resourceGroup' // parameters param location string param environment string param appConfigurationName string param appConfigurationRg string // existing resource configStore 'Microsoft.AppConfiguration/configurationStores@2023-03-01' existing = { scope: resourceGroup(appConfigurationRg) name: appConfigurationName } // defined parameters param dashboardName string = 'AppConfig' resource dashboard 'Microsoft.Portal/dashboards@2019-01-01-preview' = { name: 'dashboard-${environment}-${dashboardName}' location: location tags: { 'hidden-title': 'dashboard-${environment}-${dashboardName}' } properties: { lenses: { '0': { order: 0 parts: { '0': { position: { x: 0 y: 0 colSpan: 12 rowSpan: 2 } metadata: { inputs: [] type: 'Extension/HubsExtension/PartType/MarkdownPart' settings: { content: { content: '__Useful information__\n\n<a href=\'https://learn.microsoft.com/en-us/azure/azure-app-configuration/\' target=\'_blank\'>Azure App Configuration documentation</a><br>\n<a href=\'https://learn.microsoft.com/en-us/azure/azure-app-configuration/monitor-app-configuration?tabs=portal\' target=\'_blank\'>Monitoring App Configuration</a>\n\n' title: 'App Configuration Dashboard' subtitle: 'A managed service that helps developers centralize their application and feature settings simply and securely' markdownSource: 1 markdownUri: '' } } } } '1': { position: { x: 0 y: 2 colSpan: 12 rowSpan: 4 } metadata: { inputs: [ { name: 'partTitle' value: 'Query 1' isOptional: true } { name: 'query' value: 'resources\r\n| where type == "microsoft.appconfiguration/configurationstores"\r\n| extend sku = sku.name\r\n| extend creationDate = todatetime(properties.creationDate)\r\n| project name, resourceGroup, creationDate, location, sku, subscriptionId' isOptional: true } { name: 'chartType' isOptional: true } { name: 'isShared' isOptional: true } { name: 'queryId' value: '' isOptional: true } { name: 'formatResults' value: true isOptional: true } { name: 'queryScope' value: { scope: 0 values: [] } isOptional: true } ] type: 'Extension/HubsExtension/PartType/ArgQueryGridTile' settings: {} partHeader: { title: 'Overview App Configurations' subtitle: 'Resource Graph Explorer' } } } '2': { position: { x: 0 y: 6 colSpan: 12 rowSpan: 4 } metadata: { inputs: [ { name: 'resourceTypeMode' isOptional: true } { name: 'ComponentId' isOptional: true } { name: 'Scope' value: { resourceIds: [ configStore.id ] } isOptional: true } { name: 'PartId' value: '1158470d-5c03-431a-859f-6309b00a054e' isOptional: true } { name: 'Version' value: '2.0' isOptional: true } { name: 'TimeRange' isOptional: true } { name: 'DashboardId' isOptional: true } { name: 'DraftRequestParameters' value: { scope: 'hierarchy' } isOptional: true } { name: 'Query' value: 'AACHttpRequest\n | where TimeGenerated > ago(14d)\n | extend Day = startofday(TimeGenerated)\n | summarize requestcount=sum(HitCount) by Day\n | render columnchart \n' isOptional: true } { name: 'ControlType' value: 'FrameControlChart' isOptional: true } { name: 'SpecificChart' value: 'StackedColumn' isOptional: true } { name: 'PartTitle' value: 'Analytics' isOptional: true } { name: 'PartSubTitle' value: appConfigurationName isOptional: true } { name: 'Dimensions' value: { xAxis: { name: 'Day' type: 'datetime' } yAxis: [ { name: 'requestcount' type: 'long' } ] splitBy: [] aggregation: 'Sum' } isOptional: true } { name: 'LegendOptions' value: { isEnabled: true position: 'Bottom' } isOptional: true } { name: 'IsQueryContainTimeRange' value: true isOptional: true } ] type: 'Extension/Microsoft_OperationsManagementSuite_Workspace/PartType/LogsDashboardPart' settings: { content: { Query: 'AACHttpRequest\n | extend Day = startofday(TimeGenerated)\n | summarize requestcount=sum(HitCount) by Day\n | render columnchart \n\n' IsQueryContainTimeRange: false } } filters: { MsPortalFx_TimeRange: { model: { format: 'local' granularity: 'auto' relative: '30d' } } } partHeader: { title: 'Usage' subtitle: appConfigurationName } } } '3': { position: { x: 0 y: 10 colSpan: 12 rowSpan: 8 } metadata: { inputs: [ { name: 'resourceTypeMode' isOptional: true } { name: 'ComponentId' isOptional: true } { name: 'Scope' value: { resourceIds: [ configStore.id ] } isOptional: true } { name: 'PartId' value: '12373b3a-2894-4b2b-ae71-6ea9a910aa19' isOptional: true } { name: 'Version' value: '2.0' isOptional: true } { name: 'TimeRange' value: 'P1D' isOptional: true } { name: 'DashboardId' isOptional: true } { name: 'DraftRequestParameters' value: { scope: 'hierarchy' } isOptional: true } { name: 'Query' value: '// Most recent delete key-value operations \n// List the most recent deleting key-value operations in App Config data plane. \n// This query helps retrieve the most recent 10 audit logs for deleting key-value operations in App Configuration data plane.\nAACAudit\n| where EventCategory == "ApplicationManagement" // and OperationName == "delete-keyvalue"\n| where Status == "Finished"\n| extend Target = tostring(split(TargetResource.TargetResourceName, "/")[4])\n| extend CallerType = iif( isempty(CallerIdentity[3])\n , CallerIdentity[0].callerIdentityType\n , CallerIdentity[3].callerIdentityType\n )\n| extend CallerId = iif( isempty( CallerIdentity[3])\n , CallerIdentity[0].callerIdentity\n , CallerIdentity[3].callerIdentity\n )\n| sort by TimeGenerated desc\n| project TimeGenerated, CallerType, CallerId, Target, OperationName\n\n' isOptional: true } { name: 'ControlType' value: 'AnalyticsGrid' isOptional: true } { name: 'SpecificChart' isOptional: true } { name: 'PartTitle' value: 'Analytics' isOptional: true } { name: 'PartSubTitle' value: appConfigurationName isOptional: true } { name: 'Dimensions' isOptional: true } { name: 'LegendOptions' isOptional: true } { name: 'IsQueryContainTimeRange' value: false isOptional: true } ] type: 'Extension/Microsoft_OperationsManagementSuite_Workspace/PartType/LogsDashboardPart' settings: { content: { GridColumnsWidth: { CallerId: '276px' Target: '336px' CallerType: '128px' } } } partHeader: { title: 'Last Changes' subtitle: appConfigurationName } } } '4': { position: { x: 0 y: 18 colSpan: 12 rowSpan: 4 } metadata: { inputs: [ { name: 'resourceTypeMode' isOptional: true } { name: 'ComponentId' isOptional: true } { name: 'Scope' value: { resourceIds: [ configStore.id ] } isOptional: true } { name: 'PartId' value: '9e8320bf-09ea-4a19-949d-d5c0a30ad2b0' isOptional: true } { name: 'Version' value: '2.0' isOptional: true } { name: 'TimeRange' value: 'P7D' isOptional: true } { name: 'DashboardId' isOptional: true } { name: 'DraftRequestParameters' value: { scope: 'hierarchy' } isOptional: true } { name: 'Query' value: 'AACHttpRequest\n| where StatusCode != 200\n| summarize ErrorCount=count() by bin(TimeGenerated, 1d), StatusCode\n| extend StatusCode = tostring(StatusCode)\n| render columnchart with (kind=stacked, series=StatusCode)\n\n' isOptional: true } { name: 'ControlType' value: 'FrameControlChart' isOptional: true } { name: 'SpecificChart' value: 'StackedColumn' isOptional: true } { name: 'PartTitle' value: 'Analytics' isOptional: true } { name: 'PartSubTitle' value: appConfigurationName isOptional: true } { name: 'Dimensions' value: { xAxis: { name: 'TimeGenerated' type: 'datetime' } yAxis: [ { name: 'ErrorCount' type: 'long' } ] splitBy: [ { name: 'StatusCode' type: 'string' } ] aggregation: 'Sum' } isOptional: true } { name: 'LegendOptions' value: { isEnabled: true position: 'Bottom' } isOptional: true } { name: 'IsQueryContainTimeRange' value: false isOptional: true } ] type: 'Extension/Microsoft_OperationsManagementSuite_Workspace/PartType/LogsDashboardPart' settings: {} filters: { MsPortalFx_TimeRange: { model: { format: 'local' granularity: 'auto' relative: '7d' } } } partHeader: { title: 'HTTP error codes' subtitle: appConfigurationName } } } } } } metadata: { model: { timeRange: { value: { relative: { duration: 24 timeUnit: 1 } } type: 'MsPortalFx.Composition.Configuration.ValueTypes.TimeRange' } filterLocale: { value: 'en-us' } filters: { value: { MsPortalFx_TimeRange: { model: { format: 'local' granularity: 'auto' relative: '24h' } displayCache: { name: 'Local Time' value: 'Past 24 hours' } } } } } } } }
bicepmoduleappconfigurationdashboard.txt · Last modified: by 127.0.0.1