datadog 2.39.0 → 2.47.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.
Files changed (296) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +269 -44
  3. data/README.md +3 -0
  4. data/ext/datadog_profiling_native_extension/NativeExtensionDesign.md +12 -24
  5. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +256 -193
  6. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -5
  7. data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +0 -2
  8. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +19 -20
  9. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.h +5 -1
  10. data/ext/datadog_profiling_native_extension/collectors_stack.c +267 -171
  11. data/ext/datadog_profiling_native_extension/collectors_stack.h +17 -3
  12. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +307 -217
  13. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +10 -5
  14. data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +5 -4
  15. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +19 -11
  16. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +7 -10
  17. data/ext/datadog_profiling_native_extension/extconf.rb +67 -99
  18. data/ext/datadog_profiling_native_extension/heap_recorder.c +353 -257
  19. data/ext/datadog_profiling_native_extension/heap_recorder.h +50 -31
  20. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +3 -27
  21. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +853 -496
  22. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +42 -15
  23. data/ext/datadog_profiling_native_extension/profiling.c +30 -23
  24. data/ext/datadog_profiling_native_extension/ruby_helpers.c +4 -80
  25. data/ext/datadog_profiling_native_extension/ruby_helpers.h +4 -7
  26. data/ext/datadog_profiling_native_extension/setup_signal_handler.c +0 -2
  27. data/ext/datadog_profiling_native_extension/stack_recorder.c +116 -89
  28. data/ext/datadog_profiling_native_extension/stack_recorder.h +12 -5
  29. data/ext/datadog_profiling_native_extension/time_helpers.c +2 -4
  30. data/ext/datadog_profiling_native_extension/time_helpers.h +15 -15
  31. data/ext/libdatadog_api/datadog_ruby_common.c +19 -11
  32. data/ext/libdatadog_api/datadog_ruby_common.h +7 -10
  33. data/ext/libdatadog_api/di.c +43 -3
  34. data/ext/libdatadog_api/extconf.rb +6 -1
  35. data/ext/libdatadog_api/feature_flags.c +8 -0
  36. data/ext/libdatadog_api/init.c +9 -1
  37. data/ext/libdatadog_api/otel_thread_context.c +274 -0
  38. data/ext/libdatadog_api/otel_thread_context.h +5 -0
  39. data/ext/libdatadog_api/process_discovery.c +15 -1
  40. data/ext/libdatadog_api/trace_exporter.c +2078 -0
  41. data/ext/libdatadog_api/trace_exporter.h +5 -0
  42. data/ext/libdatadog_extconf_helpers.rb +14 -9
  43. data/lib/datadog/ai_guard/component.rb +17 -8
  44. data/lib/datadog/ai_guard/configuration/ext.rb +2 -0
  45. data/lib/datadog/ai_guard/configuration.rb +13 -0
  46. data/lib/datadog/ai_guard/contrib/ruby_llm/chat_instrumentation.rb +48 -55
  47. data/lib/datadog/ai_guard/contrib/ruby_llm/integration.rb +1 -1
  48. data/lib/datadog/ai_guard/contrib/ruby_llm/message_adapter.rb +76 -0
  49. data/lib/datadog/ai_guard/contrib/ruby_llm/patcher.rb +1 -0
  50. data/lib/datadog/ai_guard/contrib/ruby_llm/redaction_change_set.rb +135 -0
  51. data/lib/datadog/ai_guard/evaluation/client.rb +50 -0
  52. data/lib/datadog/ai_guard/evaluation/content_part.rb +12 -0
  53. data/lib/datadog/ai_guard/evaluation/message.rb +25 -7
  54. data/lib/datadog/ai_guard/evaluation/message_builder.rb +31 -0
  55. data/lib/datadog/ai_guard/evaluation/no_op_result.rb +6 -6
  56. data/lib/datadog/ai_guard/evaluation/outcome.rb +24 -0
  57. data/lib/datadog/ai_guard/evaluation/request.rb +8 -64
  58. data/lib/datadog/ai_guard/evaluation/response.rb +33 -0
  59. data/lib/datadog/ai_guard/evaluation/result.rb +11 -18
  60. data/lib/datadog/ai_guard/evaluation/tool_call.rb +15 -2
  61. data/lib/datadog/ai_guard/evaluation.rb +36 -14
  62. data/lib/datadog/ai_guard/ext.rb +4 -1
  63. data/lib/datadog/ai_guard/{api_client.rb → http_client.rb} +7 -5
  64. data/lib/datadog/ai_guard/metrics/telemetry.rb +43 -0
  65. data/lib/datadog/ai_guard/redaction/replacements.rb +97 -0
  66. data/lib/datadog/ai_guard/redaction/result.rb +29 -0
  67. data/lib/datadog/ai_guard/redaction.rb +80 -0
  68. data/lib/datadog/ai_guard.rb +58 -57
  69. data/lib/datadog/appsec/actions_handler/serializable_backtrace.rb +21 -42
  70. data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +1 -1
  71. data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +1 -1
  72. data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +1 -1
  73. data/lib/datadog/appsec/assets/blocked.html +1 -108
  74. data/lib/datadog/appsec/configuration.rb +11 -2
  75. data/lib/datadog/appsec/context.rb +1 -1
  76. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +1 -1
  77. data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +2 -2
  78. data/lib/datadog/appsec/contrib/devise/configuration.rb +1 -1
  79. data/lib/datadog/appsec/contrib/devise/patcher.rb +1 -1
  80. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +2 -2
  81. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +2 -2
  82. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +1 -1
  83. data/lib/datadog/appsec/contrib/rack/ext.rb +2 -2
  84. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +2 -2
  85. data/lib/datadog/appsec/contrib/rack/patcher.rb +1 -1
  86. data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +6 -3
  87. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +30 -3
  88. data/lib/datadog/appsec/contrib/rails/patches/render_to_body_patch.rb +8 -7
  89. data/lib/datadog/appsec/contrib/rails/request_middleware.rb +2 -1
  90. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +2 -2
  91. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +15 -3
  92. data/lib/datadog/appsec/contrib/sinatra/patches/json_patch.rb +8 -7
  93. data/lib/datadog/appsec/contrib/sinatra/request_middleware.rb +2 -1
  94. data/lib/datadog/appsec/processor/rule_loader.rb +12 -12
  95. data/lib/datadog/appsec/response.rb +1 -1
  96. data/lib/datadog/appsec/route_normalizer/route_pattern.rb +3 -3
  97. data/lib/datadog/appsec/security_engine/engine.rb +5 -4
  98. data/lib/datadog/core/configuration/components.rb +50 -19
  99. data/lib/datadog/core/configuration/components_state.rb +8 -1
  100. data/lib/datadog/core/configuration/option_definition.rb +1 -1
  101. data/lib/datadog/core/configuration/options.rb +1 -1
  102. data/lib/datadog/core/configuration/settings.rb +38 -43
  103. data/lib/datadog/core/configuration/supported_configurations.rb +18 -2
  104. data/lib/datadog/core/crashtracking/component.rb +5 -1
  105. data/lib/datadog/core/diagnostics/environment_logger.rb +36 -1
  106. data/lib/datadog/core/environment/gc.rb +1 -1
  107. data/lib/datadog/core/environment/vm_cache.rb +1 -1
  108. data/lib/datadog/core/environment/yjit.rb +2 -2
  109. data/lib/datadog/core/metrics/helpers.rb +1 -1
  110. data/lib/datadog/core/metrics/options.rb +2 -2
  111. data/lib/datadog/core/process_discovery.rb +6 -2
  112. data/lib/datadog/core/remote/client/capabilities.rb +32 -21
  113. data/lib/datadog/core/remote/client.rb +45 -4
  114. data/lib/datadog/core/remote/component.rb +30 -7
  115. data/lib/datadog/core/remote/configuration/repository.rb +2 -2
  116. data/lib/datadog/core/remote/dispatcher.rb +47 -6
  117. data/lib/datadog/core/remote/worker.rb +8 -0
  118. data/lib/datadog/core/telemetry/configuration_value.rb +38 -0
  119. data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +3 -1
  120. data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +1 -1
  121. data/lib/datadog/core/telemetry/event/app_started.rb +5 -24
  122. data/lib/datadog/core/telemetry/event/generate_metrics.rb +1 -1
  123. data/lib/datadog/core/telemetry/event/log.rb +2 -2
  124. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +1 -1
  125. data/lib/datadog/core/telemetry/metric.rb +2 -2
  126. data/lib/datadog/core/telemetry/request.rb +2 -2
  127. data/lib/datadog/core/transport/http.rb +1 -1
  128. data/lib/datadog/core/transport/transport.rb +1 -1
  129. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +170 -18
  130. data/lib/datadog/core/utils/sequence.rb +3 -6
  131. data/lib/datadog/core/utils/time.rb +16 -54
  132. data/lib/datadog/core/workers/runtime_metrics.rb +1 -1
  133. data/lib/datadog/data_streams/pathway_context.rb +20 -22
  134. data/lib/datadog/data_streams/processor.rb +45 -14
  135. data/lib/datadog/di/boot.rb +1 -0
  136. data/lib/datadog/di/capture_expression_evaluator/result.rb +30 -0
  137. data/lib/datadog/di/capture_expression_evaluator.rb +39 -9
  138. data/lib/datadog/di/component.rb +108 -3
  139. data/lib/datadog/di/configuration.rb +53 -2
  140. data/lib/datadog/di/context.rb +7 -2
  141. data/lib/datadog/di/contrib/active_record.rb +8 -2
  142. data/lib/datadog/di/el/compiler.rb +88 -12
  143. data/lib/datadog/di/el/evaluator.rb +82 -2
  144. data/lib/datadog/di/el/expression.rb +13 -2
  145. data/lib/datadog/di/evaluation_failure.rb +28 -0
  146. data/lib/datadog/di/guardrails_telemetry/reason.rb +87 -0
  147. data/lib/datadog/di/guardrails_telemetry.rb +203 -0
  148. data/lib/datadog/di/instrumenter.rb +106 -15
  149. data/lib/datadog/di/logger.rb +32 -10
  150. data/lib/datadog/di/probe.rb +9 -1
  151. data/lib/datadog/di/probe_builder.rb +7 -6
  152. data/lib/datadog/di/probe_manager.rb +56 -8
  153. data/lib/datadog/di/probe_notification_builder.rb +31 -28
  154. data/lib/datadog/di/probe_notifier_worker.rb +56 -6
  155. data/lib/datadog/di/proc_responder.rb +1 -1
  156. data/lib/datadog/di/remote.rb +49 -5
  157. data/lib/datadog/di/serializer.rb +172 -55
  158. data/lib/datadog/di/snapshot_event.rb +38 -0
  159. data/lib/datadog/di/transport/http.rb +13 -3
  160. data/lib/datadog/di/transport/input.rb +32 -7
  161. data/lib/datadog/error_tracking/component.rb +1 -1
  162. data/lib/datadog/kit/appsec/events/v2.rb +2 -2
  163. data/lib/datadog/open_feature/activation.rb +268 -0
  164. data/lib/datadog/open_feature/agentless/configuration_source.rb +246 -0
  165. data/lib/datadog/open_feature/agentless/parser.rb +43 -0
  166. data/lib/datadog/open_feature/agentless/response.rb +19 -0
  167. data/lib/datadog/open_feature/agentless/transport.rb +103 -0
  168. data/lib/datadog/open_feature/component.rb +85 -13
  169. data/lib/datadog/open_feature/configuration/agentless_endpoint.rb +90 -0
  170. data/lib/datadog/open_feature/configuration/source/resolution.rb +22 -0
  171. data/lib/datadog/open_feature/configuration/source.rb +43 -0
  172. data/lib/datadog/open_feature/configuration.rb +124 -0
  173. data/lib/datadog/open_feature/evaluation_engine.rb +29 -3
  174. data/lib/datadog/open_feature/exposures/batch_builder.rb +1 -1
  175. data/lib/datadog/open_feature/exposures/event.rb +15 -8
  176. data/lib/datadog/open_feature/ext.rb +19 -0
  177. data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +236 -80
  178. data/lib/datadog/open_feature/flag_evaluation/writer.rb +179 -68
  179. data/lib/datadog/open_feature/hooks/evaluation_telemetry_opt_out_hook.rb +25 -0
  180. data/lib/datadog/open_feature/hooks/flag_eval_evp_hook.rb +24 -21
  181. data/lib/datadog/open_feature/native_evaluator.rb +20 -6
  182. data/lib/datadog/open_feature/noop_evaluator.rb +5 -0
  183. data/lib/datadog/open_feature/provider.rb +315 -10
  184. data/lib/datadog/open_feature/remote.rb +5 -5
  185. data/lib/datadog/open_feature/transport.rb +5 -0
  186. data/lib/datadog/open_feature.rb +31 -1
  187. data/lib/datadog/opentelemetry/sdk/propagator.rb +1 -1
  188. data/lib/datadog/opentelemetry/signal_configuration.rb +13 -9
  189. data/lib/datadog/opentelemetry/trace.rb +3 -0
  190. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +10 -2
  191. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +5 -7
  192. data/lib/datadog/profiling/collectors/info.rb +40 -13
  193. data/lib/datadog/profiling/collectors/thread_context.rb +6 -17
  194. data/lib/datadog/profiling/component.rb +33 -39
  195. data/lib/datadog/profiling/exporter.rb +10 -10
  196. data/lib/datadog/profiling/tasks/exec.rb +1 -1
  197. data/lib/datadog/profiling.rb +4 -0
  198. data/lib/datadog/symbol_database/extractor.rb +89 -107
  199. data/lib/datadog/tracing/component.rb +44 -2
  200. data/lib/datadog/tracing/configuration/dynamic/option.rb +4 -0
  201. data/lib/datadog/tracing/configuration/dynamic.rb +5 -3
  202. data/lib/datadog/tracing/configuration/ext.rb +4 -0
  203. data/lib/datadog/tracing/configuration/settings.rb +36 -0
  204. data/lib/datadog/tracing/context.rb +24 -2
  205. data/lib/datadog/tracing/context_provider.rb +17 -5
  206. data/lib/datadog/tracing/contrib/action_cable/events.rb +1 -1
  207. data/lib/datadog/tracing/contrib/action_mailer/events.rb +1 -1
  208. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +2 -2
  209. data/lib/datadog/tracing/contrib/action_view/events.rb +1 -1
  210. data/lib/datadog/tracing/contrib/active_model_serializers/events.rb +1 -1
  211. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +1 -1
  212. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +1 -0
  213. data/lib/datadog/tracing/contrib/active_record/events.rb +1 -1
  214. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +2 -2
  215. data/lib/datadog/tracing/contrib/aws/ext.rb +1 -1
  216. data/lib/datadog/tracing/contrib/aws/services.rb +1 -1
  217. data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +1 -1
  218. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +10 -5
  219. data/lib/datadog/tracing/contrib/excon/middleware.rb +10 -3
  220. data/lib/datadog/tracing/contrib/ext.rb +3 -3
  221. data/lib/datadog/tracing/contrib/faraday/middleware.rb +10 -4
  222. data/lib/datadog/tracing/contrib/grape/endpoint.rb +32 -5
  223. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +1 -1
  224. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +1 -1
  225. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +1 -1
  226. data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +2 -1
  227. data/lib/datadog/tracing/contrib/http/instrumentation.rb +16 -1
  228. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +8 -2
  229. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +10 -4
  230. data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +4 -0
  231. data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +7 -2
  232. data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +7 -2
  233. data/lib/datadog/tracing/contrib/kafka/events.rb +1 -1
  234. data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +1 -1
  235. data/lib/datadog/tracing/contrib/mongodb/parsers.rb +1 -1
  236. data/lib/datadog/tracing/contrib/opensearch/ext.rb +1 -1
  237. data/lib/datadog/tracing/contrib/opensearch/quantize.rb +1 -1
  238. data/lib/datadog/tracing/contrib/patchable.rb +1 -1
  239. data/lib/datadog/tracing/contrib/patcher.rb +1 -1
  240. data/lib/datadog/tracing/contrib/que/tracer.rb +1 -1
  241. data/lib/datadog/tracing/contrib/racecar/events.rb +1 -1
  242. data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +1 -1
  243. data/lib/datadog/tracing/contrib/rack/header_tagging.rb +1 -1
  244. data/lib/datadog/tracing/contrib/rack/patcher.rb +1 -1
  245. data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +1 -1
  246. data/lib/datadog/tracing/contrib/redis/configuration/resolver.rb +1 -1
  247. data/lib/datadog/tracing/contrib/redis/quantize.rb +36 -2
  248. data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +9 -3
  249. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +10 -3
  250. data/lib/datadog/tracing/contrib/sequel/database.rb +1 -5
  251. data/lib/datadog/tracing/contrib/sequel/jdbc_connection_string.rb +140 -0
  252. data/lib/datadog/tracing/contrib/sequel/utils.rb +50 -63
  253. data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +1 -1
  254. data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +1 -1
  255. data/lib/datadog/tracing/contrib/sneakers/tracer.rb +1 -1
  256. data/lib/datadog/tracing/contrib/utils/quantization/hash_formatter.rb +1 -1
  257. data/lib/datadog/tracing/contrib/utils/quantization/http.rb +108 -3
  258. data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +1 -1
  259. data/lib/datadog/tracing/correlation.rb +2 -2
  260. data/lib/datadog/tracing/diagnostics/environment_logger.rb +3 -2
  261. data/lib/datadog/tracing/distributed/baggage.rb +1 -3
  262. data/lib/datadog/tracing/distributed/datadog.rb +3 -3
  263. data/lib/datadog/tracing/distributed/propagation.rb +3 -0
  264. data/lib/datadog/tracing/distributed/propagation_policy.rb +5 -0
  265. data/lib/datadog/tracing/distributed/trace_context.rb +14 -271
  266. data/lib/datadog/tracing/distributed/trace_state/datadog.rb +233 -0
  267. data/lib/datadog/tracing/distributed/trace_state/ext.rb +44 -0
  268. data/lib/datadog/tracing/distributed/trace_state/open_telemetry.rb +156 -0
  269. data/lib/datadog/tracing/distributed/trace_state.rb +121 -0
  270. data/lib/datadog/tracing/metadata/ext.rb +3 -0
  271. data/lib/datadog/tracing/metadata/tagging.rb +1 -1
  272. data/lib/datadog/tracing/otel_thread_context.rb +97 -0
  273. data/lib/datadog/tracing/remote.rb +236 -37
  274. data/lib/datadog/tracing/sampling/rule_sampler.rb +2 -0
  275. data/lib/datadog/tracing/span.rb +1 -1
  276. data/lib/datadog/tracing/span_operation.rb +1 -1
  277. data/lib/datadog/tracing/sync_writer.rb +8 -3
  278. data/lib/datadog/tracing/trace_digest.rb +22 -4
  279. data/lib/datadog/tracing/trace_operation.rb +22 -10
  280. data/lib/datadog/tracing/tracer.rb +28 -7
  281. data/lib/datadog/tracing/transport/http/telemetry.rb +94 -0
  282. data/lib/datadog/tracing/transport/http/traces.rb +2 -0
  283. data/lib/datadog/tracing/transport/io/traces.rb +1 -1
  284. data/lib/datadog/tracing/transport/native/response.rb +71 -0
  285. data/lib/datadog/tracing/transport/native/telemetry.rb +17 -0
  286. data/lib/datadog/tracing/transport/native.rb +395 -0
  287. data/lib/datadog/tracing/transport/span_events_negotiation.rb +41 -0
  288. data/lib/datadog/tracing/transport/telemetry.rb +62 -0
  289. data/lib/datadog/tracing/transport/trace_formatter.rb +14 -4
  290. data/lib/datadog/tracing/transport/traces.rb +85 -38
  291. data/lib/datadog/tracing/writer.rb +17 -4
  292. data/lib/datadog/version.rb +1 -1
  293. metadata +51 -13
  294. data/lib/datadog/ai_guard/evaluation/content_builder.rb +0 -31
  295. data/lib/datadog/appsec/utils/hash_coercion.rb +0 -23
  296. data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +0 -69
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../core/rate_limiter"
3
4
  require_relative "../core/utils/time"
