datadog 2.21.0 → 2.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (623) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +574 -1
  3. data/ext/LIBDATADOG_DEVELOPMENT.md +3 -0
  4. data/ext/datadog_profiling_native_extension/clock_id.h +9 -1
  5. data/ext/datadog_profiling_native_extension/clock_id_from_mach.c +66 -0
  6. data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +3 -2
  7. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +301 -82
  8. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +4 -4
  9. data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +3 -2
  10. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +18 -4
  11. data/ext/datadog_profiling_native_extension/collectors_stack.c +63 -32
  12. data/ext/datadog_profiling_native_extension/collectors_stack.h +7 -2
  13. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +728 -436
  14. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +19 -6
  15. data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +239 -0
  16. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +65 -1
  17. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +40 -1
  18. data/ext/datadog_profiling_native_extension/encoded_profile.c +2 -1
  19. data/ext/datadog_profiling_native_extension/extconf.rb +41 -37
  20. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +4 -43
  21. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +15 -47
  22. data/ext/datadog_profiling_native_extension/heap_recorder.c +252 -103
  23. data/ext/datadog_profiling_native_extension/heap_recorder.h +12 -1
  24. data/ext/datadog_profiling_native_extension/http_transport.c +66 -68
  25. data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +3 -22
  26. data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +0 -5
  27. data/ext/datadog_profiling_native_extension/macos_sampler_thread.h +55 -0
  28. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +0 -13
  29. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +40 -43
  30. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +6 -0
  31. data/ext/datadog_profiling_native_extension/profiling.c +65 -19
  32. data/ext/datadog_profiling_native_extension/ruby_helpers.c +63 -46
  33. data/ext/datadog_profiling_native_extension/ruby_helpers.h +17 -5
  34. data/ext/datadog_profiling_native_extension/setup_signal_handler.c +32 -10
  35. data/ext/datadog_profiling_native_extension/setup_signal_handler.h +2 -1
  36. data/ext/datadog_profiling_native_extension/stack_recorder.c +110 -85
  37. data/ext/datadog_profiling_native_extension/stack_recorder.h +3 -1
  38. data/ext/datadog_profiling_native_extension/time_helpers.h +13 -7
  39. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +2 -1
  40. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +9 -4
  41. data/ext/libdatadog_api/crashtracker.c +16 -15
  42. data/ext/libdatadog_api/crashtracker_report_exception.c +126 -0
  43. data/ext/libdatadog_api/datadog_ruby_common.c +65 -1
  44. data/ext/libdatadog_api/datadog_ruby_common.h +40 -1
  45. data/ext/libdatadog_api/ddsketch.c +102 -0
  46. data/ext/libdatadog_api/di.c +203 -0
  47. data/ext/libdatadog_api/extconf.rb +18 -24
  48. data/ext/libdatadog_api/feature_flags.c +554 -0
  49. data/ext/libdatadog_api/feature_flags.h +5 -0
  50. data/ext/libdatadog_api/helpers.h +27 -0
  51. data/ext/libdatadog_api/init.c +13 -1
  52. data/ext/libdatadog_api/library_config.c +34 -25
  53. data/ext/libdatadog_api/process_discovery.c +19 -13
  54. data/ext/libdatadog_extconf_helpers.rb +94 -11
  55. data/lib/datadog/ai_guard/api_client.rb +84 -0
  56. data/lib/datadog/ai_guard/autoload.rb +10 -0
  57. data/lib/datadog/ai_guard/component.rb +44 -0
  58. data/lib/datadog/ai_guard/configuration/ext.rb +17 -0
  59. data/lib/datadog/ai_guard/configuration.rb +115 -0
  60. data/lib/datadog/ai_guard/contrib/auto_instrument.rb +24 -0
  61. data/lib/datadog/ai_guard/contrib/integration.rb +37 -0
  62. data/lib/datadog/ai_guard/contrib/rack/integration.rb +42 -0
  63. data/lib/datadog/ai_guard/contrib/rack/patcher.rb +26 -0
  64. data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +97 -0
  65. data/lib/datadog/ai_guard/contrib/rails/integration.rb +41 -0
  66. data/lib/datadog/ai_guard/contrib/rails/patcher.rb +97 -0
  67. data/lib/datadog/ai_guard/contrib/ruby_llm/chat_instrumentation.rb +80 -0
  68. data/lib/datadog/ai_guard/contrib/ruby_llm/integration.rb +41 -0
  69. data/lib/datadog/ai_guard/contrib/ruby_llm/patcher.rb +30 -0
  70. data/lib/datadog/ai_guard/evaluation/content_builder.rb +31 -0
  71. data/lib/datadog/ai_guard/evaluation/content_part.rb +36 -0
  72. data/lib/datadog/ai_guard/evaluation/message.rb +25 -0
  73. data/lib/datadog/ai_guard/evaluation/no_op_result.rb +36 -0
  74. data/lib/datadog/ai_guard/evaluation/request.rb +86 -0
  75. data/lib/datadog/ai_guard/evaluation/result.rb +45 -0
  76. data/lib/datadog/ai_guard/evaluation/tool_call.rb +18 -0
  77. data/lib/datadog/ai_guard/evaluation.rb +108 -0
  78. data/lib/datadog/ai_guard/ext.rb +29 -0
  79. data/lib/datadog/ai_guard.rb +181 -0
  80. data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +26 -0
  81. data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +66 -0
  82. data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +36 -0
  83. data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +26 -0
  84. data/lib/datadog/appsec/api_security/endpoint_collection.rb +10 -0
  85. data/lib/datadog/appsec/api_security/route_extractor.rb +38 -9
  86. data/lib/datadog/appsec/api_security/sampler.rb +7 -4
  87. data/lib/datadog/appsec/assets/blocked.html +10 -1
  88. data/lib/datadog/appsec/assets/blocked.json +1 -1
  89. data/lib/datadog/appsec/assets/blocked.text +3 -1
  90. data/lib/datadog/appsec/assets/waf_rules/README.md +30 -36
  91. data/lib/datadog/appsec/assets/waf_rules/recommended.json +359 -4
  92. data/lib/datadog/appsec/assets/waf_rules/strict.json +43 -2
  93. data/lib/datadog/appsec/assets.rb +1 -1
  94. data/lib/datadog/appsec/autoload.rb +1 -1
  95. data/lib/datadog/appsec/component.rb +16 -9
  96. data/lib/datadog/appsec/compressed_json.rb +3 -3
  97. data/lib/datadog/appsec/configuration.rb +427 -1
  98. data/lib/datadog/appsec/context.rb +51 -13
  99. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +3 -1
  100. data/lib/datadog/appsec/contrib/active_record/integration.rb +1 -1
  101. data/lib/datadog/appsec/contrib/active_record/patcher.rb +4 -1
  102. data/lib/datadog/appsec/contrib/aws_lambda/gateway/watcher.rb +75 -0
  103. data/lib/datadog/appsec/contrib/aws_lambda/integration.rb +39 -0
  104. data/lib/datadog/appsec/contrib/aws_lambda/patcher.rb +30 -0
  105. data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +144 -0
  106. data/lib/datadog/appsec/contrib/devise/integration.rb +1 -1
  107. data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +2 -1
  108. data/lib/datadog/appsec/contrib/excon/integration.rb +1 -1
  109. data/lib/datadog/appsec/contrib/excon/patcher.rb +3 -1
  110. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +152 -12
  111. data/lib/datadog/appsec/contrib/faraday/integration.rb +1 -1
  112. data/lib/datadog/appsec/contrib/faraday/patcher.rb +1 -1
  113. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +138 -12
  114. data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +74 -24
  115. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +4 -2
  116. data/lib/datadog/appsec/contrib/graphql/integration.rb +2 -1
  117. data/lib/datadog/appsec/contrib/rack/buffered_input.rb +83 -0
  118. data/lib/datadog/appsec/contrib/rack/ext.rb +1 -1
  119. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +52 -13
  120. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +40 -19
  121. data/lib/datadog/appsec/contrib/rack/input_peeker.rb +79 -0
  122. data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
  123. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +48 -33
  124. data/lib/datadog/appsec/contrib/rack/response_body.rb +36 -0
  125. data/lib/datadog/appsec/contrib/rails/gateway/request.rb +40 -1
  126. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +26 -5
  127. data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
  128. data/lib/datadog/appsec/contrib/rails/patcher.rb +38 -0
  129. data/lib/datadog/appsec/contrib/rails/patches/process_action_patch.rb +2 -0
  130. data/lib/datadog/appsec/contrib/rest_client/integration.rb +1 -1
  131. data/lib/datadog/appsec/contrib/rest_client/patcher.rb +3 -1
  132. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +167 -11
  133. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +43 -13
  134. data/lib/datadog/appsec/contrib/sinatra/integration.rb +1 -1
  135. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +4 -4
  136. data/lib/datadog/appsec/contrib/sinatra/patches/json_patch.rb +1 -1
  137. data/lib/datadog/appsec/counter_sampler.rb +25 -0
  138. data/lib/datadog/appsec/default_header_tags.rb +52 -0
  139. data/lib/datadog/appsec/event.rb +13 -31
  140. data/lib/datadog/appsec/ext.rb +3 -0
  141. data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +2 -3
  142. data/lib/datadog/appsec/instrumentation/gateway.rb +2 -15
  143. data/lib/datadog/appsec/metrics/collector.rb +43 -5
  144. data/lib/datadog/appsec/metrics/exporter.rb +16 -3
  145. data/lib/datadog/appsec/metrics/telemetry.rb +20 -3
  146. data/lib/datadog/appsec/metrics/telemetry_exporter.rb +20 -1
  147. data/lib/datadog/appsec/metrics.rb +5 -5
  148. data/lib/datadog/appsec/monitor/gateway/watcher.rb +8 -6
  149. data/lib/datadog/appsec/remote.rb +44 -29
  150. data/lib/datadog/appsec/response.rb +18 -4
  151. data/lib/datadog/appsec/route_normalizer/rails_route_pattern.rb +176 -0
  152. data/lib/datadog/appsec/route_normalizer/route_pattern.rb +378 -0
  153. data/lib/datadog/appsec/route_normalizer/route_text.rb +57 -0
  154. data/lib/datadog/appsec/route_normalizer.rb +80 -0
  155. data/lib/datadog/appsec/security_engine/engine.rb +26 -5
  156. data/lib/datadog/appsec/security_engine/result.rb +29 -9
  157. data/lib/datadog/appsec/security_engine/runner.rb +20 -10
  158. data/lib/datadog/appsec/security_event.rb +5 -7
  159. data/lib/datadog/appsec/trace_keeper.rb +18 -6
  160. data/lib/datadog/appsec/utils/http/body.rb +38 -0
  161. data/lib/datadog/appsec/utils/http/body_reader.rb +61 -0
  162. data/lib/datadog/appsec/utils/http/media_range.rb +2 -1
  163. data/lib/datadog/appsec/utils/http/media_type.rb +32 -26
  164. data/lib/datadog/appsec/utils/http/url_encoded.rb +52 -0
  165. data/lib/datadog/appsec.rb +6 -3
  166. data/lib/datadog/core/configuration/agentless_settings_resolver.rb +2 -2
  167. data/lib/datadog/core/configuration/base.rb +17 -5
  168. data/lib/datadog/core/configuration/components.rb +185 -17
  169. data/lib/datadog/core/configuration/components_state.rb +6 -1
  170. data/lib/datadog/core/configuration/config_helper.rb +11 -2
  171. data/lib/datadog/core/configuration/deprecations.rb +2 -2
  172. data/lib/datadog/core/configuration/option.rb +32 -6
  173. data/lib/datadog/core/configuration/option_definition.rb +42 -14
  174. data/lib/datadog/core/configuration/options.rb +49 -12
  175. data/lib/datadog/core/configuration/settings.rb +115 -16
  176. data/lib/datadog/core/configuration/stable_config.rb +10 -0
  177. data/lib/datadog/core/configuration/supported_configurations.rb +379 -300
  178. data/lib/datadog/core/configuration.rb +3 -3
  179. data/lib/datadog/core/contrib/rails/railtie.rb +32 -0
  180. data/lib/datadog/core/contrib/rails/utils.rb +7 -3
  181. data/lib/datadog/core/crashtracking/component.rb +73 -21
  182. data/lib/datadog/core/crashtracking/tag_builder.rb +6 -0
  183. data/lib/datadog/core/ddsketch.rb +19 -0
  184. data/lib/datadog/core/diagnostics/environment_logger.rb +3 -1
  185. data/lib/datadog/core/environment/agent_info.rb +65 -1
  186. data/lib/datadog/core/environment/cgroup.rb +52 -25
  187. data/lib/datadog/core/environment/container.rb +140 -46
  188. data/lib/datadog/core/environment/ext.rb +13 -0
  189. data/lib/datadog/core/environment/identity.rb +40 -4
  190. data/lib/datadog/core/environment/process.rb +122 -0
  191. data/lib/datadog/core/environment/socket.rb +13 -0
  192. data/lib/datadog/core/environment/yjit.rb +2 -1
  193. data/lib/datadog/core/error.rb +6 -6
  194. data/lib/datadog/core/evp.rb +11 -0
  195. data/lib/datadog/core/feature_flags.rb +61 -0
  196. data/lib/datadog/core/knuth_sampler.rb +59 -0
  197. data/lib/datadog/core/logger.rb +1 -1
  198. data/lib/datadog/core/metrics/client.rb +6 -6
  199. data/lib/datadog/core/metrics/logging.rb +1 -1
  200. data/lib/datadog/core/pin.rb +8 -8
  201. data/lib/datadog/core/process_discovery.rb +21 -18
  202. data/lib/datadog/core/rate_limiter.rb +11 -1
  203. data/lib/datadog/core/remote/client/capabilities.rb +49 -6
  204. data/lib/datadog/core/remote/client.rb +15 -7
  205. data/lib/datadog/core/remote/component.rb +64 -36
  206. data/lib/datadog/core/remote/configuration/content.rb +15 -2
  207. data/lib/datadog/core/remote/configuration/digest.rb +14 -7
  208. data/lib/datadog/core/remote/configuration/repository.rb +1 -1
  209. data/lib/datadog/core/remote/configuration/target.rb +13 -6
  210. data/lib/datadog/core/remote/transport/config.rb +9 -36
  211. data/lib/datadog/core/remote/transport/http/config.rb +15 -55
  212. data/lib/datadog/core/remote/transport/http/negotiation.rb +14 -44
  213. data/lib/datadog/core/remote/transport/http.rb +15 -24
  214. data/lib/datadog/core/remote/transport/negotiation.rb +8 -33
  215. data/lib/datadog/core/remote/worker.rb +25 -37
  216. data/lib/datadog/core/runtime/metrics.rb +11 -2
  217. data/lib/datadog/core/semaphore.rb +1 -4
  218. data/lib/datadog/core/tag_builder.rb +0 -4
  219. data/lib/datadog/core/tag_normalizer.rb +84 -0
  220. data/lib/datadog/core/telemetry/component.rb +59 -15
  221. data/lib/datadog/core/telemetry/emitter.rb +6 -6
  222. data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +2 -3
  223. data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +30 -0
  224. data/lib/datadog/core/telemetry/event/app_extended_heartbeat.rb +32 -0
  225. data/lib/datadog/core/telemetry/event/app_started.rb +177 -171
  226. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +27 -4
  227. data/lib/datadog/core/telemetry/event.rb +2 -7
  228. data/lib/datadog/core/telemetry/ext.rb +1 -0
  229. data/lib/datadog/core/telemetry/logger.rb +4 -2
  230. data/lib/datadog/core/telemetry/logging.rb +17 -5
  231. data/lib/datadog/core/telemetry/metrics_manager.rb +9 -0
  232. data/lib/datadog/core/telemetry/request.rb +17 -5
  233. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +8 -34
  234. data/lib/datadog/core/telemetry/transport/http.rb +21 -16
  235. data/lib/datadog/core/telemetry/transport/telemetry.rb +8 -17
  236. data/lib/datadog/core/telemetry/worker.rb +108 -32
  237. data/lib/datadog/core/transport/ext.rb +3 -0
  238. data/lib/datadog/core/transport/http/api/endpoint.rb +9 -4
  239. data/lib/datadog/core/transport/http/api/instance.rb +4 -21
  240. data/lib/datadog/core/transport/http/builder.rb +10 -6
  241. data/lib/datadog/core/transport/http/client.rb +80 -0
  242. data/lib/datadog/core/transport/http/response.rb +4 -0
  243. data/lib/datadog/core/transport/http.rb +24 -19
  244. data/lib/datadog/core/transport/parcel.rb +61 -9
  245. data/lib/datadog/core/transport/response.rb +16 -2
  246. data/lib/datadog/core/transport/transport.rb +90 -0
  247. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +2 -2
  248. data/lib/datadog/core/utils/{base64.rb → base64_codec.rb} +4 -3
  249. data/lib/datadog/core/utils/enumerable_compat.rb +29 -0
  250. data/lib/datadog/core/utils/fnv.rb +26 -0
  251. data/lib/datadog/core/utils/forking.rb +3 -1
  252. data/lib/datadog/core/utils/hash.rb +0 -23
  253. data/lib/datadog/{appsec/api_security → core/utils}/lru_cache.rb +10 -21
  254. data/lib/datadog/core/utils/network.rb +22 -1
  255. data/lib/datadog/core/utils/only_once.rb +1 -1
  256. data/lib/datadog/core/utils/only_once_successful.rb +8 -2
  257. data/lib/datadog/core/utils/safe_dup.rb +2 -2
  258. data/lib/datadog/core/utils/sequence.rb +2 -0
  259. data/lib/datadog/core/utils/spawn_monkey_patch.rb +68 -0
  260. data/lib/datadog/core/utils/time.rb +6 -2
  261. data/lib/datadog/core/utils.rb +3 -1
  262. data/lib/datadog/core/workers/async.rb +11 -2
  263. data/lib/datadog/core/workers/interval_loop.rb +51 -3
  264. data/lib/datadog/core/workers/polling.rb +2 -0
  265. data/lib/datadog/core/workers/queue.rb +96 -1
  266. data/lib/datadog/core/workers/runtime_metrics.rb +9 -1
  267. data/lib/datadog/core.rb +10 -3
  268. data/lib/datadog/data_streams/configuration.rb +50 -0
  269. data/lib/datadog/data_streams/ext.rb +11 -0
  270. data/lib/datadog/data_streams/extensions.rb +16 -0
  271. data/lib/datadog/data_streams/pathway_context.rb +169 -0
  272. data/lib/datadog/data_streams/processor.rb +511 -0
  273. data/lib/datadog/data_streams/transport/http/stats.rb +58 -0
  274. data/lib/datadog/data_streams/transport/http.rb +36 -0
  275. data/lib/datadog/data_streams/transport/stats.rb +39 -0
  276. data/lib/datadog/data_streams.rb +100 -0
  277. data/lib/datadog/di/base.rb +15 -7
  278. data/lib/datadog/di/boot.rb +7 -2
  279. data/lib/datadog/di/capture_expression.rb +21 -0
  280. data/lib/datadog/di/capture_expression_evaluator.rb +71 -0
  281. data/lib/datadog/di/capture_limits.rb +41 -0
  282. data/lib/datadog/di/code_tracker.rb +217 -15
  283. data/lib/datadog/di/component.rb +139 -51
  284. data/lib/datadog/di/configuration.rb +241 -2
  285. data/lib/datadog/di/context.rb +82 -0
  286. data/lib/datadog/di/contrib/active_record.rb +34 -5
  287. data/lib/datadog/di/el/compiler.rb +168 -0
  288. data/lib/datadog/di/el/evaluator.rb +159 -0
  289. data/lib/datadog/di/el/expression.rb +42 -0
  290. data/lib/datadog/di/el.rb +5 -0
  291. data/lib/datadog/di/error.rb +44 -0
  292. data/lib/datadog/di/fatal_exceptions.rb +26 -0
  293. data/lib/datadog/di/instrumenter.rb +623 -147
  294. data/lib/datadog/di/logger.rb +2 -2
  295. data/lib/datadog/di/probe.rb +122 -14
  296. data/lib/datadog/di/probe_builder.rb +124 -3
  297. data/lib/datadog/di/probe_file_loader/railtie.rb +1 -1
  298. data/lib/datadog/di/probe_file_loader.rb +12 -7
  299. data/lib/datadog/di/probe_manager.rb +195 -100
  300. data/lib/datadog/di/probe_notification_builder.rb +321 -90
  301. data/lib/datadog/di/probe_notifier_worker.rb +112 -36
  302. data/lib/datadog/di/probe_repository.rb +198 -0
  303. data/lib/datadog/di/proc_responder.rb +36 -0
  304. data/lib/datadog/di/redactor.rb +24 -2
  305. data/lib/datadog/di/remote.rb +258 -93
  306. data/lib/datadog/di/serializer.rb +310 -29
  307. data/lib/datadog/di/transport/diagnostics.rb +12 -42
  308. data/lib/datadog/di/transport/http/diagnostics.rb +4 -34
  309. data/lib/datadog/di/transport/http/input.rb +2 -34
  310. data/lib/datadog/di/transport/http.rb +43 -19
  311. data/lib/datadog/di/transport/input.rb +112 -38
  312. data/lib/datadog/di/utils.rb +42 -14
  313. data/lib/datadog/di.rb +204 -4
  314. data/lib/datadog/error_tracking/collector.rb +2 -1
  315. data/lib/datadog/error_tracking/component.rb +2 -2
  316. data/lib/datadog/error_tracking/configuration.rb +55 -2
  317. data/lib/datadog/error_tracking/filters.rb +2 -2
  318. data/lib/datadog/kit/appsec/events/v2.rb +60 -3
  319. data/lib/datadog/kit/enable_core_dumps.rb +1 -1
  320. data/lib/datadog/kit/tracing/method_tracer.rb +135 -0
  321. data/lib/datadog/open_feature/component.rb +100 -0
  322. data/lib/datadog/open_feature/configuration.rb +37 -0
  323. data/lib/datadog/open_feature/evaluation_engine.rb +70 -0
  324. data/lib/datadog/open_feature/exposures/batch_builder.rb +32 -0
  325. data/lib/datadog/open_feature/exposures/buffer.rb +43 -0
  326. data/lib/datadog/open_feature/exposures/deduplicator.rb +30 -0
  327. data/lib/datadog/open_feature/exposures/event.rb +60 -0
  328. data/lib/datadog/open_feature/exposures/reporter.rb +40 -0
  329. data/lib/datadog/open_feature/exposures/worker.rb +116 -0
  330. data/lib/datadog/open_feature/ext.rb +16 -0
  331. data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +286 -0
  332. data/lib/datadog/open_feature/flag_evaluation/writer.rb +433 -0
  333. data/lib/datadog/open_feature/hooks/flag_eval_evp_hook.rb +101 -0
  334. data/lib/datadog/open_feature/hooks/flag_eval_metrics_hook.rb +49 -0
  335. data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +149 -0
  336. data/lib/datadog/open_feature/native_evaluator.rb +60 -0
  337. data/lib/datadog/open_feature/noop_evaluator.rb +26 -0
  338. data/lib/datadog/open_feature/provider.rb +191 -0
  339. data/lib/datadog/open_feature/remote.rb +67 -0
  340. data/lib/datadog/open_feature/resolution_details.rb +35 -0
  341. data/lib/datadog/open_feature/transport.rb +121 -0
  342. data/lib/datadog/open_feature.rb +19 -0
  343. data/lib/datadog/opentelemetry/api/baggage.rb +1 -1
  344. data/lib/datadog/opentelemetry/configuration/settings.rb +226 -0
  345. data/lib/datadog/opentelemetry/ext.rb +9 -0
  346. data/lib/datadog/opentelemetry/logs.rb +98 -0
  347. data/lib/datadog/opentelemetry/metrics.rb +90 -0
  348. data/lib/datadog/opentelemetry/sdk/configurator.rb +65 -1
  349. data/lib/datadog/opentelemetry/sdk/id_generator.rb +16 -10
  350. data/lib/datadog/opentelemetry/sdk/logs_exporter.rb +30 -0
  351. data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +28 -0
  352. data/lib/datadog/opentelemetry/sdk/propagator.rb +9 -3
  353. data/lib/datadog/opentelemetry/sdk/span_processor.rb +4 -1
  354. data/lib/datadog/opentelemetry/sdk.rb +19 -0
  355. data/lib/datadog/opentelemetry/signal_configuration.rb +53 -0
  356. data/lib/datadog/opentelemetry.rb +4 -0
  357. data/lib/datadog/profiling/collectors/code_provenance.rb +71 -12
  358. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +52 -4
  359. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +13 -5
  360. data/lib/datadog/profiling/collectors/info.rb +18 -4
  361. data/lib/datadog/profiling/collectors/thread_context.rb +10 -5
  362. data/lib/datadog/profiling/component.rb +82 -40
  363. data/lib/datadog/profiling/exporter.rb +41 -12
  364. data/lib/datadog/profiling/ext/dir_monkey_patches.rb +24 -5
  365. data/lib/datadog/profiling/ext/exec_monkey_patch.rb +32 -0
  366. data/lib/datadog/profiling/ext.rb +0 -2
  367. data/lib/datadog/profiling/flush.rb +23 -11
  368. data/lib/datadog/profiling/http_transport.rb +21 -8
  369. data/lib/datadog/profiling/load_native_extension.rb +2 -2
  370. data/lib/datadog/profiling/profiler.rb +31 -14
  371. data/lib/datadog/profiling/scheduler.rb +10 -9
  372. data/lib/datadog/profiling/stack_recorder.rb +0 -8
  373. data/lib/datadog/profiling/tag_builder.rb +37 -3
  374. data/lib/datadog/profiling/tasks/exec.rb +8 -3
  375. data/lib/datadog/profiling/tasks/help.rb +1 -0
  376. data/lib/datadog/profiling/tasks/setup.rb +2 -2
  377. data/lib/datadog/profiling.rb +1 -3
  378. data/lib/datadog/ruby_version.rb +25 -0
  379. data/lib/datadog/single_step_instrument.rb +2 -2
  380. data/lib/datadog/symbol_database/component.rb +734 -0
  381. data/lib/datadog/symbol_database/configuration.rb +73 -0
  382. data/lib/datadog/symbol_database/extensions.rb +19 -0
  383. data/lib/datadog/symbol_database/extractor.rb +1110 -0
  384. data/lib/datadog/symbol_database/file_hash.rb +48 -0
  385. data/lib/datadog/symbol_database/logger.rb +43 -0
  386. data/lib/datadog/symbol_database/remote.rb +180 -0
  387. data/lib/datadog/symbol_database/scope.rb +102 -0
  388. data/lib/datadog/symbol_database/scope_batcher.rb +292 -0
  389. data/lib/datadog/symbol_database/service_version.rb +66 -0
  390. data/lib/datadog/symbol_database/symbol.rb +69 -0
  391. data/lib/datadog/symbol_database/transport/http/endpoint.rb +28 -0
  392. data/lib/datadog/symbol_database/transport/http.rb +45 -0
  393. data/lib/datadog/symbol_database/transport.rb +54 -0
  394. data/lib/datadog/symbol_database/uploader.rb +230 -0
  395. data/lib/datadog/symbol_database.rb +71 -0
  396. data/lib/datadog/tracing/buffer.rb +3 -3
  397. data/lib/datadog/tracing/component.rb +17 -17
  398. data/lib/datadog/tracing/configuration/dynamic.rb +2 -2
  399. data/lib/datadog/tracing/configuration/ext.rb +22 -0
  400. data/lib/datadog/tracing/configuration/settings.rb +96 -4
  401. data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +4 -1
  402. data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +4 -1
  403. data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +4 -1
  404. data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +4 -1
  405. data/lib/datadog/tracing/contrib/action_mailer/event.rb +4 -1
  406. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +10 -7
  407. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +28 -0
  408. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +3 -1
  409. data/lib/datadog/tracing/contrib/action_pack/utils.rb +1 -2
  410. data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +4 -1
  411. data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +5 -2
  412. data/lib/datadog/tracing/contrib/active_job/data_streams.rb +62 -0
  413. data/lib/datadog/tracing/contrib/active_job/events/discard.rb +5 -2
  414. data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +5 -2
  415. data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +5 -2
  416. data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +5 -2
  417. data/lib/datadog/tracing/contrib/active_job/events/perform.rb +5 -2
  418. data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +5 -2
  419. data/lib/datadog/tracing/contrib/active_job/log_injection.rb +21 -7
  420. data/lib/datadog/tracing/contrib/active_job/patcher.rb +17 -1
  421. data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +1 -1
  422. data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +3 -4
  423. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +2 -2
  424. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +1 -1
  425. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +2 -5
  426. data/lib/datadog/tracing/contrib/active_record/utils.rb +1 -1
  427. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +2 -5
  428. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +1 -4
  429. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +2 -2
  430. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +6 -8
  431. data/lib/datadog/tracing/contrib/component.rb +3 -3
  432. data/lib/datadog/tracing/contrib/configurable.rb +18 -3
  433. data/lib/datadog/tracing/contrib/configuration/resolver.rb +14 -4
  434. data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +1 -5
  435. data/lib/datadog/tracing/contrib/dalli/integration.rb +4 -1
  436. data/lib/datadog/tracing/contrib/dalli/quantize.rb +1 -1
  437. data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +2 -0
  438. data/lib/datadog/tracing/contrib/delayed_job/server_internal_tracer/worker.rb +1 -0
  439. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +2 -6
  440. data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +2 -2
  441. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +5 -1
  442. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +5 -6
  443. data/lib/datadog/tracing/contrib/ethon/ext.rb +1 -0
  444. data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +1 -8
  445. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +16 -5
  446. data/lib/datadog/tracing/contrib/excon/ext.rb +1 -0
  447. data/lib/datadog/tracing/contrib/excon/middleware.rb +3 -7
  448. data/lib/datadog/tracing/contrib/ext.rb +3 -1
  449. data/lib/datadog/tracing/contrib/extensions.rb +19 -2
  450. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +16 -9
  451. data/lib/datadog/tracing/contrib/faraday/ext.rb +1 -0
  452. data/lib/datadog/tracing/contrib/faraday/middleware.rb +3 -7
  453. data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +7 -3
  454. data/lib/datadog/tracing/contrib/grape/endpoint.rb +10 -7
  455. data/lib/datadog/tracing/contrib/grape/instrumentation.rb +13 -8
  456. data/lib/datadog/tracing/contrib/grape/patcher.rb +6 -1
  457. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +7 -0
  458. data/lib/datadog/tracing/contrib/graphql/ext.rb +1 -0
  459. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +75 -44
  460. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +5 -2
  461. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +3 -7
  462. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +3 -7
  463. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +2 -0
  464. data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
  465. data/lib/datadog/tracing/contrib/grpc.rb +1 -0
  466. data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +1 -0
  467. data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +1 -0
  468. data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +1 -0
  469. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +16 -5
  470. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +2 -0
  471. data/lib/datadog/tracing/contrib/http/ext.rb +1 -0
  472. data/lib/datadog/tracing/contrib/http/instrumentation.rb +4 -8
  473. data/lib/datadog/tracing/contrib/http/integration.rb +0 -2
  474. data/lib/datadog/tracing/contrib/http.rb +1 -0
  475. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +16 -5
  476. data/lib/datadog/tracing/contrib/httpclient/ext.rb +1 -0
  477. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +7 -7
  478. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +16 -5
  479. data/lib/datadog/tracing/contrib/httprb/ext.rb +1 -0
  480. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +4 -8
  481. data/lib/datadog/tracing/contrib/kafka/event.rb +1 -0
  482. data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +66 -0
  483. data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +66 -0
  484. data/lib/datadog/tracing/contrib/kafka/patcher.rb +14 -0
  485. data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +5 -1
  486. data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +2 -0
  487. data/lib/datadog/tracing/contrib/karafka/ext.rb +1 -0
  488. data/lib/datadog/tracing/contrib/karafka/framework.rb +30 -0
  489. data/lib/datadog/tracing/contrib/karafka/monitor.rb +11 -0
  490. data/lib/datadog/tracing/contrib/karafka/patcher.rb +35 -4
  491. data/lib/datadog/tracing/contrib/karafka.rb +1 -0
  492. data/lib/datadog/tracing/contrib/mongodb/parsers.rb +5 -5
  493. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +5 -8
  494. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +6 -0
  495. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +3 -6
  496. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +2 -6
  497. data/lib/datadog/tracing/contrib/opensearch/quantize.rb +2 -2
  498. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +6 -0
  499. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +15 -18
  500. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +6 -8
  501. data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +13 -0
  502. data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +6 -2
  503. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +24 -0
  504. data/lib/datadog/tracing/contrib/que/configuration/settings.rb +5 -2
  505. data/lib/datadog/tracing/contrib/que/ext.rb +1 -0
  506. data/lib/datadog/tracing/contrib/que/tracer.rb +1 -0
  507. data/lib/datadog/tracing/contrib/racecar/event.rb +1 -5
  508. data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +11 -1
  509. data/lib/datadog/tracing/contrib/rack/ext.rb +28 -0
  510. data/lib/datadog/tracing/contrib/rack/header_tagging.rb +23 -0
  511. data/lib/datadog/tracing/contrib/rack/middlewares.rb +62 -27
  512. data/lib/datadog/tracing/contrib/rack/patcher.rb +2 -2
  513. data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
  514. data/lib/datadog/tracing/contrib/rack/route_inference.rb +67 -0
  515. data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +119 -1
  516. data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +5 -2
  517. data/lib/datadog/tracing/contrib/rails/ext.rb +1 -0
  518. data/lib/datadog/tracing/contrib/rails/log_injection.rb +1 -1
  519. data/lib/datadog/tracing/contrib/rails/middlewares.rb +2 -2
  520. data/lib/datadog/tracing/contrib/rails/patcher.rb +0 -1
  521. data/lib/datadog/tracing/contrib/rails/runner.rb +3 -1
  522. data/lib/datadog/tracing/contrib/rake/instrumentation.rb +6 -4
  523. data/lib/datadog/tracing/contrib/redis/quantize.rb +1 -1
  524. data/lib/datadog/tracing/contrib/redis/tags.rb +1 -6
  525. data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +2 -0
  526. data/lib/datadog/tracing/contrib/registerable.rb +11 -0
  527. data/lib/datadog/tracing/contrib/resque/resque_job.rb +1 -0
  528. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +5 -2
  529. data/lib/datadog/tracing/contrib/rest_client/ext.rb +1 -0
  530. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +5 -6
  531. data/lib/datadog/tracing/contrib/roda/ext.rb +1 -0
  532. data/lib/datadog/tracing/contrib/roda/instrumentation.rb +7 -2
  533. data/lib/datadog/tracing/contrib/sequel/database.rb +1 -0
  534. data/lib/datadog/tracing/contrib/sequel/dataset.rb +1 -0
  535. data/lib/datadog/tracing/contrib/sequel/utils.rb +2 -7
  536. data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +1 -0
  537. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +1 -0
  538. data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +5 -1
  539. data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +2 -0
  540. data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
  541. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/heartbeat.rb +2 -0
  542. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/job_fetch.rb +1 -0
  543. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/redis_info.rb +1 -0
  544. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/scheduled_poller.rb +2 -0
  545. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/stop.rb +1 -0
  546. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +3 -2
  547. data/lib/datadog/tracing/contrib/sidekiq/utils.rb +1 -1
  548. data/lib/datadog/tracing/contrib/sidekiq.rb +1 -0
  549. data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +5 -1
  550. data/lib/datadog/tracing/contrib/sinatra/ext.rb +1 -0
  551. data/lib/datadog/tracing/contrib/sinatra/framework.rb +1 -1
  552. data/lib/datadog/tracing/contrib/sinatra/tracer.rb +1 -0
  553. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +4 -1
  554. data/lib/datadog/tracing/contrib/sneakers/integration.rb +15 -4
  555. data/lib/datadog/tracing/contrib/sneakers/tracer.rb +1 -0
  556. data/lib/datadog/tracing/contrib/status_range_matcher.rb +13 -1
  557. data/lib/datadog/tracing/contrib/stripe/request.rb +1 -1
  558. data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +1 -0
  559. data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +6 -0
  560. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +4 -6
  561. data/lib/datadog/tracing/contrib/utils/quantization/{hash.rb → hash_formatter.rb} +4 -2
  562. data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +31 -0
  563. data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +50 -0
  564. data/lib/datadog/tracing/contrib/waterdrop/ext.rb +18 -0
  565. data/lib/datadog/tracing/contrib/waterdrop/integration.rb +43 -0
  566. data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +46 -0
  567. data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +49 -0
  568. data/lib/datadog/tracing/contrib/waterdrop/producer.rb +50 -0
  569. data/lib/datadog/tracing/contrib/waterdrop.rb +42 -0
  570. data/lib/datadog/tracing/contrib.rb +9 -0
  571. data/lib/datadog/tracing/diagnostics/environment_logger.rb +4 -2
  572. data/lib/datadog/tracing/distributed/baggage.rb +64 -8
  573. data/lib/datadog/tracing/distributed/datadog.rb +13 -11
  574. data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +1 -14
  575. data/lib/datadog/tracing/distributed/propagation.rb +35 -3
  576. data/lib/datadog/tracing/distributed/trace_context.rb +85 -62
  577. data/lib/datadog/tracing/event.rb +1 -1
  578. data/lib/datadog/tracing/ext.rb +9 -0
  579. data/lib/datadog/tracing/metadata/ext.rb +23 -1
  580. data/lib/datadog/tracing/metadata/tagging.rb +2 -2
  581. data/lib/datadog/tracing/pipeline.rb +1 -1
  582. data/lib/datadog/tracing/remote.rb +36 -13
  583. data/lib/datadog/tracing/sampling/ext.rb +2 -0
  584. data/lib/datadog/tracing/sampling/priority_sampler.rb +16 -1
  585. data/lib/datadog/tracing/sampling/rate_sampler.rb +8 -19
  586. data/lib/datadog/tracing/sampling/rule.rb +1 -1
  587. data/lib/datadog/tracing/sampling/rule_sampler.rb +54 -25
  588. data/lib/datadog/tracing/sampling/span/rule_parser.rb +2 -2
  589. data/lib/datadog/tracing/span.rb +1 -1
  590. data/lib/datadog/tracing/span_event.rb +2 -2
  591. data/lib/datadog/tracing/span_operation.rb +34 -10
  592. data/lib/datadog/tracing/sync_writer.rb +0 -1
  593. data/lib/datadog/tracing/trace_digest.rb +7 -0
  594. data/lib/datadog/tracing/trace_operation.rb +123 -16
  595. data/lib/datadog/tracing/tracer.rb +82 -23
  596. data/lib/datadog/tracing/transport/http/client.rb +12 -26
  597. data/lib/datadog/tracing/transport/http/traces.rb +2 -50
  598. data/lib/datadog/tracing/transport/http.rb +15 -9
  599. data/lib/datadog/tracing/transport/io/client.rb +6 -9
  600. data/lib/datadog/tracing/transport/io/traces.rb +28 -34
  601. data/lib/datadog/tracing/transport/trace_formatter.rb +22 -0
  602. data/lib/datadog/tracing/transport/traces.rb +13 -81
  603. data/lib/datadog/tracing/workers.rb +2 -1
  604. data/lib/datadog/tracing/writer.rb +1 -1
  605. data/lib/datadog/version.rb +2 -2
  606. data/lib/datadog.rb +8 -1
  607. metadata +185 -36
  608. data/ext/datadog_profiling_native_extension/clock_id_noop.c +0 -21
  609. data/ext/libdatadog_api/macos_development.md +0 -26
  610. data/lib/datadog/appsec/configuration/settings.rb +0 -400
  611. data/lib/datadog/appsec/contrib/rails/ext.rb +0 -13
  612. data/lib/datadog/core/remote/transport/http/api.rb +0 -53
  613. data/lib/datadog/core/remote/transport/http/client.rb +0 -49
  614. data/lib/datadog/core/telemetry/transport/http/api.rb +0 -43
  615. data/lib/datadog/core/telemetry/transport/http/client.rb +0 -49
  616. data/lib/datadog/core/transport/http/api/spec.rb +0 -36
  617. data/lib/datadog/di/configuration/settings.rb +0 -212
  618. data/lib/datadog/di/transport/http/api.rb +0 -42
  619. data/lib/datadog/di/transport/http/client.rb +0 -47
  620. data/lib/datadog/error_tracking/configuration/settings.rb +0 -63
  621. data/lib/datadog/opentelemetry/api/baggage.rbs +0 -26
  622. data/lib/datadog/tracing/transport/http/api.rb +0 -44
  623. data/lib/datadog/tracing/workers/trace_writer.rb +0 -199
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../input_peeker'
3
4
  require_relative '../../../instrumentation/gateway/argument'
