3 # Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 # SPDX-License-Identifier: GPL-2.0-only
12 from typing
import Optional
, Type
, Union
, List
15 Defines an abstract interface to control LTTng tracing.
17 The various control concepts are defined by this module. You can use them with a
18 Controller to interact with a session daemon.
20 This interface is not comprehensive; it currently provides a subset of the
21 control functionality that is used by tests.
25 def _generate_random_string(length
):
28 random
.choice(string
.ascii_lowercase
+ string
.digits
) for _
in range(length
)
32 class ContextType(abc
.ABC
):
33 """Base class representing a tracing context field."""
38 class VpidContextType(ContextType
):
39 """Application's virtual process id."""
44 class VuidContextType(ContextType
):
45 """Application's virtual user id."""
50 class VgidContextType(ContextType
):
51 """Application's virtual group id."""
56 class JavaApplicationContextType(ContextType
):
57 """A java application-specific context field is a piece of state which the application provides."""
61 retriever_name
, # type: str
62 field_name
, # type: str
64 self
._retriever
_name
= retriever_name
# type: str
65 self
._field
_name
= field_name
# type: str
68 def retriever_name(self
):
70 return self
._retriever
_name
75 return self
._field
_name
79 class TracingDomain(enum
.Enum
):
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."
89 return "<%s.%s>" % (self
.__class
__.__name
__, self
.name
)
93 class BufferSharingPolicy(enum
.Enum
):
94 """Buffer sharing policy."""
96 PerUID
= "Per-UID buffering"
97 PerPID
= "Per-PID buffering"
100 return "<%s.%s>" % (self
.__class
__.__name
__, self
.name
)
103 class EventRule(abc
.ABC
):
104 """Event rule base class, see LTTNG-EVENT-RULE(7)."""
113 class LogLevelRuleAsSevereAs(LogLevelRule
):
114 def __init__(self
, level
):
124 class LogLevelRuleExactly(LogLevelRule
):
125 def __init__(self
, level
):
135 class TracepointEventRule(EventRule
):
138 name_pattern
=None, # type: Optional[str]
139 filter_expression
=None, # type: Optional[str]
140 log_level_rule
=None, # type: Optional[LogLevelRule]
141 name_pattern_exclusions
=None, # type: Optional[List[str]]
143 self
._name
_pattern
= name_pattern
# type: Optional[str]
144 self
._filter
_expression
= filter_expression
# type: Optional[str]
145 self
._log
_level
_rule
= log_level_rule
# type: Optional[LogLevelRule]
146 self
._name
_pattern
_exclusions
= (
147 name_pattern_exclusions
148 ) # type: Optional[List[str]]
151 def name_pattern(self
):
152 # type: () -> Optional[str]
153 return self
._name
_pattern
156 def filter_expression(self
):
157 # type: () -> Optional[str]
158 return self
._filter
_expression
161 def log_level_rule(self
):
162 # type: () -> Optional[LogLevelRule]
163 return self
._log
_level
_rule
166 def name_pattern_exclusions(self
):
167 # type: () -> Optional[List[str]]
168 return self
._name
_pattern
_exclusions
171 class UserTracepointEventRule(TracepointEventRule
):
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]]
179 TracepointEventRule
.__init
__(**locals())
182 class KernelTracepointEventRule(TracepointEventRule
):
185 name_pattern
=None, # type: Optional[str]
186 filter_expression
=None, # type: Optional[str]
187 log_level_rule
=None, # type: Optional[LogLevelRule]
188 name_pattern_exclusions
=None, # type: Optional[List[str]]
190 TracepointEventRule
.__init
__(**locals())
193 class Channel(abc
.ABC
):
195 A channel is an object which is responsible for a set of ring buffers. It is
196 associated to a domain and
200 def _generate_name():
202 return "channel_{random_id}".format(random_id
=_generate_random_string(8))
205 def add_context(self
, context_type
):
206 # type: (ContextType) -> None
207 raise NotImplementedError
212 # type: () -> TracingDomain
213 raise NotImplementedError
219 raise NotImplementedError
222 def add_recording_rule(self
, rule
) -> None:
223 # type: (Type[EventRule]) -> None
224 raise NotImplementedError
227 class SessionOutputLocation(abc
.ABC
):
231 class LocalSessionOutputLocation(SessionOutputLocation
):
232 def __init__(self
, trace_path
):
233 # type: (pathlib.Path)
234 self
._path
= trace_path
238 # type: () -> pathlib.Path
242 class ProcessAttributeTracker(abc
.ABC
):
244 Process attribute tracker used to filter before the evaluation of event
247 Note that this interface is currently limited as it doesn't allow changing
248 the tracking policy. For instance, it is not possible to set the tracking
249 policy back to "all" once it has transitioned to "include set".
253 class TrackingPolicy(enum
.Enum
):
255 Track all possible process attribute value of a given type (i.e. no filtering).
256 This is the default state of a process attribute tracker.
258 EXCLUDE_ALL
= "Exclude all possible process attribute values of a given type."
259 INCLUDE_SET
= "Track a set of specific process attribute values."
262 return "<%s.%s>" % (self
.__class
__.__name
__, self
.name
)
264 def __init__(self
, policy
):
265 # type: (TrackingPolicy)
266 self
._policy
= policy
269 def tracking_policy(self
):
270 # type: () -> TrackingPolicy
274 class ProcessIDProcessAttributeTracker(ProcessAttributeTracker
):
276 def track(self
, pid
):
277 # type: (int) -> None
278 raise NotImplementedError
281 def untrack(self
, pid
):
282 # type: (int) -> None
283 raise NotImplementedError
286 class VirtualProcessIDProcessAttributeTracker(ProcessAttributeTracker
):
288 def track(self
, vpid
):
289 # type: (int) -> None
290 raise NotImplementedError
293 def untrack(self
, vpid
):
294 # type: (int) -> None
295 raise NotImplementedError
298 class UserIDProcessAttributeTracker(ProcessAttributeTracker
):
300 def track(self
, uid
):
301 # type: (Union[int, str]) -> None
302 raise NotImplementedError
305 def untrack(self
, uid
):
306 # type: (Union[int, str]) -> None
307 raise NotImplementedError
310 class VirtualUserIDProcessAttributeTracker(ProcessAttributeTracker
):
312 def track(self
, vuid
):
313 # type: (Union[int, str]) -> None
314 raise NotImplementedError
317 def untrack(self
, vuid
):
318 # type: (Union[int, str]) -> None
319 raise NotImplementedError
322 class GroupIDProcessAttributeTracker(ProcessAttributeTracker
):
324 def track(self
, gid
):
325 # type: (Union[int, str]) -> None
326 raise NotImplementedError
329 def untrack(self
, gid
):
330 # type: (Union[int, str]) -> None
331 raise NotImplementedError
334 class VirtualGroupIDProcessAttributeTracker(ProcessAttributeTracker
):
336 def track(self
, vgid
):
337 # type: (Union[int, str]) -> None
338 raise NotImplementedError
341 def untrack(self
, vgid
):
342 # type: (Union[int, str]) -> None
343 raise NotImplementedError
346 class Session(abc
.ABC
):
348 def _generate_name():
350 return "session_{random_id}".format(random_id
=_generate_random_string(8))
356 raise NotImplementedError
361 # type: () -> Optional[Type[SessionOutputLocation]]
362 raise NotImplementedError
369 buffer_sharing_policy
=BufferSharingPolicy
.PerUID
,
371 # type: (TracingDomain, Optional[str], BufferSharingPolicy) -> Channel
372 """Add a channel with default attributes to the session."""
373 raise NotImplementedError
378 raise NotImplementedError
383 raise NotImplementedError
388 raise NotImplementedError
393 raise NotImplementedError
398 raise NotImplementedError
400 @abc.abstractproperty
401 def kernel_pid_process_attribute_tracker(self
):
402 # type: () -> Type[ProcessIDProcessAttributeTracker]
403 raise NotImplementedError
405 @abc.abstractproperty
406 def kernel_vpid_process_attribute_tracker(self
):
407 # type: () -> Type[VirtualProcessIDProcessAttributeTracker]
408 raise NotImplementedError
410 @abc.abstractproperty
411 def user_vpid_process_attribute_tracker(
413 ) -> Type
[VirtualProcessIDProcessAttributeTracker
]:
414 # type: () -> Type[VirtualProcessIDProcessAttributeTracker]
415 raise NotImplementedError
417 @abc.abstractproperty
418 def kernel_gid_process_attribute_tracker(self
):
419 # type: () -> Type[GroupIDProcessAttributeTracker]
420 raise NotImplementedError
422 @abc.abstractproperty
423 def kernel_vgid_process_attribute_tracker(self
):
424 # type: () -> Type[VirtualGroupIDProcessAttributeTracker]
425 raise NotImplementedError
427 @abc.abstractproperty
428 def user_vgid_process_attribute_tracker(self
):
429 # type: () -> Type[VirtualGroupIDProcessAttributeTracker]
430 raise NotImplementedError
432 @abc.abstractproperty
433 def kernel_uid_process_attribute_tracker(self
):
434 # type: () -> Type[UserIDProcessAttributeTracker]
435 raise NotImplementedError
437 @abc.abstractproperty
438 def kernel_vuid_process_attribute_tracker(self
):
439 # type: () -> Type[VirtualUserIDProcessAttributeTracker]
440 raise NotImplementedError
442 @abc.abstractproperty
443 def user_vuid_process_attribute_tracker(self
):
444 # type: () -> Type[VirtualUserIDProcessAttributeTracker]
445 raise NotImplementedError
448 class ControlException(RuntimeError):
449 """Base type for exceptions thrown by a controller."""
451 def __init__(self
, msg
):
453 super().__init
__(msg
)
456 class Controller(abc
.ABC
):
458 Interface of a top-level control interface. A control interface can be, for
459 example, the LTTng client or a wrapper around liblttng-ctl. It is used to
460 create and manage top-level objects of a session daemon instance.
464 def create_session(self
, name
=None, output
=None):
465 # type: (Optional[str], Optional[SessionOutputLocation]) -> Session
467 Create a session with an output. Don't specify an output
468 to create a session without an output.
470 raise NotImplementedError
473 def start_session_by_name(self
, name
):
474 # type: (str) -> None
476 Start a session by name.
478 raise NotImplementedError
481 def start_session_by_glob_pattern(self
, pattern
):
482 # type: (str) -> None
484 Start sessions whose name matches `pattern`, see GLOB(7).
486 raise NotImplementedError
489 def start_sessions_all(self
):
491 Start all sessions visible to the current user.
494 raise NotImplementedError
497 def stop_session_by_name(self
, name
):
498 # type: (str) -> None
500 Stop a session by name.
502 raise NotImplementedError
505 def stop_session_by_glob_pattern(self
, pattern
):
506 # type: (str) -> None
508 Stop sessions whose name matches `pattern`, see GLOB(7).
510 raise NotImplementedError
513 def stop_sessions_all(self
):
515 Stop all sessions visible to the current user.
518 raise NotImplementedError
521 def destroy_session_by_name(self
, name
):
522 # type: (str) -> None
524 Destroy a session by name.
526 raise NotImplementedError
529 def destroy_session_by_glob_pattern(self
, pattern
):
530 # type: (str) -> None
532 Destroy sessions whose name matches `pattern`, see GLOB(7).
534 raise NotImplementedError
537 def destroy_sessions_all(self
):
540 Destroy all sessions visible to the current user.
542 raise NotImplementedError
545 def list_sessions(self
):
546 # type: () -> List[Session]
548 List all sessions visible to the current user.
550 raise NotImplementedError
553 def rotate_session_by_name(self
, name
, wait
=True):
554 # type: (str, bool) -> None
558 raise NotImplementedError
561 def schedule_size_based_rotation(self
, name
, size_bytes
):
562 # type: (str, int) -> None
564 Schedule automatic size-based rotations.
566 raise NotImplementedError
569 def schedule_time_based_rotation(self
, name
, period_seconds
):
570 # type: (str, int) -> None
572 Schedule automatic time-based rotations.
574 raise NotImplementedError