datadog 2.4.0 → 2.44.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 (1070) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1261 -1
  3. data/README.md +3 -1
  4. data/bin/ddprofrb +4 -4
  5. data/ext/LIBDATADOG_DEVELOPMENT.md +3 -0
  6. data/ext/datadog_profiling_native_extension/NativeExtensionDesign.md +12 -24
  7. data/ext/datadog_profiling_native_extension/clock_id.h +11 -3
  8. data/ext/datadog_profiling_native_extension/clock_id_from_mach.c +66 -0
  9. data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +3 -2
  10. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +653 -212
  11. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +5 -5
  12. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +1 -1
  13. data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +3 -2
  14. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +33 -20
  15. data/ext/datadog_profiling_native_extension/collectors_stack.c +409 -113
  16. data/ext/datadog_profiling_native_extension/collectors_stack.h +41 -5
  17. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +1208 -623
  18. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +33 -8
  19. data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +240 -0
  20. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +85 -16
  21. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +47 -1
  22. data/ext/datadog_profiling_native_extension/encoded_profile.c +80 -0
  23. data/ext/datadog_profiling_native_extension/encoded_profile.h +8 -0
  24. data/ext/datadog_profiling_native_extension/extconf.rb +99 -120
  25. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +6 -43
  26. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +15 -55
  27. data/ext/datadog_profiling_native_extension/heap_recorder.c +762 -608
  28. data/ext/datadog_profiling_native_extension/heap_recorder.h +67 -28
  29. data/ext/datadog_profiling_native_extension/http_transport.c +108 -144
  30. data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +18 -15
  31. data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +8 -10
  32. data/ext/datadog_profiling_native_extension/macos_sampler_thread.h +55 -0
  33. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +3 -40
  34. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +796 -417
  35. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +48 -12
  36. data/ext/datadog_profiling_native_extension/profiling.c +93 -27
  37. data/ext/datadog_profiling_native_extension/ruby_helpers.c +77 -137
  38. data/ext/datadog_profiling_native_extension/ruby_helpers.h +21 -20
  39. data/ext/datadog_profiling_native_extension/setup_signal_handler.c +34 -10
  40. data/ext/datadog_profiling_native_extension/setup_signal_handler.h +2 -1
  41. data/ext/datadog_profiling_native_extension/stack_recorder.c +458 -302
  42. data/ext/datadog_profiling_native_extension/stack_recorder.h +14 -3
  43. data/ext/datadog_profiling_native_extension/time_helpers.h +18 -11
  44. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +48 -0
  45. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +36 -0
  46. data/ext/libdatadog_api/crashtracker.c +33 -30
  47. data/ext/libdatadog_api/crashtracker.h +5 -0
  48. data/ext/libdatadog_api/crashtracker_report_exception.c +126 -0
  49. data/ext/libdatadog_api/datadog_ruby_common.c +85 -16
  50. data/ext/libdatadog_api/datadog_ruby_common.h +47 -1
  51. data/ext/libdatadog_api/ddsketch.c +102 -0
  52. data/ext/libdatadog_api/di.c +218 -0
  53. data/ext/libdatadog_api/extconf.rb +44 -45
  54. data/ext/libdatadog_api/feature_flags.c +588 -0
  55. data/ext/libdatadog_api/feature_flags.h +5 -0
  56. data/ext/libdatadog_api/helpers.h +27 -0
  57. data/ext/libdatadog_api/init.c +35 -0
  58. data/ext/libdatadog_api/library_config.c +173 -0
  59. data/ext/libdatadog_api/library_config.h +25 -0
  60. data/ext/libdatadog_api/otel_thread_context.c +268 -0
  61. data/ext/libdatadog_api/otel_thread_context.h +5 -0
  62. data/ext/libdatadog_api/process_discovery.c +118 -0
  63. data/ext/libdatadog_api/process_discovery.h +5 -0
  64. data/ext/libdatadog_api/trace_exporter.c +1932 -0
  65. data/ext/libdatadog_api/trace_exporter.h +5 -0
  66. data/ext/libdatadog_extconf_helpers.rb +116 -18
  67. data/lib/datadog/ai_guard/autoload.rb +10 -0
  68. data/lib/datadog/ai_guard/component.rb +53 -0
  69. data/lib/datadog/ai_guard/configuration/ext.rb +19 -0
  70. data/lib/datadog/ai_guard/configuration.rb +128 -0
  71. data/lib/datadog/ai_guard/contrib/auto_instrument.rb +24 -0
  72. data/lib/datadog/ai_guard/contrib/integration.rb +37 -0
  73. data/lib/datadog/ai_guard/contrib/rack/integration.rb +42 -0
  74. data/lib/datadog/ai_guard/contrib/rack/patcher.rb +26 -0
  75. data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +97 -0
  76. data/lib/datadog/ai_guard/contrib/rails/integration.rb +41 -0
  77. data/lib/datadog/ai_guard/contrib/rails/patcher.rb +97 -0
  78. data/lib/datadog/ai_guard/contrib/ruby_llm/chat_instrumentation.rb +73 -0
  79. data/lib/datadog/ai_guard/contrib/ruby_llm/integration.rb +41 -0
  80. data/lib/datadog/ai_guard/contrib/ruby_llm/message_adapter.rb +76 -0
  81. data/lib/datadog/ai_guard/contrib/ruby_llm/patcher.rb +31 -0
  82. data/lib/datadog/ai_guard/contrib/ruby_llm/redaction_change_set.rb +135 -0
  83. data/lib/datadog/ai_guard/evaluation/client.rb +50 -0
  84. data/lib/datadog/ai_guard/evaluation/content_part.rb +48 -0
  85. data/lib/datadog/ai_guard/evaluation/message.rb +43 -0
  86. data/lib/datadog/ai_guard/evaluation/message_builder.rb +31 -0
  87. data/lib/datadog/ai_guard/evaluation/no_op_result.rb +36 -0
  88. data/lib/datadog/ai_guard/evaluation/outcome.rb +24 -0
  89. data/lib/datadog/ai_guard/evaluation/request.rb +30 -0
  90. data/lib/datadog/ai_guard/evaluation/response.rb +33 -0
  91. data/lib/datadog/ai_guard/evaluation/result.rb +38 -0
  92. data/lib/datadog/ai_guard/evaluation/tool_call.rb +31 -0
  93. data/lib/datadog/ai_guard/evaluation.rb +130 -0
  94. data/lib/datadog/ai_guard/ext.rb +32 -0
  95. data/lib/datadog/ai_guard/http_client.rb +86 -0
  96. data/lib/datadog/ai_guard/metrics/telemetry.rb +43 -0
  97. data/lib/datadog/ai_guard/redaction/replacements.rb +97 -0
  98. data/lib/datadog/ai_guard/redaction/result.rb +29 -0
  99. data/lib/datadog/ai_guard/redaction.rb +80 -0
  100. data/lib/datadog/ai_guard.rb +182 -0
  101. data/lib/datadog/appsec/actions_handler/serializable_backtrace.rb +68 -0
  102. data/lib/datadog/appsec/actions_handler.rb +49 -0
  103. data/lib/datadog/appsec/anonymizer.rb +16 -0
  104. data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +26 -0
  105. data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +66 -0
  106. data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +36 -0
  107. data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +26 -0
  108. data/lib/datadog/appsec/api_security/endpoint_collection.rb +10 -0
  109. data/lib/datadog/appsec/api_security/route_extractor.rb +104 -0
  110. data/lib/datadog/appsec/api_security/sampler.rb +62 -0
  111. data/lib/datadog/appsec/api_security.rb +23 -0
  112. data/lib/datadog/appsec/assets/blocked.html +1 -99
  113. data/lib/datadog/appsec/assets/blocked.json +1 -1
  114. data/lib/datadog/appsec/assets/blocked.text +3 -1
  115. data/lib/datadog/appsec/assets/waf_rules/README.md +44 -5
  116. data/lib/datadog/appsec/assets/waf_rules/recommended.json +954 -229
  117. data/lib/datadog/appsec/assets/waf_rules/strict.json +109 -106
  118. data/lib/datadog/appsec/assets.rb +8 -8
  119. data/lib/datadog/appsec/autoload.rb +5 -5
  120. data/lib/datadog/appsec/component.rb +56 -75
  121. data/lib/datadog/appsec/compressed_json.rb +40 -0
  122. data/lib/datadog/appsec/configuration.rb +436 -1
  123. data/lib/datadog/appsec/context.rb +135 -0
  124. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +94 -0
  125. data/lib/datadog/appsec/contrib/active_record/integration.rb +41 -0
  126. data/lib/datadog/appsec/contrib/active_record/patcher.rb +104 -0
  127. data/lib/datadog/appsec/contrib/auto_instrument.rb +1 -1
  128. data/lib/datadog/appsec/contrib/aws_lambda/gateway/watcher.rb +75 -0
  129. data/lib/datadog/appsec/contrib/aws_lambda/integration.rb +39 -0
  130. data/lib/datadog/appsec/contrib/aws_lambda/patcher.rb +30 -0
  131. data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +146 -0
  132. data/lib/datadog/appsec/contrib/devise/configuration.rb +52 -0
  133. data/lib/datadog/appsec/contrib/devise/data_extractor.rb +78 -0
  134. data/lib/datadog/appsec/contrib/devise/ext.rb +22 -0
  135. data/lib/datadog/appsec/contrib/devise/integration.rb +5 -6
  136. data/lib/datadog/appsec/contrib/devise/patcher.rb +34 -26
  137. data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +104 -0
  138. data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +70 -0
  139. data/lib/datadog/appsec/contrib/devise/{patcher/rememberable_patch.rb → patches/skip_signin_tracking_patch.rb} +3 -3
  140. data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +121 -0
  141. data/lib/datadog/appsec/contrib/excon/integration.rb +41 -0
  142. data/lib/datadog/appsec/contrib/excon/patcher.rb +30 -0
  143. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +181 -0
  144. data/lib/datadog/appsec/contrib/faraday/connection_patch.rb +22 -0
  145. data/lib/datadog/appsec/contrib/faraday/integration.rb +42 -0
  146. data/lib/datadog/appsec/contrib/faraday/patcher.rb +53 -0
  147. data/lib/datadog/appsec/contrib/faraday/rack_builder_patch.rb +22 -0
  148. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +166 -0
  149. data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +4 -10
  150. data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +76 -26
  151. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +21 -36
  152. data/lib/datadog/appsec/contrib/graphql/integration.rb +10 -9
  153. data/lib/datadog/appsec/contrib/graphql/patcher.rb +3 -6
  154. data/lib/datadog/appsec/contrib/rack/buffered_input.rb +83 -0
  155. data/lib/datadog/appsec/contrib/rack/ext.rb +34 -0
  156. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +56 -21
  157. data/lib/datadog/appsec/contrib/rack/gateway/response.rb +4 -4
  158. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +101 -106
  159. data/lib/datadog/appsec/contrib/rack/input_peeker.rb +79 -0
  160. data/lib/datadog/appsec/contrib/rack/integration.rb +7 -7
  161. data/lib/datadog/appsec/contrib/rack/patcher.rb +3 -6
  162. data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +17 -15
  163. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +118 -114
  164. data/lib/datadog/appsec/contrib/rack/response_body.rb +36 -0
  165. data/lib/datadog/appsec/contrib/rails/gateway/request.rb +43 -4
  166. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +58 -35
  167. data/lib/datadog/appsec/contrib/rails/integration.rb +6 -6
  168. data/lib/datadog/appsec/contrib/rails/patcher.rb +82 -69
  169. data/lib/datadog/appsec/contrib/rails/patches/process_action_patch.rb +29 -0
  170. data/lib/datadog/appsec/contrib/rails/patches/render_to_body_patch.rb +33 -0
  171. data/lib/datadog/appsec/contrib/rails/request.rb +3 -3
  172. data/lib/datadog/appsec/contrib/rails/request_middleware.rb +2 -1
  173. data/lib/datadog/appsec/contrib/rest_client/integration.rb +45 -0
  174. data/lib/datadog/appsec/contrib/rest_client/patcher.rb +30 -0
  175. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +193 -0
  176. data/lib/datadog/appsec/contrib/sinatra/gateway/request.rb +1 -1
  177. data/lib/datadog/appsec/contrib/sinatra/gateway/route_params.rb +1 -1
  178. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +83 -71
  179. data/lib/datadog/appsec/contrib/sinatra/integration.rb +6 -6
  180. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +25 -61
  181. data/lib/datadog/appsec/contrib/sinatra/patches/json_patch.rb +31 -0
  182. data/lib/datadog/appsec/contrib/sinatra/request_middleware.rb +2 -1
  183. data/lib/datadog/appsec/counter_sampler.rb +25 -0
  184. data/lib/datadog/appsec/default_header_tags.rb +52 -0
  185. data/lib/datadog/appsec/event.rb +80 -128
  186. data/lib/datadog/appsec/ext.rb +17 -1
  187. data/lib/datadog/appsec/extensions.rb +2 -2
  188. data/lib/datadog/appsec/instrumentation/gateway/argument.rb +23 -2
  189. data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +23 -0
  190. data/lib/datadog/appsec/instrumentation/gateway.rb +6 -24
  191. data/lib/datadog/appsec/metrics/collector.rb +80 -0
  192. data/lib/datadog/appsec/metrics/exporter.rb +48 -0
  193. data/lib/datadog/appsec/metrics/telemetry.rb +40 -0
  194. data/lib/datadog/appsec/metrics/telemetry_exporter.rb +47 -0
  195. data/lib/datadog/appsec/metrics.rb +14 -0
  196. data/lib/datadog/appsec/monitor/gateway/watcher.rb +60 -36
  197. data/lib/datadog/appsec/monitor.rb +1 -1
  198. data/lib/datadog/appsec/processor/rule_loader.rb +54 -60
  199. data/lib/datadog/appsec/rate_limiter.rb +1 -1
  200. data/lib/datadog/appsec/remote.rb +59 -70
  201. data/lib/datadog/appsec/response.rb +42 -94
  202. data/lib/datadog/appsec/route_normalizer/rails_route_pattern.rb +176 -0
  203. data/lib/datadog/appsec/route_normalizer/route_pattern.rb +378 -0
  204. data/lib/datadog/appsec/route_normalizer/route_text.rb +57 -0
  205. data/lib/datadog/appsec/route_normalizer.rb +80 -0
  206. data/lib/datadog/appsec/security_engine/engine.rb +197 -0
  207. data/lib/datadog/appsec/security_engine/result.rb +103 -0
  208. data/lib/datadog/appsec/security_engine/runner.rb +111 -0
  209. data/lib/datadog/appsec/security_engine.rb +9 -0
  210. data/lib/datadog/appsec/security_event.rb +37 -0
  211. data/lib/datadog/appsec/thread_safe_ref.rb +61 -0
  212. data/lib/datadog/appsec/trace_keeper.rb +36 -0
  213. data/lib/datadog/appsec/utils/hash_coercion.rb +23 -0
  214. data/lib/datadog/appsec/utils/http/body.rb +41 -0
  215. data/lib/datadog/appsec/utils/http/body_reader.rb +61 -0
  216. data/lib/datadog/appsec/utils/http/media_range.rb +17 -16
  217. data/lib/datadog/appsec/utils/http/media_type.rb +33 -27
  218. data/lib/datadog/appsec/utils/http/url_encoded.rb +107 -0
  219. data/lib/datadog/appsec.rb +35 -28
  220. data/lib/datadog/auto_instrument.rb +5 -2
  221. data/lib/datadog/auto_instrument_base.rb +2 -1
  222. data/lib/datadog/core/buffer/cruby.rb +1 -1
  223. data/lib/datadog/core/buffer/random.rb +18 -2
  224. data/lib/datadog/core/buffer/thread_safe.rb +1 -1
  225. data/lib/datadog/core/configuration/agent_settings.rb +52 -0
  226. data/lib/datadog/core/configuration/agent_settings_resolver.rb +46 -59
  227. data/lib/datadog/core/configuration/agentless_settings_resolver.rb +176 -0
  228. data/lib/datadog/core/configuration/base.rb +19 -7
  229. data/lib/datadog/core/configuration/components.rb +283 -54
  230. data/lib/datadog/core/configuration/components_state.rb +28 -0
  231. data/lib/datadog/core/configuration/config_helper.rb +109 -0
  232. data/lib/datadog/core/configuration/deprecations.rb +36 -0
  233. data/lib/datadog/core/configuration/ext.rb +15 -12
  234. data/lib/datadog/core/configuration/option.rb +150 -84
  235. data/lib/datadog/core/configuration/option_definition.rb +51 -30
  236. data/lib/datadog/core/configuration/options.rb +58 -19
  237. data/lib/datadog/core/configuration/settings.rb +341 -140
  238. data/lib/datadog/core/configuration/stable_config.rb +32 -0
  239. data/lib/datadog/core/configuration/supported_configurations.rb +426 -0
  240. data/lib/datadog/core/configuration.rb +51 -21
  241. data/lib/datadog/core/contrib/rails/railtie.rb +32 -0
  242. data/lib/datadog/core/contrib/rails/utils.rb +28 -0
  243. data/lib/datadog/core/crashtracking/component.rb +89 -39
  244. data/lib/datadog/core/crashtracking/tag_builder.rb +11 -23
  245. data/lib/datadog/core/ddsketch.rb +19 -0
  246. data/lib/datadog/core/deprecations.rb +3 -3
  247. data/lib/datadog/core/diagnostics/environment_logger.rb +46 -9
  248. data/lib/datadog/core/diagnostics/health.rb +2 -2
  249. data/lib/datadog/core/encoding.rb +21 -5
  250. data/lib/datadog/core/environment/agent_info.rb +142 -0
  251. data/lib/datadog/core/environment/cgroup.rb +53 -28
  252. data/lib/datadog/core/environment/container.rb +143 -51
  253. data/lib/datadog/core/environment/execution.rb +3 -3
  254. data/lib/datadog/core/environment/ext.rb +32 -21
  255. data/lib/datadog/core/environment/gc.rb +1 -1
  256. data/lib/datadog/core/environment/git.rb +5 -4
  257. data/lib/datadog/core/environment/identity.rb +50 -14
  258. data/lib/datadog/core/environment/platform.rb +8 -8
  259. data/lib/datadog/core/environment/process.rb +122 -0
  260. data/lib/datadog/core/environment/socket.rb +15 -2
  261. data/lib/datadog/core/environment/variable_helpers.rb +4 -4
  262. data/lib/datadog/core/environment/vm_cache.rb +1 -1
  263. data/lib/datadog/core/environment/yjit.rb +8 -2
  264. data/lib/datadog/core/error.rb +15 -13
  265. data/lib/datadog/core/evp.rb +11 -0
  266. data/lib/datadog/core/extensions.rb +1 -1
  267. data/lib/datadog/core/feature_flags.rb +61 -0
  268. data/lib/datadog/core/git/ext.rb +4 -4
  269. data/lib/datadog/core/knuth_sampler.rb +59 -0
  270. data/lib/datadog/core/logger.rb +5 -5
  271. data/lib/datadog/core/logging/ext.rb +1 -1
  272. data/lib/datadog/core/metrics/client.rb +49 -49
  273. data/lib/datadog/core/metrics/ext.rb +5 -5
  274. data/lib/datadog/core/metrics/helpers.rb +1 -1
  275. data/lib/datadog/core/metrics/logging.rb +8 -8
  276. data/lib/datadog/core/metrics/options.rb +5 -5
  277. data/lib/datadog/core/pin.rb +9 -9
  278. data/lib/datadog/core/process_discovery/tracer_memfd.rb +13 -0
  279. data/lib/datadog/core/process_discovery.rb +62 -0
  280. data/lib/datadog/core/rate_limiter.rb +16 -4
  281. data/lib/datadog/core/remote/client/capabilities.rb +82 -11
  282. data/lib/datadog/core/remote/client.rb +130 -107
  283. data/lib/datadog/core/remote/component.rb +97 -55
  284. data/lib/datadog/core/remote/configuration/content.rb +17 -4
  285. data/lib/datadog/core/remote/configuration/digest.rb +22 -15
  286. data/lib/datadog/core/remote/configuration/path.rb +9 -9
  287. data/lib/datadog/core/remote/configuration/repository.rb +19 -6
  288. data/lib/datadog/core/remote/configuration/target.rb +15 -8
  289. data/lib/datadog/core/remote/configuration.rb +4 -4
  290. data/lib/datadog/core/remote/ext.rb +3 -3
  291. data/lib/datadog/core/remote/negotiation.rb +10 -10
  292. data/lib/datadog/core/remote/tie/tracing.rb +7 -7
  293. data/lib/datadog/core/remote/transport/config.rb +11 -37
  294. data/lib/datadog/core/remote/transport/http/config.rb +39 -107
  295. data/lib/datadog/core/remote/transport/http/negotiation.rb +19 -92
  296. data/lib/datadog/core/remote/transport/http.rb +33 -106
  297. data/lib/datadog/core/remote/transport/negotiation.rb +9 -21
  298. data/lib/datadog/core/remote/worker.rb +40 -41
  299. data/lib/datadog/core/runtime/ext.rb +22 -22
  300. data/lib/datadog/core/runtime/metrics.rb +34 -14
  301. data/lib/datadog/core/semaphore.rb +32 -0
  302. data/lib/datadog/core/tag_builder.rb +52 -0
  303. data/lib/datadog/core/tag_normalizer.rb +84 -0
  304. data/lib/datadog/core/telemetry/component.rb +143 -60
  305. data/lib/datadog/core/telemetry/configuration_value.rb +38 -0
  306. data/lib/datadog/core/telemetry/emitter.rb +26 -14
  307. data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +67 -0
  308. data/lib/datadog/core/telemetry/event/app_closing.rb +18 -0
  309. data/lib/datadog/core/telemetry/event/app_dependencies_loaded.rb +33 -0
  310. data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +30 -0
  311. data/lib/datadog/core/telemetry/event/app_extended_heartbeat.rb +32 -0
  312. data/lib/datadog/core/telemetry/event/app_heartbeat.rb +18 -0
  313. data/lib/datadog/core/telemetry/event/app_integrations_change.rb +58 -0
  314. data/lib/datadog/core/telemetry/event/app_started.rb +274 -0
  315. data/lib/datadog/core/telemetry/event/base.rb +40 -0
  316. data/lib/datadog/core/telemetry/event/distributions.rb +18 -0
  317. data/lib/datadog/core/telemetry/event/generate_metrics.rb +43 -0
  318. data/lib/datadog/core/telemetry/event/log.rb +76 -0
  319. data/lib/datadog/core/telemetry/event/message_batch.rb +42 -0
  320. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +66 -0
  321. data/lib/datadog/core/telemetry/event.rb +21 -392
  322. data/lib/datadog/core/telemetry/ext.rb +11 -9
  323. data/lib/datadog/core/telemetry/http/adapters/net.rb +12 -97
  324. data/lib/datadog/core/telemetry/logger.rb +6 -3
  325. data/lib/datadog/core/telemetry/logging.rb +35 -17
  326. data/lib/datadog/core/telemetry/metric.rb +37 -15
  327. data/lib/datadog/core/telemetry/metrics_collection.rb +2 -2
  328. data/lib/datadog/core/telemetry/metrics_manager.rb +10 -1
  329. data/lib/datadog/core/telemetry/request.rb +23 -11
  330. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +66 -0
  331. data/lib/datadog/core/telemetry/transport/http.rb +68 -0
  332. data/lib/datadog/core/telemetry/transport/telemetry.rb +42 -0
  333. data/lib/datadog/core/telemetry/worker.rb +214 -35
  334. data/lib/datadog/core/transport/ext.rb +14 -10
  335. data/lib/datadog/core/transport/http/adapters/net.rb +19 -4
  336. data/lib/datadog/core/transport/http/adapters/test.rb +3 -2
  337. data/lib/datadog/core/transport/http/adapters/unix_socket.rb +5 -5
  338. data/lib/datadog/core/transport/http/api/endpoint.rb +10 -5
  339. data/lib/datadog/{tracing → core}/transport/http/api/instance.rb +5 -5
  340. data/lib/datadog/core/transport/http/api/map.rb +1 -1
  341. data/lib/datadog/{tracing → core}/transport/http/builder.rb +62 -36
  342. data/lib/datadog/core/transport/http/client.rb +80 -0
  343. data/lib/datadog/core/transport/http/env.rb +8 -0
  344. data/lib/datadog/core/transport/http/response.rb +5 -1
  345. data/lib/datadog/core/transport/http.rb +80 -0
  346. data/lib/datadog/core/transport/parcel.rb +61 -9
  347. data/lib/datadog/core/transport/response.rb +19 -1
  348. data/lib/datadog/core/transport/transport.rb +90 -0
  349. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +181 -29
  350. data/lib/datadog/core/utils/base64_codec.rb +23 -0
  351. data/lib/datadog/core/utils/duration.rb +33 -33
  352. data/lib/datadog/core/utils/enumerable_compat.rb +29 -0
  353. data/lib/datadog/core/utils/fnv.rb +26 -0
  354. data/lib/datadog/core/utils/forking.rb +5 -3
  355. data/lib/datadog/core/utils/hash.rb +0 -23
  356. data/lib/datadog/core/utils/lru_cache.rb +45 -0
  357. data/lib/datadog/core/utils/network.rb +34 -13
  358. data/lib/datadog/core/utils/only_once.rb +1 -1
  359. data/lib/datadog/core/utils/only_once_successful.rb +25 -8
  360. data/lib/datadog/core/utils/safe_dup.rb +4 -3
  361. data/lib/datadog/core/utils/sequence.rb +3 -4
  362. data/lib/datadog/core/utils/spawn_monkey_patch.rb +68 -0
  363. data/lib/datadog/core/utils/time.rb +19 -33
  364. data/lib/datadog/core/utils/truncation.rb +21 -0
  365. data/lib/datadog/core/utils/url.rb +1 -1
  366. data/lib/datadog/core/utils.rb +14 -5
  367. data/lib/datadog/core/vendor/multipart-post/multipart/post/composite_read_io.rb +1 -1
  368. data/lib/datadog/core/vendor/multipart-post/multipart/post/multipartable.rb +8 -8
  369. data/lib/datadog/core/vendor/multipart-post/multipart/post/parts.rb +7 -7
  370. data/lib/datadog/core/worker.rb +1 -1
  371. data/lib/datadog/core/workers/async.rb +41 -15
  372. data/lib/datadog/core/workers/interval_loop.rb +63 -4
  373. data/lib/datadog/core/workers/polling.rb +4 -2
  374. data/lib/datadog/core/workers/queue.rb +96 -1
  375. data/lib/datadog/core/workers/runtime_metrics.rb +14 -6
  376. data/lib/datadog/core.rb +20 -3
  377. data/lib/datadog/data_streams/configuration.rb +50 -0
  378. data/lib/datadog/data_streams/ext.rb +11 -0
  379. data/lib/datadog/data_streams/extensions.rb +16 -0
  380. data/lib/datadog/data_streams/pathway_context.rb +167 -0
  381. data/lib/datadog/data_streams/processor.rb +542 -0
  382. data/lib/datadog/data_streams/transport/http/stats.rb +58 -0
  383. data/lib/datadog/data_streams/transport/http.rb +36 -0
  384. data/lib/datadog/data_streams/transport/stats.rb +39 -0
  385. data/lib/datadog/data_streams.rb +100 -0
  386. data/lib/datadog/di/base.rb +123 -0
  387. data/lib/datadog/di/boot.rb +47 -0
  388. data/lib/datadog/di/capture_expression.rb +21 -0
  389. data/lib/datadog/di/capture_expression_evaluator.rb +71 -0
  390. data/lib/datadog/di/capture_limits.rb +41 -0
  391. data/lib/datadog/di/code_tracker.rb +256 -18
  392. data/lib/datadog/di/component.rb +220 -0
  393. data/lib/datadog/di/configuration.rb +241 -2
  394. data/lib/datadog/di/context.rb +82 -0
  395. data/lib/datadog/di/contrib/active_record.rb +41 -0
  396. data/lib/datadog/di/contrib/railtie.rb +15 -0
  397. data/lib/datadog/di/contrib.rb +28 -0
  398. data/lib/datadog/di/el/compiler.rb +244 -0
  399. data/lib/datadog/di/el/evaluator.rb +239 -0
  400. data/lib/datadog/di/el/expression.rb +53 -0
  401. data/lib/datadog/di/el.rb +5 -0
  402. data/lib/datadog/di/error.rb +66 -0
  403. data/lib/datadog/di/fatal_exceptions.rb +26 -0
  404. data/lib/datadog/di/instrumenter.rb +978 -0
  405. data/lib/datadog/di/logger.rb +30 -0
  406. data/lib/datadog/di/preload.rb +18 -0
  407. data/lib/datadog/di/probe.rb +188 -14
  408. data/lib/datadog/di/probe_builder.rb +132 -3
  409. data/lib/datadog/di/probe_file_loader/railtie.rb +15 -0
  410. data/lib/datadog/di/probe_file_loader.rb +87 -0
  411. data/lib/datadog/di/probe_manager.rb +352 -0
  412. data/lib/datadog/di/probe_notification_builder.rb +452 -0
  413. data/lib/datadog/di/probe_notifier_worker.rb +381 -0
  414. data/lib/datadog/di/probe_repository.rb +198 -0
  415. data/lib/datadog/di/proc_responder.rb +36 -0
  416. data/lib/datadog/di/redactor.rb +24 -3
  417. data/lib/datadog/di/remote.rb +310 -0
  418. data/lib/datadog/di/serializer.rb +487 -96
  419. data/lib/datadog/di/transport/diagnostics.rb +32 -0
  420. data/lib/datadog/di/transport/http/diagnostics.rb +35 -0
  421. data/lib/datadog/di/transport/http/input.rb +45 -0
  422. data/lib/datadog/di/transport/http.rb +81 -0
  423. data/lib/datadog/di/transport/input.rb +144 -0
  424. data/lib/datadog/di/utils.rb +170 -0
  425. data/lib/datadog/di.rb +224 -2
  426. data/lib/datadog/error_tracking/collector.rb +88 -0
  427. data/lib/datadog/error_tracking/component.rb +167 -0
  428. data/lib/datadog/error_tracking/configuration.rb +64 -0
  429. data/lib/datadog/error_tracking/ext.rb +18 -0
  430. data/lib/datadog/error_tracking/extensions.rb +16 -0
  431. data/lib/datadog/error_tracking/filters.rb +77 -0
  432. data/lib/datadog/error_tracking.rb +18 -0
  433. data/lib/datadog/kit/appsec/events/v2.rb +253 -0
  434. data/lib/datadog/kit/appsec/events.rb +39 -26
  435. data/lib/datadog/kit/enable_core_dumps.rb +3 -3
  436. data/lib/datadog/kit/identity.rb +34 -24
  437. data/lib/datadog/kit/tracing/method_tracer.rb +135 -0
  438. data/lib/datadog/kit.rb +1 -1
  439. data/lib/datadog/open_feature/agentless/configuration_source.rb +246 -0
  440. data/lib/datadog/open_feature/agentless/parser.rb +43 -0
  441. data/lib/datadog/open_feature/agentless/response.rb +19 -0
  442. data/lib/datadog/open_feature/agentless/transport.rb +103 -0
  443. data/lib/datadog/open_feature/component.rb +165 -0
  444. data/lib/datadog/open_feature/configuration/agentless_endpoint.rb +90 -0
  445. data/lib/datadog/open_feature/configuration/source/resolution.rb +22 -0
  446. data/lib/datadog/open_feature/configuration/source.rb +43 -0
  447. data/lib/datadog/open_feature/configuration.rb +168 -0
  448. data/lib/datadog/open_feature/evaluation_engine.rb +96 -0
  449. data/lib/datadog/open_feature/exposures/batch_builder.rb +32 -0
  450. data/lib/datadog/open_feature/exposures/buffer.rb +43 -0
  451. data/lib/datadog/open_feature/exposures/deduplicator.rb +30 -0
  452. data/lib/datadog/open_feature/exposures/event.rb +67 -0
  453. data/lib/datadog/open_feature/exposures/reporter.rb +40 -0
  454. data/lib/datadog/open_feature/exposures/worker.rb +116 -0
  455. data/lib/datadog/open_feature/ext.rb +40 -0
  456. data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +442 -0
  457. data/lib/datadog/open_feature/flag_evaluation/writer.rb +544 -0
  458. data/lib/datadog/open_feature/hooks/flag_eval_evp_hook.rb +105 -0
  459. data/lib/datadog/open_feature/hooks/flag_eval_metrics_hook.rb +51 -0
  460. data/lib/datadog/open_feature/hooks/span_enrichment_hook/codec.rb +58 -0
  461. data/lib/datadog/open_feature/hooks/span_enrichment_hook/span_enrichment_state.rb +96 -0
  462. data/lib/datadog/open_feature/hooks/span_enrichment_hook/span_enrichment_state_store.rb +49 -0
  463. data/lib/datadog/open_feature/hooks/span_enrichment_hook.rb +184 -0
  464. data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +149 -0
  465. data/lib/datadog/open_feature/native_evaluator.rb +74 -0
  466. data/lib/datadog/open_feature/noop_evaluator.rb +31 -0
  467. data/lib/datadog/open_feature/provider.rb +235 -0
  468. data/lib/datadog/open_feature/remote.rb +67 -0
  469. data/lib/datadog/open_feature/resolution_details.rb +37 -0
  470. data/lib/datadog/open_feature/transport.rb +126 -0
  471. data/lib/datadog/open_feature.rb +19 -0
  472. data/lib/datadog/opentelemetry/api/baggage.rb +90 -0
  473. data/lib/datadog/opentelemetry/api/context.rb +25 -10
  474. data/lib/datadog/opentelemetry/configuration/settings.rb +226 -0
  475. data/lib/datadog/opentelemetry/ext.rb +9 -0
  476. data/lib/datadog/opentelemetry/logs.rb +98 -0
  477. data/lib/datadog/opentelemetry/metrics.rb +90 -0
  478. data/lib/datadog/opentelemetry/sdk/configurator.rb +69 -5
  479. data/lib/datadog/opentelemetry/sdk/id_generator.rb +16 -10
  480. data/lib/datadog/opentelemetry/sdk/logs_exporter.rb +30 -0
  481. data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +28 -0
  482. data/lib/datadog/opentelemetry/sdk/propagator.rb +21 -15
  483. data/lib/datadog/opentelemetry/sdk/span_processor.rb +24 -21
  484. data/lib/datadog/opentelemetry/sdk/trace/span.rb +43 -39
  485. data/lib/datadog/opentelemetry/sdk.rb +19 -0
  486. data/lib/datadog/opentelemetry/signal_configuration.rb +57 -0
  487. data/lib/datadog/opentelemetry/trace.rb +8 -5
  488. data/lib/datadog/opentelemetry.rb +11 -6
  489. data/lib/datadog/profiling/collectors/code_provenance.rb +84 -16
  490. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +60 -3
  491. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +11 -4
  492. data/lib/datadog/profiling/collectors/info.rb +62 -8
  493. data/lib/datadog/profiling/collectors/thread_context.rb +25 -18
  494. data/lib/datadog/profiling/component.rb +123 -104
  495. data/lib/datadog/profiling/encoded_profile.rb +11 -0
  496. data/lib/datadog/profiling/exporter.rb +51 -17
  497. data/lib/datadog/profiling/ext/dir_monkey_patches.rb +24 -5
  498. data/lib/datadog/profiling/ext/exec_monkey_patch.rb +32 -0
  499. data/lib/datadog/profiling/ext.rb +2 -17
  500. data/lib/datadog/profiling/flush.rb +26 -17
  501. data/lib/datadog/profiling/http_transport.rb +30 -96
  502. data/lib/datadog/profiling/load_native_extension.rb +3 -35
  503. data/lib/datadog/profiling/profiler.rb +31 -12
  504. data/lib/datadog/profiling/scheduler.rb +19 -10
  505. data/lib/datadog/profiling/sequence_tracker.rb +44 -0
  506. data/lib/datadog/profiling/stack_recorder.rb +38 -18
  507. data/lib/datadog/profiling/tag_builder.rb +41 -41
  508. data/lib/datadog/profiling/tasks/exec.rb +11 -6
  509. data/lib/datadog/profiling/tasks/help.rb +1 -0
  510. data/lib/datadog/profiling/tasks/setup.rb +4 -2
  511. data/lib/datadog/profiling.rb +42 -37
  512. data/lib/datadog/ruby_version.rb +25 -0
  513. data/lib/datadog/single_step_instrument.rb +11 -2
  514. data/lib/datadog/symbol_database/component.rb +734 -0
  515. data/lib/datadog/symbol_database/configuration.rb +73 -0
  516. data/lib/datadog/symbol_database/extensions.rb +19 -0
  517. data/lib/datadog/symbol_database/extractor.rb +1092 -0
  518. data/lib/datadog/symbol_database/file_hash.rb +48 -0
  519. data/lib/datadog/symbol_database/logger.rb +43 -0
  520. data/lib/datadog/symbol_database/remote.rb +195 -0
  521. data/lib/datadog/symbol_database/scope.rb +102 -0
  522. data/lib/datadog/symbol_database/scope_batcher.rb +292 -0
  523. data/lib/datadog/symbol_database/service_version.rb +66 -0
  524. data/lib/datadog/symbol_database/symbol.rb +69 -0
  525. data/lib/datadog/symbol_database/transport/http/endpoint.rb +28 -0
  526. data/lib/datadog/symbol_database/transport/http.rb +45 -0
  527. data/lib/datadog/symbol_database/transport.rb +54 -0
  528. data/lib/datadog/symbol_database/uploader.rb +230 -0
  529. data/lib/datadog/symbol_database.rb +71 -0
  530. data/lib/datadog/tracing/analytics.rb +2 -2
  531. data/lib/datadog/tracing/buffer.rb +15 -15
  532. data/lib/datadog/tracing/client_ip.rb +4 -4
  533. data/lib/datadog/tracing/component.rb +63 -23
  534. data/lib/datadog/tracing/configuration/dynamic/option.rb +4 -0
  535. data/lib/datadog/tracing/configuration/dynamic.rb +16 -16
  536. data/lib/datadog/tracing/configuration/ext.rb +62 -33
  537. data/lib/datadog/tracing/configuration/http.rb +2 -2
  538. data/lib/datadog/tracing/configuration/settings.rb +182 -34
  539. data/lib/datadog/tracing/context.rb +27 -5
  540. data/lib/datadog/tracing/context_provider.rb +12 -8
  541. data/lib/datadog/tracing/contrib/action_cable/configuration/settings.rb +2 -2
  542. data/lib/datadog/tracing/contrib/action_cable/event.rb +5 -5
  543. data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +9 -6
  544. data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +8 -5
  545. data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +9 -6
  546. data/lib/datadog/tracing/contrib/action_cable/events.rb +5 -5
  547. data/lib/datadog/tracing/contrib/action_cable/ext.rb +18 -18
  548. data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +8 -5
  549. data/lib/datadog/tracing/contrib/action_cable/integration.rb +10 -7
  550. data/lib/datadog/tracing/contrib/action_cable/patcher.rb +4 -4
  551. data/lib/datadog/tracing/contrib/action_mailer/configuration/settings.rb +2 -2
  552. data/lib/datadog/tracing/contrib/action_mailer/event.rb +7 -4
  553. data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +8 -8
  554. data/lib/datadog/tracing/contrib/action_mailer/events/process.rb +4 -4
  555. data/lib/datadog/tracing/contrib/action_mailer/events.rb +3 -3
  556. data/lib/datadog/tracing/contrib/action_mailer/ext.rb +18 -18
  557. data/lib/datadog/tracing/contrib/action_mailer/integration.rb +11 -7
  558. data/lib/datadog/tracing/contrib/action_mailer/patcher.rb +3 -3
  559. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +38 -20
  560. data/lib/datadog/tracing/contrib/action_pack/action_controller/patcher.rb +2 -2
  561. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +48 -13
  562. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +5 -3
  563. data/lib/datadog/tracing/contrib/action_pack/configuration/settings.rb +3 -3
  564. data/lib/datadog/tracing/contrib/action_pack/ext.rb +10 -8
  565. data/lib/datadog/tracing/contrib/action_pack/integration.rb +10 -7
  566. data/lib/datadog/tracing/contrib/action_pack/patcher.rb +3 -3
  567. data/lib/datadog/tracing/contrib/action_pack/utils.rb +2 -3
  568. data/lib/datadog/tracing/contrib/action_view/configuration/settings.rb +3 -3
  569. data/lib/datadog/tracing/contrib/action_view/event.rb +1 -1
  570. data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +10 -7
  571. data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +12 -9
  572. data/lib/datadog/tracing/contrib/action_view/events.rb +3 -3
  573. data/lib/datadog/tracing/contrib/action_view/ext.rb +10 -10
  574. data/lib/datadog/tracing/contrib/action_view/integration.rb +14 -11
  575. data/lib/datadog/tracing/contrib/action_view/patcher.rb +5 -5
  576. data/lib/datadog/tracing/contrib/action_view/utils.rb +2 -2
  577. data/lib/datadog/tracing/contrib/active_job/configuration/settings.rb +2 -2
  578. data/lib/datadog/tracing/contrib/active_job/data_streams.rb +62 -0
  579. data/lib/datadog/tracing/contrib/active_job/event.rb +11 -11
  580. data/lib/datadog/tracing/contrib/active_job/events/discard.rb +11 -8
  581. data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +11 -8
  582. data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +11 -8
  583. data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +11 -8
  584. data/lib/datadog/tracing/contrib/active_job/events/perform.rb +11 -8
  585. data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +11 -8
  586. data/lib/datadog/tracing/contrib/active_job/events.rb +6 -6
  587. data/lib/datadog/tracing/contrib/active_job/ext.rb +23 -23
  588. data/lib/datadog/tracing/contrib/active_job/integration.rb +10 -7
  589. data/lib/datadog/tracing/contrib/active_job/log_injection.rb +21 -7
  590. data/lib/datadog/tracing/contrib/active_job/patcher.rb +21 -5
  591. data/lib/datadog/tracing/contrib/active_model_serializers/configuration/settings.rb +2 -2
  592. data/lib/datadog/tracing/contrib/active_model_serializers/event.rb +4 -4
  593. data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +8 -8
  594. data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +9 -10
  595. data/lib/datadog/tracing/contrib/active_model_serializers/events.rb +3 -3
  596. data/lib/datadog/tracing/contrib/active_model_serializers/ext.rb +10 -10
  597. data/lib/datadog/tracing/contrib/active_model_serializers/integration.rb +5 -6
  598. data/lib/datadog/tracing/contrib/active_model_serializers/patcher.rb +3 -3
  599. data/lib/datadog/tracing/contrib/active_record/configuration/makara_resolver.rb +1 -1
  600. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +9 -9
  601. data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +4 -4
  602. data/lib/datadog/tracing/contrib/active_record/event.rb +1 -1
  603. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +10 -10
  604. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +17 -19
  605. data/lib/datadog/tracing/contrib/active_record/events.rb +3 -3
  606. data/lib/datadog/tracing/contrib/active_record/ext.rb +15 -15
  607. data/lib/datadog/tracing/contrib/active_record/integration.rb +16 -12
  608. data/lib/datadog/tracing/contrib/active_record/patcher.rb +2 -2
  609. data/lib/datadog/tracing/contrib/active_record/utils.rb +19 -19
  610. data/lib/datadog/tracing/contrib/active_support/cache/event.rb +1 -1
  611. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +29 -21
  612. data/lib/datadog/tracing/contrib/active_support/cache/events.rb +1 -1
  613. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +40 -8
  614. data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +8 -4
  615. data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +16 -6
  616. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +26 -3
  617. data/lib/datadog/tracing/contrib/active_support/ext.rb +16 -16
  618. data/lib/datadog/tracing/contrib/active_support/integration.rb +11 -8
  619. data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +3 -2
  620. data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +2 -2
  621. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +9 -11
  622. data/lib/datadog/tracing/contrib/active_support/patcher.rb +2 -2
  623. data/lib/datadog/tracing/contrib/analytics.rb +1 -1
  624. data/lib/datadog/tracing/contrib/auto_instrument.rb +5 -5
  625. data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +3 -3
  626. data/lib/datadog/tracing/contrib/aws/ext.rb +27 -27
  627. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +21 -13
  628. data/lib/datadog/tracing/contrib/aws/integration.rb +11 -8
  629. data/lib/datadog/tracing/contrib/aws/parsed_context.rb +9 -3
  630. data/lib/datadog/tracing/contrib/aws/patcher.rb +10 -6
  631. data/lib/datadog/tracing/contrib/aws/service/base.rb +2 -1
  632. data/lib/datadog/tracing/contrib/aws/service/dynamodb.rb +2 -2
  633. data/lib/datadog/tracing/contrib/aws/service/eventbridge.rb +2 -2
  634. data/lib/datadog/tracing/contrib/aws/service/kinesis.rb +4 -4
  635. data/lib/datadog/tracing/contrib/aws/service/s3.rb +2 -2
  636. data/lib/datadog/tracing/contrib/aws/service/sns.rb +3 -3
  637. data/lib/datadog/tracing/contrib/aws/service/sqs.rb +3 -3
  638. data/lib/datadog/tracing/contrib/aws/service/states.rb +5 -5
  639. data/lib/datadog/tracing/contrib/aws/services.rb +14 -14
  640. data/lib/datadog/tracing/contrib/component.rb +3 -3
  641. data/lib/datadog/tracing/contrib/concurrent_ruby/async_patch.rb +2 -2
  642. data/lib/datadog/tracing/contrib/concurrent_ruby/configuration/settings.rb +2 -2
  643. data/lib/datadog/tracing/contrib/concurrent_ruby/context_composite_executor_service.rb +2 -2
  644. data/lib/datadog/tracing/contrib/concurrent_ruby/ext.rb +2 -2
  645. data/lib/datadog/tracing/contrib/concurrent_ruby/future_patch.rb +2 -2
  646. data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +8 -5
  647. data/lib/datadog/tracing/contrib/concurrent_ruby/patcher.rb +4 -4
  648. data/lib/datadog/tracing/contrib/concurrent_ruby/promises_future_patch.rb +2 -2
  649. data/lib/datadog/tracing/contrib/configurable.rb +24 -9
  650. data/lib/datadog/tracing/contrib/configuration/resolver.rb +14 -4
  651. data/lib/datadog/tracing/contrib/configuration/resolvers/pattern_resolver.rb +5 -5
  652. data/lib/datadog/tracing/contrib/configuration/settings.rb +3 -3
  653. data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +2 -2
  654. data/lib/datadog/tracing/contrib/dalli/ext.rb +16 -15
  655. data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +6 -10
  656. data/lib/datadog/tracing/contrib/dalli/integration.rb +10 -7
  657. data/lib/datadog/tracing/contrib/dalli/patcher.rb +3 -3
  658. data/lib/datadog/tracing/contrib/dalli/quantize.rb +3 -3
  659. data/lib/datadog/tracing/contrib/delayed_job/configuration/settings.rb +2 -2
  660. data/lib/datadog/tracing/contrib/delayed_job/ext.rb +14 -14
  661. data/lib/datadog/tracing/contrib/delayed_job/integration.rb +5 -5
  662. data/lib/datadog/tracing/contrib/delayed_job/patcher.rb +3 -3
  663. data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +7 -5
  664. data/lib/datadog/tracing/contrib/delayed_job/server_internal_tracer/worker.rb +1 -0
  665. data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +6 -2
  666. data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +18 -17
  667. data/lib/datadog/tracing/contrib/elasticsearch/integration.rb +8 -8
  668. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +63 -64
  669. data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +9 -9
  670. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +7 -3
  671. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +19 -17
  672. data/lib/datadog/tracing/contrib/ethon/ext.rb +16 -14
  673. data/lib/datadog/tracing/contrib/ethon/integration.rb +6 -6
  674. data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +4 -11
  675. data/lib/datadog/tracing/contrib/ethon/patcher.rb +3 -3
  676. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +21 -10
  677. data/lib/datadog/tracing/contrib/excon/ext.rb +14 -12
  678. data/lib/datadog/tracing/contrib/excon/integration.rb +6 -6
  679. data/lib/datadog/tracing/contrib/excon/middleware.rb +18 -17
  680. data/lib/datadog/tracing/contrib/excon/patcher.rb +2 -2
  681. data/lib/datadog/tracing/contrib/ext.rb +23 -20
  682. data/lib/datadog/tracing/contrib/extensions.rb +57 -14
  683. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +20 -13
  684. data/lib/datadog/tracing/contrib/faraday/ext.rb +14 -12
  685. data/lib/datadog/tracing/contrib/faraday/integration.rb +6 -6
  686. data/lib/datadog/tracing/contrib/faraday/middleware.rb +20 -17
  687. data/lib/datadog/tracing/contrib/faraday/patcher.rb +6 -6
  688. data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +11 -7
  689. data/lib/datadog/tracing/contrib/grape/endpoint.rb +69 -36
  690. data/lib/datadog/tracing/contrib/grape/ext.rb +15 -15
  691. data/lib/datadog/tracing/contrib/grape/instrumentation.rb +15 -10
  692. data/lib/datadog/tracing/contrib/grape/integration.rb +5 -5
  693. data/lib/datadog/tracing/contrib/grape/patcher.rb +10 -5
  694. data/lib/datadog/tracing/contrib/graphql/configuration/error_extension_env_parser.rb +21 -0
  695. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +20 -2
  696. data/lib/datadog/tracing/contrib/graphql/ext.rb +11 -5
  697. data/lib/datadog/tracing/contrib/graphql/integration.rb +9 -9
  698. data/lib/datadog/tracing/contrib/graphql/patcher.rb +8 -8
  699. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +174 -41
  700. data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +2 -2
  701. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +7 -4
  702. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +26 -24
  703. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +14 -18
  704. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor.rb +6 -6
  705. data/lib/datadog/tracing/contrib/grpc/distributed/fetcher.rb +2 -2
  706. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +13 -8
  707. data/lib/datadog/tracing/contrib/grpc/ext.rb +14 -13
  708. data/lib/datadog/tracing/contrib/grpc/formatting.rb +7 -7
  709. data/lib/datadog/tracing/contrib/grpc/integration.rb +5 -5
  710. data/lib/datadog/tracing/contrib/grpc/intercept_with_datadog.rb +1 -1
  711. data/lib/datadog/tracing/contrib/grpc/patcher.rb +3 -3
  712. data/lib/datadog/tracing/contrib/grpc.rb +7 -6
  713. data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +4 -3
  714. data/lib/datadog/tracing/contrib/hanami/configuration/settings.rb +2 -2
  715. data/lib/datadog/tracing/contrib/hanami/ext.rb +8 -8
  716. data/lib/datadog/tracing/contrib/hanami/integration.rb +6 -6
  717. data/lib/datadog/tracing/contrib/hanami/patcher.rb +5 -5
  718. data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +5 -4
  719. data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +14 -14
  720. data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +1 -7
  721. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +20 -9
  722. data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +6 -6
  723. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +13 -8
  724. data/lib/datadog/tracing/contrib/http/ext.rb +14 -12
  725. data/lib/datadog/tracing/contrib/http/instrumentation.rb +20 -24
  726. data/lib/datadog/tracing/contrib/http/integration.rb +9 -8
  727. data/lib/datadog/tracing/contrib/http/patcher.rb +3 -3
  728. data/lib/datadog/tracing/contrib/http.rb +7 -6
  729. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +20 -9
  730. data/lib/datadog/tracing/contrib/httpclient/ext.rb +14 -12
  731. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +21 -27
  732. data/lib/datadog/tracing/contrib/httpclient/integration.rb +6 -6
  733. data/lib/datadog/tracing/contrib/httpclient/patcher.rb +3 -3
  734. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +20 -9
  735. data/lib/datadog/tracing/contrib/httprb/ext.rb +14 -12
  736. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +21 -29
  737. data/lib/datadog/tracing/contrib/httprb/integration.rb +9 -6
  738. data/lib/datadog/tracing/contrib/httprb/patcher.rb +3 -3
  739. data/lib/datadog/tracing/contrib/integration.rb +3 -3
  740. data/lib/datadog/tracing/contrib/kafka/configuration/settings.rb +2 -2
  741. data/lib/datadog/tracing/contrib/kafka/event.rb +5 -4
  742. data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +8 -4
  743. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +5 -5
  744. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +5 -5
  745. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +6 -6
  746. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/join_group.rb +6 -6
  747. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/leave_group.rb +6 -6
  748. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/sync_group.rb +6 -6
  749. data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +11 -6
  750. data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +11 -6
  751. data/lib/datadog/tracing/contrib/kafka/events.rb +10 -10
  752. data/lib/datadog/tracing/contrib/kafka/ext.rb +40 -40
  753. data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +66 -0
  754. data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +66 -0
  755. data/lib/datadog/tracing/contrib/kafka/integration.rb +8 -5
  756. data/lib/datadog/tracing/contrib/kafka/patcher.rb +17 -3
  757. data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +31 -0
  758. data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +50 -0
  759. data/lib/datadog/tracing/contrib/karafka/ext.rb +28 -0
  760. data/lib/datadog/tracing/contrib/karafka/framework.rb +30 -0
  761. data/lib/datadog/tracing/contrib/karafka/integration.rb +45 -0
  762. data/lib/datadog/tracing/contrib/karafka/monitor.rb +77 -0
  763. data/lib/datadog/tracing/contrib/karafka/patcher.rb +102 -0
  764. data/lib/datadog/tracing/contrib/karafka.rb +38 -0
  765. data/lib/datadog/tracing/contrib/lograge/configuration/settings.rb +2 -2
  766. data/lib/datadog/tracing/contrib/lograge/ext.rb +1 -1
  767. data/lib/datadog/tracing/contrib/lograge/instrumentation.rb +1 -1
  768. data/lib/datadog/tracing/contrib/lograge/integration.rb +5 -5
  769. data/lib/datadog/tracing/contrib/lograge/patcher.rb +13 -11
  770. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +11 -3
  771. data/lib/datadog/tracing/contrib/mongodb/ext.rb +19 -18
  772. data/lib/datadog/tracing/contrib/mongodb/instrumentation.rb +3 -3
  773. data/lib/datadog/tracing/contrib/mongodb/integration.rb +9 -6
  774. data/lib/datadog/tracing/contrib/mongodb/parsers.rb +10 -10
  775. data/lib/datadog/tracing/contrib/mongodb/patcher.rb +3 -3
  776. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +38 -24
  777. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +9 -3
  778. data/lib/datadog/tracing/contrib/mysql2/ext.rb +12 -12
  779. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +25 -18
  780. data/lib/datadog/tracing/contrib/mysql2/integration.rb +5 -5
  781. data/lib/datadog/tracing/contrib/mysql2/patcher.rb +2 -2
  782. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +19 -2
  783. data/lib/datadog/tracing/contrib/opensearch/ext.rb +31 -21
  784. data/lib/datadog/tracing/contrib/opensearch/integration.rb +8 -6
  785. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +75 -77
  786. data/lib/datadog/tracing/contrib/opensearch/quantize.rb +10 -10
  787. data/lib/datadog/tracing/contrib/patchable.rb +1 -1
  788. data/lib/datadog/tracing/contrib/patcher.rb +15 -14
  789. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +9 -3
  790. data/lib/datadog/tracing/contrib/pg/ext.rb +19 -19
  791. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +21 -24
  792. data/lib/datadog/tracing/contrib/pg/integration.rb +5 -5
  793. data/lib/datadog/tracing/contrib/pg/patcher.rb +2 -2
  794. data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +2 -2
  795. data/lib/datadog/tracing/contrib/presto/ext.rb +22 -22
  796. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +11 -13
  797. data/lib/datadog/tracing/contrib/presto/integration.rb +8 -5
  798. data/lib/datadog/tracing/contrib/presto/patcher.rb +4 -4
  799. data/lib/datadog/tracing/contrib/propagation/sql_comment/comment.rb +2 -2
  800. data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +26 -13
  801. data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +7 -3
  802. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +29 -5
  803. data/lib/datadog/tracing/contrib/que/configuration/settings.rb +7 -4
  804. data/lib/datadog/tracing/contrib/que/ext.rb +19 -18
  805. data/lib/datadog/tracing/contrib/que/integration.rb +6 -6
  806. data/lib/datadog/tracing/contrib/que/patcher.rb +1 -1
  807. data/lib/datadog/tracing/contrib/que/tracer.rb +3 -2
  808. data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +3 -3
  809. data/lib/datadog/tracing/contrib/racecar/event.rb +6 -10
  810. data/lib/datadog/tracing/contrib/racecar/events/batch.rb +5 -5
  811. data/lib/datadog/tracing/contrib/racecar/events/consume.rb +4 -4
  812. data/lib/datadog/tracing/contrib/racecar/events/message.rb +5 -5
  813. data/lib/datadog/tracing/contrib/racecar/events.rb +4 -4
  814. data/lib/datadog/tracing/contrib/racecar/ext.rb +18 -18
  815. data/lib/datadog/tracing/contrib/racecar/integration.rb +5 -5
  816. data/lib/datadog/tracing/contrib/racecar/patcher.rb +3 -3
  817. data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +14 -4
  818. data/lib/datadog/tracing/contrib/rack/ext.rb +43 -15
  819. data/lib/datadog/tracing/contrib/rack/header_collection.rb +13 -3
  820. data/lib/datadog/tracing/contrib/rack/header_tagging.rb +55 -32
  821. data/lib/datadog/tracing/contrib/rack/integration.rb +7 -7
  822. data/lib/datadog/tracing/contrib/rack/middlewares.rb +102 -63
  823. data/lib/datadog/tracing/contrib/rack/patcher.rb +6 -6
  824. data/lib/datadog/tracing/contrib/rack/request_queue.rb +8 -7
  825. data/lib/datadog/tracing/contrib/rack/route_inference.rb +67 -0
  826. data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +131 -7
  827. data/lib/datadog/tracing/contrib/rails/auto_instrument_railtie.rb +1 -1
  828. data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +9 -6
  829. data/lib/datadog/tracing/contrib/rails/ext.rb +16 -14
  830. data/lib/datadog/tracing/contrib/rails/framework.rb +12 -12
  831. data/lib/datadog/tracing/contrib/rails/integration.rb +6 -6
  832. data/lib/datadog/tracing/contrib/rails/log_injection.rb +2 -2
  833. data/lib/datadog/tracing/contrib/rails/middlewares.rb +4 -4
  834. data/lib/datadog/tracing/contrib/rails/patcher.rb +11 -9
  835. data/lib/datadog/tracing/contrib/rails/railtie.rb +4 -4
  836. data/lib/datadog/tracing/contrib/rails/runner.rb +64 -40
  837. data/lib/datadog/tracing/contrib/rake/configuration/settings.rb +3 -3
  838. data/lib/datadog/tracing/contrib/rake/ext.rb +12 -12
  839. data/lib/datadog/tracing/contrib/rake/instrumentation.rb +13 -11
  840. data/lib/datadog/tracing/contrib/rake/integration.rb +5 -5
  841. data/lib/datadog/tracing/contrib/rake/patcher.rb +3 -3
  842. data/lib/datadog/tracing/contrib/redis/configuration/resolver.rb +5 -5
  843. data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +2 -2
  844. data/lib/datadog/tracing/contrib/redis/ext.rb +19 -18
  845. data/lib/datadog/tracing/contrib/redis/instrumentation.rb +6 -6
  846. data/lib/datadog/tracing/contrib/redis/integration.rb +7 -7
  847. data/lib/datadog/tracing/contrib/redis/patcher.rb +12 -12
  848. data/lib/datadog/tracing/contrib/redis/quantize.rb +41 -7
  849. data/lib/datadog/tracing/contrib/redis/tags.rb +7 -12
  850. data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +20 -12
  851. data/lib/datadog/tracing/contrib/registerable.rb +11 -0
  852. data/lib/datadog/tracing/contrib/registry.rb +1 -1
  853. data/lib/datadog/tracing/contrib/resque/configuration/settings.rb +2 -2
  854. data/lib/datadog/tracing/contrib/resque/ext.rb +7 -7
  855. data/lib/datadog/tracing/contrib/resque/integration.rb +5 -5
  856. data/lib/datadog/tracing/contrib/resque/patcher.rb +3 -3
  857. data/lib/datadog/tracing/contrib/resque/resque_job.rb +7 -6
  858. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +7 -4
  859. data/lib/datadog/tracing/contrib/rest_client/ext.rb +13 -11
  860. data/lib/datadog/tracing/contrib/rest_client/integration.rb +8 -5
  861. data/lib/datadog/tracing/contrib/rest_client/patcher.rb +2 -2
  862. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +19 -15
  863. data/lib/datadog/tracing/contrib/roda/configuration/settings.rb +2 -2
  864. data/lib/datadog/tracing/contrib/roda/ext.rb +6 -5
  865. data/lib/datadog/tracing/contrib/roda/instrumentation.rb +12 -7
  866. data/lib/datadog/tracing/contrib/roda/integration.rb +6 -6
  867. data/lib/datadog/tracing/contrib/roda/patcher.rb +3 -3
  868. data/lib/datadog/tracing/contrib/semantic_logger/configuration/settings.rb +2 -2
  869. data/lib/datadog/tracing/contrib/semantic_logger/ext.rb +1 -1
  870. data/lib/datadog/tracing/contrib/semantic_logger/instrumentation.rb +1 -1
  871. data/lib/datadog/tracing/contrib/semantic_logger/integration.rb +5 -5
  872. data/lib/datadog/tracing/contrib/semantic_logger/patcher.rb +2 -2
  873. data/lib/datadog/tracing/contrib/sequel/configuration/settings.rb +2 -2
  874. data/lib/datadog/tracing/contrib/sequel/database.rb +8 -11
  875. data/lib/datadog/tracing/contrib/sequel/dataset.rb +7 -6
  876. data/lib/datadog/tracing/contrib/sequel/ext.rb +12 -8
  877. data/lib/datadog/tracing/contrib/sequel/integration.rb +5 -5
  878. data/lib/datadog/tracing/contrib/sequel/jdbc_connection_string.rb +140 -0
  879. data/lib/datadog/tracing/contrib/sequel/patcher.rb +3 -3
  880. data/lib/datadog/tracing/contrib/sequel/utils.rb +103 -16
  881. data/lib/datadog/tracing/contrib/shoryuken/configuration/settings.rb +2 -2
  882. data/lib/datadog/tracing/contrib/shoryuken/ext.rb +12 -12
  883. data/lib/datadog/tracing/contrib/shoryuken/integration.rb +6 -6
  884. data/lib/datadog/tracing/contrib/shoryuken/patcher.rb +1 -1
  885. data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +3 -2
  886. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +15 -9
  887. data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +7 -3
  888. data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +14 -9
  889. data/lib/datadog/tracing/contrib/sidekiq/ext.rb +31 -29
  890. data/lib/datadog/tracing/contrib/sidekiq/integration.rb +7 -7
  891. data/lib/datadog/tracing/contrib/sidekiq/patcher.rb +8 -8
  892. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/heartbeat.rb +2 -0
  893. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/job_fetch.rb +1 -0
  894. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/redis_info.rb +1 -0
  895. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/scheduled_poller.rb +2 -0
  896. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/stop.rb +1 -0
  897. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +19 -15
  898. data/lib/datadog/tracing/contrib/sidekiq/utils.rb +10 -10
  899. data/lib/datadog/tracing/contrib/sidekiq.rb +7 -6
  900. data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +8 -4
  901. data/lib/datadog/tracing/contrib/sinatra/env.rb +6 -6
  902. data/lib/datadog/tracing/contrib/sinatra/ext.rb +17 -16
  903. data/lib/datadog/tracing/contrib/sinatra/framework.rb +2 -2
  904. data/lib/datadog/tracing/contrib/sinatra/integration.rb +5 -5
  905. data/lib/datadog/tracing/contrib/sinatra/patcher.rb +5 -5
  906. data/lib/datadog/tracing/contrib/sinatra/tracer.rb +11 -10
  907. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +46 -45
  908. data/lib/datadog/tracing/contrib/sneakers/configuration/settings.rb +1 -1
  909. data/lib/datadog/tracing/contrib/sneakers/ext.rb +12 -12
  910. data/lib/datadog/tracing/contrib/sneakers/integration.rb +19 -8
  911. data/lib/datadog/tracing/contrib/sneakers/patcher.rb +2 -2
  912. data/lib/datadog/tracing/contrib/sneakers/tracer.rb +5 -4
  913. data/lib/datadog/tracing/contrib/span_attribute_schema.rb +9 -4
  914. data/lib/datadog/tracing/contrib/status_range_env_parser.rb +2 -2
  915. data/lib/datadog/tracing/contrib/status_range_matcher.rb +13 -1
  916. data/lib/datadog/tracing/contrib/stripe/configuration/settings.rb +2 -2
  917. data/lib/datadog/tracing/contrib/stripe/ext.rb +12 -12
  918. data/lib/datadog/tracing/contrib/stripe/integration.rb +5 -5
  919. data/lib/datadog/tracing/contrib/stripe/patcher.rb +2 -2
  920. data/lib/datadog/tracing/contrib/stripe/request.rb +5 -5
  921. data/lib/datadog/tracing/contrib/sucker_punch/configuration/settings.rb +2 -2
  922. data/lib/datadog/tracing/contrib/sucker_punch/exception_handler.rb +1 -1
  923. data/lib/datadog/tracing/contrib/sucker_punch/ext.rb +13 -13
  924. data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +5 -4
  925. data/lib/datadog/tracing/contrib/sucker_punch/integration.rb +5 -5
  926. data/lib/datadog/tracing/contrib/sucker_punch/patcher.rb +4 -4
  927. data/lib/datadog/tracing/contrib/support.rb +28 -0
  928. data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +9 -3
  929. data/lib/datadog/tracing/contrib/trilogy/ext.rb +12 -12
  930. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +10 -12
  931. data/lib/datadog/tracing/contrib/trilogy/integration.rb +5 -5
  932. data/lib/datadog/tracing/contrib/trilogy/patcher.rb +2 -2
  933. data/lib/datadog/tracing/contrib/utils/database.rb +5 -5
  934. data/lib/datadog/tracing/contrib/utils/quantization/{hash.rb → hash_formatter.rb} +17 -15
  935. data/lib/datadog/tracing/contrib/utils/quantization/http.rb +16 -16
  936. data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +31 -0
  937. data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +50 -0
  938. data/lib/datadog/tracing/contrib/waterdrop/ext.rb +18 -0
  939. data/lib/datadog/tracing/contrib/waterdrop/integration.rb +43 -0
  940. data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +46 -0
  941. data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +49 -0
  942. data/lib/datadog/tracing/contrib/waterdrop/producer.rb +50 -0
  943. data/lib/datadog/tracing/contrib/waterdrop.rb +42 -0
  944. data/lib/datadog/tracing/contrib.rb +62 -52
  945. data/lib/datadog/tracing/correlation.rb +21 -14
  946. data/lib/datadog/tracing/diagnostics/environment_logger.rb +23 -15
  947. data/lib/datadog/tracing/diagnostics/ext.rb +19 -19
  948. data/lib/datadog/tracing/diagnostics/health.rb +1 -1
  949. data/lib/datadog/tracing/distributed/b3_multi.rb +9 -9
  950. data/lib/datadog/tracing/distributed/b3_single.rb +6 -6
  951. data/lib/datadog/tracing/distributed/baggage.rb +250 -0
  952. data/lib/datadog/tracing/distributed/datadog.rb +41 -38
  953. data/lib/datadog/tracing/distributed/fetcher.rb +1 -1
  954. data/lib/datadog/tracing/distributed/helpers.rb +4 -4
  955. data/lib/datadog/tracing/distributed/none.rb +4 -2
  956. data/lib/datadog/tracing/distributed/propagation.rb +73 -14
  957. data/lib/datadog/tracing/distributed/propagation_policy.rb +47 -0
  958. data/lib/datadog/tracing/distributed/trace_context.rb +31 -259
  959. data/lib/datadog/tracing/distributed/trace_state/datadog.rb +233 -0
  960. data/lib/datadog/tracing/distributed/trace_state/ext.rb +44 -0
  961. data/lib/datadog/tracing/distributed/trace_state/open_telemetry.rb +156 -0
  962. data/lib/datadog/tracing/distributed/trace_state.rb +121 -0
  963. data/lib/datadog/tracing/event.rb +6 -8
  964. data/lib/datadog/tracing/ext.rb +9 -0
  965. data/lib/datadog/tracing/flush.rb +1 -1
  966. data/lib/datadog/tracing/metadata/analytics.rb +3 -3
  967. data/lib/datadog/tracing/metadata/errors.rb +8 -8
  968. data/lib/datadog/tracing/metadata/ext.rb +89 -59
  969. data/lib/datadog/tracing/metadata/metastruct.rb +36 -0
  970. data/lib/datadog/tracing/metadata/metastruct_tagging.rb +42 -0
  971. data/lib/datadog/tracing/metadata/tagging.rb +9 -9
  972. data/lib/datadog/tracing/metadata.rb +5 -3
  973. data/lib/datadog/tracing/otel_thread_context.rb +99 -0
  974. data/lib/datadog/tracing/pipeline/span_filter.rb +5 -3
  975. data/lib/datadog/tracing/pipeline/span_processor.rb +3 -1
  976. data/lib/datadog/tracing/pipeline.rb +4 -4
  977. data/lib/datadog/tracing/remote.rb +228 -30
  978. data/lib/datadog/tracing/sampling/all_sampler.rb +1 -1
  979. data/lib/datadog/tracing/sampling/ext.rb +9 -9
  980. data/lib/datadog/tracing/sampling/matcher.rb +4 -4
  981. data/lib/datadog/tracing/sampling/priority_sampler.rb +20 -5
  982. data/lib/datadog/tracing/sampling/rate_by_key_sampler.rb +3 -3
  983. data/lib/datadog/tracing/sampling/rate_by_service_sampler.rb +2 -2
  984. data/lib/datadog/tracing/sampling/rate_sampler.rb +9 -19
  985. data/lib/datadog/tracing/sampling/rule.rb +5 -5
  986. data/lib/datadog/tracing/sampling/rule_sampler.rb +91 -58
  987. data/lib/datadog/tracing/sampling/sampler.rb +2 -2
  988. data/lib/datadog/tracing/sampling/span/ext.rb +3 -3
  989. data/lib/datadog/tracing/sampling/span/matcher.rb +2 -2
  990. data/lib/datadog/tracing/sampling/span/rule.rb +1 -2
  991. data/lib/datadog/tracing/sampling/span/rule_parser.rb +11 -11
  992. data/lib/datadog/tracing/sampling/span/sampler.rb +0 -7
  993. data/lib/datadog/tracing/span.rb +29 -12
  994. data/lib/datadog/tracing/span_event.rb +125 -5
  995. data/lib/datadog/tracing/span_link.rb +12 -12
  996. data/lib/datadog/tracing/span_operation.rb +120 -40
  997. data/lib/datadog/tracing/sync_writer.rb +22 -14
  998. data/lib/datadog/tracing/trace_digest.rb +58 -28
  999. data/lib/datadog/tracing/trace_operation.rb +263 -120
  1000. data/lib/datadog/tracing/trace_segment.rb +18 -16
  1001. data/lib/datadog/tracing/tracer.rb +208 -73
  1002. data/lib/datadog/tracing/transport/http/client.rb +17 -30
  1003. data/lib/datadog/tracing/transport/http/statistics.rb +2 -2
  1004. data/lib/datadog/tracing/transport/http/traces.rb +11 -90
  1005. data/lib/datadog/tracing/transport/http.rb +26 -73
  1006. data/lib/datadog/tracing/transport/io/client.rb +13 -16
  1007. data/lib/datadog/tracing/transport/io/response.rb +1 -1
  1008. data/lib/datadog/tracing/transport/io/traces.rb +33 -39
  1009. data/lib/datadog/tracing/transport/io.rb +3 -3
  1010. data/lib/datadog/tracing/transport/native/response.rb +71 -0
  1011. data/lib/datadog/tracing/transport/native.rb +379 -0
  1012. data/lib/datadog/tracing/transport/serializable_trace.rb +47 -23
  1013. data/lib/datadog/tracing/transport/span_events_negotiation.rb +41 -0
  1014. data/lib/datadog/tracing/transport/statistics.rb +3 -3
  1015. data/lib/datadog/tracing/transport/trace_formatter.rb +49 -10
  1016. data/lib/datadog/tracing/transport/traces.rb +45 -99
  1017. data/lib/datadog/tracing/utils.rb +3 -3
  1018. data/lib/datadog/tracing/workers.rb +12 -10
  1019. data/lib/datadog/tracing/writer.rb +54 -39
  1020. data/lib/datadog/tracing.rb +19 -6
  1021. data/lib/datadog/version.rb +4 -4
  1022. data/lib/datadog.rb +21 -5
  1023. metadata +372 -70
  1024. data/ext/datadog_profiling_loader/datadog_profiling_loader.c +0 -142
  1025. data/ext/datadog_profiling_loader/extconf.rb +0 -60
  1026. data/ext/datadog_profiling_native_extension/clock_id_noop.c +0 -21
  1027. data/ext/libdatadog_api/macos_development.md +0 -26
  1028. data/lib/datadog/appsec/assets/waf_rules/processors.json +0 -92
  1029. data/lib/datadog/appsec/assets/waf_rules/scanners.json +0 -114
  1030. data/lib/datadog/appsec/configuration/settings.rb +0 -207
  1031. data/lib/datadog/appsec/contrib/devise/event.rb +0 -57
  1032. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +0 -77
  1033. data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +0 -54
  1034. data/lib/datadog/appsec/contrib/devise/resource.rb +0 -35
  1035. data/lib/datadog/appsec/contrib/devise/tracking.rb +0 -57
  1036. data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +0 -59
  1037. data/lib/datadog/appsec/contrib/patcher.rb +0 -12
  1038. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +0 -81
  1039. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +0 -60
  1040. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +0 -66
  1041. data/lib/datadog/appsec/contrib/rails/ext.rb +0 -13
  1042. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +0 -66
  1043. data/lib/datadog/appsec/contrib/sinatra/ext.rb +0 -14
  1044. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +0 -61
  1045. data/lib/datadog/appsec/monitor/reactive/set_user.rb +0 -58
  1046. data/lib/datadog/appsec/processor/actions.rb +0 -49
  1047. data/lib/datadog/appsec/processor/rule_merger.rb +0 -170
  1048. data/lib/datadog/appsec/processor.rb +0 -170
  1049. data/lib/datadog/appsec/reactive/address_hash.rb +0 -22
  1050. data/lib/datadog/appsec/reactive/engine.rb +0 -47
  1051. data/lib/datadog/appsec/reactive/operation.rb +0 -68
  1052. data/lib/datadog/appsec/reactive/subscriber.rb +0 -19
  1053. data/lib/datadog/appsec/scope.rb +0 -61
  1054. data/lib/datadog/core/crashtracking/agent_base_url.rb +0 -21
  1055. data/lib/datadog/core/remote/transport/http/api/instance.rb +0 -39
  1056. data/lib/datadog/core/remote/transport/http/api/spec.rb +0 -21
  1057. data/lib/datadog/core/remote/transport/http/api.rb +0 -58
  1058. data/lib/datadog/core/remote/transport/http/builder.rb +0 -219
  1059. data/lib/datadog/core/remote/transport/http/client.rb +0 -48
  1060. data/lib/datadog/core/telemetry/http/env.rb +0 -20
  1061. data/lib/datadog/core/telemetry/http/ext.rb +0 -28
  1062. data/lib/datadog/core/telemetry/http/response.rb +0 -70
  1063. data/lib/datadog/core/telemetry/http/transport.rb +0 -90
  1064. data/lib/datadog/core/utils/base64.rb +0 -22
  1065. data/lib/datadog/di/configuration/settings.rb +0 -163
  1066. data/lib/datadog/tracing/contrib/rails/utils.rb +0 -26
  1067. data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +0 -84
  1068. data/lib/datadog/tracing/transport/http/api/spec.rb +0 -19
  1069. data/lib/datadog/tracing/transport/http/api.rb +0 -43
  1070. data/lib/datadog/tracing/workers/trace_writer.rb +0 -196
