1 # The MIT License (MIT)
3 # Copyright (c) 2013-2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 import babeltrace
.common
as common
25 import babeltrace
.reader_field_definition
as field_definition
29 def _create_event(event_notification
, trace_handle
=None, trace_collection
=None):
30 event
= Event
.__new
__(Event
)
31 event
._event
_notification
= event_notification
32 event
._trace
_handle
= trace_handle
33 event
._trace
_collection
= trace_collection
36 class Event(collections
.Mapping
):
38 An :class:`Event` object represents a trace event. :class:`Event`
39 objects are returned by :attr:`TraceCollection.events` and are
40 not meant to be instantiated by the user.
42 :class:`Event` has a :class:`dict`-like interface for accessing
43 an event's field value by field name:
45 .. code-block:: python
49 If a field name exists in multiple scopes, the value of the first
50 field found is returned. The scopes are searched in the following
53 1. Event fields (:attr:`babeltrace.common.CTFScope.EVENT_FIELDS`)
54 2. Event context (:attr:`babeltrace.common.CTFScope.EVENT_CONTEXT`)
55 3. Stream event context (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_CONTEXT`)
56 4. Event header (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_HEADER`)
57 5. Packet context (:attr:`babeltrace.common.CTFScope.STREAM_PACKET_CONTEXT`)
58 6. Packet header (:attr:`babeltrace.common.CTFScope.TRACE_PACKET_HEADER`)
60 It is still possible to obtain a field's value from a specific
61 scope using :meth:`field_with_scope`.
63 Field values are returned as native Python types, that is:
65 +-----------------------+----------------------------------+
66 | Field type | Python type |
67 +=======================+==================================+
68 | Integer | :class:`int` |
69 +-----------------------+----------------------------------+
70 | Floating point number | :class:`float` |
71 +-----------------------+----------------------------------+
72 | Enumeration | :class:`str` (enumeration label) |
73 +-----------------------+----------------------------------+
74 | String | :class:`str` |
75 +-----------------------+----------------------------------+
76 | Array | :class:`list` of native Python |
78 +-----------------------+----------------------------------+
79 | Sequence | :class:`list` of native Python |
81 +-----------------------+----------------------------------+
82 | Structure | :class:`dict` mapping field |
83 | | names to native Python objects |
84 +-----------------------+----------------------------------+
86 For example, printing the third element of a sequence named ``seq``
87 in a structure named ``my_struct`` of the ``event``'s field named
88 ``my_field`` is done this way:
90 .. code-block:: python
92 print(event['my_field']['my_struct']['seq'][2])
96 raise NotImplementedError("Event cannot be instantiated")
101 Event name or ``None`` on error.
105 return self
._event
_notification
.event
.name
109 def _clock_value(self
):
110 cc_prio_map
= self
._event
_notification
.clock_class_priority_map
111 clock_class
= cc_prio_map
.highest_priority_clock_class
115 return self
._event
_notification
.event
.clock_value(clock_class
)
120 Event timestamp in cycles or -1 on error.
124 clock_value
= self
._clock
_value
()
128 if clock_value
is not None:
129 return clock_value
.cycles
136 Event timestamp (nanoseconds since Epoch).
140 clock_value
= self
._clock
_value
()
142 raise RuntimeError("Failed to get event timestamp")
144 if clock_value
is not None:
145 return clock_value
.ns_from_epoch
147 raise RuntimeError("Failed to get event timestamp")
152 Event timestamp as a standard :class:`datetime.datetime`
155 Note that the :class:`datetime.datetime` class' precision
156 is limited to microseconds, whereas :attr:`timestamp` provides
157 the event's timestamp with a nanosecond resolution.
160 return datetime
.date
.fromtimestamp(self
.timestamp
/ 1E9
)
162 def field_with_scope(self
, field_name
, scope
):
164 Returns the value of a field named *field_name* within the
165 scope *scope*, or ``None`` if the field cannot be found.
167 *scope* must be one of :class:`babeltrace.common.CTFScope`
171 if scope
not in _SCOPES
:
172 raise ValueError("Invalid scope provided")
174 field
= self
._field
_with
_scope
(field_name
, scope
)
176 if field
is not None:
179 def field_list_with_scope(self
, scope
):
181 Returns a list of field names in the scope *scope*.
184 if scope
not in _SCOPES
:
185 raise ValueError("Invalid scope provided")
189 for field
in self
._field
_list
_with
_scope
(scope
):
190 field_names
.append(field
.name
)
197 :class:`TraceHandle` object containing this event, or ``None``
202 return self
._trace
_handle
203 except AttributeError:
207 def trace_collection(self
):
209 :class:`TraceCollection` object containing this event, or
214 return self
._trace
_collection
215 except AttributeError:
218 def __getitem__(self
, field_name
):
219 field
= self
._field
(field_name
)
221 raise KeyError(field_name
)
225 for key
in self
.keys():
230 for scope
in _SCOPES
:
231 scope_field
= self
._get
_scope
_field
(scope
)
232 if scope_field
is not None and isinstance(scope_field
,
233 bt2
._StructureField
):
234 count
+= len(scope_field
)
237 def __contains__(self
, field_name
):
238 return self
._field
(field_name
) is not None
242 Returns the list of field names.
244 Note: field names are unique within the returned list, although
245 a field name could exist in multiple scopes. Use
246 :meth:`field_list_with_scope` to obtain the list of field names
252 for scope
in _SCOPES
:
253 for name
in self
.field_list_with_scope(scope
):
254 field_names
.add(name
)
256 return list(field_names
)
258 def get(self
, field_name
, default
=None):
260 Returns the value of the field named *field_name*, or *default*
263 See :class:`Event` note about how fields are retrieved by
264 name when multiple fields share the same name in different
268 field
= self
._field
(field_name
)
277 Generates pairs of (field name, field value).
279 This method iterates :meth:`keys` to find field names, which
280 means some fields could be unavailable if other fields share
281 their names in scopes with higher priorities.
284 for field
in self
.keys():
285 yield (field
, self
[field
])
287 def _get_scope_field(self
, scope
):
289 event
= self
._event
_notification
.event
290 if scope
is common
.CTFScope
.EVENT_FIELDS
:
291 return event
.payload_field
293 if scope
is common
.CTFScope
.EVENT_CONTEXT
:
294 return event
.context_field
296 if scope
is common
.CTFScope
.STREAM_EVENT_CONTEXT
:
297 return event
.stream_event_context_field
299 if scope
is common
.CTFScope
.STREAM_EVENT_HEADER
:
300 return event
.header_field
302 if scope
is common
.CTFScope
.STREAM_PACKET_CONTEXT
:
303 return event
.packet
.context_field
305 if scope
is common
.CTFScope
.TRACE_PACKET_HEADER
:
306 return event
.packet
.header_field
310 raise ValueError("Invalid scope provided")
312 def _field_with_scope(self
, field_name
, scope
):
313 scope_field
= self
._get
_scope
_field
(scope
)
314 if scope_field
is not None:
316 bt2_field
= scope_field
[field_name
]
317 if bt2_field
is not None:
318 return field_definition
._Definition
(scope
, bt2_field
,
320 except (KeyError, bt2
.Error
):
323 def _field(self
, field_name
):
324 for scope
in _SCOPES
:
325 field
= self
._field
_with
_scope
(field_name
, scope
)
326 if field
is not None:
329 def _field_list_with_scope(self
, scope
):
331 scope_field
= self
._get
_scope
_field
(scope
)
333 if scope_field
is None or not isinstance(scope_field
,
334 bt2
._StructureField
):
337 for name
, field
in scope_field
.items():
338 fields
.append(field_definition
._Definition
(scope
, field
, name
))
343 # Priority of the scopes when searching for event fields
345 common
.CTFScope
.EVENT_FIELDS
,
346 common
.CTFScope
.EVENT_CONTEXT
,
347 common
.CTFScope
.STREAM_EVENT_CONTEXT
,
348 common
.CTFScope
.STREAM_EVENT_HEADER
,
349 common
.CTFScope
.STREAM_PACKET_CONTEXT
,
350 common
.CTFScope
.TRACE_PACKET_HEADER