Remove stale trace-ir test files
[babeltrace.git] / bindings / python / babeltrace / babeltrace / reader_event.py
1 # The MIT License (MIT)
2 #
3 # Copyright (c) 2013-2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 #
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:
11 #
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
14 #
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
21 # THE SOFTWARE.
22
23 import bt2
24 import babeltrace.common as common
25 import babeltrace.reader_field_definition as field_definition
26 import datetime
27 import collections
28
29
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
35 return event
36
37
38 class Event(collections.Mapping):
39 """
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.
43
44 :class:`Event` has a :class:`dict`-like interface for accessing
45 an event's field value by field name:
46
47 .. code-block:: python
48
49 event['my_field']
50
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
53 order:
54
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`)
61
62 It is still possible to obtain a field's value from a specific
63 scope using :meth:`field_with_scope`.
64
65 Field values are returned as native Python types, that is:
66
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 |
79 | | objects |
80 +-----------------------+----------------------------------+
81 | Sequence | :class:`list` of native Python |
82 | | objects |
83 +-----------------------+----------------------------------+
84 | Structure | :class:`dict` mapping field |
85 | | names to native Python objects |
86 +-----------------------+----------------------------------+
87
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:
91
92 .. code-block:: python
93
94 print(event['my_field']['my_struct']['seq'][2])
95 """
96
97 def __init__(self):
98 raise NotImplementedError("Event cannot be instantiated")
99
100 @property
101 def name(self):
102 """
103 Event name or ``None`` on error.
104 """
105
106 try:
107 return self._event_notification.event.name
108 except bt2.Error:
109 pass
110
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
114 if not clock_class:
115 return
116
117 return self._event_notification.event.clock_value(clock_class)
118
119 @property
120 def cycles(self):
121 """
122 Event timestamp in cycles or -1 on error.
123 """
124
125 try:
126 clock_value = self._clock_value()
127 except bt2.Error:
128 return -1
129
130 if clock_value is not None:
131 return clock_value.cycles
132 else:
133 return -1
134
135 @property
136 def timestamp(self):
137 """
138 Event timestamp (nanoseconds since Epoch).
139 """
140
141 try:
142 clock_value = self._clock_value()
143 except bt2.Error:
144 raise RuntimeError("Failed to get event timestamp")
145
146 if clock_value is not None:
147 return clock_value.ns_from_epoch
148 else:
149 raise RuntimeError("Failed to get event timestamp")
150
151 @property
152 def datetime(self):
153 """
154 Event timestamp as a standard :class:`datetime.datetime`
155 object.
156
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.
160 """
161
162 return datetime.date.fromtimestamp(self.timestamp / 1E9)
163
164 def field_with_scope(self, field_name, scope):
165 """
166 Returns the value of a field named *field_name* within the
167 scope *scope*, or ``None`` if the field cannot be found.
168
169 *scope* must be one of :class:`babeltrace.common.CTFScope`
170 constants.
171 """
172
173 if scope not in _SCOPES:
174 raise ValueError("Invalid scope provided")
175
176 field = self._field_with_scope(field_name, scope)
177
178 if field is not None:
179 return field.value
180
181 def field_list_with_scope(self, scope):
182 """
183 Returns a list of field names in the scope *scope*.
184 """
185
186 if scope not in _SCOPES:
187 raise ValueError("Invalid scope provided")
188
189 field_names = []
190
191 for field in self._field_list_with_scope(scope):
192 field_names.append(field.name)
193
194 return field_names
195
196 @property
197 def handle(self):
198 """
199 :class:`TraceHandle` object containing this event, or ``None``
200 on error.
201 """
202
203 try:
204 return self._trace_handle
205 except AttributeError:
206 return None
207
208 @property
209 def trace_collection(self):
210 """
211 :class:`TraceCollection` object containing this event, or
212 ``None`` on error.
213 """
214
215 try:
216 return self._trace_collection
217 except AttributeError:
218 return
219
220 def __getitem__(self, field_name):
221 field = self._field(field_name)
222 if field is None:
223 raise KeyError(field_name)
224 return field.value
225
226 def __iter__(self):
227 for key in self.keys():
228 yield key
229
230 def __len__(self):
231 count = 0
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)
237 return count
238
239 def __contains__(self, field_name):
240 return self._field(field_name) is not None
241
242 def keys(self):
243 """
244 Returns the list of field names.
245
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
249 of a given scope.
250 """
251
252 field_names = set()
253
254 for scope in _SCOPES:
255 for name in self.field_list_with_scope(scope):
256 field_names.add(name)
257
258 return list(field_names)
259
260 def get(self, field_name, default=None):
261 """
262 Returns the value of the field named *field_name*, or *default*
263 when not found.
264
265 See :class:`Event` note about how fields are retrieved by
266 name when multiple fields share the same name in different
267 scopes.
268 """
269
270 field = self._field(field_name)
271
272 if field is None:
273 return default
274
275 return field.value
276
277 def items(self):
278 """
279 Generates pairs of (field name, field value).
280
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.
284 """
285
286 for field in self.keys():
287 yield (field, self[field])
288
289 def _get_scope_field(self, scope):
290 try:
291 event = self._event_notification.event
292 if scope is common.CTFScope.EVENT_FIELDS:
293 return event.payload_field
294
295 if scope is common.CTFScope.EVENT_CONTEXT:
296 return event.context_field
297
298 if scope is common.CTFScope.STREAM_EVENT_CONTEXT:
299 return event.stream_event_context_field
300
301 if scope is common.CTFScope.STREAM_EVENT_HEADER:
302 return event.header_field
303
304 if scope is common.CTFScope.STREAM_PACKET_CONTEXT:
305 return event.packet.context_field
306
307 if scope is common.CTFScope.TRACE_PACKET_HEADER:
308 return event.packet.header_field
309 except bt2.Error:
310 return
311
312 raise ValueError("Invalid scope provided")
313
314 def _field_with_scope(self, field_name, scope):
315 scope_field = self._get_scope_field(scope)
316 if scope_field is not None:
317 try:
318 bt2_field = scope_field[field_name]
319 if bt2_field is not None:
320 return field_definition._Definition(scope, bt2_field,
321 field_name)
322 except (KeyError, bt2.Error):
323 return None
324
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:
329 return field
330
331 def _field_list_with_scope(self, scope):
332 fields = []
333 scope_field = self._get_scope_field(scope)
334
335 if scope_field is None or not isinstance(scope_field,
336 bt2._StructureField):
337 return fields
338
339 for name, field in scope_field.items():
340 fields.append(field_definition._Definition(scope, field, name))
341
342 return fields
343
344
345 # Priority of the scopes when searching for event fields
346 _SCOPES = [
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
353 ]
This page took 0.037787 seconds and 4 git commands to generate.