datadog 2.21.0 → 2.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (623) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +574 -1
  3. data/ext/LIBDATADOG_DEVELOPMENT.md +3 -0
  4. data/ext/datadog_profiling_native_extension/clock_id.h +9 -1
  5. data/ext/datadog_profiling_native_extension/clock_id_from_mach.c +66 -0
  6. data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +3 -2
  7. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +301 -82
  8. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +4 -4
  9. data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +3 -2
  10. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +18 -4
  11. data/ext/datadog_profiling_native_extension/collectors_stack.c +63 -32
  12. data/ext/datadog_profiling_native_extension/collectors_stack.h +7 -2
  13. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +728 -436
  14. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +19 -6
  15. data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +239 -0
  16. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +65 -1
  17. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +40 -1
  18. data/ext/datadog_profiling_native_extension/encoded_profile.c +2 -1
  19. data/ext/datadog_profiling_native_extension/extconf.rb +41 -37
  20. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +4 -43
  21. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +15 -47
  22. data/ext/datadog_profiling_native_extension/heap_recorder.c +252 -103
  23. data/ext/datadog_profiling_native_extension/heap_recorder.h +12 -1
  24. data/ext/datadog_profiling_native_extension/http_transport.c +66 -68
  25. data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +3 -22
  26. data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +0 -5
  27. data/ext/datadog_profiling_native_extension/macos_sampler_thread.h +55 -0
  28. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +0 -13
  29. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +40 -43
  30. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +6 -0
  31. data/ext/datadog_profiling_native_extension/profiling.c +65 -19
  32. data/ext/datadog_profiling_native_extension/ruby_helpers.c +63 -46
  33. data/ext/datadog_profiling_native_extension/ruby_helpers.h +17 -5
  34. data/ext/datadog_profiling_native_extension/setup_signal_handler.c +32 -10
  35. data/ext/datadog_profiling_native_extension/setup_signal_handler.h +2 -1
  36. data/ext/datadog_profiling_native_extension/stack_recorder.c +110 -85
  37. data/ext/datadog_profiling_native_extension/stack_recorder.h +3 -1
  38. data/ext/datadog_profiling_native_extension/time_helpers.h +13 -7
  39. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +2 -1
  40. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +9 -4
  41. data/ext/libdatadog_api/crashtracker.c +16 -15
  42. data/ext/libdatadog_api/crashtracker_report_exception.c +126 -0
  43. data/ext/libdatadog_api/datadog_ruby_common.c +65 -1
  44. data/ext/libdatadog_api/datadog_ruby_common.h +40 -1
  45. data/ext/libdatadog_api/ddsketch.c +102 -0
  46. data/ext/libdatadog_api/di.c +203 -0
  47. data/ext/libdatadog_api/extconf.rb +18 -24
  48. data/ext/libdatadog_api/feature_flags.c +554 -0
  49. data/ext/libdatadog_api/feature_flags.h +5 -0
  50. data/ext/libdatadog_api/helpers.h +27 -0
  51. data/ext/libdatadog_api/init.c +13 -1
  52. data/ext/libdatadog_api/library_config.c +34 -25
  53. data/ext/libdatadog_api/process_discovery.c +19 -13
  54. data/ext/libdatadog_extconf_helpers.rb +94 -11
  55. data/lib/datadog/ai_guard/api_client.rb +84 -0
  56. data/lib/datadog/ai_guard/autoload.rb +10 -0
  57. data/lib/datadog/ai_guard/component.rb +44 -0
  58. data/lib/datadog/ai_guard/configuration/ext.rb +17 -0
  59. data/lib/datadog/ai_guard/configuration.rb +115 -0
  60. data/lib/datadog/ai_guard/contrib/auto_instrument.rb +24 -0
  61. data/lib/datadog/ai_guard/contrib/integration.rb +37 -0
  62. data/lib/datadog/ai_guard/contrib/rack/integration.rb +42 -0
  63. data/lib/datadog/ai_guard/contrib/rack/patcher.rb +26 -0
  64. data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +97 -0
  65. data/lib/datadog/ai_guard/contrib/rails/integration.rb +41 -0
  66. data/lib/datadog/ai_guard/contrib/rails/patcher.rb +97 -0
  67. data/lib/datadog/ai_guard/contrib/ruby_llm/chat_instrumentation.rb +80 -0
  68. data/lib/datadog/ai_guard/contrib/ruby_llm/integration.rb +41 -0
  69. data/lib/datadog/ai_guard/contrib/ruby_llm/patcher.rb +30 -0
  70. data/lib/datadog/ai_guard/evaluation/content_builder.rb +31 -0
  71. data/lib/datadog/ai_guard/evaluation/content_part.rb +36 -0
  72. data/lib/datadog/ai_guard/evaluation/message.rb +25 -0
  73. data/lib/datadog/ai_guard/evaluation/no_op_result.rb +36 -0
  74. data/lib/datadog/ai_guard/evaluation/request.rb +86 -0
  75. data/lib/datadog/ai_guard/evaluation/result.rb +45 -0
  76. data/lib/datadog/ai_guard/evaluation/tool_call.rb +18 -0
  77. data/lib/datadog/ai_guard/evaluation.rb +108 -0
  78. data/lib/datadog/ai_guard/ext.rb +29 -0
  79. data/lib/datadog/ai_guard.rb +181 -0
  80. data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +26 -0
  81. data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +66 -0
  82. data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +36 -0
  83. data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +26 -0
  84. data/lib/datadog/appsec/api_security/endpoint_collection.rb +10 -0
  85. data/lib/datadog/appsec/api_security/route_extractor.rb +38 -9
  86. data/lib/datadog/appsec/api_security/sampler.rb +7 -4
  87. data/lib/datadog/appsec/assets/blocked.html +10 -1
  88. data/lib/datadog/appsec/assets/blocked.json +1 -1
  89. data/lib/datadog/appsec/assets/blocked.text +3 -1
  90. data/lib/datadog/appsec/assets/waf_rules/README.md +30 -36
  91. data/lib/datadog/appsec/assets/waf_rules/recommended.json +359 -4
  92. data/lib/datadog/appsec/assets/waf_rules/strict.json +43 -2
  93. data/lib/datadog/appsec/assets.rb +1 -1
  94. data/lib/datadog/appsec/autoload.rb +1 -1
  95. data/lib/datadog/appsec/component.rb +16 -9
  96. data/lib/datadog/appsec/compressed_json.rb +3 -3
  97. data/lib/datadog/appsec/configuration.rb +427 -1
  98. data/lib/datadog/appsec/context.rb +51 -13
  99. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +3 -1
  100. data/lib/datadog/appsec/contrib/active_record/integration.rb +1 -1
  101. data/lib/datadog/appsec/contrib/active_record/patcher.rb +4 -1
  102. data/lib/datadog/appsec/contrib/aws_lambda/gateway/watcher.rb +75 -0
  103. data/lib/datadog/appsec/contrib/aws_lambda/integration.rb +39 -0
  104. data/lib/datadog/appsec/contrib/aws_lambda/patcher.rb +30 -0
  105. data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +144 -0
  106. data/lib/datadog/appsec/contrib/devise/integration.rb +1 -1
  107. data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +2 -1
  108. data/lib/datadog/appsec/contrib/excon/integration.rb +1 -1
  109. data/lib/datadog/appsec/contrib/excon/patcher.rb +3 -1
  110. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +152 -12
  111. data/lib/datadog/appsec/contrib/faraday/integration.rb +1 -1
  112. data/lib/datadog/appsec/contrib/faraday/patcher.rb +1 -1
  113. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +138 -12
  114. data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +74 -24
  115. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +4 -2
  116. data/lib/datadog/appsec/contrib/graphql/integration.rb +2 -1
  117. data/lib/datadog/appsec/contrib/rack/buffered_input.rb +83 -0
  118. data/lib/datadog/appsec/contrib/rack/ext.rb +1 -1
  119. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +52 -13
  120. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +40 -19
  121. data/lib/datadog/appsec/contrib/rack/input_peeker.rb +79 -0
  122. data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
  123. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +48 -33
  124. data/lib/datadog/appsec/contrib/rack/response_body.rb +36 -0
  125. data/lib/datadog/appsec/contrib/rails/gateway/request.rb +40 -1
  126. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +26 -5
  127. data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
  128. data/lib/datadog/appsec/contrib/rails/patcher.rb +38 -0
  129. data/lib/datadog/appsec/contrib/rails/patches/process_action_patch.rb +2 -0
  130. data/lib/datadog/appsec/contrib/rest_client/integration.rb +1 -1
  131. data/lib/datadog/appsec/contrib/rest_client/patcher.rb +3 -1
  132. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +167 -11
  133. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +43 -13
  134. data/lib/datadog/appsec/contrib/sinatra/integration.rb +1 -1
  135. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +4 -4
  136. data/lib/datadog/appsec/contrib/sinatra/patches/json_patch.rb +1 -1
  137. data/lib/datadog/appsec/counter_sampler.rb +25 -0
  138. data/lib/datadog/appsec/default_header_tags.rb +52 -0
  139. data/lib/datadog/appsec/event.rb +13 -31
  140. data/lib/datadog/appsec/ext.rb +3 -0
  141. data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +2 -3
  142. data/lib/datadog/appsec/instrumentation/gateway.rb +2 -15
  143. data/lib/datadog/appsec/metrics/collector.rb +43 -5
  144. data/lib/datadog/appsec/metrics/exporter.rb +16 -3
  145. data/lib/datadog/appsec/metrics/telemetry.rb +20 -3
  146. data/lib/datadog/appsec/metrics/telemetry_exporter.rb +20 -1
  147. data/lib/datadog/appsec/metrics.rb +5 -5
  148. data/lib/datadog/appsec/monitor/gateway/watcher.rb +8 -6
  149. data/lib/datadog/appsec/remote.rb +44 -29
  150. data/lib/datadog/appsec/response.rb +18 -4
  151. data/lib/datadog/appsec/route_normalizer/rails_route_pattern.rb +176 -0
  152. data/lib/datadog/appsec/route_normalizer/route_pattern.rb +378 -0
  153. data/lib/datadog/appsec/route_normalizer/route_text.rb +57 -0
  154. data/lib/datadog/appsec/route_normalizer.rb +80 -0
  155. data/lib/datadog/appsec/security_engine/engine.rb +26 -5
  156. data/lib/datadog/appsec/security_engine/result.rb +29 -9
  157. data/lib/datadog/appsec/security_engine/runner.rb +20 -10
  158. data/lib/datadog/appsec/security_event.rb +5 -7
  159. data/lib/datadog/appsec/trace_keeper.rb +18 -6
  160. data/lib/datadog/appsec/utils/http/body.rb +38 -0
  161. data/lib/datadog/appsec/utils/http/body_reader.rb +61 -0
  162. data/lib/datadog/appsec/utils/http/media_range.rb +2 -1
  163. data/lib/datadog/appsec/utils/http/media_type.rb +32 -26
  164. data/lib/datadog/appsec/utils/http/url_encoded.rb +52 -0
  165. data/lib/datadog/appsec.rb +6 -3
  166. data/lib/datadog/core/configuration/agentless_settings_resolver.rb +2 -2
  167. data/lib/datadog/core/configuration/base.rb +17 -5
  168. data/lib/datadog/core/configuration/components.rb +185 -17
  169. data/lib/datadog/core/configuration/components_state.rb +6 -1
  170. data/lib/datadog/core/configuration/config_helper.rb +11 -2
  171. data/lib/datadog/core/configuration/deprecations.rb +2 -2
  172. data/lib/datadog/core/configuration/option.rb +32 -6
  173. data/lib/datadog/core/configuration/option_definition.rb +42 -14
  174. data/lib/datadog/core/configuration/options.rb +49 -12
  175. data/lib/datadog/core/configuration/settings.rb +115 -16
  176. data/lib/datadog/core/configuration/stable_config.rb +10 -0
  177. data/lib/datadog/core/configuration/supported_configurations.rb +379 -300
  178. data/lib/datadog/core/configuration.rb +3 -3
  179. data/lib/datadog/core/contrib/rails/railtie.rb +32 -0
  180. data/lib/datadog/core/contrib/rails/utils.rb +7 -3
  181. data/lib/datadog/core/crashtracking/component.rb +73 -21
  182. data/lib/datadog/core/crashtracking/tag_builder.rb +6 -0
  183. data/lib/datadog/core/ddsketch.rb +19 -0
  184. data/lib/datadog/core/diagnostics/environment_logger.rb +3 -1
  185. data/lib/datadog/core/environment/agent_info.rb +65 -1
  186. data/lib/datadog/core/environment/cgroup.rb +52 -25
  187. data/lib/datadog/core/environment/container.rb +140 -46
  188. data/lib/datadog/core/environment/ext.rb +13 -0
  189. data/lib/datadog/core/environment/identity.rb +40 -4
  190. data/lib/datadog/core/environment/process.rb +122 -0
  191. data/lib/datadog/core/environment/socket.rb +13 -0
  192. data/lib/datadog/core/environment/yjit.rb +2 -1
  193. data/lib/datadog/core/error.rb +6 -6
  194. data/lib/datadog/core/evp.rb +11 -0
  195. data/lib/datadog/core/feature_flags.rb +61 -0
  196. data/lib/datadog/core/knuth_sampler.rb +59 -0
  197. data/lib/datadog/core/logger.rb +1 -1
  198. data/lib/datadog/core/metrics/client.rb +6 -6
  199. data/lib/datadog/core/metrics/logging.rb +1 -1
  200. data/lib/datadog/core/pin.rb +8 -8
  201. data/lib/datadog/core/process_discovery.rb +21 -18
  202. data/lib/datadog/core/rate_limiter.rb +11 -1
  203. data/lib/datadog/core/remote/client/capabilities.rb +49 -6
  204. data/lib/datadog/core/remote/client.rb +15 -7
  205. data/lib/datadog/core/remote/component.rb +64 -36
  206. data/lib/datadog/core/remote/configuration/content.rb +15 -2
  207. data/lib/datadog/core/remote/configuration/digest.rb +14 -7
  208. data/lib/datadog/core/remote/configuration/repository.rb +1 -1
  209. data/lib/datadog/core/remote/configuration/target.rb +13 -6
  210. data/lib/datadog/core/remote/transport/config.rb +9 -36
  211. data/lib/datadog/core/remote/transport/http/config.rb +15 -55
  212. data/lib/datadog/core/remote/transport/http/negotiation.rb +14 -44
  213. data/lib/datadog/core/remote/transport/http.rb +15 -24
  214. data/lib/datadog/core/remote/transport/negotiation.rb +8 -33
  215. data/lib/datadog/core/remote/worker.rb +25 -37
  216. data/lib/datadog/core/runtime/metrics.rb +11 -2
  217. data/lib/datadog/core/semaphore.rb +1 -4
  218. data/lib/datadog/core/tag_builder.rb +0 -4
  219. data/lib/datadog/core/tag_normalizer.rb +84 -0
  220. data/lib/datadog/core/telemetry/component.rb +59 -15
  221. data/lib/datadog/core/telemetry/emitter.rb +6 -6
  222. data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +2 -3
  223. data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +30 -0
  224. data/lib/datadog/core/telemetry/event/app_extended_heartbeat.rb +32 -0
  225. data/lib/datadog/core/telemetry/event/app_started.rb +177 -171
  226. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +27 -4
  227. data/lib/datadog/core/telemetry/event.rb +2 -7
  228. data/lib/datadog/core/telemetry/ext.rb +1 -0
  229. data/lib/datadog/core/telemetry/logger.rb +4 -2
  230. data/lib/datadog/core/telemetry/logging.rb +17 -5
  231. data/lib/datadog/core/telemetry/metrics_manager.rb +9 -0
  232. data/lib/datadog/core/telemetry/request.rb +17 -5
  233. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +8 -34
  234. data/lib/datadog/core/telemetry/transport/http.rb +21 -16
  235. data/lib/datadog/core/telemetry/transport/telemetry.rb +8 -17
  236. data/lib/datadog/core/telemetry/worker.rb +108 -32
  237. data/lib/datadog/core/transport/ext.rb +3 -0
  238. data/lib/datadog/core/transport/http/api/endpoint.rb +9 -4
  239. data/lib/datadog/core/transport/http/api/instance.rb +4 -21
  240. data/lib/datadog/core/transport/http/builder.rb +10 -6
  241. data/lib/datadog/core/transport/http/client.rb +80 -0
  242. data/lib/datadog/core/transport/http/response.rb +4 -0
  243. data/lib/datadog/core/transport/http.rb +24 -19
  244. data/lib/datadog/core/transport/parcel.rb +61 -9
  245. data/lib/datadog/core/transport/response.rb +16 -2
  246. data/lib/datadog/core/transport/transport.rb +90 -0
  247. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +2 -2
  248. data/lib/datadog/core/utils/{base64.rb → base64_codec.rb} +4 -3
  249. data/lib/datadog/core/utils/enumerable_compat.rb +29 -0
  250. data/lib/datadog/core/utils/fnv.rb +26 -0
  251. data/lib/datadog/core/utils/forking.rb +3 -1
  252. data/lib/datadog/core/utils/hash.rb +0 -23
  253. data/lib/datadog/{appsec/api_security → core/utils}/lru_cache.rb +10 -21
  254. data/lib/datadog/core/utils/network.rb +22 -1
  255. data/lib/datadog/core/utils/only_once.rb +1 -1
  256. data/lib/datadog/core/utils/only_once_successful.rb +8 -2
  257. data/lib/datadog/core/utils/safe_dup.rb +2 -2
  258. data/lib/datadog/core/utils/sequence.rb +2 -0
  259. data/lib/datadog/core/utils/spawn_monkey_patch.rb +68 -0
  260. data/lib/datadog/core/utils/time.rb +6 -2
  261. data/lib/datadog/core/utils.rb +3 -1
  262. data/lib/datadog/core/workers/async.rb +11 -2
  263. data/lib/datadog/core/workers/interval_loop.rb +51 -3
  264. data/lib/datadog/core/workers/polling.rb +2 -0
  265. data/lib/datadog/core/workers/queue.rb +96 -1
  266. data/lib/datadog/core/workers/runtime_metrics.rb +9 -1
  267. data/lib/datadog/core.rb +10 -3
  268. data/lib/datadog/data_streams/configuration.rb +50 -0
  269. data/lib/datadog/data_streams/ext.rb +11 -0
  270. data/lib/datadog/data_streams/extensions.rb +16 -0
  271. data/lib/datadog/data_streams/pathway_context.rb +169 -0
  272. data/lib/datadog/data_streams/processor.rb +511 -0
  273. data/lib/datadog/data_streams/transport/http/stats.rb +58 -0
  274. data/lib/datadog/data_streams/transport/http.rb +36 -0
  275. data/lib/datadog/data_streams/transport/stats.rb +39 -0
  276. data/lib/datadog/data_streams.rb +100 -0
  277. data/lib/datadog/di/base.rb +15 -7
  278. data/lib/datadog/di/boot.rb +7 -2
  279. data/lib/datadog/di/capture_expression.rb +21 -0
  280. data/lib/datadog/di/capture_expression_evaluator.rb +71 -0
  281. data/lib/datadog/di/capture_limits.rb +41 -0
  282. data/lib/datadog/di/code_tracker.rb +217 -15
  283. data/lib/datadog/di/component.rb +139 -51
  284. data/lib/datadog/di/configuration.rb +241 -2
  285. data/lib/datadog/di/context.rb +82 -0
  286. data/lib/datadog/di/contrib/active_record.rb +34 -5
  287. data/lib/datadog/di/el/compiler.rb +168 -0
  288. data/lib/datadog/di/el/evaluator.rb +159 -0
  289. data/lib/datadog/di/el/expression.rb +42 -0
  290. data/lib/datadog/di/el.rb +5 -0
  291. data/lib/datadog/di/error.rb +44 -0
  292. data/lib/datadog/di/fatal_exceptions.rb +26 -0
  293. data/lib/datadog/di/instrumenter.rb +623 -147
  294. data/lib/datadog/di/logger.rb +2 -2
  295. data/lib/datadog/di/probe.rb +122 -14
  296. data/lib/datadog/di/probe_builder.rb +124 -3
  297. data/lib/datadog/di/probe_file_loader/railtie.rb +1 -1
  298. data/lib/datadog/di/probe_file_loader.rb +12 -7
  299. data/lib/datadog/di/probe_manager.rb +195 -100
  300. data/lib/datadog/di/probe_notification_builder.rb +321 -90
  301. data/lib/datadog/di/probe_notifier_worker.rb +112 -36
  302. data/lib/datadog/di/probe_repository.rb +198 -0
  303. data/lib/datadog/di/proc_responder.rb +36 -0
  304. data/lib/datadog/di/redactor.rb +24 -2
  305. data/lib/datadog/di/remote.rb +258 -93
  306. data/lib/datadog/di/serializer.rb +310 -29
  307. data/lib/datadog/di/transport/diagnostics.rb +12 -42
  308. data/lib/datadog/di/transport/http/diagnostics.rb +4 -34
  309. data/lib/datadog/di/transport/http/input.rb +2 -34
  310. data/lib/datadog/di/transport/http.rb +43 -19
  311. data/lib/datadog/di/transport/input.rb +112 -38
  312. data/lib/datadog/di/utils.rb +42 -14
  313. data/lib/datadog/di.rb +204 -4
  314. data/lib/datadog/error_tracking/collector.rb +2 -1
  315. data/lib/datadog/error_tracking/component.rb +2 -2
  316. data/lib/datadog/error_tracking/configuration.rb +55 -2
  317. data/lib/datadog/error_tracking/filters.rb +2 -2
  318. data/lib/datadog/kit/appsec/events/v2.rb +60 -3
  319. data/lib/datadog/kit/enable_core_dumps.rb +1 -1
  320. data/lib/datadog/kit/tracing/method_tracer.rb +135 -0
  321. data/lib/datadog/open_feature/component.rb +100 -0
  322. data/lib/datadog/open_feature/configuration.rb +37 -0
  323. data/lib/datadog/open_feature/evaluation_engine.rb +70 -0
  324. data/lib/datadog/open_feature/exposures/batch_builder.rb +32 -0
  325. data/lib/datadog/open_feature/exposures/buffer.rb +43 -0
  326. data/lib/datadog/open_feature/exposures/deduplicator.rb +30 -0
  327. data/lib/datadog/open_feature/exposures/event.rb +60 -0
  328. data/lib/datadog/open_feature/exposures/reporter.rb +40 -0
  329. data/lib/datadog/open_feature/exposures/worker.rb +116 -0
  330. data/lib/datadog/open_feature/ext.rb +16 -0
  331. data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +286 -0
  332. data/lib/datadog/open_feature/flag_evaluation/writer.rb +433 -0
  333. data/lib/datadog/open_feature/hooks/flag_eval_evp_hook.rb +101 -0
  334. data/lib/datadog/open_feature/hooks/flag_eval_metrics_hook.rb +49 -0
  335. data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +149 -0
  336. data/lib/datadog/open_feature/native_evaluator.rb +60 -0
  337. data/lib/datadog/open_feature/noop_evaluator.rb +26 -0
  338. data/lib/datadog/open_feature/provider.rb +191 -0
  339. data/lib/datadog/open_feature/remote.rb +67 -0
  340. data/lib/datadog/open_feature/resolution_details.rb +35 -0
  341. data/lib/datadog/open_feature/transport.rb +121 -0
  342. data/lib/datadog/open_feature.rb +19 -0
  343. data/lib/datadog/opentelemetry/api/baggage.rb +1 -1
  344. data/lib/datadog/opentelemetry/configuration/settings.rb +226 -0
  345. data/lib/datadog/opentelemetry/ext.rb +9 -0
  346. data/lib/datadog/opentelemetry/logs.rb +98 -0
  347. data/lib/datadog/opentelemetry/metrics.rb +90 -0
  348. data/lib/datadog/opentelemetry/sdk/configurator.rb +65 -1
  349. data/lib/datadog/opentelemetry/sdk/id_generator.rb +16 -10
  350. data/lib/datadog/opentelemetry/sdk/logs_exporter.rb +30 -0
  351. data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +28 -0
  352. data/lib/datadog/opentelemetry/sdk/propagator.rb +9 -3
  353. data/lib/datadog/opentelemetry/sdk/span_processor.rb +4 -1
  354. data/lib/datadog/opentelemetry/sdk.rb +19 -0
  355. data/lib/datadog/opentelemetry/signal_configuration.rb +53 -0
  356. data/lib/datadog/opentelemetry.rb +4 -0
  357. data/lib/datadog/profiling/collectors/code_provenance.rb +71 -12
  358. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +52 -4
  359. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +13 -5
  360. data/lib/datadog/profiling/collectors/info.rb +18 -4
  361. data/lib/datadog/profiling/collectors/thread_context.rb +10 -5
  362. data/lib/datadog/profiling/component.rb +82 -40
  363. data/lib/datadog/profiling/exporter.rb +41 -12
  364. data/lib/datadog/profiling/ext/dir_monkey_patches.rb +24 -5
  365. data/lib/datadog/profiling/ext/exec_monkey_patch.rb +32 -0
  366. data/lib/datadog/profiling/ext.rb +0 -2
  367. data/lib/datadog/profiling/flush.rb +23 -11
  368. data/lib/datadog/profiling/http_transport.rb +21 -8
  369. data/lib/datadog/profiling/load_native_extension.rb +2 -2
  370. data/lib/datadog/profiling/profiler.rb +31 -14
  371. data/lib/datadog/profiling/scheduler.rb +10 -9
  372. data/lib/datadog/profiling/stack_recorder.rb +0 -8
  373. data/lib/datadog/profiling/tag_builder.rb +37 -3
  374. data/lib/datadog/profiling/tasks/exec.rb +8 -3
  375. data/lib/datadog/profiling/tasks/help.rb +1 -0
  376. data/lib/datadog/profiling/tasks/setup.rb +2 -2
  377. data/lib/datadog/profiling.rb +1 -3
  378. data/lib/datadog/ruby_version.rb +25 -0
  379. data/lib/datadog/single_step_instrument.rb +2 -2
  380. data/lib/datadog/symbol_database/component.rb +734 -0
  381. data/lib/datadog/symbol_database/configuration.rb +73 -0
  382. data/lib/datadog/symbol_database/extensions.rb +19 -0
  383. data/lib/datadog/symbol_database/extractor.rb +1110 -0
  384. data/lib/datadog/symbol_database/file_hash.rb +48 -0
  385. data/lib/datadog/symbol_database/logger.rb +43 -0
  386. data/lib/datadog/symbol_database/remote.rb +180 -0
  387. data/lib/datadog/symbol_database/scope.rb +102 -0
  388. data/lib/datadog/symbol_database/scope_batcher.rb +292 -0
  389. data/lib/datadog/symbol_database/service_version.rb +66 -0
  390. data/lib/datadog/symbol_database/symbol.rb +69 -0
  391. data/lib/datadog/symbol_database/transport/http/endpoint.rb +28 -0
  392. data/lib/datadog/symbol_database/transport/http.rb +45 -0
  393. data/lib/datadog/symbol_database/transport.rb +54 -0
  394. data/lib/datadog/symbol_database/uploader.rb +230 -0
  395. data/lib/datadog/symbol_database.rb +71 -0
  396. data/lib/datadog/tracing/buffer.rb +3 -3
  397. data/lib/datadog/tracing/component.rb +17 -17
  398. data/lib/datadog/tracing/configuration/dynamic.rb +2 -2
  399. data/lib/datadog/tracing/configuration/ext.rb +22 -0
  400. data/lib/datadog/tracing/configuration/settings.rb +96 -4
  401. data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +4 -1
  402. data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +4 -1
  403. data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +4 -1
  404. data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +4 -1
  405. data/lib/datadog/tracing/contrib/action_mailer/event.rb +4 -1
  406. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +10 -7
  407. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +28 -0
  408. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +3 -1
  409. data/lib/datadog/tracing/contrib/action_pack/utils.rb +1 -2
  410. data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +4 -1
  411. data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +5 -2
  412. data/lib/datadog/tracing/contrib/active_job/data_streams.rb +62 -0
  413. data/lib/datadog/tracing/contrib/active_job/events/discard.rb +5 -2
  414. data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +5 -2
  415. data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +5 -2
  416. data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +5 -2
  417. data/lib/datadog/tracing/contrib/active_job/events/perform.rb +5 -2
  418. data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +5 -2
  419. data/lib/datadog/tracing/contrib/active_job/log_injection.rb +21 -7
  420. data/lib/datadog/tracing/contrib/active_job/patcher.rb +17 -1
  421. data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +1 -1
  422. data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +3 -4
  423. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +2 -2
  424. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +1 -1
  425. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +2 -5
  426. data/lib/datadog/tracing/contrib/active_record/utils.rb +1 -1
  427. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +2 -5
  428. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +1 -4
  429. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +2 -2
  430. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +6 -8
  431. data/lib/datadog/tracing/contrib/component.rb +3 -3
  432. data/lib/datadog/tracing/contrib/configurable.rb +18 -3
  433. data/lib/datadog/tracing/contrib/configuration/resolver.rb +14 -4
  434. data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +1 -5
  435. data/lib/datadog/tracing/contrib/dalli/integration.rb +4 -1
  436. data/lib/datadog/tracing/contrib/dalli/quantize.rb +1 -1
  437. data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +2 -0
  438. data/lib/datadog/tracing/contrib/delayed_job/server_internal_tracer/worker.rb +1 -0
  439. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +2 -6
  440. data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +2 -2
  441. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +5 -1
  442. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +5 -6
  443. data/lib/datadog/tracing/contrib/ethon/ext.rb +1 -0
  444. data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +1 -8
  445. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +16 -5
  446. data/lib/datadog/tracing/contrib/excon/ext.rb +1 -0
  447. data/lib/datadog/tracing/contrib/excon/middleware.rb +3 -7
  448. data/lib/datadog/tracing/contrib/ext.rb +3 -1
  449. data/lib/datadog/tracing/contrib/extensions.rb +19 -2
  450. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +16 -9
  451. data/lib/datadog/tracing/contrib/faraday/ext.rb +1 -0
  452. data/lib/datadog/tracing/contrib/faraday/middleware.rb +3 -7
  453. data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +7 -3
  454. data/lib/datadog/tracing/contrib/grape/endpoint.rb +10 -7
  455. data/lib/datadog/tracing/contrib/grape/instrumentation.rb +13 -8
  456. data/lib/datadog/tracing/contrib/grape/patcher.rb +6 -1
  457. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +7 -0
  458. data/lib/datadog/tracing/contrib/graphql/ext.rb +1 -0
  459. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +75 -44
  460. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +5 -2
  461. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +3 -7
  462. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +3 -7
  463. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +2 -0
  464. data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
  465. data/lib/datadog/tracing/contrib/grpc.rb +1 -0
  466. data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +1 -0
  467. data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +1 -0
  468. data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +1 -0
  469. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +16 -5
  470. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +2 -0
  471. data/lib/datadog/tracing/contrib/http/ext.rb +1 -0
  472. data/lib/datadog/tracing/contrib/http/instrumentation.rb +4 -8
  473. data/lib/datadog/tracing/contrib/http/integration.rb +0 -2
  474. data/lib/datadog/tracing/contrib/http.rb +1 -0
  475. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +16 -5
  476. data/lib/datadog/tracing/contrib/httpclient/ext.rb +1 -0
  477. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +7 -7
  478. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +16 -5
  479. data/lib/datadog/tracing/contrib/httprb/ext.rb +1 -0
  480. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +4 -8
  481. data/lib/datadog/tracing/contrib/kafka/event.rb +1 -0
  482. data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +66 -0
  483. data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +66 -0
  484. data/lib/datadog/tracing/contrib/kafka/patcher.rb +14 -0
  485. data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +5 -1
  486. data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +2 -0
  487. data/lib/datadog/tracing/contrib/karafka/ext.rb +1 -0
  488. data/lib/datadog/tracing/contrib/karafka/framework.rb +30 -0
  489. data/lib/datadog/tracing/contrib/karafka/monitor.rb +11 -0
  490. data/lib/datadog/tracing/contrib/karafka/patcher.rb +35 -4
  491. data/lib/datadog/tracing/contrib/karafka.rb +1 -0
  492. data/lib/datadog/tracing/contrib/mongodb/parsers.rb +5 -5
  493. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +5 -8
  494. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +6 -0
  495. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +3 -6
  496. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +2 -6
  497. data/lib/datadog/tracing/contrib/opensearch/quantize.rb +2 -2
  498. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +6 -0
  499. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +15 -18
  500. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +6 -8
  501. data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +13 -0
  502. data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +6 -2
  503. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +24 -0
  504. data/lib/datadog/tracing/contrib/que/configuration/settings.rb +5 -2
  505. data/lib/datadog/tracing/contrib/que/ext.rb +1 -0
  506. data/lib/datadog/tracing/contrib/que/tracer.rb +1 -0
  507. data/lib/datadog/tracing/contrib/racecar/event.rb +1 -5
  508. data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +11 -1
  509. data/lib/datadog/tracing/contrib/rack/ext.rb +28 -0
  510. data/lib/datadog/tracing/contrib/rack/header_tagging.rb +23 -0
  511. data/lib/datadog/tracing/contrib/rack/middlewares.rb +62 -27
  512. data/lib/datadog/tracing/contrib/rack/patcher.rb +2 -2
  513. data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
  514. data/lib/datadog/tracing/contrib/rack/route_inference.rb +67 -0
  515. data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +119 -1
  516. data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +5 -2
  517. data/lib/datadog/tracing/contrib/rails/ext.rb +1 -0
  518. data/lib/datadog/tracing/contrib/rails/log_injection.rb +1 -1
  519. data/lib/datadog/tracing/contrib/rails/middlewares.rb +2 -2
  520. data/lib/datadog/tracing/contrib/rails/patcher.rb +0 -1
  521. data/lib/datadog/tracing/contrib/rails/runner.rb +3 -1
  522. data/lib/datadog/tracing/contrib/rake/instrumentation.rb +6 -4
  523. data/lib/datadog/tracing/contrib/redis/quantize.rb +1 -1
  524. data/lib/datadog/tracing/contrib/redis/tags.rb +1 -6
  525. data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +2 -0
  526. data/lib/datadog/tracing/contrib/registerable.rb +11 -0
  527. data/lib/datadog/tracing/contrib/resque/resque_job.rb +1 -0
  528. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +5 -2
  529. data/lib/datadog/tracing/contrib/rest_client/ext.rb +1 -0
  530. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +5 -6
  531. data/lib/datadog/tracing/contrib/roda/ext.rb +1 -0
  532. data/lib/datadog/tracing/contrib/roda/instrumentation.rb +7 -2
  533. data/lib/datadog/tracing/contrib/sequel/database.rb +1 -0
  534. data/lib/datadog/tracing/contrib/sequel/dataset.rb +1 -0
  535. data/lib/datadog/tracing/contrib/sequel/utils.rb +2 -7
  536. data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +1 -0
  537. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +1 -0
  538. data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +5 -1
  539. data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +2 -0
  540. data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
  541. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/heartbeat.rb +2 -0
  542. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/job_fetch.rb +1 -0
  543. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/redis_info.rb +1 -0
  544. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/scheduled_poller.rb +2 -0
  545. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/stop.rb +1 -0
  546. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +3 -2
  547. data/lib/datadog/tracing/contrib/sidekiq/utils.rb +1 -1
  548. data/lib/datadog/tracing/contrib/sidekiq.rb +1 -0
  549. data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +5 -1
  550. data/lib/datadog/tracing/contrib/sinatra/ext.rb +1 -0
  551. data/lib/datadog/tracing/contrib/sinatra/framework.rb +1 -1
  552. data/lib/datadog/tracing/contrib/sinatra/tracer.rb +1 -0
  553. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +4 -1
  554. data/lib/datadog/tracing/contrib/sneakers/integration.rb +15 -4
  555. data/lib/datadog/tracing/contrib/sneakers/tracer.rb +1 -0
  556. data/lib/datadog/tracing/contrib/status_range_matcher.rb +13 -1
  557. data/lib/datadog/tracing/contrib/stripe/request.rb +1 -1
  558. data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +1 -0
  559. data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +6 -0
  560. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +4 -6
  561. data/lib/datadog/tracing/contrib/utils/quantization/{hash.rb → hash_formatter.rb} +4 -2
  562. data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +31 -0
  563. data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +50 -0
  564. data/lib/datadog/tracing/contrib/waterdrop/ext.rb +18 -0
  565. data/lib/datadog/tracing/contrib/waterdrop/integration.rb +43 -0
  566. data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +46 -0
  567. data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +49 -0
  568. data/lib/datadog/tracing/contrib/waterdrop/producer.rb +50 -0
  569. data/lib/datadog/tracing/contrib/waterdrop.rb +42 -0
  570. data/lib/datadog/tracing/contrib.rb +9 -0
  571. data/lib/datadog/tracing/diagnostics/environment_logger.rb +4 -2
  572. data/lib/datadog/tracing/distributed/baggage.rb +64 -8
  573. data/lib/datadog/tracing/distributed/datadog.rb +13 -11
  574. data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +1 -14
  575. data/lib/datadog/tracing/distributed/propagation.rb +35 -3
  576. data/lib/datadog/tracing/distributed/trace_context.rb +85 -62
  577. data/lib/datadog/tracing/event.rb +1 -1
  578. data/lib/datadog/tracing/ext.rb +9 -0
  579. data/lib/datadog/tracing/metadata/ext.rb +23 -1
  580. data/lib/datadog/tracing/metadata/tagging.rb +2 -2
  581. data/lib/datadog/tracing/pipeline.rb +1 -1
  582. data/lib/datadog/tracing/remote.rb +36 -13
  583. data/lib/datadog/tracing/sampling/ext.rb +2 -0
  584. data/lib/datadog/tracing/sampling/priority_sampler.rb +16 -1
  585. data/lib/datadog/tracing/sampling/rate_sampler.rb +8 -19
  586. data/lib/datadog/tracing/sampling/rule.rb +1 -1
  587. data/lib/datadog/tracing/sampling/rule_sampler.rb +54 -25
  588. data/lib/datadog/tracing/sampling/span/rule_parser.rb +2 -2
  589. data/lib/datadog/tracing/span.rb +1 -1
  590. data/lib/datadog/tracing/span_event.rb +2 -2
  591. data/lib/datadog/tracing/span_operation.rb +34 -10
  592. data/lib/datadog/tracing/sync_writer.rb +0 -1
  593. data/lib/datadog/tracing/trace_digest.rb +7 -0
  594. data/lib/datadog/tracing/trace_operation.rb +123 -16
  595. data/lib/datadog/tracing/tracer.rb +82 -23
  596. data/lib/datadog/tracing/transport/http/client.rb +12 -26
  597. data/lib/datadog/tracing/transport/http/traces.rb +2 -50
  598. data/lib/datadog/tracing/transport/http.rb +15 -9
  599. data/lib/datadog/tracing/transport/io/client.rb +6 -9
  600. data/lib/datadog/tracing/transport/io/traces.rb +28 -34
  601. data/lib/datadog/tracing/transport/trace_formatter.rb +22 -0
  602. data/lib/datadog/tracing/transport/traces.rb +13 -81
  603. data/lib/datadog/tracing/workers.rb +2 -1
  604. data/lib/datadog/tracing/writer.rb +1 -1
  605. data/lib/datadog/version.rb +2 -2
  606. data/lib/datadog.rb +8 -1
  607. metadata +185 -36
  608. data/ext/datadog_profiling_native_extension/clock_id_noop.c +0 -21
  609. data/ext/libdatadog_api/macos_development.md +0 -26
  610. data/lib/datadog/appsec/configuration/settings.rb +0 -400
  611. data/lib/datadog/appsec/contrib/rails/ext.rb +0 -13
  612. data/lib/datadog/core/remote/transport/http/api.rb +0 -53
  613. data/lib/datadog/core/remote/transport/http/client.rb +0 -49
  614. data/lib/datadog/core/telemetry/transport/http/api.rb +0 -43
  615. data/lib/datadog/core/telemetry/transport/http/client.rb +0 -49
  616. data/lib/datadog/core/transport/http/api/spec.rb +0 -36
  617. data/lib/datadog/di/configuration/settings.rb +0 -212
  618. data/lib/datadog/di/transport/http/api.rb +0 -42
  619. data/lib/datadog/di/transport/http/client.rb +0 -47
  620. data/lib/datadog/error_tracking/configuration/settings.rb +0 -63
  621. data/lib/datadog/opentelemetry/api/baggage.rbs +0 -26
  622. data/lib/datadog/tracing/transport/http/api.rb +0 -44
  623. data/lib/datadog/tracing/workers/trace_writer.rb +0 -199
