Class: AppMap::Hook
- Inherits:
-
Object
- Object
- AppMap::Hook
- Defined in:
- lib/appmap/hook.rb,
lib/appmap/hook/method.rb,
ext/appmap/appmap.c
Defined Under Namespace
Classes: Method
Constant Summary collapse
- LOG =
(ENV['APPMAP_DEBUG'] == 'true' || ENV['DEBUG'] == 'true')
- LOG_HOOK =
(ENV['DEBUG_HOOK'] == 'true')
- OBJECT_INSTANCE_METHODS =
i[! != !~ <=> == === =~ __id__ __send__ class clone define_singleton_method display dup enum_for eql? equal? extend freeze frozen? hash inspect instance_eval instance_exec instance_of? instance_variable_defined? instance_variable_get instance_variable_set instance_variables is_a? itself kind_of? method methods nil? object_id private_methods protected_methods public_method public_methods public_send remove_instance_variable respond_to? send singleton_class singleton_method singleton_methods taint tainted? tap then to_enum to_s to_h to_a trust untaint untrust untrusted? yield_self].freeze
- OBJECT_STATIC_METHODS =
i[! != !~ < <= <=> == === =~ > >= __id__ __send__ alias_method allocate ancestors attr attr_accessor attr_reader attr_writer autoload autoload? class class_eval class_exec class_variable_defined? class_variable_get class_variable_set class_variables clone const_defined? const_get const_missing const_set constants define_method define_singleton_method deprecate_constant display dup enum_for eql? equal? extend freeze frozen? hash include include? included_modules inspect instance_eval instance_exec instance_method instance_methods instance_of? instance_variable_defined? instance_variable_get instance_variable_set instance_variables is_a? itself kind_of? method method_defined? methods module_eval module_exec name new nil? object_id prepend private_class_method private_constant private_instance_methods private_method_defined? private_methods protected_instance_methods protected_method_defined? protected_methods public_class_method public_constant public_instance_method public_instance_methods public_method public_method_defined? public_methods public_send remove_class_variable remove_instance_variable remove_method respond_to? send singleton_class singleton_class? singleton_method singleton_methods superclass taint tainted? tap then to_enum to_s trust undef_method untaint untrust untrusted? yield_self].freeze
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
Class Method Summary collapse
- .lock_builtins ⇒ Object
-
.qualify_method_name(method) ⇒ Object
Return the class, separator (‘.’ or ‘#’), and method name for the given method.
- .singleton_method_owner_name(method) ⇒ Object
Instance Method Summary collapse
-
#enable(&block) ⇒ Object
Observe class loading and hook all methods which match the config.
-
#hook_builtins ⇒ Object
hook_builtins builds hooks for code that is built in to the Ruby standard library.
-
#initialize(config) ⇒ Hook
constructor
A new instance of Hook.
Constructor Details
#initialize(config) ⇒ Hook
Returns a new instance of Hook.
37 38 39 40 41 42 |
# File 'lib/appmap/hook.rb', line 37 def initialize(config) @config = config @trace_enabled = [] # Paths that are known to be non-tracing @notrace_paths = Set.new end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
35 36 37 |
# File 'lib/appmap/hook.rb', line 35 def config @config end |
Class Method Details
.lock_builtins ⇒ Object
17 18 19 20 21 |
# File 'lib/appmap/hook.rb', line 17 def lock_builtins return if @builtins_hooked @builtins_hooked = true end |
.qualify_method_name(method) ⇒ Object
Return the class, separator (‘.’ or ‘#’), and method name for the given method.
25 26 27 28 29 30 31 32 |
# File 'lib/appmap/hook.rb', line 25 def qualify_method_name(method) if method.owner.singleton_class? class_name = singleton_method_owner_name(method) [ class_name, '.', method.name ] else [ method.owner.name, '#', method.name ] end end |
.singleton_method_owner_name(method) ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'ext/appmap/appmap.c', line 15 static VALUE singleton_method_owner_name(VALUE klass, VALUE method) { VALUE owner = rb_funcall(method, rb_intern("owner"), 0); VALUE attached = rb_ivar_get(owner, rb_intern("__attached__")); if (!CLASS_OR_MODULE_P(attached)) { attached = rb_funcall(attached, rb_intern("class"), 0); } // Did __attached__.class return an object that's a Module or a // Class? if (CLASS_OR_MODULE_P(attached)) { // Yup, get it's name return rb_mod_name(attached); } // Nope (which seems weird, but whatever). Fall back to calling // #to_s on the method's owner and hope for the best. return rb_funcall(owner, rb_intern("to_s"), 0); } |
Instance Method Details
#enable(&block) ⇒ Object
Observe class loading and hook all methods which match the config.
45 46 47 48 49 50 51 52 |
# File 'lib/appmap/hook.rb', line 45 def enable(&block) require 'appmap/hook/method' hook_builtins @trace_end = TracePoint.new(:end, &method(:trace_end)) @trace_end.enable(&block) end |
#hook_builtins ⇒ Object
hook_builtins builds hooks for code that is built in to the Ruby standard library. No TracePoint events are emitted for builtins, so a separate hooking mechanism is needed.
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/appmap/hook.rb', line 56 def hook_builtins return unless self.class.lock_builtins class_from_string = lambda do |fq_class| fq_class.split('::').inject(Object) do |mod, class_name| mod.const_get(class_name) end end config.builtin_hooks.each do |class_name, hooks| Array(hooks).each do |hook| require hook.package.package_name if hook.package.package_name Array(hook.method_names).each do |method_name| method_name = method_name.to_sym base_cls = class_from_string.(class_name) hook_method = lambda do |entry| cls, method = entry return false if config.never_hook?(cls, method) Hook::Method.new(hook.package, cls, method).activate end methods = [] methods << [ base_cls, base_cls.public_instance_method(method_name) ] rescue nil if base_cls.respond_to?(:singleton_class) methods << [ base_cls.singleton_class, base_cls.singleton_class.public_instance_method(method_name) ] rescue nil end methods.compact! if methods.empty? warn "Method #{method_name} not found on #{base_cls.name}" else methods.each(&hook_method) end end end end end |