Azure Monitor Logs 工具手册
先把五个标识分开
Azure Monitor Logs 以 Log Analytics workspace 和 table 承载日志查询,Data Collection Rule(DCR)描述输入 stream、变换和目标。程序通过 Logs Ingestion API 直写时,URL 需要 DCR 的 logs ingestion endpoint、DCR immutable ID 和 stream name;查询又使用 workspace GUID。ARM resource ID 则用于资源管理与 RBAC。
这些值外观相近,职责完全不同。把 workspace GUID 填进 ARM scope、把 resource ID 放进摄取 URL,或者给 workspace Reader 却没给 DCR 发送权限,都会产生看似相同的 401/403/空查询。官方 Logs Ingestion API 概览 应作为端点与对象语义基线。
创建隔离的 workspace 与 table
下面使用 Linux Bash、curl 和按官方步骤安装的 Azure CLI,以当前登录用户做一次独立实验。执行者除了创建资源,还需要写 role assignment;普通 Contributor 不具备这一动作。生产发送端应使用 managed identity 或 federated credential,不应下载长期 client secret。各段在同一专用终端执行,发生错误先处理,不继续创建依赖资源。
set -euo pipefail
az login
az account show --query '{subscription:id,tenant:tenantId,user:user.name}' -o json
SUBSCRIPTION_ID=$(az account show --query id -o tsv)
test -n "$SUBSCRIPTION_ID"
LAB_ID="$(date -u +%Y%m%d%H%M%S)-$RANDOM"
RG="rg-log-lab-$LAB_ID"
LOCATION=eastus
WORKSPACE="law-log-lab-$LAB_ID"
AZ_TMP=$(mktemp -d "${TMPDIR:-/tmp}/azure-log-lab.XXXXXXXX")
EXISTS=$(az group exists --name "$RG" --subscription "$SUBSCRIPTION_ID")
test "$EXISTS" = false || { echo 'refuse existing resource group' >&2; exit 1; }
az group create --name "$RG" --location "$LOCATION" \
--tags log-lab-owner="$LAB_ID" purpose=tool-efficiency-lab
az monitor log-analytics workspace create \
--resource-group "$RG" --workspace-name "$WORKSPACE" \
--location "$LOCATION" --retention-time 30
WORKSPACE_ID=$(az monitor log-analytics workspace show \
--resource-group "$RG" --workspace-name "$WORKSPACE" \
--query customerId -o tsv)
WORKSPACE_RESOURCE_ID=$(az monitor log-analytics workspace show \
--resource-group "$RG" --workspace-name "$WORKSPACE" \
--query id -o tsv)WORKSPACE_ID 是查询 API 使用的 GUID,WORKSPACE_RESOURCE_ID 是 Azure Resource Manager 路径。自定义 table 必须先存在,名称带 _CL 后缀。URL 中三个 api-version 分别指定表管理、DCR 管理与日志摄取的接口版本,保留所选版本,不要改成当天日期。
az rest --method put \
--url "https://management.azure.com${WORKSPACE_RESOURCE_ID}/tables/Checkout_CL?api-version=2022-10-01" \
--body '{
"properties": {
"schema": {
"name": "Checkout_CL",
"columns": [
{"name":"TimeGenerated","type":"datetime"},
{"name":"Service","type":"string"},
{"name":"TraceId","type":"string"},
{"name":"Message","type":"string"}
]
},
"retentionInDays": 30,
"totalRetentionInDays": 30
}
}'DCR 既是 schema 契约,也是静默丢数点
下面的 DCR 声明输入 stream,把它送到 workspace 中的自定义 table。transformKql: source 不改动事件;真正部署时可以删字段、改类型、计算列或过滤,但每一条 transform 都要有“应通过”和“应过滤”的合成样本。
{
"location": "eastus",
"kind": "Direct",
"properties": {
"streamDeclarations": {
"Custom-CheckoutRaw": {
"columns": [
{"name":"TimeGenerated","type":"datetime"},
{"name":"Service","type":"string"},
{"name":"TraceId","type":"string"},
{"name":"Message","type":"string"}
]
}
},
"destinations": {
"logAnalytics": [
{
"workspaceResourceId": "WORKSPACE_RESOURCE_ID",
"name": "checkoutWorkspace"
}
]
},
"dataFlows": [
{
"streams": ["Custom-CheckoutRaw"],
"destinations": ["checkoutWorkspace"],
"transformKql": "source",
"outputStream": "Custom-Checkout_CL"
}
]
}
}保存为 $AZ_TMP/dcr.json,替换 workspace resource ID 后创建 DCR:
DCR="dcr-checkout-$LAB_ID"
DCR_RESOURCE_ID="/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RG/providers/Microsoft.Insights/dataCollectionRules/$DCR"
sed -i "s|WORKSPACE_RESOURCE_ID|$WORKSPACE_RESOURCE_ID|" "$AZ_TMP/dcr.json"
az rest --method put \
--url "https://management.azure.com${DCR_RESOURCE_ID}?api-version=2023-03-11" \
--body "@$AZ_TMP/dcr.json"
DCR_IMMUTABLE_ID=$(az rest \
--url "https://management.azure.com${DCR_RESOURCE_ID}?api-version=2023-03-11" \
--query properties.immutableId -o tsv)
DCR_ENDPOINT=$(az rest \
--url "https://management.azure.com${DCR_RESOURCE_ID}?api-version=2023-03-11" \
--query properties.endpoints.logsIngestion -o tsv)kind: Direct 让新 DCR 获得直接摄取 endpoint;字段可对照 DCR API 模板参考和日志摄取教程。使用 Private Link,或 DCR 没有该 endpoint 时,才需要独立 Data Collection Endpoint(DCE)。旧 DCR 不能原地补出 endpoint,需要创建替代 DCR;这个差异在迁移时必须显式记录。若前面修改了 LOCATION,也要把 JSON 的 location 改成相同区域;读取到空 endpoint 时先检查创建结果,不拼接空 URL 继续发送。
发送权限和查询权限是两条链
发送者在 DCR scope 上需要 Monitoring Metrics Publisher,查询者在 workspace 或更细范围上获得只读角色。下面用当前登录用户验证实验,生产应用不应照搬用户身份:
PRINCIPAL_ID=$(az ad signed-in-user show --query id -o tsv)
az role assignment create \
--assignee-object-id "$PRINCIPAL_ID" --assignee-principal-type User \
--role "Monitoring Metrics Publisher" --scope "$DCR_RESOURCE_ID"
az role assignment create \
--assignee-object-id "$PRINCIPAL_ID" --assignee-principal-type User \
--role "Log Analytics Reader" --scope "$WORKSPACE_RESOURCE_ID"生成当前 UTC 时间的 JSON 数组。Logs Ingestion API 的 body 必须是数组,即使只有一条记录:
NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
cat > "$AZ_TMP/payload.json" <<EOF
[
{
"TimeGenerated": "$NOW",
"Service": "checkout",
"TraceId": "TE-AZ-001",
"Message": "payment timeout"
}
]
EOF
TOKEN=$(az account get-access-token \
--scope https://monitor.azure.com/.default --query accessToken -o tsv)
test -n "$DCR_ENDPOINT" && test -n "$DCR_IMMUTABLE_ID"
HTTP_STATUS=$(curl -q --silent --show-error --fail-with-body --max-time 30 \
--output "$AZ_TMP/ingest-response.txt" --write-out '%{http_code}' -X POST \
"${DCR_ENDPOINT}/dataCollectionRules/${DCR_IMMUTABLE_ID}/streams/Custom-CheckoutRaw?api-version=2023-01-01" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
--data-binary "@$AZ_TMP/payload.json")
unset TOKEN
test "$HTTP_STATUS" = 204 || { echo "unexpected HTTP: $HTTP_STATUS" >&2; exit 1; }HTTP 204 表示摄取 API 接纳了请求,不代表查询立即可见。等待处理后再按 workspace GUID 查询:
az monitor log-analytics query \
--workspace "$WORKSPACE_ID" \
--analytics-query 'Checkout_CL | where TraceId == "TE-AZ-001" | project TimeGenerated, Service, Message' \
--timespan PT1H -o table401 先查 token audience 与过期时间;403 查发送身份是否能访问 DCR;400 查 stream name、数组形状、字段类型和 transform。204 后长期无数据,要查 DCR 目标 table、transformKql、workspace region、table 摄取状态与 DCR 自身错误日志。查询 403 属于另一条读权限链,不能反推摄取失败。
table plan 会改变能力,不只是单价
Analytics、Basic、Auxiliary 等 table plan 会改变查询、保留与交互能力。为了降低摄取单价切换 plan,却继续假设所有 KQL、告警和查询延迟保持不变,是一种常见的迁移失误。变更前要用真实查询集验证扫描量、延迟和缺失操作。
成本通常包括摄取与保留,还可能叠加查询、search job、restore、export、Sentinel、dedicated cluster、跨区域 DCR、Event Hub、Storage 与 Private Link。配额和 API 限制随订阅、region、table plan 与合同变化,容量评审应读取目标订阅的 Usage and estimated costs、服务限制和 DCR 指标。
Azure Monitor Agent 与 Logs Ingestion API 都可能经过 DCR。平台应监控 DCR 的接收量、处理错误和 transformation 结果;只看 workspace 里偶尔出现数据,无法证明日志链完整。
实验清理与生产退出不是同一动作
清理前先从内存移除访问令牌,再核对订阅、资源组前缀和 owner tag。三项任一不匹配就停止:
unset TOKEN
(
set -euo pipefail
: "${SUBSCRIPTION_ID:?}" "${LAB_ID:?}" "${RG:?}"
test "$RG" = "rg-log-lab-$LAB_ID" || { echo 'refuse unexpected RG' >&2; exit 1; }
CURRENT_SUBSCRIPTION=$(az account show --query id -o tsv) || exit 1
test "$CURRENT_SUBSCRIPTION" = "$SUBSCRIPTION_ID" \
|| { echo 'refuse changed subscription' >&2; exit 1; }
OWNER=$(az group show --name "$RG" --subscription "$SUBSCRIPTION_ID" \
--query 'tags."log-lab-owner"' -o tsv) || exit 1
test "$OWNER" = "$LAB_ID" || { echo 'refuse owner mismatch' >&2; exit 1; }
az group delete --name "$RG" --subscription "$SUBSCRIPTION_ID" --yes
)这段删除只适用于本次独立实验资源组。检查失败会退出子 Shell,不调用删除 API。删除命令成功后,可用 az group exists --name "$RG" --subscription "$SUBSCRIPTION_ID" 确认返回 false;若调用超时,先查询实际状态,不直接重建同名资源。本地 $AZ_TMP 中的三个实验文件可逐个移除,再用 rmdir 删除空目录。
生产回滚 DCR 时应恢复旧 association 或旧摄取 endpoint,保留新旧 table 的核对窗口;删除 workspace 会同时影响查询、告警、Sentinel、导出和审计引用,不能作为普通配置回滚。
权威资料与规范地址
- Logs Ingestion API 概览:https://learn.microsoft.com/en-us/azure/azure-monitor/logs/logs-ingestion-api-overview
- 官方步骤安装的 Azure CLI:https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-linux
- DCR API 模板参考:https://learn.microsoft.com/en-us/azure/templates/microsoft.insights/2023-03-11/datacollectionrules
- 日志摄取教程:https://learn.microsoft.com/en-us/azure/azure-monitor/logs/tutorial-logs-ingestion-api
