import os
import xlsxwriter
from ._ipcmonitor_C import ipcmonitor_C_module
from .file_manager import FileManager
from .singleton import Singleton
ActivityKind = ipcmonitor_C_module.monitor.ActivityKind
@Singleton
class Monitor:
API_HEADER = ["Name", "Start(us)", "End(us)", "Pid", "Tid", "Correlation ID", "Duration(us)"]
HEADER = {
ActivityKind.API: API_HEADER,
ActivityKind.AclAPI: API_HEADER,
ActivityKind.NodeAPI: API_HEADER,
ActivityKind.RuntimeAPI: API_HEADER,
ActivityKind.Kernel: ["Name", "Start(us)", "End(us)", "Device ID", "Stream ID", "Correlation ID", "Type", "Duration(us)"],
ActivityKind.Communication: ["Name", "Start(us)", "End(us)", "Device ID", "Stream ID",
"Count", "DataType", "CommName", "AlgType", "Correlation ID", "Duration(us)"],
ActivityKind.Marker: ["Name", "SourceKind", "Domain", "ID", "Start(us)", "End(us)",
"Pid", "Tid", "Device ID", "Stream ID", "Duration(us)"]
}
GET_DATA_FUNC = {
ActivityKind.API: ipcmonitor_C_module.monitor.get_api_data,
ActivityKind.AclAPI: ipcmonitor_C_module.monitor.get_acl_api_data,
ActivityKind.NodeAPI: ipcmonitor_C_module.monitor.get_node_api_data,
ActivityKind.RuntimeAPI: ipcmonitor_C_module.monitor.get_runtime_api_data,
ActivityKind.Kernel: ipcmonitor_C_module.monitor.get_kernel_data,
ActivityKind.Communication: ipcmonitor_C_module.monitor.get_communication_data,
ActivityKind.Marker: ipcmonitor_C_module.monitor.get_marker_data
}
NS_TO_US = 1000.0
@classmethod
def start(cls, kinds: list[ActivityKind]):
if not kinds or not isinstance(kinds, list) \
or not all(isinstance(kind, ActivityKind) for kind in kinds):
print("[ERROR] Invalid activity kind list")
return
ipcmonitor_C_module.monitor.start_monitor(kinds)
@classmethod
def stop(cls):
ipcmonitor_C_module.monitor.stop_monitor()
@classmethod
def get_result(cls) -> dict:
kinds = ipcmonitor_C_module.monitor.get_kinds()
if not kinds:
print("[WARNING] No valid activity kind")
return {}
result = {}
for kind in kinds:
if kind not in cls.GET_DATA_FUNC:
print(f"[WARNING] Unsupported activity kind: {kind}")
continue
result[kind] = cls.GET_DATA_FUNC[kind]()
return result
@classmethod
def save(cls, file_path: str):
if not file_path or not isinstance(file_path, str):
print("[ERROR] Invalid file path")
return
if not file_path.endswith(".xlsx"):
file_path += ".xlsx"
if os.path.exists(file_path):
print(f"[WARNING] File already exists: {file_path}, will be overwritten")
try:
result = cls.get_result()
if not result:
print("[WARNING] No valid activity data")
return
print(f"[INFO] Start to save activity data file: {file_path}")
FileManager.create_file_by_path(file_path)
with xlsxwriter.Workbook(file_path) as workbook:
for kind, data in result.items():
worksheet = workbook.add_worksheet(kind.name)
worksheet.write_row(0, 0, cls.HEADER[kind])
for i, row in enumerate(data, start=1):
worksheet.write_row(i, 0, [str(item) for item in row.to_tuple()] +
[(row.endNs - row.startNs) / cls.NS_TO_US])
print(f"[INFO] File saved successfully: {file_path}")
except Exception as err:
print(f"[ERROR] Failed to save file: {file_path}, error: {err}")