wiki.getshifting.com

--- Sjoerd Hooft's InFormation Technology ---

User Tools

Site Tools


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