* [PATCH 1/3] trace-cruncher: Add ksynth class to ft_utiles
@ 2022-02-03 15:35 Yordan Karadzhov (VMware)
2022-02-03 15:35 ` [PATCH 2/3] trace-cruncher: Add tests for the ksynth class Yordan Karadzhov (VMware)
2022-02-03 15:35 ` [PATCH 3/3] trace-cruncher: Add example for the high-level synth. events APIs Yordan Karadzhov (VMware)
0 siblings, 2 replies; 3+ messages in thread
From: Yordan Karadzhov (VMware) @ 2022-02-03 15:35 UTC (permalink / raw)
To: linux-trace-devel; +Cc: Yordan Karadzhov (VMware)
Define a Python class and helper methods to be used for easy manipulation
of kernel synthetic events.
Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
tracecruncher/ft_utils.py | 119 ++++++++++++++++++++++++++++++++++++++
1 file changed, 119 insertions(+)
diff --git a/tracecruncher/ft_utils.py b/tracecruncher/ft_utils.py
index 26c06ec..26978f3 100644
--- a/tracecruncher/ft_utils.py
+++ b/tracecruncher/ft_utils.py
@@ -314,3 +314,122 @@ def find_khist(name, event, axes, instance=None,
raise RuntimeError(msg) from err
return hist
+
+class ksynth(event):
+ def __init__(self, name, start_event, end_event,
+ synth_fields=None, match_name=ft.no_arg()):
+ """ Constructor.
+ """
+ super().__init__(system='synthetic', name=name, static=False)
+ self.synth = ft.synth(name,
+ start_sys=start_event['event'].system,
+ start_evt=start_event['event'].name,
+ end_sys=end_event['event'].system,
+ end_evt=end_event['event'].name,
+ start_match=start_event['match'],
+ end_match=end_event['match'],
+ match_name=match_name)
+
+ start_fields = end_fields = []
+
+ if 'fields' in start_event:
+ start_fields = start_event['fields']
+
+ start_field_names = [None] * len(start_fields)
+ if 'field_names' in start_event:
+ start_field_names = start_event['field_names']
+
+ self.synth.add_start_fields(fields=start_fields,
+ names=start_field_names)
+
+ if 'fields' in end_event:
+ end_fields = end_event['fields']
+
+ end_field_names = [None] * len(end_fields)
+ if 'field_names' in end_event:
+ end_field_names = end_event['field_names']
+
+ self.synth.add_end_fields(fields=end_fields,
+ names=end_field_names)
+
+ if synth_fields is not None:
+ for f in synth_fields:
+ args = f.split(' ')
+ if args[0] == 'delta_t' and len(args) < 4:
+ if len(args) == 1:
+ self.synth.add_delta_T()
+ elif len(args) == 3 and args[2] == 'hd':
+ self.synth.add_delta_T(name=args[1], hd=True)
+ elif args[1] == 'hd':
+ self.synth.add_delta_T(hd=True)
+ else:
+ self.synth.add_delta_T(name=args[1])
+ elif args[0] == 'delta_start' and len(args) == 4:
+ self.synth.add_delta_start(name=args[1],
+ start_field=args[2],
+ end_field=args[3])
+ elif args[0] == 'delta_end' and len(args) == 4:
+ self.synth.add_delta_end(name=args[1],
+ start_field=args[2],
+ end_field=args[3])
+ elif args[0] == 'delta_start' and len(args) == 3:
+ self.synth.add_sum(start_field=args[1], end_field=args[2])
+ else:
+ raise ValueError('Invalid synth. field \'{0}\''.format(f))
+
+ self.synth.register()
+ self.evt_id = find_event_id(system=self.system, event=self.name)
+
+ def __repr__(self):
+ """ Read the descriptor of the synthetic event.
+ """
+ return self.synth.repr(event=True, hist_start=True, hist_end=True)
+
+
+def ksynth_event_item(event, match, fields=[]):
+ """ Create descriptor for an event item (component) of a synthetic event.
+ To be used as a start/end event.
+ """
+ sub_evt = {}
+ sub_evt['event'] = event
+ sub_evt['fields'] = fields
+ sub_evt['field_names'] = [None] * len(fields)
+ sub_evt['match'] = match
+
+ return sub_evt
+
+
+def ksynth_field_rename(event, field, name):
+ """ Change the name of a field in the event component of a synthetic event.
+ """
+ pos = event['fields'].index(field)
+ event['field_names'][pos] = name
+
+ return event
+
+
+def ksynth_field_deltaT(name='delta_T', hd=False):
+ """ Create descriptor for time-diference synthetic field.
+ """
+ if hd:
+ return 'delta_t {0} hd'.format(name)
+
+ return 'delta_t {0} hd'.format(name)
+
+
+def ksynth_field_delta_start(name, start_field, end_field):
+ """ Create descriptor for field diference (start - end) synthetic field.
+ """
+ return 'delta_start {0} {1} {2}'.format(name, start_field, end_field)
+
+
+def ksynth_field_delta_end(name, start_field, end_field):
+ """ Create descriptor for field diference (end - start) synthetic field.
+ """
+ return 'delta_end {0} {1} {2}'.format(name, start_field, end_field)
+
+
+def ksynth_field_sum(name, start_field, end_field):
+ """ Create descriptor for field sum synthetic field.
+ """
+ return 'sum {0} {1} {2}'.format(name, start_field, end_field)
--
2.32.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/3] trace-cruncher: Add tests for the ksynth class
2022-02-03 15:35 [PATCH 1/3] trace-cruncher: Add ksynth class to ft_utiles Yordan Karadzhov (VMware)
@ 2022-02-03 15:35 ` Yordan Karadzhov (VMware)
2022-02-03 15:35 ` [PATCH 3/3] trace-cruncher: Add example for the high-level synth. events APIs Yordan Karadzhov (VMware)
1 sibling, 0 replies; 3+ messages in thread
From: Yordan Karadzhov (VMware) @ 2022-02-03 15:35 UTC (permalink / raw)
To: linux-trace-devel; +Cc: Yordan Karadzhov (VMware)
Testing the high-level Python APIs for kernel synthetic events.
Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
.../tests/1_unit/test_01_ftracepy_unit.py | 55 +++++++++++++++++++
1 file changed, 55 insertions(+)
diff --git a/tracecruncher/tests/1_unit/test_01_ftracepy_unit.py b/tracecruncher/tests/1_unit/test_01_ftracepy_unit.py
index f51bcc1..70f5d29 100644
--- a/tracecruncher/tests/1_unit/test_01_ftracepy_unit.py
+++ b/tracecruncher/tests/1_unit/test_01_ftracepy_unit.py
@@ -825,6 +825,61 @@ class SyntTestCase(unittest.TestCase):
self.assertEqual('none', synth.get_filter())
synth.unregister()
+swaking = tc.event('sched', 'sched_waking')
+sswitch = tc.event('sched', 'sched_switch')
+
+class SyntTestCase(unittest.TestCase):
+ def test_synt_create(self):
+ start = tc.ksynth_event_item(event=swaking,
+ fields=['target_cpu', 'prio'],
+ match='pid')
+ self.assertEqual(start['fields'], ['target_cpu', 'prio'])
+ self.assertEqual(start['match'], 'pid')
+ self.assertEqual(start['field_names'], [None, None])
+
+ start = tc.ksynth_field_rename(start,
+ field='target_cpu', name='cpu')
+ self.assertEqual(start['field_names'], ['cpu', None])
+
+ end = tc.ksynth_event_item(event=sswitch,
+ fields=['prev_prio'],
+ match='next_pid')
+ self.assertEqual(end['fields'], ['prev_prio'])
+ self.assertEqual(end['match'], 'next_pid')
+
+ synth = tc.ksynth(name='synth_wakeup',
+ start_event=start, end_event=end,
+ synth_fields=[tc.ksynth_field_deltaT(hd=True)],
+ match_name='pid')
+
+ synth_str = synth.__repr__().split('\n')
+ event = synth_str[0]
+ hist_s = synth_str[1]
+ hist_e = synth_str[2]
+
+ self.assertTrue('keys=pid'in hist_s)
+ self.assertTrue('keys=next_pid' in hist_e)
+ self.assertTrue('pid=next_pid' in hist_e)
+ self.assertTrue('onmatch(sched.sched_waking).trace(synth_wakeup,$pid' in hist_e)
+ self.assertTrue('s32 cpu;' in event)
+ self.assertTrue('s32 prio;' in event)
+ split_1 = hist_s.split('__arg_')
+ arg1 = '__arg_' + split_1[1].split('=')[0]
+ arg2 = '__arg_' + split_1[2].split('=')[0]
+ self.assertTrue(arg1 + '=target_cpu' in hist_s)
+ self.assertTrue(arg2 + '=prio' in hist_s)
+ self.assertTrue('cpu=$' + arg1 in hist_e)
+ self.assertTrue('prio=$' + arg2 in hist_e)
+ split_2 = hist_e.split('trace(')
+ self.assertTrue('$pid' in split_2[1])
+ self.assertTrue('$prio' in split_2[1])
+ self.assertTrue('s32 prev_prio;' in event)
+ split_3 = hist_e.split('__arg_')
+ arg3 = '__arg_' + split_3[3].split('=')[0]
+ self.assertTrue(arg3 + '=prev_prio' in hist_e)
+ split_4 = hist_e.split('trace(')
+ self.assertTrue('$' + arg3 in split_4[1])
+
if __name__ == '__main__':
unittest.main()
--
2.32.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 3/3] trace-cruncher: Add example for the high-level synth. events APIs
2022-02-03 15:35 [PATCH 1/3] trace-cruncher: Add ksynth class to ft_utiles Yordan Karadzhov (VMware)
2022-02-03 15:35 ` [PATCH 2/3] trace-cruncher: Add tests for the ksynth class Yordan Karadzhov (VMware)
@ 2022-02-03 15:35 ` Yordan Karadzhov (VMware)
1 sibling, 0 replies; 3+ messages in thread
From: Yordan Karadzhov (VMware) @ 2022-02-03 15:35 UTC (permalink / raw)
To: linux-trace-devel; +Cc: Yordan Karadzhov (VMware)
This is a very basic example, demonstrating the usage of the new
high-level Python APIs for kernel synthetic events.
Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
examples/synth_oop.py | 45 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
create mode 100644 examples/synth_oop.py
diff --git a/examples/synth_oop.py b/examples/synth_oop.py
new file mode 100644
index 0000000..865e784
--- /dev/null
+++ b/examples/synth_oop.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python3
+
+"""
+SPDX-License-Identifier: CC-BY-4.0
+
+Copyright 2021 VMware Inc, Yordan Karadzhov (VMware) <y.karadz@gmail.com>
+"""
+
+import tracecruncher.ftracepy as ft
+import tracecruncher.ft_utils as tc
+
+# We will define a synthetic event, to be recorded every time a 'start' event is
+# followed by an 'end' event and both events have the same value of a 'match' field.
+
+# Get the static kernel event 'sched_waking' and 'sched_switch' from system
+# 'sched'. Those two events will be used to create the synthetic event.
+swaking = tc.event('sched', 'sched_waking')
+sswitch = tc.event('sched', 'sched_switch')
+
+# Add to the synth. event two fields from the 'start' event (sched_waking). In the
+# synth. event, the field 'target_cpu' will be renamed to 'cpu'. Use the 'pid' field
+# for matching with the corresponding 'end' event.
+start = tc.ksynth_event_item(event=swaking, fields=['target_cpu', 'prio'], match='pid')
+start = tc.ksynth_field_rename(start, field='target_cpu', name='cpu')
+
+# Add to the synth. event one field from the 'end' event (sched_switch).
+# Use the 'next_pid' field for matching with the corresponding 'start' event.
+end = tc.ksynth_event_item(event=sswitch, fields=['prev_prio'], match='next_pid')
+
+# Define a synthetic event. The 'match' value will be recorder as a field in the
+# synth. event using 'pid' as name. We also add to the synth. event a field that
+# measures the time-difference between the 'start' and 'end' events. This new field
+# will use 'hd' time resolution (nanoseconds).
+synth = tc.ksynth(name='synth_wakeup', start_event=start, end_event=end,
+ synth_fields=[tc.ksynth_field_deltaT(hd=True)], match_name='pid')
+
+# Create new instance of Ftrace.
+inst = ft.create_instance()
+
+# Apply a filter and enable the synth. event.
+synth.set_filter(instance=inst, filter='prio<100')
+synth.enable(instance=inst)
+
+# Print the stream of trace events. "Ctrl+c" to stop tracing.
+ft.read_trace(instance=inst)
--
2.32.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2022-02-03 15:36 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-02-03 15:35 [PATCH 1/3] trace-cruncher: Add ksynth class to ft_utiles Yordan Karadzhov (VMware)
2022-02-03 15:35 ` [PATCH 2/3] trace-cruncher: Add tests for the ksynth class Yordan Karadzhov (VMware)
2022-02-03 15:35 ` [PATCH 3/3] trace-cruncher: Add example for the high-level synth. events APIs Yordan Karadzhov (VMware)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).