@@ -2,10 +2,13 @@
2
2
  #include <datadog/crashtracker.h>
3
3
 
4
4
  #include "datadog_ruby_common.h"
5
+ #include "helpers.h"
5
6
 
6
7
  static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self);
7
8
  static VALUE _native_stop(DDTRACE_UNUSED VALUE _self);
8
9
 
10
+ void crashtracker_report_exception_init(VALUE crashtracker_class);
11
+
9
12
  static bool first_init = true;
10
13
 
11
14
  // Used to report Ruby VM crashes.
@@ -17,6 +20,9 @@ void crashtracker_init(VALUE core_module) {
17
20
 
18
21
  rb_define_singleton_method(crashtracker_class, "_native_start_or_update_on_fork", _native_start_or_update_on_fork, -1);
19
22
  rb_define_singleton_method(crashtracker_class, "_native_stop", _native_stop, 0);
23
+
24
+ // Initialize Ruby non-signal-crash reporting
25
+ crashtracker_report_exception_init(crashtracker_class);
20
26
  }
21
27
 
22
28
  static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self) {
@@ -41,16 +47,12 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
41
47
  ENFORCE_TYPE(action, T_SYMBOL);
42
48
  ENFORCE_TYPE(upload_timeout_seconds, T_FIXNUM);
43
49
 
44
- if (action != start_action && action != update_on_fork_action) rb_raise(rb_eArgError, "Unexpected action: %+"PRIsVALUE, action);
50
+ if (action != start_action && action != update_on_fork_action) raise_error(rb_eArgError, "Unexpected action: %+"PRIsVALUE, action);
45
51
 
46
52
  VALUE version = datadog_gem_version();
47
53
 
48
- // Tags and endpoint are heap-allocated, so after here we can't raise exceptions otherwise we'll leak this memory
54
+ // Tags are heap-allocated, so after here we can't raise exceptions otherwise we'll leak this memory
49
55
  // Start of exception-free zone to prevent leaks {{
50
- ddog_Endpoint *endpoint = ddog_endpoint_from_url(char_slice_from_ruby_string(agent_base_url));
51
- if (endpoint == NULL) {
52
- rb_raise(rb_eRuntimeError, "Failed to create endpoint from agent_base_url: %"PRIsVALUE, agent_base_url);
53
- }
54
56
  ddog_Vec_Tag tags = convert_tags(tags_as_array);
55
57
 
56
58
  ddog_crasht_Config config = {
@@ -67,9 +69,11 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
67
69
  // overriding what Ruby set up seems a saner default to keep anyway.
68
70
  .create_alt_stack = false,
69
71
  .use_alt_stack = true,
70
- .endpoint = endpoint,
72
+ .endpoint = {.url = char_slice_from_ruby_string(agent_base_url)},
71
73
  .resolve_frames = DDOG_CRASHT_STACKTRACE_COLLECTION_ENABLED_WITH_SYMBOLS_IN_RECEIVER,
72
74
  .timeout_ms = FIX2INT(upload_timeout_seconds) * 1000,
75
+ .collect_all_threads = true,
76
+ .max_threads = 128,
73
77
  };
74
78
 
75
79
  ddog_crasht_Metadata metadata = {
@@ -100,16 +104,15 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
100
104
  ) :
101
105
  ddog_crasht_update_on_fork(config, receiver_config, metadata);
102
106
 
103
- first_init = false;
107
+ // We use first_init to know which of [init, reconfigure] needs to be called. BUT if init failed we actually need
108
+ // to call init next time again, not reconfigure.
109
+ if (result.tag == DDOG_VOID_RESULT_OK) first_init = false;
104
110
 
105
111
  // Clean up before potentially raising any exceptions
106
112
  ddog_Vec_Tag_drop(tags);
107
- ddog_endpoint_drop(endpoint);
108
113
  // }} End of exception-free zone to prevent leaks
109
114
 
110
- if (result.tag == DDOG_VOID_RESULT_ERR) {
111
- rb_raise(rb_eRuntimeError, "Failed to start/update the crash tracker: %"PRIsVALUE, get_error_details_and_drop(&result.err));
112
- }
115
+ CHECK_VOID_RESULT("Failed to start/update the crash tracker", result);
113
116
 
114
117
  return Qtrue;
115
118
  }
