Tests: add basic ust context tests for $app, vpid, vuid, vgid
[lttng-tools.git] / tests / utils / lttngtest / lttngctl.py
diff --git a/tests/utils/lttngtest/lttngctl.py b/tests/utils/lttngtest/lttngctl.py
new file mode 100644 (file)
index 0000000..632c130
--- /dev/null
@@ -0,0 +1,406 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+#
+# SPDX-License-Identifier: GPL-2.0-only
+
+import abc
+import random
+import string
+import pathlib
+import enum
+from typing import Optional, Type, Union, List
+
+"""
+Defines an abstract interface to control LTTng tracing.
+
+The various control concepts are defined by this module. You can use them with a
+Controller to interact with a session daemon.
+
+This interface is not comprehensive; it currently provides a subset of the
+control functionality that is used by tests.
+"""
+
+
+def _generate_random_string(length: int) -> str:
+    return "".join(
+        random.choice(string.ascii_lowercase + string.digits) for _ in range(length)
+    )
+
+
+class ContextType(abc.ABC):
+    """Base class representing a tracing context field."""
+
+    pass
+
+
+class VpidContextType(ContextType):
+    """Application's virtual process id."""
+
+    pass
+
+
+class VuidContextType(ContextType):
+    """Application's virtual user id."""
+
+    pass
+
+
+class VgidContextType(ContextType):
+    """Application's virtual group id."""
+
+    pass
+
+
+class JavaApplicationContextType(ContextType):
+    """A java application-specific context field is a piece of state which the application provides."""
+
+    def __init__(self, retriever_name: str, field_name: str):
+        self._retriever_name: str = retriever_name
+        self._field_name: str = field_name
+
+    @property
+    def retriever_name(self) -> str:
+        return self._retriever_name
+
+    @property
+    def field_name(self) -> str:
+        return self._field_name
+
+
+class TracingDomain(enum.Enum):
+    """Tracing domain."""
+
+    User = enum.auto(), "User space tracing domain"
+    Kernel = enum.auto(), "Linux kernel tracing domain."
+    Log4j = enum.auto(), "Log4j tracing back-end."
+    JUL = enum.auto(), "Java Util Logging tracing back-end."
+    Python = enum.auto(), "Python logging module tracing back-end."
+
+
+class EventRule(abc.ABC):
+    """Event rule base class, see LTTNG-EVENT-RULE(7)."""
+
+    pass
+
+
+class LogLevelRule:
+    pass
+
+
+class LogLevelRuleAsSevereAs(LogLevelRule):
+    def __init__(self, level: int):
+        self._level = level
+
+    @property
+    def level(self) -> int:
+        return self._level
+
+
+class LogLevelRuleExactly(LogLevelRule):
+    def __init__(self, level: int):
+        self._level = level
+
+    @property
+    def level(self) -> int:
+        return self._level
+
+
+class TracepointEventRule(EventRule):
+    def __init__(
+        self,
+        name_pattern: Optional[str] = None,
+        filter_expression: Optional[str] = None,
+        log_level_rule: Optional[LogLevelRule] = None,
+        name_pattern_exclusions: Optional[List[str]] = None,
+    ):
+        self._name_pattern: Optional[str] = name_pattern
+        self._filter_expression: Optional[str] = filter_expression
+        self._log_level_rule: Optional[LogLevelRule] = log_level_rule
+        self._name_pattern_exclusions: Optional[List[str]] = name_pattern_exclusions
+
+    @property
+    def name_pattern(self) -> Optional[str]:
+        return self._name_pattern
+
+    @property
+    def filter_expression(self) -> Optional[str]:
+        return self._filter_expression
+
+    @property
+    def log_level_rule(self) -> Optional[LogLevelRule]:
+        return self._log_level_rule
+
+    @property
+    def name_pattern_exclusions(self) -> Optional[List[str]]:
+        return self._name_pattern_exclusions
+
+
+class UserTracepointEventRule(TracepointEventRule):
+    def __init__(
+        self,
+        name_pattern: Optional[str] = None,
+        filter_expression: Optional[str] = None,
+        log_level_rule: Optional[LogLevelRule] = None,
+        name_pattern_exclusions: Optional[List[str]] = None,
+    ):
+        TracepointEventRule.__init__(**locals())
+
+
+class KernelTracepointEventRule(TracepointEventRule):
+    def __init__(
+        self,
+        name_pattern: Optional[str] = None,
+        filter_expression: Optional[str] = None,
+        log_level_rule: Optional[LogLevelRule] = None,
+        name_pattern_exclusions: Optional[List[str]] = None,
+    ):
+        TracepointEventRule.__init__(**locals())
+
+
+class Channel(abc.ABC):
+    """
+    A channel is an object which is responsible for a set of ring buffers. It is
+    associated to a domain and
+    """
+
+    @staticmethod
+    def _generate_name() -> str:
+        return "channel_{random_id}".format(random_id=_generate_random_string(8))
+
+    @abc.abstractmethod
+    def add_context(self, context_type: ContextType) -> None:
+        pass
+
+    @property
+    @abc.abstractmethod
+    def domain(self) -> TracingDomain:
+        pass
+
+    @property
+    @abc.abstractmethod
+    def name(self) -> str:
+        pass
+
+    @abc.abstractmethod
+    def add_recording_rule(self, rule: Type[EventRule]) -> None:
+        pass
+
+
+class SessionOutputLocation(abc.ABC):
+    pass
+
+
+class LocalSessionOutputLocation(SessionOutputLocation):
+    def __init__(self, trace_path: pathlib.Path):
+        self._path = trace_path
+
+    @property
+    def path(self) -> pathlib.Path:
+        return self._path
+
+
+class ProcessAttributeTracker(abc.ABC):
+    """
+    Process attribute tracker used to filter before the evaluation of event
+    rules.
+
+    Note that this interface is currently limited as it doesn't allow changing
+    the tracking policy. For instance, it is not possible to set the tracking
+    policy back to "all" once it has transitioned to "include set".
+    """
+
+    class TrackingPolicy(enum.Enum):
+        INCLUDE_ALL = (
+            enum.auto(),
+            """
+            Track all possible process attribute value of a given type (i.e. no filtering).
+            This is the default state of a process attribute tracker.
+            """,
+        )
+        EXCLUDE_ALL = (
+            enum.auto(),
+            "Exclude all possible process attribute values of a given type.",
+        )
+        INCLUDE_SET = enum.auto(), "Track a set of specific process attribute values."
+
+    def __init__(self, policy: TrackingPolicy):
+        self._policy = policy
+
+    @property
+    def tracking_policy(self) -> TrackingPolicy:
+        return self._policy
+
+
+class ProcessIDProcessAttributeTracker(ProcessAttributeTracker):
+    @abc.abstractmethod
+    def track(self, pid: int) -> None:
+        pass
+
+    @abc.abstractmethod
+    def untrack(self, pid: int) -> None:
+        pass
+
+
+class VirtualProcessIDProcessAttributeTracker(ProcessAttributeTracker):
+    @abc.abstractmethod
+    def track(self, vpid: int) -> None:
+        pass
+
+    @abc.abstractmethod
+    def untrack(self, vpid: int) -> None:
+        pass
+
+
+class UserIDProcessAttributeTracker(ProcessAttributeTracker):
+    @abc.abstractmethod
+    def track(self, uid: Union[int, str]) -> None:
+        pass
+
+    @abc.abstractmethod
+    def untrack(self, uid: Union[int, str]) -> None:
+        pass
+
+
+class VirtualUserIDProcessAttributeTracker(ProcessAttributeTracker):
+    @abc.abstractmethod
+    def track(self, vuid: Union[int, str]) -> None:
+        pass
+
+    @abc.abstractmethod
+    def untrack(self, vuid: Union[int, str]) -> None:
+        pass
+
+
+class GroupIDProcessAttributeTracker(ProcessAttributeTracker):
+    @abc.abstractmethod
+    def track(self, gid: Union[int, str]) -> None:
+        pass
+
+    @abc.abstractmethod
+    def untrack(self, gid: Union[int, str]) -> None:
+        pass
+
+
+class VirtualGroupIDProcessAttributeTracker(ProcessAttributeTracker):
+    @abc.abstractmethod
+    def track(self, vgid: Union[int, str]) -> None:
+        pass
+
+    @abc.abstractmethod
+    def untrack(self, vgid: Union[int, str]) -> None:
+        pass
+
+
+class Session(abc.ABC):
+    @staticmethod
+    def _generate_name() -> str:
+        return "session_{random_id}".format(random_id=_generate_random_string(8))
+
+    @property
+    @abc.abstractmethod
+    def name(self) -> str:
+        pass
+
+    @property
+    @abc.abstractmethod
+    def output(self) -> Optional[Type[SessionOutputLocation]]:
+        pass
+
+    @abc.abstractmethod
+    def add_channel(
+        self, domain: TracingDomain, channel_name: Optional[str] = None
+    ) -> Channel:
+        """Add a channel with default attributes to the session."""
+        pass
+
+    @abc.abstractmethod
+    def start(self) -> None:
+        pass
+
+    @abc.abstractmethod
+    def stop(self) -> None:
+        pass
+
+    @abc.abstractmethod
+    def destroy(self) -> None:
+        pass
+
+    @abc.abstractproperty
+    def kernel_pid_process_attribute_tracker(
+        self,
+    ) -> Type[ProcessIDProcessAttributeTracker]:
+        raise NotImplementedError
+
+    @abc.abstractproperty
+    def kernel_vpid_process_attribute_tracker(
+        self,
+    ) -> Type[VirtualProcessIDProcessAttributeTracker]:
+        raise NotImplementedError
+
+    @abc.abstractproperty
+    def user_vpid_process_attribute_tracker(
+        self,
+    ) -> Type[VirtualProcessIDProcessAttributeTracker]:
+        raise NotImplementedError
+
+    @abc.abstractproperty
+    def kernel_gid_process_attribute_tracker(
+        self,
+    ) -> Type[GroupIDProcessAttributeTracker]:
+        raise NotImplementedError
+
+    @abc.abstractproperty
+    def kernel_vgid_process_attribute_tracker(
+        self,
+    ) -> Type[VirtualGroupIDProcessAttributeTracker]:
+        raise NotImplementedError
+
+    @abc.abstractproperty
+    def user_vgid_process_attribute_tracker(
+        self,
+    ) -> Type[VirtualGroupIDProcessAttributeTracker]:
+        raise NotImplementedError
+
+    @abc.abstractproperty
+    def kernel_uid_process_attribute_tracker(
+        self,
+    ) -> Type[UserIDProcessAttributeTracker]:
+        raise NotImplementedError
+
+    @abc.abstractproperty
+    def kernel_vuid_process_attribute_tracker(
+        self,
+    ) -> Type[VirtualUserIDProcessAttributeTracker]:
+        raise NotImplementedError
+
+    @abc.abstractproperty
+    def user_vuid_process_attribute_tracker(
+        self,
+    ) -> Type[VirtualUserIDProcessAttributeTracker]:
+        raise NotImplementedError
+
+
+class ControlException(RuntimeError):
+    """Base type for exceptions thrown by a controller."""
+
+    def __init__(self, msg: str):
+        super().__init__(msg)
+
+
+class Controller(abc.ABC):
+    """
+    Interface of a top-level control interface. A control interface can be, for
+    example, the LTTng client or a wrapper around liblttng-ctl. It is used to
+    create and manage top-level objects of a session daemon instance.
+    """
+
+    @abc.abstractmethod
+    def create_session(
+        self, name: Optional[str] = None, output: Optional[SessionOutputLocation] = None
+    ) -> Session:
+        """
+        Create a session with an output. Don't specify an output
+        to create a session without an output.
+        """
+        pass
This page took 0.025871 seconds and 4 git commands to generate.