How to Monitor Cost Export Status and Data Freshness in Azure
Azure Cost Management exports can silently fail, leaving you with stale billing data that undermines financial decisions and budget tracking. Without active monitoring, you might not discover export failures until month-end reports reveal missing data. This guide shows you how to proactively monitor export health, verify data freshness, and set up automated alerts to catch issues before they impact your business.
Overview
Effective cost export monitoring covers several key areas:
- Export execution status: Verify exports are running successfully on schedule
- Data freshness: Ensure billing files are being created with recent data
- Failure detection: Identify and diagnose export errors quickly
- Run history tracking: Monitor export performance and reliability over time
- Storage validation: Confirm files are actually reaching your storage account
- Data completeness: Verify exported data contains expected records
This guide provides four monitoring approaches:
- Azure Portal: Manual checking through the Cost Management interface
- Azure CLI/PowerShell: Scripted monitoring for automation
- Azure Monitor: Alerts and dashboards for proactive monitoring
- Logic Apps: Automated health checks with notifications
Prerequisites
Before you begin, ensure you have:
- Azure subscription with active cost exports configured
- Cost Management Reader role at minimum for viewing export status
- Azure CLI (2.40.0+) OR Azure PowerShell module (7.0.0+)
- Storage Blob Data Reader role for validating exported files
- Azure Monitor permissions for creating alerts (optional)
- Logic Apps permissions for automated monitoring (optional)
Understanding Export States
Azure Cost Management exports have several execution states:
| State | Description | Action Required |
|---|---|---|
| Completed | Export ran successfully and created files | None - normal state |
| InProgress | Export is currently executing | Wait for completion |
| Failed | Export encountered an error | Investigate error message |
| TimedOut | Export exceeded execution time limit | Check scope size, consider narrowing |
| NoDataInRange | No billing data available for export period | Normal for new subscriptions or future dates |
Method 1: Azure Portal Monitoring
Step 1: Check Export Status
- Navigate to Azure Portal → Cost Management + Billing
- Select Cost Management in the left navigation
- Click Exports under the Data section
- View your exports list with the following columns:
- Name: Export configuration name
- Status: Current execution state
- Last run: Timestamp of most recent execution
- Next run: Scheduled next execution time
Step 2: View Export Run History
- Click on an export name to open details
- Scroll to the Run history section
- Review recent execution records:
- Execution time: When the export ran
- Status: Success or failure indicator
- Duration: How long the export took
- Error details: Failure information if applicable
Step 3: Verify Data in Storage
- From the export details, note the Storage account and Container path
- Navigate to Storage accounts → Select your account
- Click Containers → Select the export container
- Browse to the export folder (typically organized by date)
- Check for recent files:
- File timestamp: Should match last export run time
- File size: Should not be 0 bytes
- File naming: Typically includes date in filename
Portal Dashboard Creation
Create a custom dashboard for at-a-glance monitoring:
- Go to Dashboard → New dashboard
- Add tiles:
- Cost Management exports summary (if available)
- Storage account metrics for your export destination
- Resource health for Cost Management service
- Save the dashboard for quick access
Method 2: Azure CLI Monitoring
Check All Export Statuses
#!/bin/bash
# Monitor all cost exports in subscription
SUBSCRIPTION_ID="your-subscription-id"
# Set subscription context
az account set --subscription $SUBSCRIPTION_ID
echo "=== Cost Export Status Report ==="
echo "Generated: $(date)"
echo ""
# List all exports
EXPORTS=$(az costmanagement export list \
--scope "/subscriptions/$SUBSCRIPTION_ID" \
--query "[].{Name:name, Schedule:schedule.recurrence, Status:schedule.status}" \
--output tsv)
echo "Exports found:"
echo "$EXPORTS"
echo ""
# Check each export's last run
while IFS=$'\t' read -r name schedule status; do
echo "--- Export: $name ---"
echo "Schedule: $schedule"
echo "Status: $status"
# Get run history (last 5 runs)
RUN_HISTORY=$(az costmanagement export show \
--name "$name" \
--scope "/subscriptions/$SUBSCRIPTION_ID" \
--query "runHistory.value[:5].{Start:executionTime,Status:status,Error:error.message}" \
--output table)
echo "Recent runs:"
echo "$RUN_HISTORY"
echo ""
done <<< "$EXPORTS"
Check Specific Export Details
# Get detailed information about a specific export
EXPORT_NAME="DailyCostExport"
SUBSCRIPTION_ID="your-subscription-id"
az costmanagement export show \
--name $EXPORT_NAME \
--scope "/subscriptions/$SUBSCRIPTION_ID" \
--query "{
Name: name,
Status: schedule.status,
LastRun: runHistory.value[0].executionTime,
LastStatus: runHistory.value[0].status,
LastError: runHistory.value[0].error.message,
StorageAccount: deliveryInfo.destination.resourceId,
Container: deliveryInfo.destination.container,
Path: deliveryInfo.destination.rootFolderPath
}" \
--output table
Verify Data Freshness
#!/bin/bash
# Check if export data is recent
STORAGE_ACCOUNT="yourstorageaccount"
CONTAINER="cost-exports"
EXPORT_PATH="daily"
MAX_AGE_HOURS=24
# Get storage account key
STORAGE_KEY=$(az storage account keys list \
--resource-group "your-resource-group" \
--account-name $STORAGE_ACCOUNT \
--query "[0].value" -o tsv)
# List recent blobs
LATEST_BLOB=$(az storage blob list \
--account-name $STORAGE_ACCOUNT \
--account-key $STORAGE_KEY \
--container-name $CONTAINER \
--prefix $EXPORT_PATH \
--query "reverse(sort_by([].{name:name, modified:properties.lastModified}, &modified))[0]" \
--output json)
BLOB_NAME=$(echo $LATEST_BLOB | jq -r '.name')
BLOB_MODIFIED=$(echo $LATEST_BLOB | jq -r '.modified')
echo "Latest export file: $BLOB_NAME"
echo "Last modified: $BLOB_MODIFIED"
# Calculate age in hours
CURRENT_TIMESTAMP=$(date +%s)
BLOB_TIMESTAMP=$(date -d "$BLOB_MODIFIED" +%s)
AGE_SECONDS=$((CURRENT_TIMESTAMP - BLOB_TIMESTAMP))
AGE_HOURS=$((AGE_SECONDS / 3600))
echo "Age: $AGE_HOURS hours"
if [ $AGE_HOURS -gt $MAX_AGE_HOURS ]; then
echo "WARNING: Export data is stale (older than $MAX_AGE_HOURS hours)"
exit 1
else
echo "OK: Export data is fresh"
exit 0
fi
Method 3: Azure PowerShell Monitoring
Comprehensive Export Health Check Script
# Cost Export Health Check Script
param(
[Parameter(Mandatory=$true)]
[string]$SubscriptionId,
[Parameter(Mandatory=$false)]
[int]$MaxAgeHours = 48,
[Parameter(Mandatory=$false)]
[int]$RecentRunsToCheck = 5,
[Parameter(Mandatory=$false)]
[string]$OutputPath = "export-health-report.html"
)
# Install required modules
Import-Module Az.CostManagement
Import-Module Az.Storage
# Connect and set context
Connect-AzAccount -ErrorAction SilentlyContinue
Set-AzContext -SubscriptionId $SubscriptionId | Out-Null
$scope = "/subscriptions/$SubscriptionId"
$reportTime = Get-Date
Write-Host "Checking cost export health..." -ForegroundColor Cyan
# Get all exports
$exports = Get-AzCostManagementExport -Scope $scope
$results = @()
foreach ($export in $exports) {
Write-Host "Checking export: $($export.Name)" -ForegroundColor Yellow
# Get run history
$runHistory = $export.RunHistory | Select-Object -First $RecentRunsToCheck
# Calculate success rate
$totalRuns = $runHistory.Count
$successfulRuns = ($runHistory | Where-Object { $_.Status -eq 'Completed' }).Count
$successRate = if ($totalRuns -gt 0) { [math]::Round(($successfulRuns / $totalRuns) * 100, 2) } else { 0 }
# Get last run details
$lastRun = $runHistory | Select-Object -First 1
$lastRunTime = if ($lastRun) { $lastRun.ExecutionTime } else { $null }
$lastRunStatus = if ($lastRun) { $lastRun.Status } else { "Never Run" }
# Calculate time since last run
$hoursSinceLastRun = if ($lastRunTime) {
[math]::Round(((Get-Date) - $lastRunTime).TotalHours, 2)
} else {
999
}
# Determine health status
$healthStatus = if ($lastRunStatus -eq 'Completed' -and $hoursSinceLastRun -le $MaxAgeHours) {
"Healthy"
} elseif ($lastRunStatus -eq 'InProgress') {
"Running"
} elseif ($hoursSinceLastRun -gt $MaxAgeHours) {
"Stale"
} else {
"Unhealthy"
}
# Get storage details
$storageResourceId = $export.DestinationResourceId
$container = $export.DestinationContainer
$rootFolder = $export.DestinationRootFolderPath
# Check if files exist in storage
$filesExist = "Unknown"
if ($storageResourceId -and $container) {
try {
$storageAccountName = ($storageResourceId -split '/')[8]
$resourceGroupName = ($storageResourceId -split '/')[4]
$storageAccount = Get-AzStorageAccount `
-ResourceGroupName $resourceGroupName `
-Name $storageAccountName
$ctx = $storageAccount.Context
$blobs = Get-AzStorageBlob `
-Context $ctx `
-Container $container `
-Prefix $rootFolder `
-MaxCount 1
$filesExist = if ($blobs) { "Yes" } else { "No" }
} catch {
$filesExist = "Error: $($_.Exception.Message)"
}
}
# Create result object
$result = [PSCustomObject]@{
ExportName = $export.Name
Schedule = $export.ScheduleRecurrence
ScheduleStatus = $export.ScheduleStatus
LastRunTime = $lastRunTime
LastRunStatus = $lastRunStatus
HoursSinceLastRun = $hoursSinceLastRun
SuccessRate = "$successRate%"
RecentRuns = $totalRuns
HealthStatus = $healthStatus
FilesInStorage = $filesExist
StorageAccount = if ($storageResourceId) { ($storageResourceId -split '/')[8] } else { "N/A" }
Container = $container
Errors = if ($lastRun.Error) { $lastRun.Error.Message } else { "None" }
}
$results += $result
# Console output
Write-Host " Status: $healthStatus" -ForegroundColor $(
switch ($healthStatus) {
"Healthy" { "Green" }
"Running" { "Yellow" }
"Stale" { "Yellow" }
"Unhealthy" { "Red" }
}
)
Write-Host " Last run: $lastRunTime ($hoursSinceLastRun hours ago)"
Write-Host " Success rate: $successRate% ($successfulRuns/$totalRuns)"
Write-Host ""
}
# Display summary
Write-Host "=== SUMMARY ===" -ForegroundColor Cyan
$healthy = ($results | Where-Object { $_.HealthStatus -eq 'Healthy' }).Count
$unhealthy = ($results | Where-Object { $_.HealthStatus -eq 'Unhealthy' }).Count
$stale = ($results | Where-Object { $_.HealthStatus -eq 'Stale' }).Count
Write-Host "Total exports: $($results.Count)"
Write-Host "Healthy: $healthy" -ForegroundColor Green
Write-Host "Stale: $stale" -ForegroundColor Yellow
Write-Host "Unhealthy: $unhealthy" -ForegroundColor Red
# Generate HTML report
$html = @"
<!DOCTYPE html>
<html>
<head>
<title>Cost Export Health Report</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
h1 { color: #0078D4; }
table { border-collapse: collapse; width: 100%; margin-top: 20px; }
th { background-color: #0078D4; color: white; padding: 10px; text-align: left; }
td { border: 1px solid #ddd; padding: 8px; }
tr:nth-child(even) { background-color: #f2f2f2; }
.healthy { background-color: #DFF0D8; }
.unhealthy { background-color: #F2DEDE; }
.stale { background-color: #FCF8E3; }
.running { background-color: #D9EDF7; }
.summary { background-color: #f9f9f9; padding: 15px; border-radius: 5px; margin-bottom: 20px; }
</style>
</head>
<body>
<h1>Cost Export Health Report</h1>
<div class="summary">
<p><strong>Generated:</strong> $reportTime</p>
<p><strong>Subscription:</strong> $SubscriptionId</p>
<p><strong>Total Exports:</strong> $($results.Count)</p>
<p><strong>Healthy:</strong> $healthy | <strong>Stale:</strong> $stale | <strong>Unhealthy:</strong> $unhealthy</p>
</div>
<table>
<tr>
<th>Export Name</th>
<th>Schedule</th>
<th>Last Run</th>
<th>Status</th>
<th>Hours Since</th>
<th>Success Rate</th>
<th>Health</th>
<th>Files</th>
<th>Errors</th>
</tr>
"@
foreach ($result in $results) {
$rowClass = $result.HealthStatus.ToLower()
$html += @"
<tr class="$rowClass">
<td>$($result.ExportName)</td>
<td>$($result.Schedule)</td>
<td>$($result.LastRunTime)</td>
<td>$($result.LastRunStatus)</td>
<td>$($result.HoursSinceLastRun)</td>
<td>$($result.SuccessRate)</td>
<td><strong>$($result.HealthStatus)</strong></td>
<td>$($result.FilesInStorage)</td>
<td>$($result.Errors)</td>
</tr>
"@
}
$html += @"
</table>
</body>
</html>
"@
# Save HTML report
$html | Out-File -FilePath $OutputPath -Encoding UTF8
Write-Host "`nReport saved to: $OutputPath" -ForegroundColor Green
# Return results object for further processing
return $results
Run the health check script:
.\Check-ExportHealth.ps1 `
-SubscriptionId "your-subscription-id" `
-MaxAgeHours 48 `
-RecentRunsToCheck 10 `
-OutputPath "C:\Reports\export-health-$(Get-Date -Format 'yyyyMMdd').html"
Method 4: Azure Monitor Alerts
Create Alert for Export Failures
# Create action group for notifications
az monitor action-group create \
--name "CostExportAlerts" \
--resource-group "rg-cost-monitoring" \
--short-name "CostAlert" \
--email-receiver \
name="FinanceTeam" \
email="[email protected]" \
use-common-alert-schema
# Create log query alert for export failures
az monitor scheduled-query create \
--name "Cost Export Failure Alert" \
--resource-group "rg-cost-monitoring" \
--scopes "/subscriptions/your-subscription-id" \
--condition "count > 0" \
--condition-query "AzureDiagnostics
| where Category == 'CostManagement'
| where OperationName == 'ExportExecution'
| where ResultType == 'Failed'
| where TimeGenerated > ago(1h)" \
--description "Alert when cost export fails" \
--evaluation-frequency "1h" \
--window-size "1h" \
--severity 2 \
--action-groups "/subscriptions/your-sub-id/resourceGroups/rg-cost-monitoring/providers/microsoft.insights/actionGroups/CostExportAlerts"
Create Alert for Stale Data
# Alert when no new exports in last 48 hours
az monitor scheduled-query create \
--name "Stale Cost Export Data" \
--resource-group "rg-cost-monitoring" \
--scopes "/subscriptions/your-subscription-id/resourceGroups/your-rg/providers/Microsoft.Storage/storageAccounts/yourstorageaccount" \
--condition "count == 0" \
--condition-query "StorageBlobLogs
| where AccountName == 'yourstorageaccount'
| where OperationName == 'PutBlob'
| where Uri contains 'cost-exports'
| where TimeGenerated > ago(48h)" \
--description "Alert when cost export data is stale" \
--evaluation-frequency "6h" \
--window-size "48h" \
--severity 3 \
--action-groups "/subscriptions/your-sub-id/resourceGroups/rg-cost-monitoring/providers/microsoft.insights/actionGroups/CostExportAlerts"
Method 5: Azure Logic Apps Monitoring
Automated Health Check Workflow
Create a Logic App that runs daily health checks:
Workflow outline:
- Recurrence trigger: Runs daily at 9 AM
- HTTP action: Call Azure Management API to list exports
- For each export: Check run history and status
- Condition: If any exports failed or are stale
- Send email/Teams notification: Alert with details
- Log to Azure Table Storage: Track export health history
ARM Template for Logic App:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"logicAppName": {
"type": "string",
"defaultValue": "CostExportMonitor"
},
"emailRecipient": {
"type": "string"
}
},
"resources": [
{
"type": "Microsoft.Logic/workflows",
"apiVersion": "2019-05-01",
"name": "[parameters('logicAppName')]",
"location": "[resourceGroup().location]",
"properties": {
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"triggers": {
"Recurrence": {
"type": "Recurrence",
"recurrence": {
"frequency": "Day",
"interval": 1,
"schedule": {
"hours": ["9"],
"minutes": [0]
}
}
}
},
"actions": {
"Get_Exports": {
"type": "Http",
"inputs": {
"method": "GET",
"uri": "https://management.azure.com/subscriptions/@{parameters('subscriptionId')}/providers/Microsoft.CostManagement/exports?api-version=2023-03-01",
"authentication": {
"type": "ManagedServiceIdentity"
}
}
},
"For_Each_Export": {
"type": "Foreach",
"foreach": "@body('Get_Exports')['value']",
"actions": {
"Check_Export_Health": {
"type": "If",
"expression": {
"or": [
{
"equals": [
"@item()['properties']['schedule']['status']",
"Inactive"
]
},
{
"equals": [
"@item()['properties']['runHistory']['value'][0]['status']",
"Failed"
]
}
]
},
"actions": {
"Send_Alert_Email": {
"type": "ApiConnection",
"inputs": {
"host": {
"connection": {
"name": "@parameters('$connections')['office365']['connectionId']"
}
},
"method": "post",
"path": "/v2/Mail",
"body": {
"To": "[parameters('emailRecipient')]",
"Subject": "Cost Export Alert: @{item()['name']}",
"Body": "Export '@{item()['name']}' requires attention. Status: @{item()['properties']['schedule']['status']}"
}
}
}
}
}
}
}
}
}
}
}
]
}
Best Practices
1. Establish Monitoring Baselines
Track normal export patterns:
# Collect baseline metrics over 30 days
$baseline = @{
AverageExecutionTime = (Get-AzCostManagementExportRunHistory -ExportName "MyExport" |
Where-Object { $_.Status -eq 'Completed' } |
Measure-Object -Property Duration -Average).Average
TypicalFileSize = (Get-AzStorageBlob -Container "exports" |
Measure-Object -Property Length -Average).Average
SuccessRate = # Calculate from run history
}
2. Set Appropriate Alert Thresholds
- Critical: Export hasn't run in 2x schedule frequency (e.g., 48 hours for daily)
- Warning: Export failed once in last 5 runs
- Info: Export duration 50% longer than baseline
3. Monitor Multiple Metrics
Don't rely on status alone:
- Export execution status
- File creation timestamp
- File size (detect empty/corrupt files)
- Storage account availability
- API quota consumption
4. Implement Tiered Alerting
Tier 1 - Info: Log to monitoring system only
Tier 2 - Warning: Email to operations team
Tier 3 - Critical: Email + SMS + PagerDuty escalation
5. Create Runbooks for Common Issues
Document resolution steps:
# Export Failure Runbook
## Issue: Export Status = Failed
1. Check error message in run history
2. If "Authorization failed": Verify managed identity permissions
3. If "Storage error": Check storage account health
4. If "Timeout": Consider narrowing export scope
5. Retry export manually
6. If persists, contact Azure support
6. Track Long-Term Trends
-- Create historical tracking table
CREATE TABLE ExportHealthHistory (
Timestamp DATETIME,
ExportName VARCHAR(100),
Status VARCHAR(50),
Duration INT,
ErrorMessage VARCHAR(MAX)
);
-- Query failure trends
SELECT
ExportName,
DATEPART(month, Timestamp) AS Month,
COUNT(CASE WHEN Status = 'Failed' THEN 1 END) AS Failures,
COUNT(*) AS TotalRuns,
CAST(COUNT(CASE WHEN Status = 'Failed' THEN 1 END) AS FLOAT) / COUNT(*) * 100 AS FailureRate
FROM ExportHealthHistory
WHERE Timestamp >= DATEADD(month, -6, GETDATE())
GROUP BY ExportName, DATEPART(month, Timestamp)
ORDER BY ExportName, Month;
Troubleshooting
Issue: Export shows "Completed" but no files in storage
Symptoms: Run history shows successful completion, but storage container is empty
Resolution:
# Verify managed identity has storage permissions
EXPORT_IDENTITY=$(az costmanagement export show \
--name "MyExport" \
--scope "/subscriptions/$SUBSCRIPTION_ID" \
--query "identity.principalId" -o tsv)
# Check role assignments
az role assignment list \
--assignee $EXPORT_IDENTITY \
--scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RG_NAME/providers/Microsoft.Storage/storageAccounts/$STORAGE_ACCOUNT" \
--query "[?roleDefinitionName=='Storage Blob Data Contributor']"
# If missing, assign the role
az role assignment create \
--role "Storage Blob Data Contributor" \
--assignee-object-id $EXPORT_IDENTITY \
--scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RG_NAME/providers/Microsoft.Storage/storageAccounts/$STORAGE_ACCOUNT"
Issue: Cannot see run history in API responses
Symptoms: runHistory property is null or empty
Resolution:
# Ensure you're using correct API version
az costmanagement export show \
--name "MyExport" \
--scope "/subscriptions/$SUBSCRIPTION_ID" \
--query "runHistory" \
--api-version "2023-03-01"
# If still null, export may never have run
# Trigger manual run
az costmanagement export run \
--export-name "MyExport" \
--scope "/subscriptions/$SUBSCRIPTION_ID"
Issue: Monitoring script fails with authentication errors
Symptoms: "Authorization failed" or "Token expired" errors
Resolution:
# Clear and refresh Azure PowerShell session
Disconnect-AzAccount
Clear-AzContext -Force
Connect-AzAccount
# For automation, use managed identity or service principal
Connect-AzAccount -Identity # For Azure Automation
# OR
Connect-AzAccount -ServicePrincipal -Credential $credential -Tenant $tenantId
Issue: Logic App workflow times out
Symptoms: Logic App runs show timeout errors
Resolution:
// Add pagination to handle large result sets
"Get_Exports": {
"type": "Http",
"inputs": {
"method": "GET",
"uri": "https://management.azure.com/subscriptions/@{parameters('subscriptionId')}/providers/Microsoft.CostManagement/exports?api-version=2023-03-01",
"pagination": {
"enabled": true
}
}
}
Issue: Alert fires too frequently (false positives)
Symptoms: Getting alerts even when exports are healthy
Resolution:
# Increase evaluation window
az monitor scheduled-query update \
--name "Cost Export Failure Alert" \
--resource-group "rg-cost-monitoring" \
--evaluation-frequency "6h" \
--window-size "12h"
# Add suppression for known maintenance windows
# Update query to exclude specific time ranges
Automated Monitoring Dashboard
Create Custom Workbook in Azure Monitor
{
"version": "Notebook/1.0",
"items": [
{
"type": 1,
"content": {
"json": "# Cost Export Monitoring Dashboard\n\nReal-time monitoring of Azure Cost Management exports"
}
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
"query": "AzureDiagnostics\n| where Category == 'CostManagement'\n| where OperationName == 'ExportExecution'\n| summarize \n TotalRuns = count(),\n Failures = countif(ResultType == 'Failed'),\n SuccessRate = round(todouble(countif(ResultType == 'Succeeded')) / count() * 100, 2)\n by ExportName = resource_exportName_s\n| order by Failures desc",
"size": 0,
"title": "Export Success Rates",
"queryType": 0,
"visualization": "table"
}
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
"query": "AzureDiagnostics\n| where Category == 'CostManagement'\n| where OperationName == 'ExportExecution'\n| where ResultType == 'Failed'\n| project TimeGenerated, ExportName = resource_exportName_s, ErrorMessage = message_s\n| order by TimeGenerated desc\n| take 50",
"size": 0,
"title": "Recent Export Failures",
"queryType": 0,
"visualization": "table"
}
},
{
"type": 3,
"content": {
"version": "KqlItem/1.0",
"query": "StorageBlobLogs\n| where OperationName == 'PutBlob'\n| where Uri contains 'cost-exports'\n| summarize \n LastExportTime = max(TimeGenerated),
FileCount = count()\n by AccountName\n| extend HoursSinceLastExport = datetime_diff('hour', now(), LastExportTime)\n| order by HoursSinceLastExport desc",
"size": 0,
"title": "Export Data Freshness",
"queryType": 0,
"visualization": "table"
}
}
]
}
Next Steps
Once monitoring is in place:
- Tune alert thresholds: Adjust based on observed patterns to reduce false positives
- Integrate with ITSM: Connect alerts to ServiceNow, Jira, or other ticketing systems
- Create response playbooks: Document steps for common failure scenarios
- Set up cost anomaly detection: Use "How to Set Up Cost Alerts and Budgets in Azure"
- Secure your pipeline: Review "How to Secure Cost Management Data in Azure Storage and Synapse"
Related Resources
Frequently Asked Questions
Find answers to common questions
Need Professional Help?
Our team of experts can help you implement and configure these solutions for your organization.