lib/datadog/di/instrumenter.rb in datadog-2.6.0 vs lib/datadog/di/instrumenter.rb in datadog-2.7.0
- old
+ new
@@ -52,22 +52,24 @@
# (however, Probe instances can be replaced by OpenStruct instances
# providing the same interface with not much effort).
#
# @api private
class Instrumenter
- def initialize(settings, serializer, logger, code_tracker: nil)
+ def initialize(settings, serializer, logger, code_tracker: nil, telemetry: nil)
@settings = settings
@serializer = serializer
@logger = logger
+ @telemetry = telemetry
@code_tracker = code_tracker
@lock = Mutex.new
end
attr_reader :settings
attr_reader :serializer
attr_reader :logger
+ attr_reader :telemetry
attr_reader :code_tracker
# This is a substitute for Thread::Backtrace::Location
# which does not have a public constructor.
# Used for the fabricated stack frame for the method itself
@@ -170,16 +172,16 @@
# value for the setting.
# Normally none of the settings should change, but in the test suite
# we use mock objects and the methods may be mocked with
# individual invocations, yielding different return values on
# different calls to the same method.
- permit_untargeted_trace_points = settings.dynamic_instrumentation.untargeted_trace_points
+ permit_untargeted_trace_points = settings.dynamic_instrumentation.internal.untargeted_trace_points
iseq = nil
if code_tracker
- iseq = code_tracker.iseqs_for_path_suffix(probe.file).first # steep:ignore
- unless iseq
+ ret = code_tracker.iseqs_for_path_suffix(probe.file) # steep:ignore
+ unless ret
if permit_untargeted_trace_points
# Continue withoout targeting the trace point.
# This is going to cause a serious performance penalty for
# the entire file containing the line to be instrumented.
else
@@ -202,10 +204,14 @@
# explicitly defined, and we do not have code tracking, do not
# instrument the method.
raise Error::DITargetNotDefined, "File not in code tracker registry: #{probe.file}"
end
+ if ret
+ actual_path, iseq = ret
+ end
+
# If trace point is not targeted, we only need one trace point per file.
# Creating a trace point for each probe does work but the performance
# penalty will be taken for each trace point defined in the file.
# Since untargeted trace points are only (currently) used internally
# for benchmarking, and shouldn't be used in customer applications,
@@ -215,22 +221,30 @@
# file and line, we also only need one trace point, but since the
# overhead of targeted trace points is minimal, don't worry about
# this optimization just yet and create a trace point for each probe.
tp = TracePoint.new(:line) do |tp|
- # If trace point is not targeted, we must verify that the invocation
- # is the file & line that we want, because untargeted trace points
- # are invoked for *each* line of Ruby executed.
- if iseq || tp.lineno == probe.line_no && probe.file_matches?(tp.path)
- if rate_limiter.nil? || rate_limiter.allow?
- # & is to stop steep complaints, block is always present here.
- block&.call(probe: probe, trace_point: tp, caller_locations: caller_locations)
+ begin
+ # If trace point is not targeted, we must verify that the invocation
+ # is the file & line that we want, because untargeted trace points
+ # are invoked for *each* line of Ruby executed.
+ if iseq || tp.lineno == probe.line_no && probe.file_matches?(tp.path)
+ if rate_limiter.nil? || rate_limiter.allow?
+ # & is to stop steep complaints, block is always present here.
+ block&.call(probe: probe, trace_point: tp, caller_locations: caller_locations)
+ end
end
+ rescue => exc
+ raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
+ logger.warn("Unhandled exception in line trace point: #{exc.class}: #{exc}")
+ telemetry&.report(exc, description: "Unhandled exception in line trace point")
+ # TODO test this path
end
rescue => exc
raise if settings.dynamic_instrumentation.propagate_all_exceptions
logger.warn("Unhandled exception in line trace point: #{exc.class}: #{exc}")
+ telemetry&.report(exc, description: "Unhandled exception in line trace point")
# TODO test this path
end
# TODO internal check - remove or use a proper exception
if !iseq && !permit_untargeted_trace_points
@@ -242,9 +256,11 @@
# Already instrumented in another thread, warn?
return
end
probe.instrumentation_trace_point = tp
+ # actual_path could be nil if we don't use targeted trace points.
+ probe.instrumented_path = actual_path
if iseq
tp.enable(target: iseq, target_line: line_no)
else
tp.enable