4
5
  require_relative "../ruby_version"
5
6
  require_relative "fatal_exceptions"
6
- require_relative "capture_expression_evaluator"
7
+ require_relative "guardrails_telemetry"
7
8
 
8
9
  # rubocop:disable Lint/AssignmentInCondition
9
10
  # rubocop:disable Style/AndOr
@@ -69,12 +70,35 @@ module Datadog
69
70
  #
70
71
  # @api private
71
72
  class Instrumenter
72
- def initialize(settings, serializer, logger, code_tracker: nil, telemetry: nil)
73
+ # Maximum number of capturing-probe snapshots admitted per second across the
74
+ # whole process.
75
+ GLOBAL_SNAPSHOT_RATE_LIMIT = 20
76
+
77
+ # Maximum number of non-capturing probe emissions admitted per second across
78
+ # the whole process.
79
+ GLOBAL_LOG_RATE_LIMIT = 5000
80
+
81
+ # Initializes the instrumenter.
82
+ #
83
+ # @param settings [Datadog::Core::Configuration::Settings] tracer settings
84
+ # @param serializer [Serializer] serializer for captured values
85
+ # @param logger [DI::Logger] logger for instrumenter diagnostics
86
+ # @param guardrails_telemetry [GuardrailsTelemetry] emitter for the canonical rate-limit skip metric
87
+ # @param capture_expression_evaluator [CaptureExpressionEvaluator] evaluator for the probe's capture expressions
88
+ # @param code_tracker [CodeTracker, nil] code tracker for line probe installation
89
+ # @param telemetry [Datadog::Core::Telemetry::Component, nil] component instrumenter errors are reported through
90
+ # @return [void]
91
+ def initialize(settings, serializer, logger, guardrails_telemetry:, capture_expression_evaluator:,
92
+ code_tracker: nil, telemetry: nil)
73
93
  @settings = settings
