Test: client: start, stop, destroy: add tests for --glob/--all
[lttng-tools.git] / tests / utils / lttngtest / lttngctl.py
1 #!/usr/bin/env python3
2 #
3 # Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 #
5 # SPDX-License-Identifier: GPL-2.0-only
6
7 import abc
8 import random
9 import string
10 import pathlib
11 import enum
12 from typing import Optional, Type, Union, List
13
14 """
15 Defines an abstract interface to control LTTng tracing.
16
17 The various control concepts are defined by this module. You can use them with a
18 Controller to interact with a session daemon.
19
20 This interface is not comprehensive; it currently provides a subset of the
21 control functionality that is used by tests.
22 """
23
24
25 def _generate_random_string(length):
26 # type: (int) -> str
27 return "".join(
28 random.choice(string.ascii_lowercase + string.digits) for _ in range(length)
29 )
30
31
32 class ContextType(abc.ABC):
33 """Base class representing a tracing context field."""
34
35 pass
36
37
38 class VpidContextType(ContextType):
39 """Application's virtual process id."""
40
41 pass
42
43
44 class VuidContextType(ContextType):
45 """Application's virtual user id."""
46
47 pass
48
49
50 class VgidContextType(ContextType):
51 """Application's virtual group id."""
52
53 pass
54
55
56 class JavaApplicationContextType(ContextType):
57 """A java application-specific context field is a piece of state which the application provides."""
58
59 def __init__(
60 self,
61 retriever_name, # type: str
62 field_name, # type: str
63 ):
64 self._retriever_name = retriever_name # type: str
65 self._field_name = field_name # type: str
66
67 @property
68 def retriever_name(self):
69 # type: () -> str
70 return self._retriever_name
71
72 @property
73 def field_name(self):
74 # type: () -> str
75 return self._field_name
76
77
78 @enum.unique
79 class TracingDomain(enum.Enum):
80 """Tracing domain."""
81
82 User = "User space tracing domain"
83 Kernel = "Linux kernel tracing domain."
84 Log4j = "Log4j tracing back-end."
85 JUL = "Java Util Logging tracing back-end."
86 Python = "Python logging module tracing back-end."
87
88 def __repr__(self):
89 return "<%s.%s>" % (self.__class__.__name__, self.name)
90
91
92 class EventRule(abc.ABC):
93 """Event rule base class, see LTTNG-EVENT-RULE(7)."""
94
95 pass
96
97
98 class LogLevelRule:
99 pass
100
101
102 class LogLevelRuleAsSevereAs(LogLevelRule):
103 def __init__(self, level):
104 # type: (int)
105 self._level = level
106
107 @property
108 def level(self):
109 # type: () -> int
110 return self._level
111
112
113 class LogLevelRuleExactly(LogLevelRule):
114 def __init__(self, level):
115 # type: (int)
116 self._level = level
117
118 @property
119 def level(self):
120 # type: () -> int
121 return self._level
122
123
124 class TracepointEventRule(EventRule):
125 def __init__(
126 self,
127 name_pattern=None, # type: Optional[str]
128 filter_expression=None, # type: Optional[str]
129 log_level_rule=None, # type: Optional[LogLevelRule]
130 name_pattern_exclusions=None, # type: Optional[List[str]]
131 ):
132 self._name_pattern = name_pattern # type: Optional[str]
133 self._filter_expression = filter_expression # type: Optional[str]
134 self._log_level_rule = log_level_rule # type: Optional[LogLevelRule]
135 self._name_pattern_exclusions = (
136 name_pattern_exclusions
137 ) # type: Optional[List[str]]
138
139 @property
140 def name_pattern(self):
141 # type: () -> Optional[str]
142 return self._name_pattern
143
144 @property
145 def filter_expression(self):
146 # type: () -> Optional[str]
147 return self._filter_expression
148
149 @property
150 def log_level_rule(self):
151 # type: () -> Optional[LogLevelRule]
152 return self._log_level_rule
153
154 @property
155 def name_pattern_exclusions(self):
156 # type: () -> Optional[List[str]]
157 return self._name_pattern_exclusions
158
159
160 class UserTracepointEventRule(TracepointEventRule):
161 def __init__(
162 self,
163 name_pattern=None, # type: Optional[str]
164 filter_expression=None, # type: Optional[str]
165 log_level_rule=None, # type: Optional[LogLevelRule]
166 name_pattern_exclusions=None, # type: Optional[List[str]]
167 ):
168 TracepointEventRule.__init__(**locals())
169
170
171 class KernelTracepointEventRule(TracepointEventRule):
172 def __init__(
173 self,
174 name_pattern=None, # type: Optional[str]
175 filter_expression=None, # type: Optional[str]
176 log_level_rule=None, # type: Optional[LogLevelRule]
177 name_pattern_exclusions=None, # type: Optional[List[str]]
178 ):
179 TracepointEventRule.__init__(**locals())
180
181
182 class Channel(abc.ABC):
183 """
184 A channel is an object which is responsible for a set of ring buffers. It is
185 associated to a domain and
186 """
187
188 @staticmethod
189 def _generate_name():
190 # type: () -> str
191 return "channel_{random_id}".format(random_id=_generate_random_string(8))
192
193 @abc.abstractmethod
194 def add_context(self, context_type):
195 # type: (ContextType) -> None
196 pass
197
198 @property
199 @abc.abstractmethod
200 def domain(self):
201 # type: () -> TracingDomain
202 pass
203
204 @property
205 @abc.abstractmethod
206 def name(self):
207 # type: () -> str
208 pass
209
210 @abc.abstractmethod
211 def add_recording_rule(self, rule) -> None:
212 # type: (Type[EventRule]) -> None
213 pass
214
215
216 class SessionOutputLocation(abc.ABC):
217 pass
218
219
220 class LocalSessionOutputLocation(SessionOutputLocation):
221 def __init__(self, trace_path):
222 # type: (pathlib.Path)
223 self._path = trace_path
224
225 @property
226 def path(self):
227 # type: () -> pathlib.Path
228 return self._path
229
230
231 class ProcessAttributeTracker(abc.ABC):
232 """
233 Process attribute tracker used to filter before the evaluation of event
234 rules.
235
236 Note that this interface is currently limited as it doesn't allow changing
237 the tracking policy. For instance, it is not possible to set the tracking
238 policy back to "all" once it has transitioned to "include set".
239 """
240
241 @enum.unique
242 class TrackingPolicy(enum.Enum):
243 INCLUDE_ALL = """
244 Track all possible process attribute value of a given type (i.e. no filtering).
245 This is the default state of a process attribute tracker.
246 """
247 EXCLUDE_ALL = "Exclude all possible process attribute values of a given type."
248 INCLUDE_SET = "Track a set of specific process attribute values."
249
250 def __repr__(self):
251 return "<%s.%s>" % (self.__class__.__name__, self.name)
252
253 def __init__(self, policy):
254 # type: (TrackingPolicy)
255 self._policy = policy
256
257 @property
258 def tracking_policy(self):
259 # type: () -> TrackingPolicy
260 return self._policy
261
262
263 class ProcessIDProcessAttributeTracker(ProcessAttributeTracker):
264 @abc.abstractmethod
265 def track(self, pid):
266 # type: (int) -> None
267 pass
268
269 @abc.abstractmethod
270 def untrack(self, pid):
271 # type: (int) -> None
272 pass
273
274
275 class VirtualProcessIDProcessAttributeTracker(ProcessAttributeTracker):
276 @abc.abstractmethod
277 def track(self, vpid):
278 # type: (int) -> None
279 pass
280
281 @abc.abstractmethod
282 def untrack(self, vpid):
283 # type: (int) -> None
284 pass
285
286
287 class UserIDProcessAttributeTracker(ProcessAttributeTracker):
288 @abc.abstractmethod
289 def track(self, uid):
290 # type: (Union[int, str]) -> None
291 pass
292
293 @abc.abstractmethod
294 def untrack(self, uid):
295 # type: (Union[int, str]) -> None
296 pass
297
298
299 class VirtualUserIDProcessAttributeTracker(ProcessAttributeTracker):
300 @abc.abstractmethod
301 def track(self, vuid):
302 # type: (Union[int, str]) -> None
303 pass
304
305 @abc.abstractmethod
306 def untrack(self, vuid):
307 # type: (Union[int, str]) -> None
308 pass
309
310
311 class GroupIDProcessAttributeTracker(ProcessAttributeTracker):
312 @abc.abstractmethod
313 def track(self, gid):
314 # type: (Union[int, str]) -> None
315 pass
316
317 @abc.abstractmethod
318 def untrack(self, gid):
319 # type: (Union[int, str]) -> None
320 pass
321
322
323 class VirtualGroupIDProcessAttributeTracker(ProcessAttributeTracker):
324 @abc.abstractmethod
325 def track(self, vgid):
326 # type: (Union[int, str]) -> None
327 pass
328
329 @abc.abstractmethod
330 def untrack(self, vgid):
331 # type: (Union[int, str]) -> None
332 pass
333
334
335 class Session(abc.ABC):
336 @staticmethod
337 def _generate_name():
338 # type: () -> str
339 return "session_{random_id}".format(random_id=_generate_random_string(8))
340
341 @property
342 @abc.abstractmethod
343 def name(self):
344 # type: () -> str
345 pass
346
347 @property
348 @abc.abstractmethod
349 def output(self):
350 # type: () -> Optional[Type[SessionOutputLocation]]
351 pass
352
353 @abc.abstractmethod
354 def add_channel(self, domain, channel_name=None):
355 # type: (TracingDomain, Optional[str]) -> Channel
356 """Add a channel with default attributes to the session."""
357 pass
358
359 @abc.abstractmethod
360 def start(self):
361 # type: () -> None
362 pass
363
364 @abc.abstractmethod
365 def stop(self):
366 # type: () -> None
367 pass
368
369 @abc.abstractmethod
370 def destroy(self):
371 # type: () -> None
372 pass
373
374 @abc.abstractmethod
375 def is_active(self):
376 # type: () -> bool
377 pass
378
379 @abc.abstractproperty
380 def kernel_pid_process_attribute_tracker(self):
381 # type: () -> Type[ProcessIDProcessAttributeTracker]
382 raise NotImplementedError
383
384 @abc.abstractproperty
385 def kernel_vpid_process_attribute_tracker(self):
386 # type: () -> Type[VirtualProcessIDProcessAttributeTracker]
387 raise NotImplementedError
388
389 @abc.abstractproperty
390 def user_vpid_process_attribute_tracker(
391 self,
392 ) -> Type[VirtualProcessIDProcessAttributeTracker]:
393 # type: () -> Type[VirtualProcessIDProcessAttributeTracker]
394 raise NotImplementedError
395
396 @abc.abstractproperty
397 def kernel_gid_process_attribute_tracker(self):
398 # type: () -> Type[GroupIDProcessAttributeTracker]
399 raise NotImplementedError
400
401 @abc.abstractproperty
402 def kernel_vgid_process_attribute_tracker(self):
403 # type: () -> Type[VirtualGroupIDProcessAttributeTracker]
404 raise NotImplementedError
405
406 @abc.abstractproperty
407 def user_vgid_process_attribute_tracker(self):
408 # type: () -> Type[VirtualGroupIDProcessAttributeTracker]
409 raise NotImplementedError
410
411 @abc.abstractproperty
412 def kernel_uid_process_attribute_tracker(self):
413 # type: () -> Type[UserIDProcessAttributeTracker]
414 raise NotImplementedError
415
416 @abc.abstractproperty
417 def kernel_vuid_process_attribute_tracker(self):
418 # type: () -> Type[VirtualUserIDProcessAttributeTracker]
419 raise NotImplementedError
420
421 @abc.abstractproperty
422 def user_vuid_process_attribute_tracker(self):
423 # type: () -> Type[VirtualUserIDProcessAttributeTracker]
424 raise NotImplementedError
425
426
427 class ControlException(RuntimeError):
428 """Base type for exceptions thrown by a controller."""
429
430 def __init__(self, msg):
431 # type: (str)
432 super().__init__(msg)
433
434
435 class Controller(abc.ABC):
436 """
437 Interface of a top-level control interface. A control interface can be, for
438 example, the LTTng client or a wrapper around liblttng-ctl. It is used to
439 create and manage top-level objects of a session daemon instance.
440 """
441
442 @abc.abstractmethod
443 def create_session(self, name=None, output=None):
444 # type: (Optional[str], Optional[SessionOutputLocation]) -> Session
445 """
446 Create a session with an output. Don't specify an output
447 to create a session without an output.
448 """
449 pass
450
451 @abc.abstractmethod
452 def start_session_by_name(self, name):
453 # type: (str) -> None
454 """
455 Start a session by name.
456 """
457 pass
458
459 @abc.abstractmethod
460 def start_session_by_glob_pattern(self, pattern):
461 # type: (str) -> None
462 """
463 Start sessions whose name matches `pattern`, see GLOB(7).
464 """
465 pass
466
467 @abc.abstractmethod
468 def start_sessions_all(self):
469 """
470 Start all sessions visible to the current user.
471 """
472 # type: () -> None
473 pass
474
475 @abc.abstractmethod
476 def stop_session_by_name(self, name):
477 # type: (str) -> None
478 """
479 Stop a session by name.
480 """
481 pass
482
483 @abc.abstractmethod
484 def stop_session_by_glob_pattern(self, pattern):
485 # type: (str) -> None
486 """
487 Stop sessions whose name matches `pattern`, see GLOB(7).
488 """
489 pass
490
491 @abc.abstractmethod
492 def stop_sessions_all(self):
493 """
494 Stop all sessions visible to the current user.
495 """
496 # type: () -> None
497 pass
498
499 @abc.abstractmethod
500 def destroy_session_by_name(self, name):
501 # type: (str) -> None
502 """
503 Destroy a session by name.
504 """
505 pass
506
507 @abc.abstractmethod
508 def destroy_session_by_glob_pattern(self, pattern):
509 # type: (str) -> None
510 """
511 Destroy sessions whose name matches `pattern`, see GLOB(7).
512 """
513 pass
514
515 @abc.abstractmethod
516 def destroy_sessions_all(self):
517 # type: () -> None
518 """
519 Destroy all sessions visible to the current user.
520 """
521 pass
522
523 @abc.abstractmethod
524 def list_sessions(self):
525 # type: () -> List[Session]
526 """
527 List all sessions visible to the current user.
528 """
529 pass
This page took 0.04098 seconds and 4 git commands to generate.