datadog 2.19.0 → 2.21.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 (302) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +52 -1
  3. data/README.md +0 -1
  4. data/ext/libdatadog_api/extconf.rb +3 -1
  5. data/ext/libdatadog_api/process_discovery.c +5 -5
  6. data/ext/libdatadog_extconf_helpers.rb +13 -3
  7. data/lib/datadog/appsec/api_security/route_extractor.rb +6 -2
  8. data/lib/datadog/appsec/autoload.rb +1 -1
  9. data/lib/datadog/appsec/component.rb +3 -13
  10. data/lib/datadog/appsec/context.rb +23 -0
  11. data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +2 -1
  12. data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +2 -1
  13. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +0 -1
  14. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +0 -1
  15. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +14 -22
  16. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +23 -2
  17. data/lib/datadog/appsec/contrib/rails/patcher.rb +14 -26
  18. data/lib/datadog/appsec/contrib/rails/patches/process_action_patch.rb +27 -0
  19. data/lib/datadog/appsec/contrib/rails/patches/render_to_body_patch.rb +33 -0
  20. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +0 -1
  21. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +23 -0
  22. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +8 -18
  23. data/lib/datadog/appsec/contrib/sinatra/patches/json_patch.rb +31 -0
  24. data/lib/datadog/appsec/event.rb +3 -18
  25. data/lib/datadog/appsec/instrumentation/gateway/argument.rb +16 -0
  26. data/lib/datadog/appsec/metrics/collector.rb +7 -3
  27. data/lib/datadog/appsec/metrics/telemetry.rb +1 -1
  28. data/lib/datadog/appsec/metrics/telemetry_exporter.rb +28 -0
  29. data/lib/datadog/appsec/metrics.rb +1 -0
  30. data/lib/datadog/appsec/security_engine/engine.rb +14 -32
  31. data/lib/datadog/appsec/security_engine/result.rb +16 -0
  32. data/lib/datadog/appsec/security_engine/runner.rb +18 -4
  33. data/lib/datadog/appsec/thread_safe_ref.rb +61 -0
  34. data/lib/datadog/appsec/trace_keeper.rb +24 -0
  35. data/lib/datadog/appsec/utils/hash_coercion.rb +23 -0
  36. data/lib/datadog/appsec.rb +0 -7
  37. data/lib/datadog/auto_instrument_base.rb +2 -1
  38. data/lib/datadog/core/configuration/agent_settings_resolver.rb +4 -4
  39. data/lib/datadog/core/configuration/components.rb +8 -2
  40. data/lib/datadog/core/configuration/config_helper.rb +100 -0
  41. data/lib/datadog/core/configuration/deprecations.rb +36 -0
  42. data/lib/datadog/core/configuration/ext.rb +0 -1
  43. data/lib/datadog/core/configuration/option.rb +55 -51
  44. data/lib/datadog/core/configuration/option_definition.rb +2 -11
  45. data/lib/datadog/core/configuration/options.rb +14 -12
  46. data/lib/datadog/core/configuration/settings.rb +10 -6
  47. data/lib/datadog/core/configuration/supported_configurations.rb +335 -0
  48. data/lib/datadog/core/configuration.rb +1 -1
  49. data/lib/datadog/core/deprecations.rb +2 -2
  50. data/lib/datadog/core/environment/ext.rb +0 -2
  51. data/lib/datadog/core/environment/git.rb +2 -2
  52. data/lib/datadog/core/environment/variable_helpers.rb +3 -3
  53. data/lib/datadog/core/metrics/client.rb +2 -2
  54. data/lib/datadog/core/process_discovery/tracer_memfd.rb +2 -4
  55. data/lib/datadog/core/process_discovery.rb +46 -23
  56. data/lib/datadog/core/runtime/ext.rb +0 -1
  57. data/lib/datadog/core/telemetry/event/app_started.rb +2 -2
  58. data/lib/datadog/core.rb +2 -0
  59. data/lib/datadog/di/boot.rb +9 -1
  60. data/lib/datadog/di/component.rb +7 -0
  61. data/lib/datadog/di/probe_file_loader/railtie.rb +15 -0
  62. data/lib/datadog/di/probe_file_loader.rb +82 -0
  63. data/lib/datadog/di/probe_notification_builder.rb +1 -1
  64. data/lib/datadog/di/remote.rb +3 -5
  65. data/lib/datadog/di.rb +0 -1
  66. data/lib/datadog/kit/appsec/events/v2.rb +5 -4
  67. data/lib/datadog/kit/appsec/events.rb +11 -10
  68. data/lib/datadog/kit/identity.rb +17 -11
  69. data/lib/datadog/opentelemetry/api/baggage.rb +2 -2
  70. data/lib/datadog/opentelemetry/api/context.rb +10 -9
  71. data/lib/datadog/opentelemetry/sdk/configurator.rb +1 -1
  72. data/lib/datadog/opentelemetry/sdk/propagator.rb +4 -4
  73. data/lib/datadog/opentelemetry/sdk/span_processor.rb +8 -8
  74. data/lib/datadog/opentelemetry/sdk/trace/span.rb +14 -10
  75. data/lib/datadog/opentelemetry/trace.rb +4 -4
  76. data/lib/datadog/profiling/collectors/info.rb +1 -1
  77. data/lib/datadog/profiling/ext.rb +2 -1
  78. data/lib/datadog/profiling/http_transport.rb +1 -1
  79. data/lib/datadog/profiling/tasks/exec.rb +2 -2
  80. data/lib/datadog/profiling.rb +6 -8
  81. data/lib/datadog/tracing/analytics.rb +1 -1
  82. data/lib/datadog/tracing/buffer.rb +7 -7
  83. data/lib/datadog/tracing/configuration/dynamic.rb +4 -6
  84. data/lib/datadog/tracing/configuration/ext.rb +3 -5
  85. data/lib/datadog/tracing/configuration/settings.rb +29 -7
  86. data/lib/datadog/tracing/context.rb +2 -2
  87. data/lib/datadog/tracing/contrib/action_cable/event.rb +1 -1
  88. data/lib/datadog/tracing/contrib/action_cable/integration.rb +1 -1
  89. data/lib/datadog/tracing/contrib/action_mailer/integration.rb +1 -1
  90. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +4 -4
  91. data/lib/datadog/tracing/contrib/action_pack/integration.rb +1 -1
  92. data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +1 -1
  93. data/lib/datadog/tracing/contrib/active_job/event.rb +8 -8
  94. data/lib/datadog/tracing/contrib/active_job/events/discard.rb +1 -1
  95. data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +1 -1
  96. data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +1 -1
  97. data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +1 -1
  98. data/lib/datadog/tracing/contrib/active_job/events/perform.rb +1 -1
  99. data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +1 -1
  100. data/lib/datadog/tracing/contrib/active_job/integration.rb +1 -1
  101. data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +1 -1
  102. data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +3 -3
  103. data/lib/datadog/tracing/contrib/active_model_serializers/integration.rb +1 -2
  104. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +1 -1
  105. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +1 -1
  106. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +5 -5
  107. data/lib/datadog/tracing/contrib/active_record/integration.rb +1 -1
  108. data/lib/datadog/tracing/contrib/active_record/utils.rb +15 -15
  109. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +6 -6
  110. data/lib/datadog/tracing/contrib/active_support/integration.rb +1 -1
  111. data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +2 -1
  112. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +7 -9
  113. data/lib/datadog/tracing/contrib/aws/ext.rb +1 -1
  114. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +2 -2
  115. data/lib/datadog/tracing/contrib/aws/parsed_context.rb +3 -1
  116. data/lib/datadog/tracing/contrib/aws/patcher.rb +5 -1
  117. data/lib/datadog/tracing/contrib/aws/service/base.rb +2 -1
  118. data/lib/datadog/tracing/contrib/aws/service/dynamodb.rb +1 -1
  119. data/lib/datadog/tracing/contrib/aws/service/eventbridge.rb +1 -1
  120. data/lib/datadog/tracing/contrib/aws/service/kinesis.rb +1 -1
  121. data/lib/datadog/tracing/contrib/aws/service/s3.rb +1 -1
  122. data/lib/datadog/tracing/contrib/aws/service/sns.rb +1 -1
  123. data/lib/datadog/tracing/contrib/aws/service/sqs.rb +1 -1
  124. data/lib/datadog/tracing/contrib/aws/service/states.rb +1 -1
  125. data/lib/datadog/tracing/contrib/aws/services.rb +7 -7
  126. data/lib/datadog/tracing/contrib/concurrent_ruby/async_patch.rb +1 -1
  127. data/lib/datadog/tracing/contrib/concurrent_ruby/context_composite_executor_service.rb +1 -1
  128. data/lib/datadog/tracing/contrib/concurrent_ruby/future_patch.rb +1 -1
  129. data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +1 -1
  130. data/lib/datadog/tracing/contrib/concurrent_ruby/promises_future_patch.rb +1 -1
  131. data/lib/datadog/tracing/contrib/configurable.rb +6 -6
  132. data/lib/datadog/tracing/contrib/configuration/resolvers/pattern_resolver.rb +4 -4
  133. data/lib/datadog/tracing/contrib/dalli/ext.rb +3 -2
  134. data/lib/datadog/tracing/contrib/dalli/integration.rb +1 -1
  135. data/lib/datadog/tracing/contrib/delayed_job/integration.rb +1 -1
  136. data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +3 -2
  137. data/lib/datadog/tracing/contrib/elasticsearch/integration.rb +4 -4
  138. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +51 -53
  139. data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +5 -5
  140. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +2 -2
  141. data/lib/datadog/tracing/contrib/ethon/ext.rb +3 -2
  142. data/lib/datadog/tracing/contrib/ethon/integration.rb +1 -1
  143. data/lib/datadog/tracing/contrib/excon/ext.rb +3 -2
  144. data/lib/datadog/tracing/contrib/excon/integration.rb +1 -1
  145. data/lib/datadog/tracing/contrib/excon/middleware.rb +2 -2
  146. data/lib/datadog/tracing/contrib/ext.rb +3 -3
  147. data/lib/datadog/tracing/contrib/extensions.rb +9 -9
  148. data/lib/datadog/tracing/contrib/faraday/ext.rb +3 -2
  149. data/lib/datadog/tracing/contrib/faraday/integration.rb +1 -1
  150. data/lib/datadog/tracing/contrib/faraday/middleware.rb +4 -2
  151. data/lib/datadog/tracing/contrib/grape/endpoint.rb +8 -8
  152. data/lib/datadog/tracing/contrib/grape/integration.rb +1 -1
  153. data/lib/datadog/tracing/contrib/graphql/integration.rb +1 -1
  154. data/lib/datadog/tracing/contrib/graphql/patcher.rb +2 -2
  155. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +36 -25
  156. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +8 -8
  157. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +3 -3
  158. data/lib/datadog/tracing/contrib/grpc/distributed/fetcher.rb +1 -1
  159. data/lib/datadog/tracing/contrib/grpc/integration.rb +1 -1
  160. data/lib/datadog/tracing/contrib/hanami/ext.rb +2 -2
  161. data/lib/datadog/tracing/contrib/hanami/integration.rb +1 -1
  162. data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +1 -1
  163. data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +9 -11
  164. data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +4 -4
  165. data/lib/datadog/tracing/contrib/http/ext.rb +3 -2
  166. data/lib/datadog/tracing/contrib/http/instrumentation.rb +5 -5
  167. data/lib/datadog/tracing/contrib/httpclient/ext.rb +3 -2
  168. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +3 -3
  169. data/lib/datadog/tracing/contrib/httpclient/integration.rb +1 -1
  170. data/lib/datadog/tracing/contrib/httprb/ext.rb +3 -2
  171. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +4 -4
  172. data/lib/datadog/tracing/contrib/httprb/integration.rb +1 -1
  173. data/lib/datadog/tracing/contrib/kafka/event.rb +1 -1
  174. data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +1 -1
  175. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +1 -1
  176. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +1 -1
  177. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +1 -1
  178. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/join_group.rb +1 -1
  179. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/leave_group.rb +1 -1
  180. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/sync_group.rb +1 -1
  181. data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +1 -1
  182. data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +1 -1
  183. data/lib/datadog/tracing/contrib/kafka/integration.rb +1 -1
  184. data/lib/datadog/tracing/contrib/karafka/monitor.rb +13 -13
  185. data/lib/datadog/tracing/contrib/karafka/patcher.rb +4 -4
  186. data/lib/datadog/tracing/contrib/lograge/instrumentation.rb +1 -1
  187. data/lib/datadog/tracing/contrib/lograge/integration.rb +1 -1
  188. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +1 -1
  189. data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -1
  190. data/lib/datadog/tracing/contrib/mongodb/integration.rb +1 -1
  191. data/lib/datadog/tracing/contrib/mongodb/parsers.rb +1 -1
  192. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +6 -6
  193. data/lib/datadog/tracing/contrib/mysql2/ext.rb +1 -1
  194. data/lib/datadog/tracing/contrib/mysql2/integration.rb +1 -1
  195. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +1 -1
  196. data/lib/datadog/tracing/contrib/opensearch/ext.rb +3 -2
  197. data/lib/datadog/tracing/contrib/opensearch/integration.rb +1 -2
  198. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +68 -70
  199. data/lib/datadog/tracing/contrib/opensearch/quantize.rb +5 -5
  200. data/lib/datadog/tracing/contrib/patcher.rb +7 -9
  201. data/lib/datadog/tracing/contrib/pg/integration.rb +1 -1
  202. data/lib/datadog/tracing/contrib/presto/ext.rb +1 -1
  203. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +3 -3
  204. data/lib/datadog/tracing/contrib/presto/integration.rb +1 -1
  205. data/lib/datadog/tracing/contrib/propagation/sql_comment/comment.rb +1 -1
  206. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +1 -1
  207. data/lib/datadog/tracing/contrib/que/integration.rb +1 -1
  208. data/lib/datadog/tracing/contrib/racecar/event.rb +1 -1
  209. data/lib/datadog/tracing/contrib/racecar/events/batch.rb +2 -2
  210. data/lib/datadog/tracing/contrib/racecar/events/consume.rb +1 -1
  211. data/lib/datadog/tracing/contrib/racecar/events/message.rb +2 -2
  212. data/lib/datadog/tracing/contrib/racecar/integration.rb +1 -1
  213. data/lib/datadog/tracing/contrib/rack/header_collection.rb +1 -1
  214. data/lib/datadog/tracing/contrib/rack/header_tagging.rb +32 -32
  215. data/lib/datadog/tracing/contrib/rack/integration.rb +1 -1
  216. data/lib/datadog/tracing/contrib/rack/middlewares.rb +21 -17
  217. data/lib/datadog/tracing/contrib/rack/patcher.rb +1 -1
  218. data/lib/datadog/tracing/contrib/rack/request_queue.rb +3 -2
  219. data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +7 -1
  220. data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +1 -1
  221. data/lib/datadog/tracing/contrib/rails/ext.rb +2 -1
  222. data/lib/datadog/tracing/contrib/rails/integration.rb +2 -2
  223. data/lib/datadog/tracing/contrib/rails/log_injection.rb +1 -1
  224. data/lib/datadog/tracing/contrib/rails/middlewares.rb +1 -1
  225. data/lib/datadog/tracing/contrib/rails/runner.rb +5 -4
  226. data/lib/datadog/tracing/contrib/rake/instrumentation.rb +4 -4
  227. data/lib/datadog/tracing/contrib/rake/integration.rb +1 -1
  228. data/lib/datadog/tracing/contrib/redis/configuration/resolver.rb +2 -2
  229. data/lib/datadog/tracing/contrib/redis/ext.rb +3 -2
  230. data/lib/datadog/tracing/contrib/redis/integration.rb +2 -2
  231. data/lib/datadog/tracing/contrib/redis/patcher.rb +4 -4
  232. data/lib/datadog/tracing/contrib/redis/quantize.rb +1 -1
  233. data/lib/datadog/tracing/contrib/redis/tags.rb +1 -1
  234. data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +4 -4
  235. data/lib/datadog/tracing/contrib/registry.rb +1 -1
  236. data/lib/datadog/tracing/contrib/resque/integration.rb +1 -1
  237. data/lib/datadog/tracing/contrib/resque/resque_job.rb +1 -1
  238. data/lib/datadog/tracing/contrib/rest_client/ext.rb +3 -2
  239. data/lib/datadog/tracing/contrib/rest_client/integration.rb +1 -1
  240. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +3 -3
  241. data/lib/datadog/tracing/contrib/roda/instrumentation.rb +1 -1
  242. data/lib/datadog/tracing/contrib/roda/integration.rb +1 -1
  243. data/lib/datadog/tracing/contrib/semantic_logger/instrumentation.rb +1 -1
  244. data/lib/datadog/tracing/contrib/semantic_logger/integration.rb +1 -1
  245. data/lib/datadog/tracing/contrib/sequel/database.rb +5 -5
  246. data/lib/datadog/tracing/contrib/sequel/dataset.rb +1 -1
  247. data/lib/datadog/tracing/contrib/sequel/integration.rb +1 -1
  248. data/lib/datadog/tracing/contrib/sequel/utils.rb +1 -1
  249. data/lib/datadog/tracing/contrib/shoryuken/integration.rb +1 -1
  250. data/lib/datadog/tracing/contrib/sidekiq/integration.rb +1 -1
  251. data/lib/datadog/tracing/contrib/sidekiq/utils.rb +1 -1
  252. data/lib/datadog/tracing/contrib/sinatra/integration.rb +1 -1
  253. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +38 -40
  254. data/lib/datadog/tracing/contrib/sneakers/integration.rb +1 -1
  255. data/lib/datadog/tracing/contrib/span_attribute_schema.rb +1 -1
  256. data/lib/datadog/tracing/contrib/stripe/integration.rb +1 -1
  257. data/lib/datadog/tracing/contrib/stripe/request.rb +1 -1
  258. data/lib/datadog/tracing/contrib/sucker_punch/integration.rb +1 -1
  259. data/lib/datadog/tracing/contrib/trilogy/ext.rb +1 -1
  260. data/lib/datadog/tracing/contrib/trilogy/integration.rb +1 -1
  261. data/lib/datadog/tracing/contrib/utils/quantization/hash.rb +11 -11
  262. data/lib/datadog/tracing/contrib/utils/quantization/http.rb +6 -6
  263. data/lib/datadog/tracing/diagnostics/environment_logger.rb +5 -1
  264. data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
  265. data/lib/datadog/tracing/distributed/baggage.rb +73 -8
  266. data/lib/datadog/tracing/distributed/datadog.rb +4 -5
  267. data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +11 -13
  268. data/lib/datadog/tracing/distributed/helpers.rb +1 -1
  269. data/lib/datadog/tracing/distributed/none.rb +4 -2
  270. data/lib/datadog/tracing/distributed/propagation.rb +4 -1
  271. data/lib/datadog/tracing/distributed/propagation_policy.rb +1 -1
  272. data/lib/datadog/tracing/distributed/trace_context.rb +22 -16
  273. data/lib/datadog/tracing/event.rb +5 -7
  274. data/lib/datadog/tracing/flush.rb +1 -1
  275. data/lib/datadog/tracing/metadata/analytics.rb +1 -1
  276. data/lib/datadog/tracing/metadata/tagging.rb +4 -4
  277. data/lib/datadog/tracing/pipeline/span_filter.rb +3 -1
  278. data/lib/datadog/tracing/pipeline/span_processor.rb +3 -1
  279. data/lib/datadog/tracing/pipeline.rb +1 -1
  280. data/lib/datadog/tracing/sampling/ext.rb +0 -2
  281. data/lib/datadog/tracing/sampling/rule_sampler.rb +30 -30
  282. data/lib/datadog/tracing/sampling/span/rule_parser.rb +1 -1
  283. data/lib/datadog/tracing/sampling/span/sampler.rb +0 -7
  284. data/lib/datadog/tracing/span.rb +1 -1
  285. data/lib/datadog/tracing/span_event.rb +10 -10
  286. data/lib/datadog/tracing/span_link.rb +12 -12
  287. data/lib/datadog/tracing/span_operation.rb +9 -11
  288. data/lib/datadog/tracing/trace_digest.rb +21 -23
  289. data/lib/datadog/tracing/trace_operation.rb +84 -88
  290. data/lib/datadog/tracing/trace_segment.rb +2 -2
  291. data/lib/datadog/tracing/tracer.rb +36 -38
  292. data/lib/datadog/tracing/transport/http/client.rb +1 -1
  293. data/lib/datadog/tracing/transport/http/traces.rb +2 -2
  294. data/lib/datadog/tracing/transport/io/client.rb +5 -5
  295. data/lib/datadog/tracing/transport/io/traces.rb +4 -4
  296. data/lib/datadog/tracing/transport/statistics.rb +1 -1
  297. data/lib/datadog/tracing/transport/traces.rb +5 -5
  298. data/lib/datadog/tracing/workers/trace_writer.rb +12 -12
  299. data/lib/datadog/tracing/workers.rb +2 -2
  300. data/lib/datadog/tracing.rb +2 -2
  301. data/lib/datadog/version.rb +1 -1
  302. metadata +18 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9c533682b9a96989e1ad8d4eb96339af4bffdb5fd9cbfe447bd0a034bc387c03
