
Dt Obs Azure
- 966 installs
- 119 repo stars
- Updated July 29, 2026
- dynatrace/dynatrace-for-ai
dt-obs-azure is a Dynatrace observability skill that instruments AI workloads on Microsoft Azure for developers who need traces, error signals, and dependency health across models and agents.
About
dt-obs-azure is a Dynatrace agent skill for configuring observability on Microsoft Azure environments running AI workloads. The skill guides setup so teams trace latency, surface errors, and monitor dependency health across LLM endpoints, agent runtimes, and supporting Azure services like functions, containers, and managed databases. Developers reach for it when AI features are already deployed on Azure and blind spots appear—slow inference chains, failing tool calls, or unclear cross-service bottlenecks. It focuses on Dynatrace-specific instrumentation patterns for AI pipelines rather than generic infrastructure provisioning or model training workflows.
- Azure-native Dynatrace instrumentation
- AI workload tracing and metrics
- Error and latency visibility
- Dependency and infra health maps
- Supports production incident response
Dt Obs Azure by the numbers
- 966 all-time installs (skills.sh)
- +71 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #320 of 1,039 Cloud & Infrastructure skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/dynatrace/dynatrace-for-ai --skill dt-obs-azureAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 966 |
|---|---|
| repo stars | ★ 119 |
| Last updated | July 29, 2026 |
| Repository | dynatrace/dynatrace-for-ai ↗ |
How do you monitor AI workloads on Azure with Dynatrace?
Configure Dynatrace observability on Azure for AI workloads so teams trace latency, errors, and dependency health across models, agents, and supporting cloud services.
Who is it for?
Platform engineers running LLM or agent services on Azure who need Dynatrace traces and dependency monitoring for production AI pipelines.
Skip if: Greenfield Azure provisioning without observability goals, or teams standardized on a non-Dynatrace monitoring stack.
When should I use this skill?
User asks to add Dynatrace monitoring, tracing, or error visibility for AI agents or models deployed on Azure.
What you get
Dynatrace instrumentation config, distributed traces, error dashboards, and dependency health views
- Observability configuration
- Trace dashboards
- Dependency health views
Files
Azure Cloud Infrastructure
Monitor and analyze Azure resources using Dynatrace Smartscape and DQL. Query Azure services, audit security, manage organizational hierarchy, and plan capacity across your Azure infrastructure.
When to Use This Skill
Use this skill when the user needs to work with Azure resources in Dynatrace. Load the reference file for the task type:
| Task | File to load |
|---|---|
| Inventory and topology queries | (no additional file — use core patterns below) |
| Query Azure metric timeseries (CPU, latency, throughput) | Load references/metrics-performance.md |
| VNet topology, subnets, NSGs, public IPs, VPN, peering | Load references/vnet-networking-security.md |
| Azure SQL, Cosmos DB, PostgreSQL, Redis investigation | Load references/database-monitoring.md |
| Functions, App Service, AKS infrastructure, Container Apps | Load references/serverless-containers.md |
| Azure LB, Application Gateway, Front Door, API Management | Load references/load-balancing-api.md |
| WAF rule analysis, false-positive investigation | Load references/load-balancing-api.md |
| Event Hubs, Service Bus, Event Grid | Load references/messaging-integration.md |
| Storage Accounts, Blob, File, Queue, Table | Load references/storage-monitoring.md |
| Unattached resources, tag compliance, lifecycle | Load references/resource-management.md |
| Cost savings, unused resources, SKU analysis | Load references/cost-optimization.md |
| Capacity headroom, VMSS scaling, quotas | Load references/capacity-planning.md |
| Security audit, encryption, public access, Key Vault | Load references/security-compliance.md |
| NSG rule analysis (0.0.0.0/0, open ports) | Load references/security-compliance.md |
| Storage account encryption/public access audit | Load references/security-compliance.md |
| Cost allocation, chargeback, ownership | Load references/resource-ownership.md |
| Determine orchestration context (AKS, VMSS, standalone) | Load references/workload-detection.md |
---
Core Concepts
Entity Types
Azure resources use the AZURE_* prefix and can be queried using the smartscapeNodes function. All Azure entities are automatically discovered and modeled in Dynatrace Smartscape. Entity type names are derived from the ARM resource provider path: /Microsoft.Compute/virtualMachines becomes AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINES. Sub-resources append with underscores: /Microsoft.Sql/servers/databases becomes AZURE_MICROSOFT_SQL_SERVERS_DATABASES.
Compute: AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINES, AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINESCALESETS, AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINESCALESETS_VIRTUALMACHINES, AZURE_MICROSOFT_COMPUTE_DISKS, AZURE_MICROSOFT_COMPUTE_SSHPUBLICKEYS, AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINES_EXTENSIONS Networking: AZURE_MICROSOFT_NETWORK_VIRTUALNETWORKS, AZURE_MICROSOFT_NETWORK_VIRTUALNETWORKS_SUBNETS, AZURE_MICROSOFT_NETWORK_NETWORKSECURITYGROUPS, AZURE_MICROSOFT_NETWORK_PUBLICIPADDRESSES, AZURE_MICROSOFT_NETWORK_NETWORKINTERFACES, AZURE_MICROSOFT_NETWORK_LOADBALANCERS, AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS, AZURE_MICROSOFT_NETWORK_VIRTUALNETWORKGATEWAYS, AZURE_MICROSOFT_NETWORK_CONNECTIONS, AZURE_MICROSOFT_NETWORK_EXPRESSROUTECIRCUITS Database: AZURE_MICROSOFT_SQL_SERVERS, AZURE_MICROSOFT_SQL_SERVERS_DATABASES, AZURE_MICROSOFT_CACHE_REDIS, AZURE_MICROSOFT_CACHE_REDISENTERPRISE, AZURE_MICROSOFT_DOCUMENTDB_DATABASEACCOUNTS Storage: AZURE_MICROSOFT_STORAGE_STORAGEACCOUNTS, AZURE_MICROSOFT_STORAGE_STORAGEACCOUNTS_BLOBSERVICES_CONTAINERS, AZURE_MICROSOFT_STORAGE_STORAGEACCOUNTS_FILESERVICES_SHARES, AZURE_MICROSOFT_STORAGE_STORAGEACCOUNTS_QUEUESERVICES_QUEUES, AZURE_MICROSOFT_STORAGE_STORAGEACCOUNTS_TABLESERVICES_TABLES Kubernetes/Containers: AZURE_MICROSOFT_CONTAINERSERVICE_MANAGEDCLUSTERS, AZURE_MICROSOFT_CONTAINERSERVICE_MANAGEDCLUSTERS_AGENTPOOLS, AZURE_MICROSOFT_CONTAINERREGISTRY_REGISTRIES, AZURE_MICROSOFT_APP_CONTAINERAPPS, AZURE_MICROSOFT_APP_MANAGEDENVIRONMENTS, AZURE_MICROSOFT_APP_JOBS App Service: AZURE_MICROSOFT_WEB_SITES, AZURE_MICROSOFT_WEB_SERVERFARMS, AZURE_MICROSOFT_WEB_SITES_FUNCTIONS Messaging: AZURE_MICROSOFT_EVENTHUB_NAMESPACES, AZURE_MICROSOFT_EVENTHUB_NAMESPACES_EVENTHUBS, AZURE_MICROSOFT_SERVICEBUS_NAMESPACES, AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_QUEUES, AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_TOPICS, AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_TOPICS_SUBSCRIPTIONS Security/Identity: AZURE_MICROSOFT_KEYVAULT_VAULTS, AZURE_MICROSOFT_MANAGEDIDENTITY_USERASSIGNEDIDENTITIES Monitoring: AZURE_MICROSOFT_OPERATIONALINSIGHTS_WORKSPACES, AZURE_MICROSOFT_INSIGHTS_COMPONENTS API Management: AZURE_MICROSOFT_APIMANAGEMENT_SERVICE
Azure Organizational Hierarchy
Azure organizes resources in a three-level hierarchy: Tenant > Subscription > Resource Group. Every resource belongs to exactly one resource group within one subscription. Use these fields to scope queries:
filter azure.subscription == "08b9810e-..."filter azure.resource.group == "my-rg"filter azure.location == "eastus"Combine these filters for precise scoping:
smartscapeNodes "AZURE_*"
| filter azure.subscription == "<SUBSCRIPTION_ID>"
and azure.resource.group == "<RESOURCE_GROUP>"
and azure.location == "<REGION>"
| summarize count = count(), by: {type}
| sort count descTo see the organizational breakdown across your environment:
smartscapeNodes "AZURE_*"
| summarize resource_count = count(), by: {azure.subscription, azure.resource.group}
| sort resource_count descCommon Azure Fields
All Azure entities include:
azure.subscription— Azure subscription GUIDazure.resource.group— Resource group nameazure.location— Azure region (e.g.,eastus,polandcentral)azure.resourceType— ARM resource type (e.g.,microsoft.compute/virtualmachines)azure.provisioning_state— Provisioning state (e.g.,Succeeded)azure.object— Full ARM resource JSON (see Configuration Parsing)cloud.provider— Alwaysazuretags— Resource tags (use `tags[key]`)
Some entity types also have:
azure.resourceId— Full ARM resource ID (VMs and some others)azure.resourceName— Resource name (VMs and some others)azure.availabilityZones— Availability zone list (VMs)
Relationship Types
Azure entity relationships can be traversed using traverse. The dt.traverse.relationship field is not populated for Azure entities, so you must use "*" as the relationship name in all traversal commands.
Key traversal pairs:
- VM → Disks:
traverse "*", "AZURE_MICROSOFT_COMPUTE_DISKS" - VM → NICs:
traverse "*", "AZURE_MICROSOFT_NETWORK_NETWORKINTERFACES" - VM → VMSS:
traverse "*", "AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINESCALESETS" - VM → Availability Zones:
traverse "*", "AZURE_MICROSOFT_RESOURCES_LOCATIONS_AVAILABILITYZONES" - VM ← Extensions:
traverse "*", "AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINES_EXTENSIONS", direction:backward - VMSS → AKS Clusters:
traverse "*", "AZURE_MICROSOFT_CONTAINERSERVICE_MANAGEDCLUSTERS" - VMSS → Subnets:
traverse "*", "AZURE_MICROSOFT_NETWORK_VIRTUALNETWORKS_SUBNETS" - VMSS → NSGs:
traverse "*", "AZURE_MICROSOFT_NETWORK_NETWORKSECURITYGROUPS" - VMSS → LB Backend Pools:
traverse "*", "AZURE_MICROSOFT_NETWORK_LOADBALANCERS_BACKENDADDRESSPOOLS" - Subnet → VNet:
traverse "*", "AZURE_MICROSOFT_NETWORK_VIRTUALNETWORKS" - Subnet → NSG:
traverse "*", "AZURE_MICROSOFT_NETWORK_NETWORKSECURITYGROUPS" - Subnet ← VMSS:
traverse "*", "AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINESCALESETS", direction:backward - NSG ← NICs:
traverse "*", "AZURE_MICROSOFT_NETWORK_NETWORKINTERFACES", direction:backward - NSG ← Subnets:
traverse "*", "AZURE_MICROSOFT_NETWORK_VIRTUALNETWORKS_SUBNETS", direction:backward - LB → Backend Pools:
traverse "*", "AZURE_MICROSOFT_NETWORK_LOADBALANCERS_BACKENDADDRESSPOOLS" - LB → Frontend IPs:
traverse "*", "AZURE_MICROSOFT_NETWORK_LOADBALANCERS_FRONTENDIPCONFIGURATIONS" - LB → LB Rules:
traverse "*", "AZURE_MICROSOFT_NETWORK_LOADBALANCERS_LOADBALANCINGRULES" - SQL Server ← SQL Databases:
traverse "*", "AZURE_MICROSOFT_SQL_SERVERS_DATABASES", direction:backward - Storage Account ← Blob Containers:
traverse "*", "AZURE_MICROSOFT_STORAGE_STORAGEACCOUNTS_BLOBSERVICES_CONTAINERS", direction:backward - Storage Account ← File Shares:
traverse "*", "AZURE_MICROSOFT_STORAGE_STORAGEACCOUNTS_FILESERVICES_SHARES", direction:backward - AKS ← VMSS:
traverse "*", "AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINESCALESETS", direction:backward - AKS ← Agent Pools:
traverse "*", "AZURE_MICROSOFT_CONTAINERSERVICE_MANAGEDCLUSTERS_AGENTPOOLS", direction:backward - AKS ← NSGs:
traverse "*", "AZURE_MICROSOFT_NETWORK_NETWORKSECURITYGROUPS", direction:backward - AKS ← Public IPs:
traverse "*", "AZURE_MICROSOFT_NETWORK_PUBLICIPADDRESSES", direction:backward - AKS → Public IPs:
traverse "*", "AZURE_MICROSOFT_NETWORK_PUBLICIPADDRESSES" - Web Site → App Service Plan:
traverse "*", "AZURE_MICROSOFT_WEB_SERVERFARMS" - Web Site ← Functions:
traverse "*", "AZURE_MICROSOFT_WEB_SITES_FUNCTIONS", direction:backward - Container App → Managed Environment:
traverse "*", "AZURE_MICROSOFT_APP_MANAGEDENVIRONMENTS" - EventHub Namespace ← Event Hubs:
traverse "*", "AZURE_MICROSOFT_EVENTHUB_NAMESPACES_EVENTHUBS", direction:backward - ServiceBus Namespace ← Queues:
traverse "*", "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_QUEUES", direction:backward - ServiceBus Namespace ← Topics:
traverse "*", "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_TOPICS", direction:backward - ServiceBus Topic ← Subscriptions:
traverse "*", "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_TOPICS_SUBSCRIPTIONS", direction:backward - Use
fieldsKeep:{field1, field2}to carry fields through multi-hop traversals - After a single-hop traverse, use
dt.traverse.history[0][id]to get the source entity ID, thenlookupto resolve the source entity name:
| fieldsAdd sourceId = dt.traverse.history[0][id]
| lookup [smartscapeNodes "SOURCE_TYPE" | fields name, id], sourceField: sourceId, lookupField: id, prefix: "src."- After multi-hop traversals,
dt.traverse.history[-N]works for fields carried viafieldsKeep
Azure Metric Naming Convention
Dynatrace ingests Azure Monitor metrics and exposes them using this naming pattern:
cloud.azure.<provider_namespace>.<resource_type>.<MetricName>The <provider_namespace> uses underscores within the namespace (e.g., microsoft_compute) and <resource_type> is lowercase (e.g., virtualmachines). Hierarchy levels are dot-separated: microsoft_sql.servers.databases. <MetricName> is the Azure Monitor metric name.
Examples:
| Azure Monitor metric | Dynatrace metric key |
|---|---|
VM Percentage CPU | cloud.azure.microsoft_compute.virtualmachines.PercentageCPU |
SQL DB cpu_percent | cloud.azure.microsoft_sql.servers.databases.cpu_percent |
Storage Ingress | cloud.azure.microsoft_storage.storageaccounts.Ingress |
Event Hub IncomingMessages | cloud.azure.microsoft_eventhub.namespaces.IncomingMessages |
Service Bus IncomingMessages | cloud.azure.microsoft_servicebus.namespaces.IncomingMessages |
App Service HttpResponseTime | cloud.azure.microsoft_web.sites.HttpResponseTime |
Load Balancer ByteCount | cloud.azure.microsoft_network.loadbalancers.ByteCount |
AKS node_cpu_usage_percentage | cloud.azure.microsoft_containerservice.managedclusters.node_cpu_usage_percentage |
Cosmos DB TotalRequestUnits | cloud.azure.microsoft_documentdb.databaseaccounts.TotalRequestUnits |
Redis serverLoad | cloud.azure.microsoft_cache.redis.serverLoad |
App Gateway TotalRequests | cloud.azure.microsoft_network.applicationgateways.TotalRequests |
To query a metric:
timeseries cpu = avg(cloud.azure.microsoft_compute.virtualmachines.PercentageCPU),
by: {dt.smartscape_source.id},
from: now()-1h
| limit 10Important: Never refer to these as "Azure Monitor alerts" or "Azure Monitor metrics" in output. Dynatrace monitors Azure resources natively through its Azure integration — these are Dynatrace metrics ingested from Azure.
Configuration Parsing with azure.object
The azure.object field contains the full ARM resource JSON. Parse it with the azjson alias:
parse azure.object, "JSON:azjson"The JSON is wrapped in a configuration key:
{
"configuration": {
"id": "<ARM resource ID>",
"name": "<resource name>",
"type": "<ARM resource type>",
"location": "<region>",
"sku": { ... },
"properties": { ... },
"zones": [...]
},
"tags": { ... }
}Access patterns:
- Properties:
azjson[configuration][properties][field] - SKU:
azjson[configuration][sku][name] - Kind:
azjson[configuration][kind] - Zones:
azjson[configuration][zones]
Common configuration fields by service:
- VM:
properties.hardwareProfile.vmSize,properties.storageProfile.imageReference.offer,properties.storageProfile.osDisk.osType,properties.extended.instanceView.powerState.displayStatus - VMSS:
sku.name(VM size),sku.capacity(instance count),tags.aks-managed-poolName - NSG:
properties.securityRules[](custom rules array),properties.securityRules[].properties.direction,properties.securityRules[].properties.access,properties.securityRules[].properties.sourceAddressPrefix - Storage Account:
kind(e.g., StorageV2),sku.name,properties.accessTier,properties.supportsHttpsTrafficOnly,properties.allowBlobPublicAccess,properties.encryption.keySource - SQL Server:
properties.fullyQualifiedDomainName,properties.publicNetworkAccess,properties.minimalTlsVersion - SQL Database:
sku.name(tier),sku.capacity(DTU/vCore),properties.status,properties.zoneRedundant - AKS:
properties.kubernetesVersion,properties.powerState.code,properties.networkProfile.networkPlugin,properties.enableRBAC - Web Site:
kind(e.g.,functionapp,linux),properties.state,properties.defaultHostName,properties.siteConfig.linuxFxVersion - Container App:
properties.runningStatus,properties.template.containers[].image,properties.template.scale.minReplicas,properties.template.scale.maxReplicas - Event Hub Namespace:
sku.name,properties.kafkaEnabled,properties.zoneRedundant - Service Bus Namespace:
sku.name(Basic/Standard/Premium),properties.zoneRedundant,properties.minimumTlsVersion,properties.publicNetworkAccess,properties.disableLocalAuth,properties.status - Service Bus Queue:
properties.maxSizeInMegabytes,properties.enablePartitioning,properties.deadLetteringOnMessageExpiration,properties.maxDeliveryCount,properties.lockDuration,properties.requiresDuplicateDetection,properties.status - Key Vault:
properties.enableRbacAuthorization,properties.enableSoftDelete,properties.publicNetworkAccess - Redis:
properties.sku.name,properties.hostName,properties.redisVersion,properties.enableNonSslPort - Cosmos DB:
kind(e.g., GlobalDocumentDB),properties.EnabledApiTypes,properties.consistencyPolicy.defaultConsistencyLevel - Load Balancer:
sku.name,tags.aks-managed-cluster-name - App Gateway:
properties.sku.name,properties.sku.tier,properties.operationalState,properties.webApplicationFirewallConfiguration.enabled,properties.webApplicationFirewallConfiguration.firewallMode(Detection/Prevention),properties.webApplicationFirewallConfiguration.ruleSetType,properties.webApplicationFirewallConfiguration.ruleSetVersion,properties.webApplicationFirewallConfiguration.disabledRuleGroups[],properties.webApplicationFirewallConfiguration.exclusions[],properties.firewallPolicy.id
---
Query Patterns
All Azure queries build on four core patterns. Master these and adapt them to any entity type.
Pattern 1: Resource Discovery
List resources by type, filter by subscription/resource group/region/tags, summarize counts:
smartscapeNodes "AZURE_*"
| filter azure.subscription == "<SUBSCRIPTION_ID>" and azure.location == "<REGION>"
| summarize count = count(), by: {type}
| sort count descTo list a specific type, replace "AZURE_*" with the entity type (e.g., "AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINES"). Add | fields name, azure.subscription, azure.resource.group, azure.location, ... to select specific columns. Use ` tags[TagName] ` for tag-based filtering.
Pattern 2: Configuration Parsing
Parse azure.object JSON for detailed configuration fields:
smartscapeNodes "AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINES"
| parse azure.object, "JSON:azjson"
| fieldsAdd vmSize = azjson[configuration][properties][hardwareProfile][vmSize],
osType = azjson[configuration][properties][storageProfile][osDisk][osType]
| summarize vm_count = count(), by: {vmSize, osType, azure.location}Pattern 3: Relationship Traversal
Follow relationships between resources. Use "*" for the relationship name since Azure does not populate dt.traverse.relationship:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS"
| parse azure.object, "JSON:azjson"
| fieldsAdd lbSku = azjson[configuration][sku][name]
| traverse "*", "AZURE_MICROSOFT_NETWORK_LOADBALANCERS_BACKENDADDRESSPOOLS", fieldsKeep:{lbSku, name, id}
| fieldsAdd backendPoolName = name
| traverse "*", "AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINESCALESETS", direction:backward, fieldsKeep:{backendPoolName, id}
| fieldsAdd loadBalancerName = dt.traverse.history[-2][name],
loadBalancerId = dt.traverse.history[-2][id],
backendPoolId = dt.traverse.history[-1][id]Key differences from AWS traversals:
- Always use
"*"as the relationship name (relationship type names are empty for Azure) - Azure relationships primarily follow a parent-child hierarchy: sub-resources link backward to parent resources
- AKS is a major relationship hub with backward links from VMSS, NSGs, LBs, Public IPs, Agent Pools, and Managed Identities
Pattern 4: Tag-Based Ownership
Group resources by any tag for ownership/chargeback:
smartscapeNodes "AZURE_*"
| filter isNotNull(tags[`<TAG_NAME>`])
| summarize resource_count = count(), by: {tags[`<TAG_NAME>`], type}
| sort resource_count descCommon Azure tags: ` tags[ACE:CREATED-BY] , tags[dt_owner_email] , tags[dt_owner_team] , tags[project] , tags[managed-by] . Replace "AZURE_*"` with a specific type to scope to one service.
Find untagged resources: | filter arraySize(tags) == 0
---
Reference Guide
Load reference files for detailed queries when the core patterns above need service-specific adaptation.
| Reference | When to load | Key content |
|---|---|---|
| vnet-networking-security.md | VNet topology, subnets, NSGs, public IPs, VPN, peering | VNet/subnet mapping, NSG blast radius, public IP detection |
| database-monitoring.md | Azure SQL, Cosmos DB, Redis Cache | Service tier distribution, zone redundancy, public access checks |
| serverless-containers.md | Functions, App Service, AKS infra, Container Apps | Runtime distribution, App Service Plan mapping, AKS node pools |
| load-balancing-api.md | Load Balancers, Application Gateways, API Management | LB backend pool traversal, App Gateway routing, APIM config |
| messaging-integration.md | Event Hubs, Service Bus, Event Grid | Namespace inventory, Kafka enablement, throughput unit analysis |
| storage-monitoring.md | Storage Accounts, Blob, File, Queue, Table | SKU distribution, access tier, encryption audit, public access |
| resource-management.md | Resource audits, tag compliance, lifecycle | Unattached disks, tag coverage, provisioning state analysis |
| cost-optimization.md | Cost savings, unused resources, sizing | VM SKU analysis, unattached disks, deallocated VMs |
| capacity-planning.md | Capacity analysis, scaling, utilization | VMSS headroom, subnet IP counts, AKS node pool sizing |
| security-compliance.md | Security audits, encryption, public access, Key Vault | NSG rule analysis, TLS version audit, public endpoint detection, encryption checks |
| resource-ownership.md | Chargeback, ownership, cost allocation | Tag-based grouping, subscription/resource-group summaries |
| workload-detection.md | Determine orchestration context and resolution path | AKS node, VMSS member, standalone VM detection for blast radius analysis |
| metrics-performance.md | Query metric timeseries for a specific resource | DQL timeseries patterns for VM, SQL, Storage, Event Hub, LB, App Service, AKS, Cosmos DB, Redis, App Gateway |
---
Best Practices
Query Optimization
1. Filter early by subscription, resource group, and region 2. Use specific entity types (avoid "AZURE_*" wildcards when possible) 3. Limit results with | limit N for exploration 4. Use isNotNull() checks before accessing nested fields
Configuration Parsing
1. Always parse azure.object with JSON parser: parse azure.object, "JSON:azjson" 2. Use consistent field naming: fieldsAdd configField = azjson[configuration][properties][field] 3. Access SKU via azjson[configuration][sku][name] (not inside properties) 4. Check for null values after parsing — not all entity types have the same properties structure 5. Use toString() for complex nested objects
Organizational Hierarchy
1. Always scope queries by azure.subscription in multi-subscription environments 2. Use azure.resource.group to narrow to a team or application boundary 3. Combine azure.location for region-specific analysis 4. Use summarize ... by: {azure.subscription, azure.resource.group} for organizational breakdowns
Tagging Strategy
1. Use ` tags[key] for filtering (backtick-quoted key names) 2. Check arraySize(tags) for untagged resources 3. Track tag coverage with summarize operations 4. Common ownership tags: dt_owner_email, dt_owner_team, ACE:CREATED-BY`
---
Limitations and Notes
Smartscape Limitations
- Azure object configuration requires parsing with
parse azure.object, "JSON:azjson" - Azure metrics are available as Dynatrace metrics using the
cloud.azure.*naming convention (see Azure Metric Naming Convention) - Resource discovery depends on Azure integration configuration in Dynatrace
- Tag synchronization may have slight delays
Relationship Traversal
- Azure relationship type names are empty — always use
"*"as the relationship name intraversecommands - Use
direction:backwardfor reverse relationships (e.g., sub-resources to parent) - Use
fieldsKeepto maintain important fields through traversal - Access traversal history with
dt.traverse.history[0][id]for single-hop source entity ID; uselookupto resolve source entity name - For multi-hop traversals,
dt.traverse.history[-N]accesses fields carried viafieldsKeep - Azure relationships primarily follow parent-child hierarchy patterns
- AKS is a major relationship hub — expect many backward relationships converging on AKS cluster entities
AKS Coverage
- This skill covers AKS infrastructure-layer entities only (clusters, agent pools, VMSS, networking)
- For Kubernetes workload-layer observability (pods, deployments, services, namespaces), defer to the
dt-obs-kubernetesskill
General Tips
- Use
getNodeName()for human-readable resource names - Handle null values gracefully with
isNotNull()andisNull() - Combine subscription, resource group, and region filters for large environments
- Use
countDistinct()for unique resource counts - The
azure.resourceTypefield is lowercase ARM format (e.g.,microsoft.compute/virtualmachines) — useful for filtering but not for entity type matching
Azure Capacity Planning
Analyze resource capacity and plan for growth across compute, networking, containers, databases, and infrastructure services.
Table of Contents
- Compute Capacity
- Network Capacity
- Container & Serverless Capacity
- Database & Storage Capacity
- Infrastructure Capacity
Compute Capacity
VM SKU distribution across regions:
smartscapeNodes "AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINES"
| parse azure.object, "JSON:azjson"
| fieldsAdd vmSize = azjson[configuration][properties][hardwareProfile][vmSize],
powerState = azjson[configuration][properties][extended][instanceView][powerState][displayStatus]
| summarize vm_count = count(), by: {vmSize, powerState, azure.location}
| sort vm_count descVMSS capacity analysis (current instance count vs configured SKU):
smartscapeNodes "AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINESCALESETS"
| parse azure.object, "JSON:azjson"
| fieldsAdd vmSize = azjson[configuration][sku][name],
tier = azjson[configuration][sku][tier],
capacity = azjson[configuration][sku][capacity]
| fields name, vmSize, tier, capacity, azure.resource.group, azure.location
| sort capacity descNetwork Capacity
Subnet count per virtual network:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_VIRTUALNETWORKS_SUBNETS"
| traverse "*", "AZURE_MICROSOFT_NETWORK_VIRTUALNETWORKS"
| summarize subnet_count = count(), by: {name, azure.location}
| sort subnet_count descNIC usage across resource groups:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_NETWORKINTERFACES"
| summarize nic_count = count(), by: {azure.resource.group, azure.location}
| sort nic_count descPublic IP address counts by region:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_PUBLICIPADDRESSES"
| summarize ip_count = count(), by: {azure.location, azure.resource.group}
| sort ip_count descVirtual network address space inventory:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_VIRTUALNETWORKS"
| parse azure.object, "JSON:azjson"
| fieldsAdd addressPrefixes = toString(azjson[configuration][properties][addressSpace][addressPrefixes]),
ddosProtection = azjson[configuration][properties][enableDdosProtection]
| fields name, addressPrefixes, ddosProtection, azure.location, azure.resource.groupContainer & Serverless Capacity
AKS cluster capacity overview:
smartscapeNodes "AZURE_MICROSOFT_CONTAINERSERVICE_MANAGEDCLUSTERS"
| parse azure.object, "JSON:azjson"
| fieldsAdd k8sVersion = azjson[configuration][properties][kubernetesVersion],
currentVersion = azjson[configuration][properties][currentKubernetesVersion],
powerState = azjson[configuration][properties][powerState][code],
skuTier = azjson[configuration][sku][tier]
| fields name, k8sVersion, currentVersion, powerState, skuTier, azure.resource.group, azure.locationAKS agent pool sizing:
smartscapeNodes "AZURE_MICROSOFT_CONTAINERSERVICE_MANAGEDCLUSTERS_AGENTPOOLS"
| parse azure.object, "JSON:azjson"
| fieldsAdd vmSize = azjson[configuration][vmSize],
nodeCount = azjson[configuration][count],
minCount = azjson[configuration][minCount],
maxCount = azjson[configuration][maxCount],
enableAutoScaling = azjson[configuration][enableAutoScaling],
mode = azjson[configuration][mode]
| fields name, vmSize, nodeCount, minCount, maxCount, enableAutoScaling, mode, azure.resource.group
| sort nodeCount descApp Service Plan capacity and headroom:
smartscapeNodes "AZURE_MICROSOFT_WEB_SERVERFARMS"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][sku][name],
skuTier = azjson[configuration][sku][tier],
capacity = azjson[configuration][sku][capacity]
| fields name, skuName, skuTier, capacity, azure.resource.group, azure.location
| sort capacity descContainer App scaling configuration:
smartscapeNodes "AZURE_MICROSOFT_APP_CONTAINERAPPS"
| parse azure.object, "JSON:azjson"
| fieldsAdd minReplicas = azjson[configuration][properties][template][scale][minReplicas],
maxReplicas = azjson[configuration][properties][template][scale][maxReplicas],
runningStatus = azjson[configuration][properties][runningStatus]
| fields name, minReplicas, maxReplicas, runningStatus, azure.resource.group, azure.locationDatabase & Storage Capacity
SQL database sizing and tier distribution:
smartscapeNodes "AZURE_MICROSOFT_SQL_SERVERS_DATABASES"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][sku][name],
skuTier = azjson[configuration][sku][tier],
skuCapacity = azjson[configuration][sku][capacity],
maxSizeBytes = azjson[configuration][properties][maxSizeBytes],
zoneRedundant = azjson[configuration][properties][zoneRedundant]
| fields name, skuName, skuTier, skuCapacity, maxSizeBytes, zoneRedundant, azure.resource.group
| sort skuCapacity descStorage account distribution across regions:
smartscapeNodes "AZURE_MICROSOFT_STORAGE_STORAGEACCOUNTS"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][sku][name],
kind = azjson[configuration][kind],
accessTier = azjson[configuration][properties][accessTier]
| summarize account_count = count(), by: {skuName, kind, azure.location}
| sort account_count descEvent Hub namespace throughput units:
smartscapeNodes "AZURE_MICROSOFT_EVENTHUB_NAMESPACES"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][sku][name],
throughputUnits = azjson[configuration][sku][capacity],
isAutoInflate = azjson[configuration][properties][isAutoInflateEnabled],
maxThroughputUnits = azjson[configuration][properties][maximumThroughputUnits]
| fields name, skuName, throughputUnits, isAutoInflate, maxThroughputUnits, azure.locationInfrastructure Capacity
VPN gateway inventory:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_VIRTUALNETWORKGATEWAYS"
| parse azure.object, "JSON:azjson"
| fieldsAdd gatewaySku = azjson[configuration][properties][sku][name],
gatewayType = azjson[configuration][properties][gatewayType]
| fields name, gatewaySku, gatewayType, azure.resource.group, azure.locationExpressRoute circuit inventory:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_EXPRESSROUTECIRCUITS"
| fields name, id, azure.resource.group, azure.locationAzure Cost Optimization
Identify cost savings opportunities and optimize Azure spending across compute, storage, networking, and managed services.
Table of Contents
- Compute Costs
- Storage Costs
- Network Costs
- Database Costs
- Serverless Costs
- Infrastructure Management Costs
Compute Costs
Analyze VM SKU distribution for right-sizing opportunities:
smartscapeNodes "AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINES"
| parse azure.object, "JSON:azjson"
| fieldsAdd vmSize = azjson[configuration][properties][hardwareProfile][vmSize],
powerState = azjson[configuration][properties][extended][instanceView][powerState][displayStatus]
| summarize vm_count = count(), by: {vmSize, azure.location}
| sort vm_count descFind deallocated VMs (still incurring disk costs):
smartscapeNodes "AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINES"
| parse azure.object, "JSON:azjson"
| fieldsAdd powerState = azjson[configuration][properties][extended][instanceView][powerState][displayStatus]
| filter powerState != "VM running"
| fields name, id, powerState, azure.resource.group, azure.locationAnalyze VMSS instance sizing and capacity:
smartscapeNodes "AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINESCALESETS"
| parse azure.object, "JSON:azjson"
| fieldsAdd vmSize = azjson[configuration][sku][name],
capacity = azjson[configuration][sku][capacity]
| summarize vmss_count = count(), total_instances = sum(capacity), by: {vmSize}
| sort total_instances descStorage Costs
Find unattached managed disks by SKU and size (wasted spend):
smartscapeNodes "AZURE_MICROSOFT_COMPUTE_DISKS"
| parse azure.object, "JSON:azjson"
| fieldsAdd diskState = azjson[configuration][properties][diskState],
diskSizeGB = azjson[configuration][properties][diskSizeGB],
skuName = azjson[configuration][sku][name]
| filter diskState == "Unattached"
| fields name, skuName, diskSizeGB, azure.resource.group, azure.location
| sort diskSizeGB descAnalyze storage account access tier distribution:
smartscapeNodes "AZURE_MICROSOFT_STORAGE_STORAGEACCOUNTS"
| parse azure.object, "JSON:azjson"
| fieldsAdd accessTier = azjson[configuration][properties][accessTier],
kind = azjson[configuration][kind]
| summarize account_count = count(), by: {accessTier, kind}
| sort account_count descAnalyze storage account redundancy for cost reduction:
smartscapeNodes "AZURE_MICROSOFT_STORAGE_STORAGEACCOUNTS"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][sku][name],
skuTier = azjson[configuration][sku][tier]
| summarize account_count = count(), by: {skuName, skuTier}
| sort account_count descNetwork Costs
Count public IP addresses (each incurs cost):
smartscapeNodes "AZURE_MICROSOFT_NETWORK_PUBLICIPADDRESSES"
| parse azure.object, "JSON:azjson"
| fieldsAdd ipConfig = azjson[configuration][properties][ipConfiguration]
| fieldsAdd is_associated = if(isNotNull(ipConfig), "associated", else: "unassociated")
| summarize ip_count = count(), by: {is_associated, azure.location}
| sort ip_count descAnalyze VPN gateway SKUs:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_VIRTUALNETWORKGATEWAYS"
| parse azure.object, "JSON:azjson"
| fieldsAdd gatewaySku = azjson[configuration][properties][sku][name],
gatewayType = azjson[configuration][properties][gatewayType]
| fields name, gatewaySku, gatewayType, azure.resource.group, azure.locationReview load balancer SKUs:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][sku][name]
| summarize lb_count = count(), by: {skuName, azure.location}
| sort lb_count descDatabase Costs
Analyze SQL database tier and DTU allocation:
smartscapeNodes "AZURE_MICROSOFT_SQL_SERVERS_DATABASES"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][sku][name],
skuTier = azjson[configuration][sku][tier],
skuCapacity = azjson[configuration][sku][capacity],
serviceObjective = azjson[configuration][properties][currentServiceObjectiveName]
| fields name, skuName, skuTier, skuCapacity, serviceObjective, azure.resource.group
| sort skuCapacity descSummarize SQL database costs by tier:
smartscapeNodes "AZURE_MICROSOFT_SQL_SERVERS_DATABASES"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuTier = azjson[configuration][sku][tier],
skuCapacity = azjson[configuration][sku][capacity]
| summarize db_count = count(), total_capacity = sum(skuCapacity), by: {skuTier}
| sort total_capacity descReview Redis cache SKU distribution:
smartscapeNodes "AZURE_MICROSOFT_CACHE_REDIS"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][properties][sku][name],
skuFamily = azjson[configuration][properties][sku][family],
skuCapacity = azjson[configuration][properties][sku][capacity]
| fields name, skuName, skuFamily, skuCapacity, azure.resource.group, azure.locationServerless Costs
Analyze Azure Functions runtime distribution:
smartscapeNodes "AZURE_MICROSOFT_WEB_SITES"
| parse azure.object, "JSON:azjson"
| fieldsAdd kind = azjson[configuration][kind],
runtime = azjson[configuration][properties][siteConfig][linuxFxVersion],
sku = azjson[configuration][properties][sku]
| filter contains(toString(kind), "functionapp")
| summarize function_count = count(), by: {runtime, sku}
| sort function_count descAnalyze App Service Plan SKU distribution:
smartscapeNodes "AZURE_MICROSOFT_WEB_SERVERFARMS"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][sku][name],
skuTier = azjson[configuration][sku][tier],
skuCapacity = azjson[configuration][sku][capacity]
| summarize plan_count = count(), total_instances = sum(skuCapacity), by: {skuName, skuTier}
| sort plan_count descInfrastructure Management Costs
List Key Vaults and their configuration:
smartscapeNodes "AZURE_MICROSOFT_KEYVAULT_VAULTS"
| parse azure.object, "JSON:azjson"
| fieldsAdd rbacAuth = azjson[configuration][properties][enableRbacAuthorization],
softDelete = azjson[configuration][properties][enableSoftDelete]
| fields name, rbacAuth, softDelete, azure.resource.group, azure.locationReview monitoring resource counts (Log Analytics workspaces, Application Insights):
smartscapeNodes "AZURE_MICROSOFT_OPERATIONALINSIGHTS_WORKSPACES",
"AZURE_MICROSOFT_INSIGHTS_COMPONENTS"
| summarize count = count(), by: {type, azure.location}
| sort count descAzure Database Monitoring
Monitor and analyze Azure database services including Azure SQL, Cosmos DB, and Redis Cache.
Table of Contents
- Database Entity Types
- Azure SQL Monitoring
- Cosmos DB Monitoring
- Redis Cache
- Database Security
- Cross-Service Analysis
Database Entity Types
All these types support the standard discovery pattern: smartscapeNodes "<TYPE>" | fields name, id, azure.subscription, azure.resource.group, azure.location, ...
| Entity Type | Description |
|---|---|
AZURE_MICROSOFT_SQL_SERVERS | Azure SQL logical servers |
AZURE_MICROSOFT_SQL_SERVERS_DATABASES | Azure SQL databases |
AZURE_MICROSOFT_CACHE_REDIS | Azure Cache for Redis |
AZURE_MICROSOFT_CACHE_REDISENTERPRISE | Azure Cache for Redis Enterprise |
AZURE_MICROSOFT_CACHE_REDISENTERPRISE_DATABASES | Redis Enterprise databases |
AZURE_MICROSOFT_DOCUMENTDB_DATABASEACCOUNTS | Cosmos DB accounts |
AZURE_MICROSOFT_DOCUMENTDB_DATABASEACCOUNTS_SQLDATABASES | Cosmos DB SQL databases |
Azure SQL Monitoring
List all SQL servers:
smartscapeNodes "AZURE_MICROSOFT_SQL_SERVERS"
| parse azure.object, "JSON:azjson"
| fieldsAdd fqdn = azjson[configuration][properties][fullyQualifiedDomainName],
state = azjson[configuration][properties][state],
version = azjson[configuration][properties][version],
adminLogin = azjson[configuration][properties][administratorLogin]
| fields name, fqdn, state, version, adminLogin, azure.resource.group, azure.locationList all SQL databases with SKU and tier details:
smartscapeNodes "AZURE_MICROSOFT_SQL_SERVERS_DATABASES"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][sku][name],
skuTier = azjson[configuration][sku][tier],
skuCapacity = azjson[configuration][sku][capacity],
status = azjson[configuration][properties][status],
serviceObjective = azjson[configuration][properties][currentServiceObjectiveName],
maxSizeBytes = azjson[configuration][properties][maxSizeBytes]
| fields name, skuName, skuTier, skuCapacity, status, serviceObjective, maxSizeBytes,
azure.resource.group, azure.locationFind SQL databases by service tier:
smartscapeNodes "AZURE_MICROSOFT_SQL_SERVERS_DATABASES"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuTier = azjson[configuration][sku][tier]
| summarize db_count = count(), by: {skuTier}
| sort db_count descFind zone-redundant SQL databases:
smartscapeNodes "AZURE_MICROSOFT_SQL_SERVERS_DATABASES"
| parse azure.object, "JSON:azjson"
| fieldsAdd zoneRedundant = azjson[configuration][properties][zoneRedundant],
skuTier = azjson[configuration][sku][tier]
| fields name, zoneRedundant, skuTier, azure.resource.group, azure.locationFind SQL databases belonging to a specific server (SQL Database → SQL Server backward traversal):
smartscapeNodes "AZURE_MICROSOFT_SQL_SERVERS"
| filter name == "<SQL_SERVER_NAME>"
| traverse "*", "AZURE_MICROSOFT_SQL_SERVERS_DATABASES", direction:backward
| fields name, id, azure.resource.groupAnalyze backup redundancy configuration:
smartscapeNodes "AZURE_MICROSOFT_SQL_SERVERS_DATABASES"
| parse azure.object, "JSON:azjson"
| fieldsAdd backupRedundancy = azjson[configuration][properties][currentBackupStorageRedundancy],
skuTier = azjson[configuration][sku][tier]
| summarize db_count = count(), by: {backupRedundancy, skuTier}
| sort db_count descCosmos DB Monitoring
List Cosmos DB accounts with configuration details:
smartscapeNodes "AZURE_MICROSOFT_DOCUMENTDB_DATABASEACCOUNTS"
| parse azure.object, "JSON:azjson"
| fieldsAdd accountKind = azjson[configuration][kind],
apiTypes = azjson[configuration][properties][EnabledApiTypes],
consistencyLevel = azjson[configuration][properties][consistencyPolicy][defaultConsistencyLevel],
autoFailover = azjson[configuration][properties][enableAutomaticFailover],
multiWrite = azjson[configuration][properties][enableMultipleWriteLocations],
endpoint = azjson[configuration][properties][documentEndpoint]
| fields name, accountKind, apiTypes, consistencyLevel, autoFailover, multiWrite, endpoint,
azure.resource.group, azure.locationFind serverless Cosmos DB accounts:
smartscapeNodes "AZURE_MICROSOFT_DOCUMENTDB_DATABASEACCOUNTS"
| parse azure.object, "JSON:azjson"
| fieldsAdd capabilities = azjson[configuration][properties][capabilities]
| expand capabilities
| filter capabilities[name] == "EnableServerless"
| fields name, azure.resource.group, azure.locationAnalyze Cosmos DB backup configuration:
smartscapeNodes "AZURE_MICROSOFT_DOCUMENTDB_DATABASEACCOUNTS"
| parse azure.object, "JSON:azjson"
| fieldsAdd backupType = azjson[configuration][properties][backupPolicy][type],
vnetFilter = azjson[configuration][properties][isVirtualNetworkFilterEnabled]
| fields name, backupType, vnetFilter, azure.resource.group, azure.locationRedis Cache
List all Redis Cache instances with configuration:
smartscapeNodes "AZURE_MICROSOFT_CACHE_REDIS"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][properties][sku][name],
skuFamily = azjson[configuration][properties][sku][family],
skuCapacity = azjson[configuration][properties][sku][capacity],
hostName = azjson[configuration][properties][hostName],
redisVersion = azjson[configuration][properties][redisVersion],
sslPort = azjson[configuration][properties][sslPort]
| fields name, skuName, skuFamily, skuCapacity, hostName, redisVersion, sslPort,
azure.resource.group, azure.locationList Redis Enterprise clusters:
smartscapeNodes "AZURE_MICROSOFT_CACHE_REDISENTERPRISE"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][sku][name],
skuCapacity = azjson[configuration][sku][capacity]
| fields name, skuName, skuCapacity, azure.resource.group, azure.locationFind Redis Enterprise databases:
smartscapeNodes "AZURE_MICROSOFT_CACHE_REDISENTERPRISE_DATABASES"
| fields name, id, azure.resource.group, azure.location, azure.provisioning_stateCheck Redis non-SSL port status:
smartscapeNodes "AZURE_MICROSOFT_CACHE_REDIS"
| parse azure.object, "JSON:azjson"
| fieldsAdd enableNonSslPort = azjson[configuration][properties][enableNonSslPort],
minimumTlsVersion = azjson[configuration][properties][minimumTlsVersion]
| fields name, enableNonSslPort, minimumTlsVersion, azure.resource.groupDatabase Security
Find SQL servers with public network access enabled:
smartscapeNodes "AZURE_MICROSOFT_SQL_SERVERS"
| parse azure.object, "JSON:azjson"
| fieldsAdd publicAccess = azjson[configuration][properties][publicNetworkAccess],
minTls = azjson[configuration][properties][minimalTlsVersion],
outboundRestriction = azjson[configuration][properties][restrictOutboundNetworkAccess]
| fields name, publicAccess, minTls, outboundRestriction, azure.resource.group, azure.locationAnalyze TLS versions across all database services:
smartscapeNodes "AZURE_MICROSOFT_SQL_SERVERS"
| parse azure.object, "JSON:azjson"
| fieldsAdd minTls = azjson[configuration][properties][minimalTlsVersion], service = "SQL Server"
| fields name, minTls, service
| append [
smartscapeNodes "AZURE_MICROSOFT_CACHE_REDIS"
| parse azure.object, "JSON:azjson"
| fieldsAdd minTls = azjson[configuration][properties][minimumTlsVersion], service = "Redis"
| fields name, minTls, service
]
| append [
smartscapeNodes "AZURE_MICROSOFT_DOCUMENTDB_DATABASEACCOUNTS"
| parse azure.object, "JSON:azjson"
| fieldsAdd minTls = azjson[configuration][properties][minimalTlsVersion], service = "Cosmos DB"
| fields name, minTls, service
]
| sort service, minTlsFind Redis instances with non-SSL port enabled (security risk):
smartscapeNodes "AZURE_MICROSOFT_CACHE_REDIS"
| parse azure.object, "JSON:azjson"
| fieldsAdd enableNonSslPort = azjson[configuration][properties][enableNonSslPort]
| filter enableNonSslPort == true
| fields name, azure.resource.group, azure.locationCross-Service Analysis
Count all database resources by type:
smartscapeNodes "AZURE_MICROSOFT_SQL_SERVERS", "AZURE_MICROSOFT_SQL_SERVERS_DATABASES",
"AZURE_MICROSOFT_CACHE_REDIS", "AZURE_MICROSOFT_CACHE_REDISENTERPRISE",
"AZURE_MICROSOFT_DOCUMENTDB_DATABASEACCOUNTS"
| summarize db_count = count(), by: {type}
| sort db_count descCount databases across regions:
smartscapeNodes "AZURE_MICROSOFT_SQL_SERVERS_DATABASES", "AZURE_MICROSOFT_CACHE_REDIS",
"AZURE_MICROSOFT_DOCUMENTDB_DATABASEACCOUNTS"
| summarize db_count = count(), by: {type, azure.location}
| sort azure.location, db_count descFind all databases in a specific resource group:
smartscapeNodes "AZURE_MICROSOFT_SQL_SERVERS", "AZURE_MICROSOFT_SQL_SERVERS_DATABASES",
"AZURE_MICROSOFT_CACHE_REDIS", "AZURE_MICROSOFT_DOCUMENTDB_DATABASEACCOUNTS"
| filter azure.resource.group == "<RESOURCE_GROUP>"
| fields type, name, azure.location, azure.provisioning_stateAzure Load Balancing & API Management
Monitor Azure Load Balancers, Application Gateways, and API Management services.
Table of Contents
- Load Balancing & API Entity Types
- Azure Load Balancer Topology Traversal
- Application Gateway Configuration
- WAF Configuration & Rule Analysis
- WAF Mode Detection
- WAF-Enabled Gateway Inventory
- WAF Rule Configuration
- Disabled Rule Groups
- WAF Exclusions
- Firewall Policy Association
- API Management
- Security & Networking
- Cross-Service Analysis
Load Balancing & API Entity Types
All these types support the standard discovery pattern: smartscapeNodes "<TYPE>" | fields name, id, azure.subscription, azure.resource.group, azure.location, ...
| Entity Type | Description |
|---|---|
AZURE_MICROSOFT_NETWORK_LOADBALANCERS | Azure Load Balancers (Standard and Basic SKU) |
AZURE_MICROSOFT_NETWORK_LOADBALANCERS_FRONTENDIPCONFIGURATIONS | LB frontend IP configurations |
AZURE_MICROSOFT_NETWORK_LOADBALANCERS_BACKENDADDRESSPOOLS | LB backend address pools |
AZURE_MICROSOFT_NETWORK_LOADBALANCERS_LOADBALANCINGRULES | LB load balancing rules |
AZURE_MICROSOFT_NETWORK_LOADBALANCERS_OUTBOUNDRULES | LB outbound rules |
AZURE_MICROSOFT_NETWORK_LOADBALANCERS_INBOUNDNATRULES | LB inbound NAT rules |
AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS | Application Gateways |
AZURE_MICROSOFT_APIMANAGEMENT_SERVICE | API Management services |
Azure Load Balancer Topology Traversal
Complete LB → Backend Pool → VMSS Mapping
This is the most important query — maps load balancers through backend pools to the VMSS instances serving traffic:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][sku][name]
| traverse "*", "AZURE_MICROSOFT_NETWORK_LOADBALANCERS_BACKENDADDRESSPOOLS", fieldsKeep:{skuName, name, id}
| fieldsAdd poolName = name, poolId = id
| traverse "*", "AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINESCALESETS", direction:backward, fieldsKeep:{poolName, poolId}
| fieldsAdd lbName = dt.traverse.history[-2][name],
lbId = dt.traverse.history[-2][id],
lbSku = dt.traverse.history[-2][skuName]
| fields lbName, lbSku, poolName, name, id, azure.resource.groupSimpler Traversals
LB to frontend IP configurations:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS"
| traverse "*", "AZURE_MICROSOFT_NETWORK_LOADBALANCERS_FRONTENDIPCONFIGURATIONS"
| fieldsAdd sourceId = dt.traverse.history[0][id]
| lookup [smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS" | fields name, id], sourceField: sourceId, lookupField: id, prefix: "lb."
| fields lb.name, name, id, azure.resource.groupLB to backend address pools:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS"
| traverse "*", "AZURE_MICROSOFT_NETWORK_LOADBALANCERS_BACKENDADDRESSPOOLS"
| fieldsAdd sourceId = dt.traverse.history[0][id]
| lookup [smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS" | fields name, id], sourceField: sourceId, lookupField: id, prefix: "lb."
| fields lb.name, name, idLB to load balancing rules:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS"
| traverse "*", "AZURE_MICROSOFT_NETWORK_LOADBALANCERS_LOADBALANCINGRULES"
| fieldsAdd sourceId = dt.traverse.history[0][id]
| lookup [smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS" | fields name, id], sourceField: sourceId, lookupField: id, prefix: "lb."
| fields lb.name, name, idLB to outbound rules:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS"
| traverse "*", "AZURE_MICROSOFT_NETWORK_LOADBALANCERS_OUTBOUNDRULES"
| fieldsAdd sourceId = dt.traverse.history[0][id]
| lookup [smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS" | fields name, id], sourceField: sourceId, lookupField: id, prefix: "lb."
| fields lb.name, name, idLB to AKS Cluster Mapping
Find which AKS clusters a load balancer is associated with:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS"
| traverse "*", "AZURE_MICROSOFT_CONTAINERSERVICE_MANAGEDCLUSTERS"
| fieldsAdd sourceId = dt.traverse.history[0][id]
| lookup [smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS" | fields name, id], sourceField: sourceId, lookupField: id, prefix: "lb."
| fields lb.name, name, id, azure.resource.groupIdentify AKS-managed load balancers via tags:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS"
| fieldsAdd aksCluster = tags[`aks-managed-cluster-name`]
| filter isNotNull(aksCluster)
| fields name, aksCluster, azure.resource.group, azure.locationLoad Balancer Configuration
List all load balancers with SKU:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][sku][name]
| fields name, skuName, azure.resource.group, azure.location, azure.provisioning_stateApplication Gateway Configuration
List Application Gateways with configuration details:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][properties][sku][name],
skuTier = azjson[configuration][properties][sku][tier],
skuCapacity = azjson[configuration][properties][sku][capacity],
operationalState = azjson[configuration][properties][operationalState],
enableHttp2 = azjson[configuration][properties][enableHttp2]
| fields name, skuName, skuTier, skuCapacity, operationalState, enableHttp2,
azure.resource.group, azure.locationAnalyze Application Gateway backend pools:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS"
| parse azure.object, "JSON:azjson"
| fieldsAdd backendPools = azjson[configuration][properties][backendAddressPools]
| expand backendPools
| fieldsAdd poolName = backendPools[name]
| fields name, poolName, azure.resource.groupAnalyze Application Gateway HTTP listeners:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS"
| parse azure.object, "JSON:azjson"
| fieldsAdd listeners = azjson[configuration][properties][httpListeners]
| expand listeners
| fieldsAdd listenerName = listeners[name],
protocol = listeners[properties][protocol],
hostName = listeners[properties][hostName]
| fields name, listenerName, protocol, hostNameAnalyze Application Gateway routing rules:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS"
| parse azure.object, "JSON:azjson"
| fieldsAdd rules = azjson[configuration][properties][requestRoutingRules]
| expand rules
| fieldsAdd ruleName = rules[name],
ruleType = rules[properties][ruleType],
priority = rules[properties][priority]
| fields name, ruleName, ruleType, priority
| sort priority ascApplication Gateway sub-resource entities for fine-grained traversal:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS_BACKENDADDRESSPOOLS",
"AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS_HTTPLISTENERS",
"AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS_REQUESTROUTINGRULES",
"AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS_URLPATHMAPS",
"AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS_FRONTENDIPCONFIGURATIONS",
"AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS_FRONTENDPORTS"
| fields type, name, id, azure.resource.group
| sort typeWAF Configuration & Rule Analysis
Queries for investigating Web Application Firewall configuration on Application Gateways. Essential during false-positive incident investigation.
WAF Mode Detection
List WAF-enabled gateways with their mode (Detection vs Prevention):
smartscapeNodes "AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS"
| parse azure.object, "JSON:azjson"
| fieldsAdd wafEnabled = azjson[configuration][properties][webApplicationFirewallConfiguration][enabled],
wafMode = azjson[configuration][properties][webApplicationFirewallConfiguration][firewallMode],
skuTier = azjson[configuration][properties][sku][tier]
| filter wafEnabled == true
| fields name, wafMode, skuTier, azure.resource.group, azure.locationFind gateways in Detection mode only (logging but not blocking — common during rollout or after false-positive issues):
smartscapeNodes "AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS"
| parse azure.object, "JSON:azjson"
| fieldsAdd wafEnabled = azjson[configuration][properties][webApplicationFirewallConfiguration][enabled],
wafMode = azjson[configuration][properties][webApplicationFirewallConfiguration][firewallMode]
| filter wafEnabled == true and wafMode == "Detection"
| fields name, wafMode, azure.resource.group, azure.locationWAF-Enabled Gateway Inventory
Full inventory with SKU, WAF status, and rule set info:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS"
| parse azure.object, "JSON:azjson"
| fieldsAdd wafEnabled = azjson[configuration][properties][webApplicationFirewallConfiguration][enabled],
wafMode = azjson[configuration][properties][webApplicationFirewallConfiguration][firewallMode],
ruleSetType = azjson[configuration][properties][webApplicationFirewallConfiguration][ruleSetType],
ruleSetVersion = azjson[configuration][properties][webApplicationFirewallConfiguration][ruleSetVersion],
skuName = azjson[configuration][properties][sku][name],
skuTier = azjson[configuration][properties][sku][tier]
| fields name, skuName, skuTier, wafEnabled, wafMode, ruleSetType, ruleSetVersion,
azure.resource.group, azure.locationFind gateways with a WAF-capable SKU but WAF not enabled:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS"
| parse azure.object, "JSON:azjson"
| fieldsAdd wafEnabled = azjson[configuration][properties][webApplicationFirewallConfiguration][enabled],
skuTier = azjson[configuration][properties][sku][tier]
| filter contains(toString(skuTier), "WAF") and wafEnabled != true
| fields name, skuTier, wafEnabled, azure.resource.group, azure.locationWAF Rule Configuration
Inspect rule set type, version, and body inspection limits:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS"
| parse azure.object, "JSON:azjson"
| fieldsAdd wafEnabled = azjson[configuration][properties][webApplicationFirewallConfiguration][enabled],
ruleSetType = azjson[configuration][properties][webApplicationFirewallConfiguration][ruleSetType],
ruleSetVersion = azjson[configuration][properties][webApplicationFirewallConfiguration][ruleSetVersion],
maxRequestBodySizeInKb = azjson[configuration][properties][webApplicationFirewallConfiguration][maxRequestBodySizeInKb],
fileUploadLimitInMb = azjson[configuration][properties][webApplicationFirewallConfiguration][fileUploadLimitInMb],
requestBodyCheck = azjson[configuration][properties][webApplicationFirewallConfiguration][requestBodyCheck]
| filter wafEnabled == true
| fields name, ruleSetType, ruleSetVersion, maxRequestBodySizeInKb, fileUploadLimitInMb, requestBodyCheck,
azure.resource.groupSummarize rule set versions in use across all gateways:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS"
| parse azure.object, "JSON:azjson"
| fieldsAdd wafEnabled = azjson[configuration][properties][webApplicationFirewallConfiguration][enabled],
ruleSetType = azjson[configuration][properties][webApplicationFirewallConfiguration][ruleSetType],
ruleSetVersion = azjson[configuration][properties][webApplicationFirewallConfiguration][ruleSetVersion]
| filter wafEnabled == true
| summarize count = count(), by: {ruleSetType, ruleSetVersion}
| sort count descDisabled Rule Groups
This is the most critical section for false-positive investigation. Disabled rule groups indicate rules that were turned off to avoid blocking legitimate traffic.
Expand disabled rule groups to show which rules are disabled per gateway:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS"
| parse azure.object, "JSON:azjson"
| fieldsAdd wafEnabled = azjson[configuration][properties][webApplicationFirewallConfiguration][enabled],
disabledRuleGroups = azjson[configuration][properties][webApplicationFirewallConfiguration][disabledRuleGroups]
| filter wafEnabled == true
| expand disabledRuleGroups
| fieldsAdd ruleGroupName = disabledRuleGroups[ruleGroupName],
rules = toString(disabledRuleGroups[rules])
| fields name, ruleGroupName, rules, azure.resource.groupFind gateways with no disabled rules (fully enforcing all rule groups):
smartscapeNodes "AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS"
| parse azure.object, "JSON:azjson"
| fieldsAdd wafEnabled = azjson[configuration][properties][webApplicationFirewallConfiguration][enabled],
disabledRuleGroups = azjson[configuration][properties][webApplicationFirewallConfiguration][disabledRuleGroups]
| filter wafEnabled == true and (isnull(disabledRuleGroups) or arraySize(disabledRuleGroups) == 0)
| fields name, azure.resource.group, azure.locationInvestigation tip: Common false-positive rule groups includeREQUEST-942-APPLICATION-ATTACK-SQLI(SQL injection) andREQUEST-941-APPLICATION-ATTACK-XSS(cross-site scripting). If these appear indisabledRuleGroups, the team likely encountered false positives from application payloads matching SQL/XSS patterns. Check whether exclusions (below) would be a more targeted fix than disabling entire rule groups.
WAF Exclusions
Expand WAF exclusions to see which request attributes are excluded from rule evaluation:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS"
| parse azure.object, "JSON:azjson"
| fieldsAdd wafEnabled = azjson[configuration][properties][webApplicationFirewallConfiguration][enabled],
exclusions = azjson[configuration][properties][webApplicationFirewallConfiguration][exclusions]
| filter wafEnabled == true
| expand exclusions
| fieldsAdd matchVariable = exclusions[matchVariable],
selectorMatchOperator = exclusions[selectorMatchOperator],
selector = exclusions[selector]
| fields name, matchVariable, selectorMatchOperator, selector, azure.resource.groupNote: CommonmatchVariablevalues areRequestHeaderNames,RequestCookieNames,RequestArgNames, andRequestBodyPostArgNames. Exclusions are more targeted than disabling entire rule groups and are the preferred approach for handling false positives.
Firewall Policy Association
Find gateways with a linked firewall policy (newer policy-based WAF configuration model):
smartscapeNodes "AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS"
| parse azure.object, "JSON:azjson"
| fieldsAdd firewallPolicyId = azjson[configuration][properties][firewallPolicy][id],
wafEnabled = azjson[configuration][properties][webApplicationFirewallConfiguration][enabled]
| filter isNotNull(firewallPolicyId)
| fields name, firewallPolicyId, wafEnabled, azure.resource.group, azure.locationNote: Azure supports two WAF configuration models: inlinewebApplicationFirewallConfiguration(classic) and linkedfirewallPolicy(newer). When a firewall policy is linked, rule configuration and exclusions are managed on the policy resource rather than inline on the gateway. The queries above inspect inline configuration; policy-based WAF requires querying the policy resource separately.
API Management
List API Management services with configuration:
smartscapeNodes "AZURE_MICROSOFT_APIMANAGEMENT_SERVICE"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][sku][name],
skuCapacity = azjson[configuration][sku][capacity],
gatewayUrl = azjson[configuration][properties][gatewayUrl],
devPortalUrl = azjson[configuration][properties][developerPortalUrl],
vnetType = azjson[configuration][properties][virtualNetworkType],
platformVersion = azjson[configuration][properties][platformVersion]
| fields name, skuName, skuCapacity, gatewayUrl, devPortalUrl, vnetType, platformVersion,
azure.resource.group, azure.locationFind API Management policies and subscriptions:
smartscapeNodes "AZURE_MICROSOFT_APIMANAGEMENT_SERVICE_POLICIES",
"AZURE_MICROSOFT_APIMANAGEMENT_SERVICE_SUBSCRIPTIONS"
| fields type, name, id, azure.resource.groupSecurity & Networking
Identify public vs. internal load balancers (check frontend IP configuration for public IP association):
smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS"
| traverse "*", "AZURE_MICROSOFT_NETWORK_LOADBALANCERS_FRONTENDIPCONFIGURATIONS"
| fieldsAdd sourceId = dt.traverse.history[0][id]
| parse azure.object, "JSON:azjson"
| fieldsAdd publicIpId = azjson[configuration][properties][publicIPAddress][id],
privateIp = azjson[configuration][properties][privateIPAddress]
| lookup [smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS" | fields name, id], sourceField: sourceId, lookupField: id, prefix: "lb."
| fieldsAdd lbType = if(isNotNull(publicIpId), "Public", else: "Internal")
| fields lb.name, name, lbType, publicIpId, privateIpFind API Management services exposed without VNet integration:
smartscapeNodes "AZURE_MICROSOFT_APIMANAGEMENT_SERVICE"
| parse azure.object, "JSON:azjson"
| fieldsAdd vnetType = azjson[configuration][properties][virtualNetworkType]
| filter vnetType == "None"
| fields name, vnetType, azure.resource.group, azure.locationCross-Service Analysis
Count all load balancing and API resources by type:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS",
"AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS",
"AZURE_MICROSOFT_APIMANAGEMENT_SERVICE"
| summarize count = count(), by: {type}
| sort count descCount load balancing resources by region:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS",
"AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS",
"AZURE_MICROSOFT_APIMANAGEMENT_SERVICE"
| summarize count = count(), by: {type, azure.location}
| sort azure.location, count descFind all load balancing resources in a specific resource group:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_LOADBALANCERS",
"AZURE_MICROSOFT_NETWORK_APPLICATIONGATEWAYS",
"AZURE_MICROSOFT_APIMANAGEMENT_SERVICE"
| filter azure.resource.group == "<RESOURCE_GROUP>"
| fields type, name, azure.location, azure.provisioning_stateAzure Messaging & Integration
Monitor Azure Event Hubs, Service Bus, and messaging infrastructure.
Table of Contents
- Messaging & Integration Entity Types
- Event Hubs
- Service Bus
- Namespace Inventory
- Zone Redundancy
- TLS Configuration
- Public Network Access
- Topics
- Subscriptions
- Queue Configuration
- Namespace Traversals
- Dead-Letter Queue Detection
- Cross-Service Analysis
Messaging & Integration Entity Types
All these types support the standard discovery pattern: smartscapeNodes "<TYPE>" | fields name, id, azure.subscription, azure.resource.group, azure.location, ...
| Entity Type | Description |
|---|---|
AZURE_MICROSOFT_EVENTHUB_NAMESPACES | Event Hub namespaces |
AZURE_MICROSOFT_EVENTHUB_NAMESPACES_EVENTHUBS | Individual Event Hubs within a namespace |
AZURE_MICROSOFT_SERVICEBUS_NAMESPACES | Service Bus namespaces |
AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_QUEUES | Service Bus queues |
AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_TOPICS | Service Bus topics |
AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_TOPICS_SUBSCRIPTIONS | Service Bus subscriptions |
Event Hubs
Namespace Inventory
List all Event Hub namespaces with configuration:
smartscapeNodes "AZURE_MICROSOFT_EVENTHUB_NAMESPACES"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][sku][name],
skuTier = azjson[configuration][sku][tier],
skuCapacity = azjson[configuration][sku][capacity],
status = azjson[configuration][properties][status],
kafkaEnabled = azjson[configuration][properties][kafkaEnabled],
zoneRedundant = azjson[configuration][properties][zoneRedundant]
| fields name, skuName, skuTier, skuCapacity, status, kafkaEnabled, zoneRedundant,
azure.resource.group, azure.locationSummarize Event Hub namespaces by SKU tier:
smartscapeNodes "AZURE_MICROSOFT_EVENTHUB_NAMESPACES"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][sku][name]
| summarize ns_count = count(), by: {skuName}
| sort ns_count descKafka Enablement
Find Kafka-enabled Event Hub namespaces:
smartscapeNodes "AZURE_MICROSOFT_EVENTHUB_NAMESPACES"
| parse azure.object, "JSON:azjson"
| fieldsAdd kafkaEnabled = azjson[configuration][properties][kafkaEnabled],
skuName = azjson[configuration][sku][name]
| filter kafkaEnabled == true
| fields name, skuName, azure.resource.group, azure.locationThroughput Units and Auto-Inflate
Analyze throughput unit allocation and auto-inflate configuration:
smartscapeNodes "AZURE_MICROSOFT_EVENTHUB_NAMESPACES"
| parse azure.object, "JSON:azjson"
| fieldsAdd throughputUnits = azjson[configuration][sku][capacity],
autoInflate = azjson[configuration][properties][isAutoInflateEnabled],
maxThroughputUnits = azjson[configuration][properties][maximumThroughputUnits]
| fields name, throughputUnits, autoInflate, maxThroughputUnits,
azure.resource.group, azure.location
| sort throughputUnits descFind namespaces without auto-inflate (potential scaling risk):
smartscapeNodes "AZURE_MICROSOFT_EVENTHUB_NAMESPACES"
| parse azure.object, "JSON:azjson"
| fieldsAdd autoInflate = azjson[configuration][properties][isAutoInflateEnabled],
throughputUnits = azjson[configuration][sku][capacity]
| filter autoInflate == false
| fields name, throughputUnits, azure.resource.group, azure.locationZone Redundancy
Find Event Hub namespaces that are not zone-redundant:
smartscapeNodes "AZURE_MICROSOFT_EVENTHUB_NAMESPACES"
| parse azure.object, "JSON:azjson"
| fieldsAdd zoneRedundant = azjson[configuration][properties][zoneRedundant],
skuName = azjson[configuration][sku][name]
| filter zoneRedundant == false
| fields name, skuName, azure.resource.group, azure.locationTLS Configuration
Check minimum TLS version across Event Hub namespaces:
smartscapeNodes "AZURE_MICROSOFT_EVENTHUB_NAMESPACES"
| parse azure.object, "JSON:azjson"
| fieldsAdd minimumTlsVersion = azjson[configuration][properties][minimumTlsVersion]
| summarize ns_count = count(), by: {minimumTlsVersion}
| sort minimumTlsVersion descFind namespaces with TLS version below 1.2:
smartscapeNodes "AZURE_MICROSOFT_EVENTHUB_NAMESPACES"
| parse azure.object, "JSON:azjson"
| fieldsAdd minimumTlsVersion = azjson[configuration][properties][minimumTlsVersion]
| filter minimumTlsVersion != "1.2"
| fields name, minimumTlsVersion, azure.resource.group, azure.locationEvent Hub Entities
List all individual Event Hubs:
smartscapeNodes "AZURE_MICROSOFT_EVENTHUB_NAMESPACES_EVENTHUBS"
| fields name, id, azure.resource.group, azure.location, azure.provisioning_stateFind Event Hubs belonging to a specific namespace (Event Hub → Namespace backward traversal):
smartscapeNodes "AZURE_MICROSOFT_EVENTHUB_NAMESPACES"
| filter name == "<NAMESPACE_NAME>"
| traverse "*", "AZURE_MICROSOFT_EVENTHUB_NAMESPACES_EVENTHUBS", direction:backward
| fields name, id, azure.resource.groupCount Event Hubs per namespace:
smartscapeNodes "AZURE_MICROSOFT_EVENTHUB_NAMESPACES_EVENTHUBS"
| traverse "*", "AZURE_MICROSOFT_EVENTHUB_NAMESPACES"
| fieldsAdd namespaceName = name
| summarize eh_count = count(), by: {namespaceName}
| sort eh_count descService Bus
Namespace Inventory
List all Service Bus namespaces with configuration:
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][sku][name],
skuTier = azjson[configuration][sku][tier],
skuCapacity = azjson[configuration][sku][capacity],
status = azjson[configuration][properties][status],
zoneRedundant = azjson[configuration][properties][zoneRedundant],
minimumTlsVersion = azjson[configuration][properties][minimumTlsVersion],
disableLocalAuth = azjson[configuration][properties][disableLocalAuth]
| fields name, skuName, skuTier, skuCapacity, status, zoneRedundant, minimumTlsVersion, disableLocalAuth,
azure.resource.group, azure.locationSummarize Service Bus namespaces by SKU tier:
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][sku][name]
| summarize ns_count = count(), by: {skuName}
| sort ns_count descZone Redundancy
Find Service Bus namespaces that are not zone-redundant:
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES"
| parse azure.object, "JSON:azjson"
| fieldsAdd zoneRedundant = azjson[configuration][properties][zoneRedundant],
skuName = azjson[configuration][sku][name]
| filter zoneRedundant == false
| fields name, skuName, azure.resource.group, azure.locationTLS Configuration
Check minimum TLS version across Service Bus namespaces:
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES"
| parse azure.object, "JSON:azjson"
| fieldsAdd minimumTlsVersion = azjson[configuration][properties][minimumTlsVersion]
| summarize ns_count = count(), by: {minimumTlsVersion}
| sort minimumTlsVersion descFind namespaces with TLS version below 1.2:
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES"
| parse azure.object, "JSON:azjson"
| fieldsAdd minimumTlsVersion = azjson[configuration][properties][minimumTlsVersion]
| filter minimumTlsVersion != "1.2"
| fields name, minimumTlsVersion, azure.resource.group, azure.locationPublic Network Access
Find Service Bus namespaces with public network access enabled:
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES"
| parse azure.object, "JSON:azjson"
| fieldsAdd publicNetworkAccess = azjson[configuration][properties][publicNetworkAccess]
| filter publicNetworkAccess == "Enabled"
| fields name, publicNetworkAccess, azure.resource.group, azure.locationTopics
List all Service Bus topics:
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_TOPICS"
| fields name, id, azure.resource.group, azure.location, azure.provisioning_stateList topics with configuration details:
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_TOPICS"
| parse azure.object, "JSON:azjson"
| fieldsAdd maxSizeInMegabytes = azjson[configuration][properties][maxSizeInMegabytes],
status = azjson[configuration][properties][status],
enablePartitioning = azjson[configuration][properties][enablePartitioning],
requiresDuplicateDetection = azjson[configuration][properties][requiresDuplicateDetection]
| fields name, maxSizeInMegabytes, status, enablePartitioning, requiresDuplicateDetection,
azure.resource.group, azure.locationSubscriptions
List all Service Bus subscriptions:
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_TOPICS_SUBSCRIPTIONS"
| fields name, id, azure.resource.group, azure.location, azure.provisioning_stateList subscriptions with configuration details:
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_TOPICS_SUBSCRIPTIONS"
| parse azure.object, "JSON:azjson"
| fieldsAdd maxDeliveryCount = azjson[configuration][properties][maxDeliveryCount],
lockDuration = azjson[configuration][properties][lockDuration],
deadLetteringOnMessageExpiration = azjson[configuration][properties][deadLetteringOnMessageExpiration],
status = azjson[configuration][properties][status]
| fields name, maxDeliveryCount, lockDuration, deadLetteringOnMessageExpiration, status,
azure.resource.group, azure.locationQueue Configuration
List all Service Bus queues:
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_QUEUES"
| fields name, id, azure.resource.group, azure.location, azure.provisioning_stateList Service Bus queues with configuration:
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_QUEUES"
| parse azure.object, "JSON:azjson"
| fieldsAdd maxSizeInMegabytes = azjson[configuration][properties][maxSizeInMegabytes],
status = azjson[configuration][properties][status],
enablePartitioning = azjson[configuration][properties][enablePartitioning],
requiresDuplicateDetection = azjson[configuration][properties][requiresDuplicateDetection],
deadLetteringOnMessageExpiration = azjson[configuration][properties][deadLetteringOnMessageExpiration],
maxDeliveryCount = azjson[configuration][properties][maxDeliveryCount],
lockDuration = azjson[configuration][properties][lockDuration]
| fields name, maxSizeInMegabytes, status, enablePartitioning, requiresDuplicateDetection,
deadLetteringOnMessageExpiration, maxDeliveryCount, lockDuration,
azure.resource.group, azure.locationFind queues by name pattern:
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_QUEUES"
| filter contains(name, "<PATTERN>")
| fields name, id, azure.resource.group, azure.locationNamespace Traversals
Find queues belonging to a specific Service Bus namespace (Queue → Namespace backward traversal):
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES"
| filter name == "<NAMESPACE_NAME>"
| traverse "*", "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_QUEUES", direction:backward
| fields name, id, azure.resource.groupFind topics belonging to a specific Service Bus namespace (Topic → Namespace backward traversal):
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES"
| filter name == "<NAMESPACE_NAME>"
| traverse "*", "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_TOPICS", direction:backward
| fields name, id, azure.resource.groupCount queues per namespace:
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_QUEUES"
| traverse "*", "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES"
| fieldsAdd namespaceName = name
| summarize queue_count = count(), by: {namespaceName}
| sort queue_count descCount topics per namespace:
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_TOPICS"
| traverse "*", "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES"
| fieldsAdd namespaceName = name
| summarize topic_count = count(), by: {namespaceName}
| sort topic_count descCount subscriptions per topic:
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_TOPICS_SUBSCRIPTIONS"
| traverse "*", "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_TOPICS"
| fieldsAdd topicName = name
| summarize subscription_count = count(), by: {topicName}
| sort subscription_count descDead-Letter Queue Detection
Find queues with dead-lettering on message expiration enabled:
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_QUEUES"
| parse azure.object, "JSON:azjson"
| fieldsAdd deadLetteringOnMessageExpiration = azjson[configuration][properties][deadLetteringOnMessageExpiration]
| filter deadLetteringOnMessageExpiration == true
| fields name, azure.resource.group, azure.locationFind subscriptions with dead-lettering on message expiration enabled:
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_TOPICS_SUBSCRIPTIONS"
| parse azure.object, "JSON:azjson"
| fieldsAdd deadLetteringOnMessageExpiration = azjson[configuration][properties][deadLetteringOnMessageExpiration]
| filter deadLetteringOnMessageExpiration == true
| fields name, azure.resource.group, azure.locationFind queues with low max delivery count (messages reach dead-letter faster):
smartscapeNodes "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_QUEUES"
| parse azure.object, "JSON:azjson"
| fieldsAdd maxDeliveryCount = azjson[configuration][properties][maxDeliveryCount],
deadLetteringOnMessageExpiration = azjson[configuration][properties][deadLetteringOnMessageExpiration]
| filter maxDeliveryCount <= 3
| fields name, maxDeliveryCount, deadLetteringOnMessageExpiration, azure.resource.group, azure.locationCross-Service Analysis
Count all messaging resources by type:
smartscapeNodes "AZURE_MICROSOFT_EVENTHUB_NAMESPACES", "AZURE_MICROSOFT_EVENTHUB_NAMESPACES_EVENTHUBS",
"AZURE_MICROSOFT_SERVICEBUS_NAMESPACES", "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_QUEUES",
"AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_TOPICS", "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_TOPICS_SUBSCRIPTIONS"
| summarize total = count(), by: {type}
| sort total descCount messaging resources by region:
smartscapeNodes "AZURE_MICROSOFT_EVENTHUB_NAMESPACES", "AZURE_MICROSOFT_EVENTHUB_NAMESPACES_EVENTHUBS",
"AZURE_MICROSOFT_SERVICEBUS_NAMESPACES", "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_QUEUES",
"AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_TOPICS", "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES_TOPICS_SUBSCRIPTIONS"
| summarize total = count(), by: {type, azure.location}
| sort azure.location, total descFilter messaging resources to a specific subscription:
smartscapeNodes "AZURE_MICROSOFT_EVENTHUB_NAMESPACES", "AZURE_MICROSOFT_SERVICEBUS_NAMESPACES"
| filter azure.subscription == "<SUBSCRIPTION_ID>"
| fields type, name, azure.resource.group, azure.locationAzure Metrics & Performance
DQL timeseries patterns for Azure Monitor-sourced metrics. Use during investigation to determine whether a resource is saturated, erroring, or slow.
Table of Contents
- Query Template
- VM Metrics
- Azure SQL Metrics
- Storage Account Metrics
- Event Hub Metrics
- Service Bus Metrics
- Load Balancer Metrics
- App Service / Functions Metrics
- AKS (Managed Cluster) Metrics
- Cosmos DB Metrics
- Redis Cache Metrics
- Application Gateway Metrics
- Combining Entity Queries with Metrics
- Metric Availability Note
Query Template
Azure metrics in Dynatrace follow the naming convention:
cloud.azure.<resource_provider_path>.<MetricName>Where <resource_provider_path> is <provider_namespace>.<resource_type> (lowercase, dots separating hierarchy levels):
| Resource provider path | Service |
|---|---|
microsoft_compute.virtualmachines | Virtual Machines |
microsoft_sql.servers.databases | Azure SQL Databases |
microsoft_storage.storageaccounts | Storage Accounts |
microsoft_network.loadbalancers | Load Balancers |
microsoft_eventhub.namespaces | Event Hub Namespaces |
microsoft_servicebus.namespaces | Service Bus Namespaces |
microsoft_web.sites | App Service / Functions |
microsoft_containerservice.managedclusters | AKS Managed Clusters |
microsoft_documentdb.databaseaccounts | Cosmos DB Accounts |
microsoft_cache.redis | Redis Cache |
microsoft_cache.redisenterprise | Redis Enterprise |
microsoft_network.applicationgateways | Application Gateways |
The dt.smartscape_source.id dimension splits results by Dynatrace entity. Use it in the by: clause and filter to scope metrics to a specific resource.
timeseries cpu = avg(cloud.azure.microsoft_compute.virtualmachines.<METRIC_NAME>),
by: { dt.smartscape_source.id },
from: <PROBLEM_START - 30m>, to: <PROBLEM_END + 15m>
| filter dt.smartscape_source.id == toSmartscapeId("<ROOT_CAUSE_ENTITY_ID>")Replace <METRIC_NAME> with the metric from the tables below, and <ROOT_CAUSE_ENTITY_ID> with the Dynatrace entity ID (e.g., AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINES-2B0D33F11CE649F4). Omit the | filter clause to get all instances of that metric.
Time windows: The template above uses<PROBLEM_START>and<PROBLEM_END>for scoping queries to a specific incident window. The per-service examples below usefrom: now()-1hfor simplicity — substitute your incident timestamps when investigating a specific problem.
---
VM Metrics
| Metric key | Description | Unit | Investigation threshold |
|---|---|---|---|
cloud.azure.microsoft_compute.virtualmachines.PercentageCPU | CPU utilization | % | > 85% sustained |
cloud.azure.microsoft_compute.virtualmachines.AvailableMemoryBytes | Available memory | Bytes | Trending toward 0 |
cloud.azure.microsoft_compute.virtualmachines.DiskReadBytes | Disk read throughput | Bytes/sec | Spike vs baseline |
cloud.azure.microsoft_compute.virtualmachines.DiskWriteBytes | Disk write throughput | Bytes/sec | Spike vs baseline |
cloud.azure.microsoft_compute.virtualmachines.NetworkInTotal | Inbound network traffic | Bytes | Spike or drop vs baseline |
cloud.azure.microsoft_compute.virtualmachines.NetworkOutTotal | Outbound network traffic | Bytes | Spike or drop vs baseline |
Check CPU utilization for a specific VM:
timeseries cpu = avg(cloud.azure.microsoft_compute.virtualmachines.PercentageCPU),
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<ROOT_CAUSE_ENTITY_ID>")Check available memory (low values indicate memory pressure):
timeseries mem = avg(cloud.azure.microsoft_compute.virtualmachines.AvailableMemoryBytes),
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<ROOT_CAUSE_ENTITY_ID>")---
Azure SQL Metrics
| Metric key | Description | Unit | Investigation threshold |
|---|---|---|---|
cloud.azure.microsoft_sql.servers.databases.cpu_percent | Database CPU utilization | % | > 85% sustained |
cloud.azure.microsoft_sql.servers.databases.dtu_consumption_percent | DTU consumption percentage | % | > 90% sustained |
cloud.azure.microsoft_sql.servers.databases.storage_percent | Storage space used | % | > 85% (plan expansion) |
cloud.azure.microsoft_sql.servers.databases.deadlock | Deadlock count | Count | > 0 during incident |
cloud.azure.microsoft_sql.servers.databases.connection_failed | Failed connections | Count | > 0 during incident |
Check CPU and DTU consumption for a specific SQL database:
timeseries { cpu = avg(cloud.azure.microsoft_sql.servers.databases.cpu_percent),
dtu = avg(cloud.azure.microsoft_sql.servers.databases.dtu_consumption_percent) },
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<SQL_DB_ENTITY_ID>")Check storage percentage and deadlocks:
timeseries { storage = avg(cloud.azure.microsoft_sql.servers.databases.storage_percent),
deadlocks = sum(cloud.azure.microsoft_sql.servers.databases.deadlock) },
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<SQL_DB_ENTITY_ID>")---
Storage Account Metrics
| Metric key | Description | Unit | Investigation threshold |
|---|---|---|---|
cloud.azure.microsoft_storage.storageaccounts.UsedCapacity | Total storage used | Bytes | Trending toward account limit |
cloud.azure.microsoft_storage.storageaccounts.Ingress | Data ingress | Bytes | Spike vs baseline |
cloud.azure.microsoft_storage.storageaccounts.Egress | Data egress | Bytes | Spike vs baseline (cost impact) |
cloud.azure.microsoft_storage.storageaccounts.Transactions | Transaction count | Count | Spike vs baseline |
cloud.azure.microsoft_storage.storageaccounts.Availability | Service availability | % | < 100% indicates issues |
Check ingress, egress, and transactions for a storage account:
timeseries { ingress = sum(cloud.azure.microsoft_storage.storageaccounts.Ingress),
egress = sum(cloud.azure.microsoft_storage.storageaccounts.Egress),
txn = sum(cloud.azure.microsoft_storage.storageaccounts.Transactions) },
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<STORAGE_ENTITY_ID>")Check availability:
timeseries avail = avg(cloud.azure.microsoft_storage.storageaccounts.Availability),
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<STORAGE_ENTITY_ID>")---
Event Hub Metrics
| Metric key | Description | Unit | Investigation threshold |
|---|---|---|---|
cloud.azure.microsoft_eventhub.namespaces.IncomingMessages | Messages received | Count | Drop vs baseline (upstream issue) |
cloud.azure.microsoft_eventhub.namespaces.OutgoingMessages | Messages delivered | Count | Drop vs baseline (consumer issue) |
cloud.azure.microsoft_eventhub.namespaces.IncomingBytes | Ingress bytes | Bytes | Near throughput unit limit |
cloud.azure.microsoft_eventhub.namespaces.ThrottledRequests | Throttled requests | Count | > 0 (throughput limit hit) |
Check message flow and throttling:
timeseries { incoming = sum(cloud.azure.microsoft_eventhub.namespaces.IncomingMessages),
outgoing = sum(cloud.azure.microsoft_eventhub.namespaces.OutgoingMessages),
throttled = sum(cloud.azure.microsoft_eventhub.namespaces.ThrottledRequests) },
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<EVENTHUB_ENTITY_ID>")---
Service Bus Metrics
| Metric key | Description | Unit | Investigation threshold |
|---|---|---|---|
cloud.azure.microsoft_servicebus.namespaces.IncomingMessages | Messages received | Count | Drop vs baseline (upstream issue) |
cloud.azure.microsoft_servicebus.namespaces.OutgoingMessages | Messages delivered | Count | Drop vs baseline (consumer issue) |
cloud.azure.microsoft_servicebus.namespaces.IncomingRequests | Total incoming requests | Count | Spike vs baseline |
cloud.azure.microsoft_servicebus.namespaces.SuccessfulRequests | Successful requests | Count | Drop vs baseline |
cloud.azure.microsoft_servicebus.namespaces.ServerErrors | Server errors (5xx) | Count | > 0 during incident |
cloud.azure.microsoft_servicebus.namespaces.UserErrors | User errors (4xx) | Count | Spike vs baseline (bad messages) |
cloud.azure.microsoft_servicebus.namespaces.ThrottledRequests | Throttled requests | Count | > 0 (throughput limit hit) |
cloud.azure.microsoft_servicebus.namespaces.ActiveMessages | Active messages in queue/topic | Count | Growing backlog |
cloud.azure.microsoft_servicebus.namespaces.DeadletteredMessages | Dead-lettered messages | Count | > 0 (poison messages) |
cloud.azure.microsoft_servicebus.namespaces.ScheduledMessages | Scheduled messages | Count | Context-dependent |
cloud.azure.microsoft_servicebus.namespaces.Size | Size of queue/topic in bytes | Bytes | Near max size |
Check message flow and throttling:
timeseries { incoming = sum(cloud.azure.microsoft_servicebus.namespaces.IncomingMessages),
outgoing = sum(cloud.azure.microsoft_servicebus.namespaces.OutgoingMessages),
throttled = sum(cloud.azure.microsoft_servicebus.namespaces.ThrottledRequests) },
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<SERVICEBUS_ENTITY_ID>")Check dead-letter accumulation:
timeseries { deadLettered = sum(cloud.azure.microsoft_servicebus.namespaces.DeadletteredMessages),
active = sum(cloud.azure.microsoft_servicebus.namespaces.ActiveMessages) },
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<SERVICEBUS_ENTITY_ID>")Check server and user errors:
timeseries { serverErrors = sum(cloud.azure.microsoft_servicebus.namespaces.ServerErrors),
userErrors = sum(cloud.azure.microsoft_servicebus.namespaces.UserErrors),
requests = sum(cloud.azure.microsoft_servicebus.namespaces.IncomingRequests) },
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<SERVICEBUS_ENTITY_ID>")Important: Non-zero DeadletteredMessages indicates poison messages that failed processing. Cross-reference with the dead-letter analysis queries in messaging-integration.md to identify root causes.---
Load Balancer Metrics
| Metric key | Description | Unit | Investigation threshold |
|---|---|---|---|
cloud.azure.microsoft_network.loadbalancers.ByteCount | Bytes processed | Bytes | Near throughput limit |
cloud.azure.microsoft_network.loadbalancers.PacketCount | Packets processed | Count | Spike vs baseline |
cloud.azure.microsoft_network.loadbalancers.DipAvailability | Backend pool health (data path) | % | < 100% (unhealthy backends) |
cloud.azure.microsoft_network.loadbalancers.VipAvailability | Frontend data path availability | % | < 100% (frontend issues) |
Check backend health and traffic for a load balancer:
timeseries { dipHealth = avg(cloud.azure.microsoft_network.loadbalancers.DipAvailability),
bytes = sum(cloud.azure.microsoft_network.loadbalancers.ByteCount) },
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<LB_ENTITY_ID>")Important: A DipAvailability below 100% indicates one or more backend instances are failing health probes. Cross-reference with VM metrics to identify the unhealthy instance.---
App Service / Functions Metrics
| Metric key | Description | Unit | Investigation threshold |
|---|---|---|---|
cloud.azure.microsoft_web.sites.HttpResponseTime | Average HTTP response time | Seconds | > p99 baseline |
cloud.azure.microsoft_web.sites.Requests | Total HTTP requests | Count | Drop vs baseline |
cloud.azure.microsoft_web.sites.Http5xx | 5xx server error responses | Count | > 0 during incident |
cloud.azure.microsoft_web.sites.FunctionExecutionCount | Function execution count | Count | Drop vs baseline |
cloud.azure.microsoft_web.sites.FunctionExecutionUnits | Function execution units | MB-ms | Spike vs baseline |
Check response time and errors for an App Service:
timeseries { responseTime = avg(cloud.azure.microsoft_web.sites.HttpResponseTime),
errors = sum(cloud.azure.microsoft_web.sites.Http5xx),
requests = sum(cloud.azure.microsoft_web.sites.Requests) },
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<APP_SERVICE_ENTITY_ID>")Check Function execution metrics:
timeseries { executions = sum(cloud.azure.microsoft_web.sites.FunctionExecutionCount),
units = sum(cloud.azure.microsoft_web.sites.FunctionExecutionUnits) },
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<FUNCTION_ENTITY_ID>")---
AKS (Managed Cluster) Metrics
AKS infrastructure-layer metrics cover API server, etcd, and node-level resource usage. For workload-level observability (pods, deployments, services), defer to dt-obs-kubernetes.
| Metric key | Description | Unit | Investigation threshold |
|---|---|---|---|
cloud.azure.microsoft_containerservice.managedclusters.apiserver_cpu_usage_percentage | API server CPU | % | > 80% sustained |
cloud.azure.microsoft_containerservice.managedclusters.apiserver_memory_usage_percentage | API server memory | % | > 80% sustained |
cloud.azure.microsoft_containerservice.managedclusters.etcd_database_usage_percentage | etcd storage usage | % | > 80% (risk of cluster instability) |
cloud.azure.microsoft_containerservice.managedclusters.node_cpu_usage_percentage | Node CPU usage | % | > 85% sustained |
cloud.azure.microsoft_containerservice.managedclusters.node_memory_working_set_percentage | Node memory working set | % | > 85% sustained |
cloud.azure.microsoft_containerservice.managedclusters.node_disk_usage_percentage | Node disk usage | % | > 85% (eviction risk) |
cloud.azure.microsoft_containerservice.managedclusters.kube_node_status_condition | Node readiness status | Status | Not-ready nodes |
cloud.azure.microsoft_containerservice.managedclusters.kube_pod_status_ready | Pod readiness | Status | Drop vs baseline |
Check API server and etcd health for an AKS cluster:
timeseries { apiCpu = avg(cloud.azure.microsoft_containerservice.managedclusters.apiserver_cpu_usage_percentage),
etcd = avg(cloud.azure.microsoft_containerservice.managedclusters.etcd_database_usage_percentage) },
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<AKS_ENTITY_ID>")Check node resource pressure:
timeseries { nodeCpu = avg(cloud.azure.microsoft_containerservice.managedclusters.node_cpu_usage_percentage),
nodeMem = avg(cloud.azure.microsoft_containerservice.managedclusters.node_memory_working_set_percentage),
nodeDisk = avg(cloud.azure.microsoft_containerservice.managedclusters.node_disk_usage_percentage) },
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<AKS_ENTITY_ID>")---
Cosmos DB Metrics
| Metric key | Description | Unit | Investigation threshold |
|---|---|---|---|
cloud.azure.microsoft_documentdb.databaseaccounts.TotalRequestUnits | RU consumption | RU/s | Near provisioned limit |
cloud.azure.microsoft_documentdb.databaseaccounts.TotalRequests | Total requests | Count | Drop vs baseline |
cloud.azure.microsoft_documentdb.databaseaccounts.ServerSideLatency | Server-side latency | ms | > p99 baseline |
cloud.azure.microsoft_documentdb.databaseaccounts.ServiceAvailability | Service availability | % | < 100% |
cloud.azure.microsoft_documentdb.databaseaccounts.DataUsage | Data storage used | Bytes | Near partition limit |
cloud.azure.microsoft_documentdb.databaseaccounts.DocumentCount | Document count | Count | Trending toward partition limit |
Check RU consumption and latency for a Cosmos DB account:
timeseries { ru = sum(cloud.azure.microsoft_documentdb.databaseaccounts.TotalRequestUnits),
latency = avg(cloud.azure.microsoft_documentdb.databaseaccounts.ServerSideLatency) },
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<COSMOSDB_ENTITY_ID>")Check availability:
timeseries avail = avg(cloud.azure.microsoft_documentdb.databaseaccounts.ServiceAvailability),
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<COSMOSDB_ENTITY_ID>")Important: ATotalRequestUnitsvalue near the provisioned RU limit means the account is at risk of 429 (throttled) responses. Cross-reference withTotalRequeststo check if request volume is spiking.
---
Redis Cache Metrics
| Metric key | Description | Unit | Investigation threshold |
|---|---|---|---|
cloud.azure.microsoft_cache.redis.serverLoad | Server CPU load | % | > 80% sustained |
cloud.azure.microsoft_cache.redis.usedmemorypercentage | Memory usage | % | > 85% (eviction risk) |
cloud.azure.microsoft_cache.redis.cachehits | Cache hits | Count | Drop vs baseline |
cloud.azure.microsoft_cache.redis.cachemisses | Cache misses | Count | Spike vs baseline |
cloud.azure.microsoft_cache.redis.cachemissrate | Cache miss rate | % | Sustained increase |
cloud.azure.microsoft_cache.redis.connectedclients | Connected clients | Count | Near maxclients limit |
cloud.azure.microsoft_cache.redis.evictedkeys | Evicted keys | Count | > 0 (memory pressure) |
cloud.azure.microsoft_cache.redis.cacheLatency | Operation latency | ms | > p99 baseline |
cloud.azure.microsoft_cache.redis.errors | Error count | Count | > 0 during incident |
cloud.azure.microsoft_cache.redis.totalcommandsprocessed | Commands processed | Count/s | Drop vs baseline |
Check server load and memory for a Redis instance:
timeseries { load = avg(cloud.azure.microsoft_cache.redis.serverLoad),
mem = avg(cloud.azure.microsoft_cache.redis.usedmemorypercentage) },
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<REDIS_ENTITY_ID>")Check hit/miss ratio and evictions:
timeseries { hits = sum(cloud.azure.microsoft_cache.redis.cachehits),
misses = sum(cloud.azure.microsoft_cache.redis.cachemisses),
evictions = sum(cloud.azure.microsoft_cache.redis.evictedkeys) },
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<REDIS_ENTITY_ID>")Note: Redis Enterprise metrics use themicrosoft_cache.redisenterprisepath with the same metric names. Replacerediswithredisenterprisein the metric key. Thedt.smartscape_source.iddimension works for all entity types.
---
Application Gateway Metrics
| Metric key | Description | Unit | Investigation threshold |
|---|---|---|---|
cloud.azure.microsoft_network.applicationgateways.TotalRequests | Total requests | Count | Drop vs baseline |
cloud.azure.microsoft_network.applicationgateways.FailedRequests | Failed requests | Count | > 0 during incident |
cloud.azure.microsoft_network.applicationgateways.Throughput | Data throughput | Bytes/sec | Near SKU limit |
cloud.azure.microsoft_network.applicationgateways.CurrentConnections | Active connections | Count | Near connection limit |
cloud.azure.microsoft_network.applicationgateways.HealthyHostCount | Healthy backend hosts | Count | Decrease from baseline |
cloud.azure.microsoft_network.applicationgateways.UnhealthyHostCount | Unhealthy backend hosts | Count | > 0 (backend failure) |
cloud.azure.microsoft_network.applicationgateways.WebApplicationFirewallBlockedRequests | WAF blocked request count | Count | > 0 (active blocking) |
cloud.azure.microsoft_network.applicationgateways.WebApplicationFirewallMatchedRequests | WAF matched (triggered) request count | Count | Spike vs baseline (possible false positives) |
cloud.azure.microsoft_network.applicationgateways.WebApplicationFirewallTotalRuleDistribution | WAF rule hit distribution | Count | Identifies which rules trigger most |
cloud.azure.microsoft_network.applicationgateways.WebApplicationFirewallManagedRuleDistribution | WAF managed rule hit distribution | Count | Identifies managed rules triggering |
Check request volume and errors for an Application Gateway:
timeseries { requests = sum(cloud.azure.microsoft_network.applicationgateways.TotalRequests),
failures = sum(cloud.azure.microsoft_network.applicationgateways.FailedRequests) },
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<APPGW_ENTITY_ID>")Check backend pool health:
timeseries { healthy = avg(cloud.azure.microsoft_network.applicationgateways.HealthyHostCount),
unhealthy = avg(cloud.azure.microsoft_network.applicationgateways.UnhealthyHostCount) },
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<APPGW_ENTITY_ID>")Important: An UnhealthyHostCount > 0 means backend VMs or containers are failing health probes. Cross-reference with the backend resource metrics (VM, App Service) to identify the root cause.Check WAF blocked and matched requests during an incident (spikes in matched requests with user-reported issues indicate false positives):
timeseries { blocked = sum(cloud.azure.microsoft_network.applicationgateways.WebApplicationFirewallBlockedRequests),
matched = sum(cloud.azure.microsoft_network.applicationgateways.WebApplicationFirewallMatchedRequests) },
by: { dt.smartscape_source.id },
from: now()-1h
| filter dt.smartscape_source.id == toSmartscapeId("<APPGW_ENTITY_ID>")Investigation tip: A spike in WebApplicationFirewallMatchedRequests correlated with user-reported 403 errors strongly suggests a false positive. Cross-reference with the disabled rule groups and exclusions in load-balancing-api.md to identify which rules are triggering and whether they should be tuned.---
Combining Entity Queries with Metrics
Find a set of entities by filter, then query metrics for all of them. Example: are all VMs in a resource group experiencing high CPU, or just one?
Step 1 — Find resource IDs for the group:
smartscapeNodes "AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINES"
| filter azure.resource.group == "<RESOURCE_GROUP>"
| fields name, idStep 2 — Query metrics for all VMs (no filter = all series):
timeseries cpu = avg(cloud.azure.microsoft_compute.virtualmachines.PercentageCPU),
by: { dt.smartscape_source.id },
from: now()-1hCross-reference the dt.smartscape_source.id dimension values against the entity IDs from Step 1 to identify which VMs in the resource group are affected.
---
Metric Availability Note
Azure metrics are only available when Azure Monitor integration is enabled and configured for the relevant services in Dynatrace (Settings > Cloud and Virtualization > Azure). If a timeseries query returns no data:
1. Verify the entity exists: run the corresponding smartscapeNodes query 2. Confirm the Azure Monitor integration is configured and metric ingestion is enabled for this service 3. Check the metric name matches the naming convention: cloud.azure.<resource_provider_path>.<MetricName>
Do not interpret empty timeseries results as "no problem" — it may mean the metric is not configured for this resource type.
Note: All metric keys documented here were verified against a live Dynatrace tenant with Azure Monitor integration enabled. If a metric key is not found in your environment, confirm Azure Monitor integration is configured for that service in Settings > Cloud and Virtualization > Azure.
Azure Skill References
Detailed Azure-specific reference documentation organized by use case category.
Reference Files
- [vnet-networking-security.md](vnet-networking-security.md) — VNet infrastructure, NSGs, subnets, public IPs, VPN gateways, and network connectivity
- [database-monitoring.md](database-monitoring.md) — Azure SQL, Cosmos DB, Redis Cache monitoring and configuration analysis
- [serverless-containers.md](serverless-containers.md) — Functions, App Service, AKS infrastructure layer, Container Apps
- [load-balancing-api.md](load-balancing-api.md) — Azure Load Balancers, Application Gateways, API Management
- [messaging-integration.md](messaging-integration.md) — Event Hubs, Service Bus, Event Grid
- [storage-monitoring.md](storage-monitoring.md) — Storage Accounts (blob, file, queue, table) and managed disks
- [resource-management.md](resource-management.md) — Resource inventory, tag compliance, unattached resources, and lifecycle management
- [cost-optimization.md](cost-optimization.md) — Cost savings, SKU analysis, unused resources
- [capacity-planning.md](capacity-planning.md) — VMSS scaling, subnet utilization, and capacity analysis
- [security-compliance.md](security-compliance.md) — NSG rule analysis, Key Vault, encryption status, and public resource detection
- [resource-ownership.md](resource-ownership.md) — Cost allocation, chargeback, team-based grouping, and ownership tracking
- [workload-detection.md](workload-detection.md) — Identify how a VM is orchestrated (AKS node, VMSS member, standalone)
- [metrics-performance.md](metrics-performance.md) — DQL timeseries patterns for Azure VM, SQL, Storage, Event Hub metrics
Usage
These reference files provide detailed DQL query patterns and examples for specific Azure use cases. Load them as needed based on your monitoring requirements.
Azure Resource Management & Optimization
Analyze Azure resource usage, identify optimization opportunities, and manage resource tagging across subscriptions and resource groups.
Table of Contents
- Resource Inventory
- Tag Compliance
- Resource Lifecycle
- Regional & Resource Group Distribution
- Storage & Security Resources
Resource Inventory
Count all Azure resources by type:
smartscapeNodes "AZURE_*"
| summarize resource_count = count(), by: {type}
| sort resource_count descView resource distribution across subscriptions:
smartscapeNodes "AZURE_*"
| summarize resource_count = count(), by: {azure.subscription, azure.location}
| sort resource_count descFind resource types spanning multiple regions:
smartscapeNodes "AZURE_*"
| summarize
region_count = countDistinct(azure.location),
total_resources = count(),
by: {type}
| filter region_count > 1
| sort region_count descTag Compliance
Find completely untagged resources:
smartscapeNodes "AZURE_*"
| filter isNull(tags)
| fields type, name, id, azure.subscription, azure.resource.group, azure.locationFind resources missing a specific required tag:
smartscapeNodes "AZURE_*"
| filter isNull(tags[`<TAG_NAME>`]) or tags[`<TAG_NAME>`] == ""
| summarize count = count(), by: {type, azure.subscription}Calculate tag coverage percentages across resource types:
smartscapeNodes "AZURE_*"
| fieldsAdd has_owner_tag = if(isNotNull(tags[`dt_owner_email`]), 1)
| fieldsAdd has_env_tag = if(isNotNull(tags[`Environment`]), 1)
| summarize
total = count(),
with_env = sum(has_env_tag),
with_owner = sum(has_owner_tag),
by: { type }
| fieldsAdd
env_coverage_pct = (with_env * 100.0) / total,
owner_coverage_pct = (with_owner * 100.0) / total
| sort env_coverage_pct ascFind resources by tag value:
smartscapeNodes "AZURE_*"
| filter tags[`<TAG_NAME>`] == "<TAG_VALUE>"
| summarize count = count(), by: {type, azure.location}Find resources by naming convention:
smartscapeNodes "AZURE_*"
| filter matchesPhrase(name, "<SEARCH_TERM>")
| fields type, name, id, azure.location, azure.resource.group, tags[`Environment`]Resource Lifecycle
Detect deleted resources:
smartscapeNodes "AZURE_*"
| filter cloud.acquisitionStatus == "DELETED"
| fields type, name, id, azure.subscription, azure.resource.group, azure.locationFind resources with acquisition issues:
smartscapeNodes "AZURE_*"
| filter cloud.acquisitionStatus != "OK"
| fields type, name, id, cloud.acquisitionStatus, azure.subscriptionFind unattached managed disks:
smartscapeNodes "AZURE_MICROSOFT_COMPUTE_DISKS"
| parse azure.object, "JSON:azjson"
| fieldsAdd diskState = azjson[configuration][properties][diskState]
| filter diskState == "Unattached"
| fields name, id, azure.resource.group, azure.location, azure.subscriptionFind unassociated public IPs:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_PUBLICIPADDRESSES"
| parse azure.object, "JSON:azjson"
| fieldsAdd ipConfig = azjson[configuration][properties][ipConfiguration]
| filter isNull(ipConfig)
| fields name, id, azure.resource.group, azure.location, azure.subscriptionRegional & Resource Group Distribution
View resources by region:
smartscapeNodes "AZURE_*"
| summarize resource_count = count(), by: {azure.location}
| sort resource_count descCount resources per resource group:
smartscapeNodes "AZURE_*"
| summarize resource_count = count(), by: {azure.resource.group, type}
| sort resource_count descStorage & Security Resources
Count storage services:
smartscapeNodes "AZURE_MICROSOFT_STORAGE_STORAGEACCOUNTS",
"AZURE_MICROSOFT_COMPUTE_DISKS",
"AZURE_MICROSOFT_STORAGE_STORAGEACCOUNTS_BLOBSERVICES_CONTAINERS"
| summarize count = count(), by: {type, azure.location}
| sort count descCount security resources:
smartscapeNodes "AZURE_MICROSOFT_NETWORK_NETWORKSECURITYGROUPS",
"AZURE_MICROSOFT_KEYVAULT_VAULTS",
"AZURE_MICROSOFT_MANAGEDIDENTITY_USERASSIGNEDIDENTITIES"
| summarize count = count(), by: {type}
| sort count descList storage accounts:
smartscapeNodes "AZURE_MICROSOFT_STORAGE_STORAGEACCOUNTS"
| fields name, azure.subscription, azure.resource.group, azure.location, idList managed disks:
smartscapeNodes "AZURE_MICROSOFT_COMPUTE_DISKS"
| fields name, id, azure.resource.group, azure.location, azure.subscriptionAzure Resource Ownership & Chargeback
Track resource ownership and enable cost allocation across teams using Azure resource tags, subscriptions, and resource groups.
Table of Contents
- Tag-Based Ownership Pattern
- Common Ownership Tags
- Service-Specific Ownership
- Multi-Subscription Resource Summary
Tag-Based Ownership Pattern
All ownership queries follow the same pattern — filter by a tag, then summarize by that tag and a grouping dimension:
smartscapeNodes "AZURE_*"
| filter isNotNull(tags[`<TAG_NAME>`])
| summarize resource_count = count(), by: {tags[`<TAG_NAME>`], type}
| sort resource_count descReplace <TAG_NAME> with any tag from the table below. Replace type with azure.location, azure.subscription, or azure.resource.group for alternative groupings. Replace "AZURE_*" with a specific entity type to scope to one service.
Common Ownership Tags
| Tag | Use case | Typical values |
|---|---|---|
dt_owner_email | Individual accountability | Email address |
dt_owner_team | Team-level allocation | Team names |
ACE:CREATED-BY | Resource creator tracking | Email address |
project | Project-based grouping | Project identifiers (e.g., azure-demo) |
managed-by | Management tool tracking | Tool names (e.g., dynatrace) |
CostCenter | Financial chargeback | Cost center codes |
Environment | Environment segmentation | production, staging, dev |
Service-Specific Ownership
To scope ownership queries to a specific Azure service, replace "AZURE_*" with the entity type:
| Entity type | Example use case |
|---|---|
AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINES | VM costs by department/team |
AZURE_MICROSOFT_WEB_SITES | App Service / Functions costs by application |
AZURE_MICROSOFT_SQL_SERVERS_DATABASES | Database ownership tracking |
AZURE_MICROSOFT_CONTAINERSERVICE_MANAGEDCLUSTERS | AKS cluster ownership by business unit |
AZURE_MICROSOFT_COMPUTE_DISKS | Disk costs by project |
AZURE_MICROSOFT_STORAGE_STORAGEACCOUNTS | Storage account ownership by team |
AZURE_MICROSOFT_APP_CONTAINERAPPS | Container App ownership by team |
For service-specific queries, you can also select detail fields instead of summarizing:
smartscapeNodes "AZURE_MICROSOFT_SQL_SERVERS_DATABASES"
| filter isNotNull(tags[`dt_owner_email`])
| fields name, id, tags[`dt_owner_email`], azure.resource.group, azure.locationOwnership by resource group (useful when tags are not consistently applied):
smartscapeNodes "AZURE_*"
| summarize resource_count = count(), by: {azure.resource.group, type}
| sort resource_count desc
| limit 50Multi-Subscription Resource Summary
Summarize resources across subscriptions (independent of tags):
smartscapeNodes "AZURE_*"
| summarize resource_count = count(), by: {azure.subscription, type}
| sort resource_count desc
| limit 50Summarize resources by subscription and resource group:
smartscapeNodes "AZURE_*"
| summarize resource_count = count(), by: {azure.subscription, azure.resource.group}
| sort resource_count desc
| limit 50Azure Serverless & Container Workloads
Monitor Azure Functions, App Service, AKS infrastructure layer, and Container Apps.
Table of Contents
- Serverless & Container Entity Types
- Azure Functions Monitoring
- App Service Monitoring
- AKS Infrastructure Monitoring
- Container Apps
- Cross-Service Analysis
Serverless & Container Entity Types
All these types support the standard discovery pattern: smartscapeNodes "<TYPE>" | fields name, id, azure.subscription, azure.resource.group, azure.location, ...
| Entity Type | Description |
|---|---|
AZURE_MICROSOFT_WEB_SITES | App Service and Function Apps (differentiate via kind) |
AZURE_MICROSOFT_WEB_SERVERFARMS | App Service Plans |
AZURE_MICROSOFT_WEB_SITES_FUNCTIONS | Individual functions within a Function App |
AZURE_MICROSOFT_CONTAINERSERVICE_MANAGEDCLUSTERS | AKS clusters |
AZURE_MICROSOFT_CONTAINERSERVICE_MANAGEDCLUSTERS_AGENTPOOLS | AKS agent pools |
AZURE_MICROSOFT_CONTAINERREGISTRY_REGISTRIES | Azure Container Registry |
AZURE_MICROSOFT_APP_CONTAINERAPPS | Azure Container Apps |
AZURE_MICROSOFT_APP_MANAGEDENVIRONMENTS | Container Apps managed environments |
AZURE_MICROSOFT_APP_JOBS | Container Apps jobs |
Azure Functions Monitoring
Function Apps are AZURE_MICROSOFT_WEB_SITES entities where the kind field contains functionapp. Filter using azure.object to separate them from App Service.
List all Function Apps:
smartscapeNodes "AZURE_MICROSOFT_WEB_SITES"
| parse azure.object, "JSON:azjson"
| fieldsAdd kind = azjson[configuration][kind]
| filter contains(kind, "functionapp")
| fieldsAdd state = azjson[configuration][properties][state],
defaultHostName = azjson[configuration][properties][defaultHostName],
runtime = azjson[configuration][properties][siteConfig][linuxFxVersion],
httpsOnly = azjson[configuration][properties][httpsOnly]
| fields name, kind, state, defaultHostName, runtime, httpsOnly,
azure.resource.group, azure.locationFind Function Apps on consumption (Dynamic) plans vs. dedicated plans:
smartscapeNodes "AZURE_MICROSOFT_WEB_SITES"
| parse azure.object, "JSON:azjson"
| fieldsAdd kind = azjson[configuration][kind],
sku = azjson[configuration][properties][sku]
| filter contains(kind, "functionapp")
| summarize func_count = count(), by: {sku}
| sort func_count descFind Function Apps and their App Service Plans (Web Site → Server Farm traversal):
smartscapeNodes "AZURE_MICROSOFT_WEB_SITES"
| parse azure.object, "JSON:azjson"
| fieldsAdd kind = azjson[configuration][kind]
| filter contains(kind, "functionapp")
| traverse "*", "AZURE_MICROSOFT_WEB_SERVERFARMS"
| fieldsAdd sourceId = dt.traverse.history[0][id]
| fieldsAdd planName = name, planId = id
| lookup [smartscapeNodes "AZURE_MICROSOFT_WEB_SITES" | fields name, id], sourceField: sourceId, lookupField: id, prefix: "app."
| fields app.name, planName, planIdList individual functions within Function Apps (Function → Web Site backward traversal):
smartscapeNodes "AZURE_MICROSOFT_WEB_SITES"
| filter name == "<FUNCTION_APP_NAME>"
| traverse "*", "AZURE_MICROSOFT_WEB_SITES_FUNCTIONS", direction:backward
| fields name, id, azure.resource.groupFind Function Apps with VNet integration (check for virtual network subnet ID):
smartscapeNodes "AZURE_MICROSOFT_WEB_SITES"
| parse azure.object, "JSON:azjson"
| fieldsAdd kind = azjson[configuration][kind],
vnetSubnetId = azjson[configuration][properties][virtualNetworkSubnetId]
| filter contains(kind, "functionapp")
| filter isNotNull(vnetSubnetId)
| fields name, vnetSubnetId, azure.resource.group, azure.locationApp Service Monitoring
List all App Service web apps (exclude Function Apps):
smartscapeNodes "AZURE_MICROSOFT_WEB_SITES"
| parse azure.object, "JSON:azjson"
| fieldsAdd kind = azjson[configuration][kind]
| filter not(contains(kind, "functionapp"))
| fieldsAdd state = azjson[configuration][properties][state],
defaultHostName = azjson[configuration][properties][defaultHostName],
runtime = azjson[configuration][properties][siteConfig][linuxFxVersion],
httpsOnly = azjson[configuration][properties][httpsOnly]
| fields name, kind, state, defaultHostName, runtime, httpsOnly,
azure.resource.group, azure.locationList all App Service Plans with SKU details:
smartscapeNodes "AZURE_MICROSOFT_WEB_SERVERFARMS"
| parse azure.object, "JSON:azjson"
| fieldsAdd skuName = azjson[configuration][sku][name],
skuTier = azjson[configuration][sku][tier],
skuCapacity = azjson[configuration][sku][capacity]
| fields name, skuName, skuTier, skuCapacity, azure.resource.group, azure.locationFind stopped App Service apps:
smartscapeNodes "AZURE_MICROSOFT_WEB_SITES"
| parse azure.object, "JSON:azjson"
| fieldsAdd state = azjson[configuration][properties][state]
| filter state == "Stopped"
| fields name, state, azure.resource.group, azure.locationFind apps with public network access enabled:
smartscapeNodes "AZURE_MICROSOFT_WEB_SITES"
| parse azure.object, "JSON:azjson"
| fieldsAdd publicAccess = azjson[configuration][properties][publicNetworkAccess],
httpsOnly = azjson[configuration][properties][httpsOnly]
| fields name, publicAccess, httpsOnly, azure.resource.group, azure.locationAKS Infrastructure Monitoring
Note: This section covers the Azure infrastructure layer of AKS (clusters, agent pools, VMSS backing). For Kubernetes workload-level monitoring (pods, deployments, services), use the dt-obs-kubernetes skill.
List all AKS clusters with configuration:
smartscapeNodes "AZURE_MICROSOFT_CONTAINERSERVICE_MANAGEDCLUSTERS"
| parse azure.object, "JSON:azjson"
| fieldsAdd k8sVersion = azjson[configuration][properties][kubernetesVersion],
currentVersion = azjson[configuration][properties][currentKubernetesVersion],
powerState = azjson[configuration][properties][powerState][code],
networkPlugin = azjson[configuration][properties][networkProfile][networkPlugin],
rbac = azjson[configuration][properties][enableRBAC],
fqdn = azjson[configuration][properties][fqdn],
skuTier = azjson[configuration][sku][tier]
| fields name, k8sVersion, currentVersion, powerState, networkPlugin, rbac, fqdn, skuTier,
azure.resource.group, azure.locationFind AKS cluster networking configuration:
smartscapeNodes "AZURE_MICROSOFT_CONTAINERSERVICE_MANAGEDCLUSTERS"
| parse azure.object, "JSON:azjson"
| fieldsAdd networkPlugin = azjson[configuration][properties][networkProfile][networkPlugin],
loadBalancerSku = azjson[configuration][properties][networkProfile][loadBalancerSku],
podCidr = azjson[configuration][properties][networkProfile][podCidr],
serviceCidr = azjson[configuration][properties][networkProfile][serviceCidr],
nodeResourceGroup = azjson[configuration][properties][nodeResourceGroup]
| fields name, networkPlugin, loadBalancerSku, podCidr, serviceCidr, nodeResourceGroupFind agent pools for an AKS cluster (Agent Pool → AKS backward traversal):
smartscapeNodes "AZURE_MICROSOFT_CONTAINERSERVICE_MANAGEDCLUSTERS"
| filter name == "<AKS_CLUSTER_NAME>"
| traverse "*", "AZURE_MICROSOFT_CONTAINERSERVICE_MANAGEDCLUSTERS_AGENTPOOLS", direction:backward
| fields name, id, azure.resource.groupFind VMSS backing an AKS cluster (VMSS → AKS backward traversal):
smartscapeNodes "AZURE_MICROSOFT_CONTAINERSERVICE_MANAGEDCLUSTERS"
| filter name == "<AKS_CLUSTER_NAME>"
| traverse "*", "AZURE_MICROSOFT_COMPUTE_VIRTUALMACHINESCALESETS", direction:backward
| parse azure.object, "JSON:azjson"
| fieldsAdd vmSize = azjson[configuration][sku][name],
capacity = azjson[configuration][sku][capacity],
poolName = tags[`aks-managed-poolName`]
| fields name, vmSize, capacity, poolName, azure.resource.groupFind AKS clusters with deallocated power state:
smartscapeNodes "AZURE_MICROSOFT_CONTAINERSERVICE_MANAGEDCLUSTERS"
| parse azure.object, "JSON:azjson"
| fieldsAdd powerState = azjson[configuration][properties][powerState][code]
| filter powerState == "Deallocated"
| fields name, powerState, azure.resource.group, azure.locationList Container Registries:
smartscapeNodes "AZURE_MICROSOFT_CONTAINERREGISTRY_REGISTRIES"
| fields name, id, azure.resource.group, azure.location, azure.provisioning_stateContainer Apps
List all Container Apps with running status:
smartscapeNodes "AZURE_MICROSOFT_APP_CONTAINERAPPS"
| parse azure.object, "JSON:azjson"
| fieldsAdd runningStatus = azjson[configuration][properties][runningStatus],
provisioningState = azjson[configuration][properties][provisioningState],
latestRevision = azjson[configuration][properties][latestReadyRevisionName]
| fields name, runningStatus, provisioningState, latestRevision,
azure.resource.group, azure.locationFind Container App scaling configuration:
smartscapeNodes "AZURE_MICROSOFT_APP_CONTAINERAPPS"
| parse azure.object, "JSON:azjson"
| fieldsAdd minReplicas = azjson[configuration][properties][template][scale][minReplicas],
maxReplicas = azjson[configuration][properties][template][scale][maxReplicas]
| fields name, minReplicas, maxReplicas, azure.resource.group, azure.locationFind Container App container images:
smartscapeNodes "AZURE_MICROSOFT_APP_CONTAINERAPPS"
| parse azure.object, "JSON:azjson"
| fieldsAdd containers = azjson[configuration][properties][template][containers]
| expand containers
| fieldsAdd image = containers[image],
cpu = containers[resources][cpu],
memory = containers[resources][memory]
| fields name, image, cpu, memory, azure.resource.groupFind Container App ingress configuration:
smartscapeNodes "AZURE_MICROSOFT_APP_CONTAINERAPPS"
| parse azure.object, "JSON:azjson"
| fieldsAdd ingressFqdn = azjson[configuration][properties][configuration][ingress][fqdn],
external = azjson[configuration][properties][configuration][ingress][external],
targetPort = azjson[configuration][properties][configuration][ingress][targetPort]
| fields name, ingressFqdn, external, targetPort, azure.resource.groupFind Container Apps and their managed environments (Container App → Managed Environment traversal):
smartscapeNodes "AZURE_MICROSOFT_APP_CONTAINERAPPS"
| traverse "*", "AZURE_MICROSOFT_APP_MANAGEDENVIRONMENTS"
| fieldsAdd sourceId = dt.traverse.history[0][id]
| fieldsAdd envName = name, envId = id
| lookup [smartscapeNodes "AZURE_MICROSOFT_APP_CONTAINERAPPS" | fields name, id], sourceField: sourceId, lookupField: id, prefix: "app."
| fields app.name, envName, envIdList Container App managed environments:
smartscapeNodes "AZURE_MICROSOFT_APP_MANAGEDENVIRONMENTS"
| fields name, id, azure.resource.group, azure.location, azure.provisioning_stateList Container App jobs:
smartscapeNodes "AZURE_MICROSOFT_APP_JOBS"
| fields name, id, azure.resource.group, azure.location, azure.provisioning_stateCross-Service Analysis
Count all serverless and container resources by type:
smartscapeNodes "AZURE_MICROSOFT_WEB_SITES", "AZURE_MICROSOFT_WEB_SERVERFARMS",
"AZURE_MICROSOFT_CONTAINERSERVICE_MANAGEDCLUSTERS",
"AZURE_MICROSOFT_APP_CONTAINERAPPS", "AZURE_MICROSOFT_CONTAINERREGISTRY_REGISTRIES"
| summarize count = count(), by: {type}
| sort count descCount all serverless and container resources by region:
smartscapeNodes "AZURE_MICROSOFT_WEB_SITES", "AZURE_MICROSOFT_CONTAINERSERVICE_MANAGEDCLUSTERS",
"AZURE_MICROSOFT_APP_CONTAINERAPPS"
| summarize count = count(), by: {type, azure.location}
| sort azure.location, count descFind all resources in a specific resource group:
smartscapeNodes "AZURE_MICROSOFT_WEB_SITES", "AZURE_MICROSOFT_WEB_SERVERFARMS",
"AZURE_MICROSOFT_CONTAINERSERVICE_MANAGEDCLUSTERS",
"AZURE_MICROSOFT_APP_CONTAINERAPPS", "AZURE_MICROSOFT_APP_MANAGEDENVIRONMENTS"
| filter azure.resource.group == "<RESOURCE_GROUP>"
| fields type, name, azure.location, azure.provisioning_stateRelated skills
FAQ
What does dt-obs-azure monitor on Azure?
dt-obs-azure monitors AI workloads on Azure—including models, agents, and supporting cloud services—with Dynatrace traces for latency, errors, and dependency health across the full request chain.
Is dt-obs-azure for training or production AI systems?
dt-obs-azure targets production observability for deployed AI workloads on Azure. It configures Dynatrace instrumentation and dashboards rather than model training or dataset pipelines.