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