@@ -8,6 +8,8 @@
8
8
  #include "ruby_helpers.h"
9
9
  #include "time_helpers.h"
10
10
  #include "heap_recorder.h"
11
+ #include "encoded_profile.h"
12
+ #include "collectors_thread_context.h"
11
13
 
12
14
  // Used to wrap a ddog_prof_Profile in a Ruby object and expose Ruby-level serialization APIs
13
15
  // This file implements the native bits of the Datadog::Profiling::StackRecorder class
@@ -130,69 +132,65 @@
130
132
  static VALUE ok_symbol = Qnil; // :ok in Ruby
131
133
  static VALUE error_symbol = Qnil; // :error in Ruby
132
134
 
133
- // Note: Please DO NOT use `VALUE_STRING` anywhere else, instead use `DDOG_CHARSLICE_C`.
134
- // `VALUE_STRING` is only needed because older versions of gcc (4.9.2, used in our Ruby 2.2 CI test images)
135
- // tripped when compiling `enabled_value_types` using `-std=gnu99` due to the extra cast that is included in
136
- // `DDOG_CHARSLICE_C` with the following error:
137
- //
138
- // ```
139
- // compiling ../../../../ext/ddtrace_profiling_native_extension/stack_recorder.c
140
- // ../../../../ext/ddtrace_profiling_native_extension/stack_recorder.c:23:1: error: initializer element is not constant
141
- // static const ddog_prof_ValueType enabled_value_types[] = {CPU_TIME_VALUE, CPU_SAMPLES_VALUE, WALL_TIME_VALUE};
142
- // ^
143
- // ```
144
- #define VALUE_STRING(string) {.ptr = "" string, .len = sizeof(string) - 1}
145
-
146
- #define CPU_TIME_VALUE {.type_ = VALUE_STRING("cpu-time"), .unit = VALUE_STRING("nanoseconds")}
147
135
  #define CPU_TIME_VALUE_ID 0
