diff --git a/tracetools_analysis/tracetools_analysis/processor/__init__.py b/tracetools_analysis/tracetools_analysis/processor/__init__.py index 789265e..5cff556 100644 --- a/tracetools_analysis/tracetools_analysis/processor/__init__.py +++ b/tracetools_analysis/tracetools_analysis/processor/__init__.py @@ -121,8 +121,9 @@ class EventHandler(Dependant): :param handler_map: the mapping from event name to handling method """ - assert handler_map is not None and len(handler_map) > 0, \ + assert handler_map is None or len(handler_map) > 0, \ f'empty map: {self.__class__.__name__}' + assert all(required_name in handler_map.keys() for required_name in self.required_events()) self._handler_map = handler_map self.processor = None @@ -136,6 +137,16 @@ class EventHandler(Dependant): """Get the data model.""" return None + @staticmethod + def required_events() -> List[str]: + """ + Get the list of events required by this EventHandler. + + Without these events, the EventHandler would be invalid/useless. Inheriting classes can + decide not to declare that they require specific events. + """ + return [] + def register_processor(self, processor: 'Processor') -> None: """Register processor with this `EventHandler` so that it can query other handlers.""" self.processor = processor diff --git a/tracetools_analysis/tracetools_analysis/processor/cpu_time.py b/tracetools_analysis/tracetools_analysis/processor/cpu_time.py index 2eb1698..d842ac3 100644 --- a/tracetools_analysis/tracetools_analysis/processor/cpu_time.py +++ b/tracetools_analysis/tracetools_analysis/processor/cpu_time.py @@ -15,6 +15,7 @@ """Module for CPU time events processing.""" from typing import Dict +from typing import List from tracetools_read import get_field @@ -51,6 +52,12 @@ class CpuTimeHandler(EventHandler): # cpu_id -> start timestamp of the running thread self._cpu_start: Dict[int, int] = {} + @staticmethod + def required_events() -> List[str]: + return [ + 'sched_switch', + ] + @property def data(self) -> CpuTimeDataModel: return self._data_model diff --git a/tracetools_analysis/tracetools_analysis/processor/memory_usage.py b/tracetools_analysis/tracetools_analysis/processor/memory_usage.py index d132d1b..2891839 100644 --- a/tracetools_analysis/tracetools_analysis/processor/memory_usage.py +++ b/tracetools_analysis/tracetools_analysis/processor/memory_usage.py @@ -15,6 +15,7 @@ """Module for memory usage events processing.""" from typing import Dict +from typing import List from tracetools_read import get_field @@ -96,6 +97,17 @@ class UserspaceMemoryUsageHandler(MemoryUsageHandler): # (used to know keep track of the memory size allocated at a given pointer) self._memory: Dict[int, int] = {} + @staticmethod + def required_events() -> List[str]: + return [ + 'lttng_ust_libc:malloc', + 'lttng_ust_libc:calloc', + 'lttng_ust_libc:realloc', + 'lttng_ust_libc:free', + 'lttng_ust_libc:memalign', + 'lttng_ust_libc:posix_memalign', + ] + def _handle_malloc( self, event: Dict, metadata: EventMetadata ) -> None: @@ -200,6 +212,13 @@ class KernelMemoryUsageHandler(MemoryUsageHandler): **kwargs, ) + @staticmethod + def required_events() -> List[str]: + return [ + 'kmem_mm_page_alloc', + 'kmem_mm_page_free', + ] + def _handle_malloc( self, event: Dict, metadata: EventMetadata ) -> None: diff --git a/tracetools_analysis/tracetools_analysis/processor/profile.py b/tracetools_analysis/tracetools_analysis/processor/profile.py index 20178bb..1ed4b1a 100644 --- a/tracetools_analysis/tracetools_analysis/processor/profile.py +++ b/tracetools_analysis/tracetools_analysis/processor/profile.py @@ -86,6 +86,14 @@ class ProfileHandler(EventHandler): # ] self._current_funcs: Dict[int, List[List[Union[str, int]]]] = defaultdict(list) + @staticmethod + def required_events() -> List[str]: + return [ + 'lttng_ust_cyg_profile_fast:func_entry', + 'lttng_ust_cyg_profile_fast:func_exit', + 'sched_switch', + ] + @staticmethod def addr_to_int(addr: Union[int, str]) -> int: """Transform an address into an `int` if it's a hex `str`."""