datadog 2.17.0 → 2.37.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 (765) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +686 -1
  3. data/README.md +0 -1
  4. data/ext/LIBDATADOG_DEVELOPMENT.md +3 -0
  5. data/ext/datadog_profiling_native_extension/clock_id.h +9 -1
  6. data/ext/datadog_profiling_native_extension/clock_id_from_mach.c +66 -0
  7. data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +3 -2
  8. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +344 -126
  9. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +4 -4
  10. data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +3 -2
  11. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +18 -4
  12. data/ext/datadog_profiling_native_extension/collectors_stack.c +314 -91
  13. data/ext/datadog_profiling_native_extension/collectors_stack.h +26 -3
  14. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +680 -352
  15. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +18 -5
  16. data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +239 -0
  17. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +65 -1
  18. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +40 -1
  19. data/ext/datadog_profiling_native_extension/encoded_profile.c +2 -1
  20. data/ext/datadog_profiling_native_extension/extconf.rb +48 -34
  21. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +4 -43
  22. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +15 -47
  23. data/ext/datadog_profiling_native_extension/heap_recorder.c +455 -430
  24. data/ext/datadog_profiling_native_extension/heap_recorder.h +16 -7
  25. data/ext/datadog_profiling_native_extension/http_transport.c +66 -68
  26. data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +18 -15
  27. data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +8 -10
  28. data/ext/datadog_profiling_native_extension/macos_sampler_thread.h +55 -0
  29. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +0 -13
  30. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +73 -69
  31. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +10 -4
  32. data/ext/datadog_profiling_native_extension/profiling.c +65 -19
  33. data/ext/datadog_profiling_native_extension/ruby_helpers.c +64 -59
  34. data/ext/datadog_profiling_native_extension/ruby_helpers.h +20 -16
  35. data/ext/datadog_profiling_native_extension/setup_signal_handler.c +32 -10
  36. data/ext/datadog_profiling_native_extension/setup_signal_handler.h +2 -1
  37. data/ext/datadog_profiling_native_extension/stack_recorder.c +253 -131
  38. data/ext/datadog_profiling_native_extension/stack_recorder.h +3 -1
  39. data/ext/datadog_profiling_native_extension/time_helpers.h +1 -0
  40. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +2 -1
  41. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +9 -4
  42. data/ext/libdatadog_api/crashtracker.c +16 -15
  43. data/ext/libdatadog_api/crashtracker_report_exception.c +126 -0
  44. data/ext/libdatadog_api/datadog_ruby_common.c +65 -1
  45. data/ext/libdatadog_api/datadog_ruby_common.h +40 -1
  46. data/ext/libdatadog_api/ddsketch.c +102 -0
  47. data/ext/libdatadog_api/di.c +203 -0
  48. data/ext/libdatadog_api/extconf.rb +21 -25
  49. data/ext/libdatadog_api/feature_flags.c +554 -0
  50. data/ext/libdatadog_api/feature_flags.h +5 -0
  51. data/ext/libdatadog_api/helpers.h +27 -0
  52. data/ext/libdatadog_api/init.c +13 -1
  53. data/ext/libdatadog_api/library_config.c +88 -37
  54. data/ext/libdatadog_api/library_config.h +6 -0
  55. data/ext/libdatadog_api/process_discovery.c +25 -24
  56. data/ext/libdatadog_extconf_helpers.rb +107 -14
  57. data/lib/datadog/ai_guard/api_client.rb +84 -0
  58. data/lib/datadog/ai_guard/autoload.rb +10 -0
  59. data/lib/datadog/ai_guard/component.rb +44 -0
  60. data/lib/datadog/ai_guard/configuration/ext.rb +17 -0
  61. data/lib/datadog/ai_guard/configuration.rb +115 -0
  62. data/lib/datadog/ai_guard/contrib/auto_instrument.rb +24 -0
  63. data/lib/datadog/ai_guard/contrib/integration.rb +37 -0
  64. data/lib/datadog/ai_guard/contrib/rack/integration.rb +42 -0
  65. data/lib/datadog/ai_guard/contrib/rack/patcher.rb +26 -0
  66. data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +97 -0
  67. data/lib/datadog/ai_guard/contrib/rails/integration.rb +41 -0
  68. data/lib/datadog/ai_guard/contrib/rails/patcher.rb +97 -0
  69. data/lib/datadog/ai_guard/contrib/ruby_llm/chat_instrumentation.rb +80 -0
  70. data/lib/datadog/ai_guard/contrib/ruby_llm/integration.rb +41 -0
  71. data/lib/datadog/ai_guard/contrib/ruby_llm/patcher.rb +30 -0
  72. data/lib/datadog/ai_guard/evaluation/content_builder.rb +31 -0
  73. data/lib/datadog/ai_guard/evaluation/content_part.rb +36 -0
  74. data/lib/datadog/ai_guard/evaluation/message.rb +25 -0
  75. data/lib/datadog/ai_guard/evaluation/no_op_result.rb +36 -0
  76. data/lib/datadog/ai_guard/evaluation/request.rb +86 -0
  77. data/lib/datadog/ai_guard/evaluation/result.rb +45 -0
  78. data/lib/datadog/ai_guard/evaluation/tool_call.rb +18 -0
  79. data/lib/datadog/ai_guard/evaluation.rb +108 -0
  80. data/lib/datadog/ai_guard/ext.rb +29 -0
  81. data/lib/datadog/ai_guard.rb +181 -0
  82. data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +26 -0
  83. data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +66 -0
  84. data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +36 -0
  85. data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +26 -0
  86. data/lib/datadog/appsec/api_security/endpoint_collection.rb +10 -0
  87. data/lib/datadog/appsec/api_security/route_extractor.rb +104 -0
  88. data/lib/datadog/appsec/api_security/sampler.rb +62 -0
  89. data/lib/datadog/appsec/api_security.rb +14 -0
  90. data/lib/datadog/appsec/assets/blocked.html +10 -1
  91. data/lib/datadog/appsec/assets/blocked.json +1 -1
  92. data/lib/datadog/appsec/assets/blocked.text +3 -1
  93. data/lib/datadog/appsec/assets/waf_rules/README.md +30 -36
  94. data/lib/datadog/appsec/assets/waf_rules/recommended.json +601 -74
  95. data/lib/datadog/appsec/assets/waf_rules/strict.json +48 -75
  96. data/lib/datadog/appsec/assets.rb +1 -1
  97. data/lib/datadog/appsec/autoload.rb +2 -2
  98. data/lib/datadog/appsec/component.rb +37 -64
  99. data/lib/datadog/appsec/compressed_json.rb +3 -3
  100. data/lib/datadog/appsec/configuration.rb +427 -1
  101. data/lib/datadog/appsec/context.rb +77 -16
  102. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +3 -1
  103. data/lib/datadog/appsec/contrib/active_record/integration.rb +1 -1
  104. data/lib/datadog/appsec/contrib/active_record/patcher.rb +4 -1
  105. data/lib/datadog/appsec/contrib/aws_lambda/gateway/watcher.rb +75 -0
  106. data/lib/datadog/appsec/contrib/aws_lambda/integration.rb +39 -0
  107. data/lib/datadog/appsec/contrib/aws_lambda/patcher.rb +30 -0
  108. data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +144 -0
  109. data/lib/datadog/appsec/contrib/devise/integration.rb +1 -1
  110. data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +4 -2
  111. data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +2 -1
  112. data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +1 -1
  113. data/lib/datadog/appsec/contrib/excon/integration.rb +1 -1
  114. data/lib/datadog/appsec/contrib/excon/patcher.rb +3 -1
  115. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +152 -13
  116. data/lib/datadog/appsec/contrib/faraday/integration.rb +1 -1
  117. data/lib/datadog/appsec/contrib/faraday/patcher.rb +1 -1
  118. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +138 -13
  119. data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +74 -24
  120. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +4 -2
  121. data/lib/datadog/appsec/contrib/graphql/integration.rb +2 -1
  122. data/lib/datadog/appsec/contrib/rack/buffered_input.rb +83 -0
  123. data/lib/datadog/appsec/contrib/rack/ext.rb +1 -1
  124. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +47 -13
  125. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +40 -19
  126. data/lib/datadog/appsec/contrib/rack/input_peeker.rb +79 -0
  127. data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
  128. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +80 -62
  129. data/lib/datadog/appsec/contrib/rack/response_body.rb +36 -0
  130. data/lib/datadog/appsec/contrib/rails/gateway/request.rb +35 -1
  131. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +47 -5
  132. data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
  133. data/lib/datadog/appsec/contrib/rails/patcher.rb +52 -26
  134. data/lib/datadog/appsec/contrib/rails/patches/process_action_patch.rb +29 -0
  135. data/lib/datadog/appsec/contrib/rails/patches/render_to_body_patch.rb +33 -0
  136. data/lib/datadog/appsec/contrib/rest_client/integration.rb +1 -1
  137. data/lib/datadog/appsec/contrib/rest_client/patcher.rb +3 -1
  138. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +167 -12
  139. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +63 -10
  140. data/lib/datadog/appsec/contrib/sinatra/integration.rb +1 -1
  141. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +11 -21
  142. data/lib/datadog/appsec/contrib/sinatra/patches/json_patch.rb +31 -0
  143. data/lib/datadog/appsec/counter_sampler.rb +25 -0
  144. data/lib/datadog/appsec/default_header_tags.rb +52 -0
  145. data/lib/datadog/appsec/event.rb +14 -47
  146. data/lib/datadog/appsec/ext.rb +3 -0
  147. data/lib/datadog/appsec/instrumentation/gateway/argument.rb +17 -1
  148. data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +2 -3
  149. data/lib/datadog/appsec/instrumentation/gateway.rb +2 -15
  150. data/lib/datadog/appsec/metrics/collector.rb +47 -5
  151. data/lib/datadog/appsec/metrics/exporter.rb +16 -3
  152. data/lib/datadog/appsec/metrics/telemetry.rb +21 -4
  153. data/lib/datadog/appsec/metrics/telemetry_exporter.rb +47 -0
  154. data/lib/datadog/appsec/metrics.rb +5 -4
  155. data/lib/datadog/appsec/monitor/gateway/watcher.rb +8 -6
  156. data/lib/datadog/appsec/processor/rule_loader.rb +5 -6
  157. data/lib/datadog/appsec/remote.rb +51 -76
  158. data/lib/datadog/appsec/response.rb +18 -4
  159. data/lib/datadog/appsec/route_normalizer/rails_route_pattern.rb +176 -0
  160. data/lib/datadog/appsec/route_normalizer/route_pattern.rb +378 -0
  161. data/lib/datadog/appsec/route_normalizer/route_text.rb +57 -0
  162. data/lib/datadog/appsec/route_normalizer.rb +80 -0
  163. data/lib/datadog/appsec/security_engine/engine.rb +197 -0
  164. data/lib/datadog/appsec/security_engine/result.rb +45 -9
  165. data/lib/datadog/appsec/security_engine/runner.rb +44 -21
  166. data/lib/datadog/appsec/security_event.rb +5 -7
  167. data/lib/datadog/appsec/thread_safe_ref.rb +61 -0
  168. data/lib/datadog/appsec/trace_keeper.rb +36 -0
  169. data/lib/datadog/appsec/utils/hash_coercion.rb +23 -0
  170. data/lib/datadog/appsec/utils/http/body.rb +38 -0
  171. data/lib/datadog/appsec/utils/http/body_reader.rb +61 -0
  172. data/lib/datadog/appsec/utils/http/media_range.rb +2 -1
  173. data/lib/datadog/appsec/utils/http/media_type.rb +32 -26
  174. data/lib/datadog/appsec/utils/http/url_encoded.rb +52 -0
  175. data/lib/datadog/appsec.rb +10 -17
  176. data/lib/datadog/auto_instrument_base.rb +2 -1
  177. data/lib/datadog/core/configuration/agent_settings.rb +52 -0
  178. data/lib/datadog/core/configuration/agent_settings_resolver.rb +5 -47
  179. data/lib/datadog/core/configuration/base.rb +17 -5
  180. data/lib/datadog/core/configuration/components.rb +192 -20
  181. data/lib/datadog/core/configuration/components_state.rb +6 -1
  182. data/lib/datadog/core/configuration/config_helper.rb +109 -0
  183. data/lib/datadog/core/configuration/deprecations.rb +36 -0
  184. data/lib/datadog/core/configuration/ext.rb +0 -1
  185. data/lib/datadog/core/configuration/option.rb +95 -65
  186. data/lib/datadog/core/configuration/option_definition.rb +42 -23
  187. data/lib/datadog/core/configuration/options.rb +57 -18
  188. data/lib/datadog/core/configuration/settings.rb +160 -25
  189. data/lib/datadog/core/configuration/stable_config.rb +11 -2
  190. data/lib/datadog/core/configuration/supported_configurations.rb +413 -0
  191. data/lib/datadog/core/configuration.rb +4 -4
  192. data/lib/datadog/core/contrib/rails/railtie.rb +32 -0
  193. data/lib/datadog/core/contrib/rails/utils.rb +7 -3
  194. data/lib/datadog/core/crashtracking/component.rb +73 -21
  195. data/lib/datadog/core/crashtracking/tag_builder.rb +9 -21
  196. data/lib/datadog/core/ddsketch.rb +19 -0
  197. data/lib/datadog/core/deprecations.rb +2 -2
  198. data/lib/datadog/core/diagnostics/environment_logger.rb +3 -1
  199. data/lib/datadog/core/environment/agent_info.rb +65 -1
  200. data/lib/datadog/core/environment/cgroup.rb +52 -25
  201. data/lib/datadog/core/environment/container.rb +140 -46
  202. data/lib/datadog/core/environment/ext.rb +13 -2
  203. data/lib/datadog/core/environment/git.rb +2 -2
  204. data/lib/datadog/core/environment/identity.rb +40 -4
  205. data/lib/datadog/core/environment/process.rb +122 -0
  206. data/lib/datadog/core/environment/socket.rb +13 -0
  207. data/lib/datadog/core/environment/variable_helpers.rb +3 -3
  208. data/lib/datadog/core/environment/yjit.rb +2 -1
  209. data/lib/datadog/core/error.rb +6 -6
  210. data/lib/datadog/core/evp.rb +11 -0
  211. data/lib/datadog/core/feature_flags.rb +61 -0
  212. data/lib/datadog/core/knuth_sampler.rb +57 -0
  213. data/lib/datadog/core/logger.rb +1 -1
  214. data/lib/datadog/core/metrics/client.rb +7 -7
  215. data/lib/datadog/core/metrics/logging.rb +1 -1
  216. data/lib/datadog/core/pin.rb +8 -8
  217. data/lib/datadog/core/process_discovery/tracer_memfd.rb +13 -0
  218. data/lib/datadog/core/process_discovery.rb +51 -21
  219. data/lib/datadog/core/rate_limiter.rb +11 -1
  220. data/lib/datadog/core/remote/client/capabilities.rb +49 -6
  221. data/lib/datadog/core/remote/client.rb +15 -7
  222. data/lib/datadog/core/remote/component.rb +64 -36
  223. data/lib/datadog/core/remote/configuration/content.rb +15 -2
  224. data/lib/datadog/core/remote/configuration/digest.rb +14 -7
  225. data/lib/datadog/core/remote/configuration/repository.rb +13 -1
  226. data/lib/datadog/core/remote/configuration/target.rb +13 -6
  227. data/lib/datadog/core/remote/transport/config.rb +9 -36
  228. data/lib/datadog/core/remote/transport/http/config.rb +15 -55
  229. data/lib/datadog/core/remote/transport/http/negotiation.rb +14 -44
  230. data/lib/datadog/core/remote/transport/http.rb +15 -24
  231. data/lib/datadog/core/remote/transport/negotiation.rb +8 -33
  232. data/lib/datadog/core/remote/worker.rb +25 -37
  233. data/lib/datadog/core/runtime/ext.rb +0 -1
  234. data/lib/datadog/core/runtime/metrics.rb +11 -2
  235. data/lib/datadog/core/semaphore.rb +1 -4
  236. data/lib/datadog/core/tag_builder.rb +52 -0
  237. data/lib/datadog/core/tag_normalizer.rb +84 -0
  238. data/lib/datadog/core/telemetry/component.rb +65 -17
  239. data/lib/datadog/core/telemetry/emitter.rb +6 -6
  240. data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +3 -3
  241. data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +30 -0
  242. data/lib/datadog/core/telemetry/event/app_extended_heartbeat.rb +32 -0
  243. data/lib/datadog/core/telemetry/event/app_started.rb +203 -89
  244. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +27 -4
  245. data/lib/datadog/core/telemetry/event.rb +2 -7
  246. data/lib/datadog/core/telemetry/ext.rb +1 -0
  247. data/lib/datadog/core/telemetry/logger.rb +5 -2
  248. data/lib/datadog/core/telemetry/logging.rb +22 -4
  249. data/lib/datadog/core/telemetry/metrics_manager.rb +9 -0
  250. data/lib/datadog/core/telemetry/request.rb +17 -5
  251. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +8 -34
  252. data/lib/datadog/core/telemetry/transport/http.rb +21 -16
  253. data/lib/datadog/core/telemetry/transport/telemetry.rb +8 -17
  254. data/lib/datadog/core/telemetry/worker.rb +108 -32
  255. data/lib/datadog/core/transport/ext.rb +3 -0
  256. data/lib/datadog/core/transport/http/adapters/net.rb +17 -2
  257. data/lib/datadog/core/transport/http/api/endpoint.rb +9 -4
  258. data/lib/datadog/core/transport/http/api/instance.rb +4 -21
  259. data/lib/datadog/core/transport/http/builder.rb +11 -7
  260. data/lib/datadog/core/transport/http/client.rb +80 -0
  261. data/lib/datadog/core/transport/http/env.rb +8 -0
  262. data/lib/datadog/core/transport/http/response.rb +4 -0
  263. data/lib/datadog/core/transport/http.rb +24 -19
  264. data/lib/datadog/core/transport/parcel.rb +61 -9
  265. data/lib/datadog/core/transport/response.rb +16 -2
  266. data/lib/datadog/core/transport/transport.rb +90 -0
  267. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +1 -1
  268. data/lib/datadog/core/utils/{base64.rb → base64_codec.rb} +4 -3
  269. data/lib/datadog/core/utils/enumerable_compat.rb +29 -0
  270. data/lib/datadog/core/utils/fnv.rb +26 -0
  271. data/lib/datadog/core/utils/forking.rb +3 -1
  272. data/lib/datadog/core/utils/hash.rb +0 -23
  273. data/lib/datadog/{appsec/api_security → core/utils}/lru_cache.rb +10 -14
  274. data/lib/datadog/core/utils/network.rb +22 -1
  275. data/lib/datadog/core/utils/only_once.rb +1 -1
  276. data/lib/datadog/core/utils/only_once_successful.rb +8 -2
  277. data/lib/datadog/core/utils/safe_dup.rb +2 -2
  278. data/lib/datadog/core/utils/sequence.rb +2 -0
  279. data/lib/datadog/core/utils/spawn_monkey_patch.rb +68 -0
  280. data/lib/datadog/core/utils/time.rb +1 -1
  281. data/lib/datadog/core/utils.rb +10 -1
  282. data/lib/datadog/core/workers/async.rb +11 -2
  283. data/lib/datadog/core/workers/interval_loop.rb +51 -3
  284. data/lib/datadog/core/workers/polling.rb +2 -0
  285. data/lib/datadog/core/workers/queue.rb +96 -1
  286. data/lib/datadog/core/workers/runtime_metrics.rb +9 -1
  287. data/lib/datadog/core.rb +11 -2
  288. data/lib/datadog/data_streams/configuration.rb +50 -0
  289. data/lib/datadog/data_streams/ext.rb +11 -0
  290. data/lib/datadog/data_streams/extensions.rb +16 -0
  291. data/lib/datadog/data_streams/pathway_context.rb +169 -0
  292. data/lib/datadog/data_streams/processor.rb +511 -0
  293. data/lib/datadog/data_streams/transport/http/stats.rb +58 -0
  294. data/lib/datadog/data_streams/transport/http.rb +36 -0
  295. data/lib/datadog/data_streams/transport/stats.rb +39 -0
  296. data/lib/datadog/data_streams.rb +100 -0
  297. data/lib/datadog/di/base.rb +15 -7
  298. data/lib/datadog/di/boot.rb +11 -1
  299. data/lib/datadog/di/code_tracker.rb +217 -15
  300. data/lib/datadog/di/component.rb +143 -48
  301. data/lib/datadog/di/configuration.rb +235 -2
  302. data/lib/datadog/di/context.rb +76 -0
  303. data/lib/datadog/di/contrib/active_record.rb +34 -5
  304. data/lib/datadog/di/el/compiler.rb +168 -0
  305. data/lib/datadog/di/el/evaluator.rb +159 -0
  306. data/lib/datadog/di/el/expression.rb +42 -0
  307. data/lib/datadog/di/el.rb +5 -0
  308. data/lib/datadog/di/error.rb +44 -0
  309. data/lib/datadog/di/fatal_exceptions.rb +26 -0
  310. data/lib/datadog/di/instrumenter.rb +620 -132
  311. data/lib/datadog/di/logger.rb +2 -2
  312. data/lib/datadog/di/probe.rb +78 -15
  313. data/lib/datadog/di/probe_builder.rb +42 -3
  314. data/lib/datadog/di/probe_file_loader/railtie.rb +15 -0
  315. data/lib/datadog/di/probe_file_loader.rb +87 -0
  316. data/lib/datadog/di/probe_manager.rb +195 -100
  317. data/lib/datadog/di/probe_notification_builder.rb +285 -100
  318. data/lib/datadog/di/probe_notifier_worker.rb +120 -36
  319. data/lib/datadog/di/probe_repository.rb +198 -0
  320. data/lib/datadog/di/proc_responder.rb +36 -0
  321. data/lib/datadog/di/redactor.rb +24 -2
  322. data/lib/datadog/di/remote.rb +258 -95
  323. data/lib/datadog/di/serializer.rb +297 -20
  324. data/lib/datadog/di/transport/diagnostics.rb +12 -42
  325. data/lib/datadog/di/transport/http/diagnostics.rb +4 -34
  326. data/lib/datadog/di/transport/http/input.rb +12 -34
  327. data/lib/datadog/di/transport/http.rb +43 -19
  328. data/lib/datadog/di/transport/input.rb +121 -39
  329. data/lib/datadog/di/utils.rb +42 -14
  330. data/lib/datadog/di.rb +203 -10
  331. data/lib/datadog/error_tracking/collector.rb +2 -1
  332. data/lib/datadog/error_tracking/component.rb +2 -2
  333. data/lib/datadog/error_tracking/configuration.rb +55 -2
  334. data/lib/datadog/error_tracking/filters.rb +2 -2
  335. data/lib/datadog/kit/appsec/events/v2.rb +253 -0
  336. data/lib/datadog/kit/appsec/events.rb +11 -10
  337. data/lib/datadog/kit/enable_core_dumps.rb +1 -1
  338. data/lib/datadog/kit/identity.rb +17 -11
  339. data/lib/datadog/kit/tracing/method_tracer.rb +135 -0
  340. data/lib/datadog/open_feature/component.rb +100 -0
  341. data/lib/datadog/open_feature/configuration.rb +37 -0
  342. data/lib/datadog/open_feature/evaluation_engine.rb +70 -0
  343. data/lib/datadog/open_feature/exposures/batch_builder.rb +32 -0
  344. data/lib/datadog/open_feature/exposures/buffer.rb +43 -0
  345. data/lib/datadog/open_feature/exposures/deduplicator.rb +30 -0
  346. data/lib/datadog/open_feature/exposures/event.rb +60 -0
  347. data/lib/datadog/open_feature/exposures/reporter.rb +40 -0
  348. data/lib/datadog/open_feature/exposures/worker.rb +116 -0
  349. data/lib/datadog/open_feature/ext.rb +16 -0
  350. data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +286 -0
  351. data/lib/datadog/open_feature/flag_evaluation/writer.rb +433 -0
  352. data/lib/datadog/open_feature/hooks/flag_eval_evp_hook.rb +101 -0
  353. data/lib/datadog/open_feature/hooks/flag_eval_metrics_hook.rb +49 -0
  354. data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +149 -0
  355. data/lib/datadog/open_feature/native_evaluator.rb +60 -0
  356. data/lib/datadog/open_feature/noop_evaluator.rb +26 -0
  357. data/lib/datadog/open_feature/provider.rb +191 -0
  358. data/lib/datadog/open_feature/remote.rb +67 -0
  359. data/lib/datadog/open_feature/resolution_details.rb +35 -0
  360. data/lib/datadog/open_feature/transport.rb +121 -0
  361. data/lib/datadog/open_feature.rb +19 -0
  362. data/lib/datadog/opentelemetry/api/baggage.rb +3 -3
  363. data/lib/datadog/opentelemetry/api/context.rb +10 -9
  364. data/lib/datadog/opentelemetry/configuration/settings.rb +226 -0
  365. data/lib/datadog/opentelemetry/ext.rb +9 -0
  366. data/lib/datadog/opentelemetry/logs.rb +98 -0
  367. data/lib/datadog/opentelemetry/metrics.rb +90 -0
  368. data/lib/datadog/opentelemetry/sdk/configurator.rb +66 -2
  369. data/lib/datadog/opentelemetry/sdk/id_generator.rb +16 -10
  370. data/lib/datadog/opentelemetry/sdk/logs_exporter.rb +30 -0
  371. data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +28 -0
  372. data/lib/datadog/opentelemetry/sdk/propagator.rb +13 -7
  373. data/lib/datadog/opentelemetry/sdk/span_processor.rb +12 -9
  374. data/lib/datadog/opentelemetry/sdk/trace/span.rb +14 -10
  375. data/lib/datadog/opentelemetry/sdk.rb +19 -0
  376. data/lib/datadog/opentelemetry/signal_configuration.rb +53 -0
  377. data/lib/datadog/opentelemetry/trace.rb +4 -4
  378. data/lib/datadog/opentelemetry.rb +4 -0
  379. data/lib/datadog/profiling/collectors/code_provenance.rb +83 -15
  380. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +52 -3
  381. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +13 -4
  382. data/lib/datadog/profiling/collectors/info.rb +59 -4
  383. data/lib/datadog/profiling/collectors/thread_context.rb +17 -5
  384. data/lib/datadog/profiling/component.rb +73 -49
  385. data/lib/datadog/profiling/exporter.rb +48 -13
  386. data/lib/datadog/profiling/ext/dir_monkey_patches.rb +24 -5
  387. data/lib/datadog/profiling/ext/exec_monkey_patch.rb +32 -0
  388. data/lib/datadog/profiling/ext.rb +2 -15
  389. data/lib/datadog/profiling/flush.rb +23 -11
  390. data/lib/datadog/profiling/http_transport.rb +24 -11
  391. data/lib/datadog/profiling/load_native_extension.rb +2 -2
  392. data/lib/datadog/profiling/profiler.rb +31 -12
  393. data/lib/datadog/profiling/scheduler.rb +12 -10
  394. data/lib/datadog/profiling/sequence_tracker.rb +44 -0
  395. data/lib/datadog/profiling/stack_recorder.rb +5 -13
  396. data/lib/datadog/profiling/tag_builder.rb +42 -38
  397. data/lib/datadog/profiling/tasks/exec.rb +10 -5
  398. data/lib/datadog/profiling/tasks/help.rb +1 -0
  399. data/lib/datadog/profiling/tasks/setup.rb +4 -2
  400. data/lib/datadog/profiling.rb +8 -11
  401. data/lib/datadog/ruby_version.rb +25 -0
  402. data/lib/datadog/single_step_instrument.rb +10 -1
  403. data/lib/datadog/symbol_database/component.rb +734 -0
  404. data/lib/datadog/symbol_database/configuration.rb +73 -0
  405. data/lib/datadog/symbol_database/extensions.rb +19 -0
  406. data/lib/datadog/symbol_database/extractor.rb +1110 -0
  407. data/lib/datadog/symbol_database/file_hash.rb +48 -0
  408. data/lib/datadog/symbol_database/logger.rb +43 -0
  409. data/lib/datadog/symbol_database/remote.rb +180 -0
  410. data/lib/datadog/symbol_database/scope.rb +102 -0
  411. data/lib/datadog/symbol_database/scope_batcher.rb +292 -0
  412. data/lib/datadog/symbol_database/service_version.rb +66 -0
  413. data/lib/datadog/symbol_database/symbol.rb +69 -0
  414. data/lib/datadog/symbol_database/transport/http/endpoint.rb +28 -0
  415. data/lib/datadog/symbol_database/transport/http.rb +45 -0
  416. data/lib/datadog/symbol_database/transport.rb +54 -0
  417. data/lib/datadog/symbol_database/uploader.rb +230 -0
  418. data/lib/datadog/symbol_database.rb +71 -0
  419. data/lib/datadog/tracing/analytics.rb +1 -1
  420. data/lib/datadog/tracing/buffer.rb +10 -10
  421. data/lib/datadog/tracing/component.rb +17 -17
  422. data/lib/datadog/tracing/configuration/dynamic.rb +6 -8
  423. data/lib/datadog/tracing/configuration/ext.rb +25 -5
  424. data/lib/datadog/tracing/configuration/settings.rb +125 -11
  425. data/lib/datadog/tracing/context.rb +2 -2
  426. data/lib/datadog/tracing/contrib/action_cable/event.rb +1 -1
  427. data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +4 -1
  428. data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +4 -1
  429. data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +4 -1
  430. data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +4 -1
  431. data/lib/datadog/tracing/contrib/action_cable/integration.rb +1 -1
  432. data/lib/datadog/tracing/contrib/action_mailer/event.rb +4 -1
  433. data/lib/datadog/tracing/contrib/action_mailer/integration.rb +1 -1
  434. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +29 -11
  435. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +47 -12
  436. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +3 -1
  437. data/lib/datadog/tracing/contrib/action_pack/ext.rb +2 -0
  438. data/lib/datadog/tracing/contrib/action_pack/integration.rb +1 -1
  439. data/lib/datadog/tracing/contrib/action_pack/utils.rb +1 -2
  440. data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +4 -1
  441. data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +6 -3
  442. data/lib/datadog/tracing/contrib/active_job/event.rb +8 -8
  443. data/lib/datadog/tracing/contrib/active_job/events/discard.rb +6 -3
  444. data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +6 -3
  445. data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +6 -3
  446. data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +6 -3
  447. data/lib/datadog/tracing/contrib/active_job/events/perform.rb +6 -3
  448. data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +6 -3
  449. data/lib/datadog/tracing/contrib/active_job/integration.rb +1 -1
  450. data/lib/datadog/tracing/contrib/active_job/log_injection.rb +21 -7
  451. data/lib/datadog/tracing/contrib/active_job/patcher.rb +5 -1
  452. data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +2 -2
  453. data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +4 -4
  454. data/lib/datadog/tracing/contrib/active_model_serializers/integration.rb +1 -2
  455. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +3 -3
  456. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +2 -2
  457. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +7 -10
  458. data/lib/datadog/tracing/contrib/active_record/integration.rb +1 -1
  459. data/lib/datadog/tracing/contrib/active_record/utils.rb +16 -16
  460. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +15 -12
  461. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +1 -4
  462. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +13 -0
  463. data/lib/datadog/tracing/contrib/active_support/integration.rb +1 -1
  464. data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +2 -1
  465. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +8 -10
  466. data/lib/datadog/tracing/contrib/aws/ext.rb +1 -1
  467. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +8 -10
  468. data/lib/datadog/tracing/contrib/aws/parsed_context.rb +3 -1
  469. data/lib/datadog/tracing/contrib/aws/patcher.rb +5 -1
  470. data/lib/datadog/tracing/contrib/aws/service/base.rb +2 -1
  471. data/lib/datadog/tracing/contrib/aws/service/dynamodb.rb +1 -1
  472. data/lib/datadog/tracing/contrib/aws/service/eventbridge.rb +1 -1
  473. data/lib/datadog/tracing/contrib/aws/service/kinesis.rb +1 -1
  474. data/lib/datadog/tracing/contrib/aws/service/s3.rb +1 -1
  475. data/lib/datadog/tracing/contrib/aws/service/sns.rb +1 -1
  476. data/lib/datadog/tracing/contrib/aws/service/sqs.rb +1 -1
  477. data/lib/datadog/tracing/contrib/aws/service/states.rb +1 -1
  478. data/lib/datadog/tracing/contrib/aws/services.rb +7 -7
  479. data/lib/datadog/tracing/contrib/component.rb +3 -3
  480. data/lib/datadog/tracing/contrib/concurrent_ruby/async_patch.rb +1 -1
  481. data/lib/datadog/tracing/contrib/concurrent_ruby/context_composite_executor_service.rb +1 -1
  482. data/lib/datadog/tracing/contrib/concurrent_ruby/future_patch.rb +1 -1
  483. data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +1 -1
  484. data/lib/datadog/tracing/contrib/concurrent_ruby/promises_future_patch.rb +1 -1
  485. data/lib/datadog/tracing/contrib/configurable.rb +22 -7
  486. data/lib/datadog/tracing/contrib/configuration/resolver.rb +14 -4
  487. data/lib/datadog/tracing/contrib/configuration/resolvers/pattern_resolver.rb +4 -4
  488. data/lib/datadog/tracing/contrib/dalli/ext.rb +3 -2
  489. data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +1 -5
  490. data/lib/datadog/tracing/contrib/dalli/integration.rb +5 -2
  491. data/lib/datadog/tracing/contrib/dalli/quantize.rb +1 -1
  492. data/lib/datadog/tracing/contrib/delayed_job/integration.rb +1 -1
  493. data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +2 -0
  494. data/lib/datadog/tracing/contrib/delayed_job/server_internal_tracer/worker.rb +1 -0
  495. data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +3 -2
  496. data/lib/datadog/tracing/contrib/elasticsearch/integration.rb +4 -4
  497. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +47 -53
  498. data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +7 -7
  499. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +5 -1
  500. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +7 -8
  501. data/lib/datadog/tracing/contrib/ethon/ext.rb +4 -2
  502. data/lib/datadog/tracing/contrib/ethon/integration.rb +1 -1
  503. data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +1 -8
  504. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +16 -5
  505. data/lib/datadog/tracing/contrib/excon/ext.rb +4 -2
  506. data/lib/datadog/tracing/contrib/excon/integration.rb +1 -1
  507. data/lib/datadog/tracing/contrib/excon/middleware.rb +5 -9
  508. data/lib/datadog/tracing/contrib/ext.rb +6 -4
  509. data/lib/datadog/tracing/contrib/extensions.rb +28 -11
  510. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +16 -9
  511. data/lib/datadog/tracing/contrib/faraday/ext.rb +4 -2
  512. data/lib/datadog/tracing/contrib/faraday/integration.rb +1 -1
  513. data/lib/datadog/tracing/contrib/faraday/middleware.rb +7 -9
  514. data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +7 -3
  515. data/lib/datadog/tracing/contrib/grape/endpoint.rb +18 -15
  516. data/lib/datadog/tracing/contrib/grape/instrumentation.rb +13 -8
  517. data/lib/datadog/tracing/contrib/grape/integration.rb +1 -1
  518. data/lib/datadog/tracing/contrib/grape/patcher.rb +6 -1
  519. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +7 -0
  520. data/lib/datadog/tracing/contrib/graphql/ext.rb +1 -0
  521. data/lib/datadog/tracing/contrib/graphql/integration.rb +1 -1
  522. data/lib/datadog/tracing/contrib/graphql/patcher.rb +2 -2
  523. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +105 -63
  524. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +5 -2
  525. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +11 -15
  526. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +6 -10
  527. data/lib/datadog/tracing/contrib/grpc/distributed/fetcher.rb +1 -1
  528. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +2 -0
  529. data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
  530. data/lib/datadog/tracing/contrib/grpc/integration.rb +1 -1
  531. data/lib/datadog/tracing/contrib/grpc.rb +1 -0
  532. data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +1 -0
  533. data/lib/datadog/tracing/contrib/hanami/ext.rb +2 -2
  534. data/lib/datadog/tracing/contrib/hanami/integration.rb +1 -1
  535. data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +2 -1
  536. data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +10 -11
  537. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +16 -5
  538. data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +4 -4
  539. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +2 -0
  540. data/lib/datadog/tracing/contrib/http/ext.rb +4 -2
  541. data/lib/datadog/tracing/contrib/http/instrumentation.rb +9 -13
  542. data/lib/datadog/tracing/contrib/http/integration.rb +0 -2
  543. data/lib/datadog/tracing/contrib/http.rb +1 -0
  544. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +16 -5
  545. data/lib/datadog/tracing/contrib/httpclient/ext.rb +4 -2
  546. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +10 -10
  547. data/lib/datadog/tracing/contrib/httpclient/integration.rb +1 -1
  548. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +16 -5
  549. data/lib/datadog/tracing/contrib/httprb/ext.rb +4 -2
  550. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +8 -12
  551. data/lib/datadog/tracing/contrib/httprb/integration.rb +1 -1
  552. data/lib/datadog/tracing/contrib/kafka/event.rb +2 -1
  553. data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +1 -1
  554. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +1 -1
  555. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +1 -1
  556. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +1 -1
  557. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/join_group.rb +1 -1
  558. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/leave_group.rb +1 -1
  559. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/sync_group.rb +1 -1
  560. data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +1 -1
  561. data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +1 -1
  562. data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +66 -0
  563. data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +66 -0
  564. data/lib/datadog/tracing/contrib/kafka/integration.rb +1 -1
  565. data/lib/datadog/tracing/contrib/kafka/patcher.rb +14 -0
  566. data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +5 -1
  567. data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +2 -0
  568. data/lib/datadog/tracing/contrib/karafka/ext.rb +1 -0
  569. data/lib/datadog/tracing/contrib/karafka/framework.rb +30 -0
  570. data/lib/datadog/tracing/contrib/karafka/monitor.rb +24 -13
  571. data/lib/datadog/tracing/contrib/karafka/patcher.rb +39 -8
  572. data/lib/datadog/tracing/contrib/karafka.rb +1 -0
  573. data/lib/datadog/tracing/contrib/lograge/instrumentation.rb +1 -1
  574. data/lib/datadog/tracing/contrib/lograge/integration.rb +1 -1
  575. data/lib/datadog/tracing/contrib/lograge/patcher.rb +4 -2
  576. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +1 -1
  577. data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -1
  578. data/lib/datadog/tracing/contrib/mongodb/integration.rb +1 -1
  579. data/lib/datadog/tracing/contrib/mongodb/parsers.rb +6 -6
  580. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +11 -14
  581. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +6 -0
  582. data/lib/datadog/tracing/contrib/mysql2/ext.rb +1 -1
  583. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +19 -12
  584. data/lib/datadog/tracing/contrib/mysql2/integration.rb +1 -1
  585. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +1 -1
  586. data/lib/datadog/tracing/contrib/opensearch/ext.rb +3 -2
  587. data/lib/datadog/tracing/contrib/opensearch/integration.rb +1 -2
  588. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +64 -70
  589. data/lib/datadog/tracing/contrib/opensearch/quantize.rb +7 -7
  590. data/lib/datadog/tracing/contrib/patcher.rb +7 -9
  591. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +6 -0
  592. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +3 -6
  593. data/lib/datadog/tracing/contrib/pg/integration.rb +1 -1
  594. data/lib/datadog/tracing/contrib/presto/ext.rb +1 -1
  595. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +9 -11
  596. data/lib/datadog/tracing/contrib/presto/integration.rb +1 -1
  597. data/lib/datadog/tracing/contrib/propagation/sql_comment/comment.rb +1 -1
  598. data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +13 -0
  599. data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +6 -2
  600. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +25 -1
  601. data/lib/datadog/tracing/contrib/que/configuration/settings.rb +5 -2
  602. data/lib/datadog/tracing/contrib/que/ext.rb +1 -0
  603. data/lib/datadog/tracing/contrib/que/integration.rb +1 -1
  604. data/lib/datadog/tracing/contrib/que/tracer.rb +1 -0
  605. data/lib/datadog/tracing/contrib/racecar/event.rb +2 -6
  606. data/lib/datadog/tracing/contrib/racecar/events/batch.rb +2 -2
  607. data/lib/datadog/tracing/contrib/racecar/events/consume.rb +1 -1
  608. data/lib/datadog/tracing/contrib/racecar/events/message.rb +2 -2
  609. data/lib/datadog/tracing/contrib/racecar/integration.rb +1 -1
  610. data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +11 -1
  611. data/lib/datadog/tracing/contrib/rack/ext.rb +28 -0
  612. data/lib/datadog/tracing/contrib/rack/header_collection.rb +1 -1
  613. data/lib/datadog/tracing/contrib/rack/header_tagging.rb +55 -32
  614. data/lib/datadog/tracing/contrib/rack/integration.rb +1 -1
  615. data/lib/datadog/tracing/contrib/rack/middlewares.rb +83 -44
  616. data/lib/datadog/tracing/contrib/rack/patcher.rb +2 -2
  617. data/lib/datadog/tracing/contrib/rack/request_queue.rb +4 -3
  618. data/lib/datadog/tracing/contrib/rack/route_inference.rb +67 -0
  619. data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +126 -2
  620. data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +6 -3
  621. data/lib/datadog/tracing/contrib/rails/ext.rb +3 -1
  622. data/lib/datadog/tracing/contrib/rails/integration.rb +2 -2
  623. data/lib/datadog/tracing/contrib/rails/log_injection.rb +2 -2
  624. data/lib/datadog/tracing/contrib/rails/middlewares.rb +3 -3
  625. data/lib/datadog/tracing/contrib/rails/patcher.rb +4 -2
  626. data/lib/datadog/tracing/contrib/rails/runner.rb +64 -40
  627. data/lib/datadog/tracing/contrib/rake/instrumentation.rb +10 -8
  628. data/lib/datadog/tracing/contrib/rake/integration.rb +1 -1
  629. data/lib/datadog/tracing/contrib/redis/configuration/resolver.rb +2 -2
  630. data/lib/datadog/tracing/contrib/redis/ext.rb +3 -2
  631. data/lib/datadog/tracing/contrib/redis/integration.rb +2 -2
  632. data/lib/datadog/tracing/contrib/redis/patcher.rb +4 -4
  633. data/lib/datadog/tracing/contrib/redis/quantize.rb +2 -2
  634. data/lib/datadog/tracing/contrib/redis/tags.rb +2 -7
  635. data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +6 -4
  636. data/lib/datadog/tracing/contrib/registerable.rb +11 -0
  637. data/lib/datadog/tracing/contrib/registry.rb +1 -1
  638. data/lib/datadog/tracing/contrib/resque/integration.rb +1 -1
  639. data/lib/datadog/tracing/contrib/resque/resque_job.rb +2 -1
  640. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +5 -2
  641. data/lib/datadog/tracing/contrib/rest_client/ext.rb +4 -2
  642. data/lib/datadog/tracing/contrib/rest_client/integration.rb +1 -1
  643. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +8 -9
  644. data/lib/datadog/tracing/contrib/roda/ext.rb +1 -0
  645. data/lib/datadog/tracing/contrib/roda/instrumentation.rb +8 -3
  646. data/lib/datadog/tracing/contrib/roda/integration.rb +1 -1
  647. data/lib/datadog/tracing/contrib/semantic_logger/instrumentation.rb +1 -1
  648. data/lib/datadog/tracing/contrib/semantic_logger/integration.rb +1 -1
  649. data/lib/datadog/tracing/contrib/sequel/database.rb +6 -5
  650. data/lib/datadog/tracing/contrib/sequel/dataset.rb +2 -1
  651. data/lib/datadog/tracing/contrib/sequel/integration.rb +1 -1
  652. data/lib/datadog/tracing/contrib/sequel/utils.rb +1 -6
  653. data/lib/datadog/tracing/contrib/shoryuken/integration.rb +1 -1
  654. data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +1 -0
  655. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +1 -0
  656. data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +5 -1
  657. data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +2 -0
  658. data/lib/datadog/tracing/contrib/sidekiq/ext.rb +2 -0
  659. data/lib/datadog/tracing/contrib/sidekiq/integration.rb +1 -1
  660. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/heartbeat.rb +2 -0
  661. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/job_fetch.rb +1 -0
  662. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/redis_info.rb +1 -0
  663. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/scheduled_poller.rb +2 -0
  664. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/stop.rb +1 -0
  665. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +8 -4
  666. data/lib/datadog/tracing/contrib/sidekiq/utils.rb +1 -1
  667. data/lib/datadog/tracing/contrib/sidekiq.rb +1 -0
  668. data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +5 -1
  669. data/lib/datadog/tracing/contrib/sinatra/ext.rb +1 -0
  670. data/lib/datadog/tracing/contrib/sinatra/integration.rb +1 -1
  671. data/lib/datadog/tracing/contrib/sinatra/tracer.rb +1 -0
  672. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +40 -39
  673. data/lib/datadog/tracing/contrib/sneakers/integration.rb +15 -4
  674. data/lib/datadog/tracing/contrib/sneakers/tracer.rb +1 -0
  675. data/lib/datadog/tracing/contrib/span_attribute_schema.rb +1 -1
  676. data/lib/datadog/tracing/contrib/status_range_matcher.rb +13 -1
  677. data/lib/datadog/tracing/contrib/stripe/integration.rb +1 -1
  678. data/lib/datadog/tracing/contrib/stripe/request.rb +2 -2
  679. data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +1 -0
  680. data/lib/datadog/tracing/contrib/sucker_punch/integration.rb +1 -1
  681. data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +6 -0
  682. data/lib/datadog/tracing/contrib/trilogy/ext.rb +1 -1
  683. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +4 -6
  684. data/lib/datadog/tracing/contrib/trilogy/integration.rb +1 -1
  685. data/lib/datadog/tracing/contrib/utils/quantization/{hash.rb → hash_formatter.rb} +15 -13
  686. data/lib/datadog/tracing/contrib/utils/quantization/http.rb +6 -6
  687. data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +31 -0
  688. data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +50 -0
  689. data/lib/datadog/tracing/contrib/waterdrop/ext.rb +18 -0
  690. data/lib/datadog/tracing/contrib/waterdrop/integration.rb +43 -0
  691. data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +46 -0
  692. data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +49 -0
  693. data/lib/datadog/tracing/contrib/waterdrop/producer.rb +50 -0
  694. data/lib/datadog/tracing/contrib/waterdrop.rb +42 -0
  695. data/lib/datadog/tracing/contrib.rb +9 -0
  696. data/lib/datadog/tracing/diagnostics/environment_logger.rb +12 -4
  697. data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
  698. data/lib/datadog/tracing/distributed/baggage.rb +133 -12
  699. data/lib/datadog/tracing/distributed/datadog.rb +17 -16
  700. data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +11 -26
  701. data/lib/datadog/tracing/distributed/helpers.rb +1 -1
  702. data/lib/datadog/tracing/distributed/none.rb +4 -2
  703. data/lib/datadog/tracing/distributed/propagation.rb +39 -4
  704. data/lib/datadog/tracing/distributed/propagation_policy.rb +1 -1
  705. data/lib/datadog/tracing/distributed/trace_context.rb +107 -78
  706. data/lib/datadog/tracing/event.rb +5 -7
  707. data/lib/datadog/tracing/ext.rb +9 -0
  708. data/lib/datadog/tracing/flush.rb +1 -1
  709. data/lib/datadog/tracing/metadata/analytics.rb +1 -1
  710. data/lib/datadog/tracing/metadata/ext.rb +23 -1
  711. data/lib/datadog/tracing/metadata/tagging.rb +6 -6
  712. data/lib/datadog/tracing/pipeline/span_filter.rb +3 -1
  713. data/lib/datadog/tracing/pipeline/span_processor.rb +3 -1
  714. data/lib/datadog/tracing/pipeline.rb +2 -2
  715. data/lib/datadog/tracing/remote.rb +36 -13
  716. data/lib/datadog/tracing/sampling/ext.rb +2 -2
  717. data/lib/datadog/tracing/sampling/priority_sampler.rb +16 -1
  718. data/lib/datadog/tracing/sampling/rate_sampler.rb +8 -19
  719. data/lib/datadog/tracing/sampling/rule.rb +1 -1
  720. data/lib/datadog/tracing/sampling/rule_sampler.rb +77 -48
  721. data/lib/datadog/tracing/sampling/span/rule_parser.rb +3 -3
  722. data/lib/datadog/tracing/sampling/span/sampler.rb +0 -7
  723. data/lib/datadog/tracing/span.rb +2 -2
  724. data/lib/datadog/tracing/span_event.rb +12 -12
  725. data/lib/datadog/tracing/span_link.rb +12 -12
  726. data/lib/datadog/tracing/span_operation.rb +63 -19
  727. data/lib/datadog/tracing/sync_writer.rb +1 -2
  728. data/lib/datadog/tracing/trace_digest.rb +28 -23
  729. data/lib/datadog/tracing/trace_operation.rb +209 -98
  730. data/lib/datadog/tracing/trace_segment.rb +2 -2
  731. data/lib/datadog/tracing/tracer.rb +113 -52
  732. data/lib/datadog/tracing/transport/http/client.rb +12 -26
  733. data/lib/datadog/tracing/transport/http/traces.rb +4 -52
  734. data/lib/datadog/tracing/transport/http.rb +15 -9
  735. data/lib/datadog/tracing/transport/io/client.rb +11 -14
  736. data/lib/datadog/tracing/transport/io/traces.rb +28 -34
  737. data/lib/datadog/tracing/transport/statistics.rb +1 -1
  738. data/lib/datadog/tracing/transport/trace_formatter.rb +22 -0
  739. data/lib/datadog/tracing/transport/traces.rb +14 -82
  740. data/lib/datadog/tracing/workers.rb +4 -3
  741. data/lib/datadog/tracing/writer.rb +1 -1
  742. data/lib/datadog/tracing.rb +2 -2
  743. data/lib/datadog/version.rb +2 -2
  744. data/lib/datadog.rb +14 -0
  745. metadata +201 -40
  746. data/ext/datadog_profiling_native_extension/clock_id_noop.c +0 -21
  747. data/ext/libdatadog_api/macos_development.md +0 -26
  748. data/lib/datadog/appsec/assets/waf_rules/processors.json +0 -321
  749. data/lib/datadog/appsec/assets/waf_rules/scanners.json +0 -1023
  750. data/lib/datadog/appsec/configuration/settings.rb +0 -342
  751. data/lib/datadog/appsec/contrib/rails/ext.rb +0 -13
  752. data/lib/datadog/appsec/processor/rule_merger.rb +0 -171
  753. data/lib/datadog/appsec/processor.rb +0 -107
  754. data/lib/datadog/core/remote/transport/http/api.rb +0 -53
  755. data/lib/datadog/core/remote/transport/http/client.rb +0 -49
  756. data/lib/datadog/core/telemetry/transport/http/api.rb +0 -43
  757. data/lib/datadog/core/telemetry/transport/http/client.rb +0 -49
  758. data/lib/datadog/core/transport/http/api/spec.rb +0 -36
  759. data/lib/datadog/di/configuration/settings.rb +0 -212
  760. data/lib/datadog/di/transport/http/api.rb +0 -42
  761. data/lib/datadog/di/transport/http/client.rb +0 -47
  762. data/lib/datadog/error_tracking/configuration/settings.rb +0 -63
  763. data/lib/datadog/opentelemetry/api/baggage.rbs +0 -26
  764. data/lib/datadog/tracing/transport/http/api.rb +0 -44
  765. data/lib/datadog/tracing/workers/trace_writer.rb +0 -199
