def __init__(self, trace_events, trace_output_dir, trace_name="bioflow_trace"): if type(trace_events) is str: trace_events = [trace_events] self.trace_events = trace_events user = getpass.getuser() trace_name = "{name}_{user}".format(name=trace_name, user=user) self.sess_name = trace_name domain = lttng.Domain() domain.type = lttng.DOMAIN_UST handle = lttng.Handle(domain=domain, session_name=trace_name) self.domain = domain self.handle = handle new_handle = trace_output_dir count = 0 while os.path.exists(new_handle): new_handle = "{trace_dir}_{cnt}".format(trace_dir=trace_output_dir, cnt=count) count += 1 trace_output_dir = new_handle os.makedirs(name=trace_output_dir, exist_ok=False) self.outdir = trace_output_dir curr_sessions = lttng.list_sessions() if trace_name in curr_sessions: lttng.destroy(trace_name) # note: this doesn't delete any files
def lttng_start(events=["*"], domain_type=lttng.DOMAIN_UST): if lttng.session_daemon_alive() == 0: daemon_cmd = "lttng-sessiond --background" daemon_cmd += " --pidfile " + sessiond_pidfile subprocess.check_call(daemon_cmd, shell=True, stdout=sessiond_logfile, stderr=sessiond_logfile) lttng.destroy(session_name) ret = lttng.create_snapshot(session_name, trace_path) if ret < 0: raise RuntimeError("LTTng: " + lttng.strerror(ret)) domain = lttng.Domain() domain.type = domain_type channel = lttng.Channel() channel.name = "channel0" lttng.channel_set_default_attr(domain, channel.attr) han = lttng.Handle(session_name, domain) if han is None: raise RuntimeError("LTTng: failed to create handle") ret = lttng.enable_channel(han, channel) if ret < 0: raise RuntimeError("LTTng: " + lttng.strerror(ret)) for name in events: event = lttng.Event() event.name = name event.type = lttng.EVENT_TRACEPOINT event.loglevel = lttng.EVENT_LOGLEVEL_ALL ret = lttng.enable_event(han, event, channel.name) if ret < 0: raise RuntimeError("LTTng: " + lttng.strerror(ret)) ret = lttng.start(session_name) if ret < 0: raise RuntimeError("LTTng: " + lttng.strerror(ret))
def setup( session_name: str, base_path: str = DEFAULT_BASE_PATH, ros_events: Union[List[str], Set[str]] = DEFAULT_EVENTS_ROS, kernel_events: Union[List[str], Set[str]] = DEFAULT_EVENTS_KERNEL, context_names: Union[List[str], Set[str]] = DEFAULT_CONTEXT, channel_name_ust: str = 'ros2', channel_name_kernel: str = 'kchan', ) -> Optional[str]: """ Set up LTTng session, with events and context. See: https://lttng.org/docs/#doc-core-concepts :param session_name: the name of the session :param base_path: the path to the directory in which to create the tracing session directory :param ros_events: list of ROS events to enable :param kernel_events: list of kernel events to enable :param context_names: list of context elements to enable :param channel_name_ust: the UST channel name :param channel_name_kernel: the kernel channel name :return: the full path to the trace directory """ # Convert lists to sets if not isinstance(ros_events, set): ros_events = set(ros_events) if not isinstance(kernel_events, set): kernel_events = set(kernel_events) if not isinstance(context_names, set): context_names = set(context_names) # Resolve full tracing directory path full_path = get_full_session_path(session_name, base_path=base_path) ust_enabled = ros_events is not None and len(ros_events) > 0 kernel_enabled = kernel_events is not None and len(kernel_events) > 0 # Domains if ust_enabled: domain_ust = lttng.Domain() domain_ust.type = lttng.DOMAIN_UST # Per-user buffer domain_ust.buf_type = lttng.BUFFER_PER_UID channel_ust = lttng.Channel() channel_ust.name = channel_name_ust # Discard, do not overwrite channel_ust.attr.overwrite = 0 # 8 sub-buffers of 2 times the usual page size channel_ust.attr.subbuf_size = 2 * 4096 channel_ust.attr.num_subbuf = 8 # Ignore switch timer interval and use read timer instead channel_ust.attr.switch_timer_interval = 0 channel_ust.attr.read_timer_interval = 200 # mmap channel output instead of splice channel_ust.attr.output = lttng.EVENT_MMAP events_list_ust = _create_events(ros_events) if kernel_enabled: domain_kernel = lttng.Domain() domain_kernel.type = lttng.DOMAIN_KERNEL # Global buffer (only option for kernel domain) domain_kernel.buf_type = lttng.BUFFER_GLOBAL channel_kernel = lttng.Channel() channel_kernel.name = channel_name_kernel # Discard, do not overwrite channel_kernel.attr.overwrite = 0 # 8 sub-buffers of 8 times the usual page size, since # there can be way more kernel events than UST events channel_kernel.attr.subbuf_size = 8 * 4096 channel_kernel.attr.num_subbuf = 8 # Ignore switch timer interval and use read timer instead channel_kernel.attr.switch_timer_interval = 0 channel_kernel.attr.read_timer_interval = 200 # mmap channel output instead of splice channel_kernel.attr.output = lttng.EVENT_MMAP events_list_kernel = _create_events(kernel_events) # Session _create_session(session_name, full_path) # Handles, channels, events handle_ust = None if ust_enabled: handle_ust = _create_handle(session_name, domain_ust) _enable_channel(handle_ust, channel_ust) _enable_events(handle_ust, events_list_ust, channel_ust.name) handle_kernel = None if kernel_enabled: handle_kernel = _create_handle(session_name, domain_kernel) _enable_channel(handle_kernel, channel_kernel) _enable_events(handle_kernel, events_list_kernel, channel_kernel.name) # Context context_list = _create_context_list(context_names) # TODO make it possible to add context in userspace and kernel separately, since some context # types might only apply to userspace OR kernel; only consider userspace contexts for now handles_context = [handle_ust] enabled_handles = list(filter(None, handles_context)) _add_context(enabled_handles, context_list) return full_path
class BabeltraceError(Exception): pass # LTTNG-TOOLS # Making sure session does not already exist lttng.destroy(ses_name) # Creating a new session and handle ret = lttng.create(ses_name, trace_path) if ret < 0: raise LTTngError(lttng.strerror(ret)) domain = lttng.Domain() domain.type = lttng.DOMAIN_KERNEL han = None han = lttng.Handle(ses_name, domain) if han is None: raise LTTngError("Handle not created") # Enabling all events event = lttng.Event() event.type = lttng.EVENT_ALL event.loglevel_type = lttng.EVENT_LOGLEVEL_ALL ret = lttng.enable_event(han, event, None) if ret < 0: raise LTTngError(lttng.strerror(ret))
def setup( *, session_name: str, base_path: str, ros_events: Union[List[str], Set[str]] = DEFAULT_EVENTS_ROS, kernel_events: Union[List[str], Set[str]] = [], context_fields: Union[List[str], Set[str], Dict[str, List[str]]] = DEFAULT_CONTEXT, context_names: Optional[Union[List[str], Set[str], Dict[str, List[str]]]] = None, channel_name_ust: str = 'ros2', channel_name_kernel: str = 'kchan', ) -> Optional[str]: """ Set up LTTng session, with events and context. See: https://lttng.org/docs/#doc-core-concepts Initialization will fail if the list of kernel events to be enabled is not empty and if the kernel tracer is not installed. :param session_name: the name of the session :param base_path: the path to the directory in which to create the tracing session directory :param ros_events: list of ROS events to enable :param kernel_events: list of kernel events to enable :param context_fields: the names of context fields to enable if it's a list or a set, the context fields are enabled for both kernel and userspace; if it's a dictionary: { domain type string -> context fields list } :param context_names: DEPRECATED, use context_fields instead :param channel_name_ust: the UST channel name :param channel_name_kernel: the kernel channel name :return: the full path to the trace directory, or `None` if initialization failed """ # Use value from deprecated param if it is provided # TODO(christophebedard) remove context_names param in Rolling after Humble release if context_names is not None: context_fields = context_names warnings.warn( 'context_names parameter is deprecated, use context_fields', stacklevel=4) # Check if there is a session daemon running if lttng.session_daemon_alive() == 0: # Otherwise spawn one and check if it worked subprocess.run(['lttng-sessiond', '--daemonize'], ) if lttng.session_daemon_alive() == 0: print('error: failed to start lttng session daemon') return None # Make sure the kernel tracer is available if there are kernel events # Do this after spawning a session daemon, otherwise we can't detect the kernel tracer if 0 < len(kernel_events): kernel_tracer_available, message = is_kernel_tracer_available() if not kernel_tracer_available: print( f'error: kernel tracer is not available: {message}\n' ' cannot use kernel events:\n' " 'ros2 trace' command: cannot use '-k' option\n" " 'Trace' action: cannot set 'events_kernel'/'events-kernel' list\n" ' install the kernel tracer, e.g., on Ubuntu, install lttng-modules-dkms\n' ' see: https://gitlab.com/ros-tracing/ros2_tracing#building') return None # Convert lists to sets if not isinstance(ros_events, set): ros_events = set(ros_events) if not isinstance(kernel_events, set): kernel_events = set(kernel_events) if isinstance(context_fields, list): context_fields = set(context_fields) # Resolve full tracing directory path full_path = os.path.join(base_path, session_name) ust_enabled = ros_events is not None and len(ros_events) > 0 kernel_enabled = kernel_events is not None and len(kernel_events) > 0 # Domains if ust_enabled: domain_ust = lttng.Domain() domain_ust.type = lttng.DOMAIN_UST # Per-user buffer domain_ust.buf_type = lttng.BUFFER_PER_UID channel_ust = lttng.Channel() channel_ust.name = channel_name_ust # Discard, do not overwrite channel_ust.attr.overwrite = 0 # 2 sub-buffers of 8 times the usual page size # We use 2 sub-buffers because the number of sub-buffers is pointless in discard mode, # and switching between sub-buffers introduces noticeable CPU overhead channel_ust.attr.subbuf_size = 8 * 4096 channel_ust.attr.num_subbuf = 2 # Ignore switch timer interval and use read timer instead channel_ust.attr.switch_timer_interval = 0 channel_ust.attr.read_timer_interval = 200 # mmap channel output (only option for UST) channel_ust.attr.output = lttng.EVENT_MMAP events_list_ust = _create_events(ros_events) if kernel_enabled: domain_kernel = lttng.Domain() domain_kernel.type = lttng.DOMAIN_KERNEL # Global buffer (only option for kernel domain) domain_kernel.buf_type = lttng.BUFFER_GLOBAL channel_kernel = lttng.Channel() channel_kernel.name = channel_name_kernel # Discard, do not overwrite channel_kernel.attr.overwrite = 0 # 2 sub-buffers of 32 times the usual page size, since # there can be way more kernel events than UST events channel_kernel.attr.subbuf_size = 32 * 4096 channel_kernel.attr.num_subbuf = 2 # Ignore switch timer interval and use read timer instead channel_kernel.attr.switch_timer_interval = 0 channel_kernel.attr.read_timer_interval = 200 # mmap channel output instead of splice channel_kernel.attr.output = lttng.EVENT_MMAP events_list_kernel = _create_events(kernel_events) # Session _create_session(session_name, full_path) # Handles, channels, events handle_ust = None if ust_enabled: handle_ust = _create_handle(session_name, domain_ust) _enable_channel(handle_ust, channel_ust) _enable_events(handle_ust, events_list_ust, channel_ust.name) handle_kernel = None if kernel_enabled: handle_kernel = _create_handle(session_name, domain_kernel) _enable_channel(handle_kernel, channel_kernel) _enable_events(handle_kernel, events_list_kernel, channel_kernel.name) # Context contexts_dict = _normalize_contexts_dict( { 'kernel': handle_kernel, 'userspace': handle_ust }, context_fields) _add_context(contexts_dict) return full_path
def setup( session_name: str, base_path: str = DEFAULT_BASE_PATH, ros_events: List[str] = DEFAULT_EVENTS_ROS, kernel_events: List[str] = DEFAULT_EVENTS_KERNEL, context_names: List[str] = DEFAULT_CONTEXT, channel_name_ust: str = 'ros2', channel_name_kernel: str = 'kchan', ) -> None: """ Set up LTTng session, with events and context. See: https://lttng.org/docs/#doc-core-concepts :param session_name: the name of the session :param base_path: the path to the directory in which to create the tracing session directory :param ros_events: list of ROS events to enable :param kernel_events: list of kernel events to enable :param context_names: list of context elements to enable :param channel_name_ust: the UST channel name :param channel_name_kernel: the kernel channel name """ # Resolve full tracing directory path full_path = get_full_session_path(session_name, base_path=base_path) ust_enabled = ros_events is not None and len(ros_events) > 0 kernel_enabled = kernel_events is not None and len(kernel_events) > 0 # Domains if ust_enabled: domain_ust = lttng.Domain() domain_ust.type = lttng.DOMAIN_UST # Per-user buffer domain_ust.buf_type = lttng.BUFFER_PER_UID channel_ust = lttng.Channel() channel_ust.name = channel_name_ust # Discard, do not overwrite channel_ust.attr.overwrite = 0 # 8 sub-buffers of 2 times the usual page size channel_ust.attr.subbuf_size = 2 * 4096 channel_ust.attr.num_subbuf = 8 # Ignore switch timer interval and use read timer instead channel_ust.attr.switch_timer_interval = 0 channel_ust.attr.read_timer_interval = 200 # mmap channel output instead of splice channel_ust.attr.output = lttng.EVENT_MMAP events_list_ust = _create_events(ros_events) if kernel_enabled: domain_kernel = lttng.Domain() domain_kernel.type = lttng.DOMAIN_KERNEL # Global buffer (only option for kernel domain) domain_kernel.buf_type = lttng.BUFFER_GLOBAL channel_kernel = lttng.Channel() channel_kernel.name = channel_name_kernel # Discard, do not overwrite channel_kernel.attr.overwrite = 0 # 8 sub-buffers of 8 times the usual page size, since # there can be way more kernel events than UST events channel_kernel.attr.subbuf_size = 8 * 4096 channel_kernel.attr.num_subbuf = 8 # Ignore switch timer interval and use read timer instead channel_kernel.attr.switch_timer_interval = 0 channel_kernel.attr.read_timer_interval = 200 # mmap channel output instead of splice channel_kernel.attr.output = lttng.EVENT_MMAP events_list_kernel = _create_events(kernel_events) # Session _create_session(session_name, full_path) # Handles, channels, events handle_ust = None if ust_enabled: handle_ust = _create_handle(session_name, domain_ust) _enable_channel(handle_ust, channel_ust) _enable_events(handle_ust, events_list_ust, channel_ust.name) handle_kernel = None if kernel_enabled: handle_kernel = _create_handle(session_name, domain_kernel) _enable_channel(handle_kernel, channel_kernel) _enable_events(handle_kernel, events_list_kernel, channel_kernel.name) # Context context_list = _create_context_list(context_names) enabled_handles = [h for h in [handle_ust, handle_kernel] if h is not None] _add_context(enabled_handles, context_list)