74
94
  @serializer = serializer
75
95
  @logger = logger
76
96
  @telemetry = telemetry
97
+ @guardrails_telemetry = guardrails_telemetry
98
+ @capture_expression_evaluator = capture_expression_evaluator
77
99
  @code_tracker = code_tracker
100
+ @global_snapshot_rate_limiter = Datadog::Core::TokenBucket.new(GLOBAL_SNAPSHOT_RATE_LIMIT)
101
+ @global_log_rate_limiter = Datadog::Core::TokenBucket.new(GLOBAL_LOG_RATE_LIMIT)
78
102
 
79
103
  @lock = Mutex.new
80
104
  end
@@ -83,6 +107,12 @@ module Datadog
83
107
  attr_reader :serializer
84
108
  attr_reader :logger
85
109
  attr_reader :telemetry
110
+ # The guardrails metric emitter.
111
+ # @return [GuardrailsTelemetry]
112
+ attr_reader :guardrails_telemetry
113
+ # The capture expression evaluator.
114
+ # @return [CaptureExpressionEvaluator]
115
+ attr_reader :capture_expression_evaluator
86
116
  attr_reader :code_tracker
87
117
 
88
118
  # The code tracker is a global singleton created lazily by
@@ -91,10 +121,41 @@ module Datadog
91
121
  # Component#start! assigns the now-current tracker here.