@@ -117,9 +120,7 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
117
120
  static VALUE _native_stop(DDTRACE_UNUSED VALUE _self) {
118
121
  ddog_VoidResult result = ddog_crasht_disable();
119
122
 
120
- if (result.tag == DDOG_VOID_RESULT_ERR) {
121
- rb_raise(rb_eRuntimeError, "Failed to stop the crash tracker: %"PRIsVALUE, get_error_details_and_drop(&result.err));
122
- }
123
+ CHECK_VOID_RESULT("Failed to stop the crash tracker", result);
123
124
 
124
125
  return Qtrue;
125
126
  }
@@ -0,0 +1,126 @@
1
+ #include <datadog/common.h>
2
+ #include <datadog/crashtracker.h>
3
+ #include <ruby.h>
4
+
5
+ #include "datadog_ruby_common.h"
6
+
7
+ static VALUE _native_report_ruby_exception(VALUE _self, VALUE exception_type,
8
+ VALUE message, VALUE frames_data);
9
+
10
+ static bool process_crash_frames(VALUE frames_data, ddog_crasht_Handle_StackTrace *stack_trace);
11
+
12
+ void crashtracker_report_exception_init(VALUE crashtracker_class) {
13
+ rb_define_singleton_method(crashtracker_class, "_native_report_ruby_exception",
14
+ _native_report_ruby_exception, 3);
15
+ }
16
+
17
+ static VALUE _native_report_ruby_exception(DDTRACE_UNUSED VALUE _self, VALUE exception_type,
18
+ VALUE message, VALUE frames_data) {
19
+ ENFORCE_TYPE(exception_type, T_STRING);
20
+ ENFORCE_TYPE(message, T_STRING);
21
+ ENFORCE_TYPE(frames_data, T_ARRAY);
22
+
23
+ // Build stack trace
24
+ ddog_crasht_StackTrace_NewResult stack_result = ddog_crasht_StackTrace_new();
25
+ if (stack_result.tag != DDOG_CRASHT_STACK_TRACE_NEW_RESULT_OK) {
26
+ ddog_Error_drop(&stack_result.err);
27
+ return Qfalse;
28
+ }
29
+
30
+ ddog_crasht_Handle_StackTrace *stack_trace = &stack_result.ok;
31
+
32
+ bool frames_ok = process_crash_frames(frames_data, stack_trace);
33
+ if (frames_ok) {
34
+ ddog_VoidResult complete_result = ddog_crasht_StackTrace_set_complete(stack_trace);
35
+ if (complete_result.tag != DDOG_VOID_RESULT_OK) {
36
+ ddog_crasht_StackTrace_drop(stack_trace);
37
+ ddog_Error_drop(&complete_result.err);
38
+ return Qfalse;
39
+ }
40
+ }
41
+
42
+ // ddog_crasht_report_unhandled_exception takes ownership of stack_trace
43
+ ddog_VoidResult result = ddog_crasht_report_unhandled_exception(
44
+ char_slice_from_ruby_string(exception_type),
45
+ char_slice_from_ruby_string(message),
46
+ stack_trace
47
+ );
48
+
49
+ if (result.tag != DDOG_VOID_RESULT_OK) {
50
+ ddog_Error_drop(&result.err);
51
+ return Qfalse;
52
+ }
53
+
54
+ return Qtrue;
55
+ }
56
+
57
+ static bool process_crash_frames(VALUE frames_data, ddog_crasht_Handle_StackTrace *stack_trace) {
58
+ size_t frame_count = RARRAY_LEN(frames_data);
59
+
60
+ // Return false and early so we can mark the stack as incomplete
61
+ // libdatadog's definition of an incomplete stack is that it has no frames
62
+ // or that report generation died in the middle of unwinding frames
63
+ if (frame_count == 0) {
64
+ return false;
65
+ }
66
+
67
+ for (size_t i = 0; i < frame_count; i++) {
68
+ VALUE frame_array = RARRAY_AREF(frames_data, i);
69
+
70
+ // ruby should guarantee [String, String, Integer]
71
+ if (!RB_TYPE_P(frame_array, T_ARRAY) || RARRAY_LEN(frame_array) != 3) {
72
+ // Malformed data from Ruby; this is a bug, bail out
73
+ return false;
74
+ }
75
+
76
+ VALUE file_val = RARRAY_AREF(frame_array, 0);
77
+ VALUE func_val = RARRAY_AREF(frame_array, 1);
78
+ VALUE line_val = RARRAY_AREF(frame_array, 2);
79
+
80
+ // validate types; Ruby should guarantee these
81
+ if (!RB_TYPE_P(file_val, T_STRING) || !RB_TYPE_P(func_val, T_STRING) || !RB_TYPE_P(line_val, T_FIXNUM)) {
82
+ // Type mismatch from Ruby; this is a bug, bail out
83
+ return false;
84
+ }
85
+
86
+ ddog_crasht_StackFrame_NewResult frame_result = ddog_crasht_StackFrame_new();
87
+ if (frame_result.tag != DDOG_CRASHT_STACK_FRAME_NEW_RESULT_OK) {
88
+ ddog_Error_drop(&frame_result.err);
89
+ return false;
90
+ }
91
+
92
+ ddog_crasht_Handle_StackFrame *frame = &frame_result.ok;
93
+
94
+ ddog_VoidResult file_result = ddog_crasht_StackFrame_with_file(frame, char_slice_from_ruby_string(file_val));
95
+ if (file_result.tag != DDOG_VOID_RESULT_OK) {
96
+ ddog_crasht_StackFrame_drop(frame);
97
+ ddog_Error_drop(&file_result.err);
98
+ return false;
99
+ }
100
+ ddog_VoidResult func_result = ddog_crasht_StackFrame_with_function(frame, char_slice_from_ruby_string(func_val));
101
+ if (func_result.tag != DDOG_VOID_RESULT_OK) {
102
+ ddog_crasht_StackFrame_drop(frame);
103
+ ddog_Error_drop(&func_result.err);
104
+ return false;
105
+ }
106
+
107
+ uint32_t line = (uint32_t)FIX2INT(line_val);
108
+ if (line > 0) {
109
+ ddog_VoidResult line_result = ddog_crasht_StackFrame_with_line(frame, line);
110
+ if (line_result.tag != DDOG_VOID_RESULT_OK) {
111
+ ddog_crasht_StackFrame_drop(frame);
112
+ ddog_Error_drop(&line_result.err);
113
+ return false;
114
+ }
115
+ }
116
+
117
+ ddog_VoidResult push_result = ddog_crasht_StackTrace_push_frame(stack_trace, frame, true);
118
+ if (push_result.tag != DDOG_VOID_RESULT_OK) {
119
+ ddog_crasht_StackFrame_drop(frame);
120
+ ddog_Error_drop(&push_result.err);
121
+ return false;
122
+ }
123
+ }
124
+
125
+ return true;
126
+ }
@@ -1,8 +1,11 @@
1
1
  #include "datadog_ruby_common.h"
2
+ #include <stdarg.h>
2
3
 
3
4
  // IMPORTANT: Currently this file is copy-pasted between extensions. Make sure to update all versions when doing any change!
4
5
 
5
- void raise_unexpected_type(VALUE value, const char *value_name, const char *type_name, const char *file, int line, const char* function_name) {
6
+ static ID telemetry_message_id;
7
+
8
+ void raise_unexpected_type(VALUE value, const char *value_name, const char *type_name, const char *file, int line, const char *function_name) {
6
9
  rb_exc_raise(
7
10
  rb_exc_new_str(
8
11
  rb_eTypeError,
@@ -18,6 +21,25 @@ void raise_unexpected_type(VALUE value, const char *value_name, const char *type
18
21
  );
19
22
  }
20
23
 
24
+ // Raises an exception with separate telemetry-safe and detailed messages.
25
+ // NOTE: Raising an exception always invokes Ruby code so it requires the GVL and is not compatible with "debug_enter_unsafe_context".
26
+ // @see debug_enter_unsafe_context
27
+ void private_raise_exception(VALUE exception, const char *static_message) {
28
+ rb_ivar_set(exception, telemetry_message_id, rb_str_new_cstr(static_message));
29
+ rb_exc_raise(exception);
30
+ }
31
+
32
+ // Use `raise_error` the macro instead, as it provides additional argument checks.
33
+ void private_raise_error(VALUE exception_class, const char *fmt, ...) {
34
+ va_list args;
35
+ va_start(args, fmt);
36
+ VALUE detailed_message = rb_vsprintf(fmt, args);
37
+ va_end(args);
38
+
39
+ VALUE exception = rb_exc_new_str(exception_class, detailed_message);
40
+ private_raise_exception(exception, fmt);
41
+ }
42
+
21
43
  VALUE datadog_gem_version(void) {
22
44
  VALUE ddtrace_module = rb_const_get(rb_cObject, rb_intern("Datadog"));
23
45
  ENFORCE_TYPE(ddtrace_module, T_MODULE);
@@ -78,3 +100,45 @@ ddog_Vec_Tag convert_tags(VALUE tags_as_array) {
78
100
 
79
101
  return tags;
80
102
  }
103
+
104
+ size_t read_ddogerr_string_and_drop(ddog_Error *error, char *string, size_t capacity) {
105
+ if (capacity == 0 || string == NULL) {
106
+ // short-circuit, we can't write anything
107
+ ddog_Error_drop(error);
108
+ return 0;
109
+ }
110
+
111
+ ddog_CharSlice error_msg_slice = ddog_Error_message(error);
112
+ size_t error_msg_size = error_msg_slice.len;
113
+ // Account for extra null char for proper cstring
114
+ if (error_msg_size >= capacity) {
115
+ // Error message too big, lets truncate it to capacity - 1 to allow for extra null at end
116
+ error_msg_size = capacity - 1;
117
+ }
118
+ strncpy(string, error_msg_slice.ptr, error_msg_size);
119
+ string[error_msg_size] = '\0';
120
+ ddog_Error_drop(error);
121
+ return error_msg_size;
122
+ }
123
+
124
+ static void verify_libdatadog_version(void) {
125
+ rb_eval_string(
126
+ "require 'libdatadog';"
127
+ "expected = '" EXPECTED_LIBDATADOG_VERSION "';"
128
+ "if expected != Libdatadog::VERSION;"
129
+ "raise(LoadError, <<MSG\n"
130
+ "The `datadog` gem needs to be reinstalled whenever the `libdatadog` gem version is changed. "
131
+ "The currently-installed version of `datadog` was built to work with `libdatadog` gem version #{expected} "
132
+ "but the currently-loaded version of `libdatadog` is #{Libdatadog::VERSION}. "
133
+ "To fix this, reinstall the `datadog` gem (e.g. `bundle exec gem pristine datadog`) "
134
+ "or contact Datadog support for help at <https://docs.datadoghq.com/help/>.\n"
135
+ "MSG\n"
136
+ ");"
137
+ "end"
138
+ );
139
+ }
140
+
141
+ void datadog_ruby_common_init(void) {
142
+ telemetry_message_id = rb_intern("@telemetry_message");
143
+ verify_libdatadog_version();
144
+ }
@@ -3,7 +3,10 @@
3
3
  // IMPORTANT: Currently this file is copy-pasted between extensions. Make sure to update all versions when doing any change!
4
4
 
5
5
  #include <ruby.h>
6
- #include <datadog/profiling.h>
6
+ #include <datadog/common.h>
7
+
8
+ // Must be called once during initialization
9
+ void datadog_ruby_common_init(void);
7
10
 
8
11
  // Used to mark symbols to be exported to the outside of the extension.
9
12
  // Consider very carefully before tagging a function with this.
@@ -32,6 +35,27 @@
32
35
 
33
36
  NORETURN(void raise_unexpected_type(VALUE value, const char *value_name, const char *type_name, const char *file, int line, const char* function_name));
34
37
 
38
+ // Raises an exception of the specified class with the formatted string as its message.
39
+ // This macro ensures that the literal string is sent for telemetry, while the formatted
40
+ // message is the default `Exception#message`.
41
+ // *Ruby exceptions not raised through this function will not be reported via telemetry.*
42
+ #define raise_error(exception_class, fmt, ...) \
43
+ private_raise_error(exception_class, "" fmt, ##__VA_ARGS__)
44
+
45
+ NORETURN(
46
+ void private_raise_error(VALUE exception_class, const char *fmt, ...)
47
+ __attribute__ ((format (printf, 2, 3)));
48
+ );
49
+
50
+ // Raises an exception with separate telemetry-safe and detailed messages.
51
+ // NOTE: Raising an exception always invokes Ruby code so it requires the GVL and is not compatible with "debug_enter_unsafe_context".
52
+ // @see debug_enter_unsafe_context
53
+ NORETURN(
54
+ void private_raise_exception(VALUE exception, const char *static_message)
55
+ );
56
+
57
+ #define MAX_RAISE_MESSAGE_SIZE 256
58
+
35
59
  // Helper to retrieve Datadog::VERSION::STRING
36
60
  VALUE datadog_gem_version(void);
37
61
 
@@ -61,3 +85,18 @@ static inline VALUE get_error_details_and_drop(ddog_Error *error) {
61
85
  ddog_Error_drop(error);
62
86
  return result;
63
87
  }
88
+
89
+ // Utility function to be able to extract an error cstring from a ddog_Error.
90
+ // Returns the amount of characters written to string (which are necessarily
91
+ // bounded by capacity - 1 since the string will be null-terminated).
92
+ size_t read_ddogerr_string_and_drop(ddog_Error *error, char *string, size_t capacity);
93
+
94
+ #define IMEMO_MASK 0x0f
95
+
96
+ // Returns the imemo type of an imemo object.
97
+ // This mask is the same between Ruby 2.5 and 3.3-preview3. Furthermore, the intention of this method is to be used
98
+ // to call `rb_imemo_name` which correctly handles invalid numbers so even if the mask changes in the future, at most
99
+ // we'll get incorrect results (and never a VM crash)
100
+ static inline int ddtrace_imemo_type(VALUE imemo) {
101
+ return (RBASIC(imemo)->flags >> FL_USHIFT) & IMEMO_MASK;
102
+ }
@@ -0,0 +1,102 @@
1
+ #include <ruby.h>
2
+ #include <datadog/ddsketch.h>
3
+
4
+ #include "datadog_ruby_common.h"
5
+ #include "helpers.h"
6
+
7
+ static VALUE _native_new(VALUE klass);
8
+ static void ddsketch_free(void *ptr);
9
+ static VALUE native_add(VALUE self, VALUE point);
10
+ static VALUE native_add_with_count(VALUE self, VALUE point, VALUE count);
11
+ static VALUE native_count(VALUE self);
12
+ static VALUE native_encode(VALUE self);
13
+
14
+ void ddsketch_init(VALUE core_module) {
15
+ VALUE ddsketch_class = rb_define_class_under(core_module, "DDSketch", rb_cObject);
16
+
17
+ rb_define_alloc_func(ddsketch_class, _native_new);
18
+ rb_define_method(ddsketch_class, "add", native_add, 1);
19
+ rb_define_method(ddsketch_class, "add_with_count", native_add_with_count, 2);
20
+ rb_define_method(ddsketch_class, "count", native_count, 0);
21
+ rb_define_method(ddsketch_class, "encode", native_encode, 0);
22
+ }
23
+
24
+ // This structure is used to define a Ruby object that stores a pointer to a ddsketch_Handle_DDSketch
25
+ // See also https://github.com/ruby/ruby/blob/master/doc/extension.rdoc for how this works
26
+ static const rb_data_type_t ddsketch_typed_data = {
27
+ .wrap_struct_name = "Datadog::DDSketch",
28
+ .function = {
29
+ .dmark = NULL, // We don't store references to Ruby objects so we don't need to mark any of them
30
+ .dfree = ddsketch_free,
31
+ .dsize = NULL, // We don't track memory usage (although it'd be cool if we did!)
32
+ //.dcompact = NULL, // Not needed -- we don't store references to Ruby objects
33
+ },
34
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
35
+ };
36
+
37
+ static VALUE _native_new(VALUE klass) {
38
+ ddsketch_Handle_DDSketch *state = ruby_xcalloc(1, sizeof(ddsketch_Handle_DDSketch));
39
+
40
+ *state = ddog_ddsketch_new();
41
+
42
+ return TypedData_Wrap_Struct(klass, &ddsketch_typed_data, state);
43
+ }
44
+
45
+ static void ddsketch_free(void *ptr) {
46
+ ddsketch_Handle_DDSketch *state = (ddsketch_Handle_DDSketch *) ptr;
47
+ ddog_ddsketch_drop(state);
48
+ ruby_xfree(ptr);
49
+ }
50
+
51
+ static VALUE native_add(VALUE self, VALUE point) {
52
+ ddsketch_Handle_DDSketch *state;
53
+ TypedData_Get_Struct(self, ddsketch_Handle_DDSketch, &ddsketch_typed_data, state);
54
+
55
+ ddog_VoidResult result = ddog_ddsketch_add(state, NUM2DBL(point));
56
+
57
+ CHECK_VOID_RESULT("DDSketch add failed", result);
58
+
59
+ return self;
60
+ }
61
+
62
+ static VALUE native_add_with_count(VALUE self, VALUE point, VALUE count) {
63
+ ddsketch_Handle_DDSketch *state;
64
+ TypedData_Get_Struct(self, ddsketch_Handle_DDSketch, &ddsketch_typed_data, state);
65
+
66
+ ddog_VoidResult result = ddog_ddsketch_add_with_count(state, NUM2DBL(point), NUM2DBL(count));
67
+
68
+ CHECK_VOID_RESULT("DDSketch add_with_count failed", result);
69
+
70
+ return self;
71
+ }
72
+
73
+ static VALUE native_count(VALUE self) {
74
+ ddsketch_Handle_DDSketch *state;
75
+ TypedData_Get_Struct(self, ddsketch_Handle_DDSketch, &ddsketch_typed_data, state);
76
+
77
+ double count_out;
78
+ ddog_VoidResult result = ddog_ddsketch_count(state, &count_out);
79
+
80
+ CHECK_VOID_RESULT("DDSketch count failed", result);
81
+
82
+ return DBL2NUM(count_out);
83
+ }
84
+
85
+ static VALUE native_encode(VALUE self) {
86
+ ddsketch_Handle_DDSketch *state;
87
+ TypedData_Get_Struct(self, ddsketch_Handle_DDSketch, &ddsketch_typed_data, state);
88
+
89
+ ddog_Vec_U8 encoded = ddog_ddsketch_encode(state);
90
+
91
+ // Copy into a Ruby string
92
+ VALUE bytes = rb_str_new((const char *) encoded.ptr, encoded.len);
93
+
94
+ ddog_Vec_U8_drop(encoded);
95
+
96
+ // The sketch is consumed by encode; to make this a bit more user-friendly for
97
+ // a Ruby API (since we can't "kill" the Ruby object), let's re-initialize it so
98
+ // it can be used again.
99
+ *state = ddog_ddsketch_new();
100
+
101
+ return bytes;
102
+ }
@@ -0,0 +1,203 @@
1
+ #include <stdbool.h>
2
+
3
+ #include "datadog_ruby_common.h"
4
+
5
+ // Prototypes for Ruby functions declared in internal Ruby headers.
6
+ // rb_iseqw_new wraps an internal iseq pointer into a Ruby-visible
7
+ // RubyVM::InstructionSequence object.
8
+ VALUE rb_iseqw_new(const void *iseq);
9
+ // rb_iseqw_to_iseq unwraps a RubyVM::InstructionSequence object back
10
+ // to its internal iseq pointer.
11
+ const void *rb_iseqw_to_iseq(VALUE iseqw);
12
+ int rb_objspace_internal_object_p(VALUE obj);
13
+ void rb_objspace_each_objects(
14
+ int (*callback)(void *start, void *end, size_t stride, void *data),
15
+ void *data);
16
+
17
+ #define IMEMO_TYPE_ISEQ 7
18
+
19
+ // The ID value of the string "mesg" which is used in Ruby source as
20
+ // id_mesg or idMesg, and is used to set and retrieve the exception message
21
+ // from standard library exception classes like NameError.
22
+ static ID id_mesg;
23
+
24
+ // ID for the fiber-local key that backs the method-probe re-entrancy guard.
25
+ // Storage is the same hashtable that backs Thread#[] / Thread#[]=, but accessed
26
+ // directly via rb_thread_local_aref / rb_thread_local_aset so that user-installed
27
+ // method probes on Thread#[] / Thread#[]= cannot intercept guard reads/writes.
28
+ static ID id_datadog_di_in_probe;
29
+
30
+ // Returns whether the argument is an IMEMO of type ISEQ.
31
+ static bool ddtrace_imemo_iseq_p(VALUE v) {
32
+ return rb_objspace_internal_object_p(v) && RB_TYPE_P(v, T_IMEMO) && ddtrace_imemo_type(v) == IMEMO_TYPE_ISEQ;
33
+ }
34
+
35
+ static int ddtrace_di_os_obj_of_i(void *vstart, void *vend, size_t stride, void *data)
36
+ {
37
+ VALUE *array = (VALUE *)data;
38
+
39
+ VALUE v = (VALUE)vstart;
40
+ for (; v != (VALUE)vend; v += stride) {
41
+ if (ddtrace_imemo_iseq_p(v)) {
42
+ VALUE iseq = rb_iseqw_new((void *) v);
43
+ rb_ary_push(*array, iseq);
44
+ }
45
+ }
46
+
47
+ return 0;
48
+ }
49
+
50
+ /*
51
+ Returns all RubyVM::InstructionSequence objects existing in the current process.
52
+
53
+ This uses the same approach as ruby/debug's iseq_collector.c:
54
+ https://github.com/ruby/debug/blob/master/ext/debug/iseq_collector.c
55
+ */
56
+ static VALUE all_iseqs(DDTRACE_UNUSED VALUE _self) {
57
+ VALUE array = rb_ary_new();
58
+ rb_objspace_each_objects(ddtrace_di_os_obj_of_i, &array);
59
+ return array;
60
+ }
61
+
62
+ /*
63
+ * call-seq:
64
+ * DI.exception_message(exception) -> String | Object
65
+ *
66
+ * Returns the exception message associated with the exception via the
67
+ * exception's constructor.
68
+ *
69
+ * This method does not invoke Ruby code and as such will not call
70
+ * the +message+ method, if one is defined on the exception object.
71
+ *
72
+ * Normally, the exception message is a string, however there is no
73
+ * type enforcement done by Ruby for the messages and objects of arbitrary
74
+ * classes can be passed to exception constructors and will, subsequently,
75
+ * be returned by this method.
76
+ *
77
+ * @param exception [Exception] The exception object
78
+ * @return [String | Object] The exception message
79
+ */
80
+ static VALUE exception_message(DDTRACE_UNUSED VALUE _self, VALUE exception) {
81
+ return rb_ivar_get(exception, id_mesg);
82
+ }
83
+
84
+ /*
85
+ * call-seq:
86
+ * DI.in_probe? -> true | false
87
+ *
88
+ * Returns whether the current fiber is currently inside DI probe processing.
89
+ * Reads the same fiber-local storage as Thread.current[:datadog_di_in_probe]
90
+ * but bypasses Thread#[] method dispatch — a user method probe on Thread#[]
91
+ * cannot observe or intercept this call.
92
+ *
93
+ * @api private
94
+ */
95
+ static VALUE in_probe_p(DDTRACE_UNUSED VALUE _self) {
96
+ VALUE v = rb_thread_local_aref(rb_thread_current(), id_datadog_di_in_probe);
97
+ return RTEST(v) ? Qtrue : Qfalse;
98
+ }
99
+
100
+ /*
101
+ * call-seq:
102
+ * DI.enter_probe -> nil
103
+ *
104
+ * Marks the current fiber as inside DI probe processing. Writes to the same
105
+ * fiber-local storage as Thread.current[:datadog_di_in_probe] = true, but
106
+ * bypasses Thread#[]= method dispatch — a user method probe on Thread#[]=
107
+ * cannot observe or intercept this call.
108
+ *
109
+ * @api private
110
+ */
111
+ static VALUE enter_probe(DDTRACE_UNUSED VALUE _self) {
112
+ rb_thread_local_aset(rb_thread_current(), id_datadog_di_in_probe, Qtrue);
113
+ return Qnil;
114
+ }
115
+
116
+ /*
117
+ * call-seq:
118
+ * DI.leave_probe -> nil
119
+ *
120
+ * Marks the current fiber as no longer inside DI probe processing. Writes to
121
+ * the same fiber-local storage as Thread.current[:datadog_di_in_probe] = nil,
122
+ * but bypasses Thread#[]= method dispatch — a user method probe on Thread#[]=
123
+ * cannot observe or intercept this call.
124
+ *
125
+ * @api private
126
+ */
127
+ static VALUE leave_probe(DDTRACE_UNUSED VALUE _self) {
128
+ rb_thread_local_aset(rb_thread_current(), id_datadog_di_in_probe, Qnil);
129
+ return Qnil;
130
+ }
131
+
132
+ /*
133
+ * call-seq:
134
+ * DI.hash?(obj) -> true | false
135
+ *
136
+ * Returns whether the given object is a Hash via a direct type check
137
+ * (RB_TYPE_P), bypassing Kernel#is_a? method dispatch. Used in the method
138
+ * probe wrapper (the Ruby < 3 argument-serialization split) to test whether
139
+ * the trailing argument is a hash without giving a user-installed method
140
+ * probe on Kernel#is_a? a chance to recurse. Matches Hash and its
141
+ * subclasses, like is_a?(Hash), since their instances are still T_HASH.
142
+ *
143
+ * @api private
144
+ */
145
+ static VALUE is_hash(DDTRACE_UNUSED VALUE _self, VALUE obj) {
146
+ return RB_TYPE_P(obj, T_HASH) ? Qtrue : Qfalse;
147
+ }
148
+
149
+ // rb_iseq_type was added in Ruby 3.1 (commit 89a02d89 by Koichi Sasada,
150
+ // 2021-12-19). It returns the iseq type as a Symbol. On Ruby < 3.1 this
151
+ // function does not exist, so have_func('rb_iseq_type') in extconf.rb
152
+ // gates compilation. When unavailable, backfill_registry falls back to
153
+ // the first_lineno == 0 heuristic.
154
+ #ifdef HAVE_RB_ISEQ_TYPE
155
+ VALUE rb_iseq_type(const void *iseq);
156
+
157
+ /*
158
+ * call-seq:
159
+ * DI.iseq_type(iseq) -> Symbol
160
+ *
161
+ * Returns the type of an InstructionSequence as a symbol by calling
162
+ * the internal rb_iseq_type() function (available since Ruby 3.1).
163
+ *
164
+ * This method is only defined when rb_iseq_type is detected at compile
165
+ * time via have_func in extconf.rb. On Ruby < 3.1 it is not available
166
+ * and callers must use an alternative (e.g. first_lineno heuristic).
167
+ *
168
+ * Possible return values: :top, :method, :block, :class, :rescue,
169
+ * :ensure, :eval, :main, :plain.
170
+ *
171
+ * :top and :main represent whole-file iseqs (from require/load and the
172
+ * entry point script respectively). Other types represent sub-file
173
+ * constructs (method definitions, class bodies, blocks, etc.).
174
+ *
175
+ * Used by CodeTracker#backfill_registry to distinguish whole-file iseqs
176
+ * from per-method/block/class iseqs when populating the registry from
177
+ * the object space.
178
+ *
179
+ * @param iseq [RubyVM::InstructionSequence] The instruction sequence
180
+ * @return [Symbol] The iseq type
181
+ */
182
+ static VALUE iseq_type(DDTRACE_UNUSED VALUE _self, VALUE iseq_val) {
183
+ const void *iseq = rb_iseqw_to_iseq(iseq_val);
184
+ if (!iseq) return Qnil;
185
+ return rb_iseq_type(iseq);
186
+ }
187
+ #endif
188
+
189
+ void di_init(VALUE datadog_module) {
190
+ id_mesg = rb_intern("mesg");
191
+ id_datadog_di_in_probe = rb_intern("datadog_di_in_probe");
192
+
193
+ VALUE di_module = rb_define_module_under(datadog_module, "DI");
194
+ rb_define_singleton_method(di_module, "all_iseqs", all_iseqs, 0);
195
+ rb_define_singleton_method(di_module, "exception_message", exception_message, 1);
196
+ rb_define_singleton_method(di_module, "in_probe?", in_probe_p, 0);
197
+ rb_define_singleton_method(di_module, "enter_probe", enter_probe, 0);
198
+ rb_define_singleton_method(di_module, "leave_probe", leave_probe, 0);
199
+ rb_define_singleton_method(di_module, "hash?", is_hash, 1);
200
+ #ifdef HAVE_RB_ISEQ_TYPE
201
+ rb_define_singleton_method(di_module, "iseq_type", iseq_type, 1);
202
+ #endif
203
+ }