通過阿里雲 CMS OpenAPI(ServiceTaskController,API 版本 2024-03-30)管理 Live-Debug 探針任務,在不重啟應用的情況下動態下發代碼探針(LOG / SNAPSHOT / METRIC / SPAN / SPAN_TAG),即時採集函數入參、傳回值、自訂指標等運行時資料,並通過 SLS 查詢採集結果。本文僅覆蓋 Python 應用(Probe 探針任務)。
介面一覽
操作 | HTTP | Path | CLI 命令 |
建立任務 |
|
|
|
列舉任務 |
|
|
|
查詢單個任務 |
|
|
|
刪除任務 |
|
|
|
查詢採集結果 | SLS | (非 CMS) |
|
路徑參數(Path)
參數 | 類型 | 必填 | 說明 |
| string | 是 | ARMS 工作空間 ID,如 |
| string | 是 | 應用/服務 ID,如 |
| string | Get/Delete 必填 | 建立介面返回的任務 ID |
公用 CLI 參數
參數 | 說明 | 預設 |
| 接入地區;CMS 與 SLS 命令都建議顯式傳入,避免依賴 CLI 預設地區 | 阿里雲 CLI 配置的預設地區 |
| 直接指定 CMS endpoint,覆蓋按 region 的推導 |
|
| 縮排 JSON 輸出(預設 |
|
建立任務(CreateServiceTask)
請求
POST /serviceTask/{workspace}/{serviceId}/task
Content-Type: application/jsonBody 參數
參數 | 類型 | 必填 | 說明 |
| string | 是 | 任務類型,即 |
| string | 是 | 目標執行個體 IP;匹配全部執行個體填 |
| string(JSON 文本) | 是 | 扁平的單命令/單探針配置;服務端按字串儲存。CLI 的 |
調用樣本:
aliyun cms2 apm service-task create \
--workspace <workspace> --service-id <serviceId> \
--type <taskType> --ip '<targetIp>' \
--task-config '<taskConfigJson>' \
--region <regionId> -o json匹配全部執行個體時
--ip傳*。--task-config直接傳原始 JSON 對象,無需手動二次轉義。
響應(CLI 輸出)
{
"success": true,
"data": {
"requestId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"taskId": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"
}
}欄位 | 說明 |
| 本次請求 ID |
| 任務 ID;查詢 SLS 結果、Get、Delete 均使用該值 |
Body 樣本(CLI 拼裝後的 HTTP 形態)
{
"type": "live_debug_log_probe",
"ip": "*",
"taskConfig": "{\"probeType\":\"LOG\",\"language\":\"python\",\"target\":{\"typeName\":\"app.service.order\",\"methodName\":\"OrderService.create_order\",\"location\":\"exit\",\"instanceIds\":[\"*\"]},\"action\":{\"type\":\"LOG\",\"template\":\"id={order_id}\"},\"ttl\":\"30m\",\"captureCount\":100}"
}HTTP Body 裡 taskConfig 是轉義後的 JSON 字串;向 CLI --task-config 傳參時傳未轉義的對象 JSON 即可,轉義由 CLI 完成。
列舉任務(ListServiceTask)
請求
GET /serviceTask/{workspace}/{serviceId}/tasks?type={taskType}&maxResults={n}Query 參數
參數 | 類型 | 必填 | 說明 |
| string | 是 | 精確匹配的任務類型,如 |
| int | 否 | 返回條數上限,預設 |
響應欄位
CLI 輸出 data.serviceTasks[] 數組,每項常見欄位:
欄位 | 說明 |
| 任務 ID |
| 任務類型 |
| 服務 ID |
| 建立時指定的 IP / |
| 建立時間 |
| 更新時間 |
| 任務配置(扁平探針對象) |
調用樣本:
aliyun cms2 apm service-task list \
--workspace <workspace> --service-id <serviceId> \
--type <taskType> --max-results 100 \
--region <regionId> -o json查詢單個任務(GetServiceTask)
請求
GET /serviceTask/{workspace}/{serviceId}/task/{taskId}?type={taskType}Query 參數
參數 | 類型 | 必填 | 說明 |
| string | 是 | 必須與任務實際類型一致 |
響應
CLI 輸出 data.serviceTask 對象,欄位同 List 單項。
調用樣本:
aliyun cms2 apm service-task get \
--workspace <workspace> --service-id <serviceId> \
--task-id <taskId> --type <taskType> \
--region <regionId> -o json刪除任務(DeleteServiceTask)
請求
DELETE /serviceTask/{workspace}/{serviceId}/task/{taskId}?type={taskType}Query 參數
參數 | 類型 | 必填 | 說明 |
| string | 是 | 必須與任務實際類型一致 |
刪除後服務端移除任務並 syncToConfigServer,Agent 側對應探針隨之失效。這是停用已下發探針的正確方式。
調用樣本:
aliyun cms2 apm service-task delete \
--workspace <workspace> --service-id <serviceId> \
--task-id <taskId> --type <taskType> \
--region <regionId> -o json批量清空某服務下全部 Probe(List 按 type 精確過濾,需對五種 probe type 逐個 list + delete):
WS=<workspace>; SVC=<serviceId>; REGION=<regionId>
for t in live_debug_log_probe live_debug_snapshot_probe \
live_debug_metric_probe live_debug_span_probe live_debug_span_tag_probe; do
aliyun cms2 apm service-task list \
--workspace "$WS" --service-id "$SVC" --type "$t" --region "$REGION" -o json |
python3 -c 'import sys,json; [print(t["taskId"]) for t in (json.load(sys.stdin)["data"].get("serviceTasks") or [])]' |
while read -r id; do
aliyun cms2 apm service-task delete \
--workspace "$WS" --service-id "$SVC" \
--task-id "$id" --type "$t" --region "$REGION" -o json
done
done查詢採集結果(SLS)
採集狀態與結果寫入 SLS,不通過 CMS Get 介面返回業務資料。
調用樣本(查詢最近 10 分鐘,<taskId> 為建立返回的任務 ID):
FROM=$(( $(date +%s) - 600 )); TO=$(date +%s)
# 任務狀態(安裝狀態、funnel 指標)
aliyun sls get-logs-v2 --region <regionId> --accept-encoding gzip \
--project <slsProject> --logstore logstore-apm-logs \
--from "$FROM" --to "$TO" \
--query "* and \"<taskId>\" | SELECT content FROM log WHERE json_extract_scalar(attributes, '\$[\"livedebug.report_type\"]') = 'status'"
# 採集結果(實際捕獲資料)
aliyun sls get-logs-v2 --region <regionId> --accept-encoding gzip \
--project <slsProject> --logstore logstore-apm-logs \
--from "$FROM" --to "$TO" \
--query "* and \"<taskId>\" | SELECT content FROM log WHERE json_extract_scalar(attributes, '\$[\"livedebug.report_type\"]') != 'status'"參數 | 必填 | 說明 |
| 是 | 應用接入的 SLS Project(如 |
| 是 | 預設 |
| 是 | Unix 秒級時間戳記查詢區間 |
| 是 | 與 Project 同地區,需顯式傳入 |
兩類查詢:
類型 | 過濾條件 | 含義 |
Task Status |
| 安裝狀態、funnel 指標 |
Capture Results |
| 實際採集資料 |
SLS Project 按地區隔離。--region 錯誤會報 ProjectNotExist。
任務類型枚舉(taskType/type)
Probe(代碼增強)
| 探針類型 |
| LOG |
| SNAPSHOT |
| METRIC |
| SPAN |
| SPAN_TAG |
命名規則:live_debug_ + 探針語義小寫 + _probe。五種探針 Python 均支援。
Probe taskConfig 通用結構
建立時傳入的扁平對象(--task-config 入參形態):
{
"probeType": "LOG|SNAPSHOT|METRIC|SPAN|SPAN_TAG",
"language": "python",
"target": { },
"action": { },
"trigger": { },
"rateLimit": { },
"ttl": "1h",
"captureCount": 100,
"enabled": true
}頂層欄位
欄位 | 類型 | 必填 | 說明 |
| string | 是 |
|
| string | 是 | 固定 |
| object | 是 | 定位目標方法/行 |
| object | 是 | 探針動作;結構隨 |
| object | 否 | 觸發條件 |
| object | 否 | 速率控制 |
| string | 與 | 存活時間長度。支援 |
| int | 與 | 最大採集次數;與 ttl 任一先滿足即終止 |
| boolean | 否 | 建立時通常為 |
target — 定位目標
欄位 | 類型 | 必填 | 說明 |
| string | 函數級建議必填 | 模組名( |
| string | 函數級建議必填 | 函數 |
| string | 否(行級建議填) | 源碼檔案名稱或路徑尾碼 |
| string | 否 | Hook 點: |
| string[] | 強烈建議必填 | 生效執行個體 ID 列表,必須放在 target 內(不要放 |
| string[] | 否 | 生效 IP 列表;與 |
行級探針可主要依賴 sourceFile + location:"line:N"。
trigger — 觸發條件(可選)
欄位 | 類型 | 預設 | 說明 |
| string | - | 為真時才採集 |
| string | - | 調用方過濾(Python 情境較少使用) |
條件樣本:amount > 10000 或 @return is None or amount > 10000
運算式規則:
直接使用參數名/局部變數/模組全域變數。
exit/exception可用@return、@duration(毫秒)、@exception。不要使用 OGNL、
args[0]、returnValue、durationMs。若條件引用
@return/@exception,探針location必須是exit或exception。
rateLimit — 速率控制(可選)
欄位 | 類型 | 預設 | 說明 |
| int | 按探針類型(見下) | 令牌桶每秒最多執行次數 |
| double | 1.0 | 隨機允許存取機率(0~1) |
| int | 100 | 單次採集逾時(ms) |
預設限流:LOG/METRIC/SPAN/SPAN_TAG 約 5000 次/秒,SNAPSHOT 約 1 次/秒;行級探針另有全域約 100 次/秒保護。
Probe action 按類型填寫
LOG(taskType: live_debug_log_probe)
在目標點輸出動態日誌;不做對象圖序列化。
action 欄位
欄位 | 類型 | 必填 | 說明 |
| string | 是 | 固定 |
| string | 是 | 日誌模板, |
LOG 探針只渲染模板,會忽略 capture 維度。需要采參數/傳回值/棧請用 SNAPSHOT。
樣本:
{
"probeType": "LOG",
"language": "python",
"target": {
"typeName": "app.service.order",
"methodName": "OrderService.create_order",
"location": "exit",
"instanceIds": ["*"]
},
"action": {
"type": "LOG",
"template": "create_order id={order_id} amount={amount} ret={@return} cost={@duration}ms"
},
"ttl": "30m",
"captureCount": 100
}SNAPSHOT(taskType: live_debug_snapshot_probe)
採集方法快照並做對象圖序列化上報。
action 欄位
欄位 | 類型 | 必填 | 說明 |
| string | 是 | 固定 |
| string[] | 是 | 採集維度枚舉;不傳或 |
| string[] | 否 | 額外求值運算式列表 |
| object | 否 | 對象圖序列化預算 |
capture 枚舉
值 | 說明 |
| 序列化方法參數 |
| 序列化傳回值 |
| 序列化當前執行個體 |
| 記錄異常摘要 |
| 採集局部變數(依賴調試資訊) |
| 採集調用棧(opt-in,需顯式包含) |
| 方法體內子調用彙總 |
captureConfig
欄位 | 預設 | 說明 |
| 3 | 對象序列化最大深度 |
| 100 | 集合/數組最大元素數 |
| 1024 | 字串最大長度 |
| 50 | 對象最大欄位數 |
| 65536 | 單次快照最大位元組數 |
| 50 | 調用棧最大深度 |
|
| 脫敏欄位正則 |
captureExpressions
文法同 trigger.condition / LOG 模板(受限 eval)。結果寫入 context.evaluatedExpressions,每項形如:
{"name": "order_id", "type": "...", "value": "...", "notCapturedReason": null}求值失敗時 value=null 且 notCapturedReason 記錄原因,不影響其它維度。captureExpressions 與 capture 相互獨立。
樣本:
{
"probeType": "SNAPSHOT",
"language": "python",
"target": {
"typeName": "app.service.order",
"methodName": "OrderService.create_order",
"location": "exit",
"instanceIds": ["*"]
},
"trigger": {
"condition": "@return is None or amount > 10000"
},
"action": {
"type": "SNAPSHOT",
"capture": ["ARGS"],
"captureExpressions": ["order_id", "amount * count", "self.user_id", "@return"],
"captureConfig": {
"maxDepth": 3,
"maxCollectionSize": 100,
"maxStringLength": 1024
}
},
"ttl": "30m",
"captureCount": 50
}METRIC(taskType: live_debug_metric_probe)
在目標點產生自訂指標,寫入監控系統。
action 欄位
欄位 | 類型 | 必填 | 說明 |
| string | 是 | 固定 |
| string | 是 | 指標名,如 |
| string | 是 |
|
| string | 是 | 指標值的 Python 運算式 |
| object | 否 | 標籤 map;值是 Python 運算式字串 |
樣本:
{
"probeType": "METRIC",
"language": "python",
"target": {
"typeName": "app.service.order",
"methodName": "OrderService.create_order",
"location": "exit",
"instanceIds": ["*"]
},
"action": {
"type": "METRIC",
"metricName": "livedebug.order.amount",
"metricType": "HISTOGRAM",
"valueExpression": "amount",
"tags": {
"is_vip": "str(user_id == 'vip')"
}
},
"ttl": "1h"
}SPAN(taskType: live_debug_span_probe)
在目標函數執行期間建立 OTel Span;異常時標記 ERROR 並記錄 exception event。僅函數級。
action 欄位
欄位 | 類型 | 必填 | 說明 |
| string | 是 | 固定 |
| string | 是 | Span 名稱 |
| object | 否 | 屬性 map;值為 Python 運算式字串 |
樣本:
{
"probeType": "SPAN",
"language": "python",
"target": {
"typeName": "app.service.order",
"methodName": "OrderService.create_order",
"location": "enter",
"instanceIds": ["*"]
},
"action": {
"type": "SPAN",
"spanName": "dyn.create_order",
"spanTags": {
"order.id": "str(order_id)",
"order.amount": "str(amount)"
}
},
"ttl": "1h"
}SPAN_TAG(taskType: live_debug_span_tag_probe)
給當前活躍 Span 追加屬性;無活躍 Span 時靜默跳過。
action 欄位
欄位 | 類型 | 必填 | 說明 |
| string | 是 | 固定 |
| array | 是 | 標籤數組,每項 |
樣本:
{
"probeType": "SPAN_TAG",
"language": "python",
"target": {
"typeName": "app.service.order",
"methodName": "OrderService.create_order",
"location": "exit",
"instanceIds": ["*"]
},
"action": {
"type": "SPAN_TAG",
"tags": [
{"key": "order.id", "value": "str(order_id)"},
{"key": "order.result", "value": "str(@return)"}
]
},
"ttl": "1h"
}錯誤與注意事項
現象 | 可能原因 | 處理建議 |
| SLS region 不正確 |
|
List 結果為空白但任務存在 |
| 按精確類型分別 List |
建立 | 不會影響已下發任務 | 使用 DeleteServiceTask 刪除任務 |
探針無資料 |
| 填 |
SPAN 建立失敗或無效 | 使用了 | 改為函數級 |
ttl 異常 | 使用了 | 改用 |
完整調用鏈路樣本(LOG 探針)
# 0. 環境
REGION=cn-hangzhou
SLS_PROJECT=proj-xtrace-xxxxxxxxxxxxxxxxxxxxxx-cn-hangzhou
WORKSPACE=default-cms-xxxxxxxxxxxxxxxxxx-cn-hangzhou
SERVICE_ID='ggxw4lnjuz@f2fd3a6265a254a052afb'
# 1. 建立
RESP=$(aliyun cms2 apm service-task create \
--workspace "$WORKSPACE" --service-id "$SERVICE_ID" \
--type live_debug_log_probe --ip '*' \
--task-config '{"probeType":"LOG","language":"python","target":{"typeName":"app.service.order","methodName":"OrderService.create_order","location":"exit","instanceIds":["*"]},"action":{"type":"LOG","template":"id={order_id} ret={@return}"},"ttl":"30m","captureCount":50}' \
--region "$REGION" -o json)
echo "$RESP"
TASK_ID=$(echo "$RESP" | python3 -c 'import sys,json; print(json.load(sys.stdin)["data"]["taskId"])')
# 2. 確認任務
aliyun cms2 apm service-task get \
--workspace "$WORKSPACE" --service-id "$SERVICE_ID" \
--task-id "$TASK_ID" --type live_debug_log_probe \
--region "$REGION" -o json
# 3. 觸發業務後查結果(最近 10 分鐘)
FROM=$(( $(date +%s) - 600 )); TO=$(date +%s)
aliyun sls get-logs-v2 --region "$REGION" --accept-encoding gzip \
--project "$SLS_PROJECT" --logstore logstore-apm-logs \
--from "$FROM" --to "$TO" \
--query "* and \"$TASK_ID\" | SELECT content FROM log WHERE json_extract_scalar(attributes, '\$[\"livedebug.report_type\"]') != 'status'"
# 4. 清理
aliyun cms2 apm service-task delete \
--workspace "$WORKSPACE" --service-id "$SERVICE_ID" \
--task-id "$TASK_ID" --type live_debug_log_probe \
--region "$REGION" -o json