92
122
  attr_writer :code_tracker
93
123
 
94
- def capture_expression_evaluator
95
- @capture_expression_evaluator ||= CaptureExpressionEvaluator.new(
96
- settings: settings, serializer: serializer, logger: logger, telemetry: telemetry,
124
+ # Process-wide snapshot rate limiter.
125
+ # @return [Datadog::Core::TokenBucket]
126
+ attr_reader :global_snapshot_rate_limiter
127
+ # Process-wide log rate limiter.
128
+ # @return [Datadog::Core::TokenBucket]
129
+ attr_reader :global_log_rate_limiter
130
+
131
+ # Returns the process-wide rate limiter for the probe.
132
+ #
133
+ # @param probe [Probe] the probe whose invocation is being rate limited
134
+ # @return [Datadog::Core::TokenBucket] the shared limiter for the probe's category
135
+ def probe_global_rate_limiter(probe)
136
+ if probe.capturing?
137
+ global_snapshot_rate_limiter
138
+ else
139
+ global_log_rate_limiter
140
+ end
141
+ end
142
+
143
+ # Emits the canonical rate-limit skip metric for a probe.
144
+ #
145
+ # @param probe [Probe] the probe being skipped
146
+ # @param reason [String] a GuardrailsTelemetry::Reason constant for the rejecting limit
147
+ # @return [void]
148
+ def record_rate_limit_skip(reason, probe)
149
+ logger.trace do
150
+ "di: #{probe.type} probe #{probe.id}: skipping due to " \
151
+ "#{(reason == GuardrailsTelemetry::Reason::RATE_LIMIT_PROBE) ? "per-probe" : "global"} rate limit" \
152
+ " (#{reason})"
153
+ end
154
+ guardrails_telemetry.skipped(
155
+ reason: reason,
156
+ probe: probe,
97
157
  )
158
+ nil
98
159
  end
99
160
 
100
161
  # This is a substitute for Thread::Backtrace::Location
@@ -160,6 +221,7 @@ module Datadog
160
221
  end
161
222
 
162
223
  loc = target_method&.source_location
224
+ # @type var instrumenter: Instrumenter
163
225
  instrumenter = self
164
226
 
165
227
  mod = Module.new do
@@ -193,7 +255,7 @@ module Datadog
193
255
  # user probe on Proc#call cannot intercept the trampoline, and no
194
256
  # Proc is allocated for the block.
195
257
  if RubyVersion.is?(">= 3")
196
- define_method(method_name) do |*args, **kwargs, &target_block| # steep:ignore NoMethod
258
+ define_method(method_name) do |*args, **kwargs, &target_block|
197
259
  # steep:ignore FallbackAny below: Steep cannot narrow the
198
260
  # **kwargs parameter inside this define_method block, so it
199
261
  # falls back to untyped at the super and run_method_probe sites.
@@ -211,7 +273,7 @@ module Datadog
211
273
  end
212
274
  end
213
275
  else
214
- define_method(method_name) do |*args, &target_block| # steep:ignore NoMethod
276
+ define_method(method_name) do |*args, &target_block|
215
277
  if DI.in_probe?
216
278
  return super(*args, &target_block)
217
279
  end
@@ -230,7 +292,7 @@ module Datadog
230
292
  super(*args, &target_block)
231
293
  end
232
294
  end
233
- ruby2_keywords(method_name) if respond_to?(:ruby2_keywords, true) # steep:ignore NoMethod
295
+ ruby2_keywords(method_name) if respond_to?(:ruby2_keywords, true)
234
296
  end
235
297
  end
236
298
 
@@ -461,7 +523,7 @@ module Datadog
461
523
  # @param args [Array] positional arguments passed to the probed method
462
524
  # @param kwargs [Hash{Symbol => Object}] keyword arguments passed to the probed method
463
525
  # @param target_block [Proc, nil] block argument passed to the probed method
464
- # @param target_self [Object] the receiver of the probed method invocation
526
+ # @param target_self [any] the receiver of the probed method invocation
465
527
  # @param probe [Datadog::DI::Probe] the probe whose callback this invocation runs
466
528
  # @param responder [#probe_executed_callback, #probe_condition_evaluation_failed_callback] callback target invoked with the built Context
467
529
  # @param loc [Array(String, Integer), nil] source location of the probed method, or nil for virtual/lazily-defined methods
@@ -507,7 +569,7 @@ module Datadog
507
569
  # the context, we won't be able to report anything as
508
570
  # the probe notifier builder requires a context.
509
571
  begin
510
- responder.probe_condition_evaluation_failed_callback(context, exc)
572
+ responder.probe_condition_evaluation_failed_callback(context, condition, exc)
511
573
  rescue Exception => nested_exc # standard:disable Lint/RescueException
512
574
  Datadog::DI.reraise_if_fatal(nested_exc)
513
575
  raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
@@ -528,12 +590,22 @@ module Datadog
528
590
  end
529
591
 
530
592
  rate_limiter = probe.rate_limiter
531
- if continue and rate_limiter.nil? || rate_limiter.allow?
593
+ admitted = continue
594
+ if continue && rate_limiter && !rate_limiter.allow?
595
+ admitted = false
596
+ record_rate_limit_skip(GuardrailsTelemetry::Reason::RATE_LIMIT_PROBE, probe)
597
+ end
598
+ if admitted && !probe_global_rate_limiter(probe).allow?
599
+ admitted = false
600
+ record_rate_limit_skip(GuardrailsTelemetry::Reason::RATE_LIMIT_GLOBAL, probe)
601
+ end
602
+ if admitted
532
603
  # Arguments may be mutated by the method, therefore
533
604
  # they need to be serialized prior to method invocation.
534
605
  serialized_entry_args = if probe.capture_snapshot?
535
606
  serializer.serialize_args(args, kwargs, target_self,
536
- **probe.snapshot_serializer_limits(settings))
607
+ deadline: serializer.serialization_deadline,
608
+ **probe.snapshot_serializer_limits(settings),)
537
609
  end
