Module: Contrast::Agent::Patching::Policy::Patcher
- Extended by:
- AfterLoadPatcher
- Includes:
- Components::Interface
- Defined in:
- lib/contrast/agent/patching/policy/patcher.rb
Overview
This is how we patch into our customer’s code. It provides a way to track which classes we need to patch into and, once we’ve woven, provides a map for which methods our renamed functions need to call and how.
Constant Summary collapse
- PATCH_MONITOR =
Hook to only monkeypatch Contrast. This will not trigger any other functions, like rewriting or scanning. Exposed for those situations, like ActiveRecord dynamically defining functions, where only a subset of the Assess changes are needed.
Monitor.new
Class Method Summary collapse
-
.patch ⇒ Object
Hook to install the Contrast changes needed to allow for the instrumentation of the application - this only occurs once, during startup to catchup on everything we didn’t see get loaded.
-
.patch_method(mod, methods, method_policy) ⇒ Boolean
We did it, team.
- .patch_methods ⇒ Object
-
.patch_specific_module(mod) ⇒ Object
This method is called by TracePointHook to instrument a specific class during a require or eval of dynamic class definition.
Methods included from AfterLoadPatcher
Methods included from Components::Interface
Class Method Details
.patch ⇒ Object
Hook to install the Contrast changes needed to allow for the instrumentation of the application - this only occurs once, during startup to catchup on everything we didn’t see get loaded
53 54 55 56 57 |
# File 'lib/contrast/agent/patching/policy/patcher.rb', line 53 def patch catchup_after_load_patches patch_methods Contrast::Agent::Assess::Policy::RewriterPatch.rewrite_interpolations end |
.patch_method(mod, methods, method_policy) ⇒ Boolean
We did it, team. We found a patcher(s) that applies to the given class (or module) and the given method. Time to do some tracking.
108 109 110 111 112 113 114 115 116 |
# File 'lib/contrast/agent/patching/policy/patcher.rb', line 108 def patch_method mod, methods, method_policy return false unless methods&.any? # don't even build the name if there are no methods if Contrast::Utils::ClassUtil.prepended_method?(mod, method_policy) Contrast::Agent::Patching::Policy::Patch.instrument_with_prepend(mod, method_policy) else Contrast::Agent::Patching::Policy::Patch.instrument_with_alias(mod, methods, method_policy) end end |
.patch_methods ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/contrast/agent/patching/policy/patcher.rb', line 65 def patch_methods PATCH_MONITOR.synchronize do t = Contrast::Agent::Thread.new do synchronized_patch_methods end # aborting on exception makes exceptions propagate. t.abort_on_exception = true t.priority = Thread.current.priority + 1 t.join end end |
.patch_specific_module(mod) ⇒ Object
This method is called by TracePointHook to instrument a specific class during a require or eval of dynamic class definition
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/contrast/agent/patching/policy/patcher.rb', line 79 def patch_specific_module mod with_contrast_scope do mod_name = mod.cs__name return unless Contrast::Utils::ClassUtil.truly_defined?(mod_name) return if AGENT.skip_instrumentation?(mod_name) load_patches_for_module(mod_name) return unless all_module_names.any? { |name| name == mod_name } module_data = Contrast::Agent::ModuleData.new(mod, mod_name) patch_into_module(module_data) all_module_names.delete(mod_name) if status_type.get_status(mod).patched? rescue StandardError => e logger.error('Unable to patch module', e, module: mod_name) end end |