Infrastructure

Azure Monitor: diagnose missing logs before changing alerts

A production runbook for qualifying missing Azure Monitor logs with Diagnostic Settings, DCRs, ingestion, KQL, cost controls, validation and rollback before changing alerts.

27 Jun 2026 azureazure-monitorkqlobservabilitydiagnostic-settingsdcrlogsrunbookvalidationrollbackautomation

An alert that stops firing is not always a bad rule. In Azure production environments, the problem often sits lower in the chain: a deleted Diagnostic Setting, a modified Data Collection Rule, a table that stopped ingesting, a moved workspace, an aggressive transformation, a retention change, or an ingestion cost reduction made too quickly. The symptom is dangerous because it looks quiet: dashboards get cleaner, alerts stop making noise, but operations lose part of their evidence.

The use case is an Azure application operated with Application Insights, Log Analytics, Diagnostic Settings on managed resources, a few DCRs for VMs or agents, and KQL alerts used during incidents. After a deployment or logging rationalization effort, the team notices that some errors no longer appear. The runbook goal is to diagnose the observability chain before changing thresholds, recreating alerts or assuming the service is healthier.

Describe the expected signal

Before searching with KQL, write down the signal that should exist. Missing logs should be diagnosed as a production path: producer, collection configuration, destination, table, transformation, alert and operational consumer.

text observability-signal-contract.txt
Expected signal
Source resource: app-orders-prod / Application Gateway / Key Vault / worker VM
Expected event: application error, WAF block, Key Vault denial, runtime exception
Destination: workspace log-prod-euw
Expected table: AppRequests, AzureDiagnostics, AppExceptions, KeyVaultAuditEvents
Comparison window: 24h before change / 2h after change
Consumers: SLO alert, incident dashboard, rollback runbook, post-incident review

Questions before correction
Is the service still producing the event?
Is collection still enabled?
Did the destination change?
Is the expected table ingesting data?
Is a transformation filtering the signal?
Does the alert query the right table and window?

This contract prevents the team from starting with the alert rule. If the table no longer receives data, changing a threshold does not repair observability; it only adapts the alarm to a broken sensor.

Compare before and after the change

The first query should check signal presence, not business meaning. Compare the same scope, table and granularity before and after the suspicious window.

kusto 01-log-presence-before-after.kql
let changeStart = datetime(2026-06-27T07:30:00Z);
let beforeWindow = 24h;
let afterWindow = 4h;
let serviceName = "orders-api";
AppRequests
| where TimeGenerated between ((changeStart - beforeWindow) .. (changeStart + afterWindow))
| where AppRoleName == serviceName
| summarize
  rows = count(),
  failed = countif(Success == false),
  operations = dcount(OperationName)
by phase = iff(TimeGenerated < changeStart, "before", "after"), bin(TimeGenerated, 30m)
| order by TimeGenerated asc

If volume drops to zero, move down toward ingestion. If volume stays stable but errors disappear, check the service, success definition, transformations and filtered dimensions.

Check Diagnostic Settings

For many Azure resources, platform logs arrive through Diagnostic Settings. An infrastructure change can remove a category, switch the workspace, disable metrics or send logs to Storage instead of Log Analytics.

bash 02-capture-diagnostic-settings.sh
RESOURCE_ID="/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-prod/providers/Microsoft.Network/applicationGateways/agw-prod"

az monitor diagnostic-settings list --resource "$RESOURCE_ID" --query "[].{name:name,workspace:workspaceId,logs:logs[].{category:category,enabled:enabled},metrics:metrics[].{category:category,enabled:enabled}}" --output json

az monitor diagnostic-settings categories list --resource "$RESOURCE_ID" --query "value[].{name:name,type:categoryType}" --output table

Attach this state to the change ticket. A clean rollback needs to restore the Diagnostic Setting name, enabled categories, destination and collected metrics.

Inspect DCRs, agents and transformations

Data Collection Rules add a useful but sometimes less visible layer: resource association, data sources, destinations, KQL transformations and streams. A transformation can be syntactically valid while removing the signal operations need.

bash 03-capture-dcr-state.sh
az monitor data-collection rule association list-by-resource --resource "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-prod/providers/Microsoft.Compute/virtualMachines/vm-worker-01" --query "[].{name:name,rule:dataCollectionRuleId,description:description}" --output table

az monitor data-collection rule show --resource-group rg-observability-prod --name dcr-linux-workers-prod --query "{destinations:destinations,streams:streamDeclarations,dataFlows:dataFlows}" --output json

Prioritize missing associations, destinations that no longer point to the expected workspace, and transformations filtering on Severity, Facility, Category, ResultType or application fields.

Read ingestion health as evidence

An alert may be quiet because the service is healthy, because collection is broken, or because ingestion is delayed. Read table health and compare several sources before deciding.