538
610
 
539
611
  entry_capture_expressions = nil
@@ -545,8 +617,9 @@ module Datadog
545
617
  target_self: target_self,
546
618
  locals: serializer.combine_args(args, kwargs, target_self),
547
619
  )
548
- entry_capture_expressions, entry_capture_evaluation_errors =
549
- capture_expression_evaluator.evaluate(probe, entry_context)
620
+ entry_capture_result = capture_expression_evaluator.evaluate(probe, entry_context)
621
+ entry_capture_expressions = entry_capture_result.serialized_values
622
+ entry_capture_evaluation_errors = entry_capture_result.errors
550
623
  rescue Exception => exc # standard:disable Lint/RescueException
551
624
  Datadog::DI.reraise_if_fatal(exc)
552
625
  raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
@@ -715,6 +788,13 @@ module Datadog
715
788
  public :kwargs_from_splat
716
789
  end
717
790
 
791
+ # Trace point callback for a line probe.
792
+ #
793
+ # @param probe [Probe] the probe installed on this line
794
+ # @param iseq [RubyVM::InstructionSequence, nil] instruction sequence the trace point is targeted at, or nil when untargeted
795
+ # @param responder [#probe_executed_callback, #probe_condition_evaluation_failed_callback] callback target invoked with the built Context
796
+ # @param tp [TracePoint] the firing trace point
797
+ # @return [void]
718
798
  def line_trace_point_callback(probe, iseq, responder, tp)