@@ -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
- require_relative '../../processor'
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
@@ -46,33 +38,22 @@ module Datadog
46
38
  boot = Datadog::Core::Remote::Tie.boot
47
39
  Datadog::Core::Remote::Tie::Tracing.tag(boot, active_span)
48
40
 
49
- processor = nil
50
- ready = false
51
- ctx = nil
52
-
53
41
  # For a given request, keep using the first Rack stack scope for
54
42
  # nested apps. Don't set `context` local variable so that on popping
55
43
  # out of this nested stack we don't finalize the parent's context
56
44
  return @app.call(env) if active_context(env)
57
45
 
58
- Datadog::AppSec.reconfigure_lock do
59
- processor = Datadog::AppSec.processor
60
-
61
- if !processor.nil? && processor.ready?
62
- ctx = Datadog::AppSec::Context.activate(
63
- Datadog::AppSec::Context.new(active_trace, active_span, processor)
64
- )
65
-
66
- env[Datadog::AppSec::Ext::CONTEXT_KEY] = ctx
67
- ready = true
68
- end
69
- end
46
+ security_engine = Datadog::AppSec.security_engine
70
47
 
71
48
  # TODO: handle exceptions, except for @app.call
49
+ return @app.call(env) unless security_engine
72
50
 
73
- return @app.call(env) unless ready
51
+ ctx = Datadog::AppSec::Context.activate(
52
+ Datadog::AppSec::Context.new(active_trace, active_span, security_engine.new_runner)
53
+ )
54
+ env[Datadog::AppSec::Ext::CONTEXT_KEY] = ctx
74
55
 
