datadog 2.7.1 → 2.9.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 +69 -1
- data/ext/datadog_profiling_native_extension/clock_id.h +2 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +64 -54
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +1 -1
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +16 -16
- data/ext/datadog_profiling_native_extension/collectors_stack.c +7 -7
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +259 -132
- data/ext/datadog_profiling_native_extension/extconf.rb +0 -8
- data/ext/datadog_profiling_native_extension/heap_recorder.c +11 -89
- data/ext/datadog_profiling_native_extension/heap_recorder.h +1 -1
- data/ext/datadog_profiling_native_extension/http_transport.c +4 -4
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +4 -1
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +3 -1
- data/ext/datadog_profiling_native_extension/profiling.c +10 -8
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +8 -8
- data/ext/datadog_profiling_native_extension/stack_recorder.c +54 -88
- data/ext/datadog_profiling_native_extension/stack_recorder.h +1 -1
- data/ext/datadog_profiling_native_extension/time_helpers.h +1 -1
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +47 -0
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +31 -0
- data/ext/libdatadog_api/crashtracker.c +3 -0
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +355 -157
- data/lib/datadog/appsec/assets/waf_rules/strict.json +62 -32
- data/lib/datadog/appsec/component.rb +1 -8
- data/lib/datadog/appsec/context.rb +54 -0
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +73 -0
- data/lib/datadog/appsec/contrib/active_record/integration.rb +41 -0
- data/lib/datadog/appsec/contrib/active_record/patcher.rb +53 -0
- data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +6 -6
- data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +4 -4
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +19 -28
- data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +5 -5
- data/lib/datadog/appsec/contrib/rack/gateway/response.rb +3 -3
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +64 -96
- data/lib/datadog/appsec/contrib/rack/reactive/request.rb +10 -10
- data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +5 -5
- data/lib/datadog/appsec/contrib/rack/reactive/response.rb +6 -6
- data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +10 -11
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +43 -49
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +21 -32
- data/lib/datadog/appsec/contrib/rails/patcher.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/reactive/action.rb +6 -6
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +41 -63
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +2 -2
- data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +5 -5
- data/lib/datadog/appsec/event.rb +6 -6
- data/lib/datadog/appsec/ext.rb +3 -1
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +22 -32
- data/lib/datadog/appsec/monitor/reactive/set_user.rb +5 -5
- data/lib/datadog/appsec/processor/context.rb +2 -2
- data/lib/datadog/appsec/processor/rule_loader.rb +0 -3
- data/lib/datadog/appsec/remote.rb +1 -3
- data/lib/datadog/appsec/response.rb +7 -11
- data/lib/datadog/appsec.rb +6 -5
- data/lib/datadog/auto_instrument.rb +3 -0
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +39 -11
- data/lib/datadog/core/configuration/components.rb +20 -2
- data/lib/datadog/core/configuration/settings.rb +10 -0
- data/lib/datadog/core/configuration.rb +10 -2
- data/lib/datadog/{tracing → core}/contrib/rails/utils.rb +1 -3
- data/lib/datadog/core/crashtracking/component.rb +1 -3
- data/lib/datadog/core/remote/client/capabilities.rb +6 -0
- data/lib/datadog/core/remote/client.rb +65 -59
- data/lib/datadog/core/telemetry/component.rb +9 -3
- data/lib/datadog/core/telemetry/event.rb +87 -3
- data/lib/datadog/core/telemetry/ext.rb +1 -0
- data/lib/datadog/core/telemetry/logging.rb +2 -2
- data/lib/datadog/core/telemetry/metric.rb +22 -0
- data/lib/datadog/core/telemetry/worker.rb +33 -0
- data/lib/datadog/di/base.rb +115 -0
- data/lib/datadog/di/code_tracker.rb +11 -7
- data/lib/datadog/di/component.rb +21 -11
- data/lib/datadog/di/configuration/settings.rb +11 -1
- data/lib/datadog/di/contrib/active_record.rb +1 -0
- data/lib/datadog/di/contrib/railtie.rb +15 -0
- data/lib/datadog/di/contrib.rb +26 -0
- data/lib/datadog/di/error.rb +5 -0
- data/lib/datadog/di/instrumenter.rb +111 -20
- data/lib/datadog/di/preload.rb +18 -0
- data/lib/datadog/di/probe.rb +11 -1
- data/lib/datadog/di/probe_builder.rb +1 -0
- data/lib/datadog/di/probe_manager.rb +8 -5
- data/lib/datadog/di/probe_notification_builder.rb +27 -7
- data/lib/datadog/di/probe_notifier_worker.rb +5 -6
- data/lib/datadog/di/remote.rb +124 -0
- data/lib/datadog/di/serializer.rb +14 -7
- data/lib/datadog/di/transport.rb +3 -5
- data/lib/datadog/di/utils.rb +7 -0
- data/lib/datadog/di.rb +23 -62
- data/lib/datadog/kit/appsec/events.rb +3 -3
- data/lib/datadog/kit/identity.rb +4 -4
- data/lib/datadog/profiling/component.rb +59 -69
- data/lib/datadog/profiling/http_transport.rb +1 -26
- data/lib/datadog/tracing/configuration/settings.rb +4 -8
- data/lib/datadog/tracing/contrib/action_cable/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/action_mailer/integration.rb +6 -2
- data/lib/datadog/tracing/contrib/action_pack/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/action_view/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/active_job/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/active_record/integration.rb +6 -2
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +3 -1
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +3 -1
- data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +16 -4
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +10 -0
- data/lib/datadog/tracing/contrib/active_support/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/auto_instrument.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +4 -0
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
- data/lib/datadog/tracing/contrib/httprb/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/kafka/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/mongodb/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/opensearch/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/presto/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/rack/integration.rb +2 -2
- data/lib/datadog/tracing/contrib/rails/framework.rb +2 -2
- data/lib/datadog/tracing/contrib/rails/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/rest_client/integration.rb +3 -0
- data/lib/datadog/tracing/span.rb +12 -4
- data/lib/datadog/tracing/span_event.rb +123 -3
- data/lib/datadog/tracing/span_operation.rb +6 -0
- data/lib/datadog/tracing/transport/serializable_trace.rb +24 -6
- data/lib/datadog/version.rb +2 -2
- data/lib/datadog.rb +3 -0
- metadata +30 -17
- data/lib/datadog/appsec/processor/actions.rb +0 -49
- data/lib/datadog/appsec/reactive/operation.rb +0 -68
- data/lib/datadog/appsec/scope.rb +0 -58
- data/lib/datadog/core/crashtracking/agent_base_url.rb +0 -21
@@ -32,7 +32,7 @@ module Datadog
|
|
32
32
|
install_pending_method_probes(tp.self)
|
33
33
|
rescue => exc
|
34
34
|
raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
35
|
-
logger.
|
35
|
+
logger.debug { "di: unhandled exception in definition trace point: #{exc.class}: #{exc}" }
|
36
36
|
telemetry&.report(exc, description: "Unhandled exception in definition trace point")
|
37
37
|
# TODO test this path
|
38
38
|
end
|
@@ -120,7 +120,7 @@ module Datadog
|
|
120
120
|
# In "propagate all exceptions" mode we will try to instrument again.
|
121
121
|
raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
122
122
|
|
123
|
-
logger.
|
123
|
+
logger.debug { "di: error processing probe configuration: #{exc.class}: #{exc}" }
|
124
124
|
telemetry&.report(exc, description: "Error processing probe configuration")
|
125
125
|
# TODO report probe as failed to agent since we won't attempt to
|
126
126
|
# install it again.
|
@@ -160,8 +160,8 @@ module Datadog
|
|
160
160
|
raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
161
161
|
# Silence all exceptions?
|
162
162
|
# TODO should we propagate here and rescue upstream?
|
163
|
-
logger.
|
164
|
-
telemetry&.report(exc, description: "Error removing probe
|
163
|
+
logger.debug { "di: error removing probe #{probe.id}: #{exc.class}: #{exc}" }
|
164
|
+
telemetry&.report(exc, description: "Error removing probe")
|
165
165
|
end
|
166
166
|
end
|
167
167
|
end
|
@@ -190,7 +190,7 @@ module Datadog
|
|
190
190
|
rescue => exc
|
191
191
|
raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
192
192
|
|
193
|
-
logger.
|
193
|
+
logger.debug { "di: error installing probe after class is defined: #{exc.class}: #{exc}" }
|
194
194
|
telemetry&.report(exc, description: "Error installing probe after class is defined")
|
195
195
|
end
|
196
196
|
end
|
@@ -206,6 +206,9 @@ module Datadog
|
|
206
206
|
# point, which is invoked for each required or loaded file
|
207
207
|
# (and also for eval'd code, but those invocations are filtered out).
|
208
208
|
def install_pending_line_probes(path)
|
209
|
+
if path.nil?
|
210
|
+
raise ArgumentError, "path must not be nil"
|
211
|
+
end
|
209
212
|
@lock.synchronize do
|
210
213
|
@pending_probes.values.each do |probe|
|
211
214
|
if probe.line?
|
@@ -65,14 +65,18 @@ module Datadog
|
|
65
65
|
arguments: if serialized_entry_args
|
66
66
|
serialized_entry_args
|
67
67
|
else
|
68
|
-
(args || kwargs) && serializer.serialize_args(args, kwargs
|
68
|
+
(args || kwargs) && serializer.serialize_args(args, kwargs,
|
69
|
+
depth: probe.max_capture_depth || settings.dynamic_instrumentation.max_capture_depth,
|
70
|
+
attribute_count: probe.max_capture_attribute_count || settings.dynamic_instrumentation.max_capture_attribute_count)
|
69
71
|
end,
|
70
72
|
throwable: nil,
|
71
73
|
# standard:enable all
|
72
74
|
},
|
73
75
|
return: {
|
74
76
|
arguments: {
|
75
|
-
"@return": serializer.serialize_value(rv
|
77
|
+
"@return": serializer.serialize_value(rv,
|
78
|
+
depth: probe.max_capture_depth || settings.dynamic_instrumentation.max_capture_depth,
|
79
|
+
attribute_count: probe.max_capture_attribute_count || settings.dynamic_instrumentation.max_capture_attribute_count),
|
76
80
|
},
|
77
81
|
throwable: nil,
|
78
82
|
},
|
@@ -80,7 +84,9 @@ module Datadog
|
|
80
84
|
elsif probe.line?
|
81
85
|
{
|
82
86
|
lines: snapshot && {
|
83
|
-
probe.line_no => {locals: serializer.serialize_vars(snapshot
|
87
|
+
probe.line_no => {locals: serializer.serialize_vars(snapshot,
|
88
|
+
depth: probe.max_capture_depth || settings.dynamic_instrumentation.max_capture_depth,
|
89
|
+
attribute_count: probe.max_capture_attribute_count || settings.dynamic_instrumentation.max_capture_attribute_count,)},
|
84
90
|
},
|
85
91
|
}
|
86
92
|
end
|
@@ -121,7 +127,7 @@ module Datadog
|
|
121
127
|
},
|
122
128
|
# In python tracer duration is under debugger.snapshot,
|
123
129
|
# but UI appears to expect it here at top level.
|
124
|
-
duration: duration ? (duration * 10**9).to_i :
|
130
|
+
duration: duration ? (duration * 10**9).to_i : 0,
|
125
131
|
host: nil,
|
126
132
|
logger: {
|
127
133
|
name: probe.file,
|
@@ -135,15 +141,17 @@ module Datadog
|
|
135
141
|
version: 2,
|
136
142
|
},
|
137
143
|
# TODO add tests that the trace/span id is correctly propagated
|
138
|
-
"dd.trace_id":
|
139
|
-
"dd.span_id":
|
144
|
+
"dd.trace_id": active_trace&.id&.to_s,
|
145
|
+
"dd.span_id": active_span&.id&.to_s,
|
140
146
|
ddsource: 'dd_debugger',
|
141
147
|
message: probe.template && evaluate_template(probe.template,
|
142
|
-
duration: duration ? duration * 1000 :
|
148
|
+
duration: duration ? duration * 1000 : 0),
|
143
149
|
timestamp: timestamp,
|
144
150
|
}
|
145
151
|
end
|
146
152
|
|
153
|
+
private
|
154
|
+
|
147
155
|
def build_status(probe, message:, status:)
|
148
156
|
{
|
149
157
|
service: settings.service,
|
@@ -194,6 +202,18 @@ module Datadog
|
|
194
202
|
map[name] = value
|
195
203
|
end
|
196
204
|
end
|
205
|
+
|
206
|
+
def active_trace
|
207
|
+
if defined?(Datadog::Tracing)
|
208
|
+
Datadog::Tracing.active_trace
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def active_span
|
213
|
+
if defined?(Datadog::Tracing)
|
214
|
+
Datadog::Tracing.active_span
|
215
|
+
end
|
216
|
+
end
|
197
217
|
end
|
198
218
|
end
|
199
219
|
end
|
@@ -77,7 +77,7 @@ module Datadog
|
|
77
77
|
rescue => exc
|
78
78
|
raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
79
79
|
|
80
|
-
logger.
|
80
|
+
logger.debug { "di: error in probe notifier worker: #{exc.class}: #{exc} (at #{exc.backtrace.first})" }
|
81
81
|
telemetry&.report(exc, description: "Error in probe notifier worker")
|
82
82
|
end
|
83
83
|
@lock.synchronize do
|
@@ -183,9 +183,8 @@ module Datadog
|
|
183
183
|
define_method("add_#{event_type}") do |event|
|
184
184
|
@lock.synchronize do
|
185
185
|
queue = send("#{event_type}_queue")
|
186
|
-
|
187
|
-
|
188
|
-
logger.warn("#{self.class.name}: dropping #{event_type} because queue is full")
|
186
|
+
if queue.length > settings.dynamic_instrumentation.internal.snapshot_queue_capacity
|
187
|
+
logger.debug { "di: #{self.class.name}: dropping #{event_type} because queue is full" }
|
189
188
|
else
|
190
189
|
queue << event
|
191
190
|
end
|
@@ -242,7 +241,7 @@ module Datadog
|
|
242
241
|
end
|
243
242
|
rescue => exc
|
244
243
|
raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
245
|
-
logger.
|
244
|
+
logger.debug { "di: failed to send #{event_name}: #{exc.class}: #{exc} (at #{exc.backtrace.first})" }
|
246
245
|
# Should we report this error to telemetry? Most likely failure
|
247
246
|
# to send is due to a network issue, and trying to send a
|
248
247
|
# telemetry message would also fail.
|
@@ -253,7 +252,7 @@ module Datadog
|
|
253
252
|
# Normally the queue should only be consumed in this method,
|
254
253
|
# however if anyone consumes it elsewhere we don't want to block
|
255
254
|
# while consuming it here. Rescue ThreadError and return.
|
256
|
-
logger.
|
255
|
+
logger.debug { "di: unexpected #{event_name} queue underflow - consumed elsewhere?" }
|
257
256
|
telemetry&.report(exc, description: "Unexpected #{event_name} queue underflow")
|
258
257
|
ensure
|
259
258
|
@lock.synchronize do
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datadog
|
4
|
+
module DI
|
5
|
+
# Provides an interface expected by the core Remote subsystem to
|
6
|
+
# receive DI-specific remote configuration.
|
7
|
+
#
|
8
|
+
# In order to apply (i.e., act on) the configuration, we need the
|
9
|
+
# state stored under DI Component. Thus, this module forwards actual
|
10
|
+
# configuration application to the ProbeManager associated with the
|
11
|
+
# global DI Component.
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
module Remote
|
15
|
+
class ReadError < StandardError; end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
PRODUCT = 'LIVE_DEBUGGING'
|
19
|
+
|
20
|
+
def products
|
21
|
+
[PRODUCT]
|
22
|
+
end
|
23
|
+
|
24
|
+
def capabilities
|
25
|
+
[]
|
26
|
+
end
|
27
|
+
|
28
|
+
def receivers(telemetry)
|
29
|
+
receiver do |repository, _changes|
|
30
|
+
# DEV: Filter our by product. Given it will be very common
|
31
|
+
# DEV: we can filter this out before we receive the data in this method.
|
32
|
+
# DEV: Apply this refactor to AppSec as well if implemented.
|
33
|
+
|
34
|
+
component = DI.component
|
35
|
+
# We should always have a non-nil DI component here, because we
|
36
|
+
# only add DI product to remote config request if DI is enabled.
|
37
|
+
# Ideally, we should be injected with the DI component here
|
38
|
+
# rather than having to retrieve it from global state.
|
39
|
+
# If the component is nil for some reason, we also don't have a
|
40
|
+
# logger instance to report the issue.
|
41
|
+
if component
|
42
|
+
|
43
|
+
probe_manager = component.probe_manager
|
44
|
+
|
45
|
+
current_probe_ids = {}
|
46
|
+
repository.contents.each do |content|
|
47
|
+
case content.path.product
|
48
|
+
when PRODUCT
|
49
|
+
begin
|
50
|
+
probe_spec = parse_content(content)
|
51
|
+
probe = ProbeBuilder.build_from_remote_config(probe_spec)
|
52
|
+
payload = component.probe_notification_builder.build_received(probe)
|
53
|
+
component.probe_notifier_worker.add_status(payload)
|
54
|
+
component.logger.debug { "di: received probe from RC: #{probe.type} #{probe.location}" }
|
55
|
+
|
56
|
+
begin
|
57
|
+
# TODO test exception capture
|
58
|
+
probe_manager.add_probe(probe)
|
59
|
+
content.applied
|
60
|
+
rescue => exc
|
61
|
+
raise if component.settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
62
|
+
|
63
|
+
component.logger.debug { "di: unhandled exception adding probe in DI remote receiver: #{exc.class}: #{exc}" }
|
64
|
+
component.telemetry&.report(exc, description: "Unhandled exception adding probe in DI remote receiver")
|
65
|
+
|
66
|
+
# If a probe fails to install, we will mark the content
|
67
|
+
# as errored. On subsequent remote configuration application
|
68
|
+
# attemps, probe manager will raise the "previously errored"
|
69
|
+
# exception and we'll rescue it here, again marking the
|
70
|
+
# content as errored but with a somewhat different exception
|
71
|
+
# message.
|
72
|
+
# TODO stack trace must be redacted or not sent at all
|
73
|
+
content.errored("Error applying dynamic instrumentation configuration: #{exc.class.name} #{exc.message}: #{Array(exc.backtrace).join("\n")}")
|
74
|
+
end
|
75
|
+
|
76
|
+
# Important: even if processing fails for this probe config,
|
77
|
+
# we need to note it as being current so that we do not
|
78
|
+
# try to remove instrumentation that is still supposed to be
|
79
|
+
# active.
|
80
|
+
current_probe_ids[probe_spec.fetch('id')] = true
|
81
|
+
rescue => exc
|
82
|
+
raise if component.settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
83
|
+
|
84
|
+
component.logger.debug { "di: unhandled exception handling probe in DI remote receiver: #{exc.class}: #{exc}" }
|
85
|
+
component.telemetry&.report(exc, description: "Unhandled exception handling probe in DI remote receiver")
|
86
|
+
|
87
|
+
content.errored("Error applying dynamic instrumentation configuration: #{exc.class.name} #{exc.message}: #{Array(exc.backtrace).join("\n")}")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
begin
|
93
|
+
# TODO test exception capture
|
94
|
+
probe_manager.remove_other_probes(current_probe_ids.keys)
|
95
|
+
rescue => exc
|
96
|
+
raise if component.settings.dynamic_instrumentation.internal.propagate_all_exceptions
|
97
|
+
|
98
|
+
component.logger.debug { "di: unhandled exception removing probes in DI remote receiver: #{exc.class}: #{exc}" }
|
99
|
+
component.telemetry&.report(exc, description: "Unhandled exception removing probes in DI remote receiver")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def receiver(products = [PRODUCT], &block)
|
106
|
+
matcher = Core::Remote::Dispatcher::Matcher::Product.new(products)
|
107
|
+
[Core::Remote::Dispatcher::Receiver.new(matcher, &block)]
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def parse_content(content)
|
113
|
+
data = content.data.read
|
114
|
+
|
115
|
+
content.data.rewind
|
116
|
+
|
117
|
+
raise ReadError, 'EOF reached' if data.nil?
|
118
|
+
|
119
|
+
JSON.parse(data)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -82,7 +82,9 @@ module Datadog
|
|
82
82
|
# between positional and keyword arguments. We convert positional
|
83
83
|
# arguments to keyword arguments ("arg1", "arg2", ...) and ensure
|
84
84
|
# the positional arguments are listed first.
|
85
|
-
def serialize_args(args, kwargs
|
85
|
+
def serialize_args(args, kwargs,
|
86
|
+
depth: settings.dynamic_instrumentation.max_capture_depth,
|
87
|
+
attribute_count: settings.dynamic_instrumentation.max_capture_attribute_count)
|
86
88
|
counter = 0
|
87
89
|
combined = args.each_with_object({}) do |value, c|
|
88
90
|
counter += 1
|
@@ -90,16 +92,18 @@ module Datadog
|
|
90
92
|
# kwargs when they are merged below.
|
91
93
|
c[:"arg#{counter}"] = value
|
92
94
|
end.update(kwargs)
|
93
|
-
serialize_vars(combined)
|
95
|
+
serialize_vars(combined, depth: depth, attribute_count: attribute_count)
|
94
96
|
end
|
95
97
|
|
96
98
|
# Serializes variables captured by a line probe.
|
97
99
|
#
|
98
100
|
# These are normally local variables that exist on a particular line
|
99
101
|
# of executed code.
|
100
|
-
def serialize_vars(vars
|
102
|
+
def serialize_vars(vars,
|
103
|
+
depth: settings.dynamic_instrumentation.max_capture_depth,
|
104
|
+
attribute_count: settings.dynamic_instrumentation.max_capture_attribute_count)
|
101
105
|
vars.each_with_object({}) do |(k, v), agg|
|
102
|
-
agg[k] = serialize_value(v, name: k)
|
106
|
+
agg[k] = serialize_value(v, name: k, depth: depth, attribute_count: attribute_count)
|
103
107
|
end
|
104
108
|
end
|
105
109
|
|
@@ -115,7 +119,11 @@ module Datadog
|
|
115
119
|
# (integers, strings, arrays, hashes).
|
116
120
|
#
|
117
121
|
# Respects string length, collection size and traversal depth limits.
|
118
|
-
def serialize_value(value, name: nil,
|
122
|
+
def serialize_value(value, name: nil,
|
123
|
+
depth: settings.dynamic_instrumentation.max_capture_depth,
|
124
|
+
attribute_count: nil,
|
125
|
+
type: nil)
|
126
|
+
attribute_count ||= settings.dynamic_instrumentation.max_capture_attribute_count
|
119
127
|
cls = type || value.class
|
120
128
|
begin
|
121
129
|
if redactor.redact_type?(value)
|
@@ -203,7 +211,6 @@ module Datadog
|
|
203
211
|
serialized.update(notCapturedReason: "depth")
|
204
212
|
else
|
205
213
|
fields = {}
|
206
|
-
max = settings.dynamic_instrumentation.max_capture_attribute_count
|
207
214
|
cur = 0
|
208
215
|
|
209
216
|
# MRI and JRuby 9.4.5+ preserve instance variable definition
|
@@ -229,7 +236,7 @@ module Datadog
|
|
229
236
|
ivars = value.instance_variables
|
230
237
|
|
231
238
|
ivars.each do |ivar|
|
232
|
-
if cur >=
|
239
|
+
if cur >= attribute_count
|
233
240
|
serialized.update(notCapturedReason: "fieldCount", fields: fields)
|
234
241
|
break
|
235
242
|
end
|
data/lib/datadog/di/transport.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'ostruct'
|
4
3
|
require_relative 'error'
|
4
|
+
require_relative '../core/transport/http/adapters/net'
|
5
5
|
|
6
6
|
module Datadog
|
7
7
|
module DI
|
@@ -45,7 +45,7 @@ module Datadog
|
|
45
45
|
|
46
46
|
def send_input(payload)
|
47
47
|
send_request('Probe snapshot submission',
|
48
|
-
path: INPUT_PATH, body: payload.
|
48
|
+
path: INPUT_PATH, body: payload.to_json,
|
49
49
|
headers: {'content-type' => 'application/json'},)
|
50
50
|
end
|
51
51
|
|
@@ -60,9 +60,7 @@ module Datadog
|
|
60
60
|
attr_reader :client
|
61
61
|
|
62
62
|
def send_request(desc, **options)
|
63
|
-
|
64
|
-
env = OpenStruct.new(**options)
|
65
|
-
# steep:ignore:end
|
63
|
+
env = Core::Transport::HTTP::Env.new(nil, options)
|
66
64
|
response = client.post(env)
|
67
65
|
unless response.ok?
|
68
66
|
raise Error::AgentCommunicationError, "#{desc} failed: #{response.code}: #{response.payload}"
|
data/lib/datadog/di/utils.rb
CHANGED
@@ -12,6 +12,13 @@ module Datadog
|
|
12
12
|
# If suffix is not an absolute path, the path matches if its suffix is
|
13
13
|
# the provided suffix, at a path component boundary.
|
14
14
|
module_function def path_matches_suffix?(path, suffix)
|
15
|
+
if path.nil?
|
16
|
+
raise ArgumentError, "nil path passed"
|
17
|
+
end
|
18
|
+
if suffix.nil?
|
19
|
+
raise ArgumentError, "nil suffix passed"
|
20
|
+
end
|
21
|
+
|
15
22
|
if suffix.start_with?('/')
|
16
23
|
path == suffix
|
17
24
|
else
|
data/lib/datadog/di.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'di/base'
|
3
4
|
require_relative 'di/error'
|
4
5
|
require_relative 'di/code_tracker'
|
5
6
|
require_relative 'di/component'
|
@@ -12,22 +13,11 @@ require_relative 'di/probe_manager'
|
|
12
13
|
require_relative 'di/probe_notification_builder'
|
13
14
|
require_relative 'di/probe_notifier_worker'
|
14
15
|
require_relative 'di/redactor'
|
16
|
+
require_relative 'di/remote'
|
15
17
|
require_relative 'di/serializer'
|
16
18
|
require_relative 'di/transport'
|
17
19
|
require_relative 'di/utils'
|
18
20
|
|
19
|
-
if defined?(ActiveRecord::Base)
|
20
|
-
# The third-party library integrations need to be loaded after the
|
21
|
-
# third-party libraries are loaded. Tracing and appsec use Railtie
|
22
|
-
# to delay integrations until all of the application's dependencies
|
23
|
-
# are loaded, when running under Rails. We should do the same here in
|
24
|
-
# principle, however DI currently only has an ActiveRecord integration
|
25
|
-
# and AR should be loaded before any application code is loaded, being
|
26
|
-
# part of Rails, therefore for now we should be OK to just require the
|
27
|
-
# AR integration from here.
|
28
|
-
require_relative 'di/contrib/active_record'
|
29
|
-
end
|
30
|
-
|
31
21
|
module Datadog
|
32
22
|
# Namespace for Datadog dynamic instrumentation.
|
33
23
|
#
|
@@ -43,63 +33,34 @@ module Datadog
|
|
43
33
|
Extensions.activate!
|
44
34
|
|
45
35
|
class << self
|
46
|
-
attr_reader :code_tracker
|
47
36
|
|
48
|
-
#
|
49
|
-
#
|
50
|
-
# code tracking needs to be enabled before the third-party libraries
|
51
|
-
# are loaded. If you definitely will not be instrumenting
|
52
|
-
# third-party libraries, activating tracking after third-party libraries
|
53
|
-
# have been loaded may improve lookup performance.
|
37
|
+
# This method is called from DI Remote handler to issue DI operations
|
38
|
+
# to the probe manager (add or remove probes).
|
54
39
|
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
def activate_tracking!
|
58
|
-
(@code_tracker ||= CodeTracker.new).start
|
59
|
-
end
|
60
|
-
|
61
|
-
# Deactivates code tracking. In normal usage of DI this method should
|
62
|
-
# never be called, however it is used by DI's test suite to reset
|
63
|
-
# state for individual tests.
|
40
|
+
# When DI Remote is executing, Datadog.components should be initialized
|
41
|
+
# and we should be able to reference it to get to the DI component.
|
64
42
|
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
def deactivate_tracking!
|
69
|
-
code_tracker&.stop
|
70
|
-
end
|
71
|
-
|
72
|
-
# Returns whether code tracking is available.
|
73
|
-
# This method should be used instead of querying #code_tracker
|
74
|
-
# because the latter one may be nil.
|
75
|
-
def code_tracking_active?
|
76
|
-
code_tracker&.active? || false
|
77
|
-
end
|
78
|
-
|
43
|
+
# Given that we need the current_component anyway for code tracker,
|
44
|
+
# perhaps we should delete the +component+ method and just use
|
45
|
+
# +current_component+ in all cases.
|
79
46
|
def component
|
80
|
-
|
81
|
-
#Datadog.send(:components).dynamic_instrumentation
|
47
|
+
Datadog.send(:components).dynamic_instrumentation
|
82
48
|
end
|
83
49
|
end
|
84
50
|
end
|
85
51
|
end
|
86
52
|
|
87
|
-
|
88
|
-
#
|
89
|
-
if
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
Datadog.logger.warn("Failed to activate code tracking for DI: #{exc.class}: #{exc}")
|
97
|
-
else
|
98
|
-
# We do not have Datadog logger potentially because DI code tracker is
|
99
|
-
# being loaded early in application boot process and the rest of datadog
|
100
|
-
# wasn't loaded yet. Output to standard error.
|
101
|
-
warn("Failed to activate code tracking for DI: #{exc.class}: #{exc}")
|
102
|
-
end
|
103
|
-
end
|
53
|
+
if %w(1 true).include?(ENV['DD_DYNAMIC_INSTRUMENTATION_ENABLED']) # steep:ignore
|
54
|
+
# For initial release of Dynamic Instrumentation, activate code tracking
|
55
|
+
# only if DI is explicitly requested in the environment.
|
56
|
+
# Code tracking is required for line probes to work; see the comments
|
57
|
+
# above for the implementation of the method.
|
58
|
+
#
|
59
|
+
# If DI is enabled programmatically, the application can (and must,
|
60
|
+
# for line probes to work) activate tracking in an initializer.
|
61
|
+
Datadog::DI.activate_tracking
|
104
62
|
end
|
105
|
-
|
63
|
+
|
64
|
+
require_relative 'di/contrib'
|
65
|
+
|
66
|
+
Datadog::DI::Contrib.load_now_or_later
|
@@ -136,9 +136,9 @@ module Datadog
|
|
136
136
|
private
|
137
137
|
|
138
138
|
def set_trace_and_span_context(method, trace = nil, span = nil)
|
139
|
-
if (
|
140
|
-
trace =
|
141
|
-
span =
|
139
|
+
if (appsec_context = Datadog::AppSec.active_context)
|
140
|
+
trace = appsec_context.trace
|
141
|
+
span = appsec_context.span
|
142
142
|
end
|
143
143
|
|
144
144
|
trace ||= Datadog::Tracing.active_trace
|
data/lib/datadog/kit/identity.rb
CHANGED
@@ -66,7 +66,7 @@ module Datadog
|
|
66
66
|
active_span.set_tag("usr.#{k}", v) unless v.nil?
|
67
67
|
end
|
68
68
|
|
69
|
-
if Datadog::AppSec.
|
69
|
+
if Datadog::AppSec.active_context
|
70
70
|
user = ::Datadog::AppSec::Instrumentation::Gateway::User.new(id)
|
71
71
|
::Datadog::AppSec::Instrumentation.gateway.push('identity.set_user', user)
|
72
72
|
end
|
@@ -78,9 +78,9 @@ module Datadog
|
|
78
78
|
private
|
79
79
|
|
80
80
|
def set_trace_and_span_context(method, trace = nil, span = nil)
|
81
|
-
if (
|
82
|
-
trace =
|
83
|
-
span =
|
81
|
+
if (appsec_context = Datadog::AppSec.active_context)
|
82
|
+
trace = appsec_context.trace
|
83
|
+
span = appsec_context.span
|
84
84
|
end
|
85
85
|
|
86
86
|
trace ||= Datadog::Tracing.active_trace
|