kusto 04-ingestion-health.kql
let window = 6h;
union withsource = TableName
AppRequests,
AppExceptions,
AppDependencies,
AzureDiagnostics
| where TimeGenerated > ago(window)
| summarize
  rows = count(),
  firstSeen = min(TimeGenerated),
  lastSeen = max(TimeGenerated)
by TableName, bin(TimeGenerated, 30m)
| order by TableName asc, TimeGenerated asc

Add the platform logs available in your environment: Azure activity, configuration changes, agent events, workspace metrics or administrative queries. The point is to prove whether the silence comes from no event or no collection.

Find configuration changes

Missing logs often follow a legitimate operation: Terraform cleanup, policy change, workspace migration, cost reduction, DCR change or alert redesign. Activity logs provide the entry point.

kusto 05-observability-config-changes.kql
let changeWindow = 48h;
AzureActivity
| where TimeGenerated > ago(changeWindow)
| where OperationNameValue has_any (
  "MICROSOFT.INSIGHTS/DIAGNOSTICSETTINGS/WRITE",
  "MICROSOFT.INSIGHTS/DIAGNOSTICSETTINGS/DELETE",
  "MICROSOFT.INSIGHTS/DATACOLLECTIONRULES/WRITE",
  "MICROSOFT.INSIGHTS/SCHEDULEDQUERYRULES/WRITE",
  "MICROSOFT.OPERATIONALINSIGHTS/WORKSPACES/WRITE")
| project TimeGenerated,
        OperationNameValue,
        ActivityStatusValue,
        Caller,
        ResourceGroup,
        ResourceProviderValue,
        ResourceId,
        CorrelationId
| order by TimeGenerated desc

If an operation lines up with the volume drop, do not fix yet. First confirm whether it was intentional, whether it touched every expected resource, and whether a configuration rollback exists.

Separate log savings from evidence loss

Reducing ingestion can be necessary. But savings should come from an explicit decision, not from accidental loss of visibility. Classify signals before cutting them.

text log-signal-classification.txt
Keep during incidents without debate
User errors
Authentication and access denials
WAF, gateway and API gateway events
Deployments, revisions and configuration changes
Automation actions and execution identities

Reduce with validation
Verbose debug traces
Repetitive events without correlation value
Metrics already covered elsewhere
Non-critical dependency logs outside incident windows

Never remove without an alternative
Signal used by an SLO alert
Signal used by rollback validation
Signal needed for security evidence
Signal linking user, operation and version

This classification lets the team correct without going back to unlimited ingestion. The goal is to restore useful evidence, not to log everything by reflex.

Decide: restore, fix forward or adapt the alert

The decision should come after collection evidence. A silent alert may require restoring a Diagnostic Setting, fixing a DCR, rolling back Terraform or adapting a query. These actions do not carry the same risk.

text missing-logs-decision-matrix.txt
Restore previous configuration
Diagnostic Setting deleted or destination changed
DCR detached from a critical resource
Table empty while the service still produces events
Known low-risk rollback exists

Fix forward
Transformation is too broad but intent is correct
Category missing on a limited scope
Target workspace is correct but stream is incomplete
Ingestion test is immediately available

Adapt the alert
Logs are present
Schema or table changed intentionally
Old signal has a documented replacement
Query is replayed on before/after data with expected result

Do not act yet
Drop explained by real absence of events
Window too short to conclude
Temporary ingestion delay confirmed
No operational consumer is affected

Do not modify the alert until the collection chain is proven. Otherwise, the team may tune the alarm to a broken sensor.

Validate after correction

Validation must replay the signal end to end: event produced, ingestion visible, alert query active and evidence attached to the change.

text observability-rollback-validation.txt
Minimum validation
Diagnostic Settings or DCR match the expected state
The table receives new rows after correction
The KQL query finds the test signal
The alert targets the right workspace and table
The incident dashboard is coherent again
Expected cost or volume is accepted
The correction rollback is documented

Evidence to keep
State before correction
Applied change
Timestamp when logs returned
Validation KQL query
Decision: restore, fix forward or adapt alert

If the signal returns but the alert remains quiet, move the investigation to the query, evaluation window, dimensions, action group or frequency. Collection is operable again.

Conclusion

Missing Azure Monitor logs should be handled as an observability incident, not as an alert-tuning task. The right sequence is to describe the expected signal, compare before and after, check Diagnostic Settings, DCRs, destinations, transformations and ingestion, then decide what to change.

The healthy decision is simple: restore when critical collection disappeared, fix forward when the defect is bounded, adapt the alert when the signal intentionally changed, and change nothing when the silence is genuinely explained. That keeps incidents from looking cleaner in dashboards while becoming more opaque for operations.