148
- #define CPU_SAMPLES_VALUE {.type_ = VALUE_STRING("cpu-samples"), .unit = VALUE_STRING("count")}
149
136
  #define CPU_SAMPLES_VALUE_ID 1
150
- #define WALL_TIME_VALUE {.type_ = VALUE_STRING("wall-time"), .unit = VALUE_STRING("nanoseconds")}
151
137
  #define WALL_TIME_VALUE_ID 2
152
- #define ALLOC_SAMPLES_VALUE {.type_ = VALUE_STRING("alloc-samples"), .unit = VALUE_STRING("count")}
153
138
  #define ALLOC_SAMPLES_VALUE_ID 3
154
- #define ALLOC_SAMPLES_UNSCALED_VALUE {.type_ = VALUE_STRING("alloc-samples-unscaled"), .unit = VALUE_STRING("count")}
155
139
  #define ALLOC_SAMPLES_UNSCALED_VALUE_ID 4
156
- #define HEAP_SAMPLES_VALUE {.type_ = VALUE_STRING("heap-live-samples"), .unit = VALUE_STRING("count")}
157
140
  #define HEAP_SAMPLES_VALUE_ID 5
158
- #define HEAP_SIZE_VALUE {.type_ = VALUE_STRING("heap-live-size"), .unit = VALUE_STRING("bytes")}
159
141
  #define HEAP_SIZE_VALUE_ID 6