4
5
  require_relative '../../../../core/header_collection'
5
6
  require_relative '../../../../tracing/client_ip'
@@ -23,16 +24,12 @@ module Datadog
23
24
  end
24
25
 
25
26
  def query
26
- # Downstream libddwaf expects keys and values to be extractable
27
- # separately so we can't use [[k, v], ...]. We also want to allow
28
- # duplicate keys, so we use {k => [v, ...], ...} instead, taking into
29
- # account that {k => [v1, v2, ...], ...} is possible for duplicate keys.
30
- request.query_string.split('&').each.with_object({}) do |e, hash|
31
- k, v = e.split('=').map { |s| CGI.unescape(s) }
32
- hash[k] ||= []
33
-
34
- hash[k] << v
35
- end
27
+ ::Rack::Utils.parse_query(request.query_string)
28
+ rescue => e
29
+ Datadog.logger.debug { "AppSec: Failed to parse request query string: #{e.class}: #{e.message}" }
30
+ AppSec.telemetry.report(e, description: 'AppSec: Failed to parse request query string')
31
+
32
+ {}
36
33
  end
37
34
 
38
35
  def method
@@ -79,12 +76,54 @@ module Datadog
79
76
  end
80
77
 
81
78
  def form_hash
82
- # force form data processing
79
+ # NOTE: Rack populates `rack.request.form_hash` only as a side effect
80
+ # of {::Rack::Request#POST}, which reads and parses the body.
83
81
  request.POST if request.form_data?
