Class: Datadog::DI::Probe Private

Inherits:
Object
  • Object
show all
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 confilcting 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

Instance Method Summary collapse

Constructor Details

#initialize(id:, type:, file: nil, line_no: nil, type_name: nil, method_name: nil, template: nil, capture_snapshot: false, max_capture_depth: nil, max_capture_attribute_count: 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
# 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, capture_snapshot: false, max_capture_depth: nil,
  max_capture_attribute_count: 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

  if line_no && method_name
    raise ArgumentError, "Probe contains both line number and method name: #{id}"
  end

  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

  @id = id
  @type = type
  @file = file
  @line_no = line_no
  @type_name = type_name
  @method_name = method_name
  @template = template
  @capture_snapshot = !!capture_snapshot
  @max_capture_depth = max_capture_depth
  @max_capture_attribute_count = max_capture_attribute_count

  # These checks use instance methods that have more complex logic
  # than checking a single argument value. To avoid duplicating
  # the logic here, use the methods and perform these checks after
  # instance variable assignment.
  unless method? || line?
    raise ArgumentError, "Unhandled probe type: neither method nor line probe: #{id}"
  end

  @rate_limit = rate_limit || (@capture_snapshot ? 1 : 5000)
  @rate_limiter = Datadog::Core::TokenBucket.new(@rate_limit)

  @emitting_notified = false
end

Instance Attribute Details

#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.



188
189
190
# File 'lib/datadog/di/probe.rb', line 188

def emitting_notified=(value)
  @emitting_notified = value
end

#fileObject (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.



87
88
89
# File 'lib/datadog/di/probe.rb', line 87

def file
  @file
end

#idObject (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.



85
86
87
# File 'lib/datadog/di/probe.rb', line 85

def id
  @id
end

#instrumentation_moduleObject

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.



174
175
176
# File 'lib/datadog/di/probe.rb', line 174

def instrumentation_module
  @instrumentation_module
end

#instrumentation_trace_pointObject

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.



178
179
180
# File 'lib/datadog/di/probe.rb', line 178

def instrumentation_trace_point
  @instrumentation_trace_point
end

#instrumented_pathObject

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.



183
184
185
# File 'lib/datadog/di/probe.rb', line 183

def instrumented_path
  @instrumented_path
end

#line_noObject (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.



88
89
90
# File 'lib/datadog/di/probe.rb', line 88

def line_no
  @line_no
end

#max_capture_attribute_countObject (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.



99
100
101
# File 'lib/datadog/di/probe.rb', line 99

def max_capture_attribute_count
  @max_capture_attribute_count
end

#max_capture_depthObject (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.



95
96
97
# File 'lib/datadog/di/probe.rb', line 95

def max_capture_depth
  @max_capture_depth
end

#method_nameObject (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.



90
91
92
# File 'lib/datadog/di/probe.rb', line 90

def method_name
  @method_name
end

#rate_limitObject (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.



102
103
104
# File 'lib/datadog/di/probe.rb', line 102

def rate_limit
  @rate_limit
end

#rate_limiterObject (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.



105
106
107
# File 'lib/datadog/di/probe.rb', line 105

def rate_limiter
  @rate_limiter
end

#templateObject (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.



91
92
93
# File 'lib/datadog/di/probe.rb', line 91

def template
  @template
end

#typeObject (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.



86
87
88
# File 'lib/datadog/di/probe.rb', line 86

def type
  @type
end

#type_nameObject (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.



89
90
91
# File 'lib/datadog/di/probe.rb', line 89

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.

Returns:

  • (Boolean)


107
108
109
# File 'lib/datadog/di/probe.rb', line 107

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.

Returns:

  • (Boolean)


189
190
191
# File 'lib/datadog/di/probe.rb', line 189

def emitting_notified?
  !!@emitting_notified
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).

If file is an absolute path (i.e., it starts with a slash), the file must be identical to path to match.

If file is not an absolute path, the path matches if the file is its suffix, at a path component boundary.

Returns:

  • (Boolean)


163
164
165
166
167
168
169
170
171
# File 'lib/datadog/di/probe.rb', line 163

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_matches_suffix?(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.

Returns:

  • (Boolean)


116
117
118
119
120
121
# File 'lib/datadog/di/probe.rb', line 116

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.



135
136
137
138
139
140
# File 'lib/datadog/di/probe.rb', line 135

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

#locationObject

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.



143
144
145
146
147
148
149
150
151
152
153
# File 'lib/datadog/di/probe.rb', line 143

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.

Returns:

  • (Boolean)


124
125
126
# File 'lib/datadog/di/probe.rb', line 124

def method?
  !!(type_name && method_name)
end