160
- #define TIMELINE_VALUE {.type_ = VALUE_STRING("timeline"), .unit = VALUE_STRING("nanoseconds")}
161
142
  #define TIMELINE_VALUE_ID 7
162
143
 
163
- static const ddog_prof_ValueType all_value_types[] =
164
- {CPU_TIME_VALUE, CPU_SAMPLES_VALUE, WALL_TIME_VALUE, ALLOC_SAMPLES_VALUE, ALLOC_SAMPLES_UNSCALED_VALUE, HEAP_SAMPLES_VALUE, HEAP_SIZE_VALUE, TIMELINE_VALUE};
144
+ static const ddog_prof_SampleType all_sample_types[] = {
145
+ DDOG_PROF_SAMPLE_TYPE_CPU_TIME,
146
+ DDOG_PROF_SAMPLE_TYPE_CPU_SAMPLES,
147
+ DDOG_PROF_SAMPLE_TYPE_WALL_TIME,
148
+ DDOG_PROF_SAMPLE_TYPE_ALLOC_SAMPLES,
149
+ DDOG_PROF_SAMPLE_TYPE_ALLOC_SAMPLES_UNSCALED,
150
+ DDOG_PROF_SAMPLE_TYPE_HEAP_LIVE_SAMPLES,
151
+ DDOG_PROF_SAMPLE_TYPE_HEAP_LIVE_SIZE,
152
+ DDOG_PROF_SAMPLE_TYPE_TIMELINE,
153
+ };
165
154
 
