예제 #1
0
def run_and_trace(
    base_path: str,
    session_name_prefix: str,
    ros_events: List[str],
    kernel_events: List[str],
    package_name: str,
    node_names: List[str],
    additional_actions: Union[List[Action], Action] = [],
) -> Tuple[int, str]:
    """
    Run a node while tracing.

    :param base_path: the base path where to put the trace directory
    :param session_name_prefix: the session name prefix for the trace directory
    :param ros_events: the list of ROS UST events to enable
    :param kernel_events: the list of kernel events to enable
    :param package_name: the name of the package to use
    :param node_names: the names of the nodes to execute
    :param additional_actions: the list of additional actions to prepend
    :return: exit code, full generated path
    """
    session_name = append_timestamp(session_name_prefix)
    full_path = os.path.join(base_path, session_name)
    if not isinstance(additional_actions, list):
        additional_actions = [additional_actions]

    launch_actions = additional_actions
    # Add trace action
    launch_actions.append(
        Trace(
            session_name=session_name,
            append_timestamp=False,
            base_path=base_path,
            events_ust=ros_events,
            events_kernel=kernel_events,
        ))
    # Add nodes
    for node_name in node_names:
        n = Node(
            package=package_name,
            executable=node_name,
            output='screen',
        )
        launch_actions.append(n)
    ld = LaunchDescription(launch_actions)
    ls = LaunchService()
    ls.include_launch_description(ld)

    exit_code = ls.run()

    return exit_code, full_path
예제 #2
0
    def __init__(
        self,
        *,
        session_name: str,
        append_timestamp: bool = False,
        base_path: Optional[str] = None,
        events_ust: List[str] = names.DEFAULT_EVENTS_ROS,
        events_kernel: List[str] = names.DEFAULT_EVENTS_KERNEL,
        context_names: List[str] = names.DEFAULT_CONTEXT,
        profile_fast: bool = True,
        **kwargs,
    ) -> None:
        """
        Create a Trace.

        :param session_name: the name of the tracing session
        :param append_timestamp: whether to append timestamp to the session name
        :param base_path: the path to the base directory in which to create the session directory,
        or `None` for default
        :param events_ust: the list of ROS UST events to enable
        :param events_kernel: the list of kernel events to enable
        :param context_names: the list of context names to enable
        :param profile_fast: `True` to use fast profiling, `False` for normal (only if necessary)
        """
        super().__init__(**kwargs)
        if append_timestamp:
            session_name = path.append_timestamp(session_name)
        self.__session_name = session_name
        self.__base_path = base_path or path.get_tracing_directory()
        self.__events_ust = events_ust
        self.__events_kernel = events_kernel
        self.__context_names = context_names
        self.__profile_fast = profile_fast
        self.__logger = logging.get_logger(__name__)
        self.__ld_preload_actions: List[LdPreload] = []
        # Add LD_PRELOAD actions if corresponding events are enabled
        if self.has_profiling_events(self.__events_ust):
            self.__ld_preload_actions.append(
                LdPreload(self.LIB_PROFILE_FAST if profile_fast else self.LIB_PROFILE_NORMAL)
            )
        if self.has_ust_memory_events(self.__events_ust):
            self.__ld_preload_actions.append(
                LdPreload(self.LIB_MEMORY_UST)
            )
예제 #3
0
    def __perform_substitutions(self, context: LaunchContext) -> None:
        self.__session_name = perform_substitutions(context,
                                                    self.__session_name)
        if self.__append_timestamp:
            self.__session_name = path.append_timestamp(self.__session_name)
        self.__base_path = perform_substitutions(context, self.__base_path) \
            if self.__base_path else path.get_tracing_directory()
        self.__events_ust = [
            perform_substitutions(context, x) for x in self.__events_ust
        ]
        self.__events_kernel = [
            perform_substitutions(context, x) for x in self.__events_kernel
        ]
        self.__context_fields = \
            {
                domain: [perform_substitutions(context, field) for field in fields]
                for domain, fields in self.__context_fields.items()
            } \
            if isinstance(self.__context_fields, dict) \
            else [perform_substitutions(context, field) for field in self.__context_fields]

        # Add LD_PRELOAD actions if corresponding events are enabled
        if self.has_libc_wrapper_events(self.__events_ust):
            self.__ld_preload_actions.append(LdPreload(self.LIB_LIBC_WRAPPER))
        if self.has_pthread_wrapper_events(self.__events_ust):
            self.__ld_preload_actions.append(
                LdPreload(self.LIB_PTHREAD_WRAPPER))
        if self.has_dl_events(self.__events_ust):
            self.__ld_preload_actions.append(LdPreload(self.LIB_DL))
        # Warn if events match both normal AND fast profiling libs
        has_fast_profiling_events = self.has_profiling_events(
            self.__events_ust, True)
        has_normal_profiling_events = self.has_profiling_events(
            self.__events_ust, False)
        # In practice, the first lib in the LD_PRELOAD list will be used, so the fast one here
        if has_fast_profiling_events:
            self.__ld_preload_actions.append(LdPreload(self.LIB_PROFILE_FAST))
        if has_normal_profiling_events:
            self.__ld_preload_actions.append(LdPreload(
                self.LIB_PROFILE_NORMAL))
        if has_normal_profiling_events and has_fast_profiling_events:
            self.__logger.warning(
                'events match both normal and fast profiling shared libraries')
예제 #4
0
    def __init__(
        self,
        *,
        session_name: str,
        append_timestamp: bool = False,
        base_path: str = path.DEFAULT_BASE_PATH,
        events_ust: List[str] = names.DEFAULT_EVENTS_ROS,
        events_kernel: List[str] = names.DEFAULT_EVENTS_KERNEL,
        profile_fast: bool = True,
        **kwargs,
    ) -> None:
        """
        Constructor.

        :param session_name: the name of the tracing session
        :param append_timestamp: whether to append timestamp to the session name
        :param base_path: the path to the base directory in which to create the session directory
        :param events_ust: the list of ROS UST events to enable
        :param events_kernel: the list of kernel events to enable
        :param profile_fast: `True` to use fast profiling, `False` for normal (only if necessary)
        """
        super().__init__(**kwargs)
        if append_timestamp:
            session_name = path.append_timestamp(session_name)
        self.__session_name = session_name
        self.__base_path = base_path
        self.__events_ust = events_ust
        self.__events_kernel = events_kernel
        self.__profile_fast = profile_fast
        self.__ld_preload_action = None
        if self.has_profiling_events(events_ust):
            profile_lib_name = self.PROFILE_LIB_FAST if profile_fast else self.PROFILE_LIB_NORMAL
            profile_lib_path = self.get_shared_lib_path(profile_lib_name)
            if profile_lib_path is not None:
                self.__ld_preload_action = SetEnvironmentVariable(
                    'LD_PRELOAD',
                    profile_lib_path,
                )