75
- add_appsec_tags(processor, ctx)
56
+ add_appsec_tags(ctx)
76
57
  add_request_tags(ctx, env)
77
58
 
78
59
  http_response = nil
@@ -96,22 +77,42 @@ module Datadog
96
77
  nil
97
78
  end
98
79
 
80
+ add_normalized_route_tag(ctx, env)
81
+
99
82
  if interrupt_params
83
+ ctx.mark_as_interrupted!
100
84
  http_response = AppSec::Response.from_interrupt_params(interrupt_params, env['HTTP_ACCEPT']).to_rack
101
85
  end
102
86
 
103
- if AppSec.perform_api_security_check?
104
- ctx.events.push(
105
- AppSec::SecurityEvent.new(ctx.extract_schema, trace: ctx.trace, span: ctx.span)
106
- )
87
+ # NOTE: This is not optimal, but in the current implementation
88
+ # `gateway_response` is a container to dispatch response event
89
+ # and in case of interruption it suppose to be `nil`.
90
+ #
91
+ # `http_response` is a real response object in both cases, but
92
+ # to save us some computations, we will use already pre-computed
93
+ # `gateway_response` instead of re-creating it.
94
+ #
95
+ # WARNING: This part will be refactored.
96
+ tmp_response = if interrupt_params
97
+ Gateway::Response.new(http_response[2], http_response[0], http_response[1], context: ctx)
98
+ else
99
+ gateway_response
107
100
  end
