azure-monitor-query-py — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited azure-monitor-query-py (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Query logs and metrics from Azure Monitor and Log Analytics workspaces.
pip install azure-monitor-query# 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🔑 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:DefaultAzureCredentialworks as-is. - Production: setAZURE_TOKEN_CREDENTIALS=prod(orAZURE_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:andasync with DefaultAzureCredential() as credential:(fromazure.identity.aio)
>
Snippets may abbreviate this setup, but production code should always follow both rules.
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()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)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)
)
)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())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)}")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}")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}")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
]
)response = metrics_client.query_resource(
resource_uri=resource_uri,
metric_names=["Requests"],
timespan=timedelta(hours=1),
filter="ApiName eq 'GetBlob'"
)definitions = metrics_client.list_metric_definitions(resource_uri)
for definition in definitions:
print(f"{definition.name}: {definition.unit}")namespaces = metrics_client.list_metric_namespaces(resource_uri)
for ns in namespaces:
print(ns.fully_qualified_namespace)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// 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 | Purpose |
|---|---|
LogsQueryClient | Query Log Analytics workspaces |
MetricsQueryClient | Query Azure Monitor metrics |
azure.xxx sync clients with azure.xxx.aio async clients in the same call path. Choose one mode per module.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.| File | Contents |
|---|---|
| references/capabilities.md | Additional non-hero capabilities, operation-group coverage, and production checklists. |
| references/non-hero-scenarios.md | Dedicated non-hero examples for secondary/advanced scenarios. |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.