通过阿里云 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