719
799
  di_start_time = Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID)
720
800
 
@@ -791,7 +871,15 @@ module Datadog
791
871
 
792
872
  # In practice we should always have a rate limiter, but be safe
793
873
  # and check that it is in fact set.
794
- return if probe.rate_limiter && !probe.rate_limiter.allow?
874
+ if probe.rate_limiter && !probe.rate_limiter.allow?
875
+ record_rate_limit_skip(GuardrailsTelemetry::Reason::RATE_LIMIT_PROBE, probe)
876
+ return
877
+ end
878
+
879
+ unless probe_global_rate_limiter(probe).allow?
880
+ record_rate_limit_skip(GuardrailsTelemetry::Reason::RATE_LIMIT_GLOBAL, probe)
881
+ return
882
+ end
795
883
 
796
884
  # The context creation is relatively expensive and we don't
797
885
  # want to run it if the callback won't be executed due to the
@@ -802,12 +890,14 @@ module Datadog
802
890
  responder.probe_executed_callback(context)
803
891
 
804
892
  check_and_disable_if_exceeded(probe, responder, di_start_time)
893
+ nil
805
894
  rescue Exception => exc # standard:disable Lint/RescueException
806
895
  Datadog::DI.reraise_if_fatal(exc)
807
896
  raise if settings.dynamic_instrumentation.internal.propagate_all_exceptions
808
897
  logger.debug { "di: unhandled exception in line trace point: #{exc.class}: #{exc.message}" }
809
898
  telemetry&.report(exc, description: "Unhandled exception in line trace point")
810
899
  # TODO test this path
900
+ nil
811
901
  end
812
902
 
813
903
  def build_trace_point_context(probe, tp)
@@ -840,6 +930,7 @@ module Datadog
840
930
  # avoid a dependency on ProbeManager from Instrumenter.
841
931
  probe.disable!
842
932
  responder.probe_disabled_callback(probe, di_duration)
933
+ nil
843
934
  end
844
935
  end
845
936
 
@@ -1,29 +1,51 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "forwardable"
4
-
5
3
  module Datadog
6
4
  module DI
7
5
  # Logger facade to add the +trace+ method.
8
6
  #
9
7
  # @api private
10
8
  class Logger
11
- extend Forwardable
12
-
9
+ # Initializes the logger facade with the trace-logging gate resolved
10
+ # once.
11
+ # Resolving the gate at construction keeps the per-call settings
12
+ # traversal off the probe hot path. Components are rebuilt on
13
+ # reconfiguration, so the cached value tracks configuration
14
+ # changes.
15
+ #
16
+ # @param settings [Datadog::Core::Configuration::Settings] tracer settings the gate is resolved from
17
+ # @param target [::Logger] logger the facade delegates to
13
18
  def initialize(settings, target)
14
- @settings = settings
19
+ @trace_logging = settings.dynamic_instrumentation.internal.trace_logging
15
20
  @target = target
16
21
  end
17
22
 
18
- attr_reader :settings
23
+ # Whether trace logging is enabled.
24
+ # @return [Boolean]
25
+ attr_reader :trace_logging
26
+ # The target logger.
27
+ # @return [::Logger]
19
28
  attr_reader :target
20
29
 
21
- def_delegators :target, :debug
30
+ # Writes the given message or the block's message to the target
31
+ # logger.
32
+ #
33
+ # @param message [String, nil] message written when no block is given
34
+ # @return [void]
35
+ def debug(message = nil, &block)
36
+ target.debug(message, &block)
37
+ nil
38
+ end
22
39
 
