datadog 2.45.0 → 2.46.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 +25 -2
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +4 -0
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +2 -0
- data/ext/datadog_profiling_native_extension/profiling.c +6 -0
- data/ext/libdatadog_api/di.c +30 -5
- data/ext/libdatadog_api/extconf.rb +2 -0
- data/ext/libdatadog_api/otel_thread_context.c +20 -14
- data/ext/libdatadog_api/process_discovery.c +15 -1
- data/ext/libdatadog_api/trace_exporter.c +105 -25
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/core/configuration/components.rb +29 -8
- data/lib/datadog/core/configuration/supported_configurations.rb +5 -2
- data/lib/datadog/core/process_discovery.rb +5 -1
- data/lib/datadog/core/remote/client/capabilities.rb +34 -29
- data/lib/datadog/core/remote/component.rb +28 -12
- data/lib/datadog/core/remote/dispatcher.rb +13 -3
- data/lib/datadog/di/boot.rb +1 -0
- data/lib/datadog/di/capture_expression_evaluator/result.rb +30 -0
- data/lib/datadog/di/capture_expression_evaluator.rb +39 -9
- data/lib/datadog/di/component.rb +38 -3
- data/lib/datadog/di/configuration.rb +53 -2
- data/lib/datadog/di/context.rb +7 -2
- data/lib/datadog/di/contrib/active_record.rb +8 -2
- data/lib/datadog/di/evaluation_failure.rb +28 -0
- data/lib/datadog/di/guardrails_telemetry/reason.rb +87 -0
- data/lib/datadog/di/guardrails_telemetry.rb +203 -0
- data/lib/datadog/di/instrumenter.rb +65 -15
- data/lib/datadog/di/logger.rb +30 -8
- data/lib/datadog/di/probe_manager.rb +48 -5
- data/lib/datadog/di/probe_notification_builder.rb +28 -26
- data/lib/datadog/di/probe_notifier_worker.rb +56 -6
- data/lib/datadog/di/serializer.rb +130 -54
- data/lib/datadog/di/snapshot_event.rb +38 -0
- data/lib/datadog/di/transport/http.rb +13 -3
- data/lib/datadog/di/transport/input.rb +32 -7
- data/lib/datadog/open_feature/activation.rb +268 -0
- data/lib/datadog/open_feature/component.rb +31 -15
- data/lib/datadog/open_feature/provider.rb +282 -5
- data/lib/datadog/open_feature.rb +31 -1
- data/lib/datadog/tracing/component.rb +14 -0
- data/lib/datadog/tracing/configuration/settings.rb +3 -1
- data/lib/datadog/tracing/otel_thread_context.rb +3 -5
- data/lib/datadog/tracing/transport/http/telemetry.rb +94 -0
- data/lib/datadog/tracing/transport/http/traces.rb +2 -0
- data/lib/datadog/tracing/transport/native/telemetry.rb +17 -0
- data/lib/datadog/tracing/transport/native.rb +16 -1
- data/lib/datadog/tracing/transport/telemetry.rb +62 -0
- data/lib/datadog/tracing/transport/traces.rb +82 -15
- data/lib/datadog/version.rb +1 -1
- metadata +16 -7
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
# rubocop:disable Lint/AssignmentInCondition
|
|
4
4
|
|
|
5
|
+
require_relative "evaluation_failure"
|
|
5
6
|
require_relative "fatal_exceptions"
|
|
6
|
-
require_relative "capture_expression_evaluator"
|
|
7
7
|
|
|
8
8
|
module Datadog
|
|
9
9
|
module DI
|
|
@@ -11,14 +11,18 @@ module Datadog
|
|
|
11
11
|
#
|
|
12
12
|
# @api private
|
|
13
13
|
class ProbeNotificationBuilder
|
|
14
|
-
|
|
14
|
+
# Initializes the builder.
|
|
15
|
+
#
|
|
16
|
+
# @param settings [Datadog::Core::Configuration::Settings] tracer settings
|
|
17
|
+
# @param serializer [Serializer] serializer for captured values
|
|
18
|
+
# @param logger [DI::Logger] logger for builder diagnostics
|
|
19
|
+
# @param capture_expression_evaluator [CaptureExpressionEvaluator] evaluator for the probe's capture expressions
|
|
20
|
+
# @return [void]
|
|
21
|
+
def initialize(settings, serializer, logger, capture_expression_evaluator:)
|
|
15
22
|
@settings = settings
|
|
16
23
|
@serializer = serializer
|
|
17
24
|
@logger = logger
|
|
18
|
-
@
|
|
19
|
-
@capture_expression_evaluator = CaptureExpressionEvaluator.new(
|
|
20
|
-
settings: settings, serializer: serializer, logger: logger, telemetry: telemetry,
|
|
21
|
-
)
|
|
25
|
+
@capture_expression_evaluator = capture_expression_evaluator
|
|
22
26
|
end
|
|
23
27
|
|
|
24
28
|
attr_reader :settings
|
|
@@ -27,8 +31,6 @@ module Datadog
|
|
|
27
31
|
|
|
28
32
|
attr_reader :logger
|
|
29
33
|
|
|
30
|
-
attr_reader :telemetry
|
|
31
|
-
|
|
32
34
|
attr_reader :capture_expression_evaluator
|
|
33
35
|
|
|
34
36
|
def build_received(probe)
|
|
@@ -53,7 +55,7 @@ module Datadog
|
|
|
53
55
|
build_status(probe,
|
|
54
56
|
message: "Instrumentation for probe #{probe.id} failed: #{exc}",
|
|
55
57
|
status: "ERROR",
|
|
56
|
-
exception: exc)
|
|
58
|
+
exception: exc,)
|
|
57
59
|
end
|
|
58
60
|
|
|
59
61
|
def build_disabled(probe, duration)
|
|
@@ -83,10 +85,11 @@ module Datadog
|
|
|
83
85
|
capture_expression_evaluation_errors = []
|
|
84
86
|
captures = if probe.capture_snapshot?
|
|
85
87
|
snapshot_limits = probe.snapshot_serializer_limits(settings)
|
|
88
|
+
serialization_deadline = serializer.serialization_deadline
|
|
86
89
|
if probe.method?
|
|
87
90
|
return_arguments = {
|
|
88
|
-
"@return": serializer.serialize_value(context.return_value, **snapshot_limits),
|
|
89
|
-
self: serializer.serialize_value(context.target_self, **snapshot_limits),
|
|
91
|
+
"@return": serializer.serialize_value(context.return_value, deadline: serialization_deadline, **snapshot_limits),
|
|
92
|
+
self: serializer.serialize_value(context.target_self, deadline: serialization_deadline, **snapshot_limits),
|
|
90
93
|
}
|
|
91
94
|
{
|
|
92
95
|
entry: {
|
|
@@ -99,10 +102,10 @@ module Datadog
|
|
|
99
102
|
}
|
|
100
103
|
elsif probe.line?
|
|
101
104
|
{
|
|
102
|
-
lines: (locals = context.serialized_locals) && {
|
|
105
|
+
lines: (locals = context.serialized_locals(serialization_deadline: serialization_deadline)) && {
|
|
103
106
|
probe.line_no => {
|
|
104
107
|
locals: locals,
|
|
105
|
-
arguments: {self: serializer.serialize_value(context.target_self, **snapshot_limits)},
|
|
108
|
+
arguments: {self: serializer.serialize_value(context.target_self, deadline: serialization_deadline, **snapshot_limits)},
|
|
106
109
|
},
|
|
107
110
|
},
|
|
108
111
|
}
|
|
@@ -116,8 +119,9 @@ module Datadog
|
|
|
116
119
|
entry: {captureExpressions: captured_block},
|
|
117
120
|
}
|
|
118
121
|
else
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
capture_evaluation_result = capture_expression_evaluator.evaluate(probe, context)
|
|
123
|
+
captured_block = capture_evaluation_result.serialized_values
|
|
124
|
+
capture_expression_evaluation_errors = capture_evaluation_result.errors
|
|
121
125
|
{
|
|
122
126
|
return: {
|
|
123
127
|
captureExpressions: captured_block,
|
|
@@ -126,8 +130,9 @@ module Datadog
|
|
|
126
130
|
}
|
|
127
131
|
end
|
|
128
132
|
elsif probe.line?
|
|
129
|
-
|
|
130
|
-
|
|
133
|
+
capture_evaluation_result = capture_expression_evaluator.evaluate(probe, context)
|
|
134
|
+
captured_block = capture_evaluation_result.serialized_values
|
|
135
|
+
capture_expression_evaluation_errors = capture_evaluation_result.errors
|
|
131
136
|
{
|
|
132
137
|
lines: {
|
|
133
138
|
probe.line_no => {captureExpressions: captured_block},
|
|
@@ -144,14 +149,11 @@ module Datadog
|
|
|
144
149
|
evaluation_errors.concat(capture_expression_evaluation_errors)
|
|
145
150
|
build_snapshot_base(context,
|
|
146
151
|
evaluation_errors: evaluation_errors, message: message,
|
|
147
|
-
captures: captures)
|
|
152
|
+
captures: captures,)
|
|
148
153
|
end
|
|
149
154
|
|
|
150
155
|
def build_condition_evaluation_failed(context, expression, exception)
|
|
151
|
-
error = {
|
|
152
|
-
message: "#{exception.class}: #{exception}",
|
|
153
|
-
expr: expression.dsl_expr,
|
|
154
|
-
}
|
|
156
|
+
error = EvaluationFailure.new(expr: expression.dsl_expr, message: "#{exception.class}: #{exception}")
|
|
155
157
|
build_snapshot_base(context, evaluation_errors: [error])
|
|
156
158
|
end
|
|
157
159
|
|
|
@@ -350,7 +352,7 @@ module Datadog
|
|
|
350
352
|
snapshot: {
|
|
351
353
|
id: SecureRandom.uuid,
|
|
352
354
|
timestamp: timestamp,
|
|
353
|
-
evaluationErrors: evaluation_errors,
|
|
355
|
+
evaluationErrors: evaluation_errors.map { |failure| {expr: failure.expr, message: failure.message} },
|
|
354
356
|
probe: {
|
|
355
357
|
id: probe.id,
|
|
356
358
|
version: 0,
|
|
@@ -412,10 +414,10 @@ module Datadog
|
|
|
412
414
|
end
|
|
413
415
|
rescue Exception => exc # standard:disable Lint/RescueException
|
|
414
416
|
Datadog::DI.reraise_if_fatal(exc)
|
|
415
|
-
evaluation_errors <<
|
|
416
|
-
message: "#{exc.class}: #{exc.message}",
|
|
417
|
+
evaluation_errors << EvaluationFailure.new(
|
|
417
418
|
expr: segment.dsl_expr, # steep:ignore NoMethod
|
|
418
|
-
|
|
419
|
+
message: "#{exc.class}: #{exc.message}",
|
|
420
|
+
)
|
|
419
421
|
"[evaluation error]"
|
|
420
422
|
end.join
|
|
421
423
|
[message, evaluation_errors]
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "../core/semaphore"
|
|
4
4
|
require_relative "fatal_exceptions"
|
|
5
|
+
require_relative "guardrails_telemetry"
|
|
6
|
+
require_relative "snapshot_event"
|
|
5
7
|
|
|
6
8
|
module Datadog
|
|
7
9
|
module DI
|
|
@@ -24,14 +26,23 @@ module Datadog
|
|
|
24
26
|
#
|
|
25
27
|
# @api private
|
|
26
28
|
class ProbeNotifierWorker
|
|
29
|
+
# Initializes the background worker.
|
|
30
|
+
#
|
|
31
|
+
# @param settings [Datadog::Core::Configuration::Settings] tracer settings
|
|
32
|
+
# @param logger [DI::Logger] logger for worker diagnostics
|
|
33
|
+
# @param agent_settings [Datadog::Core::Configuration::AgentSettings] agent connection settings for the transports
|
|
27
34
|
# @param probe_repository [ProbeRepository] Repository for looking up probes.
|
|
28
35
|
# Used for handling serialization errors (disabling affected probes).
|
|
29
36
|
# @param probe_notification_builder [ProbeNotificationBuilder] Builder for
|
|
30
37
|
# creating status notifications. Used for reporting ERROR status.
|
|
38
|
+
# @param telemetry [Datadog::Core::Telemetry::Component, nil] component worker errors are reported through
|
|
39
|
+
# @param guardrails_telemetry [GuardrailsTelemetry] emitter for the canonical
|
|
40
|
+
# guardrails drop metric at the queue-full admission drop
|
|
31
41
|
def initialize(settings, logger, agent_settings:,
|
|
32
|
-
probe_repository:, probe_notification_builder:, telemetry: nil)
|
|
42
|
+
probe_repository:, probe_notification_builder:, guardrails_telemetry:, telemetry: nil)
|
|
33
43
|
@settings = settings
|
|
34
44
|
@telemetry = telemetry
|
|
45
|
+
@guardrails_telemetry = guardrails_telemetry
|
|
35
46
|
@status_queue = []
|
|
36
47
|
@snapshot_queue = []
|
|
37
48
|
@agent_settings = agent_settings
|
|
@@ -42,6 +53,8 @@ module Datadog
|
|
|
42
53
|
@sleep_remaining = nil
|
|
43
54
|
@wake_scheduled = false
|
|
44
55
|
@thread = nil
|
|
56
|
+
@status_transport = nil
|
|
57
|
+
@snapshot_transport = nil
|
|
45
58
|
@pid = nil
|
|
46
59
|
@flush = 0
|
|
47
60
|
@probe_repository = probe_repository
|
|
@@ -51,6 +64,9 @@ module Datadog
|
|
|
51
64
|
attr_reader :settings
|
|
52
65
|
attr_reader :logger
|
|
53
66
|
attr_reader :telemetry
|
|
67
|
+
# The guardrails metric emitter.
|
|
68
|
+
# @return [GuardrailsTelemetry]
|
|
69
|
+
attr_reader :guardrails_telemetry
|
|
54
70
|
attr_reader :agent_settings
|
|
55
71
|
attr_reader :probe_repository
|
|
56
72
|
attr_reader :probe_notification_builder
|
|
@@ -188,6 +204,9 @@ module Datadog
|
|
|
188
204
|
|
|
189
205
|
attr_reader :last_sent
|
|
190
206
|
|
|
207
|
+
# Builds and memoizes the diagnostics transport for status events.
|
|
208
|
+
#
|
|
209
|
+
# @return [DI::Transport::Diagnostics::Transport]
|
|
191
210
|
def status_transport
|
|
192
211
|
@status_transport ||= DI::Transport::HTTP.diagnostics(agent_settings: agent_settings, logger: logger)
|
|
193
212
|
end
|
|
@@ -196,8 +215,12 @@ module Datadog
|
|
|
196
215
|
status_transport.send_diagnostics(batch)
|
|
197
216
|
end
|
|
198
217
|
|
|
218
|
+
# Builds and memoizes the snapshot input transport.
|
|
219
|
+
#
|
|
220
|
+
# @return [DI::Transport::Input::Transport]
|
|
199
221
|
def snapshot_transport
|
|
200
|
-
@snapshot_transport ||= DI::Transport::HTTP.input(agent_settings: agent_settings, logger: logger,
|
|
222
|
+
@snapshot_transport ||= DI::Transport::HTTP.input(agent_settings: agent_settings, logger: logger,
|
|
223
|
+
telemetry: telemetry, guardrails_telemetry: guardrails_telemetry,)
|
|
201
224
|
end
|
|
202
225
|
|
|
203
226
|
# Sends a batch of snapshot payloads to the agent.
|
|
@@ -206,7 +229,7 @@ module Datadog
|
|
|
206
229
|
# serialization failures via callback. This allows healthy probes
|
|
207
230
|
# to continue working even when one probe produces un-serializable data.
|
|
208
231
|
#
|
|
209
|
-
# @param batch [Array<
|
|
232
|
+
# @param batch [Array<SnapshotEvent>] the snapshot events queued for sending
|
|
210
233
|
def do_send_snapshot(batch)
|
|
211
234
|
snapshot_transport.send_input(batch, tags, on_serialization_error: method(:handle_serialization_error))
|
|
212
235
|
end
|
|
@@ -259,6 +282,12 @@ module Datadog
|
|
|
259
282
|
# Signals the background thread to wake up (and do the sending)
|
|
260
283
|
# if it has been more than 1 second since the last send of the same
|
|
261
284
|
# event type.
|
|
285
|
+
#
|
|
286
|
+
# @param event [Hash] the status or snapshot payload to enqueue
|
|
287
|
+
# @param probe [Probe, nil] the probe the payload belongs to, for status log
|
|
288
|
+
# attribution, the queue-full drop event type, and the queued
|
|
289
|
+
# snapshot event's guardrails event type
|
|
290
|
+
# @return [void]
|
|
262
291
|
define_method("add_#{event_type}") do |event, probe: nil|
|
|
263
292
|
# Enqueueing reads DI configuration and writes debug/trace logs, both
|
|
264
293
|
# of which can call stdlib methods (e.g. Set#include? via the
|
|
@@ -275,12 +304,28 @@ module Datadog
|
|
|
275
304
|
begin
|
|
276
305
|
@lock.synchronize do
|
|
277
306
|
queue = send("#{event_type}_queue")
|
|
307
|
+
guardrails_event_type = if event_type == :snapshot
|
|
308
|
+
probe ? GuardrailsTelemetry.probe_event_type_tag(probe) : GuardrailsTelemetry::EVENT_TYPE_SNAPSHOT
|
|
309
|
+
end
|
|
278
310
|
if queue.length > settings.dynamic_instrumentation.internal.snapshot_queue_capacity
|
|
279
311
|
if event_type == :status && probe
|
|
280
312
|
status = event.dig(:debugger, :diagnostics, :status)
|
|
281
|
-
logger.debug
|
|
313
|
+
logger.debug do
|
|
314
|
+
"di: dropping status for #{probe.type} probe at #{probe.location}" \
|
|
315
|
+
" (#{probe.id}): #{status} because queue is full" \
|
|
316
|
+
" (#{GuardrailsTelemetry::Reason::QUEUE_FULL})"
|
|
317
|
+
end
|
|
282
318
|
else
|
|
283
|
-
logger.debug
|
|
319
|
+
logger.debug do
|
|
320
|
+
"di: #{self.class.name}: dropping #{event_type} event because queue is full" \
|
|
321
|
+
" (#{GuardrailsTelemetry::Reason::QUEUE_FULL})"
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
if event_type == :snapshot
|
|
325
|
+
guardrails_telemetry.dropped(
|
|
326
|
+
reason: GuardrailsTelemetry::Reason::QUEUE_FULL,
|
|
327
|
+
event_type: guardrails_event_type,
|
|
328
|
+
)
|
|
284
329
|
end
|
|
285
330
|
else
|
|
286
331
|
if event_type == :status && probe
|
|
@@ -289,7 +334,11 @@ module Datadog
|
|
|
289
334
|
else
|
|
290
335
|
logger.trace { "di: #{self.class.name}: queueing #{event_type} event" }
|
|
291
336
|
end
|
|
292
|
-
queue <<
|
|
337
|
+
queue << if event_type == :snapshot
|
|
338
|
+
SnapshotEvent.new(payload: event, event_type: guardrails_event_type)
|
|
339
|
+
else
|
|
340
|
+
event
|
|
341
|
+
end
|
|
293
342
|
end
|
|
294
343
|
end
|
|
295
344
|
|
|
@@ -307,6 +356,7 @@ module Datadog
|
|
|
307
356
|
# Worker could be not running if the process forked - check and
|
|
308
357
|
# start it again in this case.
|
|
309
358
|
start
|
|
359
|
+
nil
|
|
310
360
|
ensure
|
|
311
361
|
Datadog::DI.leave_probe unless was_in_probe
|
|
312
362
|
end
|