/trappy/dynamic.py

https://github.com/ARM-software/trappy · Python · 157 lines · 113 code · 13 blank · 31 comment · 2 complexity · e7efc4d6c66ff82782c4efd6a5cfb924 MD5 · raw file

  1. # Copyright 2015-2017 ARM Limited
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. #
  15. """The idea is to create a wrapper class that
  16. returns a Type of a Class dynamically created based
  17. on the input parameters. Similar to a factory design
  18. pattern
  19. """
  20. from __future__ import unicode_literals
  21. from __future__ import division
  22. from __future__ import print_function
  23. from trappy.base import Base
  24. import re
  25. from trappy.ftrace import GenericFTrace
  26. def default_init(self):
  27. """Default Constructor for the
  28. Dynamic MetaClass. This is used for
  29. the dynamic object creation in
  30. :mod:`trappy.dynamic.DynamicTypeFactory`
  31. """
  32. kwords = {}
  33. try:
  34. kwords["parse_raw"] = self.parse_raw
  35. except AttributeError:
  36. pass
  37. super(type(self), self).__init__(**kwords)
  38. class DynamicTypeFactory(type):
  39. """Override the type class to create
  40. a dynamic type on the fly. This Factory
  41. class is used internally by
  42. :mod:`trappy.dynamic.register_dynamic_ftrace`
  43. """
  44. def __new__(mcs, name, bases, dct):
  45. """Override the new method"""
  46. return type.__new__(mcs, str(name), bases, dct)
  47. def __init__(cls, name, bases, dct):
  48. """Override the constructor"""
  49. super(DynamicTypeFactory, cls).__init__(name, bases, dct)
  50. def _get_name(name):
  51. """Internal Method to Change camelcase to
  52. underscores. CamelCase -> camel_case
  53. """
  54. return re.sub('(?!^)([A-Z]+)', r'_\1', name).lower()
  55. def register_dynamic_ftrace(class_name, unique_word, scope="all",
  56. parse_raw=False, pivot=None):
  57. """Create a Dynamic FTrace parser and register it with any FTrace parsing classes
  58. :param class_name: The name of the class to be registered
  59. (Should be in CamelCase)
  60. :type class_name: str
  61. :param unique_word: The unique_word to be matched in the
  62. trace
  63. :type unique_word: str
  64. :param scope: Registry Scope (Can be used to constrain
  65. the parsing of events and group them together)
  66. :type scope: str
  67. :param parse_raw: If, true, raw trace output (-r flag)
  68. will be used
  69. :type parse_raw: bool
  70. :param pivot: The data column about which the data can be grouped
  71. :type pivot: str
  72. For example if a new unique word :code:`my_unique_word` has
  73. to be registered with TRAPpy:
  74. ::
  75. import trappy
  76. custom_class = trappy.register_dynamic_ftrace("MyEvent", "my_unique_word")
  77. trace = trappy.FTrace("/path/to/trace_file")
  78. # New data member created in the ftrace object
  79. trace.my_event
  80. .. note:: The name of the member is :code:`my_event` from **MyEvent**
  81. :return: A class object of type :mod:`trappy.base.Base`
  82. """
  83. kwords = {
  84. "__init__": default_init,
  85. "unique_word": unique_word,
  86. "name": _get_name(class_name),
  87. "parse_raw" : parse_raw,
  88. }
  89. if pivot:
  90. kwords["pivot"] = pivot
  91. dyn_class = DynamicTypeFactory(class_name, (Base,), kwords)
  92. GenericFTrace.register_parser(dyn_class, scope)
  93. return dyn_class
  94. def register_ftrace_parser(cls, scope="all"):
  95. """Register a new FTrace parser class implementation
  96. Should be used when the class has complex helper methods and does
  97. not expect to use the default constructor.
  98. :param cls: The class to be registered for
  99. enabling the parsing of an event in trace
  100. :type cls: :mod:`trappy.base.Base`
  101. :param scope: scope of this parser class. The scope can be used
  102. to restrict the parsing done on an individual file. Currently
  103. the only scopes available are "sched", "thermal" or "all"
  104. :type scope: string
  105. """
  106. # Check the argspec of the class
  107. GenericFTrace.register_parser(cls, scope)
  108. def unregister_ftrace_parser(ftrace_parser):
  109. """Unregister an ftrace parser
  110. :param ftrace_parser: An ftrace parser class that was registered
  111. with register_ftrace_parser() or register_dynamic_ftrace().
  112. If done with the latter, the cls parameter is the return value
  113. of register_dynamic_ftrace()
  114. :type ftrace_parser: class derived from :mod:`trappy.base.Base`
  115. """
  116. GenericFTrace.unregister_parser(ftrace_parser)