diff --git a/tracetools_launch/.gitignore b/tracetools_launch/.gitignore new file mode 100644 index 0000000..eef29c1 --- /dev/null +++ b/tracetools_launch/.gitignore @@ -0,0 +1,3 @@ +*~ +*.pyc + diff --git a/tracetools_launch/launch/example.launch.py b/tracetools_launch/launch/example.launch.py new file mode 100644 index 0000000..f5499db --- /dev/null +++ b/tracetools_launch/launch/example.launch.py @@ -0,0 +1,21 @@ +# Example launch file for the Trace action + +from launch import LaunchDescription +from launch_ros.actions import Node +from tracetools_launch.trace import Trace + + +def generate_launch_description(): + return LaunchDescription([ + Trace( + session_name='my-tracing-session', + base_path='/tmp'), + Node( + package='examples_rclcpp_minimal_publisher', + node_executable='publisher_member_function', + output='screen'), + Node( + package='examples_rclcpp_minimal_subscriber', + node_executable='subscriber_member_function', + output='screen'), + ]) diff --git a/tracetools_launch/package.xml b/tracetools_launch/package.xml new file mode 100644 index 0000000..b99c7a6 --- /dev/null +++ b/tracetools_launch/package.xml @@ -0,0 +1,23 @@ + + + + tracetools_launch + 0.0.1 + Launch integration for tracing + Christophe Bedard + TODO + Christophe Bedard + + launch + launch_ros + tracetools_trace + + ament_copyright + ament_flake8 + ament_pep257 + python3-pytest + + + ament_python + + diff --git a/tracetools_launch/setup.cfg b/tracetools_launch/setup.cfg new file mode 100644 index 0000000..b7ef5cb --- /dev/null +++ b/tracetools_launch/setup.cfg @@ -0,0 +1,4 @@ +[develop] +script-dir=$base/lib/tracetools_launch +[install] +install-scripts=$base/lib/tracetools_launch diff --git a/tracetools_launch/setup.py b/tracetools_launch/setup.py new file mode 100644 index 0000000..370b97c --- /dev/null +++ b/tracetools_launch/setup.py @@ -0,0 +1,26 @@ +import glob + +from setuptools import find_packages +from setuptools import setup + +package_name = 'tracetools_launch' + +setup( + name=package_name, + version='0.0.1', + packages=find_packages(exclude=['test']), + data_files=[ + ('share/' + package_name, ['package.xml']), + ('share/' + package_name + '/launch', glob.glob('launch/*.launch.py')), + ], + install_requires=['setuptools'], + maintainer='Christophe Bedard', + maintainer_email='fixed-term.christophe.bourquebedard@de.bosch.com', + author='Christophe Bedard', + author_email='fixed-term.christophe.bourquebedard@de.bosch.com', + # url='', + keywords=['ROS'], + description='Launch integration for tracing', + license='TODO', + tests_require=['pytest'], +) diff --git a/tracetools_launch/tracetools_launch/__init__.py b/tracetools_launch/tracetools_launch/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tracetools_launch/tracetools_launch/trace.py b/tracetools_launch/tracetools_launch/trace.py new file mode 100644 index 0000000..2c7cbff --- /dev/null +++ b/tracetools_launch/tracetools_launch/trace.py @@ -0,0 +1,63 @@ +"""Module for the Trace action.""" + +import os +from typing import List +from typing import Optional + +from launch.action import Action +from launch.event import Event +from launch.event_handlers import OnShutdown +from launch.launch_context import LaunchContext +from tracetools_trace.tools import lttng +from tracetools_trace.tools import names + + +class Trace(Action): + """ + Tracing action for launch. + + Sets up and enables tracing through a launch file description. + """ + + def __init__( + self, + *, + session_name: str, + base_path: str = '/tmp', + events_ust: List[str] = names.DEFAULT_EVENTS_ROS, + events_kernel: List[str] = names.DEFAULT_EVENTS_KERNEL, + **kwargs, + ) -> None: + """Constructor.""" + super().__init__(**kwargs) + self.__session_name = session_name + self.__path = os.path.join(base_path, session_name) + self.__events_ust = events_ust + self.__events_kernel = events_kernel + + def execute(self, context: LaunchContext) -> Optional[List[Action]]: + # TODO make sure this is done as late as possible + context.register_event_handler(OnShutdown(on_shutdown=self._destroy)) + # TODO make sure this is done as early as possible + self._setup() + + def _setup(self) -> None: + print('setting up tracing!') + lttng.lttng_init( + self.__session_name, + self.__path, + ros_events=self.__events_ust, + kernel_events=self.__events_kernel) + + def _destroy(self, event: Event, context: LaunchContext) -> None: + print('destroying tracing session!') + lttng.lttng_fini(self.__session_name) + + def __repr__(self): + return ( + "Trace(" + f"session_name='{self.__session_name}', " + f"path='{self.__path}', " + f"num_events_ust={len(self.__events_ust)}, " + f"num_events_kernel={len(self.__events_kernel)})" + )