108
101
 
109
- AppSec::Event.record(ctx, request: gateway_request, response: gateway_response)
102
+ if AppSec::APISecurity.enabled? && AppSec::APISecurity.sample_trace?(ctx.trace) &&
103
+ AppSec::APISecurity.sample?(gateway_request.request, tmp_response.response)
104
+ ctx.extract_schema!
105
+ end
106
+
107
+ AppSec::Event.record(ctx, request: gateway_request)
110
108
 
109
+ add_response_tags(ctx, tmp_response)
111
110
  http_response
112
111
  ensure
113
112
  if ctx
114
113
  ctx.export_metrics
114
+ ctx.export_request_telemetry
115
+
115
116
  Datadog::AppSec::Context.deactivate
116
117
  end
117
118
  end
@@ -140,7 +141,7 @@ module Datadog
140
141
  end
141
142
 
142
143
  # standard:disable Metrics/MethodLength
143
- def add_appsec_tags(processor, context)
144
+ def add_appsec_tags(context)
144
145
  span = context.span
145
146
  trace = context.trace
146
147
 
@@ -150,20 +151,15 @@ module Datadog
150
151
  span.set_tag('_dd.runtime_family', 'ruby')
151
152
  span.set_tag('_dd.appsec.waf.version', Datadog::AppSec::WAF::VERSION::BASE_STRING)
