dv-flow-mgr 1.7.14886019138rc0__py3-none-any.whl → 1.8.14930698570rc0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dv_flow/mgr/__init__.py +2 -2
- dv_flow/mgr/cmds/cmd_run.py +11 -0
- dv_flow/mgr/task_listener_trace.py +171 -0
- dv_flow/mgr/task_node.py +3 -2
- {dv_flow_mgr-1.7.14886019138rc0.dist-info → dv_flow_mgr-1.8.14930698570rc0.dist-info}/METADATA +1 -1
- {dv_flow_mgr-1.7.14886019138rc0.dist-info → dv_flow_mgr-1.8.14930698570rc0.dist-info}/RECORD +10 -9
- {dv_flow_mgr-1.7.14886019138rc0.dist-info → dv_flow_mgr-1.8.14930698570rc0.dist-info}/WHEEL +0 -0
- {dv_flow_mgr-1.7.14886019138rc0.dist-info → dv_flow_mgr-1.8.14930698570rc0.dist-info}/entry_points.txt +0 -0
- {dv_flow_mgr-1.7.14886019138rc0.dist-info → dv_flow_mgr-1.8.14930698570rc0.dist-info}/licenses/LICENSE +0 -0
- {dv_flow_mgr-1.7.14886019138rc0.dist-info → dv_flow_mgr-1.8.14930698570rc0.dist-info}/top_level.txt +0 -0
dv_flow/mgr/__init__.py
CHANGED
@@ -31,7 +31,7 @@ from .task_node_ctor_wrapper import task
|
|
31
31
|
from .task_runner import TaskSetRunner
|
32
32
|
from .task_listener_log import TaskListenerLog
|
33
33
|
|
34
|
-
VERSION="1.
|
35
|
-
SUFFIX="
|
34
|
+
VERSION="1.8.0"
|
35
|
+
SUFFIX="14930698570rc0"
|
36
36
|
__version__="%s%s" % (VERSION, SUFFIX)
|
37
37
|
|
dv_flow/mgr/cmds/cmd_run.py
CHANGED
@@ -28,6 +28,7 @@ from ..task_data import SeverityE
|
|
28
28
|
from ..task_graph_builder import TaskGraphBuilder
|
29
29
|
from ..task_runner import TaskSetRunner
|
30
30
|
from ..task_listener_log import TaskListenerLog
|
31
|
+
from ..task_listener_trace import TaskListenerTrace
|
31
32
|
|
32
33
|
|
33
34
|
class CmdRun(object):
|
@@ -98,7 +99,14 @@ class CmdRun(object):
|
|
98
99
|
if args.j != -1:
|
99
100
|
runner.nproc = int(args.j)
|
100
101
|
|
102
|
+
if not os.path.isdir(os.path.join(rundir, "log")):
|
103
|
+
os.makedirs(os.path.join(rundir, "log"))
|
104
|
+
|
105
|
+
fp = open(os.path.join(rundir, "log", "%s.trace.json" % pkg.name), "w")
|
106
|
+
trace = TaskListenerTrace(fp)
|
107
|
+
|
101
108
|
runner.add_listener(listener.event)
|
109
|
+
runner.add_listener(trace.event)
|
102
110
|
|
103
111
|
tasks = []
|
104
112
|
|
@@ -110,6 +118,9 @@ class CmdRun(object):
|
|
110
118
|
|
111
119
|
asyncio.run(runner.run(tasks))
|
112
120
|
|
121
|
+
trace.close()
|
122
|
+
fp.close()
|
123
|
+
|
113
124
|
return runner.status
|
114
125
|
|
115
126
|
|
@@ -0,0 +1,171 @@
|
|
1
|
+
import dataclasses as dc
|
2
|
+
import json
|
3
|
+
import time
|
4
|
+
from typing import Dict, List, TextIO
|
5
|
+
from .task_node import TaskNode
|
6
|
+
|
7
|
+
@dc.dataclass
|
8
|
+
class TaskListenerTrace(object):
|
9
|
+
"""Task listener that generates Google Trace Event Format output."""
|
10
|
+
|
11
|
+
fp: TextIO # File to write trace events to
|
12
|
+
_free_tids: List = dc.field(default_factory=list) # Pool of available thread IDs
|
13
|
+
_task_tid_map: Dict = dc.field(default_factory=dict) # Map of tasks to their assigned thread IDs
|
14
|
+
_next_tid: int = dc.field(default=1) # Next thread ID to assign if pool is empty
|
15
|
+
_next_flow_id: int = dc.field(default=1) # Counter for unique flow IDs
|
16
|
+
_events: List = dc.field(default_factory=list) # Store events in memory
|
17
|
+
|
18
|
+
def __post_init__(self):
|
19
|
+
# Add metadata event
|
20
|
+
self._events.append({
|
21
|
+
"name": "metadata",
|
22
|
+
"ph": "M",
|
23
|
+
"pid": 1,
|
24
|
+
"tid": 0,
|
25
|
+
"args": {
|
26
|
+
"name": "Task Execution",
|
27
|
+
"timeUnit": "us"
|
28
|
+
}
|
29
|
+
})
|
30
|
+
|
31
|
+
def close(self):
|
32
|
+
"""Write the complete trace file and close it."""
|
33
|
+
trace = {
|
34
|
+
"traceEvents": self._events,
|
35
|
+
"displayTimeUnit": "ms" # Show times in milliseconds in the viewer
|
36
|
+
}
|
37
|
+
json.dump(trace, self.fp, indent=2)
|
38
|
+
self.fp.flush()
|
39
|
+
|
40
|
+
def _get_tid(self, task: TaskNode) -> int:
|
41
|
+
"""Get a thread ID for a task, either from the pool or creating a new one."""
|
42
|
+
if task in self._task_tid_map:
|
43
|
+
return self._task_tid_map[task]
|
44
|
+
|
45
|
+
if len(self._free_tids) > 0:
|
46
|
+
tid = self._free_tids.pop()
|
47
|
+
else:
|
48
|
+
tid = self._next_tid
|
49
|
+
self._next_tid += 1
|
50
|
+
|
51
|
+
self._task_tid_map[task] = tid
|
52
|
+
return tid
|
53
|
+
|
54
|
+
def _release_tid(self, task: TaskNode):
|
55
|
+
"""Return a task's thread ID to the pool."""
|
56
|
+
if task in self._task_tid_map:
|
57
|
+
tid = self._task_tid_map[task]
|
58
|
+
del self._task_tid_map[task]
|
59
|
+
self._free_tids.append(tid)
|
60
|
+
|
61
|
+
def _get_task_data(self, task: TaskNode) -> dict:
|
62
|
+
"""Extract serializable task data"""
|
63
|
+
data = {}
|
64
|
+
|
65
|
+
# Add any parameters
|
66
|
+
if hasattr(task, 'params') and task.params:
|
67
|
+
# If params is a dataclass or has __dict__, get its fields
|
68
|
+
if hasattr(task.params, '__dict__'):
|
69
|
+
data['params'] = task.params.__dict__
|
70
|
+
elif isinstance(task.params, dict):
|
71
|
+
data['params'] = task.params
|
72
|
+
|
73
|
+
# Add inputs if present
|
74
|
+
if hasattr(task, 'needs') and task.needs:
|
75
|
+
inputs = []
|
76
|
+
for need, _ in task.needs:
|
77
|
+
if hasattr(need, 'output') and need.output:
|
78
|
+
inputs.append({
|
79
|
+
'task': need.name,
|
80
|
+
'data': need.output.__dict__ if hasattr(need.output, '__dict__') else need.output
|
81
|
+
})
|
82
|
+
if inputs:
|
83
|
+
data['inputs'] = inputs
|
84
|
+
|
85
|
+
return data
|
86
|
+
|
87
|
+
def event(self, task: TaskNode, reason: str):
|
88
|
+
"""Record a task execution event.
|
89
|
+
|
90
|
+
Args:
|
91
|
+
task: The task that generated the event
|
92
|
+
reason: Either 'enter' or 'leave' marking start/end of task execution
|
93
|
+
"""
|
94
|
+
# Get/create thread ID for this task
|
95
|
+
tid = self._get_tid(task)
|
96
|
+
|
97
|
+
# Map the event type
|
98
|
+
ph = 'B' if reason == 'enter' else 'E'
|
99
|
+
|
100
|
+
# Get current timestamp in microseconds
|
101
|
+
ts = int(time.time() * 1_000_000) if reason == "enter" else int(task.end.timestamp() * 1_000_000)
|
102
|
+
|
103
|
+
# Create the duration event with initial args
|
104
|
+
args = {}
|
105
|
+
|
106
|
+
# Add task data
|
107
|
+
if reason == "enter":
|
108
|
+
# Add input data on task start
|
109
|
+
input_data = self._get_task_data(task)
|
110
|
+
if input_data:
|
111
|
+
args = input_data
|
112
|
+
|
113
|
+
elif reason == 'leave':
|
114
|
+
if task.result:
|
115
|
+
# Add status and change info
|
116
|
+
args["status"] = task.result.status
|
117
|
+
args["changed"] = task.result.changed
|
118
|
+
|
119
|
+
# Add output data if present
|
120
|
+
if hasattr(task.result, 'output') and task.result.output:
|
121
|
+
args["output"] = [
|
122
|
+
out.__dict__ if hasattr(out, '__dict__') else out
|
123
|
+
for out in task.result.output
|
124
|
+
]
|
125
|
+
|
126
|
+
self._release_tid(task)
|
127
|
+
|
128
|
+
# Create the event with collected args
|
129
|
+
event = {
|
130
|
+
"name": task.name,
|
131
|
+
"cat": "task",
|
132
|
+
"ph": ph,
|
133
|
+
"pid": 1,
|
134
|
+
"tid": tid,
|
135
|
+
"ts": ts,
|
136
|
+
"args": args
|
137
|
+
}
|
138
|
+
|
139
|
+
# Store the duration event
|
140
|
+
self._events.append(event)
|
141
|
+
|
142
|
+
# Add flow event for dependencies
|
143
|
+
if reason == "enter":
|
144
|
+
# When task starts, add flow event from each dependency
|
145
|
+
for need, _ in task.needs:
|
146
|
+
# Create flow start from completed task to this one
|
147
|
+
flow = {
|
148
|
+
"name": f"{need.name} -> {task.name}",
|
149
|
+
"cat": "flow",
|
150
|
+
"ph": "s", # Flow start
|
151
|
+
"pid": 1,
|
152
|
+
"tid": self._task_tid_map.get(need, 0),
|
153
|
+
"ts": int(need.end.timestamp() * 1_000_000) if need.end else ts,
|
154
|
+
"id": self._next_flow_id,
|
155
|
+
"bp": "e"
|
156
|
+
}
|
157
|
+
self._events.append(flow)
|
158
|
+
|
159
|
+
# Create flow finish at the start of this task
|
160
|
+
flow_end = {
|
161
|
+
"name": f"{need.name} -> {task.name}",
|
162
|
+
"cat": "flow",
|
163
|
+
"ph": "f", # Flow finish
|
164
|
+
"pid": 1,
|
165
|
+
"tid": tid,
|
166
|
+
"ts": ts,
|
167
|
+
"id": self._next_flow_id,
|
168
|
+
"bp": "e"
|
169
|
+
}
|
170
|
+
self._events.append(flow_end)
|
171
|
+
self._next_flow_id += 1
|
dv_flow/mgr/task_node.py
CHANGED
@@ -24,6 +24,7 @@ import json
|
|
24
24
|
import os
|
25
25
|
import sys
|
26
26
|
import dataclasses as dc
|
27
|
+
import datetime
|
27
28
|
import pydantic.dataclasses as pdc
|
28
29
|
import logging
|
29
30
|
import toposort
|
@@ -55,8 +56,8 @@ class TaskNode(object):
|
|
55
56
|
rundir : List[str] = dc.field(default=None)
|
56
57
|
output : TaskDataOutput = dc.field(default=None)
|
57
58
|
result : TaskDataResult = dc.field(default=None)
|
58
|
-
start :
|
59
|
-
end :
|
59
|
+
start : datetime.datetime = dc.field(default=None)
|
60
|
+
end : datetime.datetime = dc.field(default=None)
|
60
61
|
save_exec_data : bool = dc.field(default=True)
|
61
62
|
iff : bool = dc.field(default=True)
|
62
63
|
parent : 'TaskNode' = dc.field(default=None)
|
{dv_flow_mgr-1.7.14886019138rc0.dist-info → dv_flow_mgr-1.8.14930698570rc0.dist-info}/RECORD
RENAMED
@@ -1,4 +1,4 @@
|
|
1
|
-
dv_flow/mgr/__init__.py,sha256=
|
1
|
+
dv_flow/mgr/__init__.py,sha256=SuHUNRUr03Dy5bvMChNK6x76Zw1l66AEIps_uNN-cOQ,1315
|
2
2
|
dv_flow/mgr/__main__.py,sha256=BogNdBkXhgg05E8_IumNkVoag6WwvfbpiI8346oOtPo,3844
|
3
3
|
dv_flow/mgr/cond_def.py,sha256=2ZkzPusqVkN1fFMTvkDl9O_OJLPdD_cK3xzX9J75RMw,343
|
4
4
|
dv_flow/mgr/config.py,sha256=b2MVlVVNB0psk8x4bQRAYshkpNJrtyMtV1Ymhmx9AfM,137
|
@@ -37,7 +37,8 @@ dv_flow/mgr/task_def.py,sha256=8NPwtTROfWDkMqcO9mKXV4dw0sC4mCMmnsNuv8uTdTY,5094
|
|
37
37
|
dv_flow/mgr/task_graph_builder.py,sha256=q7BS7OLYkS6uZwQLvo6P_CtJkhIvPal_tXLZHgUuLpU,28172
|
38
38
|
dv_flow/mgr/task_graph_dot_writer.py,sha256=qK4Imy9o2_F1aKoU1tJ-qoBHslq2BhSMbdjAUPfpN7I,6009
|
39
39
|
dv_flow/mgr/task_listener_log.py,sha256=Ai-6X5BOoGsaNTgnlXEW0-czrjJm7__ShNK501CUmko,4337
|
40
|
-
dv_flow/mgr/
|
40
|
+
dv_flow/mgr/task_listener_trace.py,sha256=6MvVmy4Rc30qTYpA4yaF760Qlszk34FQOCtRD9slkNE,6064
|
41
|
+
dv_flow/mgr/task_node.py,sha256=OC3rkeRSFv9wmgkMZ_7eJu7nuXGJcwW_b6FGQM-w7AU,5231
|
41
42
|
dv_flow/mgr/task_node_compound.py,sha256=0biBPT_2SpCPJL7DFaFY27_K7kNxJ1taIut3Fv12HXk,3347
|
42
43
|
dv_flow/mgr/task_node_ctor.py,sha256=YsoVMX5WbpbzcHvEK7ps_ZRV-J7MZ3F8NNozQw7vbog,4418
|
43
44
|
dv_flow/mgr/task_node_ctor_compound.py,sha256=290JdcTnL3b3Gv7s_wRLjdM02ezKhc9QnxZE0mv72i8,4379
|
@@ -56,7 +57,7 @@ dv_flow/mgr/type.py,sha256=hoJTatlPC0yOazKSWduK-5CfY38RPkc6qXFzOCcVSdM,723
|
|
56
57
|
dv_flow/mgr/type_def.py,sha256=4sge3PibO1jDnS0cXdX0PiurcKbDA3kT6rb4DGIKwEM,1176
|
57
58
|
dv_flow/mgr/yaml_srcinfo_loader.py,sha256=29BNRiB8Hj1FepkrLtdjHSv5U_85Q432gBeeK80nKEA,1606
|
58
59
|
dv_flow/mgr/cmds/cmd_graph.py,sha256=yg5KbNrGvm3dySiI0Qei_pMWZkOE9GtEyaQ4IdNVmoE,2852
|
59
|
-
dv_flow/mgr/cmds/cmd_run.py,sha256=
|
60
|
+
dv_flow/mgr/cmds/cmd_run.py,sha256=SsCZXwutJW1XT5iXtJqvdeg6p6HEa86V5hELNKuaWgA,4082
|
60
61
|
dv_flow/mgr/cmds/cmd_show.py,sha256=JOIFaVXt8YCf9bKXfq6qzV5wQdxdLHqE-yCj0ecGREs,3755
|
61
62
|
dv_flow/mgr/share/flow.json,sha256=lNmZex9NXkYbyb2aZseQfUOkV9CMyfH0iLODEI7EPBw,5096
|
62
63
|
dv_flow/mgr/std/create_file.py,sha256=SEpKTQdiY32002C7b4kYfAiK9v_xajixOJU5WftW75I,2957
|
@@ -73,9 +74,9 @@ dv_flow/mgr/util/util.py,sha256=BO7iqP_c9ttmXkojq7nKDN-g8wl1_Pco9k-KnrXxjwE,1889
|
|
73
74
|
dv_flow/mgr/util/cmds/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
74
75
|
dv_flow/mgr/util/cmds/cmd_schema.py,sha256=IJzZdxCSEgIQ79LpYiM7UqJ9RJ-7yraqmBN2XVgAgXA,1752
|
75
76
|
dv_flow/mgr/util/cmds/cmd_workspace.py,sha256=egmaIXpe5L-TePwmcfisfrG6tdiTUWSjqa9Za5WChVs,890
|
76
|
-
dv_flow_mgr-1.
|
77
|
-
dv_flow_mgr-1.
|
78
|
-
dv_flow_mgr-1.
|
79
|
-
dv_flow_mgr-1.
|
80
|
-
dv_flow_mgr-1.
|
81
|
-
dv_flow_mgr-1.
|
77
|
+
dv_flow_mgr-1.8.14930698570rc0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
78
|
+
dv_flow_mgr-1.8.14930698570rc0.dist-info/METADATA,sha256=vPln7CEjSer8daHBSV2zvvNRpQi2dYtKvYLIJ3R1yog,13335
|
79
|
+
dv_flow_mgr-1.8.14930698570rc0.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
80
|
+
dv_flow_mgr-1.8.14930698570rc0.dist-info/entry_points.txt,sha256=1roy8wAFM48LabOvr6jiOw0MUs-qE8X3Vf8YykPazxk,50
|
81
|
+
dv_flow_mgr-1.8.14930698570rc0.dist-info/top_level.txt,sha256=amfVTkggzYPtWwLqNmRukfz1Buu0pGS2SrYBBLhXm04,8
|
82
|
+
dv_flow_mgr-1.8.14930698570rc0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
{dv_flow_mgr-1.7.14886019138rc0.dist-info → dv_flow_mgr-1.8.14930698570rc0.dist-info}/top_level.txt
RENAMED
File without changes
|