datadog 2.36.0 → 2.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +74 -1
- data/ext/datadog_profiling_native_extension/clock_id_from_mach.c +5 -12
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +29 -18
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +17 -3
- data/ext/datadog_profiling_native_extension/collectors_stack.c +19 -24
- data/ext/datadog_profiling_native_extension/collectors_stack.h +0 -1
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +348 -213
- data/ext/datadog_profiling_native_extension/collectors_thread_context.h +3 -0
- data/ext/datadog_profiling_native_extension/extconf.rb +11 -3
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +5 -0
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +2 -0
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +7 -0
- data/ext/datadog_profiling_native_extension/time_helpers.h +12 -7
- data/ext/libdatadog_api/di.c +76 -0
- data/ext/libdatadog_api/extconf.rb +6 -0
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/ai_guard/api_client.rb +6 -4
- data/lib/datadog/appsec/api_security/route_extractor.rb +7 -4
- data/lib/datadog/appsec/configuration.rb +6 -0
- data/lib/datadog/appsec/context.rb +4 -2
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +59 -4
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +59 -5
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/gateway/request.rb +5 -0
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +4 -0
- data/lib/datadog/appsec/contrib/rack/input_peeker.rb +4 -17
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +21 -0
- data/lib/datadog/appsec/contrib/rails/gateway/request.rb +7 -1
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +60 -7
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +4 -0
- data/lib/datadog/appsec/ext.rb +1 -0
- data/lib/datadog/appsec/metrics/collector.rb +18 -1
- data/lib/datadog/appsec/metrics/exporter.rb +9 -3
- data/lib/datadog/appsec/remote.rb +9 -3
- data/lib/datadog/appsec/route_normalizer/rails_route_pattern.rb +176 -0
- data/lib/datadog/appsec/route_normalizer/route_pattern.rb +378 -0
- data/lib/datadog/appsec/route_normalizer/route_text.rb +57 -0
- data/lib/datadog/appsec/route_normalizer.rb +80 -0
- data/lib/datadog/appsec/utils/http/body_reader.rb +61 -0
- data/lib/datadog/core/configuration/agentless_settings_resolver.rb +2 -2
- data/lib/datadog/core/configuration/components.rb +82 -2
- data/lib/datadog/core/configuration/components_state.rb +6 -1
- data/lib/datadog/core/configuration/settings.rb +4 -7
- data/lib/datadog/core/configuration/supported_configurations.rb +3 -0
- data/lib/datadog/core/evp.rb +11 -0
- data/lib/datadog/core/knuth_sampler.rb +3 -1
- data/lib/datadog/core/metrics/client.rb +1 -1
- data/lib/datadog/core/remote/client/capabilities.rb +34 -7
- data/lib/datadog/core/telemetry/event/app_started.rb +8 -1
- data/lib/datadog/core/transport/http/builder.rb +1 -1
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +1 -1
- data/lib/datadog/core/utils/time.rb +5 -1
- data/lib/datadog/di/base.rb +3 -1
- data/lib/datadog/di/boot.rb +3 -0
- data/lib/datadog/di/capture_expression.rb +21 -0
- data/lib/datadog/di/capture_expression_evaluator.rb +71 -0
- data/lib/datadog/di/capture_limits.rb +41 -0
- data/lib/datadog/di/code_tracker.rb +5 -2
- data/lib/datadog/di/component.rb +112 -38
- data/lib/datadog/di/configuration.rb +6 -0
- data/lib/datadog/di/context.rb +9 -3
- data/lib/datadog/di/el/compiler.rb +1 -1
- data/lib/datadog/di/error.rb +10 -0
- data/lib/datadog/di/fatal_exceptions.rb +26 -0
- data/lib/datadog/di/instrumenter.rb +412 -165
- data/lib/datadog/di/probe.rb +61 -2
- data/lib/datadog/di/probe_builder.rb +83 -1
- data/lib/datadog/di/probe_file_loader.rb +8 -3
- data/lib/datadog/di/probe_manager.rb +67 -9
- data/lib/datadog/di/probe_notification_builder.rb +52 -8
- data/lib/datadog/di/probe_notifier_worker.rb +52 -32
- data/lib/datadog/di/redactor.rb +16 -1
- data/lib/datadog/di/remote.rb +176 -15
- data/lib/datadog/di/serializer.rb +34 -15
- data/lib/datadog/di/transport/input.rb +8 -4
- data/lib/datadog/di.rb +63 -0
- data/lib/datadog/kit/appsec/events/v2.rb +60 -2
- data/lib/datadog/open_feature/component.rb +29 -6
- data/lib/datadog/open_feature/configuration.rb +8 -0
- data/lib/datadog/open_feature/ext.rb +2 -0
- data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +286 -0
- data/lib/datadog/open_feature/flag_evaluation/writer.rb +433 -0
- data/lib/datadog/open_feature/hooks/flag_eval_evp_hook.rb +101 -0
- data/lib/datadog/open_feature/hooks/{flag_eval_hook.rb → flag_eval_metrics_hook.rb} +1 -1
- data/lib/datadog/open_feature/native_evaluator.rb +22 -0
- data/lib/datadog/open_feature/provider.rb +59 -27
- data/lib/datadog/open_feature/transport.rb +55 -1
- data/lib/datadog/opentelemetry/sdk/logs_exporter.rb +5 -12
- data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +4 -11
- data/lib/datadog/opentelemetry/sdk.rb +19 -0
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +6 -1
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +5 -3
- data/lib/datadog/profiling/collectors/thread_context.rb +9 -1
- data/lib/datadog/profiling/component.rb +17 -0
- data/lib/datadog/symbol_database/component.rb +164 -47
- data/lib/datadog/symbol_database/configuration.rb +12 -4
- data/lib/datadog/symbol_database/extensions.rb +19 -0
- data/lib/datadog/symbol_database/extractor.rb +124 -87
- data/lib/datadog/symbol_database/file_hash.rb +3 -1
- data/lib/datadog/symbol_database/remote.rb +8 -3
- data/lib/datadog/symbol_database/scope_batcher.rb +7 -3
- data/lib/datadog/symbol_database/uploader.rb +9 -2
- data/lib/datadog/symbol_database.rb +22 -0
- data/lib/datadog/tracing/contrib/active_job/data_streams.rb +62 -0
- data/lib/datadog/tracing/contrib/active_job/patcher.rb +12 -0
- data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +2 -3
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +12 -12
- data/lib/datadog/tracing/contrib/rack/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/sequel/utils.rb +2 -2
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +1 -1
- data/lib/datadog/tracing/contrib/sinatra/framework.rb +1 -1
- data/lib/datadog/tracing/distributed/baggage.rb +2 -1
- data/lib/datadog/tracing/ext.rb +9 -0
- data/lib/datadog/tracing/remote.rb +34 -3
- data/lib/datadog/tracing/transport/trace_formatter.rb +1 -1
- data/lib/datadog/version.rb +1 -1
- data/lib/datadog.rb +1 -0
- metadata +25 -8
data/lib/datadog/di/component.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'fatal_exceptions'
|
|
4
|
+
|
|
3
5
|
module Datadog
|
|
4
6
|
module DI
|
|
5
7
|
# Component for dynamic instrumentation.
|
|
@@ -15,45 +17,51 @@ module Datadog
|
|
|
15
17
|
class Component
|
|
16
18
|
class << self
|
|
17
19
|
def build(settings, agent_settings, logger, telemetry: nil)
|
|
18
|
-
return unless settings.respond_to?(:dynamic_instrumentation)
|
|
20
|
+
return unless settings.respond_to?(:dynamic_instrumentation)
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
# Explicit DD_DYNAMIC_INSTRUMENTATION_ENABLED=false: do not build the
|
|
23
|
+
# component at all. This is customer intent, not a failure — log at
|
|
24
|
+
# debug and emit no telemetry error. Capabilities#register skips the
|
|
25
|
+
# DI RC block under the same condition, so no enable signal arrives.
|
|
26
|
+
if Remote.explicitly_disabled?(settings)
|
|
27
|
+
logger.debug("di: dynamic instrumentation is explicitly disabled (DD_DYNAMIC_INSTRUMENTATION_ENABLED=false); not building component")
|
|
22
28
|
return
|
|
23
29
|
end
|
|
24
30
|
|
|
25
|
-
|
|
31
|
+
reason = DI.unsupported_reason(settings)
|
|
32
|
+
if reason
|
|
33
|
+
# Log level mirrors customer intent: if the customer explicitly
|
|
34
|
+
# opted in via DD_DYNAMIC_INSTRUMENTATION_ENABLED, warn. Otherwise
|
|
35
|
+
# debug — with always-build, this path runs on every tracer boot
|
|
36
|
+
# for every customer, including those who never wanted DI. Spamming
|
|
37
|
+
# warnings to silent users (especially on JRuby or Ruby 2.5) would
|
|
38
|
+
# be noise. Customers who later trigger implicit enablement via the
|
|
39
|
+
# Datadog UI get a symmetric warn from Remote.handle_rc_enablement
|
|
40
|
+
# when the RC enable signal finds no component to start.
|
|
41
|
+
level = explicitly_enabled?(settings) ? :warn : :debug
|
|
42
|
+
logger.public_send(level, "di: dynamic instrumentation is disabled: #{reason}")
|
|
43
|
+
return
|
|
44
|
+
end
|
|
26
45
|
|
|
27
46
|
new(settings, agent_settings, logger, code_tracker: DI.code_tracker, telemetry: telemetry).tap do |component|
|
|
28
47
|
DI.add_current_component(component)
|
|
29
48
|
end
|
|
30
49
|
end
|
|
31
50
|
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return false
|
|
47
|
-
end
|
|
48
|
-
if RubyVersion.is?('< 2.6')
|
|
49
|
-
logger.warn("di: cannot enable dynamic instrumentation: Ruby 2.6+ is required, but running on #{RUBY_VERSION}")
|
|
50
|
-
return false
|
|
51
|
-
end
|
|
52
|
-
unless DI.respond_to?(:exception_message)
|
|
53
|
-
logger.warn("di: cannot enable dynamic instrumentation: C extension is not available")
|
|
54
|
-
return false
|
|
55
|
-
end
|
|
56
|
-
true
|
|
51
|
+
# True when the customer explicitly set
|
|
52
|
+
# DD_DYNAMIC_INSTRUMENTATION_ENABLED=true (or its equivalent in code).
|
|
53
|
+
# Symmetric to {Remote.explicitly_disabled?}.
|
|
54
|
+
#
|
|
55
|
+
# Uses {Datadog::Core::Configuration::Options::InstanceMethods#using_default?}
|
|
56
|
+
# rather than `options[:enabled].default_precedence?` because the option
|
|
57
|
+
# hash is populated lazily on first access; reading the underlying option
|
|
58
|
+
# before {Component.build} touches the value would NoMethodError on nil.
|
|
59
|
+
#
|
|
60
|
+
# @param settings [Datadog::Core::Configuration::Settings]
|
|
61
|
+
# @return [Boolean]
|
|
62
|
+
def explicitly_enabled?(settings)
|
|
63
|
+
!settings.dynamic_instrumentation.using_default?(:enabled) &&
|
|
64
|
+
settings.dynamic_instrumentation.enabled
|
|
57
65
|
end
|
|
58
66
|
end
|
|
59
67
|
|
|
@@ -68,7 +76,7 @@ module Datadog
|
|
|
68
76
|
@serializer = Serializer.new(settings, redactor, telemetry: telemetry)
|
|
69
77
|
@instrumenter = Instrumenter.new(settings, serializer, logger, code_tracker: code_tracker, telemetry: telemetry)
|
|
70
78
|
@probe_repository = ProbeRepository.new
|
|
71
|
-
@probe_notification_builder = ProbeNotificationBuilder.new(settings, serializer)
|
|
79
|
+
@probe_notification_builder = ProbeNotificationBuilder.new(settings, serializer, logger, telemetry: telemetry)
|
|
72
80
|
@probe_notifier_worker = ProbeNotifierWorker.new(
|
|
73
81
|
settings, logger,
|
|
74
82
|
agent_settings: agent_settings,
|
|
@@ -80,7 +88,11 @@ module Datadog
|
|
|
80
88
|
settings, instrumenter, probe_notification_builder, probe_notifier_worker, logger, probe_repository,
|
|
81
89
|
telemetry: telemetry,
|
|
82
90
|
)
|
|
83
|
-
|
|
91
|
+
# @started transitions are serialized by @lifecycle_mutex so that
|
|
92
|
+
# concurrent RC callbacks (which run on the remote-config thread)
|
|
93
|
+
# cannot race a foreground start! with a background stop!.
|
|
94
|
+
@lifecycle_mutex = Mutex.new
|
|
95
|
+
@started = false
|
|
84
96
|
end
|
|
85
97
|
|
|
86
98
|
attr_reader :settings
|
|
@@ -96,9 +108,61 @@ module Datadog
|
|
|
96
108
|
attr_reader :redactor
|
|
97
109
|
attr_reader :serializer
|
|
98
110
|
|
|
99
|
-
#
|
|
111
|
+
# Starts the DI component: begins accepting probes and
|
|
112
|
+
# processing snapshots.
|
|
113
|
+
#
|
|
114
|
+
# Starts the probe notifier worker thread before enabling the
|
|
115
|
+
# definition trace point, so any future status emission from a
|
|
116
|
+
# trace-point-driven installation has a worker to drain it.
|
|
117
|
+
# Today {ProbeManager#reopen} re-hooks without emitting statuses, so
|
|
118
|
+
# the order is defensive rather than load-bearing. No-op if already
|
|
119
|
+
# started. Serialized by @lifecycle_mutex.
|
|
120
|
+
#
|
|
121
|
+
# @return [void]
|
|
122
|
+
def start!
|
|
123
|
+
@lifecycle_mutex.synchronize do
|
|
124
|
+
return if @started
|
|
125
|
+
|
|
126
|
+
probe_notifier_worker.start
|
|
127
|
+
probe_manager.reopen
|
|
128
|
+
@started = true
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Stops the DI component: removes all probes and stops
|
|
133
|
+
# background threads.
|
|
134
|
+
#
|
|
135
|
+
# The component remains alive and can be restarted with {#start!}.
|
|
136
|
+
# Does not clear out the code tracker.
|
|
137
|
+
# No-op if already stopped. Serialized by @lifecycle_mutex.
|
|
138
|
+
#
|
|
139
|
+
# @return [void]
|
|
140
|
+
def stop!
|
|
141
|
+
@lifecycle_mutex.synchronize do
|
|
142
|
+
return unless @started
|
|
143
|
+
|
|
144
|
+
probe_manager.stop
|
|
145
|
+
probe_notifier_worker.stop
|
|
146
|
+
@started = false
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Whether the component is currently started.
|
|
151
|
+
#
|
|
152
|
+
# Read by remote config dispatch to decide whether to apply probe
|
|
153
|
+
# changes (changes received while stopped are dropped, since the
|
|
154
|
+
# next start! will reconcile from the latest RC state).
|
|
155
|
+
#
|
|
156
|
+
# @return [Boolean] true if start! has been called and stop! has not
|
|
157
|
+
def started?
|
|
158
|
+
@started
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Shuts down dynamic instrumentation permanently.
|
|
100
162
|
#
|
|
101
163
|
# Removes all code hooks and stops background threads.
|
|
164
|
+
# Called by Components#shutdown! during component destruction.
|
|
165
|
+
# Unlike {#stop!}, this is not reversible.
|
|
102
166
|
#
|
|
103
167
|
# Does not clear out the code tracker, because it's only populated
|
|
104
168
|
# by code when code is compiled and therefore, if the code tracker
|
|
@@ -107,21 +171,31 @@ module Datadog
|
|
|
107
171
|
def shutdown!(replacement = nil)
|
|
108
172
|
DI.remove_current_component(self)
|
|
109
173
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
174
|
+
# Hold the lifecycle mutex so all transitions of @started are
|
|
175
|
+
# serialized — start! / stop! / shutdown! cannot interleave with
|
|
176
|
+
# one another. Without the mutex an in-flight stop! from an RC
|
|
177
|
+
# callback could complete after shutdown!'s probe_manager.close,
|
|
178
|
+
# producing an inconsistent state.
|
|
179
|
+
@lifecycle_mutex.synchronize do
|
|
180
|
+
@started = false
|
|
181
|
+
probe_manager.clear_hooks
|
|
182
|
+
probe_manager.close
|
|
183
|
+
probe_notifier_worker.stop
|
|
184
|
+
end
|
|
113
185
|
end
|
|
114
186
|
|
|
115
187
|
def parse_probe_spec_and_notify(probe_spec)
|
|
116
|
-
probe = ProbeBuilder.build_from_remote_config(probe_spec)
|
|
117
|
-
rescue => exc
|
|
188
|
+
probe = ProbeBuilder.build_from_remote_config(probe_spec, logger: logger)
|
|
189
|
+
rescue Exception => exc # standard:disable Lint/RescueException
|
|
190
|
+
Datadog::DI.reraise_if_fatal(exc)
|
|
118
191
|
begin
|
|
119
192
|
probe = Struct.new(:id).new(
|
|
120
193
|
probe_spec['id'],
|
|
121
194
|
)
|
|
122
195
|
payload = probe_notification_builder.build_errored(probe, exc)
|
|
123
196
|
probe_notifier_worker.add_status(payload)
|
|
124
|
-
rescue => nested_exc
|
|
197
|
+
rescue Exception => nested_exc # standard:disable Lint/RescueException
|
|
198
|
+
Datadog::DI.reraise_if_fatal(nested_exc)
|
|
125
199
|
logger.debug { "di: failed to build error notification: #{nested_exc.class}: #{nested_exc.message}" }
|
|
126
200
|
telemetry&.report(nested_exc, description: 'Error building probe error notification')
|
|
127
201
|
raise
|
|
@@ -134,6 +134,12 @@ module Datadog
|
|
|
134
134
|
o.default 20
|
|
135
135
|
end
|
|
136
136
|
|
|
137
|
+
option :max_time_to_serialize_ms do |o|
|
|
138
|
+
o.type :int
|
|
139
|
+
o.default 200
|
|
140
|
+
o.env 'DD_DYNAMIC_INSTRUMENTATION_MAX_TIME_TO_SERIALIZE'
|
|
141
|
+
end
|
|
142
|
+
|
|
137
143
|
# Settings in the 'internal' group are for internal Datadog
|
|
138
144
|
# use only, and are needed to test dynamic instrumentation or
|
|
139
145
|
# experiment with features not released to customers.
|
data/lib/datadog/di/context.rb
CHANGED
|
@@ -14,6 +14,8 @@ module Datadog
|
|
|
14
14
|
target_self: nil,
|
|
15
15
|
path: nil, caller_locations: nil,
|
|
16
16
|
serialized_entry_args: nil,
|
|
17
|
+
entry_capture_expressions: nil,
|
|
18
|
+
entry_capture_evaluation_errors: nil,
|
|
17
19
|
return_value: nil, duration: nil, exception: nil)
|
|
18
20
|
@probe = probe
|
|
19
21
|
@settings = settings
|
|
@@ -23,6 +25,8 @@ module Datadog
|
|
|
23
25
|
@path = path
|
|
24
26
|
@caller_locations = caller_locations
|
|
25
27
|
@serialized_entry_args = serialized_entry_args
|
|
28
|
+
@entry_capture_expressions = entry_capture_expressions
|
|
29
|
+
@entry_capture_evaluation_errors = entry_capture_evaluation_errors
|
|
26
30
|
@return_value = return_value
|
|
27
31
|
@duration = duration
|
|
28
32
|
@exception = exception
|
|
@@ -44,6 +48,10 @@ module Datadog
|
|
|
44
48
|
|
|
45
49
|
attr_reader :serialized_entry_args
|
|
46
50
|
|
|
51
|
+
attr_reader :entry_capture_expressions
|
|
52
|
+
|
|
53
|
+
attr_reader :entry_capture_evaluation_errors
|
|
54
|
+
|
|
47
55
|
# Return value for the method, for a method probe
|
|
48
56
|
attr_reader :return_value
|
|
49
57
|
|
|
@@ -55,9 +63,7 @@ module Datadog
|
|
|
55
63
|
|
|
56
64
|
def serialized_locals
|
|
57
65
|
# TODO cache?
|
|
58
|
-
locals && serializer.serialize_vars(locals,
|
|
59
|
-
depth: probe.max_capture_depth || settings.dynamic_instrumentation.max_capture_depth,
|
|
60
|
-
attribute_count: probe.max_capture_attribute_count || settings.dynamic_instrumentation.max_capture_attribute_count,)
|
|
66
|
+
locals && serializer.serialize_vars(locals, **probe.snapshot_serializer_limits(settings))
|
|
61
67
|
end
|
|
62
68
|
|
|
63
69
|
def fetch(var_name)
|
|
@@ -78,7 +78,7 @@ module Datadog
|
|
|
78
78
|
# We could format to a string here but what if customer
|
|
79
79
|
# has @duration as part of an expression and wants
|
|
80
80
|
# to retain it as a number?
|
|
81
|
-
"(context.duration * 1000)"
|
|
81
|
+
"(context.duration && context.duration * 1000)"
|
|
82
82
|
when '@exception'
|
|
83
83
|
"context.exception"
|
|
84
84
|
else
|
data/lib/datadog/di/error.rb
CHANGED
|
@@ -18,6 +18,10 @@ module Datadog
|
|
|
18
18
|
class MissingLineNumber < Error
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
+
# Probe does not contain a method name (i.e., is not a method probe).
|
|
22
|
+
class MissingMethodName < Error
|
|
23
|
+
end
|
|
24
|
+
|
|
21
25
|
# Failed to communicate to the local Datadog agent (e.g. to send
|
|
22
26
|
# probe status or a snapshot).
|
|
23
27
|
class AgentCommunicationError < Error
|
|
@@ -47,6 +51,12 @@ module Datadog
|
|
|
47
51
|
class AlreadyInstrumented < Error
|
|
48
52
|
end
|
|
49
53
|
|
|
54
|
+
# Raised when a probe targets a class or module that the tracer
|
|
55
|
+
# refuses to instrument (for example, anything in the Datadog
|
|
56
|
+
# namespace, which the tracer itself uses internally).
|
|
57
|
+
class ProbeTargetForbidden < Error
|
|
58
|
+
end
|
|
59
|
+
|
|
50
60
|
# Raised when installing a line probe and multiple files match the
|
|
51
61
|
# specified path suffix.
|
|
52
62
|
# A probe must be installed into one file only, since UI only
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Defined under DI rather than Core because the DI preload path
|
|
4
|
+
# (datadog/di/preload -> base) activates code tracking before the rest of the
|
|
5
|
+
# library, including Datadog::Core, is loaded. Catch-all rescues on that path
|
|
6
|
+
# must be able to re-raise fatal exceptions without referencing Core.
|
|
7
|
+
|
|
8
|
+
module Datadog
|
|
9
|
+
module DI
|
|
10
|
+
# Exception classes that catch-all rescues must never swallow: they signal
|
|
11
|
+
# that the process is being torn down or has run out of memory and have to
|
|
12
|
+
# propagate. SignalException covers Interrupt (Ctrl+C) and every other
|
|
13
|
+
# signal delivered as an exception.
|
|
14
|
+
FATAL_EXCEPTION_CLASSES = [SystemExit, SignalException, NoMemoryError].freeze
|
|
15
|
+
|
|
16
|
+
# Re-raise +exc+ when it is fatal (see FATAL_EXCEPTION_CLASSES). Call this as
|
|
17
|
+
# the first statement of a `rescue Exception` handler so that fatal
|
|
18
|
+
# conditions are not accidentally swallowed by a broad rescue.
|
|
19
|
+
#
|
|
20
|
+
# @param exc [Exception] the currently-handled exception
|
|
21
|
+
# @return [nil] when +exc+ is not fatal; otherwise re-raises +exc+
|
|
22
|
+
def self.reraise_if_fatal(exc)
|
|
23
|
+
raise exc if FATAL_EXCEPTION_CLASSES.any? { |klass| exc.is_a?(klass) }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|