84
82
 
85
- # usually Hash<String,String> but can be a more complex
86
- # Hash<String,String||Array||Hash> when e.g coming from JSON
83
+ # usually Hash[String, String] but can be a more complex
84
+ # Hash[String, (String|Array|Hash)] when e.g coming from JSON
87
85
  env['rack.request.form_hash']
86
+ rescue => e
87
+ Datadog.logger.debug { "AppSec: Failed to parse request body: #{e.class}: #{e.message}" }
88
+ AppSec.telemetry.report(e, description: 'AppSec: Failed to parse request body')
89
+
90
+ nil
91
+ end
92
+
93
+ # Returns the request body size in bytes using all available methods,
94
+ # or nil when the size cannot be measured within the limit
95
+ #
96
+ # NOTE: The priority of the measurement is the following:
97
+ # size if it's known, content-length if provided, and buffering
98
+ # to the limit if unknown-length
99
+ #
100
+ # WARNING: The buffering path adds overhead for streaming web-servers
101
+ # (Rack 3+) when the body length is unknown
102
+ def body_bytesize(limit)
103
+ io = request.body
104
+
105
+ return 0 unless io
106
+ return io.size if io.respond_to?(:size)
107
+
108
+ # NOTE: {::Rack::Request#content_length} is a plain `CONTENT_LENGTH`
109
+ # getter forces no body read
110
+ content_length = request.content_length
111
+ return content_length.to_i if content_length
112
+
113
+ # NOTE: A parsed-body cache without a raw byte count means the input
114
+ # stream was consumed before measurement, consider it unknown-length
115
+ return if env.key?('rack.request.form_hash')
116
+
117
+ InputPeeker.peek_bytesize(env, limit: limit)
118
+ end
119
+
120
+ # Whether a request body can be collected without forcing a parse:
121
+ # either form data parseable on demand, or a body already parsed upstream
122
+ #
123
+ # NOTE: Rack does not parse JSON itself, a body parser middleware such as
124
+ # {Rack::JSONBodyParser} populates the form hash read by {#form_hash}
125
+ def collectable_body?
126
+ request.form_data? || request.parseable_data? || env.key?('rack.request.form_hash')
88
127
  end
