Class: Datadog::DI::Probe Private
- Inherits:
-
Object
- Object
- Datadog::DI::Probe
- Defined in:
- lib/datadog/di/probe.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
Encapsulates probe information (as received via remote config) and state (e.g. whether the probe was installed, or executed).
It is possible that remote configuration will specify an unsupported probe type or attribute, due to new DI functionality being added over time. We want to have predictable behavior in such cases, and since we can’t guarantee that there will be enough information in a remote config payload to construct a functional probe, ProbeBuilder and remote config code must be prepared to deal with exceptions raised by Probe constructor in particular. Therefore, Probe constructor will raise an exception if it determines that there is not enough information (or conflicting information) in the arguments to create a functional probe, and upstream code is tasked with not spamming logs with notifications of such errors (and potentially limiting the attempts to construct probe from a given payload).
Note that, while remote configuration provides line numbers as an array, the only supported line number configuration is a single line (this is the case for all languages currently). Therefore Probe only supports one line number, and ProbeBuilder is responsible for extracting that one line number out of the array received from RC.
Note: only some of the parameter/attribute values are currently validated.
Constant Summary collapse
- KNOWN_TYPES =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
i[log].freeze
Instance Attribute Summary collapse
-
#condition ⇒ Object
readonly
private
The compiled condition for the probe, as a String.
-
#condition_evaluation_failed_rate_limiter ⇒ Object
readonly
private
Rate limiter object for sending snapshots with evaluation errors for when probe condition evaluation fails.
-
#emitting_notified ⇒ Object
writeonly
private
TODO emitting_notified reads and writes should in theory be locked, however since DI is only implemented for MRI in practice the missing locking should not cause issues.
- #file ⇒ Object readonly private
- #id ⇒ Object readonly private
-
#instrumentation_module ⇒ Object
private
Instrumentation module for method probes.
-
#instrumentation_trace_point ⇒ Object
private
Line trace point for line probes.
-
#instrumented_path ⇒ Object
private
Actual path to the file instrumented by the probe, for line probes, when code tracking is available and line trace point is targeted.
- #line_no ⇒ Object readonly private
-
#max_capture_attribute_count ⇒ Object
readonly
private
Configured maximum capture attribute count.
-
#max_capture_depth ⇒ Object
readonly
private
Configured maximum capture depth.
- #method_name ⇒ Object readonly private
-
#rate_limit ⇒ Object
readonly
private
Rate limit in effect, in invocations per second.
-
#rate_limiter ⇒ Object
readonly
private
Rate limiter object.
- #template ⇒ Object readonly private
- #template_segments ⇒ Object readonly private
- #type ⇒ Object readonly private
- #type_name ⇒ Object readonly private
Instance Method Summary collapse
- #capture_snapshot? ⇒ Boolean private
- #emitting_notified? ⇒ Boolean private
- #executed_on_line! ⇒ Object private
- #executed_on_line? ⇒ Boolean private
-
#file_matches?(path) ⇒ Boolean
private
Returns whether the provided
pathmatches the user-designated file (of a line probe). -
#initialize(id:, type:, file: nil, line_no: nil, type_name: nil, method_name: nil, template: nil, template_segments: nil, capture_snapshot: false, max_capture_depth: nil, max_capture_attribute_count: nil, condition: nil, rate_limit: nil) ⇒ Probe
constructor
private
A new instance of Probe.
-
#line? ⇒ Boolean
private
Returns whether the probe is a line probe.
-
#line_no! ⇒ Object
private
Returns the line number associated with the probe, raising Error::MissingLineNumber if the probe does not have a line number associated with it.
-
#location ⇒ Object
private
Source code location of the probe, for diagnostic reporting.
-
#method? ⇒ Boolean
private
Returns whether the probe is a method probe.
Constructor Details
#initialize(id:, type:, file: nil, line_no: nil, type_name: nil, method_name: nil, template: nil, template_segments: nil, capture_snapshot: false, max_capture_depth: nil, max_capture_attribute_count: nil, condition: nil, rate_limit: nil) ⇒ Probe
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of Probe.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 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 94 95 96 97 98 99 100 |
# File 'lib/datadog/di/probe.rb', line 37 def initialize(id:, type:, file: nil, line_no: nil, type_name: nil, method_name: nil, template: nil, template_segments: nil, capture_snapshot: false, max_capture_depth: nil, max_capture_attribute_count: nil, condition: nil, rate_limit: nil) # Perform some sanity checks here to detect unexpected attribute # combinations, in order to not do them in subsequent code. unless KNOWN_TYPES.include?(type) raise ArgumentError, "Unknown probe type: #{type}" end # Probe should be inferred to be a line probe if the specification # contains a line number. This how Java tracer works and Go tracer # is implementing the same behavior, and Go will have all 3 fields # (file path, line number and method name) for line probes. # Do not raise if line number and method name both exist - instead # treat the probe as a line probe. # # In the future we want to provide type name and method name to line # probes, so that the library can verify that the instrumented line # is in the method that the frontend showed to the user when the # user created the probe. if line_no && !file raise ArgumentError, "Probe contains line number but not file: #{id}" end if type_name && !method_name || method_name && !type_name raise ArgumentError, "Partial method probe definition: #{id}" end if line_no.nil? && method_name.nil? raise ArgumentError, "Unhandled probe type: neither method nor line probe: #{id}" end @id = id @type = type @file = file @line_no = line_no @type_name = type_name @method_name = method_name @template = template @template_segments = template_segments @capture_snapshot = !!capture_snapshot @max_capture_depth = max_capture_depth @max_capture_attribute_count = max_capture_attribute_count @condition = condition @rate_limit = rate_limit || (@capture_snapshot ? 1 : 5000) @rate_limiter = Datadog::Core::TokenBucket.new(@rate_limit) # At most one report per second. # We create the rate limiter here even though it may never be used, # to avoid having to synchronize the creation since method probes # can be executed on multiple threads concurrently (even if line # probes are never executed concurrently since those are done in a # trace point). if condition @condition_evaluation_failed_rate_limiter = Datadog::Core::TokenBucket.new(1) end @emitting_notified = false end |
Instance Attribute Details
#condition ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
The compiled condition for the probe, as a String.
112 113 114 |
# File 'lib/datadog/di/probe.rb', line 112 def condition @condition end |
#condition_evaluation_failed_rate_limiter ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Rate limiter object for sending snapshots with evaluation errors for when probe condition evaluation fails. This rate limit is separate from the “base” rate limit for the probe because when the condition evaluation succeeds we want the “base” rate limit applied, not tainted by any evaluation errors (for example, the condition can be highly selective, and when it does not hold the evaluation may fail - we don’t want to use up the probe rate limit for the errors).
136 137 138 |
# File 'lib/datadog/di/probe.rb', line 136 def condition_evaluation_failed_rate_limiter @condition_evaluation_failed_rate_limiter end |
#emitting_notified=(value) ⇒ Object (writeonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
TODO emitting_notified reads and writes should in theory be locked, however since DI is only implemented for MRI in practice the missing locking should not cause issues.
216 217 218 |
# File 'lib/datadog/di/probe.rb', line 216 def emitting_notified=(value) @emitting_notified = value end |
#file ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
104 105 106 |
# File 'lib/datadog/di/probe.rb', line 104 def file @file end |
#id ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
102 103 104 |
# File 'lib/datadog/di/probe.rb', line 102 def id @id end |
#instrumentation_module ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Instrumentation module for method probes.
202 203 204 |
# File 'lib/datadog/di/probe.rb', line 202 def instrumentation_module @instrumentation_module end |
#instrumentation_trace_point ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Line trace point for line probes. Normally this would be a targeted trace point.
206 207 208 |
# File 'lib/datadog/di/probe.rb', line 206 def instrumentation_trace_point @instrumentation_trace_point end |
#instrumented_path ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Actual path to the file instrumented by the probe, for line probes, when code tracking is available and line trace point is targeted. For untargeted line trace points instrumented path will be nil.
211 212 213 |
# File 'lib/datadog/di/probe.rb', line 211 def instrumented_path @instrumented_path end |
#line_no ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
105 106 107 |
# File 'lib/datadog/di/probe.rb', line 105 def line_no @line_no end |
#max_capture_attribute_count ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Configured maximum capture attribute count. Can be nil in which case the global default will be used.
120 121 122 |
# File 'lib/datadog/di/probe.rb', line 120 def max_capture_attribute_count @max_capture_attribute_count end |
#max_capture_depth ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Configured maximum capture depth. Can be nil in which case the global default will be used.
116 117 118 |
# File 'lib/datadog/di/probe.rb', line 116 def max_capture_depth @max_capture_depth end |
#method_name ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
107 108 109 |
# File 'lib/datadog/di/probe.rb', line 107 def method_name @method_name end |
#rate_limit ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Rate limit in effect, in invocations per second. Always present.
123 124 125 |
# File 'lib/datadog/di/probe.rb', line 123 def rate_limit @rate_limit end |
#rate_limiter ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Rate limiter object. For internal DI use only.
126 127 128 |
# File 'lib/datadog/di/probe.rb', line 126 def rate_limiter @rate_limiter end |
#template ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
108 109 110 |
# File 'lib/datadog/di/probe.rb', line 108 def template @template end |
#template_segments ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
109 110 111 |
# File 'lib/datadog/di/probe.rb', line 109 def template_segments @template_segments end |
#type ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
103 104 105 |
# File 'lib/datadog/di/probe.rb', line 103 def type @type end |
#type_name ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
106 107 108 |
# File 'lib/datadog/di/probe.rb', line 106 def type_name @type_name end |
Instance Method Details
#capture_snapshot? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
138 139 140 |
# File 'lib/datadog/di/probe.rb', line 138 def capture_snapshot? @capture_snapshot end |
#emitting_notified? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
217 218 219 |
# File 'lib/datadog/di/probe.rb', line 217 def emitting_notified? !!@emitting_notified end |
#executed_on_line! ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
225 226 227 228 |
# File 'lib/datadog/di/probe.rb', line 225 def executed_on_line! # TODO lock? @executed_on_line = true end |
#executed_on_line? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
221 222 223 |
# File 'lib/datadog/di/probe.rb', line 221 def executed_on_line? !!@executed_on_line end |
#file_matches?(path) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns whether the provided path matches the user-designated file (of a line probe).
Delegates to Utils.path_can_match_spec? which performs fuzzy matching. See the comments in utils.rb for details.
191 192 193 194 195 196 197 198 199 |
# File 'lib/datadog/di/probe.rb', line 191 def file_matches?(path) if path.nil? raise ArgumentError, "Cannot match against a nil path" end unless file raise ArgumentError, "Probe does not have a file to match against" end Utils.path_can_match_spec?(path, file) end |
#line? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns whether the probe is a line probe.
Method probes may still specify a file name (to aid in locating the method or for stack traversal purposes?), therefore we do not check for file name/path presence here and just consider the line number.
147 148 149 150 151 152 |
# File 'lib/datadog/di/probe.rb', line 147 def line? # Constructor checks that file is given if line number is given, # but for safety, check again here since we somehow got a probe with # a line number but no file in the wild. !!(file && line_no) end |
#line_no! ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns the line number associated with the probe, raising Error::MissingLineNumber if the probe does not have a line number associated with it.
This method is used by instrumentation driver to ensure a line number that is passed into the instrumentation logic is actually a line number and not nil.
166 167 168 169 170 171 |
# File 'lib/datadog/di/probe.rb', line 166 def line_no! if line_no.nil? raise Error::MissingLineNumber, "Probe #{id} does not have a line number associated with it" end line_no end |
#location ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Source code location of the probe, for diagnostic reporting.
174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/datadog/di/probe.rb', line 174 def location if method? "#{type_name}.#{method_name}" elsif line? "#{file}:#{line_no}" else # This case should not be possible because constructor verifies that # the probe is a method or a line probe. raise NotImplementedError end end |
#method? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns whether the probe is a method probe.
155 156 157 |
# File 'lib/datadog/di/probe.rb', line 155 def method? line_no.nil? end |