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
30 def _create_event(event_notification
, trace_handle
=None, trace_collection
=None):
31 event
= Event
.__new
__(Event
)
32 event
._event
_notification
= event_notification
33 event
._trace
_handle
= trace_handle
34 event
._trace
_collection
= trace_collection
38 class Event(collections
.Mapping
):
40 An :class:`Event` object represents a trace event. :class:`Event`
41 objects are returned by :attr:`TraceCollection.events` and are
42 not meant to be instantiated by the user.
44 :class:`Event` has a :class:`dict`-like interface for accessing
45 an event's field value by field name:
47 .. code-block:: python
51 If a field name exists in multiple scopes, the value of the first
52 field found is returned. The scopes are searched in the following
55 1. Event fields (:attr:`babeltrace.common.CTFScope.EVENT_FIELDS`)
56 2. Event context (:attr:`babeltrace.common.CTFScope.EVENT_CONTEXT`)
57 3. Stream event context (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_CONTEXT`)
58 4. Event header (:attr:`babeltrace.common.CTFScope.STREAM_EVENT_HEADER`)
59 5. Packet context (:attr:`babeltrace.common.CTFScope.STREAM_PACKET_CONTEXT`)
60 6. Packet header (:attr:`babeltrace.common.CTFScope.TRACE_PACKET_HEADER`)
62 It is still possible to obtain a field's value from a specific
63 scope using :meth:`field_with_scope`.
65 Field values are returned as native Python types, that is:
67 +-----------------------+----------------------------------+
68 | Field type | Python type |
69 +=======================+==================================+
70 | Integer | :class:`int` |
71 +-----------------------+----------------------------------+
72 | Floating point number | :class:`float` |
73 +-----------------------+----------------------------------+
74 | Enumeration | :class:`str` (enumeration label) |
75 +-----------------------+----------------------------------+
76 | String | :class:`str` |
77 +-----------------------+----------------------------------+
78 | Array | :class:`list` of native Python |
80 +-----------------------+----------------------------------+
81 | Sequence | :class:`list` of native Python |
83 +-----------------------+----------------------------------+
84 | Structure | :class:`dict` mapping field |
85 | | names to native Python objects |
86 +-----------------------+----------------------------------+
88 For example, printing the third element of a sequence named ``seq``
89 in a structure named ``my_struct`` of the ``event``'s field named
90 ``my_field`` is done this way:
92 .. code-block:: python
94 print(event['my_field']['my_struct']['seq'][2])
98 raise NotImplementedError("Event cannot be instantiated")
103 Event name or ``None`` on error.
107 return self
._event
_notification
.event
.name
111 def _clock_value(self
):
112 cc_prio_map
= self
._event
_notification
.clock_class_priority_map
113 clock_class
= cc_prio_map
.highest_priority_clock_class
117 return self
._event
_notification
.event
.clock_value(clock_class
)
122 Event timestamp in cycles or -1 on error.
126 clock_value
= self
._clock
_value
()
130 if clock_value
is not None:
131 return clock_value
.cycles
138 Event timestamp (nanoseconds since Epoch).
142 clock_value
= self
._clock
_value
()
144 raise RuntimeError("Failed to get event timestamp")
146 if clock_value
is not None:
147 return clock_value
.ns_from_epoch
149 raise RuntimeError("Failed to get event timestamp")
154 Event timestamp as a standard :class:`datetime.datetime`
157 Note that the :class:`datetime.datetime` class' precision
158 is limited to microseconds, whereas :attr:`timestamp` provides
159 the event's timestamp with a nanosecond resolution.
162 return datetime
.date
.fromtimestamp(self
.timestamp
/ 1E9
)
164 def field_with_scope(self
, field_name
, scope
):
166 Returns the value of a field named *field_name* within the
167 scope *scope*, or ``None`` if the field cannot be found.
169 *scope* must be one of :class:`babeltrace.common.CTFScope`
173 if scope
not in _SCOPES
:
174 raise ValueError("Invalid scope provided")
176 field
= self
._field
_with
_scope
(field_name
, scope
)
178 if field
is not None:
181 def field_list_with_scope(self
, scope
):
183 Returns a list of field names in the scope *scope*.
186 if scope
not in _SCOPES
:
187 raise ValueError("Invalid scope provided")
191 for field
in self
._field
_list
_with
_scope
(scope
):
192 field_names
.append(field
.name
)
199 :class:`TraceHandle` object containing this event, or ``None``
204 return self
._trace
_handle
205 except AttributeError:
209 def trace_collection(self
):
211 :class:`TraceCollection` object containing this event, or
216 return self
._trace
_collection
217 except AttributeError:
220 def __getitem__(self
, field_name
):
221 field
= self
._field
(field_name
)
223 raise KeyError(field_name
)
227 for key
in self
.keys():
232 for scope
in _SCOPES
:
233 scope_field
= self
._get
_scope
_field
(scope
)
234 if scope_field
is not None and isinstance(scope_field
,
235 bt2
._StructureField
):
236 count
+= len(scope_field
)
239 def __contains__(self
, field_name
):
240 return self
._field
(field_name
) is not None
244 Returns the list of field names.
246 Note: field names are unique within the returned list, although
247 a field name could exist in multiple scopes. Use
248 :meth:`field_list_with_scope` to obtain the list of field names
254 for scope
in _SCOPES
:
255 for name
in self
.field_list_with_scope(scope
):
256 field_names
.add(name
)
258 return list(field_names
)
260 def get(self
, field_name
, default
=None):
262 Returns the value of the field named *field_name*, or *default*
265 See :class:`Event` note about how fields are retrieved by
266 name when multiple fields share the same name in different
270 field
= self
._field
(field_name
)
279 Generates pairs of (field name, field value).
281 This method iterates :meth:`keys` to find field names, which
282 means some fields could be unavailable if other fields share
283 their names in scopes with higher priorities.
286 for field
in self
.keys():
287 yield (field
, self
[field
])
289 def _get_scope_field(self
, scope
):
291 event
= self
._event
_notification
.event
292 if scope
is common
.CTFScope
.EVENT_FIELDS
:
293 return event
.payload_field
295 if scope
is common
.CTFScope
.EVENT_CONTEXT
:
296 return event
.context_field
298 if scope
is common
.CTFScope
.STREAM_EVENT_CONTEXT
:
299 return event
.stream_event_context_field
301 if scope
is common
.CTFScope
.STREAM_EVENT_HEADER
:
302 return event
.header_field
304 if scope
is common
.CTFScope
.STREAM_PACKET_CONTEXT
:
305 return event
.packet
.context_field
307 if scope
is common
.CTFScope
.TRACE_PACKET_HEADER
:
308 return event
.packet
.header_field
312 raise ValueError("Invalid scope provided")
314 def _field_with_scope(self
, field_name
, scope
):
315 scope_field
= self
._get
_scope
_field
(scope
)
316 if scope_field
is not None:
318 bt2_field
= scope_field
[field_name
]
319 if bt2_field
is not None:
320 return field_definition
._Definition
(scope
, bt2_field
,
322 except (KeyError, bt2
.Error
):
325 def _field(self
, field_name
):
326 for scope
in _SCOPES
:
327 field
= self
._field
_with
_scope
(field_name
, scope
)
328 if field
is not None:
331 def _field_list_with_scope(self
, scope
):
333 scope_field
= self
._get
_scope
_field
(scope
)
335 if scope_field
is None or not isinstance(scope_field
,
336 bt2
._StructureField
):
339 for name
, field
in scope_field
.items():
340 fields
.append(field_definition
._Definition
(scope
, field
, name
))
345 # Priority of the scopes when searching for event fields
347 common
.CTFScope
.EVENT_FIELDS
,
348 common
.CTFScope
.EVENT_CONTEXT
,
349 common
.CTFScope
.STREAM_EVENT_CONTEXT
,
350 common
.CTFScope
.STREAM_EVENT_HEADER
,
351 common
.CTFScope
.STREAM_PACKET_CONTEXT
,
352 common
.CTFScope
.TRACE_PACKET_HEADER