152
153
 
153
- if processor.diagnostics
154
- diagnostics = processor.diagnostics
155
-
156
- span.set_tag('_dd.appsec.event_rules.version', diagnostics['ruleset_version'])
154
+ if context.waf_runner_ruleset_version
155
+ span.set_tag('_dd.appsec.event_rules.version', context.waf_runner_ruleset_version)
157
156
 
158
- unless @oneshot_tags_sent
157
+ unless oneshot_tags_sent?
159
158
  # Small race condition, but it's inoccuous: worst case the tags
160
159
  # are sent a couple of times more than expected
161
160
  @oneshot_tags_sent = true
162
161
 
163
- span.set_tag('_dd.appsec.event_rules.loaded', diagnostics['rules']['loaded'].size.to_f)
164
- span.set_tag('_dd.appsec.event_rules.error_count', diagnostics['rules']['failed'].size.to_f)
165
- span.set_tag('_dd.appsec.event_rules.errors', JSON.dump(diagnostics['rules']['errors']))
166
- span.set_tag('_dd.appsec.event_rules.addresses', JSON.dump(processor.addresses))
162
+ span.set_tag('_dd.appsec.event_rules.addresses', JSON.dump(context.waf_runner_known_addresses))
167
163
 
168
164
  # Ensure these tags reach the backend
