ae6c58911e11f8042bfe713635ff7982077830bf
[deliverable/lttng-analyses.git] / lttnganalyses / cli / mi.py
1 # The MIT License (MIT)
2 #
3 # Copyright (C) 2015 - Philippe Proulx <pproulx@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 THE
21 # SOFTWARE.
22
23 from collections import namedtuple
24
25
26 class Tags:
27 CPU = 'cpu'
28 MEMORY = 'memory'
29 INTERRUPT = 'interrupt'
30 SCHED = 'sched'
31 SYSCALL = 'syscall'
32 IO = 'io'
33 TOP = 'top'
34 STATS = 'stats'
35 FREQ = 'freq'
36 LOG = 'log'
37
38
39 class ColumnDescription:
40 def __init__(self, key, title, do_class, unit=None):
41 self._key = key
42 self._title = title
43 self._do_class = do_class
44 self._unit = unit
45
46 @property
47 def key(self):
48 return self._key
49
50 def to_native_object(self):
51 obj = {
52 'title': self._title,
53 'class': self._do_class,
54 }
55
56 if self._unit:
57 obj['unit'] = self._unit
58
59 return obj
60
61
62 class TableClass:
63 def __init__(self, name, title, column_descriptions_tuples=None,
64 inherit=None):
65 if column_descriptions_tuples is None:
66 column_descriptions_tuples = []
67
68 self._inherit = inherit
69 self._name = name
70 self._title = title
71 self._column_descriptions = []
72
73 for column_descr_tuple in column_descriptions_tuples:
74 key = column_descr_tuple[0]
75 title = column_descr_tuple[1]
76 do_type = column_descr_tuple[2]
77 unit = None
78
79 if len(column_descr_tuple) > 3:
80 unit = column_descr_tuple[3]
81
82 column_descr = ColumnDescription(key, title, do_type.CLASS, unit)
83 self._column_descriptions.append(column_descr)
84
85 @property
86 def name(self):
87 return self._name
88
89 @property
90 def title(self):
91 return self._title
92
93 def to_native_object(self):
94 obj = {}
95 column_descrs = self._column_descriptions
96 native_column_descrs = [c.to_native_object() for c in column_descrs]
97
98 if self._inherit is not None:
99 obj['inherit'] = self._inherit
100
101 if self._title is not None:
102 obj['title'] = self._title
103
104 if native_column_descrs:
105 obj['column-descriptions'] = native_column_descrs
106
107 return obj
108
109 def get_column_named_tuple(self):
110 keys = [cd.key for cd in self._column_descriptions]
111
112 return namedtuple('Column', keys)
113
114
115 class ResultTable:
116 def __init__(self, table_class, begin, end, subtitle=None):
117 self._table_class = table_class
118 self._column_named_tuple = table_class.get_column_named_tuple()
119 self._subtitle = subtitle
120 self._timerange = TimeRange(begin, end)
121 self._rows = []
122
123 @property
124 def table_class(self):
125 return self._table_class
126
127 @property
128 def timerange(self):
129 return self._timerange
130
131 @property
132 def title(self):
133 return self._table_class.title
134
135 @property
136 def subtitle(self):
137 return self._subtitle
138
139 def append_row(self, **kwargs):
140 row = self._column_named_tuple(**kwargs)
141 self._rows.append(row)
142
143 def append_row_tuple(self, row_tuple):
144 self._rows.append(row_tuple)
145
146 @property
147 def rows(self):
148 return self._rows
149
150 def to_native_object(self):
151 obj = {
152 'class': self._table_class.name,
153 'time-range': self._timerange.to_native_object(),
154 }
155 row_objs = []
156
157 if self._table_class.name:
158 if self._subtitle is not None:
159 full_title = '{} [{}]'.format(self.title, self._subtitle)
160 table_class = TableClass(None, full_title,
161 inherit=self._table_class.name)
162 self._table_class = table_class
163
164 if self._table_class.name is None:
165 obj['class'] = self._table_class.to_native_object()
166
167 for row in self._rows:
168 row_obj = []
169
170 for cell in row:
171 row_obj.append(cell.to_native_object())
172
173 row_objs.append(row_obj)
174
175 obj['data'] = row_objs
176
177 return obj
178
179
180 class _DataObject:
181 def to_native_object(self):
182 raise NotImplementedError
183
184 def __eq__(self, other):
185 # ensure we're comparing the same type first
186 if not isinstance(other, self.__class__):
187 return False
188
189 # call specific equality method
190 return self._eq(other)
191
192 def _eq(self, other):
193 raise NotImplementedError
194
195
196 class _UnstructuredDataObject(_DataObject):
197 def __init__(self, value):
198 self._value = value
199
200 @property
201 def value(self):
202 return self._value
203
204 def to_native_object(self):
205 return self._value
206
207 def __str__(self):
208 return str(self._value)
209
210 def _eq(self, other):
211 return self._value == other._value
212
213
214 class _StructuredDataObject(_DataObject):
215 def to_native_object(self):
216 base = {'class': self.CLASS}
217 base.update(self._to_native_object())
218
219 return base
220
221 def _to_native_object(self):
222 raise NotImplementedError
223
224
225 class Boolean(_UnstructuredDataObject):
226 CLASS = 'bool'
227
228
229 class Integer(_UnstructuredDataObject):
230 CLASS = 'int'
231
232
233 class Float(_UnstructuredDataObject):
234 CLASS = 'float'
235
236
237 class String(_UnstructuredDataObject):
238 CLASS = 'string'
239
240
241 class Empty(_DataObject):
242 def to_native_object(self):
243 return None
244
245 def _eq(self, other):
246 return True
247
248
249 class Unknown(_StructuredDataObject):
250 CLASS = 'unknown'
251
252 def _to_native_object(self):
253 return {}
254
255 def _eq(self, other):
256 return True
257
258 def __str__(self):
259 return '?'
260
261
262 class _SimpleValue(_StructuredDataObject):
263 def __init__(self, value):
264 self._value = value
265
266 @property
267 def value(self):
268 return self._value
269
270 def _to_native_object(self):
271 return {'value': self._value}
272
273 def __str__(self):
274 return str(self._value)
275
276 def _eq(self, other):
277 return self._value == other._value
278
279
280 class _SimpleName(_StructuredDataObject):
281 def __init__(self, name):
282 self._name = name
283
284 @property
285 def name(self):
286 return self._name
287
288 def _to_native_object(self):
289 return {'name': self._name}
290
291 def __str__(self):
292 return self._name
293
294 def _eq(self, other):
295 return self._name == other._name
296
297
298 class Ratio(_SimpleValue):
299 CLASS = 'ratio'
300
301 @classmethod
302 def from_percentage(cls, value):
303 return cls(value / 100)
304
305 def to_percentage(self):
306 return self._value * 100
307
308
309 class Timestamp(_SimpleValue):
310 CLASS = 'timestamp'
311
312
313 class Duration(_SimpleValue):
314 CLASS = 'duration'
315
316 @classmethod
317 def from_ms(cls, ms):
318 return cls(ms * 1000000)
319
320 @classmethod
321 def from_us(cls, us):
322 return cls(us * 1000)
323
324 def to_ms(self):
325 return self._value / 1000000
326
327 def to_us(self):
328 return self._value / 1000
329
330
331 class Size(_SimpleValue):
332 CLASS = 'size'
333
334
335 class Bitrate(_SimpleValue):
336 CLASS = 'bitrate'
337
338 @classmethod
339 def from_size_duration(cls, size, duration):
340 return cls(size * 8 / duration)
341
342
343 class TimeRange(_StructuredDataObject):
344 CLASS = 'time-range'
345
346 def __init__(self, begin, end):
347 self._begin = begin
348 self._end = end
349
350 @property
351 def begin(self):
352 return self._begin
353
354 @property
355 def end(self):
356 return self._end
357
358 def _to_native_object(self):
359 return {'begin': self._begin, 'end': self._end}
360
361 def _eq(self, other):
362 return (self._begin, self._end) == (other._begin, other._end)
363
364
365 class Syscall(_SimpleName):
366 CLASS = 'syscall'
367
368
369 class Process(_StructuredDataObject):
370 CLASS = 'process'
371
372 def __init__(self, name=None, pid=None, tid=None):
373 self._name = name
374 self._pid = pid
375 self._tid = tid
376
377 @property
378 def name(self):
379 return self._name
380
381 @property
382 def pid(self):
383 return self._pid
384
385 @property
386 def tid(self):
387 return self._tid
388
389 def _to_native_object(self):
390 ret_dict = {}
391
392 if self._name is not None:
393 ret_dict['name'] = self._name
394
395 if self._pid is not None:
396 ret_dict['pid'] = self._pid
397
398 if self._tid is not None:
399 ret_dict['tid'] = self._tid
400
401 return ret_dict
402
403 def _eq(self, other):
404 self_tuple = (self._name, self._pid, self._tid)
405 other_tuple = (other._name, other._pid, other._tid)
406
407 return self_tuple == other_tuple
408
409
410 class Path(_StructuredDataObject):
411 CLASS = 'path'
412
413 def __init__(self, path):
414 self._path = path
415
416 @property
417 def path(self):
418 return self._path
419
420 def _to_native_object(self):
421 return {'path': self._path}
422
423 def _eq(self, other):
424 return self._path == other._path
425
426
427 class Fd(_StructuredDataObject):
428 CLASS = 'fd'
429
430 def __init__(self, fd):
431 self._fd = fd
432
433 @property
434 def fd(self):
435 return self._fd
436
437 def _to_native_object(self):
438 return {'fd': self._fd}
439
440 def _eq(self, other):
441 return self._fd == other._fd
442
443
444 class Irq(_StructuredDataObject):
445 CLASS = 'irq'
446
447 def __init__(self, is_hard, nr, name=None):
448 self._is_hard = is_hard
449 self._nr = nr
450 self._name = name
451
452 @property
453 def is_hard(self):
454 return self._is_hard
455
456 @property
457 def nr(self):
458 return self._nr
459
460 @property
461 def name(self):
462 return self._name
463
464 def _to_native_object(self):
465 obj = {'hard': self._is_hard, 'nr': self._nr}
466
467 if self._name is not None:
468 obj['name'] = self._name
469
470 return obj
471
472 def _eq(self, other):
473 self_tuple = (self._is_hard, self._nr, self._name)
474 other_tuple = (other._is_hard, other._nr, other._name)
475
476 return self_tuple == other_tuple
477
478
479 class Cpu(_StructuredDataObject):
480 CLASS = 'cpu'
481
482 def __init__(self, cpu_id):
483 self._id = cpu_id
484
485 @property
486 def id(self):
487 return self._id
488
489 def _to_native_object(self):
490 return {'id': self._id}
491
492 def _eq(self, other):
493 return self._id == other._id
494
495
496 class Disk(_SimpleName):
497 CLASS = 'disk'
498
499
500 class Partition(_SimpleName):
501 CLASS = 'part'
502
503
504 class NetIf(_SimpleName):
505 CLASS = 'netif'
506
507
508 def get_metadata(version, title, description, authors, url, tags,
509 table_classes):
510 t_classes = {t.name: t.to_native_object() for t in table_classes}
511
512 return {
513 'mi-version': {
514 'major': 0,
515 'minor': 1,
516 },
517 'version': {
518 'major': version.major,
519 'minor': version.minor,
520 'patch': version.patch,
521 'extra': version.extra
522 },
523 'title': title,
524 'description': description,
525 'authors': authors,
526 'url': url,
527 'tags': tags,
528 'table-classes': t_classes,
529 }
This page took 0.039181 seconds and 4 git commands to generate.