docs/sources/datasources/azure-monitor/annotations/index.md
Annotations overlay rich event information on top of graphs. You can use Azure Monitor Log Analytics queries to create annotations that mark important events, deployments, alerts, or other significant occurrences on your dashboards.
To add an Azure Monitor annotation to a dashboard:
Your KQL query should return columns that Grafana can use to create annotations:
| Column | Required | Description |
|---|---|---|
TimeGenerated | Yes | The timestamp for the annotation. Grafana uses this to position the annotation on the time axis. |
Text | Recommended | The annotation text displayed when you hover over or click the annotation. |
| Additional columns | Optional | Any other columns returned become annotation tags. |
{{< admonition type="note" >}}
Always include a time filter in your query to limit results to the dashboard's time range. Use the $__timeFilter() macro.
{{< /admonition >}}
The following examples demonstrate common annotation use cases.
Display Azure Activity Log events such as resource modifications, deployments, and administrative actions:
AzureActivity
| where $__timeFilter(TimeGenerated)
| where Level == "Error" or Level == "Warning" or CategoryValue == "Administrative"
| project TimeGenerated, Text=OperationNameValue, Level, ResourceGroup, Caller
| order by TimeGenerated desc
| take 100
Show deployment-related activity:
AzureActivity
| where $__timeFilter(TimeGenerated)
| where OperationNameValue contains "deployments"
| project TimeGenerated, Text=strcat("Deployment: ", OperationNameValue), Status=ActivityStatusValue, ResourceGroup
| order by TimeGenerated desc
Mark application exceptions as annotations:
AppExceptions
| where $__timeFilter(TimeGenerated)
| project TimeGenerated, Text=strcat(ProblemId, ": ", OuterMessage), SeverityLevel, AppRoleName
| order by TimeGenerated desc
| take 50
Display custom events logged by your application:
AppEvents
| where $__timeFilter(TimeGenerated)
| where Name == "DeploymentStarted" or Name == "DeploymentCompleted"
| project TimeGenerated, Text=Name, AppRoleName
| order by TimeGenerated desc
Show security-related alerts:
SecurityAlert
| where $__timeFilter(TimeGenerated)
| project TimeGenerated, Text=AlertName, Severity=AlertSeverity, Description
| order by TimeGenerated desc
| take 50
Display resource health status changes:
AzureActivity
| where $__timeFilter(TimeGenerated)
| where CategoryValue == "ResourceHealth"
| project TimeGenerated, Text=OperationNameValue, Status=ActivityStatusValue, ResourceId
| order by TimeGenerated desc
Mark virtual machine state changes:
AzureActivity
| where $__timeFilter(TimeGenerated)
| where OperationNameValue has_any ("start", "deallocate", "restart")
| where ResourceProviderValue == "MICROSOFT.COMPUTE"
| project TimeGenerated, Text=OperationNameValue, VM=Resource, Status=ActivityStatusValue
| order by TimeGenerated desc
Show autoscale operations:
AzureActivity
| where $__timeFilter(TimeGenerated)
| where OperationNameValue contains "autoscale"
| project TimeGenerated, Text=strcat("Autoscale: ", OperationNameValue), Status=ActivityStatusValue, ResourceGroup
| order by TimeGenerated desc
After creating an annotation query, you can customize its appearance:
| Setting | Description |
|---|---|
| Color | Choose a color for the annotation markers. Use different colors to distinguish between annotation types. |
| Show in | Select which panels display the annotations. |
| Filter by | Add filters to limit when annotations appear. |
Follow these recommendations when creating annotations:
Limit results: Always use take or limit to restrict the number of annotations. Too many annotations can clutter your dashboard and impact performance.
Use time filters: Include $__timeFilter() to ensure queries only return data within the dashboard's time range.
Create meaningful text: Use strcat() or project to create descriptive annotation text that provides context at a glance.
Add relevant tags: Include columns like ResourceGroup, Severity, or Status that become clickable tags for filtering.
Use descriptive names: Name your annotations clearly (e.g., "Production Deployments", "Critical Alerts") so dashboard users understand what they represent.
If annotations aren't appearing as expected, try the following solutions.
TimeGenerated column.take to limit results.TimeGenerated column contains the correct timestamp.