169
165
  trace.keep!
@@ -176,33 +172,55 @@ module Datadog
176
172
  end
177
173
  # standard:enable Metrics/MethodLength
178
174
 
179
- # standard:disable Metrics/MethodLength
180
175
  def add_request_tags(context, env)
181
176
  span = context.span
182
-
183
177
  return unless span
184
178
 
185
- # Always add WAF vendors headers
186
- WAF_VENDOR_HEADERS_TAGS.each do |lowercase_header|
187
- rack_header = to_rack_header(lowercase_header)
188
- span.set_tag("http.request.headers.#{lowercase_header}", env[rack_header]) if env[rack_header]
189
- end
190
-
191
- if span && span.get_tag(Tracing::Metadata::Ext::HTTP::TAG_CLIENT_IP).nil?
192
- 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)
193
181
 
182
+ if span.get_tag(Tracing::Metadata::Ext::HTTP::TAG_CLIENT_IP).nil?
194
183
  # always collect client ip, as this is part of AppSec provided functionality
195
184
  Datadog::Tracing::ClientIp.set_client_ip_tag!(
196
- span,
197
- headers: request_header_collection,
198
- remote_ip: env['REMOTE_ADDR']
185
+ span, headers: headers, remote_ip: env['REMOTE_ADDR']
199
186
  )
