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