4
- data.tar.gz: 5d7808aa6b7fd5f9c68e453fef4fff8c5345c62fb26a7f7839d630ec0da2fe9f
3
+ metadata.gz: e804b0ea5131eba47b865f95a6540c84a2c20e061a9d25a9bf1f2841895c46c6
4
+ data.tar.gz: 7c7b61bb061c943aad519ede1f4900351db8b79e7111368c3d85f23ac73fafb8
5
5
  SHA512:
6
- metadata.gz: 6b35d7ef1ce2f9e565727037f9e5b329d019202ff20c01a15bb5096cf14253b3ab9812d4fc84fc23e265ec2e7e0096e34acc6a845ad510b215ef7df4093107e7
7
- data.tar.gz: 72fff247b51de201e4373638627fa419a3a679979f880dfa44c73d1c9a7c062991746045d41cbe5fa47d824b025fb9cad2f34c0139e034df1b85ddb4a07bccd9
6
+ metadata.gz: 669cc7248fe15fbd07ab98e71d20e3ec97d644b27ef43be9b7fe7b047c60bd8794c903db3cfe1f4580f7877f7a1491f5028743a618e649930ff10d14756ae820
7
+ data.tar.gz: e5a2e28ebcc390f1e2277299b883946c4f0baec35754216bbea4da4df437fa06e8c2b6cc0aa5f7847256e0b500903076a19ec7456c7979e7759fc7a4fb8836d3
data/CHANGELOG.md CHANGED
@@ -2,6 +2,42 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [2.21.0] - 2025-09-17
6
+
7
+ ### Added
8
+
9
+ * Tracing: Generate metrics for GraphQL operation execution ([#4862][])
10
+
11
+ ### Changed
12
+
13
+ * Tracing: The `graphql.execute` span resource now includes the operation type ([#4862][])
14
+
15
+ ### Fixed
16
+
17
+ * Tracing: Fix Service Discovery capabilities on forked processes ([#4877][])
18
+ * Tracing: Fix an unclosed trace issue when the Rack application has proxy spans and raises an exception. This caused traces that encompassed multiple requests ([#4779][])
19
+ * AppSec: Fix API Security route extraction for Rails ([#4887][])
20
+ * AppSec: Fix a bug with non-string Hash keys conversion ([#4893][])
21
+ * Dynamic Instrumentation: Fix incorrect template expression evaluation in some cases ([#4884][])
22
+
23
+ ## [2.20.0] - 2025-09-04
24
+
25
+ ### Added
26
+
27
+ * Tracing: Add capability to add [W3C Baggage](https://www.w3.org/TR/baggage/#example) headers to the local root span as span tags ([#4716][])
28
+ * AppSec: Add WAF analysis of the responses with JSON body ([#4848][])
29
+ * Dynamic Instrumentation: Live Debugger: Add support for specifying probes in a file via `DD_DYNAMIC_INSTRUMENTATION_PROBE_FILE` environment variable ([#4838][])
30
+
31
+ ### Changed
32
+
33
+ * Core: Expand generated warning and error messages during `libdatadog` build ([#4831][])
34
+ * AppSec: Rework handling of Remote Config updates for multi-threaded web servers ([#4833][])
35
+ * AppSec: Update security tags for Business Logic Events and User Events SDK v1 and v2 ([#4851][])
36
+
37
+ ### Fixed
38
+
39
+ * Tracing: Fix constants resolution for Rails runner ([#4863][])
40
+
5
41
  ## [2.19.0] - 2025-07-24
6
42
 
7
43
  ### Added
@@ -3297,7 +3333,9 @@ Release notes: https://github.com/DataDog/dd-trace-rb/releases/tag/v0.3.1
3297
3333
  Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
3298
3334
 
3299
3335
 
3300
- [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.19.0...master
3336
+ [Unreleased]: https://github.com/DataDog/dd-trace-rb/compare/v2.21.0...master
3337
+ [2.21.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.20.0...v2.21.0
3338
+ [2.20.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.19.0...v2.20.0
3301
3339
  [2.19.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.18.0...v2.19.0
3302
3340
  [2.18.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.17.0...v2.18.0
3303
3341
  [2.17.0]: https://github.com/DataDog/dd-trace-rb/compare/v2.16.0...v2.17.0
@@ -4863,6 +4901,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
4863
4901
  [#4693]: https://github.com/DataDog/dd-trace-rb/issues/4693
4864
4902
  [#4697]: https://github.com/DataDog/dd-trace-rb/issues/4697
4865
4903
  [#4699]: https://github.com/DataDog/dd-trace-rb/issues/4699
4904
+ [#4716]: https://github.com/DataDog/dd-trace-rb/issues/4716
4866
4905
  [#4718]: https://github.com/DataDog/dd-trace-rb/issues/4718
4867
4906
  [#4721]: https://github.com/DataDog/dd-trace-rb/issues/4721
4868
4907
  [#4728]: https://github.com/DataDog/dd-trace-rb/issues/4728
@@ -4874,6 +4913,7 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
4874
4913
  [#4771]: https://github.com/DataDog/dd-trace-rb/issues/4771
4875
4914
  [#4772]: https://github.com/DataDog/dd-trace-rb/issues/4772
4876
4915
  [#4776]: https://github.com/DataDog/dd-trace-rb/issues/4776
4916
+ [#4779]: https://github.com/DataDog/dd-trace-rb/issues/4779
4877
4917
  [#4783]: https://github.com/DataDog/dd-trace-rb/issues/4783
4878
4918
  [#4785]: https://github.com/DataDog/dd-trace-rb/issues/4785
4879
4919
  [#4786]: https://github.com/DataDog/dd-trace-rb/issues/4786
@@ -4884,6 +4924,17 @@ Git diff: https://github.com/DataDog/dd-trace-rb/compare/v0.3.0...v0.3.1
4884
4924
  [#4813]: https://github.com/DataDog/dd-trace-rb/issues/4813
4885
4925
  [#4814]: https://github.com/DataDog/dd-trace-rb/issues/4814
4886
4926
  [#4819]: https://github.com/DataDog/dd-trace-rb/issues/4819
4927
+ [#4831]: https://github.com/DataDog/dd-trace-rb/issues/4831
4928
+ [#4833]: https://github.com/DataDog/dd-trace-rb/issues/4833
4929
+ [#4838]: https://github.com/DataDog/dd-trace-rb/issues/4838
4930
+ [#4848]: https://github.com/DataDog/dd-trace-rb/issues/4848
4931
+ [#4851]: https://github.com/DataDog/dd-trace-rb/issues/4851
4932
+ [#4862]: https://github.com/DataDog/dd-trace-rb/issues/4862
4933
+ [#4863]: https://github.com/DataDog/dd-trace-rb/issues/4863
4934
+ [#4877]: https://github.com/DataDog/dd-trace-rb/issues/4877
4935
+ [#4884]: https://github.com/DataDog/dd-trace-rb/issues/4884
4936
+ [#4887]: https://github.com/DataDog/dd-trace-rb/issues/4887
4937
+ [#4893]: https://github.com/DataDog/dd-trace-rb/issues/4893
4887
4938
  [@AdrianLC]: https://github.com/AdrianLC
4888
4939
  [@Azure7111]: https://github.com/Azure7111
4889
4940
  [@BabyGroot]: https://github.com/BabyGroot
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # Datadog Trace Client
2
2
 
3
3
  [![Gem](https://img.shields.io/gem/v/datadog)](https://rubygems.org/gems/datadog/)
4
- [![codecov](https://codecov.io/gh/DataDog/dd-trace-rb/branch/master/graph/badge.svg)](https://app.codecov.io/gh/DataDog/dd-trace-rb/branch/master)
5
4
  [![YARD documentation](https://img.shields.io/badge/YARD-documentation-blue)][api docs]
6
5
 
7
6
  ``datadog`` is Datadog's client library for Ruby. It includes a suite of tools which provide visibility into the performance and security of Ruby applications, to enable Ruby developers to identify bottlenecks and other issues.
@@ -26,7 +26,9 @@ if ENV['DD_NO_EXTENSION'].to_s.strip.downcase == 'true'
26
26
  end
27
27
  skip_building_extension!('current Ruby VM is not supported') if RUBY_ENGINE != 'ruby'
28
28
  skip_building_extension!('Microsoft Windows is not supported') if Gem.win_platform?
29
- skip_building_extension!('issue setting up `libdatadog` gem') if Datadog::LibdatadogExtconfHelpers.libdatadog_issue?
29
+
30
+ libdatadog_issue = Datadog::LibdatadogExtconfHelpers.load_libdatadog_or_get_issue
31
+ skip_building_extension!("issue setting up `libdatadog` gem: #{libdatadog_issue}") if libdatadog_issue
30
32
 
31
33
  require 'mkmf'
32
34
 
@@ -27,13 +27,13 @@ static const rb_data_type_t tracer_memfd_type = {
27
27
  };
28
28
 
29
29
  void process_discovery_init(VALUE core_module) {
30
- VALUE process_discovery_class = rb_define_class_under(core_module, "ProcessDiscovery", rb_cObject);
31
- VALUE tracer_memfd_class = rb_define_class_under(process_discovery_class, "TracerMemfd", rb_cObject);
30
+ VALUE process_discovery_module = rb_define_module_under(core_module, "ProcessDiscovery");
31
+ VALUE tracer_memfd_class = rb_define_class_under(process_discovery_module, "TracerMemfd", rb_cObject);
32
32
  rb_undef_alloc_func(tracer_memfd_class); // Class cannot be instantiated from Ruby
33
33
 
34
- rb_define_singleton_method(process_discovery_class, "_native_store_tracer_metadata", _native_store_tracer_metadata, -1);
35
- rb_define_singleton_method(process_discovery_class, "_native_to_rb_int", _native_to_rb_int, 1);
36
- rb_define_singleton_method(process_discovery_class, "_native_close_tracer_memfd", _native_close_tracer_memfd, 2);
34
+ rb_define_module_function(process_discovery_module, "_native_store_tracer_metadata", _native_store_tracer_metadata, -1);
35
+ rb_define_module_function(process_discovery_module, "_native_to_rb_int", _native_to_rb_int, 1);
36
+ rb_define_module_function(process_discovery_module, "_native_close_tracer_memfd", _native_close_tracer_memfd, 2);
37
37
  }
38
38
 
39
39
  static VALUE _native_store_tracer_metadata(int argc, VALUE *argv, VALUE self) {
@@ -5,6 +5,8 @@ require 'pathname'
5
5
 
6
6
  module Datadog
7
7
  # Contains a bunch of shared helpers that get used during building of extensions that link to libdatadog
8
+ #
9
+ # Note: Specs for this file currently live in `spec/datadog/profiling/native_extension_helpers_spec.rb`.
8
10
  module LibdatadogExtconfHelpers
9
11
  # Used to make sure the correct gem version gets loaded, as extconf.rb does not get run with "bundle exec" and thus
10
12
  # may see multiple libdatadog versions. See https://github.com/DataDog/dd-trace-rb/pull/2531 for the horror story.
@@ -122,9 +124,17 @@ module Datadog
122
124
  end
123
125
  end
124
126
 
125
- def self.libdatadog_issue?
126
- try_loading_libdatadog { |_exception| return true }
127
- Libdatadog.pkgconfig_folder.nil?
127
+ # Note: This helper is currently only used in the `libdatadog_api/extconf.rb` BUT still lives here to enable testing.
128
+ def self.load_libdatadog_or_get_issue
129
+ try_loading_libdatadog do |exception|
130
+ return "There was an error loading `libdatadog`: #{exception.class} #{exception.message}"
131
+ end
132
+
133
+ unless Libdatadog.pkgconfig_folder
134
+ "The `libdatadog` gem installed on your system is missing binaries for your platform variant. " \
135
+ "Your platform: " \
136
+ "`#{Libdatadog.current_platform}`; available binaries: `#{Libdatadog.available_binaries.join("`, `")}`"
137
+ end
128
138
  end
129
139
  end
130
140
  end
@@ -39,9 +39,9 @@ module Datadog
39
39
  # WARNING: This method works only *after* the request has been routed.
40
40
  #
41
41
  # WARNING: In Rails > 7.1 when a route was not found,
42
- # action_dispatch.route_uri_pattern will not be set.
42
+ # `action_dispatch.route_uri_pattern` will not be set.
43
43
  # In Rails < 7.1 it also will not be set even if a route was found,
44
- # but in this case action_dispatch.request.path_parameters won't be empty.
44
+ # but in this case `action_dispatch.request.path_parameters` won't be empty.
45
45
  def self.route_pattern(request)
46
46
  if request.env.key?(GRAPE_ROUTE_KEY)
47
47
  pattern = request.env[GRAPE_ROUTE_KEY][:route_info]&.pattern&.origin
@@ -52,6 +52,10 @@ module Datadog
52
52
  elsif request.env.key?(RAILS_ROUTE_KEY)
53
53
  request.env[RAILS_ROUTE_KEY].delete_suffix(RAILS_FORMAT_SUFFIX)
54
54
  elsif request.env.key?(RAILS_ROUTES_KEY) && !request.env.fetch(RAILS_PATH_PARAMS_KEY, {}).empty?
55
+ # NOTE: Rails mutate HEAD request in order to understand that route is supported.
56
+ # It will assing GET request method and run the route recognition.
57
+ request = request.env[RAILS_ROUTES_KEY].request_class.new(request.env) if request.head?
58
+
55
59
  pattern = request.env[RAILS_ROUTES_KEY].router
56
60
  .recognize(request) { |route, _| break route.path.spec.to_s }
57
61
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- if %w[1 true].include?((ENV['DD_APPSEC_ENABLED'] || '').downcase)
3
+ if %w[1 true].include?((Datadog::DATADOG_ENV['DD_APPSEC_ENABLED'] || '').downcase)
4
4
  begin
5
5
  require_relative 'contrib/auto_instrument'
6
6
  Datadog::AppSec::Contrib::AutoInstrument.patch_all
@@ -4,6 +4,7 @@ require_relative 'security_engine/engine'
4
4
  require_relative 'security_engine/runner'
5
5
  require_relative 'processor/rule_loader'
6
6
  require_relative 'actions_handler'
7
+ require_relative 'thread_safe_ref'
7
8
 
8
9
  module Datadog
9
10
  module AppSec
@@ -74,25 +75,14 @@ module Datadog
74
75
  def initialize(security_engine:, telemetry:)
75
76
  @security_engine = security_engine
76
77
  @telemetry = telemetry
77
-
78
- @mutex = Mutex.new
79
78
  end
80
79
 
81
80
  def reconfigure!
82
- @mutex.synchronize do
83
- security_engine.reconfigure!
84
- end
85
- end
86
-
87
- def reconfigure_lock(&block)
88
- @mutex.synchronize(&block)
81
+ security_engine.reconfigure!
89
82
  end
90
83
 
91
84
  def shutdown!
92
- @mutex.synchronize do
93
- security_engine.finalize!
94
- @security_engine = nil
95
- end
85
+ # no-op
96
86
  end
97
87
  end
98
88
  end
@@ -37,6 +37,7 @@ module Datadog
37
37
  @events = []
38
38
  @waf_runner = waf_runner
39
39
  @metrics = Metrics::Collector.new
40
+ @interrupted = false
40
41
  end
41
42
 
42
43
  def run_waf(persistent_data, ephemeral_data, timeout = WAF::LibDDWAF::DDWAF_RUN_TIMEOUT)
@@ -55,6 +56,22 @@ module Datadog
55
56
  result
56
57
  end
57
58
 
59
+ def mark_as_interrupted!
60
+ @interrupted = true
61
+ end
62
+
63
+ def interrupted?
64
+ @interrupted
65
+ end
66
+
67
+ def waf_runner_ruleset_version
68
+ @waf_runner.ruleset_version
69
+ end
70
+
71
+ def waf_runner_known_addresses
72
+ @waf_runner.waf_addresses
73
+ end
74
+
58
75
  def extract_schema
59
76
  @waf_runner.run({'waf.context.processor' => {'extract-schema' => true}}, {})
60
77
  end
@@ -66,6 +83,12 @@ module Datadog
66
83
  Metrics::Exporter.export_rasp_metrics(@metrics.rasp, @span)
67
84
  end
68
85
 
86
+ def export_request_telemetry
87
+ return if @trace.nil?
88
+
89
+ Metrics::TelemetryExporter.export_waf_request_metrics(@metrics.waf, self)
90
+ end
91
+
69
92
  def finalize!
70
93
  @waf_runner.finalize!
71
94
  end
@@ -3,6 +3,7 @@
3
3
  require_relative '../ext'
4
4
  require_relative '../configuration'
5
5
  require_relative '../data_extractor'
6
+ require_relative '../../../trace_keeper'
6
7
 
7
8
  module Datadog
8
9
  module AppSec
@@ -25,7 +26,7 @@ module Datadog
25
26
  return result
26
27
  end
27
28
 
28
- context.trace.keep!
29
+ TraceKeeper.keep!(context.trace)
29
30
 
30
31
  if result
31
32
  record_successful_signin(context, resource)
@@ -3,6 +3,7 @@
3
3
  require_relative '../ext'
4
4
  require_relative '../configuration'
5
5
  require_relative '../data_extractor'
6
+ require_relative '../../../trace_keeper'
6
7
 
7
8
  module Datadog
8
9
  module AppSec
@@ -26,7 +27,7 @@ module Datadog
26
27
 
27
28
  next yield(resource) if resource.new_record? && block_given?
28
29
 
29
- context.trace.keep!
30
+ TraceKeeper.keep!(context.trace)
30
31
  record_successful_signup(context, resource)
31
32
  Instrumentation.gateway.push('appsec.events.user_lifecycle', Ext::EVENT_SIGNUP)
32
33
 
@@ -1,4 +1,3 @@
1
- # rubocop:disable Naming/FileName
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require 'excon'
@@ -1,4 +1,3 @@
1
- # rubocop:disable Naming/FileName
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require_relative '../../event'
@@ -46,33 +46,22 @@ module Datadog
46
46
  boot = Datadog::Core::Remote::Tie.boot
47
47
  Datadog::Core::Remote::Tie::Tracing.tag(boot, active_span)
48
48
 
49
- security_engine = nil
50
- ready = false
51
- ctx = nil
52
-
53
49
  # For a given request, keep using the first Rack stack scope for
54
50
  # nested apps. Don't set `context` local variable so that on popping
55
51
  # out of this nested stack we don't finalize the parent's context
56
52
  return @app.call(env) if active_context(env)
57
53
 
58
- Datadog::AppSec.reconfigure_lock do
59
- security_engine = Datadog::AppSec.security_engine
60
-
61
- if security_engine
62
- ctx = Datadog::AppSec::Context.activate(
63
- Datadog::AppSec::Context.new(active_trace, active_span, security_engine.new_runner)
64
- )
65
-
66
- env[Datadog::AppSec::Ext::CONTEXT_KEY] = ctx
67
- ready = true
68
- end
69
- end
54
+ security_engine = Datadog::AppSec.security_engine
70
55
 
71
56
  # TODO: handle exceptions, except for @app.call
57
+ return @app.call(env) unless security_engine
72
58
 
73
- return @app.call(env) unless ready
59
+ ctx = Datadog::AppSec::Context.activate(
60
+ Datadog::AppSec::Context.new(active_trace, active_span, security_engine.new_runner)
61
+ )
62
+ env[Datadog::AppSec::Ext::CONTEXT_KEY] = ctx
74
63
 
75
- add_appsec_tags(security_engine, ctx)
64
+ add_appsec_tags(ctx)
76
65
  add_request_tags(ctx, env)
77
66
 
78
67
  http_response = nil
@@ -97,6 +86,7 @@ module Datadog
97
86
  end
98
87
 
99
88
  if interrupt_params
89
+ ctx.mark_as_interrupted!
100
90
  http_response = AppSec::Response.from_interrupt_params(interrupt_params, env['HTTP_ACCEPT']).to_rack
101
91
  end
102
92
 
@@ -128,6 +118,8 @@ module Datadog
128
118
  ensure
129
119
  if ctx
130
120
  ctx.export_metrics
121
+ ctx.export_request_telemetry
122
+
131
123
  Datadog::AppSec::Context.deactivate
132
124
  end
133
125
  end
@@ -156,7 +148,7 @@ module Datadog
156
148
  end
157
149
 
158
150
  # standard:disable Metrics/MethodLength
159
- def add_appsec_tags(security_engine, context)
151
+ def add_appsec_tags(context)
160
152
  span = context.span
161
153
  trace = context.trace
162
154
 
@@ -166,15 +158,15 @@ module Datadog
166
158
  span.set_tag('_dd.runtime_family', 'ruby')
167
159
  span.set_tag('_dd.appsec.waf.version', Datadog::AppSec::WAF::VERSION::BASE_STRING)
168
160
 
169
- if security_engine.ruleset_version
170
- span.set_tag('_dd.appsec.event_rules.version', security_engine.ruleset_version)
161
+ if context.waf_runner_ruleset_version
162
+ span.set_tag('_dd.appsec.event_rules.version', context.waf_runner_ruleset_version)
171
163
 
172
164
  unless @oneshot_tags_sent
173
165
  # Small race condition, but it's inoccuous: worst case the tags
174
166
  # are sent a couple of times more than expected
175
167
  @oneshot_tags_sent = true
176
168
 
177
- span.set_tag('_dd.appsec.event_rules.addresses', JSON.dump(security_engine.waf_addresses))
169
+ span.set_tag('_dd.appsec.event_rules.addresses', JSON.dump(context.waf_runner_known_addresses))
178
170
 
179
171
  # Ensure these tags reach the backend
180
172
  trace.keep!
@@ -16,6 +16,7 @@ module Datadog
16
16
  gateway = Instrumentation.gateway
17
17
 
18
18
  watch_request_action(gateway)
19
+ watch_response_body_json(gateway)
19
20
  end
20
21
 
21
22
  def watch_request_action(gateway = Instrumentation.gateway)
@@ -29,18 +30,38 @@ module Datadog
29
30
 
30
31
  result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
31
32
 
32
- if result.match? || !result.derivatives.empty?
33
+ if result.match?
33
34
  context.events.push(
34
35
  AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
35
36
  )
37
+
38
+ AppSec::Event.tag_and_keep!(context, result)
39
+ AppSec::ActionsHandler.handle(result.actions)
36
40
  end
37
41
 
42
+ stack.call(gateway_request.request)
43
+ end
44
+ end
45
+
46
+ def watch_response_body_json(gateway = Instrumentation.gateway)
47
+ gateway.watch('rails.response.body.json', :appsec) do |stack, container|
48
+ context = container.context
49
+
50
+ persistent_data = {
51
+ 'server.response.body' => container.data
52
+ }
53
+ result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
54
+
38
55
  if result.match?
56
+ context.events.push(
57
+ AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
58
+ )
59
+
39
60
  AppSec::Event.tag_and_keep!(context, result)
40
61
  AppSec::ActionsHandler.handle(result.actions)
41
62
  end
42
63
 
43
- stack.call(gateway_request.request)
64
+ stack.call(container)
44
65
  end
45
66
  end
46
67
  end
@@ -8,6 +8,8 @@ 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'
11
13
 
12
14
  require_relative '../../../tracing/contrib/rack/middlewares'
13
15
 
@@ -17,6 +19,7 @@ module Datadog
17
19
  module Rails
18
20
  # Patcher for AppSec on Rails
19
21
  module Patcher
22
+ GUARD_ACTION_CONTROLLER_ONCE_PER_APP = Hash.new { |h, key| h[key] = Datadog::Core::Utils::OnlyOnce.new }
20
23
  BEFORE_INITIALIZE_ONLY_ONCE_PER_APP = Hash.new { |h, key| h[key] = Datadog::Core::Utils::OnlyOnce.new }
21
24
  AFTER_INITIALIZE_ONLY_ONCE_PER_APP = Hash.new { |h, key| h[key] = Datadog::Core::Utils::OnlyOnce.new }
22
25
 
@@ -34,6 +37,7 @@ module Datadog
34
37
  Gateway::Watcher.watch
35
38
  patch_before_initialize
36
39
  patch_after_initialize
40
+ patch_action_controller
37
41
 
38
42
  Patcher.instance_variable_set(:@patched, true)
39
43
  end
@@ -49,7 +53,8 @@ module Datadog
49
53
  # Middleware must be added before the application is initialized.
50
54
  # Otherwise the middleware stack will be frozen.
51
55
  add_middleware(app) if Datadog.configuration.tracing[:rails][:middleware]
52
- patch_process_action
56
+
57
+ ::ActionController::Metal.prepend(Patches::ProcessActionPatch)
53
58
  end
54
59
  end
55
60
 
@@ -65,31 +70,6 @@ module Datadog
65
70
  end
66
71
  end
67
72
 
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
73
  def include_middleware?(middleware, app)
94
74
  found = false
95
75
 
@@ -143,6 +123,14 @@ module Datadog
143
123
  end
144
124
  end
145
125
 
126
+ def patch_action_controller
127
+ ::ActiveSupport.on_load(:action_controller) do
128
+ GUARD_ACTION_CONTROLLER_ONCE_PER_APP[self].run do
129
+ ::ActionController::Base.prepend(Patches::RenderToBodyPatch)
130
+ end
131
+ end
132
+ end
133
+
146
134
  def setup_security
147
135
  Datadog::AppSec::Contrib::Rails::Framework.setup
148
136
  end
@@ -0,0 +1,27 @@
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
+ # TODO: handle exceptions, except for super
15
+ gateway_request = Gateway::Request.new(request)
16
+ http_response, _gateway_request = Instrumentation.gateway.push('rails.request.action', gateway_request) do
17
+ super
18
+ end
19
+
20
+ http_response
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../utils/hash_coercion'
4
+ require_relative '../../../instrumentation/gateway/argument'
5
+
6
+ module Datadog
7
+ module AppSec
8
+ module Contrib
9
+ module Rails
10
+ module Patches
11
+ # A patch targeting `AbstractController::Rendering#render_to_body`
12
+ # method to capture JSON response body right before it is serialized.
13
+ module RenderToBodyPatch
14
+ def render_to_body(options = {})
15
+ return super unless options.key?(:json)
16
+
17
+ context = request.env[Datadog::AppSec::Ext::CONTEXT_KEY]
18
+ return super unless context
19
+
20
+ data = Utils::HashCoercion.coerce(options[:json])
21
+ return super unless data
22
+
23
+ container = Instrumentation::Gateway::DataContainer.new(data, context: context)
24
+ Instrumentation.gateway.push('rails.response.body.json', container)
25
+
26
+ super
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,4 +1,3 @@
1
- # rubocop:disable Naming/FileName
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require_relative '../../event'
@@ -17,6 +17,7 @@ module Datadog
17
17
 
18
18
  watch_request_dispatch(gateway)
19
19
  watch_request_routed(gateway)
20
+ watch_response_body_json(gateway)
20
21
  end
21
22
 
22
23
  def watch_request_dispatch(gateway = Instrumentation.gateway)
@@ -67,6 +68,28 @@ module Datadog
67
68
  stack.call(gateway_request.request)
68
69
  end
69
70
  end
71
+
72
+ def watch_response_body_json(gateway = Instrumentation.gateway)
73
+ gateway.watch('sinatra.response.body.json', :appsec) do |stack, container|
74
+ context = container.context
75
+
76
+ persistent_data = {
77
+ 'server.response.body' => container.data
78
+ }
79
+ result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
80
+
81
+ if result.match?
82
+ context.events.push(
83
+ AppSec::SecurityEvent.new(result, trace: context.trace, span: context.span)
84
+ )
85
+
86
+ AppSec::Event.tag_and_keep!(context, result)
87
+ AppSec::ActionsHandler.handle(result.actions)
88
+ end
89
+
90
+ stack.call(container)
91
+ end
92
+ end
70
93
  end
71
94
  end
72
95
  end