200
187
  end
201
188
  end
202
- # standard:enable Metrics/MethodLength
203
189
 
204
- def to_rack_header(header)
205
- @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
206
224
  end
207
225
  end
208
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,6 +47,7 @@ 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)
@@ -55,10 +57,42 @@ module Datadog
55
57
  def route_params
56
58
  excluded = [:controller, :action]
57
59
 
58
- request.env['action_dispatch.request.path_parameters'].reject do |k, _v|
60
+ request.env.fetch('action_dispatch.request.path_parameters', {}).reject do |k, _v|
59
61
  excluded.include?(k)
60
62
  end
61
63
  end
64
+
65
+ # Returns the request body size in bytes using all available methods,
66
+ # or nil when the size cannot be measured within the limit
67
+ #
68
+ # NOTE: The priority of the measurement is the following:
69
+ # raw posted data, raw form vars, size if known, raw
70
+ # Content-Length, then buffering to the limit if unknown-length
71
+ def body_bytesize(limit)
72
+ raw_body = env['RAW_POST_DATA']
73
+ return raw_body.bytesize if raw_body
74
+
75
+ form_vars = env['rack.request.form_vars']
76
+ return form_vars.bytesize if form_vars
77
+
78
+ io = request.body
79
+ return 0 unless io
80
+ return io.size if io.respond_to?(:size)
81
+
82
+ # NOTE: Read raw `CONTENT_LENGTH` as {ActionDispatch::Request#content_length}
83
+ # drains `rack.input` into `RAW_POST_DATA` on chunked Transfer-Encoding
84
+ content_length = env['CONTENT_LENGTH']
85
+ return content_length.to_i if content_length
86
+
87
+ # NOTE: An already-read body (e.g. late-parsed multipart on Rack 3+) peeks
88
+ # as 0, so we skip byte_length but still collect the parsed body
89
+ begin
90
+ Rack::InputPeeker.peek_bytesize(env, limit: limit)
91
+ rescue => e
92
+ Datadog.logger.debug { "AppSec: Failed to measure Rails request body: #{e.class}: #{e.message}" }
93
+ nil
94
+ end
95
+ end
62
96
  end
