Commit | Line | Data |
---|---|---|
ef945e4d JG |
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 | ||
ce8470c9 MJ |
25 | def _generate_random_string(length): |
26 | # type: (int) -> str | |
ef945e4d JG |
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 | ||
ce8470c9 MJ |
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 | |
ef945e4d JG |
66 | |
67 | @property | |
ce8470c9 MJ |
68 | def retriever_name(self): |
69 | # type: () -> str | |
ef945e4d JG |
70 | return self._retriever_name |
71 | ||
72 | @property | |
ce8470c9 MJ |
73 | def field_name(self): |
74 | # type: () -> str | |
ef945e4d JG |
75 | return self._field_name |
76 | ||
77 | ||
544d8425 | 78 | @enum.unique |
ef945e4d JG |
79 | class TracingDomain(enum.Enum): |
80 | """Tracing domain.""" | |
81 | ||
544d8425 MJ |
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) | |
ef945e4d JG |
90 | |
91 | ||
a631186c JG |
92 | @enum.unique |
93 | class BufferSharingPolicy(enum.Enum): | |
94 | """Buffer sharing policy.""" | |
95 | ||
96 | PerUID = "Per-UID buffering" | |
97 | PerPID = "Per-PID buffering" | |
98 | ||
99 | def __repr__(self): | |
100 | return "<%s.%s>" % (self.__class__.__name__, self.name) | |
101 | ||
102 | ||
ef945e4d JG |
103 | class EventRule(abc.ABC): |
104 | """Event rule base class, see LTTNG-EVENT-RULE(7).""" | |
105 | ||
106 | pass | |
107 | ||
108 | ||
109 | class LogLevelRule: | |
03f7bb03 JG |
110 | def __eq__(self, other): |
111 | # type (LogLevelRule) -> bool | |
112 | if type(self) != type(other): | |
113 | return False | |
114 | ||
115 | return self.level == other.level | |
116 | ||
117 | ||
118 | @enum.unique | |
119 | class LogLevel(enum.Enum): | |
ef945e4d JG |
120 | pass |
121 | ||
122 | ||
03f7bb03 JG |
123 | @enum.unique |
124 | class UserLogLevel(LogLevel): | |
125 | EMERGENCY = 0 | |
126 | ALERT = 1 | |
127 | CRITICAL = 2 | |
128 | ERROR = 3 | |
129 | WARNING = 4 | |
130 | NOTICE = 5 | |
131 | INFO = 6 | |
132 | DEBUG_SYSTEM = 7 | |
133 | DEBUG_PROGRAM = 8 | |
134 | DEBUG_PROCESS = 9 | |
135 | DEBUG_MODULE = 10 | |
136 | DEBUG_UNIT = 11 | |
137 | DEBUG_FUNCTION = 12 | |
138 | DEBUG_LINE = 13 | |
139 | DEBUG = 14 | |
140 | ||
141 | ||
142 | @enum.unique | |
143 | class JULLogLevel(LogLevel): | |
144 | OFF = 2147483647 | |
145 | SEVERE = 1000 | |
146 | WARNING = 900 | |
147 | INFO = 800 | |
148 | CONFIG = 700 | |
149 | FINE = 500 | |
150 | FINER = 400 | |
151 | FINEST = 300 | |
152 | ALL = -2147483648 | |
153 | ||
154 | ||
155 | @enum.unique | |
156 | class Log4jLogLevel(LogLevel): | |
157 | OFF = 2147483647 | |
158 | FATAL = 50000 | |
159 | ERROR = 40000 | |
160 | WARN = 30000 | |
161 | INFO = 20000 | |
162 | DEBUG = 10000 | |
163 | TRACE = 5000 | |
164 | ALL = -2147483648 | |
165 | ||
166 | ||
167 | @enum.unique | |
168 | class PythonLogLevel(LogLevel): | |
169 | CRITICAL = 50 | |
170 | ERROR = 40 | |
171 | WARNING = 30 | |
172 | INFO = 20 | |
173 | DEBUG = 10 | |
174 | NOTSET = 0 | |
175 | ||
176 | ||
ef945e4d | 177 | class LogLevelRuleAsSevereAs(LogLevelRule): |
ce8470c9 | 178 | def __init__(self, level): |
03f7bb03 | 179 | # type: (LogLevel) |
ef945e4d JG |
180 | self._level = level |
181 | ||
182 | @property | |
ce8470c9 | 183 | def level(self): |
03f7bb03 | 184 | # type: () -> LogLevel |
ef945e4d JG |
185 | return self._level |
186 | ||
187 | ||
188 | class LogLevelRuleExactly(LogLevelRule): | |
ce8470c9 | 189 | def __init__(self, level): |
03f7bb03 | 190 | # type: (LogLevel) |
ef945e4d JG |
191 | self._level = level |
192 | ||
193 | @property | |
ce8470c9 | 194 | def level(self): |
03f7bb03 | 195 | # type: () -> LogLevel |
ef945e4d JG |
196 | return self._level |
197 | ||
198 | ||
199 | class TracepointEventRule(EventRule): | |
200 | def __init__( | |
201 | self, | |
ce8470c9 MJ |
202 | name_pattern=None, # type: Optional[str] |
203 | filter_expression=None, # type: Optional[str] | |
ef945e4d | 204 | ): |
ce8470c9 MJ |
205 | self._name_pattern = name_pattern # type: Optional[str] |
206 | self._filter_expression = filter_expression # type: Optional[str] | |
03f7bb03 JG |
207 | |
208 | def _equals(self, other): | |
209 | # type (TracepointEventRule) -> bool | |
210 | # Overridden by derived classes that have supplementary attributes. | |
211 | return True | |
212 | ||
213 | def __eq__(self, other): | |
214 | # type (TracepointEventRule) -> bool | |
215 | if type(self) != type(other): | |
216 | return False | |
217 | ||
218 | if self.name_pattern != other.name_pattern: | |
219 | return False | |
220 | ||
221 | if self.filter_expression != other.filter_expression: | |
222 | return False | |
223 | ||
224 | return self._equals(other) | |
ef945e4d JG |
225 | |
226 | @property | |
ce8470c9 MJ |
227 | def name_pattern(self): |
228 | # type: () -> Optional[str] | |
ef945e4d JG |
229 | return self._name_pattern |
230 | ||
231 | @property | |
ce8470c9 MJ |
232 | def filter_expression(self): |
233 | # type: () -> Optional[str] | |
ef945e4d JG |
234 | return self._filter_expression |
235 | ||
03f7bb03 JG |
236 | |
237 | class UserTracepointEventRule(TracepointEventRule): | |
238 | def __init__( | |
239 | self, | |
240 | name_pattern=None, # type: Optional[str] | |
241 | filter_expression=None, # type: Optional[str] | |
242 | log_level_rule=None, # type: Optional[LogLevelRule] | |
243 | name_pattern_exclusions=None, # type: Optional[List[str]] | |
244 | ): | |
245 | TracepointEventRule.__init__(self, name_pattern, filter_expression) | |
246 | self._log_level_rule = log_level_rule # type: Optional[LogLevelRule] | |
247 | self._name_pattern_exclusions = ( | |
248 | name_pattern_exclusions | |
249 | ) # type: Optional[List[str]] | |
250 | ||
251 | if log_level_rule and not isinstance(log_level_rule.level, UserLogLevel): | |
252 | raise ValueError("Log level rule must use a UserLogLevel as its value") | |
253 | ||
254 | def _equals(self, other): | |
255 | # type (UserTracepointEventRule) -> bool | |
256 | return ( | |
257 | self.log_level_rule == other.log_level_rule | |
258 | and self.name_pattern_exclusions == other.name_pattern_exclusions | |
259 | ) | |
260 | ||
ef945e4d | 261 | @property |
ce8470c9 MJ |
262 | def log_level_rule(self): |
263 | # type: () -> Optional[LogLevelRule] | |
ef945e4d JG |
264 | return self._log_level_rule |
265 | ||
266 | @property | |
ce8470c9 MJ |
267 | def name_pattern_exclusions(self): |
268 | # type: () -> Optional[List[str]] | |
ef945e4d JG |
269 | return self._name_pattern_exclusions |
270 | ||
271 | ||
03f7bb03 | 272 | class Log4jTracepointEventRule(TracepointEventRule): |
ef945e4d JG |
273 | def __init__( |
274 | self, | |
ce8470c9 MJ |
275 | name_pattern=None, # type: Optional[str] |
276 | filter_expression=None, # type: Optional[str] | |
277 | log_level_rule=None, # type: Optional[LogLevelRule] | |
278 | name_pattern_exclusions=None, # type: Optional[List[str]] | |
ef945e4d | 279 | ): |
03f7bb03 JG |
280 | TracepointEventRule.__init__(self, name_pattern, filter_expression) |
281 | self._log_level_rule = log_level_rule # type: Optional[LogLevelRule] | |
282 | self._name_pattern_exclusions = ( | |
283 | name_pattern_exclusions | |
284 | ) # type: Optional[List[str]] | |
ef945e4d | 285 | |
03f7bb03 JG |
286 | if log_level_rule and not isinstance(log_level_rule.level, Log4jLogLevel): |
287 | raise ValueError("Log level rule must use a Log4jLogLevel as its value") | |
ef945e4d | 288 | |
03f7bb03 JG |
289 | def _equals(self, other): |
290 | # type (Log4jTracepointEventRule) -> bool | |
291 | return ( | |
292 | self.log_level_rule == other.log_level_rule | |
293 | and self.name_pattern_exclusions == other.name_pattern_exclusions | |
294 | ) | |
295 | ||
296 | @property | |
297 | def log_level_rule(self): | |
298 | # type: () -> Optional[LogLevelRule] | |
299 | return self._log_level_rule | |
300 | ||
301 | @property | |
302 | def name_pattern_exclusions(self): | |
303 | # type: () -> Optional[List[str]] | |
304 | return self._name_pattern_exclusions | |
305 | ||
306 | ||
307 | class JULTracepointEventRule(TracepointEventRule): | |
ef945e4d JG |
308 | def __init__( |
309 | self, | |
ce8470c9 MJ |
310 | name_pattern=None, # type: Optional[str] |
311 | filter_expression=None, # type: Optional[str] | |
312 | log_level_rule=None, # type: Optional[LogLevelRule] | |
313 | name_pattern_exclusions=None, # type: Optional[List[str]] | |
03f7bb03 JG |
314 | ): |
315 | TracepointEventRule.__init__(self, name_pattern, filter_expression) | |
316 | self._log_level_rule = log_level_rule # type: Optional[LogLevelRule] | |
317 | self._name_pattern_exclusions = ( | |
318 | name_pattern_exclusions | |
319 | ) # type: Optional[List[str]] | |
320 | ||
321 | if log_level_rule and not isinstance(log_level_rule.level, JULLogLevel): | |
322 | raise ValueError("Log level rule must use a JULLogLevel as its value") | |
323 | ||
324 | def _equals(self, other): | |
325 | # type (JULTracepointEventRule) -> bool | |
326 | return ( | |
327 | self.log_level_rule == other.log_level_rule | |
328 | and self.name_pattern_exclusions == other.name_pattern_exclusions | |
329 | ) | |
330 | ||
331 | @property | |
332 | def log_level_rule(self): | |
333 | # type: () -> Optional[LogLevelRule] | |
334 | return self._log_level_rule | |
335 | ||
336 | @property | |
337 | def name_pattern_exclusions(self): | |
338 | # type: () -> Optional[List[str]] | |
339 | return self._name_pattern_exclusions | |
340 | ||
341 | ||
342 | class PythonTracepointEventRule(TracepointEventRule): | |
343 | def __init__( | |
344 | self, | |
345 | name_pattern=None, # type: Optional[str] | |
346 | filter_expression=None, # type: Optional[str] | |
347 | log_level_rule=None, # type: Optional[LogLevelRule] | |
348 | name_pattern_exclusions=None, # type: Optional[List[str]] | |
349 | ): | |
350 | TracepointEventRule.__init__(self, name_pattern, filter_expression) | |
351 | self._log_level_rule = log_level_rule # type: Optional[LogLevelRule] | |
352 | self._name_pattern_exclusions = ( | |
353 | name_pattern_exclusions | |
354 | ) # type: Optional[List[str]] | |
355 | ||
356 | if log_level_rule and not isinstance(log_level_rule.level, PythonLogLevel): | |
357 | raise ValueError("Log level rule must use a PythonLogLevel as its value") | |
358 | ||
359 | def _equals(self, other): | |
360 | # type (PythonTracepointEventRule) -> bool | |
361 | return ( | |
362 | self.log_level_rule == other.log_level_rule | |
363 | and self.name_pattern_exclusions == other.name_pattern_exclusions | |
364 | ) | |
365 | ||
366 | @property | |
367 | def log_level_rule(self): | |
368 | # type: () -> Optional[LogLevelRule] | |
369 | return self._log_level_rule | |
370 | ||
371 | @property | |
372 | def name_pattern_exclusions(self): | |
373 | # type: () -> Optional[List[str]] | |
374 | return self._name_pattern_exclusions | |
375 | ||
376 | ||
377 | class KernelTracepointEventRule(TracepointEventRule): | |
378 | def __init__( | |
379 | self, | |
380 | name_pattern=None, # type: Optional[str] | |
381 | filter_expression=None, # type: Optional[str] | |
ef945e4d JG |
382 | ): |
383 | TracepointEventRule.__init__(**locals()) | |
384 | ||
385 | ||
386 | class Channel(abc.ABC): | |
387 | """ | |
388 | A channel is an object which is responsible for a set of ring buffers. It is | |
389 | associated to a domain and | |
390 | """ | |
391 | ||
392 | @staticmethod | |
ce8470c9 MJ |
393 | def _generate_name(): |
394 | # type: () -> str | |
ef945e4d JG |
395 | return "channel_{random_id}".format(random_id=_generate_random_string(8)) |
396 | ||
397 | @abc.abstractmethod | |
ce8470c9 MJ |
398 | def add_context(self, context_type): |
399 | # type: (ContextType) -> None | |
fe3442d8 | 400 | raise NotImplementedError |
ef945e4d JG |
401 | |
402 | @property | |
403 | @abc.abstractmethod | |
ce8470c9 MJ |
404 | def domain(self): |
405 | # type: () -> TracingDomain | |
fe3442d8 | 406 | raise NotImplementedError |
ef945e4d JG |
407 | |
408 | @property | |
409 | @abc.abstractmethod | |
ce8470c9 MJ |
410 | def name(self): |
411 | # type: () -> str | |
fe3442d8 | 412 | raise NotImplementedError |
ef945e4d JG |
413 | |
414 | @abc.abstractmethod | |
ce8470c9 MJ |
415 | def add_recording_rule(self, rule) -> None: |
416 | # type: (Type[EventRule]) -> None | |
fe3442d8 | 417 | raise NotImplementedError |
ef945e4d JG |
418 | |
419 | ||
420 | class SessionOutputLocation(abc.ABC): | |
421 | pass | |
422 | ||
423 | ||
424 | class LocalSessionOutputLocation(SessionOutputLocation): | |
ce8470c9 MJ |
425 | def __init__(self, trace_path): |
426 | # type: (pathlib.Path) | |
ef945e4d JG |
427 | self._path = trace_path |
428 | ||
429 | @property | |
ce8470c9 MJ |
430 | def path(self): |
431 | # type: () -> pathlib.Path | |
ef945e4d JG |
432 | return self._path |
433 | ||
434 | ||
435 | class ProcessAttributeTracker(abc.ABC): | |
436 | """ | |
437 | Process attribute tracker used to filter before the evaluation of event | |
438 | rules. | |
439 | ||
440 | Note that this interface is currently limited as it doesn't allow changing | |
441 | the tracking policy. For instance, it is not possible to set the tracking | |
442 | policy back to "all" once it has transitioned to "include set". | |
443 | """ | |
444 | ||
544d8425 | 445 | @enum.unique |
ef945e4d | 446 | class TrackingPolicy(enum.Enum): |
544d8425 | 447 | INCLUDE_ALL = """ |
ef945e4d JG |
448 | Track all possible process attribute value of a given type (i.e. no filtering). |
449 | This is the default state of a process attribute tracker. | |
544d8425 MJ |
450 | """ |
451 | EXCLUDE_ALL = "Exclude all possible process attribute values of a given type." | |
452 | INCLUDE_SET = "Track a set of specific process attribute values." | |
453 | ||
454 | def __repr__(self): | |
455 | return "<%s.%s>" % (self.__class__.__name__, self.name) | |
ef945e4d | 456 | |
ce8470c9 MJ |
457 | def __init__(self, policy): |
458 | # type: (TrackingPolicy) | |
ef945e4d JG |
459 | self._policy = policy |
460 | ||
461 | @property | |
ce8470c9 MJ |
462 | def tracking_policy(self): |
463 | # type: () -> TrackingPolicy | |
ef945e4d JG |
464 | return self._policy |
465 | ||
466 | ||
467 | class ProcessIDProcessAttributeTracker(ProcessAttributeTracker): | |
468 | @abc.abstractmethod | |
ce8470c9 MJ |
469 | def track(self, pid): |
470 | # type: (int) -> None | |
fe3442d8 | 471 | raise NotImplementedError |
ef945e4d JG |
472 | |
473 | @abc.abstractmethod | |
ce8470c9 MJ |
474 | def untrack(self, pid): |
475 | # type: (int) -> None | |
fe3442d8 | 476 | raise NotImplementedError |
ef945e4d JG |
477 | |
478 | ||
479 | class VirtualProcessIDProcessAttributeTracker(ProcessAttributeTracker): | |
480 | @abc.abstractmethod | |
ce8470c9 MJ |
481 | def track(self, vpid): |
482 | # type: (int) -> None | |
fe3442d8 | 483 | raise NotImplementedError |
ef945e4d JG |
484 | |
485 | @abc.abstractmethod | |
ce8470c9 MJ |
486 | def untrack(self, vpid): |
487 | # type: (int) -> None | |
fe3442d8 | 488 | raise NotImplementedError |
ef945e4d JG |
489 | |
490 | ||
491 | class UserIDProcessAttributeTracker(ProcessAttributeTracker): | |
492 | @abc.abstractmethod | |
ce8470c9 MJ |
493 | def track(self, uid): |
494 | # type: (Union[int, str]) -> None | |
fe3442d8 | 495 | raise NotImplementedError |
ef945e4d JG |
496 | |
497 | @abc.abstractmethod | |
ce8470c9 MJ |
498 | def untrack(self, uid): |
499 | # type: (Union[int, str]) -> None | |
fe3442d8 | 500 | raise NotImplementedError |
ef945e4d JG |
501 | |
502 | ||
503 | class VirtualUserIDProcessAttributeTracker(ProcessAttributeTracker): | |
504 | @abc.abstractmethod | |
ce8470c9 MJ |
505 | def track(self, vuid): |
506 | # type: (Union[int, str]) -> None | |
fe3442d8 | 507 | raise NotImplementedError |
ef945e4d JG |
508 | |
509 | @abc.abstractmethod | |
ce8470c9 MJ |
510 | def untrack(self, vuid): |
511 | # type: (Union[int, str]) -> None | |
fe3442d8 | 512 | raise NotImplementedError |
ef945e4d JG |
513 | |
514 | ||
515 | class GroupIDProcessAttributeTracker(ProcessAttributeTracker): | |
516 | @abc.abstractmethod | |
ce8470c9 MJ |
517 | def track(self, gid): |
518 | # type: (Union[int, str]) -> None | |
fe3442d8 | 519 | raise NotImplementedError |
ef945e4d JG |
520 | |
521 | @abc.abstractmethod | |
ce8470c9 MJ |
522 | def untrack(self, gid): |
523 | # type: (Union[int, str]) -> None | |
fe3442d8 | 524 | raise NotImplementedError |
ef945e4d JG |
525 | |
526 | ||
527 | class VirtualGroupIDProcessAttributeTracker(ProcessAttributeTracker): | |
528 | @abc.abstractmethod | |
ce8470c9 MJ |
529 | def track(self, vgid): |
530 | # type: (Union[int, str]) -> None | |
fe3442d8 | 531 | raise NotImplementedError |
ef945e4d JG |
532 | |
533 | @abc.abstractmethod | |
ce8470c9 MJ |
534 | def untrack(self, vgid): |
535 | # type: (Union[int, str]) -> None | |
fe3442d8 | 536 | raise NotImplementedError |
ef945e4d JG |
537 | |
538 | ||
539 | class Session(abc.ABC): | |
540 | @staticmethod | |
ce8470c9 MJ |
541 | def _generate_name(): |
542 | # type: () -> str | |
ef945e4d JG |
543 | return "session_{random_id}".format(random_id=_generate_random_string(8)) |
544 | ||
545 | @property | |
546 | @abc.abstractmethod | |
ce8470c9 MJ |
547 | def name(self): |
548 | # type: () -> str | |
fe3442d8 | 549 | raise NotImplementedError |
ef945e4d JG |
550 | |
551 | @property | |
552 | @abc.abstractmethod | |
ce8470c9 MJ |
553 | def output(self): |
554 | # type: () -> Optional[Type[SessionOutputLocation]] | |
fe3442d8 | 555 | raise NotImplementedError |
ef945e4d JG |
556 | |
557 | @abc.abstractmethod | |
a631186c JG |
558 | def add_channel( |
559 | self, | |
560 | domain, | |
561 | channel_name=None, | |
562 | buffer_sharing_policy=BufferSharingPolicy.PerUID, | |
563 | ): | |
564 | # type: (TracingDomain, Optional[str], BufferSharingPolicy) -> Channel | |
ef945e4d | 565 | """Add a channel with default attributes to the session.""" |
fe3442d8 | 566 | raise NotImplementedError |
ef945e4d JG |
567 | |
568 | @abc.abstractmethod | |
ce8470c9 MJ |
569 | def start(self): |
570 | # type: () -> None | |
fe3442d8 | 571 | raise NotImplementedError |
ef945e4d JG |
572 | |
573 | @abc.abstractmethod | |
ce8470c9 MJ |
574 | def stop(self): |
575 | # type: () -> None | |
fe3442d8 | 576 | raise NotImplementedError |
ef945e4d JG |
577 | |
578 | @abc.abstractmethod | |
ce8470c9 MJ |
579 | def destroy(self): |
580 | # type: () -> None | |
fe3442d8 | 581 | raise NotImplementedError |
ef945e4d | 582 | |
b9780062 JG |
583 | @abc.abstractmethod |
584 | def is_active(self): | |
585 | # type: () -> bool | |
fe3442d8 | 586 | raise NotImplementedError |
b9780062 | 587 | |
a8cac44b JG |
588 | @abc.abstractmethod |
589 | def rotate(self): | |
590 | # type: () -> None | |
591 | raise NotImplementedError | |
592 | ||
ef945e4d | 593 | @abc.abstractproperty |
ce8470c9 MJ |
594 | def kernel_pid_process_attribute_tracker(self): |
595 | # type: () -> Type[ProcessIDProcessAttributeTracker] | |
ef945e4d JG |
596 | raise NotImplementedError |
597 | ||
598 | @abc.abstractproperty | |
ce8470c9 MJ |
599 | def kernel_vpid_process_attribute_tracker(self): |
600 | # type: () -> Type[VirtualProcessIDProcessAttributeTracker] | |
ef945e4d JG |
601 | raise NotImplementedError |
602 | ||
603 | @abc.abstractproperty | |
604 | def user_vpid_process_attribute_tracker( | |
605 | self, | |
606 | ) -> Type[VirtualProcessIDProcessAttributeTracker]: | |
ce8470c9 | 607 | # type: () -> Type[VirtualProcessIDProcessAttributeTracker] |
ef945e4d JG |
608 | raise NotImplementedError |
609 | ||
610 | @abc.abstractproperty | |
ce8470c9 MJ |
611 | def kernel_gid_process_attribute_tracker(self): |
612 | # type: () -> Type[GroupIDProcessAttributeTracker] | |
ef945e4d JG |
613 | raise NotImplementedError |
614 | ||
615 | @abc.abstractproperty | |
ce8470c9 MJ |
616 | def kernel_vgid_process_attribute_tracker(self): |
617 | # type: () -> Type[VirtualGroupIDProcessAttributeTracker] | |
ef945e4d JG |
618 | raise NotImplementedError |
619 | ||
620 | @abc.abstractproperty | |
ce8470c9 MJ |
621 | def user_vgid_process_attribute_tracker(self): |
622 | # type: () -> Type[VirtualGroupIDProcessAttributeTracker] | |
ef945e4d JG |
623 | raise NotImplementedError |
624 | ||
625 | @abc.abstractproperty | |
ce8470c9 MJ |
626 | def kernel_uid_process_attribute_tracker(self): |
627 | # type: () -> Type[UserIDProcessAttributeTracker] | |
ef945e4d JG |
628 | raise NotImplementedError |
629 | ||
630 | @abc.abstractproperty | |
ce8470c9 MJ |
631 | def kernel_vuid_process_attribute_tracker(self): |
632 | # type: () -> Type[VirtualUserIDProcessAttributeTracker] | |
ef945e4d JG |
633 | raise NotImplementedError |
634 | ||
635 | @abc.abstractproperty | |
ce8470c9 MJ |
636 | def user_vuid_process_attribute_tracker(self): |
637 | # type: () -> Type[VirtualUserIDProcessAttributeTracker] | |
ef945e4d JG |
638 | raise NotImplementedError |
639 | ||
640 | ||
641 | class ControlException(RuntimeError): | |
642 | """Base type for exceptions thrown by a controller.""" | |
643 | ||
ce8470c9 MJ |
644 | def __init__(self, msg): |
645 | # type: (str) | |
ef945e4d JG |
646 | super().__init__(msg) |
647 | ||
648 | ||
649 | class Controller(abc.ABC): | |
650 | """ | |
651 | Interface of a top-level control interface. A control interface can be, for | |
652 | example, the LTTng client or a wrapper around liblttng-ctl. It is used to | |
653 | create and manage top-level objects of a session daemon instance. | |
654 | """ | |
655 | ||
656 | @abc.abstractmethod | |
ce8470c9 MJ |
657 | def create_session(self, name=None, output=None): |
658 | # type: (Optional[str], Optional[SessionOutputLocation]) -> Session | |
ef945e4d JG |
659 | """ |
660 | Create a session with an output. Don't specify an output | |
661 | to create a session without an output. | |
662 | """ | |
fe3442d8 | 663 | raise NotImplementedError |
b9780062 JG |
664 | |
665 | @abc.abstractmethod | |
666 | def start_session_by_name(self, name): | |
667 | # type: (str) -> None | |
668 | """ | |
669 | Start a session by name. | |
670 | """ | |
fe3442d8 | 671 | raise NotImplementedError |
b9780062 JG |
672 | |
673 | @abc.abstractmethod | |
674 | def start_session_by_glob_pattern(self, pattern): | |
675 | # type: (str) -> None | |
676 | """ | |
677 | Start sessions whose name matches `pattern`, see GLOB(7). | |
678 | """ | |
fe3442d8 | 679 | raise NotImplementedError |
b9780062 JG |
680 | |
681 | @abc.abstractmethod | |
682 | def start_sessions_all(self): | |
683 | """ | |
684 | Start all sessions visible to the current user. | |
685 | """ | |
686 | # type: () -> None | |
fe3442d8 | 687 | raise NotImplementedError |
b9780062 JG |
688 | |
689 | @abc.abstractmethod | |
690 | def stop_session_by_name(self, name): | |
691 | # type: (str) -> None | |
692 | """ | |
693 | Stop a session by name. | |
694 | """ | |
fe3442d8 | 695 | raise NotImplementedError |
b9780062 JG |
696 | |
697 | @abc.abstractmethod | |
698 | def stop_session_by_glob_pattern(self, pattern): | |
699 | # type: (str) -> None | |
700 | """ | |
701 | Stop sessions whose name matches `pattern`, see GLOB(7). | |
702 | """ | |
fe3442d8 | 703 | raise NotImplementedError |
b9780062 JG |
704 | |
705 | @abc.abstractmethod | |
706 | def stop_sessions_all(self): | |
707 | """ | |
708 | Stop all sessions visible to the current user. | |
709 | """ | |
710 | # type: () -> None | |
fe3442d8 | 711 | raise NotImplementedError |
b9780062 JG |
712 | |
713 | @abc.abstractmethod | |
714 | def destroy_session_by_name(self, name): | |
715 | # type: (str) -> None | |
716 | """ | |
717 | Destroy a session by name. | |
718 | """ | |
fe3442d8 | 719 | raise NotImplementedError |
b9780062 JG |
720 | |
721 | @abc.abstractmethod | |
722 | def destroy_session_by_glob_pattern(self, pattern): | |
723 | # type: (str) -> None | |
724 | """ | |
725 | Destroy sessions whose name matches `pattern`, see GLOB(7). | |
726 | """ | |
fe3442d8 | 727 | raise NotImplementedError |
b9780062 JG |
728 | |
729 | @abc.abstractmethod | |
730 | def destroy_sessions_all(self): | |
731 | # type: () -> None | |
732 | """ | |
733 | Destroy all sessions visible to the current user. | |
734 | """ | |
fe3442d8 | 735 | raise NotImplementedError |
b9780062 JG |
736 | |
737 | @abc.abstractmethod | |
738 | def list_sessions(self): | |
739 | # type: () -> List[Session] | |
740 | """ | |
741 | List all sessions visible to the current user. | |
742 | """ | |
fe3442d8 | 743 | raise NotImplementedError |
a8cac44b JG |
744 | |
745 | @abc.abstractmethod | |
746 | def rotate_session_by_name(self, name, wait=True): | |
747 | # type: (str, bool) -> None | |
748 | """ | |
749 | Rotate a session | |
750 | """ | |
751 | raise NotImplementedError | |
752 | ||
753 | @abc.abstractmethod | |
754 | def schedule_size_based_rotation(self, name, size_bytes): | |
755 | # type: (str, int) -> None | |
756 | """ | |
757 | Schedule automatic size-based rotations. | |
758 | """ | |
759 | raise NotImplementedError | |
760 | ||
761 | @abc.abstractmethod | |
762 | def schedule_time_based_rotation(self, name, period_seconds): | |
763 | # type: (str, int) -> None | |
764 | """ | |
765 | Schedule automatic time-based rotations. | |
766 | """ | |
767 | raise NotImplementedError |