166
- // This array MUST be kept in sync with all_value_types above and is intended to act as a "hashmap" between VALUE_ID and the position it
167
- // occupies on the all_value_types array.
168
- // E.g. all_value_types_positions[CPU_TIME_VALUE_ID] => 0, means that CPU_TIME_VALUE was declared at position 0 of all_value_types.
155
+ // This array MUST be kept in sync with all_sample_types above and is intended to act as a "hashmap" between VALUE_ID and the position it
156
+ // occupies on the all_sample_types array.
169
157
  static const uint8_t all_value_types_positions[] =
170
158
  {CPU_TIME_VALUE_ID, CPU_SAMPLES_VALUE_ID, WALL_TIME_VALUE_ID, ALLOC_SAMPLES_VALUE_ID, ALLOC_SAMPLES_UNSCALED_VALUE_ID, HEAP_SAMPLES_VALUE_ID, HEAP_SIZE_VALUE_ID, TIMELINE_VALUE_ID};
171
159
 
172
- #define ALL_VALUE_TYPES_COUNT (sizeof(all_value_types) / sizeof(ddog_prof_ValueType))
160
+ #define ALL_VALUE_TYPES_COUNT (sizeof(all_sample_types) / sizeof(ddog_prof_SampleType))
173
161
 
174
162
  // Struct for storing stats related to a profile in a particular slot.
175
163
  // These stats will share the same lifetime as the data in that profile slot.