63
97
  end
64
98
  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
 
@@ -16,31 +17,72 @@ module Datadog
16
17
  gateway = Instrumentation.gateway
17
18
 
18
19
  watch_request_action(gateway)
20
+ watch_response_body_json(gateway)
19
21
  end
20
22
 
21
23
  def watch_request_action(gateway = Instrumentation.gateway)
22
- gateway.watch('rails.request.action', :appsec) do |stack, gateway_request|
24
+ gateway.watch('rails.request.action') do |stack, gateway_request|
23
25
  context = gateway_request.env[AppSec::Ext::CONTEXT_KEY]
26
+ limit = Datadog.configuration.appsec.body_parsing_size_limit
24
27
 
25
28
  persistent_data = {
26
- 'server.request.body' => gateway_request.parsed_body,
27
29
  'server.request.path_params' => gateway_request.route_params
28
30
  }
29
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
+
30
48
  result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
31
49
 
32
- if result.match? || !result.derivatives.empty?
50
+ if result.match?
33
51
  context.events.push(
34
52
  AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
35
53
  )
54
+
55
+ AppSec::Event.tag(context, result)
56
+ TraceKeeper.keep!(context.trace) if result.keep?
57
+
58
+ AppSec::ActionsHandler.handle(result.actions)
36
59
  end
37
60
 
61
+ stack.call(gateway_request.request)
62
+ end
63
+ end
64
+
65
+ def watch_response_body_json(gateway = Instrumentation.gateway)
66
+ gateway.watch('rails.response.body.json') do |stack, container|
67
+ context = container.context
68
+
69
+ persistent_data = {
70
+ 'server.response.body' => container.data
71
+ }
72
+ result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
73
+
38
74
  if result.match?
39
- AppSec::Event.tag_and_keep!(context, result)
75
+ context.events.push(
76
+ AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
77
+ )
78
+
79
+ AppSec::Event.tag(context, result)
80
+ TraceKeeper.keep!(context.trace) if result.keep?
81
+
40
82
  AppSec::ActionsHandler.handle(result.actions)
41
83
  end
42
84
 
43
- stack.call(gateway_request.request)
85
+ stack.call(container)
44
86
  end
45
87
  end
46
88
  end
@@ -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?
@@ -8,6 +8,9 @@ require_relative '../rack/request_middleware'
8
8
  require_relative '../rack/request_body_middleware'
9
9
  require_relative 'gateway/watcher'
10
10
  require_relative 'gateway/request'
11
+ require_relative 'patches/render_to_body_patch'
12
+ require_relative 'patches/process_action_patch'
13
+ require_relative '../../api_security/endpoint_collection/rails_collector'
11
14
 
12
15
  require_relative '../../../tracing/contrib/rack/middlewares'
13
16
 
@@ -17,6 +20,8 @@ module Datadog
17
20
  module Rails
18
21
  # Patcher for AppSec on Rails
19
22
  module Patcher
23
+ GUARD_ACTION_CONTROLLER_ONCE_PER_APP = Hash.new { |h, key| h[key] = Datadog::Core::Utils::OnlyOnce.new }
24
+ GUARD_ROUTES_REPORTING_ONCE_PER_APP = Hash.new { |h, key| h[key] = Datadog::Core::Utils::OnlyOnce.new }
20
25
  BEFORE_INITIALIZE_ONLY_ONCE_PER_APP = Hash.new { |h, key| h[key] = Datadog::Core::Utils::OnlyOnce.new }
21
26
  AFTER_INITIALIZE_ONLY_ONCE_PER_APP = Hash.new { |h, key| h[key] = Datadog::Core::Utils::OnlyOnce.new }
22
27
 
@@ -34,6 +39,8 @@ module Datadog
34
39
  Gateway::Watcher.watch
35
40
  patch_before_initialize
36
41
  patch_after_initialize
42
+ patch_action_controller
43
+ subscribe_to_routes_loaded
37
44
 
38
45
  Patcher.instance_variable_set(:@patched, true)
39
46
  end
@@ -49,7 +56,8 @@ module Datadog
49
56
  # Middleware must be added before the application is initialized.
50
57
  # Otherwise the middleware stack will be frozen.
51
58
  add_middleware(app) if Datadog.configuration.tracing[:rails][:middleware]
52
- patch_process_action
59
+
60
+ ::ActionController::Metal.prepend(Patches::ProcessActionPatch)
53
61
  end
54
62
  end
55
63
 
@@ -65,31 +73,6 @@ module Datadog
65
73
  end
66
74
  end
67
75
 
68
- # Hook into ActionController::Instrumentation#process_action, which encompasses action filters
69
- module ProcessActionPatch
70
- def process_action(*args)
71
- env = request.env
72
-
73
- context = env[Datadog::AppSec::Ext::CONTEXT_KEY]
74
-
75
- return super unless context
76
-
77
- # TODO: handle exceptions, except for super
78
-
79
- gateway_request = Gateway::Request.new(request)
80
-
81
- http_response, _gateway_request = Instrumentation.gateway.push('rails.request.action', gateway_request) do
82
- super
83
- end
84
-
85
- http_response
86
- end
87
- end
88
-
89
- def patch_process_action
90
- ::ActionController::Metal.prepend(ProcessActionPatch)
91
- end
92
-
93
76
  def include_middleware?(middleware, app)
94
77
  found = false
95
78
 
@@ -143,6 +126,49 @@ module Datadog
143
126
  end
144
127
  end
145
128
 
129
+ def patch_action_controller
130
+ ::ActiveSupport.on_load(:action_controller) do
131
+ GUARD_ACTION_CONTROLLER_ONCE_PER_APP[self].run do
132
+ ::ActionController::Base.prepend(Patches::RenderToBodyPatch)
133
+ end
134
+
135
+ # Rails 7.1 adds `after_routes_loaded` hook
136
+ if Datadog::AppSec::Contrib::Rails::Patcher.target_version < Gem::Version.new('7.1')
137
+ Datadog::AppSec::Contrib::Rails::Patcher.report_routes_via_telemetry(::Rails.application.routes.routes)
138
+ end
139
+ rescue => e
140
+ error_message = 'Failed to get application routes'
141
+ Datadog.logger.error("#{error_message}, #{e.class}: #{e.message}")
142
+ AppSec.telemetry.report(e, description: error_message)
143
+ end
144
+ end
145
+
146
+ def subscribe_to_routes_loaded
147
+ ::ActiveSupport.on_load(:after_routes_loaded) do
148
+ Datadog::AppSec::Contrib::Rails::Patcher.report_routes_via_telemetry(::Rails.application.routes.routes)
149
+ rescue => e
150
+ error_message = 'Failed to get application routes'
151
+ Datadog.logger.error("#{error_message}, #{e.class}: #{e.message}")
152
+ AppSec.telemetry.report(e, description: error_message)
153
+ end
154
+ end
155
+
156
+ def report_routes_via_telemetry(routes)
157
+ # We do not support Rails 4.x for Endpoint Collection,
158
+ # mainly because the Route#verb was a Regexp before Rails 5.0
159
+ return if target_version < Gem::Version.new('5.0')
160
+ return unless Datadog.configuration.appsec.api_security.endpoint_collection.enabled
161
+ return unless AppSec.telemetry
162
+
163
+ GUARD_ROUTES_REPORTING_ONCE_PER_APP[::Rails.application].run do
164
+ AppSec.telemetry.app_endpoints_loaded(
165
+ APISecurity::EndpointCollection::RailsCollector.new(routes).to_enum
166
+ )
167
+ end
168
+ rescue => e
169
+ AppSec.telemetry&.report(e, description: 'failed to report application endpoints')
170
+ end
171
+
146
172
  def setup_security
147
173
  Datadog::AppSec::Contrib::Rails::Framework.setup
148
174
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module AppSec
5
+ module Contrib
6
+ module Rails
7
+ module Patches
8
+ # Hook into ActionController::Instrumentation#process_action, which encompasses action filters
9
+ module ProcessActionPatch
10
+ def process_action(*args)
11
+ context = request.env[Datadog::AppSec::Ext::CONTEXT_KEY]
12
+ return super unless context
13
+
14
+ context.state[:web_framework] = 'rails'
15
+
16
+ # TODO: handle exceptions, except for super
17
+ gateway_request = Gateway::Request.new(request)
18
+ http_response, _gateway_request = Instrumentation.gateway.push('rails.request.action', gateway_request) do
19
+ super
20
+ end
21
+
22
+ http_response
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end