def test_iter_auto_source_component_spec_string(self): msg_iter = bt2.TraceCollectionMessageIterator( _3EVENTS_INTERSECT_TRACE_PATH) msgs = list(msg_iter) self.assertEqual(len(msgs), 28) hist = _count_msgs_by_type(msgs) self.assertEqual(hist[bt2._EventMessageConst], 8)
def test_iter_intersection_subscribe(self): specs = [bt2.ComponentSpec('ctf', 'fs', _3EVENTS_INTERSECT_TRACE_PATH)] msg_iter = bt2.TraceCollectionMessageIterator( specs, stream_intersection_mode=True, message_types=[bt2.EventMessage]) self.assertEqual(len(list(msg_iter)), 3)
def test_iter_intersection_params(self): # Check that all params used to create the source component are passed # to the `babeltrace.trace-infos` query. specs = [ bt2.ComponentSpec.from_named_plugin_and_component_class( 'ctf', 'fs', { 'inputs': [_3EVENTS_INTERSECT_TRACE_PATH], 'clock-class-offset-s': 1000, }, ) ] msg_iter = bt2.TraceCollectionMessageIterator( specs, stream_intersection_mode=True) event_msgs = [x for x in msg_iter if type(x) is bt2._EventMessageConst] self.assertEqual(len(event_msgs), 3) self.assertEqual(event_msgs[0].default_clock_snapshot.ns_from_origin, 13516309000000071) self.assertEqual(event_msgs[1].default_clock_snapshot.ns_from_origin, 13516309000000072) self.assertEqual(event_msgs[2].default_clock_snapshot.ns_from_origin, 13516309000000082)
def test_create_end_s(self): specs = [ bt2.ComponentSpec.from_named_plugin_and_component_class( 'ctf', 'fs', _3EVENTS_INTERSECT_TRACE_PATH ) ] bt2.TraceCollectionMessageIterator(specs, end=123.12312)
def test_create_begin_datetime(self): specs = [ bt2.ComponentSpec.from_named_plugin_and_component_class( 'ctf', 'fs', _3EVENTS_INTERSECT_TRACE_PATH) ] bt2.TraceCollectionMessageIterator(specs, begin=datetime.datetime.now())
def _test_one_comp_from_one_spec_one_comp_from_both_2( self, params_ab=None, params_a=None, obj_ab=None, obj_a=None, logging_level_ab=None, logging_level_a=None, ): specs = [ bt2.AutoSourceComponentSpec( self._dir_ab, params=params_ab, obj=obj_ab, logging_level=logging_level_ab, ), bt2.AutoSourceComponentSpec(self._dir_a, params=params_a, obj=obj_a, logging_level=logging_level_a), ] it = bt2.TraceCollectionMessageIterator(specs) msgs = [x for x in it if type(x) is bt2._StreamBeginningMessageConst] self.assertEqual(len(msgs), 2) return msgs
def test_iter_intersection_no_path_param(self): specs = [bt2.ComponentSpec('text', 'dmesg', {'read-from-stdin': True})] with self.assertRaises(bt2.Error): msg_iter = bt2.TraceCollectionMessageIterator( specs, stream_intersection_mode=True, message_types=[bt2.EventMessage])
def test_iter_specs_not_list(self): spec = bt2.ComponentSpec.from_named_plugin_and_component_class( 'ctf', 'fs', _3EVENTS_INTERSECT_TRACE_PATH) msg_iter = bt2.TraceCollectionMessageIterator(spec) msgs = list(msg_iter) self.assertEqual(len(msgs), 28) hist = _count_msgs_by_type(msgs) self.assertEqual(hist[bt2._EventMessageConst], 8)
def test_iter_custom_filter(self): src_spec = bt2.ComponentSpec.from_named_plugin_and_component_class( 'ctf', 'fs', _3EVENTS_INTERSECT_TRACE_PATH) flt_spec = bt2.ComponentSpec.from_named_plugin_and_component_class( 'utils', 'trimmer', {'end': '13515309.000000075'}) msg_iter = bt2.TraceCollectionMessageIterator(src_spec, flt_spec) hist = _count_msgs_by_type(msg_iter) self.assertEqual(hist[bt2._EventMessageConst], 5)
def test_create_wrong_end_type(self): specs = [ bt2.ComponentSpec.from_named_plugin_and_component_class( 'ctf', 'fs', _3EVENTS_INTERSECT_TRACE_PATH) ] with self.assertRaises(TypeError): bt2.TraceCollectionMessageIterator(specs, begin='lel')
def test_iter_no_intersection_two_traces(self): spec = bt2.ComponentSpec.from_named_plugin_and_component_class( 'ctf', 'fs', _3EVENTS_INTERSECT_TRACE_PATH) specs = [spec, spec] msg_iter = bt2.TraceCollectionMessageIterator(specs) msgs = list(msg_iter) self.assertEqual(len(msgs), 56) hist = _count_msgs_by_type(msgs) self.assertEqual(hist[bt2._EventMessageConst], 16)
def test_iter_no_intersection_end(self): specs = [ bt2.ComponentSpec.from_named_plugin_and_component_class( 'ctf', 'fs', _3EVENTS_INTERSECT_TRACE_PATH) ] msg_iter = bt2.TraceCollectionMessageIterator(specs, end=13515309.000000075) hist = _count_msgs_by_type(msg_iter) self.assertEqual(hist[bt2._EventMessageConst], 5)
def test_iter_custom_filter(self): src_spec = bt2.ComponentSpec('ctf', 'fs', _3EVENTS_INTERSECT_TRACE_PATH) flt_spec = bt2.ComponentSpec('utils', 'trimmer', { 'end': 13515309000000075, }) msg_iter = bt2.TraceCollectionMessageIterator( src_spec, flt_spec, message_types=[bt2.EventMessage]) self.assertEqual(len(list(msg_iter)), 5)
def test_auto_source_component_non_existent(self): with self.assertRaisesRegex( RuntimeError, 'Some auto source component specs did not produce any component', ): # Test with one path known to contain a trace and one path known # to not contain any trace. bt2.TraceCollectionMessageIterator( [_SEQUENCE_TRACE_PATH, '/this/path/better/not/exist'])
def test_iter_mixed_inputs(self): msg_iter = bt2.TraceCollectionMessageIterator([ _3EVENTS_INTERSECT_TRACE_PATH, bt2.AutoSourceComponentSpec(_SEQUENCE_TRACE_PATH), bt2.ComponentSpec.from_named_plugin_and_component_class( 'ctf', 'fs', _NOINTERSECT_TRACE_PATH), ]) msgs = list(msg_iter) self.assertEqual(len(msgs), 76) hist = _count_msgs_by_type(msgs) self.assertEqual(hist[bt2._EventMessageConst], 24)
def test_iter_intersection(self): specs = [ bt2.ComponentSpec.from_named_plugin_and_component_class( 'ctf', 'fs', _3EVENTS_INTERSECT_TRACE_PATH) ] msg_iter = bt2.TraceCollectionMessageIterator( specs, stream_intersection_mode=True) msgs = list(msg_iter) self.assertEqual(len(msgs), 15) hist = _count_msgs_by_type(msgs) self.assertEqual(hist[bt2._EventMessageConst], 3)
def _test_two_comps_from_one_spec(self, params, obj=None, logging_level=None): specs = [ bt2.AutoSourceComponentSpec( self._dir_ab, params=params, obj=obj, logging_level=logging_level ) ] it = bt2.TraceCollectionMessageIterator(specs) msgs = [x for x in it if type(x) is bt2._StreamBeginningMessageConst] self.assertEqual(len(msgs), 2) return msgs
def test_obj_no_override_with_no_obj(self): specs = [ bt2.AutoSourceComponentSpec( self._dir_ab, params={'what': 'python-obj'}, obj='deore' ), bt2.AutoSourceComponentSpec(self._dir_a, params={'what': 'python-obj'}), ] it = bt2.TraceCollectionMessageIterator(specs) msgs = [x for x in it if type(x) is bt2._StreamBeginningMessageConst] self.assertEqual(len(msgs), 2) self.assertEqual(msgs[0].stream.name, "TestSourceA: deore") self.assertEqual(msgs[1].stream.name, "TestSourceB: deore")
def test_grouping(self): specs = [ bt2.AutoSourceComponentSpec('ABCDE'), bt2.AutoSourceComponentSpec(_AUTO_SOURCE_DISCOVERY_GROUPING_PATH), ] it = bt2.TraceCollectionMessageIterator(specs) msgs = [x for x in it if type(x) is bt2._StreamBeginningMessageConst] self.assertEqual(len(msgs), 8) self.assertEqual(msgs[0].stream.name, 'TestSourceABCDE: ABCDE') self.assertEqual(msgs[1].stream.name, 'TestSourceExt: aaa1, aaa2, aaa3') self.assertEqual(msgs[2].stream.name, 'TestSourceExt: bbb1, bbb2') self.assertEqual(msgs[3].stream.name, 'TestSourceExt: ccc1') self.assertEqual(msgs[4].stream.name, 'TestSourceExt: ccc2') self.assertEqual(msgs[5].stream.name, 'TestSourceExt: ccc3') self.assertEqual(msgs[6].stream.name, 'TestSourceExt: ccc4') self.assertEqual(msgs[7].stream.name, 'TestSourceSomeDir: some-dir')
def parse(): it = bt2.TraceCollectionMessageIterator(sys.argv[1]) for msg in it: if type(msg) is not bt2._EventMessageConst: continue event = msg.event event_type = None if event.cls.name == 'null_rand_latency:tx' or event.cls.name == 'futuresdr:tx': event_type = 'tx' elif event.cls.name == 'null_rand_latency:rx' or event.cls.name == 'futuresdr:rx': event_type = 'rx' else: continue cpu = event.packet.context_field['cpu_id'] time = msg.default_clock_snapshot.ns_from_origin block = event.payload_field['block'] samples = event.payload_field['samples'] print(f"{time},{event_type},{cpu},{block},{samples}")
def test_iter_specs_not_list(self): spec = bt2.ComponentSpec('ctf', 'fs', _3EVENTS_INTERSECT_TRACE_PATH) msg_iter = bt2.TraceCollectionMessageIterator( spec, message_types=[bt2.EventMessage]) self.assertEqual(len(list(msg_iter)), 8)
def test_create_wrong_end_type(self): specs = [bt2.ComponentSpec('ctf', 'fs', _3EVENTS_INTERSECT_TRACE_PATH)] with self.assertRaises(TypeError): msg_iter = bt2.TraceCollectionMessageIterator(specs, begin='lel')
def test_create_wrong_stream_intersection_mode_type(self): specs = [bt2.ComponentSpec('ctf', 'fs', _3EVENTS_INTERSECT_TRACE_PATH)] with self.assertRaises(TypeError): msg_iter = bt2.TraceCollectionMessageIterator( specs, stream_intersection_mode=23)
def test_create_no_such_plugin(self): specs = [bt2.ComponentSpec('77', '101', _3EVENTS_INTERSECT_TRACE_PATH)] with self.assertRaises(bt2.Error): msg_iter = bt2.TraceCollectionMessageIterator(specs)
def test_create_begin_s(self): specs = [bt2.ComponentSpec('ctf', 'fs', _3EVENTS_INTERSECT_TRACE_PATH)] msg_iter = bt2.TraceCollectionMessageIterator(specs, begin=19457.918232)
def test_create_end_datetime(self): specs = [bt2.ComponentSpec('ctf', 'fs', _3EVENTS_INTERSECT_TRACE_PATH)] msg_iter = bt2.TraceCollectionMessageIterator( specs, end=datetime.datetime.now())
def test_iter_no_intersection(self): specs = [bt2.ComponentSpec('ctf', 'fs', _3EVENTS_INTERSECT_TRACE_PATH)] msg_iter = bt2.TraceCollectionMessageIterator(specs) self.assertEqual(len(list(msg_iter)), 28)
def main(): args = parse_args() msg_it = bt2.TraceCollectionMessageIterator(args.trace) last_event_ns_from_origin = None timeline = [] def get_thread(name): for t in timeline: if t.get('name', None) == name and t.get( 'in', 0) != 0 and not t.get('out', None): return t return {} for msg in msg_it: if not isinstance(msg, bt2._EventMessageConst): continue ns_from_origin = msg.default_clock_snapshot.ns_from_origin event = msg.event # Compute the time difference since the last event message. diff_s = 0 if last_event_ns_from_origin is not None: diff_s = (ns_from_origin - last_event_ns_from_origin) / 1e9 dt = datetime.datetime.fromtimestamp(ns_from_origin / 1e9) if event.name in [ 'thread_switched_out', 'thread_switched_in', 'thread_pending', 'thread_ready', 'thread_resume', 'thread_suspend', 'thread_create', 'thread_abort' ]: cpu = event.payload_field.get("cpu", None) thread_id = event.payload_field.get("thread_id", None) thread_name = event.payload_field.get("name", None) th = {} if event.name in ['thread_switched_out', 'thread_switched_in' ] and cpu is not None: cpu_string = f"(cpu: {cpu})" else: cpu_string = "" if thread_name: print( f"{dt} (+{diff_s:.6f} s): {event.name}: {thread_name} {cpu_string}" ) elif thread_id: print( f"{dt} (+{diff_s:.6f} s): {event.name}: {thread_id} {cpu_string}" ) else: print(f"{dt} (+{diff_s:.6f} s): {event.name}") if event.name in ['thread_switched_out', 'thread_switched_in']: if thread_name: th = get_thread(thread_name) if not th: th['name'] = thread_name else: th = get_thread(thread_id) if not th: th['name'] = thread_id if event.name in ['thread_switched_out']: th['out'] = ns_from_origin tin = th.get('in', None) tout = th.get('out', None) if tout is not None and tin is not None: diff = (tout - tin) th['runtime'] = diff elif event.name in ['thread_switched_in']: th['in'] = ns_from_origin timeline.append(th) elif event.name in ['thread_info']: stack_size = event.payload_field['stack_size'] print( f"{dt} (+{diff_s:.6f} s): {event.name} (Stack size: {stack_size})" ) elif event.name in ['start_call', 'end_call']: if event.payload_field['id'] == 39: c = Fore.GREEN elif event.payload_field['id'] in [37, 38]: c = Fore.CYAN else: c = Fore.YELLOW print( c + f"{dt} (+{diff_s:.6f} s): {event.name} {event.payload_field['id']}" + Fore.RESET) elif event.name in [ 'semaphore_init', 'semaphore_take', 'semaphore_give' ]: c = Fore.CYAN print( c + f"{dt} (+{diff_s:.6f} s): {event.name} ({event.payload_field['id']})" + Fore.RESET) elif event.name in ['mutex_init', 'mutex_take', 'mutex_give']: c = Fore.MAGENTA print( c + f"{dt} (+{diff_s:.6f} s): {event.name} ({event.payload_field['id']})" + Fore.RESET) else: print(f"{dt} (+{diff_s:.6f} s): {event.name}") last_event_ns_from_origin = ns_from_origin
def main(): parser = argparse.ArgumentParser( description="Convert a CTF trace to a json trace viewable with google " "chrome") parser.add_argument("ctf", metavar="CTF", type=str, help="Path to the CTF trace") parser.add_argument("-o", "--output", metavar="OUT", type=str, default="trace.json", help="the output file") args = parser.parse_args() if not os.path.isdir(args.ctf): raise NotADirectoryError(args.ctf) ctf_path = None for root, dirs, files in os.walk(args.ctf): for f in files: if f == "metadata": if ctf_path is None: ctf_path = str(root) else: raise RuntimeError("%s is not a single trace (contains " "more than one metadata file!" % args.ctf) if ctf_path is None: raise RuntimeError("%s is not a CTF trace (does not contain a metadata" " file)" % args.ctf) # Find the `ctf` plugin (shipped with Babeltrace 2). ctf_plugin = bt2.find_plugin('ctf') # Get the `source.ctf.fs` component class from the plugin. fs_cc = ctf_plugin.source_component_classes['fs'] # Create a trace collection message iterator, instantiating a single # `source.ctf.fs` component class with the `inputs` initialization # parameter set to open a single CTF trace. msg_it = bt2.TraceCollectionMessageIterator( bt2.ComponentSpec( fs_cc, { # Get the CTF trace path from the first command-line argument. 'inputs': [ctf_path], })) # keep a list of events to dump later to JSON trace_events = [] # Iterate the trace messages. for msg in msg_it: # `bt2._EventMessageConst` is the Python type of an event message. if type(msg) is bt2._EventMessageConst: event = msg.event if (event.name == "reactor_cpp:reaction_execution_starts"): trace_events.append(reaction_execution_starts_to_dict(msg)) elif (event.name == "reactor_cpp:reaction_execution_finishes"): trace_events.append(reaction_execution_finishes_to_dict(msg)) elif (event.name == "reactor_cpp:schedule_action"): trace_events.append(schedule_action_to_dict(msg)) elif (event.name == "reactor_cpp:trigger_reaction"): trace_events.append(trigger_reaction_to_dict(msg)) # add some metadata configure_process_name(trace_events, 0, "Execution") for i in range(1, 128): configure_thread_name(trace_events, 0, i, "Worker %d" % i) for process, pid in pid_registry.items(): configure_process_name(trace_events, pid, process) for thread, tid in tid_registry[process].items(): configure_thread_name(trace_events, pid, tid, thread) data = { "traceEvents": trace_events, "displayTimeUnit": "ns", } with open(args.output, 'w') as outfile: json.dump(data, outfile, indent=2)
import bt2 # Find the `ctf` plugin (shipped with Babeltrace 2). ctf_plugin = bt2.find_plugin('ctf') # Get the `source.ctf.fs` component class from the plugin. fs_cc = ctf_plugin.source_component_classes['fs'] # Create a trace collection message iterator, instantiating a single # `source.ctf.fs` component class with the `inputs` initialization # parameter set to open a single CTF trace. msg_it = bt2.TraceCollectionMessageIterator( bt2.ComponentSpec( fs_cc, { # Get the CTF trace path from the first command-line argument. 'inputs': [sys.argv[1]], })) # Iterate the trace messages. # for msg in msg_it: # # `bt2._EventMessageConst` is the Python type of an event message. # if type(msg) is bt2._EventMessageConst: # # Print event's name. # print(msg.event.name, msg.event.) # Last event's time (ns from origin). last_event_ns_from_origin = None # Iterate the trace messages. for msg in msg_it: