Class: Contrast::Agent::Scope
Overview
Scope lets us disable Contrast for certain code calls. We need to do this so that we don’t propagate through our own code.
Think logging: If you have something like “The source was ‘” + source + “’”, and source is tracked, you’ll trigger propagation with the + method. This in turn would cause propagation if you log there “The target ”” + target + “‘ was propagated’” Which would then cause another propagation with the ‘+’ method, forever.
Instead, we should say “If I’m already doing Contrast things, don’t track this”
Constant Summary collapse
- SCOPE_LIST =
%i[contrast deserialization].cs__freeze
Class Method Summary collapse
Instance Method Summary collapse
- #enter_contrast_scope! ⇒ Object
- #enter_deserialization_scope! ⇒ Object
- #enter_scope!(name) ⇒ Object
-
#exit_contrast_scope! ⇒ Object
Scope Exits…
- #exit_deserialization_scope! ⇒ Object
- #exit_scope!(name) ⇒ Object
- #in_contrast_scope? ⇒ Boolean
- #in_deserialization_scope? ⇒ Boolean
-
#in_scope?(name) ⇒ Boolean
Dynamic versions of the above.
-
#initialize ⇒ Scope
constructor
A new instance of Scope.
- #with_contrast_scope ⇒ Object
- #with_deserialization_scope ⇒ Object
Constructor Details
#initialize ⇒ Scope
Returns a new instance of Scope.
20 21 22 23 |
# File 'lib/contrast/agent/scope.rb', line 20 def initialize instance_variable_set(:@contrast_scope, 0) instance_variable_set(:@deserialization_scope, 0) end |
Class Method Details
.ensure_valid_scope!(scope_sym) ⇒ Object
113 114 115 116 117 118 119 |
# File 'lib/contrast/agent/scope.rb', line 113 def ensure_valid_scope! scope_sym unless valid_scope? scope_sym # rubocop:disable Style/GuardClause with_contrast_scope do raise NoMethodError, "Scope '#{ scope_sym.inspect }' is not registered as a scope." end end end |
.valid_scope?(scope_sym) ⇒ Boolean
109 110 111 |
# File 'lib/contrast/agent/scope.rb', line 109 def valid_scope? scope_sym Contrast::Agent::Scope::SCOPE_LIST.include? scope_sym end |
Instance Method Details
#enter_contrast_scope! ⇒ Object
33 34 35 36 |
# File 'lib/contrast/agent/scope.rb', line 33 def enter_contrast_scope! level = instance_variable_get(:@contrast_scope) instance_variable_set(:@contrast_scope, level + 1) end |
#enter_deserialization_scope! ⇒ Object
38 39 40 41 |
# File 'lib/contrast/agent/scope.rb', line 38 def enter_deserialization_scope! level = instance_variable_get(:@deserialization_scope) instance_variable_set(:@deserialization_scope, level + 1) end |
#enter_scope!(name) ⇒ Object
96 97 98 99 100 |
# File 'lib/contrast/agent/scope.rb', line 96 def enter_scope! name cs__class.ensure_valid_scope! name call = with_contrast_scope { :"enter_#{ name }_scope!" } send(call) end |
#exit_contrast_scope! ⇒ Object
Scope Exits… by design, can go below zero. every exit/enter pair (regardless of series) should cancel each other out.
so we prefer this sequence:
scope = 0
exit = -1
enter = 0
enter = 1
exit = 0
scope = 0
over this sequence:
scope = 0
exit = 0
enter = 1
enter = 2
exit = 1
scope = 1
63 64 65 66 |
# File 'lib/contrast/agent/scope.rb', line 63 def exit_contrast_scope! level = instance_variable_get(:@contrast_scope) instance_variable_set(:@contrast_scope, level - 1) end |
#exit_deserialization_scope! ⇒ Object
68 69 70 71 |
# File 'lib/contrast/agent/scope.rb', line 68 def exit_deserialization_scope! level = instance_variable_get(:@deserialization_scope) instance_variable_set(:@deserialization_scope, level - 1) end |
#exit_scope!(name) ⇒ Object
102 103 104 105 106 |
# File 'lib/contrast/agent/scope.rb', line 102 def exit_scope! name cs__class.ensure_valid_scope! name call = with_contrast_scope { :"exit_#{ name }_scope!" } send(call) end |
#in_contrast_scope? ⇒ Boolean
25 26 27 |
# File 'lib/contrast/agent/scope.rb', line 25 def in_contrast_scope? instance_variable_get(:@contrast_scope).positive? end |
#in_deserialization_scope? ⇒ Boolean
29 30 31 |
# File 'lib/contrast/agent/scope.rb', line 29 def in_deserialization_scope? instance_variable_get(:@deserialization_scope).positive? end |
#in_scope?(name) ⇒ Boolean
Dynamic versions of the above. These are equivalent, but they’re slower and riskier. Prefer the static methods if you know what scope you need at the call site.
90 91 92 93 94 |
# File 'lib/contrast/agent/scope.rb', line 90 def in_scope? name cs__class.ensure_valid_scope! name call = with_contrast_scope { :"in_#{ name }_scope?" } send(call) end |
#with_contrast_scope ⇒ Object
73 74 75 76 77 78 |
# File 'lib/contrast/agent/scope.rb', line 73 def with_contrast_scope enter_contrast_scope! yield ensure exit_contrast_scope! end |
#with_deserialization_scope ⇒ Object
80 81 82 83 84 85 |
# File 'lib/contrast/agent/scope.rb', line 80 def with_deserialization_scope enter_deserialization_scope! yield ensure exit_deserialization_scope! end |