azure-monitor-query-py — Claude Code skill: setup and usage
Guides coding agents to query Azure Monitor metrics and Log Analytics workspaces with the Python SDK. Useful when writing Kusto log queries and fetching telemetry data.
npx skills add microsoft/skills --skill azure-monitor-query-py -a claude-codeWhat azure-monitor-query-py does
This skill guides agents in writing Python code with the official azure-monitor-query package. It focuses on LogsQueryClient for querying Log Analytics tables and MetricsQueryClient for retrieving resource performance data. The skill enforces wrapping every client in a context manager (with or async with). This releases open transports and sockets deterministically.
Authentication relies on DefaultAzureCredential. In production, the environment requires AZURE_TOKEN_CREDENTIALS=prod to restrict the credential chain. Without AZURE_LOG_ANALYTICS_WORKSPACE_ID, log queries cannot execute. The agent formats Kusto queries, parses responses into pandas DataFrames, groups batch calls with LogsBatchQuery, and handles partial results.
For telemetry metrics, the generated code uses AZURE_METRICS_RESOURCE_URI. It supports metrics like CPU percentage, handles aggregation types, filters series by dimension, and inspects available namespaces.
What it helps with
- write Kusto queries to Log Analytics via LogsQueryClient
- retrieve Azure resource metrics with aggregations and time windows
- convert Azure Monitor log responses into pandas DataFrames
- batch multiple log queries using LogsBatchQuery
Example prompts for the agent
- Write an async Python script to fetch AppExceptions from Log Analytics over the last 24 hours.
- Query CPU percentage and incoming network metrics for an Azure resource using MetricsQueryClient.
- Show how to run batch Kusto queries with LogsBatchQuery and convert the output to a DataFrame.
How to install azure-monitor-query-py
1Skills CLI (Vercel)
npx skills add microsoft/skills --skill azure-monitor-query-py -a claude-code2Manually: put the files in place
~/.claude/skills/azure-monitor-query-py/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/azure-monitor-query-py/
Manually: put the files in place
.agents/skills/azure-monitor-query-py/SKILL.mdFor all projects use ~/.agents/skills/
Manually: put the files in place
.cursor/skills/azure-monitor-query-py/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install microsoft/skills azure-monitor-query-py2Manually: put the files in place
.github/skills/azure-monitor-query-py/SKILL.mdPlatform CLI
gemini skills install https://github.com/microsoft/skills --path .github/plugins/azure-sdk-python/skills/azure-monitor-query-pyManually: put the files in place
.devin/skills/azure-monitor-query-py/SKILL.mdThe legacy .windsurf/skills/ path still works
Claude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about azure-monitor-query-py
How to install azure-monitor-query-py in Claude Code?
Run npx skills add microsoft/skills --skill azure-monitor-query-py -a claude-code. The skill file is placed at ~/.claude/skills/azure-monitor-query-py/SKILL.md.
What does azure-monitor-query-py do?
It provides guidelines and code patterns for using the azure-monitor-query Python library. The skill helps agents run Kusto log queries, fetch resource metrics, and set up DefaultAzureCredential authentication.
Which environment variables are required by the generated scripts?
Querying logs requires AZURE_LOG_ANALYTICS_WORKSPACE_ID, while metrics queries need AZURE_METRICS_RESOURCE_URI. In production, set AZURE_TOKEN_CREDENTIALS=prod to constrain credential resolution.
Source text
SKILL.md · MIT
---
name: azure-monitor-query-py
description: |
Azure Monitor Query SDK for Python. Use for querying Log Analytics workspaces and Azure Monitor metrics.
Triggers: "azure-monitor-query", "LogsQueryClient", "MetricsQueryClient", "Log Analytics", "Kusto queries", "Azure metrics".
license: MIT
metadata:
author: Microsoft
version: "1.0.0"
package: azure-monitor-query
---
# Azure Monitor Query SDK for Python
Query logs and metrics from Azure Monitor and Log Analytics workspaces.
## Installation
```bash
pip install azure-monitor-query
```
## Environment Variables
```bash
# Log Analytics
AZURE_LOG_ANALYTICS_WORKSPACE_ID=<workspace-id> # Required for log queries
# Metrics
AZURE_METRICS_RESOURCE_URI=/subscriptions/<sub>/resourceGroups/<rg>/providers/<provider>/<type>/<name> # Required for metric queries
AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production
```
## Authentication & Lifecycle
> **🔑 Two rules apply to every code sample below:**
>
> 1. **Prefer `DefaultAzureCredential`.** It works locally (Azure CLI / VS Code / Developer CLI) and in Azure (managed identity, workload identity) with no code change. Avoid connection strings, account/API keys — they bypass Entra audit and rotation.
> - Local dev: `DefaultAzureCredential` works as-is.
> - Production: set `AZURE_TOKEN_CREDENTIALS=prod` (or `AZURE_TOKEN_CREDENTIALS=<specific_credential>`) to constrain the credential chain to production-safe credentials.
> 2. **Wrap every client in a context manager** so HTTP transports, sockets, and token caches are released deterministically:
> - Sync: `with <Client>(...) as client:`
> - Async: `async with <Client>(...) as client:` **and** `async with DefaultAzureCredential() as credential:` (from `azure.identity.aio`)
>
> Snippets may abbreviate this setup, but production code should always follow both rules.
```python
from azure.identity import DefaultAzureCredential, ManagedIdentityCredential
# Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
credential = DefaultAzureCredential(require_envvar=True)
# Or use a specific credential directly in production:
# See https://learn.microsoft.com/python/api/overview/azure/identity-readme?view=azure-python#credential-classes
# credential = ManagedIdentityCredential()
```
## Logs Query Client
### Basic Query
```python
from azure.monitor.query import LogsQueryClient
from datetime import timedelta
query = """
AppRequests
| where TimeGenerated > ago(1h)
| summarize count() by bin(TimeGenerated, 5m), ResultCode
| order by TimeGenerated desc
"""
with LogsQueryClient(credential) as client:
response = client.query_workspace(
workspace_id=os.environ["AZURE_LOG_ANALYTICS_WORKSPACE_ID"],
query=query,
timespan=timedelta(hours=1)
)
for table in response.tables:
for row in table.rows:
print(row)
```
### Query with Time Range
```python
from datetime import datetime, timezone
response = client.query_workspace(
workspace_id=workspace_id,
query="AppRequests | take 10",
timespan=(
datetime(2024, 1, 1, tzinfo=timezone.utc),
datetime(2024, 1, 2, tzinfo=timezone.utc)
)
)
```
### Convert to DataFrame
```python
import pandas as pd
response = client.query_workspace(workspace_id, query, timespan=timedelta(hours=1))
if response.tables:
table = response.tables[0]
df = pd.DataFrame(data=table.rows, columns=[col.name for col in table.columns])
print(df.head())
```
### Batch Query
```python
from azure.monitor.query import LogsBatchQuery
queries = [
LogsBatchQuery(workspace_id=workspace_id, query="AppRequests | take 5", timespan=timedelta(hours=1)),
LogsBatchQuery(workspace_id=workspace_id, query="AppExceptions | take 5", timespan=timedelta(hours=1))
]
responses = client.query_batch(queries)
for response in responses:
if response.tables:
print(f"Rows: {len(response.tables[0].rows)}")
```
### Handle Partial Results
```python
from azure.monitor.query import LogsQueryStatus
response = client.query_workspace(workspace_id, query, timespan=timedelta(hours=24))
if response.status == LogsQueryStatus.PARTIAL:
print(f"Partial results: {response.partial_error}")
elif response.status == LogsQueryStatus.FAILURE:
print(f"Query failed: {response.partial_error}")
```
## Metrics Query Client
### Query Resource Metrics
```python
from azure.monitor.query import MetricsQueryClient
from datetime import timedelta
with MetricsQueryClient(credential) as metrics_client:
response = metrics_client.query_resource(
resource_uri=os.environ["AZURE_METRICS_RESOURCE_URI"],
metric_names=["Percentage CPU", "Network In Total"],
timespan=timedelta(hours=1),
granularity=timedelta(minutes=5)
)
for metric in response.metrics:
print(f"{metric.name}:")
for time_series in metric.timeseries:
for data in time_series.data:
print(f" {data.timestamp}: {data.average}")
```
### Aggregations
```python
from azure.monitor.query import MetricAggregationType
response = metrics_client.query_resource(
resource_uri=resource_uri,
metric_names=["Requests"],
timespan=timedelta(hours=1),
aggregations=[
MetricAggregationType.AVERAGE,
MetricAggregationType.MAXIMUM,
MetricAggregationType.MINIMUM,
MetricAggregationType.COUNT
]
)
```
### Filter by Dimension
```python
response = metrics_client.query_resource(
resource_uri=resource_uri,
metric_names=["Requests"],
timespan=timedelta(hours=1),
filter="ApiName eq 'GetBlob'"
)
```
### List Metric Definitions
```python
definitions = metrics_client.list_metric_definitions(resource_uri)
for definition in definitions:
print(f"{definition.name}: {definition.unit}")
```
### List Metric Namespaces
```python
namespaces = metrics_client.list_metric_namespaces(resource_uri)
for ns in namespaces:
print(ns.fully_qualified_namespace)
```
## Async Clients
```python
from azure.monitor.query.aio import LogsQueryClient, MetricsQueryClient
from azure.identity.aio import DefaultAzureCredential
async def query_logs():
async with DefaultAzureCredential() as credential:
async with LogsQueryClient(credential) as client:
response = await client.query_workspace(
workspace_id=workspace_id,
query="AppRequests | take 10",
timespan=timedelta(hours=1)
)
return response
```
## Common Kusto Queries
```kusto
// Requests by status code
AppRequests
| summarize count() by ResultCode
| order by count_ desc
// Exceptions over time
AppExceptions
| summarize count() by bin(TimeGenerated, 1h)
// Slow requests
AppRequests
| where DurationMs > 1000
| project TimeGenerated, Name, DurationMs
| order by DurationMs desc
// Top errors
AppExceptions
| summarize count() by ExceptionType
| top 10 by count_
```
## Client Types
| Client | Purpose |
|--------|---------|
| `LogsQueryClient` | Query Log Analytics workspaces |
| `MetricsQueryClient` | Query Azure Monitor metrics |
## Best Practices
1. **Pick sync OR async and stay consistent.** Do not mix `azure.xxx` sync clients with `azure.xxx.aio` async clients in the same call path. Choose one mode per module.
2. **Always use context managers for clients and async credentials.** Wrap every client in `with Client(...) as client:` (sync) or `async with Client(...) as client:` (async). For async `DefaultAzureCredential` from `azure.identity.aio`, also use `async with credential:` so tokens and transports are cleaned up.
3. **Use `DefaultAzureCredential`** for portable auth across local dev and Azure (avoid connection strings / API keys when possible).
4. **Use timedelta** for relative time ranges
4. **Handle partial results** for large queries
5. **Use batch queries** when running multiple queries
6. **Set appropriate granularity** for metrics to reduce data points
7. **Convert to DataFrame** for easier data analysis
8. **Use aggregations** to summarize metric data
9. **Filter by dimensions** to narrow metric results
## Reference Files
| File | Contents |
|------|----------|
| [references/capabilities.md](references/capabilities.md) | Additional non-hero capabilities, operation-group coverage, and production checklists. |
| [references/non-hero-scenarios.md](references/non-hero-scenarios.md) | Dedicated non-hero examples for secondary/advanced scenarios. |
© Microsoft · MIT · microsoft/skills