UnitTestPlaybookAnalyzer
Profiles execution time of tasks in a playbook or sub-playbook (if specified). Provides minimum, maximum, and average task execution times in milliseconds as well as the state of each task: completed, error, notexecuted, started, and waiting.
python · Content Testing
Source
from datetime import datetime import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 def BuildTask(t) -> dict: duration = -1.0 state = "Unknown" started = 0 notexecuted = 0 if "state" in t: state = t["state"] if state == "Completed": if "startDate" in t and "completedDate" in t: start = datetime.fromisoformat(t["startDate"].replace("Z", "+00:00")) end = datetime.fromisoformat(t["completedDate"].replace("Z", "+00:00")) delta = end - start duration = int(delta.total_seconds() * 1000) else: notexecuted = 1 elif state == "inprogress": started = 1 elif state == "WillNotBeExecuted": notexecuted = 1 newtask = { "name": t["task"]["name"], "duration": duration, "state": state, "tid": t["id"], "started": started, "notexecuted": notexecuted, } return newtask def GetSubpbTasks(subplaybook, t, tasks): if "subPlaybook" in t: for _k, ts in t["subPlaybook"]["tasks"].items(): if subplaybook == t["subPlaybook"]["name"]: if ts["type"] in ["regular", "condition", "playbook", "collection"]: tasks.append(BuildTask(ts)) else: tasks = GetSubpbTasks(subplaybook, ts, tasks) return tasks def GetTasks(incid: str, subplaybook: str) -> list: body = { "states": [ "Error", "Waiting", "Completed", "inprogress" ], "types": [ "regular", "condition", "playbook," "collection" ] } resp = execute_command("core-api-post", { "uri": f"/investigation/{incid}/workplan/tasks", "body": body }) tasks: list = [] if "response" in resp and resp["response"] is not None: for t in resp["response"]: if t["type"] in ["regular", "condition", "playbook", "collection"]: if t["type"] == "playbook" and subplaybook != "": tasks = GetSubpbTasks(subplaybook, t, tasks) else: tasks.append(BuildTask(t)) return tasks def TaskStats(task: list, taskstat: dict) -> dict: for t in task: taskid = t["tid"] dur = int(t["duration"]) if taskid not in taskstat: taskstat[taskid] = { "tid": taskid, "name": t["name"], "mindur": 1000000, "maxdur": 0, "avgdur": 0, "totdur": 0, "count": 0, "completed": 0, "started": 0, "notexecuted": 0, "error": 0, "waiting": 0, } if t["state"] == "Completed": if dur > taskstat[taskid]["maxdur"]: taskstat[taskid]["maxdur"] = dur if dur < taskstat[taskid]["mindur"]: taskstat[taskid]["mindur"] = dur taskstat[taskid]["totdur"] += dur taskstat[taskid]["completed"] += 1 elif t["state"] == "Error": taskstat[taskid]["error"] += 1 elif t["state"] == "Waiting": taskstat[taskid]["waiting"] += 1 else: taskstat[taskid]["started"] += t["started"] taskstat[taskid]["notexecuted"] += t["notexecuted"] taskstat[taskid]["count"] += 1 for _key, ts in taskstat.items(): ts["avgdur"] = int(ts["totdur"] / ts["count"]) return taskstat def GetTaskStats(playbookname, subplaybookname, firstday, lastday, maxinc): argument = {"size": maxinc, "query": f'playbook:"{playbookname}" occurred:>="{firstday}T00:00:00" and occurred:<="{lastday}T23:59:59"'} response = execute_command("getIncidents", argument) taskstat: dict = {} taskstats: dict = {} count = 0 if response["data"] is not None: for inc in response["data"]: tasks = GetTasks(inc["id"], subplaybookname) taskstats = TaskStats(tasks, taskstat) count += 1 if count >= maxinc: break return taskstats, count def SummaryMarkdown(playbook, subplaybook: str, firstday: str, lastday: str, count: int) -> str: output = f"### Playbook: {playbook}\n" output += f"#### Sub-playbook: {subplaybook}\n" output += f"#### First Day: {firstday}\n" output += f"#### Last Day: {lastday}\n" output += f"#### Analysis Date: {datetime_to_string(datetime.now())}\n" output += f"#### Incidents Analyzed: {count}\n" return output def StatsInfoMarkdown(stats: dict) -> str: markdown = "<br/>\n" markdown += "|Task Name|Minimum Duration(ms)|Average Duration(ms)|Maximum Duration(ms)|\n" markdown += "|---|:---:|:---:|:---:|\n" for _key, val in stats.items(): if val["mindur"] is None: val["mindur"] = 0 markdown += f"|{val['name']}|{val['mindur']}|{val['avgdur']}|{val['maxdur']}|\n" return markdown def main(): try: pb = demisto.args()["playbook"].strip() spb = demisto.args()["subplaybook"].strip() firstday = demisto.args()["firstday"].strip() lastday = demisto.args()["lastday"].strip() maxinc = (demisto.args().get("maxinc") or "").strip() or 50 maxcount = arg_to_number(maxinc) taskstats, count = GetTaskStats(pb, spb, firstday, lastday, maxcount) demisto.setContext("PlaybookStatistics", json.dumps(taskstats)) smarkdown = SummaryMarkdown(pb, spb, firstday, lastday, count) imarkdown = StatsInfoMarkdown(taskstats) execute_command( "setIncident", {"customFields": json.dumps({"contenttestingdependencies": smarkdown, "contenttestingpbainfo": imarkdown})}, ) except Exception as ex: demisto.error(traceback.format_exc()) return_error(f"UnitTestPlaybookAnalyzer: Exception failed to execute. Error: {ex!s}") if __name__ in ("__main__", "__builtin__", "builtins"): main()
README
Profiles execution time of tasks in a playbook or sub-playbook (if specified). Provides minimum, maximum, and average task execution times in milliseconds as well as the state of each task: completed, error, notexecuted, started, and waiting.
Script Data
| Name | Description |
|---|---|
| Script Type | python3 |
Inputs
| Argument Name | Description |
|---|---|
| playbook | Name of the playbook to analyze. |
| subplaybook | Sub-playbook for analysis versus the parent playbook. |
| firstday | First day to find incident occurrences using the playbook. Example: “2023-03-01”. |
| lastday | Last day to find incident occurrences using the playbook: Example: “2023-03-31”. |
| maxinc | Maximum number of incidents to analyze. |
Outputs
There are no outputs for this script.