176
- typedef struct slot_stats {
164
+ typedef struct {
177
165
  // How many individual samples were recorded into this slot (un-weighted)
178
166
  uint64_t recorded_samples;
179
167
  } stats_slot;
180
168
 
181
- typedef struct profile_slot {
169
+ typedef struct {
182
170
  ddog_prof_Profile profile;
183
171
  stats_slot stats;
172
+ ddog_Timespec start_timestamp;
184
173
  } profile_slot;
185
174
 
186
175
  // Contains native state for each instance
187
- struct stack_recorder_state {
176
+ typedef struct {
188
177
  // Heap recorder instance
189
178
  heap_recorder *heap_recorder;
179
+ bool heap_clean_after_gc_enabled;
180
+
181
+ // When set, _native_serialize will call thread_context_collector_on_serialize on this instance
182
+ // before serializing, so that threads suspended across the whole profile period still get sampled.
183
+ VALUE thread_context_collector_instance;
190
184
 
191
185
  pthread_mutex_t mutex_slot_one;
192
186
  profile_slot profile_slot_one;
193
187
  pthread_mutex_t mutex_slot_two;
194
188
  profile_slot profile_slot_two;
195
189
 
190
+ ddog_prof_ManagedStringStorage string_storage;
191
+ ddog_prof_ManagedStringId label_key_allocation_class;
192
+ ddog_prof_ManagedStringId label_key_gc_gen_age;
193
+
196
194
  short active_slot; // MUST NEVER BE ACCESSED FROM record_sample; this is NOT for the sampler thread to use.
197
195
 
198
196
  uint8_t position_for[ALL_VALUE_TYPES_COUNT];
@@ -209,17 +207,17 @@ struct stack_recorder_state {
209
207
  long serialization_time_ns_max;
210
208
  uint64_t serialization_time_ns_total;
211
209
  } stats_lifetime;
212
- };
210
+ } stack_recorder_state;
213
211
 
214
212
  // Used to group mutex and the corresponding profile slot for easy unlocking after work is done.
215
- typedef struct locked_profile_slot {
213
+ typedef struct {
216
214
  pthread_mutex_t *mutex;
217
215
  profile_slot *data;
218
216
  } locked_profile_slot;
219
217
 
220
- struct call_serialize_without_gvl_arguments {
218
+ typedef struct {
221
219
  // Set by caller
222
- struct stack_recorder_state *state;
220
+ stack_recorder_state *state;
223
221
  ddog_Timespec finish_timestamp;
224
222
 
225
223
  // Set by callee
@@ -227,50 +225,61 @@ struct call_serialize_without_gvl_arguments {
227
225
  ddog_prof_Profile_SerializeResult result;
228
226
  long heap_profile_build_time_ns;
229
227
  long serialize_no_gvl_time_ns;
228
+ ddog_prof_MaybeError advance_gen_result;
230
229
 
231
230
  // Set by both
232
231
  bool serialize_ran;
233
- };
232
+ } call_serialize_without_gvl_arguments;
233
+
234
+ typedef struct {
235
+ // Set by caller
236
+ stack_recorder_state *state;
237
+ locked_profile_slot active_slot;
238
+ ddog_prof_Slice_Location locations;
239
+ sample_values values;
240
+ sample_labels labels;
241
+
242
+ // Set by callee
243
+ ddog_prof_Profile_Result result;
244
+ } record_sample_arguments;
234
245
 
235
246
  static VALUE _native_new(VALUE klass);
236
- static void initialize_slot_concurrency_control(struct stack_recorder_state *state);
237
- static void initialize_profiles(struct stack_recorder_state *state, ddog_prof_Slice_ValueType sample_types);
247
+ static void initialize_slot_concurrency_control(stack_recorder_state *state);
248
+ static void stack_recorder_typed_data_mark(void *data);
249
+ static void initialize_profiles(stack_recorder_state *state, ddog_prof_Slice_SampleType sample_types);
238
250
  static void stack_recorder_typed_data_free(void *data);
239
- static VALUE _native_initialize(
240
- DDTRACE_UNUSED VALUE _self,
241
- VALUE recorder_instance,
242
- VALUE cpu_time_enabled,
243
- VALUE alloc_samples_enabled,
244
- VALUE heap_samples_enabled,
245
- VALUE heap_size_enabled,
246
- VALUE heap_sample_every,
247
- VALUE timeline_enabled
248
- );
251
+ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self);
249
252
  static VALUE _native_serialize(VALUE self, VALUE recorder_instance);
250
253
  static VALUE ruby_time_from(ddog_Timespec ddprof_time);
251
254
  static void *call_serialize_without_gvl(void *call_args);
252
- static locked_profile_slot sampler_lock_active_profile(struct stack_recorder_state *state);
255
+ static VALUE record_sample_locked(VALUE record_sample_arguments_as_value);
256
+ static VALUE record_sample_unlock_ensure(VALUE record_sample_arguments_as_value);
257
+ static locked_profile_slot sampler_lock_active_profile(stack_recorder_state *state);
253
258
  static void sampler_unlock_active_profile(locked_profile_slot active_slot);
254
- static profile_slot* serializer_flip_active_and_inactive_slots(struct stack_recorder_state *state);
259
+ static profile_slot* serializer_flip_active_and_inactive_slots(stack_recorder_state *state);
255
260
  static VALUE _native_active_slot(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
256
261
  static VALUE _native_is_slot_one_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
257
262
  static VALUE _native_is_slot_two_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
258
263
  static VALUE test_slot_mutex_state(VALUE recorder_instance, int slot);
259
264
  static ddog_Timespec system_epoch_now_timespec(void);
260
265
  static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE recorder_instance);
261
- static void serializer_set_start_timestamp_for_next_profile(struct stack_recorder_state *state, ddog_Timespec start_time);
266
+ static void serializer_set_start_timestamp_for_next_profile(stack_recorder_state *state, ddog_Timespec start_time);
262
267
  static VALUE _native_record_endpoint(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE local_root_span_id, VALUE endpoint);
263
- static void reset_profile_slot(profile_slot *slot, ddog_Timespec *start_time /* Can be null */);
264
- static VALUE _native_track_object(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE new_obj, VALUE weight, VALUE alloc_class);
265
- static VALUE _native_check_heap_hashes(DDTRACE_UNUSED VALUE _self, VALUE locations);
268
+ static void reset_profile_slot(profile_slot *slot, ddog_Timespec start_timestamp);
266
269
  static VALUE _native_start_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
267
270
  static VALUE _native_end_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
268
271
  static VALUE _native_debug_heap_recorder(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
269
- static VALUE _native_gc_force_recycle(DDTRACE_UNUSED VALUE _self, VALUE obj);
270
- static VALUE _native_has_seen_id_flag(DDTRACE_UNUSED VALUE _self, VALUE obj);
271
272
  static VALUE _native_stats(DDTRACE_UNUSED VALUE self, VALUE instance);
272
273
  static VALUE build_profile_stats(profile_slot *slot, long serialization_time_ns, long heap_iteration_prep_time_ns, long heap_profile_build_time_ns);
273
-
274
+ static VALUE _native_is_object_recorded(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE record_id);
275
+ static VALUE _native_record_id_for(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE obj);
276
+ static VALUE _native_heap_recorder_reset_last_update(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
277
+ static VALUE _native_heap_recorder_exhaust_record_ids(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
278
+ static VALUE _native_heap_recorder_set_object_alloc_gen(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE record_id, VALUE alloc_gen);
279
+ static VALUE _native_recorder_heap_update(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
280
+ static VALUE _native_benchmark_intern(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE string, VALUE times, VALUE use_all);
281
+ static VALUE _native_test_managed_string_storage_produces_valid_profiles(DDTRACE_UNUSED VALUE _self);
282
+ static VALUE _native_commit_heap_recordings(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
274
283
 
275
284
  void stack_recorder_init(VALUE profiling_module) {
276
285
  VALUE stack_recorder_class = rb_define_class_under(profiling_module, "StackRecorder", rb_cObject);
@@ -287,7 +296,7 @@ void stack_recorder_init(VALUE profiling_module) {
287
296
  // https://bugs.ruby-lang.org/issues/18007 for a discussion around this.
288
297
  rb_define_alloc_func(stack_recorder_class, _native_new);
289
298
 
290
- rb_define_singleton_method(stack_recorder_class, "_native_initialize", _native_initialize, 7);
299
+ rb_define_singleton_method(stack_recorder_class, "_native_initialize", _native_initialize, -1);
291
300
  rb_define_singleton_method(stack_recorder_class, "_native_serialize", _native_serialize, 1);
292
301
  rb_define_singleton_method(stack_recorder_class, "_native_reset_after_fork", _native_reset_after_fork, 1);
293
302
  rb_define_singleton_method(stack_recorder_class, "_native_stats", _native_stats, 1);
@@ -295,18 +304,21 @@ void stack_recorder_init(VALUE profiling_module) {
295
304
  rb_define_singleton_method(testing_module, "_native_slot_one_mutex_locked?", _native_is_slot_one_mutex_locked, 1);
296
305
  rb_define_singleton_method(testing_module, "_native_slot_two_mutex_locked?", _native_is_slot_two_mutex_locked, 1);
297
306
  rb_define_singleton_method(testing_module, "_native_record_endpoint", _native_record_endpoint, 3);
298
- rb_define_singleton_method(testing_module, "_native_track_object", _native_track_object, 4);
299
- rb_define_singleton_method(testing_module, "_native_check_heap_hashes", _native_check_heap_hashes, 1);
300
307
  rb_define_singleton_method(testing_module, "_native_start_fake_slow_heap_serialization",
301
308
  _native_start_fake_slow_heap_serialization, 1);
302
309
  rb_define_singleton_method(testing_module, "_native_end_fake_slow_heap_serialization",
303
310
  _native_end_fake_slow_heap_serialization, 1);
304
311
  rb_define_singleton_method(testing_module, "_native_debug_heap_recorder",
305
312
  _native_debug_heap_recorder, 1);
306
- rb_define_singleton_method(testing_module, "_native_gc_force_recycle",
307
- _native_gc_force_recycle, 1);
308
- rb_define_singleton_method(testing_module, "_native_has_seen_id_flag",
309
- _native_has_seen_id_flag, 1);
313
+ rb_define_singleton_method(testing_module, "_native_is_object_recorded?", _native_is_object_recorded, 2);
314
+ rb_define_singleton_method(testing_module, "_native_record_id_for", _native_record_id_for, 2);
315
+ rb_define_singleton_method(testing_module, "_native_heap_recorder_reset_last_update", _native_heap_recorder_reset_last_update, 1);
316
+ rb_define_singleton_method(testing_module, "_native_heap_recorder_exhaust_record_ids", _native_heap_recorder_exhaust_record_ids, 1);
317
+ rb_define_singleton_method(testing_module, "_native_heap_recorder_set_object_alloc_gen", _native_heap_recorder_set_object_alloc_gen, 3);
318
+ rb_define_singleton_method(testing_module, "_native_recorder_heap_update", _native_recorder_heap_update, 1);
319
+ rb_define_singleton_method(testing_module, "_native_benchmark_intern", _native_benchmark_intern, 4);
320
+ rb_define_singleton_method(testing_module, "_native_test_managed_string_storage_produces_valid_profiles", _native_test_managed_string_storage_produces_valid_profiles, 0);
321
+ rb_define_singleton_method(testing_module, "_native_commit_heap_recordings", _native_commit_heap_recordings, 1);
310
322
 
311
323
  ok_symbol = ID2SYM(rb_intern_const("ok"));
312
324
  error_symbol = ID2SYM(rb_intern_const("error"));
@@ -317,20 +329,23 @@ void stack_recorder_init(VALUE profiling_module) {
317
329
  static const rb_data_type_t stack_recorder_typed_data = {
318
330
  .wrap_struct_name = "Datadog::Profiling::StackRecorder",
319
331
  .function = {
332
+ .dmark = stack_recorder_typed_data_mark,
320
333
  .dfree = stack_recorder_typed_data_free,
321
334
  .dsize = NULL, // We don't track profile memory usage (although it'd be cool if we did!)
322
- // No need to provide dmark nor dcompact because we don't directly reference Ruby VALUEs from inside this object
323
335
  },
324
336
  .flags = RUBY_TYPED_FREE_IMMEDIATELY
325
337
  };
326
338
 
327
339
  static VALUE _native_new(VALUE klass) {
328
- struct stack_recorder_state *state = ruby_xcalloc(1, sizeof(struct stack_recorder_state));
340
+ stack_recorder_state *state = ruby_xcalloc(1, sizeof(stack_recorder_state));
329
341
 
330
342
  // Note: Any exceptions raised from this note until the TypedData_Wrap_Struct call will lead to the state memory
331
343
  // being leaked.
332
344
 
333
- ddog_prof_Slice_ValueType sample_types = {.ptr = all_value_types, .len = ALL_VALUE_TYPES_COUNT};
345
+ state->heap_clean_after_gc_enabled = false;
346
+ state->thread_context_collector_instance = Qnil;
347
+
348
+ ddog_prof_Slice_SampleType sample_types = {.ptr = all_sample_types, .len = ALL_VALUE_TYPES_COUNT};
334
349
 
335
350
  initialize_slot_concurrency_control(state);
336
351
  for (uint8_t i = 0; i < ALL_VALUE_TYPES_COUNT; i++) { state->position_for[i] = all_value_types_positions[i]; }
@@ -339,29 +354,32 @@ static VALUE _native_new(VALUE klass) {
339
354
  .serialization_time_ns_min = INT64_MAX,
340
355
  };
341
356
 
342
- // Note: At this point, slot_one_profile and slot_two_profile contain null pointers. Libdatadog validates pointers
357
+ // Note: At this point, slot_one_profile/slot_two_profile/string_storage contain null pointers. Libdatadog validates pointers
343
358
  // before using them so it's ok for us to go ahead and create the StackRecorder object.
344
359
 
345
- // Note: As of this writing, no new Ruby objects get created and stored in the state. If that ever changes, remember
346
- // to keep them on the stack and mark them with RB_GC_GUARD -- otherwise it's possible for a GC to run and
347
- // since the instance representing the state does not yet exist, such objects will not get marked.
348
-
349
360
  VALUE stack_recorder = TypedData_Wrap_Struct(klass, &stack_recorder_typed_data, state);
350
361
 
351
- // NOTE: We initialize this because we want a new recorder to be operational even without initialization and our
352
- // default is everything enabled. However, if during recording initialization it turns out we don't want
353
- // heap samples, we will free and reset heap_recorder to NULL, effectively disabling all behaviour specific
354
- // to heap profiling (all calls to heap_recorder_* with a NULL heap recorder are noops).
355
- state->heap_recorder = heap_recorder_new();
362
+ ddog_prof_ManagedStringStorageNewResult string_storage = ddog_prof_ManagedStringStorage_new();
356
363
 
357
- // Note: Don't raise exceptions after this point, since it'll lead to libdatadog memory leaking!
364
+ if (string_storage.tag == DDOG_PROF_MANAGED_STRING_STORAGE_NEW_RESULT_ERR) {
365
+ raise_error(rb_eRuntimeError, "Failed to initialize string storage: %"PRIsVALUE, get_error_details_and_drop(&string_storage.err));
366
+ }
367
+
368
+ state->string_storage = string_storage.ok;
369
+ state->label_key_allocation_class = intern_or_raise(state->string_storage, DDOG_CHARSLICE_C("allocation class"));
370
+ state->label_key_gc_gen_age = intern_or_raise(state->string_storage, DDOG_CHARSLICE_C("gc gen age"));
358
371
 
359
372
  initialize_profiles(state, sample_types);
360
373
 
374
+ // NOTE: We initialize this because we want a new recorder to be operational even before #initialize runs and our
375
+ // default is everything enabled. However, if during recording initialization it turns out we don't want
376
+ // heap samples, we will free and reset heap_recorder back to NULL.
377
+ state->heap_recorder = heap_recorder_new(state->string_storage);
378
+
361
379
  return stack_recorder;
362
380
  }
363
381
 
364
- static void initialize_slot_concurrency_control(struct stack_recorder_state *state) {
382
+ static void initialize_slot_concurrency_control(stack_recorder_state *state) {
365
383
  state->mutex_slot_one = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
366
384
  state->mutex_slot_two = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
367
385
 
@@ -371,34 +389,38 @@ static void initialize_slot_concurrency_control(struct stack_recorder_state *sta
371
389
  state->active_slot = 1;
372
390
  }
373
391
 
374
- static void initialize_profiles(struct stack_recorder_state *state, ddog_prof_Slice_ValueType sample_types) {
392
+ static void initialize_profiles(stack_recorder_state *state, ddog_prof_Slice_SampleType sample_types) {
393
+ ddog_Timespec start_timestamp = system_epoch_now_timespec();
394
+
375
395
  ddog_prof_Profile_NewResult slot_one_profile_result =
376
- ddog_prof_Profile_new(sample_types, NULL /* period is optional */, NULL /* start_time is optional */);
396
+ ddog_prof_Profile_with_string_storage(sample_types, NULL /* period is optional */, state->string_storage);
377
397
 
378
398
  if (slot_one_profile_result.tag == DDOG_PROF_PROFILE_NEW_RESULT_ERR) {
379
- rb_raise(rb_eRuntimeError, "Failed to initialize slot one profile: %"PRIsVALUE, get_error_details_and_drop(&slot_one_profile_result.err));
399
+ raise_error(rb_eRuntimeError, "Failed to initialize slot one profile: %"PRIsVALUE, get_error_details_and_drop(&slot_one_profile_result.err));
380
400
  }
381
401
 
402
+ state->profile_slot_one = (profile_slot) { .profile = slot_one_profile_result.ok, .start_timestamp = start_timestamp };
403
+
382
404
  ddog_prof_Profile_NewResult slot_two_profile_result =
383
- ddog_prof_Profile_new(sample_types, NULL /* period is optional */, NULL /* start_time is optional */);
405
+ ddog_prof_Profile_with_string_storage(sample_types, NULL /* period is optional */, state->string_storage);
384
406
 
385
407
  if (slot_two_profile_result.tag == DDOG_PROF_PROFILE_NEW_RESULT_ERR) {
386
- // Uff! Though spot. We need to make sure to properly clean up the other profile as well first
387
- ddog_prof_Profile_drop(&slot_one_profile_result.ok);
388
- // And now we can raise...
389
- rb_raise(rb_eRuntimeError, "Failed to initialize slot two profile: %"PRIsVALUE, get_error_details_and_drop(&slot_two_profile_result.err));
408
+ // Note: No need to take any special care of slot one, it'll get cleaned up by stack_recorder_typed_data_free
409
+ raise_error(rb_eRuntimeError, "Failed to initialize slot two profile: %"PRIsVALUE, get_error_details_and_drop(&slot_two_profile_result.err));
390
410
  }
391
411
 
392
- state->profile_slot_one = (profile_slot) {
393
- .profile = slot_one_profile_result.ok,
394
- };
395
- state->profile_slot_two = (profile_slot) {
396
- .profile = slot_two_profile_result.ok,
397
- };
412
+ state->profile_slot_two = (profile_slot) { .profile = slot_two_profile_result.ok, .start_timestamp = start_timestamp };
413
+ }
414
+
415
+ static void stack_recorder_typed_data_mark(void *state_ptr) {
416
+ stack_recorder_state *state = (stack_recorder_state *) state_ptr;
417
+
418
+ rb_gc_mark(state->thread_context_collector_instance);
419
+ heap_recorder_mark(state->heap_recorder);
398
420
  }
399
421
 
400
422
  static void stack_recorder_typed_data_free(void *state_ptr) {
401
- struct stack_recorder_state *state = (struct stack_recorder_state *) state_ptr;
423
+ stack_recorder_state *state = (stack_recorder_state *) state_ptr;
402
424
 
403
425
  pthread_mutex_destroy(&state->mutex_slot_one);
404
426
  ddog_prof_Profile_drop(&state->profile_slot_one.profile);
@@ -408,37 +430,40 @@ static void stack_recorder_typed_data_free(void *state_ptr) {
408
430
 
409
431
  heap_recorder_free(state->heap_recorder);
410
432
 
433
+ ddog_prof_ManagedStringStorage_drop(state->string_storage);
434
+
411
435
  ruby_xfree(state);
412
436
  }
413
437
 
414
- static VALUE _native_initialize(
415
- DDTRACE_UNUSED VALUE _self,
416
- VALUE recorder_instance,
417
- VALUE cpu_time_enabled,
418
- VALUE alloc_samples_enabled,
419
- VALUE heap_samples_enabled,
420
- VALUE heap_size_enabled,
421
- VALUE heap_sample_every,
422
- VALUE timeline_enabled
423
- ) {
424
- ENFORCE_BOOLEAN(cpu_time_enabled);
438
+ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self) {
439
+ VALUE options;
440
+ rb_scan_args(argc, argv, "0:", &options);
441
+ if (options == Qnil) options = rb_hash_new();
442
+
443
+ VALUE recorder_instance = rb_hash_fetch(options, ID2SYM(rb_intern("self_instance")));
444
+ VALUE alloc_samples_enabled = rb_hash_fetch(options, ID2SYM(rb_intern("alloc_samples_enabled")));
445
+ VALUE heap_samples_enabled = rb_hash_fetch(options, ID2SYM(rb_intern("heap_samples_enabled")));
446
+ VALUE heap_size_enabled = rb_hash_fetch(options, ID2SYM(rb_intern("heap_size_enabled")));
447
+ VALUE heap_sample_every = rb_hash_fetch(options, ID2SYM(rb_intern("heap_sample_every")));
448
+ VALUE heap_clean_after_gc_enabled = rb_hash_fetch(options, ID2SYM(rb_intern("heap_clean_after_gc_enabled")));
449
+
425
450
  ENFORCE_BOOLEAN(alloc_samples_enabled);
426
451
  ENFORCE_BOOLEAN(heap_samples_enabled);
427
452
  ENFORCE_BOOLEAN(heap_size_enabled);
428
453
  ENFORCE_TYPE(heap_sample_every, T_FIXNUM);
429
- ENFORCE_BOOLEAN(timeline_enabled);
454
+ ENFORCE_BOOLEAN(heap_clean_after_gc_enabled);
430
455
 
431
- struct stack_recorder_state *state;
432
- TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
456
+ stack_recorder_state *state;
457
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
458
+
459
+ state->heap_clean_after_gc_enabled = (heap_clean_after_gc_enabled == Qtrue);
433
460
 
434
461
  heap_recorder_set_sample_rate(state->heap_recorder, NUM2INT(heap_sample_every));
435
462
 
436
463
  uint8_t requested_values_count = ALL_VALUE_TYPES_COUNT -
437
- (cpu_time_enabled == Qtrue ? 0 : 1) -
438
464
  (alloc_samples_enabled == Qtrue? 0 : 2) -
439
465
  (heap_samples_enabled == Qtrue ? 0 : 1) -
440
- (heap_size_enabled == Qtrue ? 0 : 1) -
441
- (timeline_enabled == Qtrue ? 0 : 1);
466
+ (heap_size_enabled == Qtrue ? 0 : 1);
442
467
 
443
468
  if (requested_values_count == ALL_VALUE_TYPES_COUNT) return Qtrue; // Nothing to do, this is the default
444
469
 
@@ -448,30 +473,31 @@ static VALUE _native_initialize(
448
473
 
449
474
  state->enabled_values_count = requested_values_count;
450
475
 
451
- ddog_prof_ValueType enabled_value_types[ALL_VALUE_TYPES_COUNT];
476
+ ddog_prof_SampleType enabled_sample_types[ALL_VALUE_TYPES_COUNT];
452
477
  uint8_t next_enabled_pos = 0;
453
478
  uint8_t next_disabled_pos = requested_values_count;
454
479
 
455
- // CPU_SAMPLES_VALUE is always enabled
456
- enabled_value_types[next_enabled_pos] = (ddog_prof_ValueType) CPU_SAMPLES_VALUE;
480
+ // CPU_SAMPLES is always enabled
481
+ enabled_sample_types[next_enabled_pos] = DDOG_PROF_SAMPLE_TYPE_CPU_SAMPLES;
457
482
  state->position_for[CPU_SAMPLES_VALUE_ID] = next_enabled_pos++;
458
483
 
459
- // WALL_TIME_VALUE is always enabled
460
- enabled_value_types[next_enabled_pos] = (ddog_prof_ValueType) WALL_TIME_VALUE;
484
+ // WALL_TIME is always enabled
485
+ enabled_sample_types[next_enabled_pos] = DDOG_PROF_SAMPLE_TYPE_WALL_TIME;
461
486
  state->position_for[WALL_TIME_VALUE_ID] = next_enabled_pos++;
462
487
 
463
- if (cpu_time_enabled == Qtrue) {
464
- enabled_value_types[next_enabled_pos] = (ddog_prof_ValueType) CPU_TIME_VALUE;
465
- state->position_for[CPU_TIME_VALUE_ID] = next_enabled_pos++;
466
- } else {
467
- state->position_for[CPU_TIME_VALUE_ID] = next_disabled_pos++;
468
- }
488
+ // CPU_TIME is always enabled
489
+ enabled_sample_types[next_enabled_pos] = DDOG_PROF_SAMPLE_TYPE_CPU_TIME;
490
+ state->position_for[CPU_TIME_VALUE_ID] = next_enabled_pos++;
491
+
492
+ // TIMELINE is always enabled
493
+ enabled_sample_types[next_enabled_pos] = DDOG_PROF_SAMPLE_TYPE_TIMELINE;
494
+ state->position_for[TIMELINE_VALUE_ID] = next_enabled_pos++;
469
495
 
470
496
  if (alloc_samples_enabled == Qtrue) {
471
- enabled_value_types[next_enabled_pos] = (ddog_prof_ValueType) ALLOC_SAMPLES_VALUE;
497
+ enabled_sample_types[next_enabled_pos] = DDOG_PROF_SAMPLE_TYPE_ALLOC_SAMPLES;
472
498
  state->position_for[ALLOC_SAMPLES_VALUE_ID] = next_enabled_pos++;
473
499
 
474
- enabled_value_types[next_enabled_pos] = (ddog_prof_ValueType) ALLOC_SAMPLES_UNSCALED_VALUE;
500
+ enabled_sample_types[next_enabled_pos] = DDOG_PROF_SAMPLE_TYPE_ALLOC_SAMPLES_UNSCALED;
475
501
  state->position_for[ALLOC_SAMPLES_UNSCALED_VALUE_ID] = next_enabled_pos++;
476
502
  } else {
477
503
  state->position_for[ALLOC_SAMPLES_VALUE_ID] = next_disabled_pos++;
@@ -479,14 +505,14 @@ static VALUE _native_initialize(
479
505
  }
480
506
 
481
507
  if (heap_samples_enabled == Qtrue) {
482
- enabled_value_types[next_enabled_pos] = (ddog_prof_ValueType) HEAP_SAMPLES_VALUE;
508
+ enabled_sample_types[next_enabled_pos] = DDOG_PROF_SAMPLE_TYPE_HEAP_LIVE_SAMPLES;
483
509
  state->position_for[HEAP_SAMPLES_VALUE_ID] = next_enabled_pos++;
484
510
  } else {
485
511
  state->position_for[HEAP_SAMPLES_VALUE_ID] = next_disabled_pos++;
486
512
  }
487
513
 
488
514
  if (heap_size_enabled == Qtrue) {
489
- enabled_value_types[next_enabled_pos] = (ddog_prof_ValueType) HEAP_SIZE_VALUE;
515
+ enabled_sample_types[next_enabled_pos] = DDOG_PROF_SAMPLE_TYPE_HEAP_LIVE_SIZE;
490
516
  state->position_for[HEAP_SIZE_VALUE_ID] = next_enabled_pos++;
491
517
  } else {
492
518
  state->position_for[HEAP_SIZE_VALUE_ID] = next_disabled_pos++;
@@ -500,42 +526,41 @@ static VALUE _native_initialize(
500
526
  state->heap_recorder = NULL;
501
527
  }
502
528
 
503
- if (timeline_enabled == Qtrue) {
504
- enabled_value_types[next_enabled_pos] = (ddog_prof_ValueType) TIMELINE_VALUE;
505
- state->position_for[TIMELINE_VALUE_ID] = next_enabled_pos++;
506
- } else {
507
- state->position_for[TIMELINE_VALUE_ID] = next_disabled_pos++;
508
- }
509
-
510
529
  ddog_prof_Profile_drop(&state->profile_slot_one.profile);
511
530
  ddog_prof_Profile_drop(&state->profile_slot_two.profile);
512
531
 
513
- ddog_prof_Slice_ValueType sample_types = {.ptr = enabled_value_types, .len = state->enabled_values_count};
532
+ ddog_prof_Slice_SampleType sample_types = {.ptr = enabled_sample_types, .len = state->enabled_values_count};
514
533
  initialize_profiles(state, sample_types);
515
534
 
516
535
  return Qtrue;
517
536
  }
518
537
 
519
538
  static VALUE _native_serialize(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
520
- struct stack_recorder_state *state;
521
- TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
539
+ stack_recorder_state *state;
540
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
522
541
 
523
- ddog_Timespec finish_timestamp = system_epoch_now_timespec();
524
- // Need to do this while still holding on to the Global VM Lock; see comments on method for why
525
- serializer_set_start_timestamp_for_next_profile(state, finish_timestamp);
542
+ if (state->thread_context_collector_instance != Qnil) {
543
+ thread_context_collector_on_serialize(state->thread_context_collector_instance);
544
+ }
526
545
 
527
546
  long heap_iteration_prep_start_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE);
528
547
  // Prepare the iteration on heap recorder we'll be doing outside the GVL. The preparation needs to
529
- // happen while holding on to the GVL.
548
+ // happen while holding the GVL.
549
+ // NOTE: While rare, it's possible for the GVL to be released inside this function (see comments on `heap_recorder_update`)
550
+ // and thus don't assume this is an "atomic" step -- other threads may get some running time in the meanwhile.
530
551
  heap_recorder_prepare_iteration(state->heap_recorder);
531
552
  long heap_iteration_prep_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - heap_iteration_prep_start_time_ns;
532
553
 
554
+ ddog_Timespec finish_timestamp = system_epoch_now_timespec();
555
+ // Need to do this while still holding the Global VM Lock; see comments on method for why
556
+ serializer_set_start_timestamp_for_next_profile(state, finish_timestamp);
557
+
533
558
  // We'll release the Global VM Lock while we're calling serialize, so that the Ruby VM can continue to work while this
534
559
  // is pending
535
- struct call_serialize_without_gvl_arguments args = {
560
+ call_serialize_without_gvl_arguments args = {
536
561
  .state = state,
537
562
  .finish_timestamp = finish_timestamp,
538
- .serialize_ran = false
563
+ .serialize_ran = false,
539
564
  };
540
565
 
541
566
  while (!args.serialize_ran) {
@@ -552,20 +577,16 @@ static VALUE _native_serialize(DDTRACE_UNUSED VALUE _self, VALUE recorder_instan
552
577
  rb_thread_call_without_gvl2(call_serialize_without_gvl, &args, NULL /* No interruption function needed in this case */, NULL /* Not needed */);
553
578
  }
554
579
 
555
- // Cleanup after heap recorder iteration. This needs to happen while holding on to the GVL.
580
+ // Cleanup after heap recorder iteration. This needs to happen while holding the GVL.
556
581
  heap_recorder_finish_iteration(state->heap_recorder);
557
582
 
558
583
  // NOTE: We are focusing on the serialization time outside of the GVL in this stat here. This doesn't
559
584
  // really cover the full serialization process but it gives a more useful number since it bypasses
560
585
  // the noise of acquiring GVLs and dealing with interruptions which is highly specific to runtime
561
586
  // conditions and over which we really have no control about.
562
- long serialization_time_ns = args.serialize_no_gvl_time_ns;
563
- if (serialization_time_ns >= 0) {
564
- // Only update stats if our serialization time is valid.
565
- state->stats_lifetime.serialization_time_ns_max = long_max_of(state->stats_lifetime.serialization_time_ns_max, serialization_time_ns);
566
- state->stats_lifetime.serialization_time_ns_min = long_min_of(state->stats_lifetime.serialization_time_ns_min, serialization_time_ns);
567
- state->stats_lifetime.serialization_time_ns_total += serialization_time_ns;
568
- }
587
+ state->stats_lifetime.serialization_time_ns_max = long_max_of(state->stats_lifetime.serialization_time_ns_max, args.serialize_no_gvl_time_ns);
588
+ state->stats_lifetime.serialization_time_ns_min = long_min_of(state->stats_lifetime.serialization_time_ns_min, args.serialize_no_gvl_time_ns);
589
+ state->stats_lifetime.serialization_time_ns_total += args.serialize_no_gvl_time_ns;
569
590
 
570
591
  ddog_prof_Profile_SerializeResult serialized_profile = args.result;
571
592
 
@@ -574,20 +595,22 @@ static VALUE _native_serialize(DDTRACE_UNUSED VALUE _self, VALUE recorder_instan
574
595
  return rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&serialized_profile.err));
575
596
  }
576
597
 
598
+ // Note: If we got here, the profile serialized correctly.
599
+ // Once we wrap this into a Ruby object, our `EncodedProfile` class will automatically manage memory for it and we
600
+ // can raise exceptions without worrying about leaking the profile.
577
601
  state->stats_lifetime.serialization_successes++;
602
+ VALUE encoded_profile = from_ddog_prof_EncodedProfile(serialized_profile.ok);
578
603
 
579
- VALUE encoded_pprof = ruby_string_from_vec_u8(serialized_profile.ok.buffer);
580
-
581
- ddog_Timespec ddprof_start = serialized_profile.ok.start;
582
- ddog_Timespec ddprof_finish = serialized_profile.ok.end;
583
-
584
- ddog_prof_EncodedProfile_drop(&serialized_profile.ok);
604
+ ddog_prof_MaybeError result = args.advance_gen_result;
605
+ if (result.tag == DDOG_PROF_OPTION_ERROR_SOME_ERROR) {
606
+ raise_error(rb_eRuntimeError, "Failed to advance string storage gen: %"PRIsVALUE, get_error_details_and_drop(&result.some));
607
+ }
585
608
 
586
- VALUE start = ruby_time_from(ddprof_start);
587
- VALUE finish = ruby_time_from(ddprof_finish);
588
- VALUE profile_stats = build_profile_stats(args.slot, serialization_time_ns, heap_iteration_prep_time_ns, args.heap_profile_build_time_ns);
609
+ VALUE start = ruby_time_from(args.slot->start_timestamp);
610
+ VALUE finish = ruby_time_from(finish_timestamp);
611
+ VALUE profile_stats = build_profile_stats(args.slot, args.serialize_no_gvl_time_ns, heap_iteration_prep_time_ns, args.heap_profile_build_time_ns);
589
612
 
590
- return rb_ary_new_from_args(2, ok_symbol, rb_ary_new_from_args(4, start, finish, encoded_pprof, profile_stats));
613
+ return rb_ary_new_from_args(2, ok_symbol, rb_ary_new_from_args(4, start, finish, encoded_profile, profile_stats));
591
614
  }
592
615
 
593
616
  static VALUE ruby_time_from(ddog_Timespec ddprof_time) {
@@ -597,10 +620,31 @@ static VALUE ruby_time_from(ddog_Timespec ddprof_time) {
597
620
  }
598
621
 
599
622
  void record_sample(VALUE recorder_instance, ddog_prof_Slice_Location locations, sample_values values, sample_labels labels) {
600
- struct stack_recorder_state *state;
601
- TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
623
+ stack_recorder_state *state;
624
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
602
625
 
603
- locked_profile_slot active_slot = sampler_lock_active_profile(state);
626
+ record_sample_arguments args = {
627
+ .state = state,
628
+ .active_slot = sampler_lock_active_profile(state),
629
+ .locations = locations,
630
+ .values = values,
631
+ .labels = labels,
632
+ };
633
+
634
+ // NOTE: The heap recorder is allowed to raise exceptions if something's wrong. We use `rb_ensure` to make sure we
635
+ // properly unlock the active slot mutex on our way out. Otherwise, this would later lead to deadlocks (since the
636
+ // active slot mutex is not expected to be locked forever).
637
+ rb_ensure(record_sample_locked, (VALUE) &args, record_sample_unlock_ensure, (VALUE) &args);
638
+
639
+ if (args.result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
640
+ raise_error(rb_eArgError, "Failed to record sample: %"PRIsVALUE, get_error_details_and_drop(&args.result.err));
641
+ }
642
+ }
643
+
644
+ static VALUE record_sample_locked(VALUE record_sample_arguments_as_value) {
645
+ record_sample_arguments *args = (record_sample_arguments *) record_sample_arguments_as_value;
646
+ stack_recorder_state *state = args->state;
647
+ sample_values values = args->values;
604
648
 
605
649
  // Note: We initialize this array to have ALL_VALUE_TYPES_COUNT but only tell libdatadog to use the first
606
650
  // state->enabled_values_count values. This simplifies handling disabled value types -- we still put them on the
@@ -616,53 +660,44 @@ void record_sample(VALUE recorder_instance, ddog_prof_Slice_Location locations,
616
660
  metric_values[position_for[ALLOC_SAMPLES_UNSCALED_VALUE_ID]] = values.alloc_samples_unscaled;
617
661
  metric_values[position_for[TIMELINE_VALUE_ID]] = values.timeline_wall_time_ns;
618
662
 
619
- if (values.heap_sample) {
620
- // If we got an allocation sample end the heap allocation recording to commit the heap sample.
621
- // FIXME: Heap sampling currently has to be done in 2 parts because the construction of locations is happening
622
- // very late in the allocation-sampling path (which is shared with the cpu sampling path). This can
623
- // be fixed with some refactoring but for now this leads to a less impactful change.
624
- //
625
- // NOTE: The heap recorder is allowed to raise exceptions if something's wrong. But we also need to handle it
626
- // on this side to make sure we properly unlock the active slot mutex on our way out. Otherwise, this would
627
- // later lead to deadlocks (since the active slot mutex is not expected to be locked forever).
628
- int exception_state = end_heap_allocation_recording_with_rb_protect(state->heap_recorder, locations);
629
- if (exception_state) {
630
- sampler_unlock_active_profile(active_slot);
631
- rb_jump_tag(exception_state);
632
- }
663
+ if (values.heap_sample != NULL) {
664
+ heap_recorder_record_allocation(
665
+ state->heap_recorder,
666
+ values.heap_sample->new_object,
667
+ values.alloc_samples,
668
+ values.heap_sample->alloc_class,
669
+ args->locations,
670
+ &values.heap_sample->out_needs_commit
671
+ );
633
672
  }
634
673
 
635
- ddog_prof_Profile_Result result = ddog_prof_Profile_add(
636
- &active_slot.data->profile,
674
+ args->result = ddog_prof_Profile_add(
675
+ &args->active_slot.data->profile,
637
676
  (ddog_prof_Sample) {
638
- .locations = locations,
677
+ .locations = args->locations,
639
678
  .values = (ddog_Slice_I64) {.ptr = metric_values, .len = state->enabled_values_count},
640
- .labels = labels.labels
679
+ .labels = args->labels.labels
641
680
  },
642
- labels.end_timestamp_ns
681
+ /* To disable end_timestamp_ns to get aggregated profiles in pprof, replace the below with `0` */
682
+ args->labels.end_timestamp_ns
643
683
  );
644
684
 
645
- active_slot.data->stats.recorded_samples++;
646
-
647
- sampler_unlock_active_profile(active_slot);
685
+ args->active_slot.data->stats.recorded_samples++;
648
686
 
649
- if (result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
650
- rb_raise(rb_eArgError, "Failed to record sample: %"PRIsVALUE, get_error_details_and_drop(&result.err));
651
- }
687
+ return Qnil; // Unused
652
688
  }
653
689
 
654
- void track_object(VALUE recorder_instance, VALUE new_object, unsigned int sample_weight, ddog_CharSlice *alloc_class) {
655
- struct stack_recorder_state *state;
656
- TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
657
- // FIXME: Heap sampling currently has to be done in 2 parts because the construction of locations is happening
658
- // very late in the allocation-sampling path (which is shared with the cpu sampling path). This can
659
- // be fixed with some refactoring but for now this leads to a less impactful change.
660
- start_heap_allocation_recording(state->heap_recorder, new_object, sample_weight, alloc_class);
690
+ static VALUE record_sample_unlock_ensure(VALUE record_sample_arguments_as_value) {
691
+ record_sample_arguments *args = (record_sample_arguments *) record_sample_arguments_as_value;
692
+
693
+ sampler_unlock_active_profile(args->active_slot);
694
+
695
+ return Qnil; // Unused
661
696
  }
662
697
 
663
698
  void record_endpoint(VALUE recorder_instance, uint64_t local_root_span_id, ddog_CharSlice endpoint) {
664
- struct stack_recorder_state *state;
665
- TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
699
+ stack_recorder_state *state;
700
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
666
701
 
667
702
  locked_profile_slot active_slot = sampler_lock_active_profile(state);
668
703
 
@@ -671,16 +706,30 @@ void record_endpoint(VALUE recorder_instance, uint64_t local_root_span_id, ddog_
671
706
  sampler_unlock_active_profile(active_slot);
672
707
 
673
708
  if (result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
674
- rb_raise(rb_eArgError, "Failed to record endpoint: %"PRIsVALUE, get_error_details_and_drop(&result.err));
709
+ raise_error(rb_eArgError, "Failed to record endpoint: %"PRIsVALUE, get_error_details_and_drop(&result.err));
675
710
  }
676
711
  }
677
712
 
713
+ void recorder_heap_update_may_lose_gvl(VALUE recorder_instance) {
714
+ stack_recorder_state *state;
715
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
716
+
717
+ if (state->heap_clean_after_gc_enabled) heap_recorder_update_young_objects(state->heap_recorder);
718
+ }
719
+
720
+ void recorder_commit_heap_recordings_may_lose_gvl(VALUE recorder_instance) {
721
+ stack_recorder_state *state;
722
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
723
+
724
+ heap_recorder_commit_recordings_may_lose_gvl(state->heap_recorder);
725
+ }
726
+
678
727
  #define MAX_LEN_HEAP_ITERATION_ERROR_MSG 256
679
728
 
680
729
  // Heap recorder iteration context allows us access to stack recorder state and profile being serialized
681
730
  // during iteration of heap recorder live objects.
682
731
  typedef struct heap_recorder_iteration_context {
683
- struct stack_recorder_state *state;
732
+ stack_recorder_state *state;
684
733
  profile_slot *slot;
685
734
 
686
735
  bool error;
@@ -701,18 +750,15 @@ static bool add_heap_sample_to_active_profile_without_gvl(heap_recorder_iteratio
701
750
  ddog_prof_Label labels[2];
702
751
  size_t label_offset = 0;
703
752
 
704
- if (object_data->class != NULL) {
753
+ if (object_data->class.value > 0) {
705
754
  labels[label_offset++] = (ddog_prof_Label) {
706
- .key = DDOG_CHARSLICE_C("allocation class"),
707
- .str = (ddog_CharSlice) {
708
- .ptr = object_data->class,
709
- .len = strlen(object_data->class),
710
- },
755
+ .key_id = context->state->label_key_allocation_class,
756
+ .str_id = object_data->class,
711
757
  .num = 0, // This shouldn't be needed but the tracer-2.7 docker image ships a buggy gcc that complains about this
712
758
  };
713
759
  }
714
760
  labels[label_offset++] = (ddog_prof_Label) {
715
- .key = DDOG_CHARSLICE_C("gc gen age"),
761
+ .key_id = context->state->label_key_gc_gen_age,
716
762
  .num = object_data->gen_age,
717
763
  };
718
764
 
@@ -742,7 +788,7 @@ static bool add_heap_sample_to_active_profile_without_gvl(heap_recorder_iteratio
742
788
  return true;
743
789
  }
744
790
 
745
- static void build_heap_profile_without_gvl(struct stack_recorder_state *state, profile_slot *slot) {
791
+ static void build_heap_profile_without_gvl(stack_recorder_state *state, profile_slot *slot) {
746
792
  heap_recorder_iteration_context iteration_context = {
747
793
  .state = state,
748
794
  .slot = slot,
@@ -763,12 +809,11 @@ static void build_heap_profile_without_gvl(struct stack_recorder_state *state, p
763
809
  }
764
810
 
765
811
  static void *call_serialize_without_gvl(void *call_args) {
766
- struct call_serialize_without_gvl_arguments *args = (struct call_serialize_without_gvl_arguments *) call_args;
812
+ call_serialize_without_gvl_arguments *args = (call_serialize_without_gvl_arguments *) call_args;
767
813
 
768
814
  long serialize_no_gvl_start_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE);
769
815
 
770
816
  profile_slot *slot_now_inactive = serializer_flip_active_and_inactive_slots(args->state);
771
-
772
817
  args->slot = slot_now_inactive;
773
818
 
774
819
  // Now that we have the inactive profile with all but heap samples, lets fill it with heap data
@@ -777,19 +822,20 @@ static void *call_serialize_without_gvl(void *call_args) {
777
822
  args->heap_profile_build_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - serialize_no_gvl_start_time_ns;
778
823
 
779
824
  // Note: The profile gets reset by the serialize call
780
- args->result = ddog_prof_Profile_serialize(&args->slot->profile, &args->finish_timestamp, NULL /* duration_nanos is optional */, NULL /* start_time is optional */);
825
+ args->result = ddog_prof_Profile_serialize(&args->slot->profile, &args->slot->start_timestamp, &args->finish_timestamp);
826
+ args->advance_gen_result = ddog_prof_ManagedStringStorage_advance_gen(args->state->string_storage);
781
827
  args->serialize_ran = true;
782
- args->serialize_no_gvl_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - serialize_no_gvl_start_time_ns;
828
+ args->serialize_no_gvl_time_ns = long_max_of(0, monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - serialize_no_gvl_start_time_ns);
783
829
 
784
830
  return NULL; // Unused
785
831
  }
786
832
 
787
833
  VALUE enforce_recorder_instance(VALUE object) {
788
- Check_TypedStruct(object, &stack_recorder_typed_data);
834
+ ENFORCE_TYPED_DATA(object, &stack_recorder_typed_data);
789
835
  return object;
790
836
  }
791
837
 
792
- static locked_profile_slot sampler_lock_active_profile(struct stack_recorder_state *state) {
838
+ static locked_profile_slot sampler_lock_active_profile(stack_recorder_state *state) {
793
839
  int error;
794
840
 
795
841
  for (int attempts = 0; attempts < 2; attempts++) {
@@ -809,14 +855,14 @@ static locked_profile_slot sampler_lock_active_profile(struct stack_recorder_sta
809
855
  }
810
856
 
811
857
  // We already tried both multiple times, and we did not succeed. This is not expected to happen. Let's stop sampling.
812
- rb_raise(rb_eRuntimeError, "Failed to grab either mutex in sampler_lock_active_profile");
858
+ raise_error(rb_eRuntimeError, "Failed to grab either mutex in sampler_lock_active_profile");
813
859
  }
814
860
 
815
861
  static void sampler_unlock_active_profile(locked_profile_slot active_slot) {
816
862
  ENFORCE_SUCCESS_GVL(pthread_mutex_unlock(active_slot.mutex));
817
863
  }
818
864
 
819
- static profile_slot* serializer_flip_active_and_inactive_slots(struct stack_recorder_state *state) {
865
+ static profile_slot* serializer_flip_active_and_inactive_slots(stack_recorder_state *state) {
820
866
  int previously_active_slot = state->active_slot;
821
867
 
822
868
  if (previously_active_slot != 1 && previously_active_slot != 2) {
@@ -842,8 +888,8 @@ static profile_slot* serializer_flip_active_and_inactive_slots(struct stack_reco
842
888
  // This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
843
889
  // It SHOULD NOT be used for other purposes.
844
890
  static VALUE _native_active_slot(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
845
- struct stack_recorder_state *state;
846
- TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
891
+ stack_recorder_state *state;
892
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
847
893
 
848
894
  return INT2NUM(state->active_slot);
849
895
  }
@@ -857,8 +903,8 @@ static VALUE _native_is_slot_one_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE
857
903
  static VALUE _native_is_slot_two_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) { return test_slot_mutex_state(recorder_instance, 2); }
858
904
 
859
905
  static VALUE test_slot_mutex_state(VALUE recorder_instance, int slot) {
860
- struct stack_recorder_state *state;
861
- TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
906
+ stack_recorder_state *state;
907
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
862
908
 
863
909
  pthread_mutex_t *slot_mutex = (slot == 1) ? &state->mutex_slot_one : &state->mutex_slot_two;
864
910
 
@@ -874,7 +920,7 @@ static VALUE test_slot_mutex_state(VALUE recorder_instance, int slot) {
874
920
  return Qtrue;
875
921
  } else {
876
922
  ENFORCE_SUCCESS_GVL(error);
877
- rb_raise(rb_eRuntimeError, "Failed to raise exception in test_slot_mutex_state; this should never happen");
923
+ raise_error(rb_eRuntimeError, "Failed to raise exception in test_slot_mutex_state; this should never happen");
878
924
  }
879
925
  }
880
926
 
@@ -887,16 +933,19 @@ static ddog_Timespec system_epoch_now_timespec(void) {
887
933
  //
888
934
  // Assumption: This method gets called BEFORE restarting profiling -- e.g. there are no components attempting to
889
935
  // trigger samples at the same time.
936
+ //
937
+ // Note that tests call this method directly in the same process without forking,
938
+ // and in such a case non-current Threads keep running.
890
939
  static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE recorder_instance) {
891
- struct stack_recorder_state *state;
892
- TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
940
+ stack_recorder_state *state;
941
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
893
942
 
894
943
  // In case the fork happened halfway through `serializer_flip_active_and_inactive_slots` execution and the
895
944
  // resulting state is inconsistent, we make sure to reset it back to the initial state.
896
945
  initialize_slot_concurrency_control(state);
897
-
898
- reset_profile_slot(&state->profile_slot_one, /* start_time: */ NULL);
899
- reset_profile_slot(&state->profile_slot_two, /* start_time: */ NULL);
946
+ ddog_Timespec start_timestamp = system_epoch_now_timespec();
947
+ reset_profile_slot(&state->profile_slot_one, start_timestamp);
948
+ reset_profile_slot(&state->profile_slot_two, start_timestamp);
900
949
 
901
950
  heap_recorder_after_fork(state->heap_recorder);
902
951
 
@@ -905,10 +954,10 @@ static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE recorder_
905
954
 
906
955
  // Assumption 1: This method is called with the GVL being held, because `ddog_prof_Profile_reset` mutates the profile and must
907
956
  // not be interrupted part-way through by a VM fork.
908
- static void serializer_set_start_timestamp_for_next_profile(struct stack_recorder_state *state, ddog_Timespec start_time) {
957
+ static void serializer_set_start_timestamp_for_next_profile(stack_recorder_state *state, ddog_Timespec start_time) {
909
958
  // Before making this profile active, we reset it so that it uses the correct start_time for its start
910
959
  profile_slot *next_profile_slot = (state->active_slot == 1) ? &state->profile_slot_two : &state->profile_slot_one;
911
- reset_profile_slot(next_profile_slot, &start_time);
960
+ reset_profile_slot(next_profile_slot, start_time);
912
961
  }
913
962
 
914
963
  static VALUE _native_record_endpoint(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE local_root_span_id, VALUE endpoint) {
@@ -917,56 +966,20 @@ static VALUE _native_record_endpoint(DDTRACE_UNUSED VALUE _self, VALUE recorder_
917
966
  return Qtrue;
918
967
  }
919
968
 
920
- static VALUE _native_track_object(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE new_obj, VALUE weight, VALUE alloc_class) {
921
- ENFORCE_TYPE(weight, T_FIXNUM);
922
- ddog_CharSlice alloc_class_slice = char_slice_from_ruby_string(alloc_class);
923
- track_object(recorder_instance, new_obj, NUM2UINT(weight), &alloc_class_slice);
924
- return Qtrue;
925
- }
926
-
927
- static VALUE _native_check_heap_hashes(DDTRACE_UNUSED VALUE _self, VALUE locations) {
928
- ENFORCE_TYPE(locations, T_ARRAY);
929
- size_t locations_len = rb_array_len(locations);
930
- ddog_prof_Location locations_arr[locations_len];
931
- for (size_t i = 0; i < locations_len; i++) {
932
- VALUE location = rb_ary_entry(locations, i);
933
- ENFORCE_TYPE(location, T_ARRAY);
934
- VALUE name = rb_ary_entry(location, 0);
935
- VALUE filename = rb_ary_entry(location, 1);
936
- VALUE line = rb_ary_entry(location, 2);
937
- ENFORCE_TYPE(name, T_STRING);
938
- ENFORCE_TYPE(filename, T_STRING);
939
- ENFORCE_TYPE(line, T_FIXNUM);
940
- locations_arr[i] = (ddog_prof_Location) {
941
- .line = line,
942
- .function = (ddog_prof_Function) {
943
- .name = char_slice_from_ruby_string(name),
944
- .filename = char_slice_from_ruby_string(filename),
945
- }
946
- };
947
- }
948
- ddog_prof_Slice_Location ddog_locations = {
949
- .len = locations_len,
950
- .ptr = locations_arr,
951
- };
952
- heap_recorder_testonly_assert_hash_matches(ddog_locations);
953
-
954
- return Qnil;
955
- }
956
-
957
- static void reset_profile_slot(profile_slot *slot, ddog_Timespec *start_time /* Can be null */) {
958
- ddog_prof_Profile_Result reset_result = ddog_prof_Profile_reset(&slot->profile, start_time);
969
+ static void reset_profile_slot(profile_slot *slot, ddog_Timespec start_timestamp) {
970
+ ddog_prof_Profile_Result reset_result = ddog_prof_Profile_reset(&slot->profile);
959
971
  if (reset_result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
960
- rb_raise(rb_eRuntimeError, "Failed to reset profile: %"PRIsVALUE, get_error_details_and_drop(&reset_result.err));
972
+ raise_error(rb_eRuntimeError, "Failed to reset profile: %"PRIsVALUE, get_error_details_and_drop(&reset_result.err));
961
973
  }
974
+ slot->start_timestamp = start_timestamp;
962
975
  slot->stats = (stats_slot) {};
963
976
  }
964
977
 
965
978
  // This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
966
979
  // It SHOULD NOT be used for other purposes.
967
980
  static VALUE _native_start_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
968
- struct stack_recorder_state *state;
969
- TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
981
+ stack_recorder_state *state;
982
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
970
983
 
971
984
  heap_recorder_prepare_iteration(state->heap_recorder);
972
985
 
@@ -976,8 +989,8 @@ static VALUE _native_start_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _se
976
989
  // This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
977
990
  // It SHOULD NOT be used for other purposes.
978
991
  static VALUE _native_end_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
979
- struct stack_recorder_state *state;
980
- TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
992
+ stack_recorder_state *state;
993
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
981
994
 
982
995
  heap_recorder_finish_iteration(state->heap_recorder);
983
996
 
@@ -987,43 +1000,15 @@ static VALUE _native_end_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _self
987
1000
  // This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
988
1001
  // It SHOULD NOT be used for other purposes.
989
1002
  static VALUE _native_debug_heap_recorder(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
990
- struct stack_recorder_state *state;
991
- TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
1003
+ stack_recorder_state *state;
1004
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
992
1005
 
993
1006
  return heap_recorder_testonly_debug(state->heap_recorder);
994
1007
  }
995
1008
 
996
- #pragma GCC diagnostic push
997
- // rb_gc_force_recycle was deprecated in latest versions of Ruby and is a noop.
998
- #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
999
- #pragma GCC diagnostic ignored "-Wunused-parameter"
1000
- // This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
1001
- // It SHOULD NOT be used for other purposes.
1002
- static VALUE _native_gc_force_recycle(DDTRACE_UNUSED VALUE _self, VALUE obj) {
1003
- #ifdef HAVE_WORKING_RB_GC_FORCE_RECYCLE
1004
- rb_gc_force_recycle(obj);
1005
- #endif
1006
- return Qnil;
1007
- }
1008
- #pragma GCC diagnostic pop
1009
-
1010
- // This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
1011
- // It SHOULD NOT be used for other purposes.
1012
- static VALUE _native_has_seen_id_flag(DDTRACE_UNUSED VALUE _self, VALUE obj) {
1013
- #ifndef NO_SEEN_OBJ_ID_FLAG
1014
- if (RB_FL_TEST(obj, RUBY_FL_SEEN_OBJ_ID)) {
1015
- return Qtrue;
1016
- } else {
1017
- return Qfalse;
1018
- }
1019
- #else
1020
- return Qfalse;
1021
- #endif
1022
- }
1023
-
1024
1009
  static VALUE _native_stats(DDTRACE_UNUSED VALUE self, VALUE recorder_instance) {
1025
- struct stack_recorder_state *state;
1026
- TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
1010
+ stack_recorder_state *state;
1011
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
1027
1012
 
1028
1013
  uint64_t total_serializations = state->stats_lifetime.serialization_successes + state->stats_lifetime.serialization_failures;
1029
1014
 
@@ -1057,3 +1042,174 @@ static VALUE build_profile_stats(profile_slot *slot, long serialization_time_ns,
1057
1042
  for (long unsigned int i = 0; i < VALUE_COUNT(arguments); i += 2) rb_hash_aset(stats_as_hash, arguments[i], arguments[i+1]);
1058
1043
  return stats_as_hash;
1059
1044
  }
1045
+
1046
+ static VALUE _native_is_object_recorded(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE record_id) {
1047
+ ENFORCE_TYPE(record_id, T_FIXNUM);
1048
+
1049
+ stack_recorder_state *state;
1050
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
1051
+
1052
+ return heap_recorder_testonly_is_object_recorded(state->heap_recorder, FIX2LONG(record_id));
1053
+ }
1054
+
1055
+ static VALUE _native_record_id_for(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE obj) {
1056
+ stack_recorder_state *state;
1057
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
1058
+
1059
+ return heap_recorder_testonly_record_id_for(state->heap_recorder, obj);
1060
+ }
1061
+
1062
+ static VALUE _native_heap_recorder_exhaust_record_ids(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
1063
+ stack_recorder_state *state;
1064
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
1065
+
1066
+ heap_recorder_testonly_exhaust_record_ids(state->heap_recorder);
1067
+ return Qtrue;
1068
+ }
1069
+
1070
+ static VALUE _native_heap_recorder_set_object_alloc_gen(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE record_id, VALUE alloc_gen) {
1071
+ ENFORCE_TYPE(record_id, T_FIXNUM);
1072
+ ENFORCE_TYPE(alloc_gen, T_FIXNUM);
1073
+
1074
+ stack_recorder_state *state;
1075
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
1076
+
1077
+ heap_recorder_testonly_set_object_alloc_gen(state->heap_recorder, FIX2LONG(record_id), NUM2SIZET(alloc_gen));
1078
+ return Qtrue;
1079
+ }
1080
+
1081
+ static VALUE _native_heap_recorder_reset_last_update(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
1082
+ stack_recorder_state *state;
1083
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
1084
+
1085
+ heap_recorder_testonly_reset_last_update(state->heap_recorder);
1086
+
1087
+ return Qtrue;
1088
+ }
1089
+
1090
+ static VALUE _native_recorder_heap_update(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
1091
+ recorder_heap_update_may_lose_gvl(recorder_instance);
1092
+ return Qtrue;
1093
+ }
1094
+
1095
+ static VALUE _native_benchmark_intern(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE string, VALUE times, VALUE use_all) {
1096
+ ENFORCE_TYPE(string, T_STRING);
1097
+ ENFORCE_TYPE(times, T_FIXNUM);
1098
+ ENFORCE_BOOLEAN(use_all);
1099
+
1100
+ stack_recorder_state *state;
1101
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
1102
+
1103
+ heap_recorder_testonly_benchmark_intern(state->heap_recorder, char_slice_from_ruby_string(string), FIX2INT(times), use_all == Qtrue);
1104
+
1105
+ return Qtrue;
1106
+ }
1107
+
1108
+ // See comments in rspec test for details on what we're testing here.
1109
+ static VALUE _native_test_managed_string_storage_produces_valid_profiles(DDTRACE_UNUSED VALUE _self) {
1110
+ ddog_prof_ManagedStringStorageNewResult string_storage = ddog_prof_ManagedStringStorage_new();
1111
+
1112
+ if (string_storage.tag == DDOG_PROF_MANAGED_STRING_STORAGE_NEW_RESULT_ERR) {
1113
+ raise_error(rb_eRuntimeError, "Failed to initialize string storage: %"PRIsVALUE, get_error_details_and_drop(&string_storage.err));
1114
+ }
1115
+
1116
+ ddog_prof_Slice_SampleType sample_types = {.ptr = all_sample_types, .len = ALL_VALUE_TYPES_COUNT};
1117
+ ddog_prof_Profile_NewResult profile = ddog_prof_Profile_with_string_storage(sample_types, NULL, string_storage.ok);
1118
+
1119
+ if (profile.tag == DDOG_PROF_PROFILE_NEW_RESULT_ERR) {
1120
+ raise_error(rb_eRuntimeError, "Failed to initialize profile: %"PRIsVALUE, get_error_details_and_drop(&profile.err));
1121
+ }
1122
+
1123
+ ddog_prof_ManagedStringId hello = intern_or_raise(string_storage.ok, DDOG_CHARSLICE_C("hello"));
1124
+ ddog_prof_ManagedStringId world = intern_or_raise(string_storage.ok, DDOG_CHARSLICE_C("world"));
1125
+ ddog_prof_ManagedStringId key = intern_or_raise(string_storage.ok, DDOG_CHARSLICE_C("key"));
1126
+
1127
+ int64_t metric_values[] = {1, 2, 3, 4, 5, 6, 7, 8};
1128
+ ddog_prof_Label labels[] = {{.key_id = key, .str_id = key}};
1129
+
1130
+ ddog_prof_Location locations[] = {
1131
+ (ddog_prof_Location) {
1132
+ .mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C(""), .build_id_id = {}},
1133
+ .function = {
1134
+ .name = DDOG_CHARSLICE_C(""),
1135
+ .name_id = hello,
1136
+ .filename = DDOG_CHARSLICE_C(""),
1137
+ .filename_id = world,
1138
+ },
1139
+ .line = 1,
1140
+ }
1141
+ };
1142
+
1143
+ ddog_prof_Profile_Result result = ddog_prof_Profile_add(
1144
+ &profile.ok,
1145
+ (ddog_prof_Sample) {
1146
+ .locations = (ddog_prof_Slice_Location) { .ptr = locations, .len = 1},
1147
+ .values = (ddog_Slice_I64) {.ptr = metric_values, .len = 8},
1148
+ .labels = (ddog_prof_Slice_Label) { .ptr = labels, .len = 1 }
1149
+ },
1150
+ 0
1151
+ );
1152
+
1153
+ if (result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
1154
+ raise_error(rb_eArgError, "Failed to record sample: %"PRIsVALUE, get_error_details_and_drop(&result.err));
1155
+ }
1156
+
1157
+ ddog_Timespec finish_timestamp = system_epoch_now_timespec();
1158
+ ddog_Timespec start_timestamp = {.seconds = finish_timestamp.seconds - 60};
1159
+ ddog_prof_Profile_SerializeResult serialize_result = ddog_prof_Profile_serialize(&profile.ok, &start_timestamp, &finish_timestamp);
1160
+
1161
+ if (serialize_result.tag == DDOG_PROF_PROFILE_SERIALIZE_RESULT_ERR) {
1162
+ raise_error(rb_eRuntimeError, "Failed to serialize: %"PRIsVALUE, get_error_details_and_drop(&serialize_result.err));
1163
+ }
1164
+
1165
+ ddog_prof_MaybeError advance_gen_result = ddog_prof_ManagedStringStorage_advance_gen(string_storage.ok);
1166
+
1167
+ if (advance_gen_result.tag == DDOG_PROF_OPTION_ERROR_SOME_ERROR) {
1168
+ raise_error(rb_eRuntimeError, "Failed to advance string storage gen: %"PRIsVALUE, get_error_details_and_drop(&advance_gen_result.some));
1169
+ }
1170
+
1171
+ VALUE encoded_pprof_1 = from_ddog_prof_EncodedProfile(serialize_result.ok);
1172
+
1173
+ result = ddog_prof_Profile_add(
1174
+ &profile.ok,
1175
+ (ddog_prof_Sample) {
1176
+ .locations = (ddog_prof_Slice_Location) { .ptr = locations, .len = 1},
1177
+ .values = (ddog_Slice_I64) {.ptr = metric_values, .len = 8},
1178
+ .labels = (ddog_prof_Slice_Label) { .ptr = labels, .len = 1 }
1179
+ },
1180
+ 0
1181
+ );
1182
+
1183
+ if (result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
1184
+ raise_error(rb_eArgError, "Failed to record sample: %"PRIsVALUE, get_error_details_and_drop(&result.err));
1185
+ }
1186
+
1187
+ serialize_result = ddog_prof_Profile_serialize(&profile.ok, &start_timestamp, &finish_timestamp);
1188
+
1189
+ if (serialize_result.tag == DDOG_PROF_PROFILE_SERIALIZE_RESULT_ERR) {
1190
+ raise_error(rb_eArgError, "Failed to serialize: %"PRIsVALUE, get_error_details_and_drop(&serialize_result.err));
1191
+ }
1192
+
1193
+ VALUE encoded_pprof_2 = from_ddog_prof_EncodedProfile(serialize_result.ok);
1194
+
1195
+ ddog_prof_Profile_drop(&profile.ok);
1196
+ ddog_prof_ManagedStringStorage_drop(string_storage.ok);
1197
+
1198
+ return rb_ary_new_from_args(2, encoded_pprof_1, encoded_pprof_2);
1199
+ }
1200
+
1201
+ static VALUE _native_commit_heap_recordings(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
1202
+ stack_recorder_state *state;
1203
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
1204
+
1205
+ heap_recorder_commit_recordings_may_lose_gvl(state->heap_recorder);
1206
+
1207
+ return Qtrue;
1208
+ }
1209
+
1210
+ void recorder_install_on_serialize(VALUE recorder_instance, VALUE thread_context_collector_instance) {
1211
+ stack_recorder_state *state;
1212
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
1213
+
1214
+ state->thread_context_collector_instance = enforce_thread_context_collector_instance(thread_context_collector_instance);
1215
+ }