89
128
 
90
129
  def client_ip
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative '../ext'
4
4
  require_relative '../../../event'
5
+ require_relative '../../../trace_keeper'
5
6
  require_relative '../../../security_event'
6
7
  require_relative '../../../instrumentation/gateway'
7
8
 
@@ -23,7 +24,7 @@ module Datadog
23
24
  end
24
25
 
25
26
  def watch_request(gateway = Instrumentation.gateway)
26
- gateway.watch('rack.request', :appsec) do |stack, gateway_request|
27
+ gateway.watch('rack.request') do |stack, gateway_request|
27
28
  context = gateway_request.env[AppSec::Ext::CONTEXT_KEY]
28
29
 
29
30
  persistent_data = {
@@ -38,14 +39,16 @@ module Datadog
38
39
 
39
40
  result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
40
41
 
41
- if result.match? || !result.derivatives.empty?
42
+ if result.match? || !result.attributes.empty?
42
43
  context.events.push(
43
44
  AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
44
45
  )
45
46
  end
46
47
 
47
48
  if result.match?
48
- AppSec::Event.tag_and_keep!(context, result)
49
+ AppSec::Event.tag(context, result)
50
+ TraceKeeper.keep!(context.trace) if result.keep?
51
+
49
52
  AppSec::ActionsHandler.handle(result.actions)
50
53
  end
51
54
 
@@ -54,7 +57,7 @@ module Datadog
54
57
  end
55
58
 
56
59
  def watch_response(gateway = Instrumentation.gateway)
57
- gateway.watch('rack.response', :appsec) do |stack, gateway_response|
60
+ gateway.watch('rack.response') do |stack, gateway_response|
58
61
  context = gateway_response.context
59
62
 
60
63
  persistent_data = {
@@ -66,7 +69,8 @@ module Datadog
66
69
  result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
67
70
 
68
71
  if result.match?
69
- AppSec::Event.tag_and_keep!(context, result)
72
+ AppSec::Event.tag(context, result)
73
+ TraceKeeper.keep!(context.trace) if result.keep?
70
74
 
71
75
  context.events.push(
72
76
  AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
@@ -80,17 +84,39 @@ module Datadog
80
84
  end
81
85
 
82
86
  def watch_request_body(gateway = Instrumentation.gateway)
83
- gateway.watch('rack.request.body', :appsec) do |stack, gateway_request|
87
+ gateway.watch('rack.request.body') do |stack, gateway_request|
84
88
  context = gateway_request.env[AppSec::Ext::CONTEXT_KEY]
85
89
 
86
- persistent_data = {
87
- 'server.request.body' => gateway_request.form_hash
88
- }
90
+ request = gateway_request.request
91
+ next stack.call(request) unless gateway_request.collectable_body?
92
+
93
+ # NOTE: A limit of 0 disables request body collection entirely.
94
+ limit = Datadog.configuration.appsec.body_parsing_size_limit
95
+ next stack.call(request) if limit.zero?
96
+
97
+ persistent_data = {}
98
+ byte_length = gateway_request.body_bytesize(limit)
99
+
100
+ if byte_length
101
+ persistent_data['server.request.body.byte_length'] = byte_length
102
+
103
+ if byte_length <= limit
104
+ body = gateway_request.form_hash
105
+ persistent_data['server.request.body'] = body if body
106
+ end
107
+ # NOTE: Body was parsed before measurement, keep byte_length unset
108
+ elsif gateway_request.env.key?('rack.request.form_hash')
109
+ body = gateway_request.env['rack.request.form_hash']
110
+ persistent_data['server.request.body'] = body if body
111
+ end
112
+
113
+ next stack.call(request) if persistent_data.empty?
89
114
 
90
115
  result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
91
116
 
92
117
  if result.match?
93
- AppSec::Event.tag_and_keep!(context, result)
118
+ AppSec::Event.tag(context, result)
119
+ TraceKeeper.keep!(context.trace) if result.keep?
94
120
 
95
121
  context.events.push(
96
122
  AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
@@ -108,20 +134,15 @@ module Datadog
108
134
  # somewhere closer to identity related monitor.
109
135
  # WARNING: The Gateway is a subject of refactoring
110
136
  def watch_request_finish(gateway = Instrumentation.gateway)
111
- gateway.watch('rack.request.finish', :appsec) do |stack, gateway_request|
137
+ gateway.watch('rack.request.finish') do |stack, gateway_request|
112
138
  context = gateway_request.env[AppSec::Ext::CONTEXT_KEY]
113
139
 
114
- if context.span.nil? || !gateway.pushed?('appsec.events.user_lifecycle')
115
- next stack.call(gateway_request.request)
116
- end
140
+ next stack.call(gateway_request.request) if context.span.nil?
117
141
 
118
142
  gateway_request.headers.each do |name, value|
119
- if !Ext::COLLECTABLE_REQUEST_HEADERS.include?(name) &&
120
- !Ext::IDENTITY_COLLECTABLE_REQUEST_HEADERS.include?(name)
121
- next
143
+ if context.state[:has_identity_event] && Ext::IDENTITY_COLLECTABLE_REQUEST_HEADERS.include?(name)
144
+ context.span["http.request.headers.#{name}"] ||= value
122
145
  end
123
-
124
- context.span["http.request.headers.#{name}"] ||= value
125
146
  end
126
147
 
127
148
  stack.call(gateway_request.request)
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stringio'
4
+ require_relative 'buffered_input'
5
+ require_relative '../../utils/http/body_reader'
6
+
7
+ module Datadog
8
+ module AppSec
9
+ module Contrib
10
+ module Rack
11
+ # Peeks at `rack.input` without changing what downstream Rack code can read
12
+ #
13
+ # @api private
14
+ module InputPeeker
15
+ module_function
16
+
17
+ # Peeks at `env['rack.input']` and returns the body bytesize when it
18
+ # can be measured within the given limit
19
+ #
20
+ # NOTE: Over-limit bodies cannot be fully measured, so returning `nil`
21
+ # is the tradeoff we accept
22
+ #
23
+ # WARNING: For forward-only input, replaces `env['rack.input']` with a
24
+ # replay stream over the peeked bytes, preserving the rest
25
+ # of the original stream
26
+ #
27
+ # @param env [Hash] Rack environment
28
+ # @param limit [Integer] Maximum body bytesize to measure
29
+ # @return [Integer, nil] `Integer` bytesize when measured within
30
+ # `limit`, including `0`; `nil` when input is missing, over the
31
+ # limit, or cannot be preserved for downstream reads
32
+ def peek_bytesize(env, limit:)
33
+ rack_input = env['rack.input']
34
+ return unless rack_input
35
+
36
+ rewindable = rewind? && rack_input.respond_to?(:rewind)
37
+
38
+ # NOTE: Rack 2 requires `rack.input` to be rewindable. Rewind before peeking
39
+ # in case an upstream framework already consumed part of the stream
40
+ return if rewindable && !rewind(rack_input)
41
+
42
+ # NOTE: Read one byte past the limit to distinguish an exact-limit body
43
+ # from an over-limit body without reading the whole stream.
44
+ buffer = Utils::HTTP::BodyReader.read_stream(rack_input, limit: limit)
45
+ over_limit = buffer.bytesize > limit
46
+
47
+ if rewindable
48
+ # NOTE: If we cannot rewind after peeking, downstream code would observe
49
+ # a partially consumed body. Treat it as not safely collectable
50
+ return unless rewind(rack_input)
51
+ else
52
+ env['rack.input'] = if over_limit
53
+ BufferedInput.new(rack_input, buffer: StringIO.new(buffer))
54
+ else
55
+ StringIO.new(buffer)
56
+ end
57
+ end
58
+
59
+ over_limit ? nil : buffer.bytesize
60
+ end
61
+
62
+ private_class_method def rewind?
63
+ return @rewind if defined?(@rewind)
64
+
65
+ @rewind = ::Gem::Version.new(::Rack.release) < ::Gem::Version.new('3')
66
+ end
67
+
68
+ private_class_method def rewind(io)
69
+ io.rewind
70
+ true
71
+ rescue => e
72
+ Datadog.logger.debug { "AppSec: Failed to rewind `rack.input`: #{e.class}: #{e.message}" }
73
+ false
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -27,7 +27,7 @@ module Datadog
27
27
  end
28
28
 
29
29
  def self.compatible?
30
- super && version >= MINIMUM_VERSION
30
+ !!(super && (version&.>= MINIMUM_VERSION))
31
31
  end
32
32
 
33
33
  def self.auto_instrument?
@@ -2,15 +2,19 @@
2
2
 
3
3
  require 'json'
4
4
 
5
+ require_relative 'response_body'
5
6
  require_relative 'gateway/request'
6
7
  require_relative 'gateway/response'
7
8
 
8
9
  require_relative '../../event'
9
10
  require_relative '../../response'
10
11
  require_relative '../../api_security'
12
+ require_relative '../../default_header_tags'
13
+ require_relative '../../route_normalizer'
11
14
  require_relative '../../security_event'
12
15
  require_relative '../../instrumentation/gateway'
13
16
 
17
+ require_relative '../../../core/header_collection'
14
18
  require_relative '../../../tracing/client_ip'
15
19
  require_relative '../../../tracing/contrib/rack/header_collection'
16
20
 
@@ -18,17 +22,6 @@ module Datadog
18
22
  module AppSec
19
23
  module Contrib
20
24
  module Rack
21
- WAF_VENDOR_HEADERS_TAGS = %w[
22
- X-Amzn-Trace-Id
23
- Cloudfront-Viewer-Ja3-Fingerprint
24
- Cf-Ray
25
- X-Cloud-Trace-Context
26
- X-Appgw-Trace-id
27
- X-SigSci-RequestID
28
- X-SigSci-Tags
29
- Akamai-User-Risk
30
- ].map(&:downcase).freeze
31
-
32
25
  # Topmost Rack middleware for AppSec
33
26
  # This should be inserted just below Datadog::Tracing::Contrib::Rack::TraceMiddleware
34
27
  class RequestMiddleware
@@ -36,7 +29,6 @@ module Datadog
36
29
  @app = app
37
30
 
38
31
  @oneshot_tags_sent = false
39
- @rack_headers = {}
40
32
  end
41
33
 
42
34
  # rubocop:disable Metrics/MethodLength
@@ -85,6 +77,8 @@ module Datadog
85
77
  nil
86
78
  end
87
79
 
80
+ add_normalized_route_tag(ctx, env)
81
+
88
82
  if interrupt_params
89
83
  ctx.mark_as_interrupted!
90
84
  http_response = AppSec::Response.from_interrupt_params(interrupt_params, env['HTTP_ACCEPT']).to_rack
@@ -107,13 +101,12 @@ module Datadog
107
101
 
108
102
  if AppSec::APISecurity.enabled? && AppSec::APISecurity.sample_trace?(ctx.trace) &&
109
103
  AppSec::APISecurity.sample?(gateway_request.request, tmp_response.response)
110
- ctx.events.push(
111
- AppSec::SecurityEvent.new(ctx.extract_schema, trace: ctx.trace, span: ctx.span)
112
- )
104
+ ctx.extract_schema!
113
105
  end
114
106
 
115
- AppSec::Event.record(ctx, request: gateway_request, response: gateway_response)
107
+ AppSec::Event.record(ctx, request: gateway_request)
116
108
 
109
+ add_response_tags(ctx, tmp_response)
117
110
  http_response
118
111
  ensure
119
112
  if ctx
@@ -161,7 +154,7 @@ module Datadog
161
154
  if context.waf_runner_ruleset_version
162
155
  span.set_tag('_dd.appsec.event_rules.version', context.waf_runner_ruleset_version)
163
156
 
164
- unless @oneshot_tags_sent
157
+ unless oneshot_tags_sent?
165
158
  # Small race condition, but it's inoccuous: worst case the tags
166
159
  # are sent a couple of times more than expected
167
160
  @oneshot_tags_sent = true
@@ -179,33 +172,55 @@ module Datadog
179
172
  end
180
173
  # standard:enable Metrics/MethodLength
181
174
 
182
- # standard:disable Metrics/MethodLength
183
175
  def add_request_tags(context, env)
184
176
  span = context.span
185
-
186
177
  return unless span
187
178
 
188
- # Always add WAF vendors headers
189
- WAF_VENDOR_HEADERS_TAGS.each do |lowercase_header|
190
- rack_header = to_rack_header(lowercase_header)
191
- span.set_tag("http.request.headers.#{lowercase_header}", env[rack_header]) if env[rack_header]
192
- end
193
-
194
- if span && span.get_tag(Tracing::Metadata::Ext::HTTP::TAG_CLIENT_IP).nil?
195
- request_header_collection = Datadog::Tracing::Contrib::Rack::Header::RequestHeaderCollection.new(env)
179
+ headers = Tracing::Contrib::Rack::Header::RequestHeaderCollection.new(env)
180
+ AppSec::DefaultHeaderTags.tag_request(span, headers)
196
181
 
182
+ if span.get_tag(Tracing::Metadata::Ext::HTTP::TAG_CLIENT_IP).nil?
197
183
  # always collect client ip, as this is part of AppSec provided functionality
198
184
  Datadog::Tracing::ClientIp.set_client_ip_tag!(
199
- span,
200
- headers: request_header_collection,
201
- remote_ip: env['REMOTE_ADDR']
185
+ span, headers: headers, remote_ip: env['REMOTE_ADDR']
202
186
  )
203
187
  end
204
188
  end
205
- # standard:enable Metrics/MethodLength
206
189
 
207
- def to_rack_header(header)
208
- @rack_headers[header] ||= Datadog::Tracing::Contrib::Rack::Header.to_rack_header(header)
190
+ def add_response_tags(context, response)
191
+ span = context.span
192
+ return unless span
193
+
194
+ AppSec::DefaultHeaderTags.tag_response(
195
+ span, Datadog::Core::HeaderCollection.from_hash(response.headers)
196
+ )
197
+
198
+ unless response.headers.key?('content-length')
199
+ length = ResponseBody.content_length(response.body)
200
+ span.set_tag('http.response.headers.content-length', length.to_s) if length
201
+ end
202
+ end
203
+
204
+ def add_normalized_route_tag(context, env)
205
+ return unless AppSec::APISecurity.enabled?
206
+
207
+ span = context.span
208
+ return unless span
209
+
210
+ pattern = context.trace&.get_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE)
211
+ return unless pattern
212
+
213
+ # NOTE: To build full path that covers mounted engines we need to add
214
+ # pre-computed by Tracer route path tag to the normalized route
215
+ prefix = context.trace&.get_tag(Tracing::Metadata::Ext::HTTP::TAG_ROUTE_PATH) || env['SCRIPT_NAME']
216
+ normalized_route = RouteNormalizer.extract_normalized_route(env, prefix: prefix, pattern: pattern)
217
+ return unless normalized_route
218
+
219
+ span.set_tag(AppSec::Ext::TAG_NORMALIZED_ROUTE, "#{prefix}#{normalized_route}")
220
+ end
221
+
222
+ def oneshot_tags_sent?
223
+ @oneshot_tags_sent
209
224
  end
210
225
  end
211
226
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module AppSec
5
+ module Contrib
6
+ module Rack
7
+ module ResponseBody
8
+ # NOTE: We compute content length only for fixed-size response bodies,
9
+ # ignoring streaming bodies to avoid buffering.
10
+ #
11
+ # On Rack 3.x, `body.to_ary` on a BodyProxy triggers `close` on all
12
+ # nested BodyProxy layers. This is safe because web servers, like Puma
13
+ # handles already-closed bodies (its own `to_ary` becomes a no-op).
14
+ #
15
+ # @see Puma::Response#prepare_response
16
+ # @see https://github.com/puma/puma/blob/b1271222cbf21868f3fb64154caa4d03936a7b9e/lib/puma/response.rb#L165-L168
17
+ def self.content_length(body)
18
+ return unless body.respond_to?(:to_ary)
19
+
20
+ # NOTE: When `to_ary` exists but returns `nil`, the body will be
21
+ # transferred in chunks and we can't compute content length
22
+ # without buffering it.
23
+ body_ary = body.to_ary
24
+ return unless body_ary.is_a?(Array)
25
+
26
+ body_ary.sum { |part| part.is_a?(String) ? part.bytesize : 0 }
27
+ rescue => e
28
+ AppSec.telemetry.report(e, description: 'AppSec: Failed to compute body content length')
29
+
30
+ nil
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../../rack/input_peeker'
3
4
  require_relative '../../../instrumentation/gateway/argument'
4
5
 
5
6
  module Datadog
@@ -46,19 +47,57 @@ module Datadog
46
47
  body = request.env['action_dispatch.request.request_parameters']
47
48
 
48
49
  return if body.nil?
50
+ return body unless request.env['action_dispatch.request.path_parameters']
49
51
 
50
52
  body.reject do |k, _v|
51
53
  request.env['action_dispatch.request.path_parameters'].key?(k)
52
54
  end
55
+ rescue => e
56
+ Datadog.logger.debug { "AppSec: Failed to parse request body: #{e.class}: #{e.message}" }
57
+ AppSec.telemetry.report(e, description: 'AppSec: Failed to parse request body')
58
+
59
+ nil
53
60
  end
54
61
 
55
62
  def route_params
56
63
  excluded = [:controller, :action]
57
64
 
58
- request.env['action_dispatch.request.path_parameters'].reject do |k, _v|
65
+ request.env.fetch('action_dispatch.request.path_parameters', {}).reject do |k, _v|
59
66
  excluded.include?(k)
60
67
  end
61
68
  end
69
+
70
+ # Returns the request body size in bytes using all available methods,
71
+ # or nil when the size cannot be measured within the limit
72
+ #
73
+ # NOTE: The priority of the measurement is the following:
74
+ # raw posted data, raw form vars, size if known, raw
75
+ # Content-Length, then buffering to the limit if unknown-length
76
+ def body_bytesize(limit)
77
+ raw_body = env['RAW_POST_DATA']
78
+ return raw_body.bytesize if raw_body
79
+
80
+ form_vars = env['rack.request.form_vars']
81
+ return form_vars.bytesize if form_vars
82
+
83
+ io = request.body
84
+ return 0 unless io
85
+ return io.size if io.respond_to?(:size)
86
+
87
+ # NOTE: Read raw `CONTENT_LENGTH` as {ActionDispatch::Request#content_length}
88
+ # drains `rack.input` into `RAW_POST_DATA` on chunked Transfer-Encoding
89
+ content_length = env['CONTENT_LENGTH']
90
+ return content_length.to_i if content_length
91
+
92
+ # NOTE: An already-read body (e.g. late-parsed multipart on Rack 3+) peeks
93
+ # as 0, so we skip byte_length but still collect the parsed body
94
+ begin
95
+ Rack::InputPeeker.peek_bytesize(env, limit: limit)
96
+ rescue => e
97
+ Datadog.logger.debug { "AppSec: Failed to measure Rails request body: #{e.class}: #{e.message}" }
98
+ nil
99
+ end
100
+ end
62
101
  end
63
102
  end
64
103
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../../../event'
4
+ require_relative '../../../trace_keeper'
4
5
  require_relative '../../../security_event'
5
6
  require_relative '../../../instrumentation/gateway'
6
7
 
@@ -20,14 +21,30 @@ module Datadog
20
21
  end
21
22
 
22
23
  def watch_request_action(gateway = Instrumentation.gateway)
23
- gateway.watch('rails.request.action', :appsec) do |stack, gateway_request|
24
+ gateway.watch('rails.request.action') do |stack, gateway_request|
24
25
  context = gateway_request.env[AppSec::Ext::CONTEXT_KEY]
26
+ limit = Datadog.configuration.appsec.body_parsing_size_limit
25
27
 
26
28
  persistent_data = {
27
- 'server.request.body' => gateway_request.parsed_body,
28
29
  'server.request.path_params' => gateway_request.route_params
29
30
  }
30
31
 
32
+ unless limit.zero?
33
+ byte_length = gateway_request.body_bytesize(limit)
34
+
35
+ if byte_length
36
+ # NOTE: Params may be parsed before this hook, leaving the
37
+ # body stream at EOF. Keep byte_length unset for that
38
+ # case, but still inspect cached params
39
+ persistent_data['server.request.body.byte_length'] = byte_length if byte_length.positive?
40
+
41
+ if byte_length <= limit
42
+ body = gateway_request.parsed_body
43
+ persistent_data['server.request.body'] = body unless body.nil? || body.empty?
44
+ end
45
+ end
46
+ end
47
+
31
48
  result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
32
49
 
33
50
  if result.match?
@@ -35,7 +52,9 @@ module Datadog
35
52
  AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
36
53
  )
37
54
 
38
- AppSec::Event.tag_and_keep!(context, result)
55
+ AppSec::Event.tag(context, result)
56
+ TraceKeeper.keep!(context.trace) if result.keep?
57
+
39
58
  AppSec::ActionsHandler.handle(result.actions)
40
59
  end
41
60
 
@@ -44,7 +63,7 @@ module Datadog
44
63
  end
45
64
 
46
65
  def watch_response_body_json(gateway = Instrumentation.gateway)
47
- gateway.watch('rails.response.body.json', :appsec) do |stack, container|
66
+ gateway.watch('rails.response.body.json') do |stack, container|
48
67
  context = container.context
49
68
 
50
69
  persistent_data = {
@@ -57,7 +76,9 @@ module Datadog
57
76
  AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
58
77
  )
59
78
 
60
- AppSec::Event.tag_and_keep!(context, result)
79
+ AppSec::Event.tag(context, result)
80
+ TraceKeeper.keep!(context.trace) if result.keep?
81
+
61
82
  AppSec::ActionsHandler.handle(result.actions)
62
83
  end
63
84
 
@@ -26,7 +26,7 @@ module Datadog
26
26
  end
27
27
 
28
28
  def self.compatible?
29
- super && version >= MINIMUM_VERSION
29
+ !!(super && (version&.>= MINIMUM_VERSION))
30
30
  end
31
31
 
32
32
  def self.auto_instrument?