23
- def trace(&block)
24
- if settings.dynamic_instrumentation.internal.trace_logging
25
- debug(&block)
40
+ # Writes the block's message to the target logger at debug level when
41
+ # the trace-logging gate resolved at construction is enabled.
42
+ #
43
+ # @return [void]
44
+ def trace
45
+ if trace_logging
46
+ debug { yield }
26
47
  end
48
+ nil
27
49
  end
28
50
  end
29
51
  end
@@ -97,7 +97,7 @@ module Datadog
97
97
  @evaluate_at = evaluate_at
98
98
  @condition = condition
99
99
 
100
- @rate_limit = rate_limit || ((@capture_snapshot || !@capture_expressions.empty?) ? 1 : 5000)
100
+ @rate_limit = rate_limit || (capturing? ? 1 : 5000)
101
101
  @rate_limiter = Datadog::Core::TokenBucket.new(@rate_limit)
102
102
 
103
103
  # At most one report per second.
@@ -166,6 +166,14 @@ module Datadog
166
166
  !@capture_expressions.empty?
167
167
  end
168
168
 
169
+ # Whether this probe captures user data, either as a full snapshot
170
+ # or via capture expressions.
171
+ #
172
+ # @return [Boolean]
173
+ def capturing?
174
+ capture_snapshot? || capture_expressions?
175
+ end
176
+
169
177
  def evaluate_at_entry?
170
178
  evaluate_at == :entry
171
179
  end
@@ -45,8 +45,8 @@ module Datadog
45
45
  unless cond_spec["dsl"] && cond_spec["json"]
46
46
  raise ArgumentError, "Malformed condition specification for probe: #{config}"
47
47
  end
48
- compiled = EL::Compiler.new.compile(cond_spec["json"])
49
- EL::Expression.new(cond_spec["dsl"], compiled)
48
+ compiled, regexps = EL::Compiler.new.compile(cond_spec["json"])
49
+ EL::Expression.new(cond_spec["dsl"], compiled, regexps: regexps)
50
50
  end
51
51
  capture_expressions = build_capture_expressions(config["captureExpressions"])
52
52
  capture_expressions = dedup_capture_expressions(capture_expressions, config["id"], logger)
@@ -100,8 +100,8 @@ module Datadog
100
100
  unless Hash === expr_spec && expr_spec["dsl"] && expr_spec["json"]
101
101
  raise ArgumentError, "captureExpressions entry #{name}: missing or malformed expr"
102
102
  end
103
- compiled = EL::Compiler.new.compile(expr_spec["json"])
104
- expr = EL::Expression.new(expr_spec["dsl"], compiled)
103
+ compiled, regexps = EL::Compiler.new.compile(expr_spec["json"])
104
+ expr = EL::Expression.new(expr_spec["dsl"], compiled, regexps: regexps)
105
105
  limits = build_capture_limits(entry["capture"])
106
106
  CaptureExpression.new(name: name, expr: expr, limits: limits)
107
107
  end
@@ -152,8 +152,9 @@ module Datadog
152
152
  unless dsl = segment["dsl"]
153
153
  raise ArgumentError, "Missing dsl for json in segment: #{segment}"
154
154
  end
155
- compiled = EL::Compiler.new.compile(ast)
156
- EL::Expression.new(dsl, compiled)
155
+ compiler = EL::Compiler.new
156
+ compiled, regexps = compiler.compile(ast)
157
+ EL::Expression.new(dsl, compiled, regexps: regexps, redaction_identifier: compiler.redaction_identifier(ast))
157
158
  else
158
159
  # TODO report to telemetry?
159
160
  end
@@ -3,6 +3,7 @@
3
3
  # rubocop:disable Lint/AssignmentInCondition
4
4
 
5
5
  require_relative "fatal_exceptions"
6
+ require_relative "guardrails_telemetry"
6
7
 
7
8
  module Datadog
8
9
  module DI
@@ -18,14 +19,26 @@ module Datadog
18
19
  #
19
20
  # @api private
20
21
  class ProbeManager
22
+ # Initializes the probe manager.
23
+ #
24
+ # @param settings [Datadog::Core::Configuration::Settings] tracer settings
25
+ # @param instrumenter [Instrumenter] instrumenter that executes installed probes
26
+ # @param probe_notification_builder [ProbeNotificationBuilder] builder for status and snapshot payloads
27
+ # @param probe_notifier_worker [ProbeNotifierWorker] worker that sends the built payloads
28
+ # @param logger [DI::Logger] logger for probe manager diagnostics
29
+ # @param probe_repository [ProbeRepository] repository of installed probes
30
+ # @param guardrails_telemetry [GuardrailsTelemetry] emitter for the canonical condition-error skip metric
31
+ # @param telemetry [Datadog::Core::Telemetry::Component, nil] component probe manager errors are reported through
32
+ # @return [void]
21
33
  def initialize(settings, instrumenter, probe_notification_builder,
22
- probe_notifier_worker, logger, probe_repository, telemetry: nil)
34
+ probe_notifier_worker, logger, probe_repository, guardrails_telemetry:, telemetry: nil)
23
35
  @settings = settings
24
36
  @instrumenter = instrumenter
25
37
  @probe_notification_builder = probe_notification_builder
26
38
  @probe_notifier_worker = probe_notifier_worker
27
39
  @logger = logger
28
40
  @telemetry = telemetry
41
+ @guardrails_telemetry = guardrails_telemetry
29
42
  @probe_repository = probe_repository
30
43
 
31
44
  @definition_trace_point = TracePoint.new(:end) do |tp|
@@ -40,6 +53,9 @@ module Datadog
40
53
 
41
54
  attr_reader :logger
42
55
  attr_reader :telemetry
56
+ # The guardrails metric emitter.
57
+ # @return [GuardrailsTelemetry]
58
+ attr_reader :guardrails_telemetry
43
59
  attr_reader :probe_repository
