This is documentation for the next version of Grafana documentation. For the latest stable release, go to the latest version.
Azure Monitor annotations
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.
Before you begin
- Ensure you have configured the Azure Monitor data source.
- You need access to a Log Analytics workspace containing the data you want to use for annotations.
- Annotations use Log Analytics (KQL) queries only. Metrics, Traces, and Azure Resource Graph queries are not supported for annotations.
Create an annotation query
To add an Azure Monitor annotation to a dashboard:
- Navigate to the dashboard you want to update and click Edit.
- Click the Add new element icon (blue plus sign).
- Click Annotation query.
- Enter a name for the annotation query.
- If you don’t want to use the annotation query right away, clear the Enabled checkbox.
- Select a color for the annotation event markers.
- Select an option in the Show annotation controls in drop-down list to control where on the dashboard the annotation is displayed.
- Select an option in the Show in drop-down list to control the panels in which the annotation is displayed.
- Click Open query editor to open the Annotation Query dialog box.
- Select your Azure Monitor data source from the Data source drop-down list.
- Choose the Logs service.
- Select a Resource (Log Analytics workspace or Application Insights resource).
- Write a KQL query that returns the annotation data.
- Configure the annotation query and field mappings.
- (Optional) Click Test annotation query to ensure that the query is working properly.
- Click Close when you’ve completed the query setup.
- Click Save.
- (Optional) Enter a description of the changes you’ve made.
- Click Save.
- Click Exit edit.
Query requirements
Your KQL query should return columns that Grafana can use to create annotations:
Note
Always include a time filter in your query to limit results to the dashboard’s time range. Use the
$__timeFilter()macro.
Annotation query examples
The following examples demonstrate common annotation use cases.
Azure Activity Log events
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 100Deployment events
Show deployment-related activity:
AzureActivity
| where $__timeFilter(TimeGenerated)
| where OperationNameValue contains "deployments"
| project TimeGenerated, Text=strcat("Deployment: ", OperationNameValue), Status=ActivityStatusValue, ResourceGroup
| order by TimeGenerated descApplication Insights exceptions
Mark application exceptions as annotations:
AppExceptions
| where $__timeFilter(TimeGenerated)
| project TimeGenerated, Text=strcat(ProblemId, ": ", OuterMessage), SeverityLevel, AppRoleName
| order by TimeGenerated desc
| take 50Custom events from Application Insights
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 descSecurity alerts
Show security-related alerts:
SecurityAlert
| where $__timeFilter(TimeGenerated)
| project TimeGenerated, Text=AlertName, Severity=AlertSeverity, Description
| order by TimeGenerated desc
| take 50Resource health events
Display resource health status changes:
AzureActivity
| where $__timeFilter(TimeGenerated)
| where CategoryValue == "ResourceHealth"
| project TimeGenerated, Text=OperationNameValue, Status=ActivityStatusValue, ResourceId
| order by TimeGenerated descVM start and stop events
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 descAutoscale events
Show autoscale operations:
AzureActivity
| where $__timeFilter(TimeGenerated)
| where OperationNameValue contains "autoscale"
| project TimeGenerated, Text=strcat("Autoscale: ", OperationNameValue), Status=ActivityStatusValue, ResourceGroup
| order by TimeGenerated descCustomize annotation appearance
After creating an annotation query, you can customize its appearance:
Best practices
Follow these recommendations when creating annotations:
Limit results: Always use
takeorlimitto 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()orprojectto create descriptive annotation text that provides context at a glance.Add relevant tags: Include columns like
ResourceGroup,Severity, orStatusthat become clickable tags for filtering.Use descriptive names: Name your annotations clearly (for example, “Production Deployments”, “Critical Alerts”) so dashboard users understand what they represent.
Troubleshoot annotations
If annotations aren’t appearing as expected, try the following solutions.
Annotations don’t appear
- Verify the query returns data in the selected time range.
- Check that the query includes a
TimeGeneratedcolumn. - Test the query in the Azure Portal Log Analytics query editor.
- Ensure the annotation is enabled (toggle is on).
Too many annotations
- Add more specific filters to your query.
- Use
taketo limit results. - Narrow the time range.
Annotations appear at wrong times
- Verify the
TimeGeneratedcolumn contains the correct timestamp. - Check your dashboard’s timezone settings.


