From 6dde4bd3f274536036474dada30941590175e9a8 Mon Sep 17 00:00:00 2001 From: Christophe Bedard Date: Thu, 15 Aug 2019 09:36:40 +0200 Subject: [PATCH 1/7] Check if OS is Windows when getting shared lib path --- tracetools_launch/tracetools_launch/action.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tracetools_launch/tracetools_launch/action.py b/tracetools_launch/tracetools_launch/action.py index ce46a80..5f30f16 100644 --- a/tracetools_launch/tracetools_launch/action.py +++ b/tracetools_launch/tracetools_launch/action.py @@ -14,6 +14,7 @@ """Module for the Trace action.""" +import os import re import subprocess from typing import List @@ -73,10 +74,12 @@ class Trace(Action): 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 - self.__ld_preload_action = SetEnvironmentVariable( - 'LD_PRELOAD', - self.get_shared_lib_path(profile_lib_name), - ) + 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, + ) @classmethod def has_profiling_events(cls, events_ust: List[str]) -> bool: @@ -91,6 +94,8 @@ class Trace(Action): :param lib_name: the name of the shared library :return: the full path if found, `None` otherwise """ + if os.name == 'nt': + return None (exit_code, output) = subprocess.getstatusoutput(f'whereis -b {lib_name}') if exit_code != 0: return None From 98cf3ad377639fc315e83c9df8a98e9a4881dfde Mon Sep 17 00:00:00 2001 From: Christophe Bedard Date: Thu, 15 Aug 2019 09:45:28 +0200 Subject: [PATCH 2/7] Silently do nothing if lttng cannot be imported --- .../tracetools_trace/tools/lttng.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tracetools_trace/tracetools_trace/tools/lttng.py b/tracetools_trace/tracetools_trace/tools/lttng.py index 52e4a76..95c6d1d 100644 --- a/tracetools_trace/tracetools_trace/tools/lttng.py +++ b/tracetools_trace/tracetools_trace/tools/lttng.py @@ -16,7 +16,10 @@ from typing import List -import lttng +try: + import lttng +except ImportError: + lttng = None from .names import DEFAULT_CONTEXT from .names import DEFAULT_EVENTS_KERNEL @@ -77,6 +80,9 @@ def _lttng_setup( :param channel_name_ust: the UST channel name :param channel_name_kernel: the kernel channel name """ + if lttng is None: + return None + # Resolve full tracing directory path full_path = get_full_session_path(session_name, base_path=base_path) @@ -149,6 +155,9 @@ def _lttng_start(session_name: str) -> None: :param session_name: the name of the session """ + if lttng is None: + return None + result = lttng.start(session_name) if result < 0: raise RuntimeError(f'failed to start tracing: {lttng.strerror(result)}') @@ -160,6 +169,9 @@ def _lttng_stop(session_name: str) -> None: :param session_name: the name of the session """ + if lttng is None: + return None + result = lttng.stop(session_name) if result < 0: raise RuntimeError(f'failed to stop tracing: {lttng.strerror(result)}') @@ -171,6 +183,9 @@ def _lttng_destroy(session_name: str) -> None: :param session_name: the name of the session """ + if lttng is None: + return None + result = lttng.destroy(session_name) if result < 0: raise RuntimeError(f'failed to destroy tracing session: {lttng.strerror(result)}') From 8c6486f5ba17e99e8f8f49b0668afa1b50474c94 Mon Sep 17 00:00:00 2001 From: Christophe Bedard Date: Thu, 15 Aug 2019 09:48:35 +0200 Subject: [PATCH 3/7] Simplify check for lttng import --- tracetools_trace/tracetools_trace/tools/lttng.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/tracetools_trace/tracetools_trace/tools/lttng.py b/tracetools_trace/tracetools_trace/tools/lttng.py index 95c6d1d..649e61b 100644 --- a/tracetools_trace/tracetools_trace/tools/lttng.py +++ b/tracetools_trace/tracetools_trace/tools/lttng.py @@ -44,6 +44,8 @@ def lttng_init( :param kernel_events: list of kernel events to enable :param context_names: list of context elements to enable """ + if lttng is None: + return None _lttng_setup(session_name, base_path, ros_events, kernel_events, context_names) _lttng_start(session_name) @@ -54,6 +56,8 @@ def lttng_fini(session_name: str) -> None: :param session_name: the name of the session """ + if lttng is None: + return None _lttng_stop(session_name) _lttng_destroy(session_name) @@ -80,9 +84,6 @@ def _lttng_setup( :param channel_name_ust: the UST channel name :param channel_name_kernel: the kernel channel name """ - if lttng is None: - return None - # Resolve full tracing directory path full_path = get_full_session_path(session_name, base_path=base_path) @@ -155,9 +156,6 @@ def _lttng_start(session_name: str) -> None: :param session_name: the name of the session """ - if lttng is None: - return None - result = lttng.start(session_name) if result < 0: raise RuntimeError(f'failed to start tracing: {lttng.strerror(result)}') @@ -169,9 +167,6 @@ def _lttng_stop(session_name: str) -> None: :param session_name: the name of the session """ - if lttng is None: - return None - result = lttng.stop(session_name) if result < 0: raise RuntimeError(f'failed to stop tracing: {lttng.strerror(result)}') @@ -183,9 +178,6 @@ def _lttng_destroy(session_name: str) -> None: :param session_name: the name of the session """ - if lttng is None: - return None - result = lttng.destroy(session_name) if result < 0: raise RuntimeError(f'failed to destroy tracing session: {lttng.strerror(result)}') From cd4f8d5d08b04d72930859a818b9eadfe1b045ee Mon Sep 17 00:00:00 2001 From: Christophe Bedard Date: Thu, 15 Aug 2019 10:16:46 +0200 Subject: [PATCH 4/7] Move babeltrace interface functions to separate file --- tracetools_read/tracetools_read/__init__.py | 60 +--------------- tracetools_read/tracetools_read/trace.py | 79 +++++++++++++++++++++ tracetools_test/tracetools_test/case.py | 2 +- 3 files changed, 81 insertions(+), 60 deletions(-) create mode 100644 tracetools_read/tracetools_read/trace.py diff --git a/tracetools_read/tracetools_read/__init__.py b/tracetools_read/tracetools_read/__init__.py index c689173..3c00fb4 100644 --- a/tracetools_read/tracetools_read/__init__.py +++ b/tracetools_read/tracetools_read/__init__.py @@ -12,73 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Module with functions for reading traces.""" +"""Module with trace-reading utilities.""" from typing import Any from typing import Dict -from typing import Iterable -from typing import List - -import babeltrace DictEvent = Dict[str, Any] -def get_trace_ctf_events(trace_directory: str) -> Iterable[babeltrace.babeltrace.Event]: - """ - Get the events of a trace. - - :param trace_directory: the path to the main/top trace directory - :return: events iterable - """ - tc = babeltrace.TraceCollection() - tc.add_traces_recursive(trace_directory, 'ctf') - return tc.events - - -def get_trace_events(trace_directory: str) -> List[DictEvent]: - """ - Get the events of a trace. - - :param trace_directory: the path to the main/top trace directory - :return: events - """ - return [event_to_dict(event) for event in get_trace_ctf_events(trace_directory)] - - -# List of ignored CTF fields -_IGNORED_FIELDS = [ - 'content_size', - 'events_discarded', - 'id', - 'packet_size', - 'packet_seq_num', - 'stream_id', - 'stream_instance_id', - 'timestamp_end', - 'timestamp_begin', - 'magic', - 'uuid', - 'v', -] -_DISCARD = 'events_discarded' - - -def event_to_dict(event: babeltrace.babeltrace.Event) -> DictEvent: - """ - Convert name, timestamp, and all other keys except those in IGNORED_FIELDS into a dictionary. - - :param event: the event to convert - :return: the event as a dictionary - """ - if hasattr(event, _DISCARD) and event[_DISCARD] > 0: - print(event[_DISCARD]) - meta = {'_name': event.name, '_timestamp': event.timestamp} - data = {key: event[key] for key in event.keys() if key not in _IGNORED_FIELDS} - return {**meta, **data} - - def get_field( event: DictEvent, field_name: str, diff --git a/tracetools_read/tracetools_read/trace.py b/tracetools_read/tracetools_read/trace.py new file mode 100644 index 0000000..02d2c27 --- /dev/null +++ b/tracetools_read/tracetools_read/trace.py @@ -0,0 +1,79 @@ +# Copyright 2019 Robert Bosch GmbH +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Module with functions for reading traces.""" + +from typing import Iterable +from typing import List + +import babeltrace + +from . import DictEvent + + +BabeltraceEvent = babeltrace.babeltrace.Event + + +def get_trace_ctf_events(trace_directory: str) -> Iterable[BabeltraceEvent]: + """ + Get the events of a trace. + + :param trace_directory: the path to the main/top trace directory + :return: events iterable + """ + tc = babeltrace.TraceCollection() + tc.add_traces_recursive(trace_directory, 'ctf') + return tc.events + + +def get_trace_events(trace_directory: str) -> List[DictEvent]: + """ + Get the events of a trace. + + :param trace_directory: the path to the main/top trace directory + :return: events + """ + return [event_to_dict(event) for event in get_trace_ctf_events(trace_directory)] + + +# List of ignored CTF fields +_IGNORED_FIELDS = [ + 'content_size', + 'events_discarded', + 'id', + 'packet_size', + 'packet_seq_num', + 'stream_id', + 'stream_instance_id', + 'timestamp_end', + 'timestamp_begin', + 'magic', + 'uuid', + 'v', +] +_DISCARD = 'events_discarded' + + +def event_to_dict(event: BabeltraceEvent) -> DictEvent: + """ + Convert name, timestamp, and all other keys except those in IGNORED_FIELDS into a dictionary. + + :param event: the event to convert + :return: the event as a dictionary + """ + if hasattr(event, _DISCARD) and event[_DISCARD] > 0: + print(event[_DISCARD]) + meta = {'_name': event.name, '_timestamp': event.timestamp} + data = {key: event[key] for key in event.keys() if key not in _IGNORED_FIELDS} + return {**meta, **data} diff --git a/tracetools_test/tracetools_test/case.py b/tracetools_test/tracetools_test/case.py index 94bb291..9e6a899 100644 --- a/tracetools_test/tracetools_test/case.py +++ b/tracetools_test/tracetools_test/case.py @@ -25,7 +25,7 @@ from tracetools_read import get_event_name from tracetools_read import get_event_timestamp from tracetools_read import get_field from tracetools_read import get_procname -from tracetools_read import get_trace_events +from tracetools_read.trace import get_trace_events from .utils import cleanup_trace from .utils import get_event_names From c0b86bd4db8fa739d525496ba2f17620ab6f9b3f Mon Sep 17 00:00:00 2001 From: Christophe Bedard Date: Thu, 15 Aug 2019 13:14:53 +0200 Subject: [PATCH 5/7] Create tracing_supported() util function --- tracetools_launch/tracetools_launch/action.py | 4 ++-- tracetools_trace/tracetools_trace/tools/__init__.py | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tracetools_launch/tracetools_launch/action.py b/tracetools_launch/tracetools_launch/action.py index 5f30f16..e549e3e 100644 --- a/tracetools_launch/tracetools_launch/action.py +++ b/tracetools_launch/tracetools_launch/action.py @@ -14,7 +14,6 @@ """Module for the Trace action.""" -import os import re import subprocess from typing import List @@ -26,6 +25,7 @@ from launch.actions import SetEnvironmentVariable from launch.event import Event from launch.event_handlers import OnShutdown from launch.launch_context import LaunchContext +from tracetools_trace import tracing_supported from tracetools_trace.tools import lttng from tracetools_trace.tools import names from tracetools_trace.tools import path @@ -94,7 +94,7 @@ class Trace(Action): :param lib_name: the name of the shared library :return: the full path if found, `None` otherwise """ - if os.name == 'nt': + if not tracing_supported(): return None (exit_code, output) = subprocess.getstatusoutput(f'whereis -b {lib_name}') if exit_code != 0: diff --git a/tracetools_trace/tracetools_trace/tools/__init__.py b/tracetools_trace/tracetools_trace/tools/__init__.py index 4b18865..e9bbd18 100644 --- a/tracetools_trace/tracetools_trace/tools/__init__.py +++ b/tracetools_trace/tracetools_trace/tools/__init__.py @@ -11,3 +11,15 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + +"""Module for tracing.""" + +import sys + + +def tracing_supported() -> bool: + """ + Check if tracing is supported on this platform. + It does not mean a tracer is installed. + """ + return sys.platform == 'linux' From b399d0cd1cbc075731e55507827da7766b79cfe7 Mon Sep 17 00:00:00 2001 From: Christophe Bedard Date: Thu, 15 Aug 2019 13:22:03 +0200 Subject: [PATCH 6/7] Fix tracing_supported import --- tracetools_launch/tracetools_launch/action.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracetools_launch/tracetools_launch/action.py b/tracetools_launch/tracetools_launch/action.py index e549e3e..9035b06 100644 --- a/tracetools_launch/tracetools_launch/action.py +++ b/tracetools_launch/tracetools_launch/action.py @@ -25,10 +25,10 @@ from launch.actions import SetEnvironmentVariable from launch.event import Event from launch.event_handlers import OnShutdown from launch.launch_context import LaunchContext -from tracetools_trace import tracing_supported from tracetools_trace.tools import lttng from tracetools_trace.tools import names from tracetools_trace.tools import path +from tracetools_trace.tools import tracing_supported class Trace(Action): From a72eda99579f57b6ce375fc816d7f8b81fe34a22 Mon Sep 17 00:00:00 2001 From: Christophe Bedard Date: Thu, 15 Aug 2019 13:23:14 +0200 Subject: [PATCH 7/7] Fix linter error --- tracetools_trace/tracetools_trace/tools/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tracetools_trace/tracetools_trace/tools/__init__.py b/tracetools_trace/tracetools_trace/tools/__init__.py index e9bbd18..be009ca 100644 --- a/tracetools_trace/tracetools_trace/tools/__init__.py +++ b/tracetools_trace/tracetools_trace/tools/__init__.py @@ -20,6 +20,7 @@ import sys def tracing_supported() -> bool: """ Check if tracing is supported on this platform. + It does not mean a tracer is installed. """ return sys.platform == 'linux'