44
60
 
45
61
  # Stops the probe manager without permanently releasing resources.
@@ -303,25 +319,43 @@ module Datadog
303
319
  end
304
320
 
305
321
  payload = probe_notification_builder.build_executed(context)
306
- probe_notifier_worker.add_snapshot(payload)
322
+ probe_notifier_worker.add_snapshot(payload, probe: probe)
307
323
  end
308
324
 
309
325
  # Callback invoked when a probe's condition expression fails to evaluate.
310
326
  #
311
327
  # This can happen when the expression references undefined variables,
312
328
  # has type mismatches, or encounters runtime errors during evaluation.
313
- # Rate-limited to 1 notification per second per probe to avoid
314
- # flooding the backend when conditions fail repeatedly.
329
+ # Rate-limited to 1 notification per second per probe, and subject to
330
+ # the process-wide global snapshot rate limit, to avoid flooding the
331
+ # backend when conditions fail repeatedly.
315
332
  #
316
333
  # @param context [Context] The execution context containing probe and captured data
317
- # @param expr [String] The condition expression that failed
334
+ # @param expr [EL::Expression] The condition expression that failed
318
335
  # @param exc [Exception] The exception raised during condition evaluation
336
+ # @return [void]
319
337
  def probe_condition_evaluation_failed_callback(context, expr, exc)
320
338
  probe = context.probe
321
- if probe.condition_evaluation_failed_rate_limiter&.allow?
322
- payload = probe_notification_builder.build_condition_evaluation_failed(context, expr, exc)
323
- probe_notifier_worker.add_snapshot(payload)
339
+ rate_limiter = probe.condition_evaluation_failed_rate_limiter
340
+ if rate_limiter&.allow?
341
+ if instrumenter.global_snapshot_rate_limiter.allow?
342
+ payload = probe_notification_builder.build_condition_evaluation_failed(context, expr, exc)
343
+ probe_notifier_worker.add_snapshot(payload, probe: probe)
344
+ else
345
+ logger.trace do
346
+ "di: #{probe.type} probe #{probe.id}: skipping condition error snapshot due to global rate limit" \
347
+ " (#{GuardrailsTelemetry::Reason::RATE_LIMIT_GLOBAL})"
348
+ end
349
+ record_condition_error_skip(GuardrailsTelemetry::Reason::RATE_LIMIT_GLOBAL, probe)
350
+ end
351
+ elsif rate_limiter
352
+ logger.trace do
353
+ "di: #{probe.type} probe #{probe.id}: skipping condition evaluation failure" \
354
+ " notification due to per-probe rate limit" \
355
+ " (#{GuardrailsTelemetry::Reason::EVALUATION_ERROR_THROTTLED})"
356
+ end
324
357
  end
358
+ nil
325
359
  end
326
360
 
327
361
  # Callback invoked when a probe is disabled, for example due to
@@ -336,6 +370,20 @@ module Datadog
336
370
  probe_notifier_worker.add_status(payload, probe: probe)
337
371
  end
338
372
 
373
+ # Emits the canonical skip metric for a condition evaluation failure
374
+ # notification rejected by a rate limiter.
375
+ #
376
+ # @param probe [Probe] the probe whose condition evaluation failed
377
+ # @param reason [String] the GuardrailsTelemetry::Reason constant for the rejecting limit
378
+ # @return [void]
379
+ def record_condition_error_skip(reason, probe)
380
+ guardrails_telemetry.skipped(
381
+ reason: reason,
382
+ probe: probe,
383
+ )
384
+ nil
385
+ end
386
+
339
387
  # Class/module definition trace point (:end type).
340
388
  # Used to install hooks when the target classes/modules aren't yet
341
389
  # defined when the hook request is received.
@@ -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
- def initialize(settings, serializer, logger, telemetry: nil)
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
- @telemetry = telemetry
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
- captured_block, capture_expression_evaluation_errors =
120
- capture_expression_evaluator.evaluate(probe, context)
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
- captured_block, capture_expression_evaluation_errors =
130
- capture_expression_evaluator.evaluate(probe, context)
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
 
@@ -179,7 +181,7 @@ module Datadog
179
181
  if status == "ERROR"
180
182
  diagnostics[:exception] = { # steep:ignore
181
183
  type: exception ? exception.class.name : "Error",
182
- message: exception ? exception.message : message
184
+ message: exception ? exception.message : message,
183
185
  }
184
186
  end
185
187
 
@@ -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,
@@ -379,6 +381,7 @@ module Datadog
379
381
  thread_id: nil,
380
382
  version: 2,
381
383
  },
384
+ runtime_id: Core::Environment::Identity.id,
382
385
  # TODO add tests that the trace/span id is correctly propagated
383
386
  "dd.trace_id": active_trace&.id&.to_s,
384
387
  "dd.span_id": active_span&.id&.to_s,
@@ -405,16 +408,16 @@ module Datadog
405
408
  when String
406
409
  segment
407
410
  when EL::Expression
408
- serializer.serialize_value_for_message(segment.evaluate(context))
411
+ serializer.serialize_value_for_message(segment.evaluate(context), name: segment.redaction_identifier)
409
412
  else
410
413
  raise ArgumentError, "Invalid template segment type: #{segment}"
411
414
  end
412
415
  rescue Exception => exc # standard:disable Lint/RescueException
413
416
  Datadog::DI.reraise_if_fatal(exc)
414
- evaluation_errors << {
415
- message: "#{exc.class}: #{exc.message}",
417
+ evaluation_errors << EvaluationFailure.new(
416
418
  expr: segment.dsl_expr, # steep:ignore NoMethod
417
- }
419
+ message: "#{exc.class}: #{exc.message}",
420
+ )
418
421
  "[evaluation error]"
419
422
  end.join
420
423
  [message, evaluation_errors]