
Alicloud Observability Pts
- 126 installs
- 396 repo stars
- Updated July 18, 2026
- cinience/alicloud-skills
Set up Alibaba Cloud PTS (Performance Testing Service) scenarios, virtual users, and reporting to benchmark API and web workload capacity before production launch.
About
cinience/alicloud-skills observability skill for Alibaba Cloud PTS: defines performance test plans, configures virtual users and scenarios, runs load/stress tests, and extracts latency and throughput metrics to validate SaaS and API readiness.
- PTS scenario and virtual user design
- Load, stress, and spike test execution
- Latency and throughput metric capture
- Bottleneck identification under concurrency
- Capacity planning inputs for autoscaling
Alicloud Observability Pts by the numbers
- 126 all-time installs (skills.sh)
- Ranked #528 of 1,039 Cloud & Infrastructure skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/cinience/alicloud-skills --skill alicloud-observability-ptsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 126 |
|---|---|
| repo stars | ★ 396 |
| Last updated | July 18, 2026 |
| Repository | cinience/alicloud-skills ↗ |
What it does
Set up Alibaba Cloud PTS (Performance Testing Service) scenarios, virtual users, and reporting to benchmark API and web workload capacity before production launch.
Files
Category: service
Alibaba Cloud Performance Testing Service (PTS)
Purpose
Use Alibaba Cloud PTS OpenAPI to support:
- test scene inventory and inspection
- pressure test planning and lifecycle automation
- report and metrics retrieval for verification and troubleshooting
Prerequisites
- Configure least-privilege Alibaba Cloud credentials.
- Install Python SDKs (virtual environment recommended):
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -U alibabacloud_pts20201020 alibabacloud_tea_openapi- Prefer environment variables:
ALICLOUD_ACCESS_KEY_IDALICLOUD_ACCESS_KEY_SECRET- optional
ALICLOUD_REGION_ID - Before mutating operations, run read-only API discovery and current-state checks.
AccessKey Priority
1) Environment variables: ALICLOUD_ACCESS_KEY_ID / ALICLOUD_ACCESS_KEY_SECRET / ALICLOUD_REGION_ID 2) Shared credentials file: ~/.alibabacloud/credentials
If region/environment is unclear, confirm with user before mutating operations.
Workflow
1) Identify target region, test scene identifiers, and operation scope. 2) Run API discovery to confirm API names and required parameters. 3) Execute read-only APIs first (List* / Get* / Describe*). 4) Execute mutating operations only after confirming rollback and change window. 5) Save outputs and evidence to output/alicloud-observability-pts/.
API Discovery
- Product code:
PTS - Default API version:
2020-10-20 - Metadata source:
https://api.aliyun.com/meta/v1/products/PTS/versions/2020-10-20/api-docs.json
Minimal Executable Quickstart
python skills/observability/pts/alicloud-observability-pts/scripts/list_openapi_meta_apis.pyOptional arguments:
python skills/observability/pts/alicloud-observability-pts/scripts/list_openapi_meta_apis.py \
--product-code PTS \
--version 2020-10-20 \
--output-dir output/alicloud-observability-ptsList scenes (read-only):
python skills/observability/pts/alicloud-observability-pts/scripts/list_pts_scenes.py \
--region cn-hangzhou \
--page-number 1 \
--page-size 10 \
--output output/alicloud-observability-pts/scenes.txtStart one scene (mutating):
python skills/observability/pts/alicloud-observability-pts/scripts/start_pts_scene.py \
--region cn-hangzhou \
--scene-id <scene-id> \
--wait \
--output output/alicloud-observability-pts/start-result.jsonStop one scene (mutating):
python skills/observability/pts/alicloud-observability-pts/scripts/stop_pts_scene.py \
--region cn-hangzhou \
--scene-id <scene-id> \
--wait \
--output output/alicloud-observability-pts/stop-result.jsonCommon Operation Map
- Scene inventory:
ListPtsScene,GetPtsScene,ListOpenJMeterScenes,GetOpenJMeterScene - Scene lifecycle:
CreatePtsScene,SavePtsScene,ModifyPtsScene,DeletePtsScene,DeletePtsScenes - Test execution control:
StartPtsScene,StopPtsScene,StartTestingJMeterScene,StopTestingJMeterScene - Debug control:
StartDebugPtsScene,StopDebugPtsScene,StartDebuggingJMeterScene,StopDebuggingJMeterScene - Reports/metrics:
ListPtsReports,GetPtsReportDetails,GetPtsSceneRunningData,GetPtsSceneRunningStatus
See references/api_quick_map.md for grouped API lists.
Script Catalog
scripts/list_openapi_meta_apis.py: fetch metadata and generate API inventory files.scripts/list_pts_scenes.py: list PTS scenes with pagination.scripts/start_pts_scene.py: start a scene and optionally poll running status.scripts/stop_pts_scene.py: stop a scene and optionally poll until non-running.
Output Policy
Write generated files and execution evidence to: output/alicloud-observability-pts/
Validation
mkdir -p output/alicloud-observability-pts
for f in skills/observability/pts/alicloud-observability-pts/scripts/*.py; do
python3 -m py_compile "$f"
done
echo "py_compile_ok" > output/alicloud-observability-pts/validate.txtPass criteria: command exits 0 and output/alicloud-observability-pts/validate.txt is generated.
Output And Evidence
- Save artifacts, command outputs, and API response summaries under
output/alicloud-observability-pts/. - Include key parameters (region/resource id/time range) in evidence files for reproducibility.
References
- Source list:
references/sources.md - API quick map:
references/api_quick_map.md - request/response templates:
references/templates.md
interface:
display_name: "Alibaba Cloud Observability PTS"
short_description: "PTS API discovery and safe operation workflows"
default_prompt: "Use $alicloud-observability-pts to complete this observability/pts task on Alibaba Cloud."
PTS API Quick Map (2020-10-20)
Source: https://api.aliyun.com/meta/v1/products/PTS/versions/2020-10-20/api-docs.json
Inventory And Resource Discovery
GetAllRegionsGetUserVpcsGetUserVpcVSwitchGetUserVpcSecurityGroupListEnvs
Scene Lifecycle
CreatePtsSceneSavePtsSceneModifyPtsSceneDeletePtsSceneDeletePtsScenesListPtsSceneGetPtsScene
Open JMeter Scene Lifecycle
SaveOpenJMeterSceneRemoveOpenJMeterSceneListOpenJMeterScenesGetOpenJMeterScene
Test Execution Control
StartPtsSceneStopPtsSceneAdjustPtsSceneSpeedGetPtsSceneRunningStatusGetPtsSceneRunningData
JMeter Test Execution Control
StartTestingJMeterSceneStopTestingJMeterSceneAdjustJMeterSceneSpeedGetJMeterSceneRunningData
Debug Control
StartDebugPtsSceneStopDebugPtsSceneGetPtsDebugSampleLogsStartDebuggingJMeterSceneStopDebuggingJMeterSceneGetJMeterSamplingLogs
Reports And Metrics
ListPtsReportsGetPtsReportsBySceneIdGetPtsReportDetailsListJMeterReportsGetJMeterReportDetailsGetJMeterSampleMetricsGetJMeterLogs
Baseline Management
CreatePtsSceneBaseLineFromReportGetPtsSceneBaseLineUpdatePtsSceneBaseLineDeletePtsSceneBaseLine
Environment Management
SaveEnvRemoveEnv
PTS Official Sources
- PTS product page in API Explorer:
- https://api.aliyun.com/product/PTS
- PTS OpenAPI metadata (machine-readable):
- https://api.aliyun.com/meta/v1/products/PTS/versions/2020-10-20/api-docs.json
- PTS product metadata:
- https://api.aliyun.com/meta/v1/products
- Alibaba Cloud API Explorer:
- https://api.aliyun.com/
- Alibaba Cloud PTS documentation:
- https://www.alibabacloud.com/help/en/pts
PTS Operation Templates
Use these templates as planning checklists before running PTS APIs. Replace placeholders with real values.
1) Read-only inventory template
- Goal: List current scenes and pick one target scene.
- Inputs:
- region:
<region-id> - filters:
<keyword / page size / scene type> - Recommended APIs:
ListPtsSceneListOpenJMeterScenesGetPtsScene(for one selected scene)- Evidence to save:
- request summary (region + filters)
- response summary (scene count + selected scene id)
- raw API output path in
output/alicloud-observability-pts/
2) Start a test template
- Goal: Start one bounded test run.
- Inputs:
- region:
<region-id> - scene id:
<scene-id> - run constraints:
<duration / concurrency / speed> - Recommended APIs:
GetPtsScene(pre-check)StartPtsSceneorStartTestingJMeterSceneGetPtsSceneRunningStatus/GetJMeterSceneRunningData(poll)- Safety checklist:
- Confirm change window.
- Confirm stop condition and owner.
- Confirm rollback:
StopPtsSceneorStopTestingJMeterScene.
3) Stop and verify template
- Goal: Stop an ongoing run and verify final state.
- Inputs:
- region:
<region-id> - scene id / report id:
<id> - Recommended APIs:
StopPtsSceneorStopTestingJMeterSceneGetPtsSceneRunningStatusListPtsReports/GetPtsReportDetails- Evidence to save:
- stop request timestamp
- final status
- report link/id and key metrics summary
4) Baseline update template
- Goal: Update baseline from a stable report.
- Inputs:
- scene id:
<scene-id> - report id:
<report-id> - baseline policy note:
<why this report is selected> - Recommended APIs:
GetPtsReportDetailsCreatePtsSceneBaseLineFromReportorUpdatePtsSceneBaseLineGetPtsSceneBaseLine(post-check)
5) Failure triage template
- Common checks:
- Invalid scene/config: call
GetPtsSceneand validate required fields. - Environment mismatch: validate
ListEnvsand VPC related APIs. - Runtime issues: inspect
GetPtsDebugSampleLogs,GetJMeterSamplingLogs,GetJMeterLogs. - Required failure record:
- exact API name
- error code and message
- request id and timestamp
- retry decision (yes/no) and reason
#!/usr/bin/env python3
"""Shared PTS client helpers for local scripts."""
from __future__ import annotations
import os
from typing import Tuple
def _get_env(*names: str) -> str | None:
for name in names:
value = os.getenv(name)
if value:
return value
return None
def create_client(region_id: str):
"""Return (pts_client, pts_models_module).
Imports PTS SDK lazily so scripts can provide a clear install hint.
"""
try:
from alibabacloud_pts20201020.client import Client as PtsClient
from alibabacloud_pts20201020 import models as pts_models
from alibabacloud_tea_openapi import models as open_api_models
except ImportError as exc: # pragma: no cover - compile-safe fallback
raise RuntimeError(
"Missing SDK dependencies. Install with: "
"python -m pip install -U alibabacloud_pts20201020 alibabacloud_tea_openapi"
) from exc
ak = _get_env("ALICLOUD_ACCESS_KEY_ID", "ALIBABA_CLOUD_ACCESS_KEY_ID")
sk = _get_env("ALICLOUD_ACCESS_KEY_SECRET", "ALIBABA_CLOUD_ACCESS_KEY_SECRET")
token = _get_env("ALICLOUD_SECURITY_TOKEN", "ALIBABA_CLOUD_SECURITY_TOKEN")
if not ak or not sk:
raise RuntimeError(
"Missing credentials: set ALICLOUD_ACCESS_KEY_ID and "
"ALICLOUD_ACCESS_KEY_SECRET (or ALIBABA_CLOUD_* equivalents)."
)
config = open_api_models.Config(
region_id=region_id,
endpoint=f"pts.{region_id}.aliyuncs.com",
)
config.access_key_id = ak
config.access_key_secret = sk
if token:
config.security_token = token
return PtsClient(config), pts_models
#!/usr/bin/env python3
"""Fetch PTS OpenAPI metadata API list and save artifacts to output/."""
from __future__ import annotations
import argparse
import json
import os
import pathlib
import urllib.request
DEFAULT_PRODUCT_CODE = "PTS"
DEFAULT_VERSION = "2020-10-20"
OUTPUT_DIR = pathlib.Path("output/alicloud-observability-pts")
def fetch_json(url: str, timeout: int) -> dict:
req = urllib.request.Request(url, headers={"User-Agent": "codex-skill"})
with urllib.request.urlopen(req, timeout=timeout) as resp:
return json.loads(resp.read().decode("utf-8"))
def parse_api_names(payload: dict) -> list[str]:
raw_apis = payload.get("apis", {})
if isinstance(raw_apis, dict):
return sorted(raw_apis.keys())
if isinstance(raw_apis, list):
names = []
for item in raw_apis:
if isinstance(item, dict):
name = item.get("name") or item.get("apiName")
if name:
names.append(name)
elif isinstance(item, str):
names.append(item)
return sorted(set(names))
return []
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--product-code", default=DEFAULT_PRODUCT_CODE)
parser.add_argument("--version", default=DEFAULT_VERSION)
parser.add_argument("--output-dir", default=str(OUTPUT_DIR))
args = parser.parse_args()
timeout = int(os.getenv("OPENAPI_META_TIMEOUT", "20"))
output_dir = pathlib.Path(args.output_dir)
output_dir.mkdir(parents=True, exist_ok=True)
url = (
f"https://api.aliyun.com/meta/v1/products/{args.product_code}"
f"/versions/{args.version}/api-docs.json"
)
payload = fetch_json(url, timeout)
api_names = parse_api_names(payload)
json_file = output_dir / f"{args.product_code}_{args.version}_api_docs.json"
md_file = output_dir / f"{args.product_code}_{args.version}_api_list.md"
json_file.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8")
lines = [
f"# {args.product_code} {args.version} API List",
"",
f"- Source: {url}",
f"- API count: {len(api_names)}",
"",
]
lines.extend([f"- `{name}`" for name in api_names])
md_file.write_text("\n".join(lines) + "\n", encoding="utf-8")
print(f"Saved: {json_file}")
print(f"Saved: {md_file}")
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""List PTS scenes in a region."""
from __future__ import annotations
import argparse
import json
import os
try:
from ._pts_client import create_client
except ImportError:
from _pts_client import create_client
def _render_table(scenes: list[dict], region: str, page_number: int, page_size: int) -> str:
header = f"{'SceneId':<20} {'SceneName':<36} {'Status':<16} {'CreateTime'}"
sep = "-" * len(header)
lines = [header, sep]
for scene in scenes:
lines.append(
f"{str(scene.get('SceneId', '-')):<20} "
f"{str(scene.get('SceneName', '-')):<36} "
f"{str(scene.get('Status', '-')):<16} "
f"{str(scene.get('CreateTime', '-'))}"
)
lines.append(sep)
lines.append(
f"Total page items: {len(scenes)} (region={region}, page_number={page_number}, page_size={page_size})"
)
return "\n".join(lines)
def main() -> int:
parser = argparse.ArgumentParser(description="List PTS scenes")
parser.add_argument("--region", default=os.getenv("ALICLOUD_REGION_ID", "cn-hangzhou"))
parser.add_argument("--keyword", help="Search by scene name or scene id")
parser.add_argument("--page-number", type=int, default=1)
parser.add_argument("--page-size", type=int, default=10)
parser.add_argument("--json", action="store_true", help="Output response body JSON")
parser.add_argument("--output", help="Write output to file")
args = parser.parse_args()
client, pts_models = create_client(args.region)
req = pts_models.ListPtsSceneRequest(
key_word=args.keyword,
page_number=args.page_number,
page_size=args.page_size,
)
resp = client.list_pts_scene(req)
body = resp.body.to_map() if resp.body else {}
scenes = body.get("SceneViewList") or []
if args.json:
output = json.dumps(body, ensure_ascii=False, indent=2)
else:
output = _render_table(scenes, args.region, args.page_number, args.page_size)
if args.output:
with open(args.output, "w", encoding="utf-8") as f:
f.write(output + ("\n" if not output.endswith("\n") else ""))
print(f"Output written to {args.output}")
else:
print(output)
return 0
if __name__ == "__main__":
raise SystemExit(main())
#!/usr/bin/env python3
"""Start a PTS scene and optionally poll running status."""
from __future__ import annotations
import argparse
import json
import os
import time
try:
from ._pts_client import create_client
except ImportError:
from _pts_client import create_client
RUNNING_STATES = {"RUNNING", "DEBUGGING"}
def main() -> int:
parser = argparse.ArgumentParser(description="Start a PTS scene")
parser.add_argument("--scene-id", required=True)
parser.add_argument("--region", default=os.getenv("ALICLOUD_REGION_ID", "cn-hangzhou"))
parser.add_argument("--wait", action="store_true", help="Poll running status after start")
parser.add_argument("--poll-interval", type=float, default=3.0)
parser.add_argument("--max-wait", type=int, default=120)
parser.add_argument("--output", help="Write JSON output to file")
args = parser.parse_args()
client, pts_models = create_client(args.region)
start_resp = client.start_pts_scene(pts_models.StartPtsSceneRequest(scene_id=args.scene_id))
start_body = start_resp.body.to_map() if start_resp.body else {}
result: dict[str, object] = {
"region": args.region,
"scene_id": args.scene_id,
"start_response": start_body,
}
if args.wait:
deadline = time.time() + args.max_wait
polls: list[dict] = []
final_status = None
while time.time() < deadline:
status_resp = client.get_pts_scene_running_status(
pts_models.GetPtsSceneRunningStatusRequest(scene_id=args.scene_id)
)
status_body = status_resp.body.to_map() if status_resp.body else {}
polls.append(status_body)
status = str(status_body.get("Status", "")).upper()
final_status = status
if status in RUNNING_STATES:
break
time.sleep(args.poll_interval)
result["status_polling"] = {
"timed_out": final_status not in RUNNING_STATES,
"final_status": final_status,
"attempts": len(polls),
"polls": polls,
}
output = json.dumps(result, ensure_ascii=False, indent=2)
if args.output:
with open(args.output, "w", encoding="utf-8") as f:
f.write(output)
print(f"Output written to {args.output}")
else:
print(output)
if args.wait:
sp = result.get("status_polling", {})
if isinstance(sp, dict) and sp.get("timed_out"):
return 2
return 0
if __name__ == "__main__":
raise SystemExit(main())
#!/usr/bin/env python3
"""Stop a PTS scene and optionally poll until it is not running."""
from __future__ import annotations
import argparse
import json
import os
import time
try:
from ._pts_client import create_client
except ImportError:
from _pts_client import create_client
RUNNING_STATES = {"RUNNING", "DEBUGGING", "WAITSTART"}
def main() -> int:
parser = argparse.ArgumentParser(description="Stop a PTS scene")
parser.add_argument("--scene-id", required=True)
parser.add_argument("--region", default=os.getenv("ALICLOUD_REGION_ID", "cn-hangzhou"))
parser.add_argument("--wait", action="store_true", help="Poll status after stop")
parser.add_argument("--poll-interval", type=float, default=3.0)
parser.add_argument("--max-wait", type=int, default=120)
parser.add_argument("--output", help="Write JSON output to file")
args = parser.parse_args()
client, pts_models = create_client(args.region)
stop_resp = client.stop_pts_scene(pts_models.StopPtsSceneRequest(scene_id=args.scene_id))
stop_body = stop_resp.body.to_map() if stop_resp.body else {}
result: dict[str, object] = {
"region": args.region,
"scene_id": args.scene_id,
"stop_response": stop_body,
}
if args.wait:
deadline = time.time() + args.max_wait
polls: list[dict] = []
final_status = None
while time.time() < deadline:
status_resp = client.get_pts_scene_running_status(
pts_models.GetPtsSceneRunningStatusRequest(scene_id=args.scene_id)
)
status_body = status_resp.body.to_map() if status_resp.body else {}
polls.append(status_body)
status = str(status_body.get("Status", "")).upper()
final_status = status
if status and status not in RUNNING_STATES:
break
time.sleep(args.poll_interval)
result["status_polling"] = {
"timed_out": final_status in RUNNING_STATES or final_status is None,
"final_status": final_status,
"attempts": len(polls),
"polls": polls,
}
output = json.dumps(result, ensure_ascii=False, indent=2)
if args.output:
with open(args.output, "w", encoding="utf-8") as f:
f.write(output)
print(f"Output written to {args.output}")
else:
print(output)
if args.wait:
sp = result.get("status_polling", {})
if isinstance(sp, dict) and sp.get("timed_out"):
return 2
return 0
if __name__ == "__main__":
raise SystemExit(main())