datadog 2.17.0 → 2.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (765) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +686 -1
  3. data/README.md +0 -1
  4. data/ext/LIBDATADOG_DEVELOPMENT.md +3 -0
  5. data/ext/datadog_profiling_native_extension/clock_id.h +9 -1
  6. data/ext/datadog_profiling_native_extension/clock_id_from_mach.c +66 -0
  7. data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +3 -2
  8. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +344 -126
  9. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +4 -4
  10. data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +3 -2
  11. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +18 -4
  12. data/ext/datadog_profiling_native_extension/collectors_stack.c +314 -91
  13. data/ext/datadog_profiling_native_extension/collectors_stack.h +26 -3
  14. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +680 -352
  15. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +18 -5
  16. data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +239 -0
  17. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +65 -1
  18. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +40 -1
  19. data/ext/datadog_profiling_native_extension/encoded_profile.c +2 -1
  20. data/ext/datadog_profiling_native_extension/extconf.rb +48 -34
  21. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +4 -43
  22. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +15 -47
  23. data/ext/datadog_profiling_native_extension/heap_recorder.c +455 -430
  24. data/ext/datadog_profiling_native_extension/heap_recorder.h +16 -7
  25. data/ext/datadog_profiling_native_extension/http_transport.c +66 -68
  26. data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +18 -15
  27. data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +8 -10
  28. data/ext/datadog_profiling_native_extension/macos_sampler_thread.h +55 -0
  29. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +0 -13
  30. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +73 -69
  31. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +10 -4
  32. data/ext/datadog_profiling_native_extension/profiling.c +65 -19
  33. data/ext/datadog_profiling_native_extension/ruby_helpers.c +64 -59
  34. data/ext/datadog_profiling_native_extension/ruby_helpers.h +20 -16
  35. data/ext/datadog_profiling_native_extension/setup_signal_handler.c +32 -10
  36. data/ext/datadog_profiling_native_extension/setup_signal_handler.h +2 -1
  37. data/ext/datadog_profiling_native_extension/stack_recorder.c +253 -131
  38. data/ext/datadog_profiling_native_extension/stack_recorder.h +3 -1
  39. data/ext/datadog_profiling_native_extension/time_helpers.h +1 -0
  40. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +2 -1
  41. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +9 -4
  42. data/ext/libdatadog_api/crashtracker.c +16 -15
  43. data/ext/libdatadog_api/crashtracker_report_exception.c +126 -0
  44. data/ext/libdatadog_api/datadog_ruby_common.c +65 -1
  45. data/ext/libdatadog_api/datadog_ruby_common.h +40 -1
  46. data/ext/libdatadog_api/ddsketch.c +102 -0
  47. data/ext/libdatadog_api/di.c +203 -0
  48. data/ext/libdatadog_api/extconf.rb +21 -25
  49. data/ext/libdatadog_api/feature_flags.c +554 -0
  50. data/ext/libdatadog_api/feature_flags.h +5 -0
  51. data/ext/libdatadog_api/helpers.h +27 -0
  52. data/ext/libdatadog_api/init.c +13 -1
  53. data/ext/libdatadog_api/library_config.c +88 -37
  54. data/ext/libdatadog_api/library_config.h +6 -0
  55. data/ext/libdatadog_api/process_discovery.c +25 -24
  56. data/ext/libdatadog_extconf_helpers.rb +107 -14
  57. data/lib/datadog/ai_guard/api_client.rb +84 -0
  58. data/lib/datadog/ai_guard/autoload.rb +10 -0
  59. data/lib/datadog/ai_guard/component.rb +44 -0
  60. data/lib/datadog/ai_guard/configuration/ext.rb +17 -0
  61. data/lib/datadog/ai_guard/configuration.rb +115 -0
  62. data/lib/datadog/ai_guard/contrib/auto_instrument.rb +24 -0
  63. data/lib/datadog/ai_guard/contrib/integration.rb +37 -0
  64. data/lib/datadog/ai_guard/contrib/rack/integration.rb +42 -0
  65. data/lib/datadog/ai_guard/contrib/rack/patcher.rb +26 -0
  66. data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +97 -0
  67. data/lib/datadog/ai_guard/contrib/rails/integration.rb +41 -0
  68. data/lib/datadog/ai_guard/contrib/rails/patcher.rb +97 -0
  69. data/lib/datadog/ai_guard/contrib/ruby_llm/chat_instrumentation.rb +80 -0
  70. data/lib/datadog/ai_guard/contrib/ruby_llm/integration.rb +41 -0
  71. data/lib/datadog/ai_guard/contrib/ruby_llm/patcher.rb +30 -0
  72. data/lib/datadog/ai_guard/evaluation/content_builder.rb +31 -0
  73. data/lib/datadog/ai_guard/evaluation/content_part.rb +36 -0
  74. data/lib/datadog/ai_guard/evaluation/message.rb +25 -0
  75. data/lib/datadog/ai_guard/evaluation/no_op_result.rb +36 -0
  76. data/lib/datadog/ai_guard/evaluation/request.rb +86 -0
  77. data/lib/datadog/ai_guard/evaluation/result.rb +45 -0
  78. data/lib/datadog/ai_guard/evaluation/tool_call.rb +18 -0
  79. data/lib/datadog/ai_guard/evaluation.rb +108 -0
  80. data/lib/datadog/ai_guard/ext.rb +29 -0
  81. data/lib/datadog/ai_guard.rb +181 -0
  82. data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +26 -0
  83. data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +66 -0
  84. data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +36 -0
  85. data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +26 -0
  86. data/lib/datadog/appsec/api_security/endpoint_collection.rb +10 -0
  87. data/lib/datadog/appsec/api_security/route_extractor.rb +104 -0
  88. data/lib/datadog/appsec/api_security/sampler.rb +62 -0
  89. data/lib/datadog/appsec/api_security.rb +14 -0
  90. data/lib/datadog/appsec/assets/blocked.html +10 -1
  91. data/lib/datadog/appsec/assets/blocked.json +1 -1
  92. data/lib/datadog/appsec/assets/blocked.text +3 -1
  93. data/lib/datadog/appsec/assets/waf_rules/README.md +30 -36
  94. data/lib/datadog/appsec/assets/waf_rules/recommended.json +601 -74
  95. data/lib/datadog/appsec/assets/waf_rules/strict.json +48 -75
  96. data/lib/datadog/appsec/assets.rb +1 -1
  97. data/lib/datadog/appsec/autoload.rb +2 -2
  98. data/lib/datadog/appsec/component.rb +37 -64
  99. data/lib/datadog/appsec/compressed_json.rb +3 -3
  100. data/lib/datadog/appsec/configuration.rb +427 -1
  101. data/lib/datadog/appsec/context.rb +77 -16
  102. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +3 -1
  103. data/lib/datadog/appsec/contrib/active_record/integration.rb +1 -1
  104. data/lib/datadog/appsec/contrib/active_record/patcher.rb +4 -1
  105. data/lib/datadog/appsec/contrib/aws_lambda/gateway/watcher.rb +75 -0
  106. data/lib/datadog/appsec/contrib/aws_lambda/integration.rb +39 -0
  107. data/lib/datadog/appsec/contrib/aws_lambda/patcher.rb +30 -0
  108. data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +144 -0
  109. data/lib/datadog/appsec/contrib/devise/integration.rb +1 -1
  110. data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +4 -2
  111. data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +2 -1
  112. data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +1 -1
  113. data/lib/datadog/appsec/contrib/excon/integration.rb +1 -1
  114. data/lib/datadog/appsec/contrib/excon/patcher.rb +3 -1
  115. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +152 -13
  116. data/lib/datadog/appsec/contrib/faraday/integration.rb +1 -1
  117. data/lib/datadog/appsec/contrib/faraday/patcher.rb +1 -1
  118. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +138 -13
  119. data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +74 -24
  120. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +4 -2
  121. data/lib/datadog/appsec/contrib/graphql/integration.rb +2 -1
  122. data/lib/datadog/appsec/contrib/rack/buffered_input.rb +83 -0
  123. data/lib/datadog/appsec/contrib/rack/ext.rb +1 -1
  124. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +47 -13
  125. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +40 -19
  126. data/lib/datadog/appsec/contrib/rack/input_peeker.rb +79 -0
  127. data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
  128. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +80 -62
  129. data/lib/datadog/appsec/contrib/rack/response_body.rb +36 -0
  130. data/lib/datadog/appsec/contrib/rails/gateway/request.rb +35 -1
  131. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +47 -5
  132. data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
  133. data/lib/datadog/appsec/contrib/rails/patcher.rb +52 -26
  134. data/lib/datadog/appsec/contrib/rails/patches/process_action_patch.rb +29 -0
  135. data/lib/datadog/appsec/contrib/rails/patches/render_to_body_patch.rb +33 -0
  136. data/lib/datadog/appsec/contrib/rest_client/integration.rb +1 -1
  137. data/lib/datadog/appsec/contrib/rest_client/patcher.rb +3 -1
  138. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +167 -12
  139. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +63 -10
  140. data/lib/datadog/appsec/contrib/sinatra/integration.rb +1 -1
  141. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +11 -21
  142. data/lib/datadog/appsec/contrib/sinatra/patches/json_patch.rb +31 -0
  143. data/lib/datadog/appsec/counter_sampler.rb +25 -0
  144. data/lib/datadog/appsec/default_header_tags.rb +52 -0
  145. data/lib/datadog/appsec/event.rb +14 -47
  146. data/lib/datadog/appsec/ext.rb +3 -0
  147. data/lib/datadog/appsec/instrumentation/gateway/argument.rb +17 -1
  148. data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +2 -3
  149. data/lib/datadog/appsec/instrumentation/gateway.rb +2 -15
  150. data/lib/datadog/appsec/metrics/collector.rb +47 -5
  151. data/lib/datadog/appsec/metrics/exporter.rb +16 -3
  152. data/lib/datadog/appsec/metrics/telemetry.rb +21 -4
  153. data/lib/datadog/appsec/metrics/telemetry_exporter.rb +47 -0
  154. data/lib/datadog/appsec/metrics.rb +5 -4
  155. data/lib/datadog/appsec/monitor/gateway/watcher.rb +8 -6
  156. data/lib/datadog/appsec/processor/rule_loader.rb +5 -6
  157. data/lib/datadog/appsec/remote.rb +51 -76
  158. data/lib/datadog/appsec/response.rb +18 -4
  159. data/lib/datadog/appsec/route_normalizer/rails_route_pattern.rb +176 -0
  160. data/lib/datadog/appsec/route_normalizer/route_pattern.rb +378 -0
  161. data/lib/datadog/appsec/route_normalizer/route_text.rb +57 -0
  162. data/lib/datadog/appsec/route_normalizer.rb +80 -0
  163. data/lib/datadog/appsec/security_engine/engine.rb +197 -0
  164. data/lib/datadog/appsec/security_engine/result.rb +45 -9
  165. data/lib/datadog/appsec/security_engine/runner.rb +44 -21
  166. data/lib/datadog/appsec/security_event.rb +5 -7
  167. data/lib/datadog/appsec/thread_safe_ref.rb +61 -0
  168. data/lib/datadog/appsec/trace_keeper.rb +36 -0
  169. data/lib/datadog/appsec/utils/hash_coercion.rb +23 -0
  170. data/lib/datadog/appsec/utils/http/body.rb +38 -0
  171. data/lib/datadog/appsec/utils/http/body_reader.rb +61 -0
  172. data/lib/datadog/appsec/utils/http/media_range.rb +2 -1
  173. data/lib/datadog/appsec/utils/http/media_type.rb +32 -26
  174. data/lib/datadog/appsec/utils/http/url_encoded.rb +52 -0
  175. data/lib/datadog/appsec.rb +10 -17
  176. data/lib/datadog/auto_instrument_base.rb +2 -1
  177. data/lib/datadog/core/configuration/agent_settings.rb +52 -0
  178. data/lib/datadog/core/configuration/agent_settings_resolver.rb +5 -47
  179. data/lib/datadog/core/configuration/base.rb +17 -5
  180. data/lib/datadog/core/configuration/components.rb +192 -20
  181. data/lib/datadog/core/configuration/components_state.rb +6 -1
  182. data/lib/datadog/core/configuration/config_helper.rb +109 -0
  183. data/lib/datadog/core/configuration/deprecations.rb +36 -0
  184. data/lib/datadog/core/configuration/ext.rb +0 -1
  185. data/lib/datadog/core/configuration/option.rb +95 -65
  186. data/lib/datadog/core/configuration/option_definition.rb +42 -23
  187. data/lib/datadog/core/configuration/options.rb +57 -18
  188. data/lib/datadog/core/configuration/settings.rb +160 -25
  189. data/lib/datadog/core/configuration/stable_config.rb +11 -2
  190. data/lib/datadog/core/configuration/supported_configurations.rb +413 -0
  191. data/lib/datadog/core/configuration.rb +4 -4
  192. data/lib/datadog/core/contrib/rails/railtie.rb +32 -0
  193. data/lib/datadog/core/contrib/rails/utils.rb +7 -3
  194. data/lib/datadog/core/crashtracking/component.rb +73 -21
  195. data/lib/datadog/core/crashtracking/tag_builder.rb +9 -21
  196. data/lib/datadog/core/ddsketch.rb +19 -0
  197. data/lib/datadog/core/deprecations.rb +2 -2
  198. data/lib/datadog/core/diagnostics/environment_logger.rb +3 -1
  199. data/lib/datadog/core/environment/agent_info.rb +65 -1
  200. data/lib/datadog/core/environment/cgroup.rb +52 -25
  201. data/lib/datadog/core/environment/container.rb +140 -46
  202. data/lib/datadog/core/environment/ext.rb +13 -2
  203. data/lib/datadog/core/environment/git.rb +2 -2
  204. data/lib/datadog/core/environment/identity.rb +40 -4
  205. data/lib/datadog/core/environment/process.rb +122 -0
  206. data/lib/datadog/core/environment/socket.rb +13 -0
  207. data/lib/datadog/core/environment/variable_helpers.rb +3 -3
  208. data/lib/datadog/core/environment/yjit.rb +2 -1
  209. data/lib/datadog/core/error.rb +6 -6
  210. data/lib/datadog/core/evp.rb +11 -0
  211. data/lib/datadog/core/feature_flags.rb +61 -0
  212. data/lib/datadog/core/knuth_sampler.rb +57 -0
  213. data/lib/datadog/core/logger.rb +1 -1
  214. data/lib/datadog/core/metrics/client.rb +7 -7
  215. data/lib/datadog/core/metrics/logging.rb +1 -1
  216. data/lib/datadog/core/pin.rb +8 -8
  217. data/lib/datadog/core/process_discovery/tracer_memfd.rb +13 -0
  218. data/lib/datadog/core/process_discovery.rb +51 -21
  219. data/lib/datadog/core/rate_limiter.rb +11 -1
  220. data/lib/datadog/core/remote/client/capabilities.rb +49 -6
  221. data/lib/datadog/core/remote/client.rb +15 -7
  222. data/lib/datadog/core/remote/component.rb +64 -36
  223. data/lib/datadog/core/remote/configuration/content.rb +15 -2
  224. data/lib/datadog/core/remote/configuration/digest.rb +14 -7
  225. data/lib/datadog/core/remote/configuration/repository.rb +13 -1
  226. data/lib/datadog/core/remote/configuration/target.rb +13 -6
  227. data/lib/datadog/core/remote/transport/config.rb +9 -36
  228. data/lib/datadog/core/remote/transport/http/config.rb +15 -55
  229. data/lib/datadog/core/remote/transport/http/negotiation.rb +14 -44
  230. data/lib/datadog/core/remote/transport/http.rb +15 -24
  231. data/lib/datadog/core/remote/transport/negotiation.rb +8 -33
  232. data/lib/datadog/core/remote/worker.rb +25 -37
  233. data/lib/datadog/core/runtime/ext.rb +0 -1
  234. data/lib/datadog/core/runtime/metrics.rb +11 -2
  235. data/lib/datadog/core/semaphore.rb +1 -4
  236. data/lib/datadog/core/tag_builder.rb +52 -0
  237. data/lib/datadog/core/tag_normalizer.rb +84 -0
  238. data/lib/datadog/core/telemetry/component.rb +65 -17
  239. data/lib/datadog/core/telemetry/emitter.rb +6 -6
  240. data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +3 -3
  241. data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +30 -0
  242. data/lib/datadog/core/telemetry/event/app_extended_heartbeat.rb +32 -0
  243. data/lib/datadog/core/telemetry/event/app_started.rb +203 -89
  244. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +27 -4
  245. data/lib/datadog/core/telemetry/event.rb +2 -7
  246. data/lib/datadog/core/telemetry/ext.rb +1 -0
  247. data/lib/datadog/core/telemetry/logger.rb +5 -2
  248. data/lib/datadog/core/telemetry/logging.rb +22 -4
  249. data/lib/datadog/core/telemetry/metrics_manager.rb +9 -0
  250. data/lib/datadog/core/telemetry/request.rb +17 -5
  251. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +8 -34
  252. data/lib/datadog/core/telemetry/transport/http.rb +21 -16
  253. data/lib/datadog/core/telemetry/transport/telemetry.rb +8 -17
  254. data/lib/datadog/core/telemetry/worker.rb +108 -32
  255. data/lib/datadog/core/transport/ext.rb +3 -0
  256. data/lib/datadog/core/transport/http/adapters/net.rb +17 -2
  257. data/lib/datadog/core/transport/http/api/endpoint.rb +9 -4
  258. data/lib/datadog/core/transport/http/api/instance.rb +4 -21
  259. data/lib/datadog/core/transport/http/builder.rb +11 -7
  260. data/lib/datadog/core/transport/http/client.rb +80 -0
  261. data/lib/datadog/core/transport/http/env.rb +8 -0
  262. data/lib/datadog/core/transport/http/response.rb +4 -0
  263. data/lib/datadog/core/transport/http.rb +24 -19
  264. data/lib/datadog/core/transport/parcel.rb +61 -9
  265. data/lib/datadog/core/transport/response.rb +16 -2
  266. data/lib/datadog/core/transport/transport.rb +90 -0
  267. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +1 -1
  268. data/lib/datadog/core/utils/{base64.rb → base64_codec.rb} +4 -3
  269. data/lib/datadog/core/utils/enumerable_compat.rb +29 -0
  270. data/lib/datadog/core/utils/fnv.rb +26 -0
  271. data/lib/datadog/core/utils/forking.rb +3 -1
  272. data/lib/datadog/core/utils/hash.rb +0 -23
  273. data/lib/datadog/{appsec/api_security → core/utils}/lru_cache.rb +10 -14
  274. data/lib/datadog/core/utils/network.rb +22 -1
  275. data/lib/datadog/core/utils/only_once.rb +1 -1
  276. data/lib/datadog/core/utils/only_once_successful.rb +8 -2
  277. data/lib/datadog/core/utils/safe_dup.rb +2 -2
  278. data/lib/datadog/core/utils/sequence.rb +2 -0
  279. data/lib/datadog/core/utils/spawn_monkey_patch.rb +68 -0
  280. data/lib/datadog/core/utils/time.rb +1 -1
  281. data/lib/datadog/core/utils.rb +10 -1
  282. data/lib/datadog/core/workers/async.rb +11 -2
  283. data/lib/datadog/core/workers/interval_loop.rb +51 -3
  284. data/lib/datadog/core/workers/polling.rb +2 -0
  285. data/lib/datadog/core/workers/queue.rb +96 -1
  286. data/lib/datadog/core/workers/runtime_metrics.rb +9 -1
  287. data/lib/datadog/core.rb +11 -2
  288. data/lib/datadog/data_streams/configuration.rb +50 -0
  289. data/lib/datadog/data_streams/ext.rb +11 -0
  290. data/lib/datadog/data_streams/extensions.rb +16 -0
  291. data/lib/datadog/data_streams/pathway_context.rb +169 -0
  292. data/lib/datadog/data_streams/processor.rb +511 -0
  293. data/lib/datadog/data_streams/transport/http/stats.rb +58 -0
  294. data/lib/datadog/data_streams/transport/http.rb +36 -0
  295. data/lib/datadog/data_streams/transport/stats.rb +39 -0
  296. data/lib/datadog/data_streams.rb +100 -0
  297. data/lib/datadog/di/base.rb +15 -7
  298. data/lib/datadog/di/boot.rb +11 -1
  299. data/lib/datadog/di/code_tracker.rb +217 -15
  300. data/lib/datadog/di/component.rb +143 -48
  301. data/lib/datadog/di/configuration.rb +235 -2
  302. data/lib/datadog/di/context.rb +76 -0
  303. data/lib/datadog/di/contrib/active_record.rb +34 -5
  304. data/lib/datadog/di/el/compiler.rb +168 -0
  305. data/lib/datadog/di/el/evaluator.rb +159 -0
  306. data/lib/datadog/di/el/expression.rb +42 -0
  307. data/lib/datadog/di/el.rb +5 -0
  308. data/lib/datadog/di/error.rb +44 -0
  309. data/lib/datadog/di/fatal_exceptions.rb +26 -0
  310. data/lib/datadog/di/instrumenter.rb +620 -132
  311. data/lib/datadog/di/logger.rb +2 -2
  312. data/lib/datadog/di/probe.rb +78 -15
  313. data/lib/datadog/di/probe_builder.rb +42 -3
  314. data/lib/datadog/di/probe_file_loader/railtie.rb +15 -0
  315. data/lib/datadog/di/probe_file_loader.rb +87 -0
  316. data/lib/datadog/di/probe_manager.rb +195 -100
  317. data/lib/datadog/di/probe_notification_builder.rb +285 -100
  318. data/lib/datadog/di/probe_notifier_worker.rb +120 -36
  319. data/lib/datadog/di/probe_repository.rb +198 -0
  320. data/lib/datadog/di/proc_responder.rb +36 -0
  321. data/lib/datadog/di/redactor.rb +24 -2
  322. data/lib/datadog/di/remote.rb +258 -95
  323. data/lib/datadog/di/serializer.rb +297 -20
  324. data/lib/datadog/di/transport/diagnostics.rb +12 -42
  325. data/lib/datadog/di/transport/http/diagnostics.rb +4 -34
  326. data/lib/datadog/di/transport/http/input.rb +12 -34
  327. data/lib/datadog/di/transport/http.rb +43 -19
  328. data/lib/datadog/di/transport/input.rb +121 -39
  329. data/lib/datadog/di/utils.rb +42 -14
  330. data/lib/datadog/di.rb +203 -10
  331. data/lib/datadog/error_tracking/collector.rb +2 -1
  332. data/lib/datadog/error_tracking/component.rb +2 -2
  333. data/lib/datadog/error_tracking/configuration.rb +55 -2
  334. data/lib/datadog/error_tracking/filters.rb +2 -2
  335. data/lib/datadog/kit/appsec/events/v2.rb +253 -0
  336. data/lib/datadog/kit/appsec/events.rb +11 -10
  337. data/lib/datadog/kit/enable_core_dumps.rb +1 -1
  338. data/lib/datadog/kit/identity.rb +17 -11
  339. data/lib/datadog/kit/tracing/method_tracer.rb +135 -0
  340. data/lib/datadog/open_feature/component.rb +100 -0
  341. data/lib/datadog/open_feature/configuration.rb +37 -0
  342. data/lib/datadog/open_feature/evaluation_engine.rb +70 -0
  343. data/lib/datadog/open_feature/exposures/batch_builder.rb +32 -0
  344. data/lib/datadog/open_feature/exposures/buffer.rb +43 -0
  345. data/lib/datadog/open_feature/exposures/deduplicator.rb +30 -0
  346. data/lib/datadog/open_feature/exposures/event.rb +60 -0
  347. data/lib/datadog/open_feature/exposures/reporter.rb +40 -0
  348. data/lib/datadog/open_feature/exposures/worker.rb +116 -0
  349. data/lib/datadog/open_feature/ext.rb +16 -0
  350. data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +286 -0
  351. data/lib/datadog/open_feature/flag_evaluation/writer.rb +433 -0
  352. data/lib/datadog/open_feature/hooks/flag_eval_evp_hook.rb +101 -0
  353. data/lib/datadog/open_feature/hooks/flag_eval_metrics_hook.rb +49 -0
  354. data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +149 -0
  355. data/lib/datadog/open_feature/native_evaluator.rb +60 -0
  356. data/lib/datadog/open_feature/noop_evaluator.rb +26 -0
  357. data/lib/datadog/open_feature/provider.rb +191 -0
  358. data/lib/datadog/open_feature/remote.rb +67 -0
  359. data/lib/datadog/open_feature/resolution_details.rb +35 -0
  360. data/lib/datadog/open_feature/transport.rb +121 -0
  361. data/lib/datadog/open_feature.rb +19 -0
  362. data/lib/datadog/opentelemetry/api/baggage.rb +3 -3
  363. data/lib/datadog/opentelemetry/api/context.rb +10 -9
  364. data/lib/datadog/opentelemetry/configuration/settings.rb +226 -0
  365. data/lib/datadog/opentelemetry/ext.rb +9 -0
  366. data/lib/datadog/opentelemetry/logs.rb +98 -0
  367. data/lib/datadog/opentelemetry/metrics.rb +90 -0
  368. data/lib/datadog/opentelemetry/sdk/configurator.rb +66 -2
  369. data/lib/datadog/opentelemetry/sdk/id_generator.rb +16 -10
  370. data/lib/datadog/opentelemetry/sdk/logs_exporter.rb +30 -0
  371. data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +28 -0
  372. data/lib/datadog/opentelemetry/sdk/propagator.rb +13 -7
  373. data/lib/datadog/opentelemetry/sdk/span_processor.rb +12 -9
  374. data/lib/datadog/opentelemetry/sdk/trace/span.rb +14 -10
  375. data/lib/datadog/opentelemetry/sdk.rb +19 -0
  376. data/lib/datadog/opentelemetry/signal_configuration.rb +53 -0
  377. data/lib/datadog/opentelemetry/trace.rb +4 -4
  378. data/lib/datadog/opentelemetry.rb +4 -0
  379. data/lib/datadog/profiling/collectors/code_provenance.rb +83 -15
  380. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +52 -3
  381. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +13 -4
  382. data/lib/datadog/profiling/collectors/info.rb +59 -4
  383. data/lib/datadog/profiling/collectors/thread_context.rb +17 -5
  384. data/lib/datadog/profiling/component.rb +73 -49
  385. data/lib/datadog/profiling/exporter.rb +48 -13
  386. data/lib/datadog/profiling/ext/dir_monkey_patches.rb +24 -5
  387. data/lib/datadog/profiling/ext/exec_monkey_patch.rb +32 -0
  388. data/lib/datadog/profiling/ext.rb +2 -15
  389. data/lib/datadog/profiling/flush.rb +23 -11
  390. data/lib/datadog/profiling/http_transport.rb +24 -11
  391. data/lib/datadog/profiling/load_native_extension.rb +2 -2
  392. data/lib/datadog/profiling/profiler.rb +31 -12
  393. data/lib/datadog/profiling/scheduler.rb +12 -10
  394. data/lib/datadog/profiling/sequence_tracker.rb +44 -0
  395. data/lib/datadog/profiling/stack_recorder.rb +5 -13
  396. data/lib/datadog/profiling/tag_builder.rb +42 -38
  397. data/lib/datadog/profiling/tasks/exec.rb +10 -5
  398. data/lib/datadog/profiling/tasks/help.rb +1 -0
  399. data/lib/datadog/profiling/tasks/setup.rb +4 -2
  400. data/lib/datadog/profiling.rb +8 -11
  401. data/lib/datadog/ruby_version.rb +25 -0
  402. data/lib/datadog/single_step_instrument.rb +10 -1
  403. data/lib/datadog/symbol_database/component.rb +734 -0
  404. data/lib/datadog/symbol_database/configuration.rb +73 -0
  405. data/lib/datadog/symbol_database/extensions.rb +19 -0
  406. data/lib/datadog/symbol_database/extractor.rb +1110 -0
  407. data/lib/datadog/symbol_database/file_hash.rb +48 -0
  408. data/lib/datadog/symbol_database/logger.rb +43 -0
  409. data/lib/datadog/symbol_database/remote.rb +180 -0
  410. data/lib/datadog/symbol_database/scope.rb +102 -0
  411. data/lib/datadog/symbol_database/scope_batcher.rb +292 -0
  412. data/lib/datadog/symbol_database/service_version.rb +66 -0
  413. data/lib/datadog/symbol_database/symbol.rb +69 -0
  414. data/lib/datadog/symbol_database/transport/http/endpoint.rb +28 -0
  415. data/lib/datadog/symbol_database/transport/http.rb +45 -0
  416. data/lib/datadog/symbol_database/transport.rb +54 -0
  417. data/lib/datadog/symbol_database/uploader.rb +230 -0
  418. data/lib/datadog/symbol_database.rb +71 -0
  419. data/lib/datadog/tracing/analytics.rb +1 -1
  420. data/lib/datadog/tracing/buffer.rb +10 -10
  421. data/lib/datadog/tracing/component.rb +17 -17
  422. data/lib/datadog/tracing/configuration/dynamic.rb +6 -8
  423. data/lib/datadog/tracing/configuration/ext.rb +25 -5
  424. data/lib/datadog/tracing/configuration/settings.rb +125 -11
  425. data/lib/datadog/tracing/context.rb +2 -2
  426. data/lib/datadog/tracing/contrib/action_cable/event.rb +1 -1
  427. data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +4 -1
  428. data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +4 -1
  429. data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +4 -1
  430. data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +4 -1
  431. data/lib/datadog/tracing/contrib/action_cable/integration.rb +1 -1
  432. data/lib/datadog/tracing/contrib/action_mailer/event.rb +4 -1
  433. data/lib/datadog/tracing/contrib/action_mailer/integration.rb +1 -1
  434. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +29 -11
  435. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +47 -12
  436. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +3 -1
  437. data/lib/datadog/tracing/contrib/action_pack/ext.rb +2 -0
  438. data/lib/datadog/tracing/contrib/action_pack/integration.rb +1 -1
  439. data/lib/datadog/tracing/contrib/action_pack/utils.rb +1 -2
  440. data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +4 -1
  441. data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +6 -3
  442. data/lib/datadog/tracing/contrib/active_job/event.rb +8 -8
  443. data/lib/datadog/tracing/contrib/active_job/events/discard.rb +6 -3
  444. data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +6 -3
  445. data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +6 -3
  446. data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +6 -3
  447. data/lib/datadog/tracing/contrib/active_job/events/perform.rb +6 -3
  448. data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +6 -3
  449. data/lib/datadog/tracing/contrib/active_job/integration.rb +1 -1
  450. data/lib/datadog/tracing/contrib/active_job/log_injection.rb +21 -7
  451. data/lib/datadog/tracing/contrib/active_job/patcher.rb +5 -1
  452. data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +2 -2
  453. data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +4 -4
  454. data/lib/datadog/tracing/contrib/active_model_serializers/integration.rb +1 -2
  455. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +3 -3
  456. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +2 -2
  457. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +7 -10
  458. data/lib/datadog/tracing/contrib/active_record/integration.rb +1 -1
  459. data/lib/datadog/tracing/contrib/active_record/utils.rb +16 -16
  460. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +15 -12
  461. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +1 -4
  462. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +13 -0
  463. data/lib/datadog/tracing/contrib/active_support/integration.rb +1 -1
  464. data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +2 -1
  465. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +8 -10
  466. data/lib/datadog/tracing/contrib/aws/ext.rb +1 -1
  467. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +8 -10
  468. data/lib/datadog/tracing/contrib/aws/parsed_context.rb +3 -1
  469. data/lib/datadog/tracing/contrib/aws/patcher.rb +5 -1
  470. data/lib/datadog/tracing/contrib/aws/service/base.rb +2 -1
  471. data/lib/datadog/tracing/contrib/aws/service/dynamodb.rb +1 -1
  472. data/lib/datadog/tracing/contrib/aws/service/eventbridge.rb +1 -1
  473. data/lib/datadog/tracing/contrib/aws/service/kinesis.rb +1 -1
  474. data/lib/datadog/tracing/contrib/aws/service/s3.rb +1 -1
  475. data/lib/datadog/tracing/contrib/aws/service/sns.rb +1 -1
  476. data/lib/datadog/tracing/contrib/aws/service/sqs.rb +1 -1
  477. data/lib/datadog/tracing/contrib/aws/service/states.rb +1 -1
  478. data/lib/datadog/tracing/contrib/aws/services.rb +7 -7
  479. data/lib/datadog/tracing/contrib/component.rb +3 -3
  480. data/lib/datadog/tracing/contrib/concurrent_ruby/async_patch.rb +1 -1
  481. data/lib/datadog/tracing/contrib/concurrent_ruby/context_composite_executor_service.rb +1 -1
  482. data/lib/datadog/tracing/contrib/concurrent_ruby/future_patch.rb +1 -1
  483. data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +1 -1
  484. data/lib/datadog/tracing/contrib/concurrent_ruby/promises_future_patch.rb +1 -1
  485. data/lib/datadog/tracing/contrib/configurable.rb +22 -7
  486. data/lib/datadog/tracing/contrib/configuration/resolver.rb +14 -4
  487. data/lib/datadog/tracing/contrib/configuration/resolvers/pattern_resolver.rb +4 -4
  488. data/lib/datadog/tracing/contrib/dalli/ext.rb +3 -2
  489. data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +1 -5
  490. data/lib/datadog/tracing/contrib/dalli/integration.rb +5 -2
  491. data/lib/datadog/tracing/contrib/dalli/quantize.rb +1 -1
  492. data/lib/datadog/tracing/contrib/delayed_job/integration.rb +1 -1
  493. data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +2 -0
  494. data/lib/datadog/tracing/contrib/delayed_job/server_internal_tracer/worker.rb +1 -0
  495. data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +3 -2
  496. data/lib/datadog/tracing/contrib/elasticsearch/integration.rb +4 -4
  497. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +47 -53
  498. data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +7 -7
  499. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +5 -1
  500. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +7 -8
  501. data/lib/datadog/tracing/contrib/ethon/ext.rb +4 -2
  502. data/lib/datadog/tracing/contrib/ethon/integration.rb +1 -1
  503. data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +1 -8
  504. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +16 -5
  505. data/lib/datadog/tracing/contrib/excon/ext.rb +4 -2
  506. data/lib/datadog/tracing/contrib/excon/integration.rb +1 -1
  507. data/lib/datadog/tracing/contrib/excon/middleware.rb +5 -9
  508. data/lib/datadog/tracing/contrib/ext.rb +6 -4
  509. data/lib/datadog/tracing/contrib/extensions.rb +28 -11
  510. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +16 -9
  511. data/lib/datadog/tracing/contrib/faraday/ext.rb +4 -2
  512. data/lib/datadog/tracing/contrib/faraday/integration.rb +1 -1
  513. data/lib/datadog/tracing/contrib/faraday/middleware.rb +7 -9
  514. data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +7 -3
  515. data/lib/datadog/tracing/contrib/grape/endpoint.rb +18 -15
  516. data/lib/datadog/tracing/contrib/grape/instrumentation.rb +13 -8
  517. data/lib/datadog/tracing/contrib/grape/integration.rb +1 -1
  518. data/lib/datadog/tracing/contrib/grape/patcher.rb +6 -1
  519. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +7 -0
  520. data/lib/datadog/tracing/contrib/graphql/ext.rb +1 -0
  521. data/lib/datadog/tracing/contrib/graphql/integration.rb +1 -1
  522. data/lib/datadog/tracing/contrib/graphql/patcher.rb +2 -2
  523. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +105 -63
  524. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +5 -2
  525. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +11 -15
  526. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +6 -10
  527. data/lib/datadog/tracing/contrib/grpc/distributed/fetcher.rb +1 -1
  528. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +2 -0
  529. data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
  530. data/lib/datadog/tracing/contrib/grpc/integration.rb +1 -1
  531. data/lib/datadog/tracing/contrib/grpc.rb +1 -0
  532. data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +1 -0
  533. data/lib/datadog/tracing/contrib/hanami/ext.rb +2 -2
  534. data/lib/datadog/tracing/contrib/hanami/integration.rb +1 -1
  535. data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +2 -1
  536. data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +10 -11
  537. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +16 -5
  538. data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +4 -4
  539. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +2 -0
  540. data/lib/datadog/tracing/contrib/http/ext.rb +4 -2
  541. data/lib/datadog/tracing/contrib/http/instrumentation.rb +9 -13
  542. data/lib/datadog/tracing/contrib/http/integration.rb +0 -2
  543. data/lib/datadog/tracing/contrib/http.rb +1 -0
  544. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +16 -5
  545. data/lib/datadog/tracing/contrib/httpclient/ext.rb +4 -2
  546. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +10 -10
  547. data/lib/datadog/tracing/contrib/httpclient/integration.rb +1 -1
  548. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +16 -5
  549. data/lib/datadog/tracing/contrib/httprb/ext.rb +4 -2
  550. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +8 -12
  551. data/lib/datadog/tracing/contrib/httprb/integration.rb +1 -1
  552. data/lib/datadog/tracing/contrib/kafka/event.rb +2 -1
  553. data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +1 -1
  554. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +1 -1
  555. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +1 -1
  556. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +1 -1
  557. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/join_group.rb +1 -1
  558. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/leave_group.rb +1 -1
  559. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/sync_group.rb +1 -1
  560. data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +1 -1
  561. data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +1 -1
  562. data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +66 -0
  563. data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +66 -0
  564. data/lib/datadog/tracing/contrib/kafka/integration.rb +1 -1
  565. data/lib/datadog/tracing/contrib/kafka/patcher.rb +14 -0
  566. data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +5 -1
  567. data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +2 -0
  568. data/lib/datadog/tracing/contrib/karafka/ext.rb +1 -0
  569. data/lib/datadog/tracing/contrib/karafka/framework.rb +30 -0
  570. data/lib/datadog/tracing/contrib/karafka/monitor.rb +24 -13
  571. data/lib/datadog/tracing/contrib/karafka/patcher.rb +39 -8
  572. data/lib/datadog/tracing/contrib/karafka.rb +1 -0
  573. data/lib/datadog/tracing/contrib/lograge/instrumentation.rb +1 -1
  574. data/lib/datadog/tracing/contrib/lograge/integration.rb +1 -1
  575. data/lib/datadog/tracing/contrib/lograge/patcher.rb +4 -2
  576. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +1 -1
  577. data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -1
  578. data/lib/datadog/tracing/contrib/mongodb/integration.rb +1 -1
  579. data/lib/datadog/tracing/contrib/mongodb/parsers.rb +6 -6
  580. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +11 -14
  581. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +6 -0
  582. data/lib/datadog/tracing/contrib/mysql2/ext.rb +1 -1
  583. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +19 -12
  584. data/lib/datadog/tracing/contrib/mysql2/integration.rb +1 -1
  585. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +1 -1
  586. data/lib/datadog/tracing/contrib/opensearch/ext.rb +3 -2
  587. data/lib/datadog/tracing/contrib/opensearch/integration.rb +1 -2
  588. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +64 -70
  589. data/lib/datadog/tracing/contrib/opensearch/quantize.rb +7 -7
  590. data/lib/datadog/tracing/contrib/patcher.rb +7 -9
  591. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +6 -0
  592. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +3 -6
  593. data/lib/datadog/tracing/contrib/pg/integration.rb +1 -1
  594. data/lib/datadog/tracing/contrib/presto/ext.rb +1 -1
  595. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +9 -11
  596. data/lib/datadog/tracing/contrib/presto/integration.rb +1 -1
  597. data/lib/datadog/tracing/contrib/propagation/sql_comment/comment.rb +1 -1
  598. data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +13 -0
  599. data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +6 -2
  600. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +25 -1
  601. data/lib/datadog/tracing/contrib/que/configuration/settings.rb +5 -2
  602. data/lib/datadog/tracing/contrib/que/ext.rb +1 -0
  603. data/lib/datadog/tracing/contrib/que/integration.rb +1 -1
  604. data/lib/datadog/tracing/contrib/que/tracer.rb +1 -0
  605. data/lib/datadog/tracing/contrib/racecar/event.rb +2 -6
  606. data/lib/datadog/tracing/contrib/racecar/events/batch.rb +2 -2
  607. data/lib/datadog/tracing/contrib/racecar/events/consume.rb +1 -1
  608. data/lib/datadog/tracing/contrib/racecar/events/message.rb +2 -2
  609. data/lib/datadog/tracing/contrib/racecar/integration.rb +1 -1
  610. data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +11 -1
  611. data/lib/datadog/tracing/contrib/rack/ext.rb +28 -0
  612. data/lib/datadog/tracing/contrib/rack/header_collection.rb +1 -1
  613. data/lib/datadog/tracing/contrib/rack/header_tagging.rb +55 -32
  614. data/lib/datadog/tracing/contrib/rack/integration.rb +1 -1
  615. data/lib/datadog/tracing/contrib/rack/middlewares.rb +83 -44
  616. data/lib/datadog/tracing/contrib/rack/patcher.rb +2 -2
  617. data/lib/datadog/tracing/contrib/rack/request_queue.rb +4 -3
  618. data/lib/datadog/tracing/contrib/rack/route_inference.rb +67 -0
  619. data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +126 -2
  620. data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +6 -3
  621. data/lib/datadog/tracing/contrib/rails/ext.rb +3 -1
  622. data/lib/datadog/tracing/contrib/rails/integration.rb +2 -2
  623. data/lib/datadog/tracing/contrib/rails/log_injection.rb +2 -2
  624. data/lib/datadog/tracing/contrib/rails/middlewares.rb +3 -3
  625. data/lib/datadog/tracing/contrib/rails/patcher.rb +4 -2
  626. data/lib/datadog/tracing/contrib/rails/runner.rb +64 -40
  627. data/lib/datadog/tracing/contrib/rake/instrumentation.rb +10 -8
  628. data/lib/datadog/tracing/contrib/rake/integration.rb +1 -1
  629. data/lib/datadog/tracing/contrib/redis/configuration/resolver.rb +2 -2
  630. data/lib/datadog/tracing/contrib/redis/ext.rb +3 -2
  631. data/lib/datadog/tracing/contrib/redis/integration.rb +2 -2
  632. data/lib/datadog/tracing/contrib/redis/patcher.rb +4 -4
  633. data/lib/datadog/tracing/contrib/redis/quantize.rb +2 -2
  634. data/lib/datadog/tracing/contrib/redis/tags.rb +2 -7
  635. data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +6 -4
  636. data/lib/datadog/tracing/contrib/registerable.rb +11 -0
  637. data/lib/datadog/tracing/contrib/registry.rb +1 -1
  638. data/lib/datadog/tracing/contrib/resque/integration.rb +1 -1
  639. data/lib/datadog/tracing/contrib/resque/resque_job.rb +2 -1
  640. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +5 -2
  641. data/lib/datadog/tracing/contrib/rest_client/ext.rb +4 -2
  642. data/lib/datadog/tracing/contrib/rest_client/integration.rb +1 -1
  643. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +8 -9
  644. data/lib/datadog/tracing/contrib/roda/ext.rb +1 -0
  645. data/lib/datadog/tracing/contrib/roda/instrumentation.rb +8 -3
  646. data/lib/datadog/tracing/contrib/roda/integration.rb +1 -1
  647. data/lib/datadog/tracing/contrib/semantic_logger/instrumentation.rb +1 -1
  648. data/lib/datadog/tracing/contrib/semantic_logger/integration.rb +1 -1
  649. data/lib/datadog/tracing/contrib/sequel/database.rb +6 -5
  650. data/lib/datadog/tracing/contrib/sequel/dataset.rb +2 -1
  651. data/lib/datadog/tracing/contrib/sequel/integration.rb +1 -1
  652. data/lib/datadog/tracing/contrib/sequel/utils.rb +1 -6
  653. data/lib/datadog/tracing/contrib/shoryuken/integration.rb +1 -1
  654. data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +1 -0
  655. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +1 -0
  656. data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +5 -1
  657. data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +2 -0
  658. data/lib/datadog/tracing/contrib/sidekiq/ext.rb +2 -0
  659. data/lib/datadog/tracing/contrib/sidekiq/integration.rb +1 -1
  660. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/heartbeat.rb +2 -0
  661. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/job_fetch.rb +1 -0
  662. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/redis_info.rb +1 -0
  663. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/scheduled_poller.rb +2 -0
  664. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/stop.rb +1 -0
  665. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +8 -4
  666. data/lib/datadog/tracing/contrib/sidekiq/utils.rb +1 -1
  667. data/lib/datadog/tracing/contrib/sidekiq.rb +1 -0
  668. data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +5 -1
  669. data/lib/datadog/tracing/contrib/sinatra/ext.rb +1 -0
  670. data/lib/datadog/tracing/contrib/sinatra/integration.rb +1 -1
  671. data/lib/datadog/tracing/contrib/sinatra/tracer.rb +1 -0
  672. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +40 -39
  673. data/lib/datadog/tracing/contrib/sneakers/integration.rb +15 -4
  674. data/lib/datadog/tracing/contrib/sneakers/tracer.rb +1 -0
  675. data/lib/datadog/tracing/contrib/span_attribute_schema.rb +1 -1
  676. data/lib/datadog/tracing/contrib/status_range_matcher.rb +13 -1
  677. data/lib/datadog/tracing/contrib/stripe/integration.rb +1 -1
  678. data/lib/datadog/tracing/contrib/stripe/request.rb +2 -2
  679. data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +1 -0
  680. data/lib/datadog/tracing/contrib/sucker_punch/integration.rb +1 -1
  681. data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +6 -0
  682. data/lib/datadog/tracing/contrib/trilogy/ext.rb +1 -1
  683. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +4 -6
  684. data/lib/datadog/tracing/contrib/trilogy/integration.rb +1 -1
  685. data/lib/datadog/tracing/contrib/utils/quantization/{hash.rb → hash_formatter.rb} +15 -13
  686. data/lib/datadog/tracing/contrib/utils/quantization/http.rb +6 -6
  687. data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +31 -0
  688. data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +50 -0
  689. data/lib/datadog/tracing/contrib/waterdrop/ext.rb +18 -0
  690. data/lib/datadog/tracing/contrib/waterdrop/integration.rb +43 -0
  691. data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +46 -0
  692. data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +49 -0
  693. data/lib/datadog/tracing/contrib/waterdrop/producer.rb +50 -0
  694. data/lib/datadog/tracing/contrib/waterdrop.rb +42 -0
  695. data/lib/datadog/tracing/contrib.rb +9 -0
  696. data/lib/datadog/tracing/diagnostics/environment_logger.rb +12 -4
  697. data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
  698. data/lib/datadog/tracing/distributed/baggage.rb +133 -12
  699. data/lib/datadog/tracing/distributed/datadog.rb +17 -16
  700. data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +11 -26
  701. data/lib/datadog/tracing/distributed/helpers.rb +1 -1
  702. data/lib/datadog/tracing/distributed/none.rb +4 -2
  703. data/lib/datadog/tracing/distributed/propagation.rb +39 -4
  704. data/lib/datadog/tracing/distributed/propagation_policy.rb +1 -1
  705. data/lib/datadog/tracing/distributed/trace_context.rb +107 -78
  706. data/lib/datadog/tracing/event.rb +5 -7
  707. data/lib/datadog/tracing/ext.rb +9 -0
  708. data/lib/datadog/tracing/flush.rb +1 -1
  709. data/lib/datadog/tracing/metadata/analytics.rb +1 -1
  710. data/lib/datadog/tracing/metadata/ext.rb +23 -1
  711. data/lib/datadog/tracing/metadata/tagging.rb +6 -6
  712. data/lib/datadog/tracing/pipeline/span_filter.rb +3 -1
  713. data/lib/datadog/tracing/pipeline/span_processor.rb +3 -1
  714. data/lib/datadog/tracing/pipeline.rb +2 -2
  715. data/lib/datadog/tracing/remote.rb +36 -13
  716. data/lib/datadog/tracing/sampling/ext.rb +2 -2
  717. data/lib/datadog/tracing/sampling/priority_sampler.rb +16 -1
  718. data/lib/datadog/tracing/sampling/rate_sampler.rb +8 -19
  719. data/lib/datadog/tracing/sampling/rule.rb +1 -1
  720. data/lib/datadog/tracing/sampling/rule_sampler.rb +77 -48
  721. data/lib/datadog/tracing/sampling/span/rule_parser.rb +3 -3
  722. data/lib/datadog/tracing/sampling/span/sampler.rb +0 -7
  723. data/lib/datadog/tracing/span.rb +2 -2
  724. data/lib/datadog/tracing/span_event.rb +12 -12
  725. data/lib/datadog/tracing/span_link.rb +12 -12
  726. data/lib/datadog/tracing/span_operation.rb +63 -19
  727. data/lib/datadog/tracing/sync_writer.rb +1 -2
  728. data/lib/datadog/tracing/trace_digest.rb +28 -23
  729. data/lib/datadog/tracing/trace_operation.rb +209 -98
  730. data/lib/datadog/tracing/trace_segment.rb +2 -2
  731. data/lib/datadog/tracing/tracer.rb +113 -52
  732. data/lib/datadog/tracing/transport/http/client.rb +12 -26
  733. data/lib/datadog/tracing/transport/http/traces.rb +4 -52
  734. data/lib/datadog/tracing/transport/http.rb +15 -9
  735. data/lib/datadog/tracing/transport/io/client.rb +11 -14
  736. data/lib/datadog/tracing/transport/io/traces.rb +28 -34
  737. data/lib/datadog/tracing/transport/statistics.rb +1 -1
  738. data/lib/datadog/tracing/transport/trace_formatter.rb +22 -0
  739. data/lib/datadog/tracing/transport/traces.rb +14 -82
  740. data/lib/datadog/tracing/workers.rb +4 -3
  741. data/lib/datadog/tracing/writer.rb +1 -1
  742. data/lib/datadog/tracing.rb +2 -2
  743. data/lib/datadog/version.rb +2 -2
  744. data/lib/datadog.rb +14 -0
  745. metadata +201 -40
  746. data/ext/datadog_profiling_native_extension/clock_id_noop.c +0 -21
  747. data/ext/libdatadog_api/macos_development.md +0 -26
  748. data/lib/datadog/appsec/assets/waf_rules/processors.json +0 -321
  749. data/lib/datadog/appsec/assets/waf_rules/scanners.json +0 -1023
  750. data/lib/datadog/appsec/configuration/settings.rb +0 -342
  751. data/lib/datadog/appsec/contrib/rails/ext.rb +0 -13
  752. data/lib/datadog/appsec/processor/rule_merger.rb +0 -171
  753. data/lib/datadog/appsec/processor.rb +0 -107
  754. data/lib/datadog/core/remote/transport/http/api.rb +0 -53
  755. data/lib/datadog/core/remote/transport/http/client.rb +0 -49
  756. data/lib/datadog/core/telemetry/transport/http/api.rb +0 -43
  757. data/lib/datadog/core/telemetry/transport/http/client.rb +0 -49
  758. data/lib/datadog/core/transport/http/api/spec.rb +0 -36
  759. data/lib/datadog/di/configuration/settings.rb +0 -212
  760. data/lib/datadog/di/transport/http/api.rb +0 -42
  761. data/lib/datadog/di/transport/http/client.rb +0 -47
  762. data/lib/datadog/error_tracking/configuration/settings.rb +0 -63
  763. data/lib/datadog/opentelemetry/api/baggage.rbs +0 -26
  764. data/lib/datadog/tracing/transport/http/api.rb +0 -44
  765. data/lib/datadog/tracing/workers/trace_writer.rb +0 -199
@@ -1,29 +1,46 @@
1
1
  #include <ruby.h>
2
2
  #include <ruby/debug.h>
3
- #include "extconf.h"
4
- #include "helpers.h"
5
- #include "libdatadog_helpers.h"
6
- #include "ruby_helpers.h"
3
+ #include <ruby/st.h>
4
+ #include <stdatomic.h>
5
+
6
+ #include "extconf.h" // This is needed for the HAVE_DLADDR and friends below
7
+
8
+ #if (defined(HAVE_DLADDR1) && HAVE_DLADDR1) || (defined(HAVE_DLADDR) && HAVE_DLADDR)
9
+ #ifndef _GNU_SOURCE
10
+ #define _GNU_SOURCE
11
+ #endif
12
+ #include <dlfcn.h>
13
+ #if defined(HAVE_DLADDR1) && HAVE_DLADDR1
14
+ #include <link.h>
15
+ #endif
16
+ #endif
17
+
18
+ #include "datadog_ruby_common.h"
7
19
  #include "private_vm_api_access.h"
20
+ #include "ruby_helpers.h"
8
21
  #include "stack_recorder.h"
9
22
  #include "collectors_stack.h"
10
23
 
11
24
  // Gathers stack traces from running threads, storing them in a StackRecorder instance
12
25
  // This file implements the native bits of the Datadog::Profiling::Collectors::Stack class
13
26
 
14
- static VALUE missing_string = Qnil;
15
-
16
- // Used as scratch space during sampling
17
- struct sampling_buffer { // Note: typedef'd in the header to sampling_buffer
18
- uint16_t max_frames;
19
- ddog_prof_Location *locations;
20
- frame_info *stack_buffer;
21
- };
22
-
27
+ static VALUE _native_filenames_available(DDTRACE_UNUSED VALUE self);
28
+ static VALUE _native_ruby_native_filename(DDTRACE_UNUSED VALUE self);
23
29
  static VALUE _native_sample(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self);
24
30
  static VALUE native_sample_do(VALUE args);
25
31
  static VALUE native_sample_ensure(VALUE args);
26
- static void maybe_add_placeholder_frames_omitted(VALUE thread, sampling_buffer* buffer, char *frames_omitted_message, int frames_omitted_message_size);
32
+ static void set_file_info_for_cfunc(
33
+ ddog_CharSlice *filename_slice,
34
+ int *line,
35
+ ddog_CharSlice last_ruby_frame_filename,
36
+ int last_ruby_line,
37
+ void *function,
38
+ bool top_of_the_stack,
39
+ bool native_filenames_enabled,
40
+ st_table *native_filenames_cache
41
+ );
42
+ static const char *get_or_compute_native_filename(void *function, st_table *native_filenames_cache);
43
+ static void add_truncated_frames_placeholder(ddog_prof_Location *locations);
27
44
  static void record_placeholder_stack_in_native_code(VALUE recorder_instance, sample_values values, sample_labels labels);
28
45
  static void maybe_trim_template_random_ids(ddog_CharSlice *name_slice, ddog_CharSlice *filename_slice);
29
46
 
@@ -32,16 +49,47 @@ static void maybe_trim_template_random_ids(ddog_CharSlice *name_slice, ddog_Char
32
49
  extern VALUE rb_iseq_path(const VALUE);
33
50
  extern VALUE rb_iseq_base_label(const VALUE);
34
51
 
52
+ // NULL if dladdr is not available or we weren't able to get the native filename for the Ruby VM
53
+ static const char *ruby_native_filename = NULL;
54
+
35
55
  void collectors_stack_init(VALUE profiling_module) {
36
56
  VALUE collectors_module = rb_define_module_under(profiling_module, "Collectors");
37
57
  VALUE collectors_stack_class = rb_define_class_under(collectors_module, "Stack", rb_cObject);
58
+
59
+ rb_define_singleton_method(collectors_stack_class, "_native_filenames_available?", _native_filenames_available, 0);
60
+ rb_define_singleton_method(collectors_stack_class, "_native_ruby_native_filename", _native_ruby_native_filename, 0);
61
+
38
62
  // Hosts methods used for testing the native code using RSpec
39
63
  VALUE testing_module = rb_define_module_under(collectors_stack_class, "Testing");
40
64
 
41
65
  rb_define_singleton_method(testing_module, "_native_sample", _native_sample, -1);
42
66
 
43
- missing_string = rb_str_new2("");
44
- rb_global_variable(&missing_string);
67
+ #if (defined(HAVE_DLADDR1) && HAVE_DLADDR1) || (defined(HAVE_DLADDR) && HAVE_DLADDR)
68
+ // To be able to detect when a frame is coming from Ruby, we record here its filename as returned by dladdr.
69
+ // We expect this same pointer to be returned by dladdr for all frames coming from Ruby.
70
+ //
71
+ // Small note: Creating/deleting the cache is a bit awkward here, but it seems like a bigger footgun to allow
72
+ // `get_or_compute_native_filename` to run without a cache, since we never expect that to happen during sampling. So it seems
73
+ // like a reasonable trade-off to force callers to always figure that out.
74
+ st_table *temporary_cache = st_init_numtable();
75
+ const char *native_filename = get_or_compute_native_filename(rb_ary_new, temporary_cache);
76
+ if (native_filename != NULL && native_filename[0] != '\0') {
77
+ ruby_native_filename = native_filename;
78
+ }
79
+ st_free_table(temporary_cache);
80
+ #endif
81
+ }
82
+
83
+ static VALUE _native_filenames_available(DDTRACE_UNUSED VALUE self) {
84
+ #if (defined(HAVE_DLADDR1) && HAVE_DLADDR1) || (defined(HAVE_DLADDR) && HAVE_DLADDR)
85
+ return ruby_native_filename != NULL ? Qtrue : Qfalse;
86
+ #else
87
+ return Qfalse;
88
+ #endif
89
+ }
90
+
91
+ static VALUE _native_ruby_native_filename(DDTRACE_UNUSED VALUE self) {
92
+ return ruby_native_filename != NULL ? rb_utf8_str_new_cstr(ruby_native_filename) : Qnil;
45
93
  }
46
94
 
47
95
  typedef struct {
@@ -50,8 +98,10 @@ typedef struct {
50
98
  sample_values values;
51
99
  sample_labels labels;
52
100
  VALUE thread;
53
- ddog_prof_Location *locations;
101
+ sample_locations locations;
54
102
  sampling_buffer *buffer;
103
+ bool native_filenames_enabled;
104
+ st_table *native_filenames_cache;
55
105
  } native_sample_args;
56
106
 
57
107
  // This method exists only to enable testing Datadog::Profiling::Collectors::Stack behavior using RSpec.
@@ -73,10 +123,15 @@ static VALUE _native_sample(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self) {
73
123
  VALUE max_frames = rb_hash_lookup2(options, ID2SYM(rb_intern("max_frames")), INT2NUM(400));
74
124
  VALUE in_gc = rb_hash_lookup2(options, ID2SYM(rb_intern("in_gc")), Qfalse);
75
125
  VALUE is_gvl_waiting_state = rb_hash_lookup2(options, ID2SYM(rb_intern("is_gvl_waiting_state")), Qfalse);
126
+ VALUE native_filenames_enabled = rb_hash_lookup2(options, ID2SYM(rb_intern("native_filenames_enabled")), Qfalse);
76
127
 
77
128
  ENFORCE_TYPE(metric_values_hash, T_HASH);
78
129
  ENFORCE_TYPE(labels_array, T_ARRAY);
79
130
  ENFORCE_TYPE(numeric_labels_array, T_ARRAY);
131
+ ENFORCE_TYPE(max_frames, T_FIXNUM);
132
+ ENFORCE_BOOLEAN(in_gc);
133
+ ENFORCE_BOOLEAN(is_gvl_waiting_state);
134
+ ENFORCE_BOOLEAN(native_filenames_enabled);
80
135
 
81
136
  VALUE zero = INT2NUM(0);
82
137
  VALUE heap_sample = rb_hash_lookup2(metric_values_hash, rb_str_new_cstr("heap_sample"), Qfalse);
@@ -119,7 +174,8 @@ static VALUE _native_sample(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self) {
119
174
  int max_frames_requested = sampling_buffer_check_max_frames(NUM2INT(max_frames));
120
175
 
121
176
  ddog_prof_Location *locations = ruby_xcalloc(max_frames_requested, sizeof(ddog_prof_Location));
122
- sampling_buffer *buffer = sampling_buffer_new(max_frames_requested, locations);
177
+ sampling_buffer buffer;
178
+ sampling_buffer_initialize(&buffer, max_frames_requested);
123
179
 
124
180
  ddog_prof_Slice_Label slice_labels = {.ptr = labels, .len = labels_count};
125
181
 
@@ -129,8 +185,10 @@ static VALUE _native_sample(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self) {
129
185
  .values = values,
130
186
  .labels = (sample_labels) {.labels = slice_labels, .state_label = state_label, .is_gvl_waiting_state = is_gvl_waiting_state == Qtrue},
131
187
  .thread = thread,
132
- .locations = locations,
133
- .buffer = buffer,
188
+ .locations = (sample_locations) {.ptr = locations, .len = max_frames_requested},
189
+ .buffer = &buffer,
190
+ .native_filenames_enabled = native_filenames_enabled == Qtrue,
191
+ .native_filenames_cache = st_init_numtable(),
134
192
  };
135
193
 
136
194
  return rb_ensure(native_sample_do, (VALUE) &args_struct, native_sample_ensure, (VALUE) &args_struct);
@@ -150,9 +208,12 @@ static VALUE native_sample_do(VALUE args) {
150
208
  sample_thread(
151
209
  args_struct->thread,
152
210
  args_struct->buffer,
211
+ args_struct->locations,
153
212
  args_struct->recorder_instance,
154
213
  args_struct->values,
155
- args_struct->labels
214
+ args_struct->labels,
215
+ args_struct->native_filenames_enabled,
216
+ args_struct->native_filenames_cache
156
217
  );
157
218
  }
158
219
 
@@ -162,8 +223,9 @@ static VALUE native_sample_do(VALUE args) {
162
223
  static VALUE native_sample_ensure(VALUE args) {
163
224
  native_sample_args *args_struct = (native_sample_args *) args;
164
225
 
165
- ruby_xfree(args_struct->locations);
226
+ ruby_xfree(args_struct->locations.ptr);
166
227
  sampling_buffer_free(args_struct->buffer);
228
+ st_free_table(args_struct->native_filenames_cache);
167
229
 
168
230
  return Qtrue;
169
231
  }
@@ -182,16 +244,28 @@ static VALUE native_sample_ensure(VALUE args) {
182
244
  void sample_thread(
183
245
  VALUE thread,
184
246
  sampling_buffer* buffer,
247
+ sample_locations locations,
185
248
  VALUE recorder_instance,
186
249
  sample_values values,
187
- sample_labels labels
250
+ sample_labels labels,
251
+ bool native_filenames_enabled,
252
+ st_table *native_filenames_cache
188
253
  ) {
189
- int captured_frames = ddtrace_rb_profile_frames(
190
- thread,
191
- 0 /* stack starting depth */,
192
- buffer->max_frames,
193
- buffer->stack_buffer
194
- );
254
+ // If we already prepared a sample, we use it below; if not, we prepare it now.
255
+ if (!buffer->pending_sample) {
256
+ // Reconcile the sampling_buffer's max_frames with the locations size
257
+ if (buffer->max_frames != locations.len) {
258
+ sampling_buffer_reinitialize(buffer, locations.len);
259
+ }
260
+ prepare_sample_thread(thread, buffer);
261
+ }
262
+
263
+ buffer->pending_sample = false;
264
+ int captured_frames = buffer->pending_sample_result;
265
+
266
+ // The per_thread_context's sampling_buffer may have been created by a previous collector with a
267
+ // different (larger) max_frames. Cap to the locations array size to prevent out-of-bounds writes.
268
+ if (captured_frames > (int) locations.len) captured_frames = (int) locations.len;
195
269
 
196
270
  if (captured_frames == PLACEHOLDER_STACK_IN_NATIVE_CODE) {
197
271
  record_placeholder_stack_in_native_code(recorder_instance, values, labels);
@@ -210,8 +284,9 @@ void sample_thread(
210
284
  // The convention in Kernel#caller_locations is to instead use the path and line number of the first Ruby frame
211
285
  // on the stack that is below (e.g. directly or indirectly has called) the native method.
212
286
  // Thus, we keep that frame here to able to replicate that behavior.
213
- // (This is why we also iterate the sampling buffers backwards below -- so that it's easier to keep the last_ruby_frame_filename)
214
- VALUE last_ruby_frame_filename = Qnil;
287
+ // (This is why we also iterate the sampling buffers backwards from what libdatadog uses below -- so that it's easier
288
+ // to keep the last_ruby_frame_filename)
289
+ ddog_CharSlice last_ruby_frame_filename = DDOG_CHARSLICE_C("");
215
290
  int last_ruby_line = 0;
216
291
 
217
292
  ddog_prof_Label *state_label = labels.state_label;
@@ -222,40 +297,49 @@ void sample_thread(
222
297
  // here, but >= 0 makes this easier to understand/debug.
223
298
  bool only_wall_time = cpu_or_wall_sample && values.cpu_time_ns == 0 && values.wall_time_ns >= 0;
224
299
 
225
- if (cpu_or_wall_sample && state_label == NULL) rb_raise(rb_eRuntimeError, "BUG: Unexpected missing state_label");
300
+ if (cpu_or_wall_sample && state_label == NULL) raise_error(rb_eRuntimeError, "BUG: Unexpected missing state_label");
226
301
 
227
302
  if (has_cpu_time) {
228
303
  state_label->str = DDOG_CHARSLICE_C("had cpu");
229
- if (labels.is_gvl_waiting_state) rb_raise(rb_eRuntimeError, "BUG: Unexpected combination of cpu-time with is_gvl_waiting");
304
+ if (labels.is_gvl_waiting_state) raise_error(rb_eRuntimeError, "BUG: Unexpected combination of cpu-time with is_gvl_waiting");
230
305
  }
231
306
 
232
- for (int i = captured_frames - 1; i >= 0; i--) {
233
- VALUE name, filename;
307
+ int top_of_stack_position = captured_frames - 1;
308
+
309
+ for (int i = 0; i <= top_of_stack_position; i++) {
310
+ ddog_CharSlice name_slice, filename_slice;
234
311
  int line;
312
+ bool top_of_the_stack = i == top_of_stack_position;
235
313
 
236
314
  if (buffer->stack_buffer[i].is_ruby_frame) {
237
- name = rb_iseq_base_label(buffer->stack_buffer[i].as.ruby_frame.iseq);
238
- filename = rb_iseq_path(buffer->stack_buffer[i].as.ruby_frame.iseq);
315
+ VALUE name = rb_iseq_base_label(buffer->stack_buffer[i].as.ruby_frame.iseq);
316
+ VALUE filename = rb_iseq_path(buffer->stack_buffer[i].as.ruby_frame.iseq);
317
+
318
+ name_slice = NIL_P(name) ? DDOG_CHARSLICE_C("") : char_slice_from_ruby_string(name);
319
+ filename_slice = NIL_P(filename) ? DDOG_CHARSLICE_C("") : char_slice_from_ruby_string(filename);
239
320
  line = buffer->stack_buffer[i].as.ruby_frame.line;
240
321
 
241
- last_ruby_frame_filename = filename;
322
+ last_ruby_frame_filename = filename_slice;
242
323
  last_ruby_line = line;
243
324
  } else {
244
- name = rb_id2str(buffer->stack_buffer[i].as.native_frame.method_id);
245
- filename = last_ruby_frame_filename;
246
- line = last_ruby_line;
325
+ VALUE name = rb_id2str(buffer->stack_buffer[i].as.native_frame.method_id);
326
+
327
+ name_slice = NIL_P(name) ? DDOG_CHARSLICE_C("") : char_slice_from_ruby_string(name);
328
+
329
+ set_file_info_for_cfunc(
330
+ &filename_slice,
331
+ &line,
332
+ last_ruby_frame_filename,
333
+ last_ruby_line,
334
+ buffer->stack_buffer[i].as.native_frame.function,
335
+ top_of_the_stack,
336
+ native_filenames_enabled,
337
+ native_filenames_cache
338
+ );
247
339
  }
248
340
 
249
- name = NIL_P(name) ? missing_string : name;
250
- filename = NIL_P(filename) ? missing_string : filename;
251
-
252
- ddog_CharSlice name_slice = char_slice_from_ruby_string(name);
253
- ddog_CharSlice filename_slice = char_slice_from_ruby_string(filename);
254
-
255
341
  maybe_trim_template_random_ids(&name_slice, &filename_slice);
256
342
 
257
- bool top_of_the_stack = i == 0;
258
-
259
343
  // When there's only wall-time in a sample, this means that the thread was not active in the sampled period.
260
344
  if (top_of_the_stack && only_wall_time) {
261
345
  // Did the caller already provide the state?
@@ -276,13 +360,19 @@ void sample_thread(
276
360
  } else if (CHARSLICE_EQUALS("select", name_slice)) { // Expected to be Kernel.select
277
361
  state_label->str = DDOG_CHARSLICE_C("waiting");
278
362
  } else if (
279
- CHARSLICE_EQUALS("synchronize", name_slice) || // Expected to be Monitor/Mutex#synchronize
280
- CHARSLICE_EQUALS("lock", name_slice) || // Expected to be Mutex#lock
363
+ CHARSLICE_EQUALS("synchronize", name_slice) || // Expected to be Monitor/Mutex#synchronize on Ruby 2 & 3, and Monitor#synchronize on 4 (Mutex becomes <internal:thread_sync>)
364
+ #ifdef NO_PRIMITIVE_MUTEX_AND_CONDITION_VARIABLE // Ruby < 4
365
+ CHARSLICE_EQUALS("lock", name_slice) || // Expected to be Mutex#lock
366
+ #endif
281
367
  CHARSLICE_EQUALS("join", name_slice) // Expected to be Thread#join
282
368
  ) {
283
369
  state_label->str = DDOG_CHARSLICE_C("blocked");
284
370
  } else if (CHARSLICE_EQUALS("wait_readable", name_slice)) { // Expected to be IO#wait_readable
285
371
  state_label->str = DDOG_CHARSLICE_C("network");
372
+ } else if (CHARSLICE_EQUALS("_native_idle_sampling_loop", name_slice)) { // Expected to be Datadog::Profiler::Collectors::IdleSamplingHelper#_native_idle_sampling_loop
373
+ state_label->str = DDOG_CHARSLICE_C("waiting");
374
+ } else if (CHARSLICE_EQUALS("_native_sampling_loop", name_slice)) { // Expected to be Datadog::Profiler::Collectors::CpuAndWallTimeWorker#_native_sampling_loop
375
+ state_label->str = DDOG_CHARSLICE_C("sleeping");
286
376
  }
287
377
  #ifdef NO_PRIMITIVE_POP // Ruby < 3.2
288
378
  else if (CHARSLICE_EQUALS("pop", name_slice)) { // Expected to be Queue/SizedQueue#pop
@@ -291,39 +381,140 @@ void sample_thread(
291
381
  #endif
292
382
  } else {
293
383
  #ifndef NO_PRIMITIVE_POP // Ruby >= 3.2
294
- // Unlike the above, Ruby actually treats this one specially and gives it a nice file name we can match on!
295
- if (CHARSLICE_EQUALS("pop", name_slice) && CHARSLICE_EQUALS("<internal:thread_sync>", filename_slice)) { // Expected to be Queue/SizedQueue#pop
296
- state_label->str = DDOG_CHARSLICE_C("waiting");
384
+ if (CHARSLICE_EQUALS("<internal:thread_sync>", filename_slice)) {
385
+ if (CHARSLICE_EQUALS("pop", name_slice)) { // Expected to be Queue/SizedQueue#pop
386
+ state_label->str = DDOG_CHARSLICE_C("waiting");
387
+ }
388
+ #ifndef NO_PRIMITIVE_MUTEX_AND_CONDITION_VARIABLE // Ruby >= 4
389
+ else if (CHARSLICE_EQUALS("synchronize", name_slice) || CHARSLICE_EQUALS("lock", name_slice)) { // Expected to be Mutex#lock/synchronize
390
+ state_label->str = DDOG_CHARSLICE_C("blocked");
391
+ } else if (CHARSLICE_EQUALS("sleep", name_slice)) { // Expected to be Mutex#sleep
392
+ state_label->str = DDOG_CHARSLICE_C("sleeping");
393
+ } else if (CHARSLICE_EQUALS("wait", name_slice)) { // Expected to be ConditionVariable#wait
394
+ state_label->str = DDOG_CHARSLICE_C("waiting");
395
+ }
396
+ #endif
297
397
  }
298
398
  #endif
299
399
  }
300
400
  }
301
401
 
302
- buffer->locations[i] = (ddog_prof_Location) {
402
+ int libdatadog_stores_stacks_flipped_from_rb_profile_frames_index = top_of_stack_position - i;
403
+
404
+ locations.ptr[libdatadog_stores_stacks_flipped_from_rb_profile_frames_index] = (ddog_prof_Location) {
303
405
  .mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C(""), .build_id_id = {}},
304
406
  .function = (ddog_prof_Function) {.name = name_slice, .filename = filename_slice},
305
407
  .line = line,
306
408
  };
307
409
  }
308
410
 
309
- // Used below; since we want to stack-allocate this, we must do it here rather than in maybe_add_placeholder_frames_omitted
310
- const int frames_omitted_message_size = sizeof(MAX_FRAMES_LIMIT_AS_STRING " frames omitted");
311
- char frames_omitted_message[frames_omitted_message_size];
312
-
313
- // If we filled up the buffer, some frames may have been omitted. In that case, we'll add a placeholder frame
411
+ // If we filled up the locations, some frames may have been omitted. In that case, we'll add a placeholder frame
314
412
  // with that info.
315
- if (captured_frames == (long) buffer->max_frames) {
316
- maybe_add_placeholder_frames_omitted(thread, buffer, frames_omitted_message, frames_omitted_message_size);
413
+ if (captured_frames == (long) locations.len) {
414
+ add_truncated_frames_placeholder(locations.ptr);
317
415
  }
318
416
 
319
417
  record_sample(
320
418
  recorder_instance,
321
- (ddog_prof_Slice_Location) {.ptr = buffer->locations, .len = captured_frames},
419
+ (ddog_prof_Slice_Location) {.ptr = locations.ptr, .len = captured_frames},
322
420
  values,
323
421
  labels
324
422
  );
423
+
424
+ // Reconcile the sampling_buffer's max_frames with the locations size for future samples
425
+ if (buffer->max_frames != locations.len) {
426
+ sampling_buffer_reinitialize(buffer, locations.len);
427
+ }
325
428
  }
326
429
 
430
+ #if (defined(HAVE_DLADDR1) && HAVE_DLADDR1) || (defined(HAVE_DLADDR) && HAVE_DLADDR)
431
+ static void set_file_info_for_cfunc(
432
+ ddog_CharSlice *filename_slice,
433
+ int *line,
434
+ ddog_CharSlice last_ruby_frame_filename,
435
+ int last_ruby_line,
436
+ void *function,
437
+ bool top_of_the_stack,
438
+ bool native_filenames_enabled,
439
+ st_table *native_filenames_cache
440
+ ) {
441
+ if (native_filenames_enabled) {
442
+ const char *native_filename = get_or_compute_native_filename(function, native_filenames_cache);
443
+ if (native_filename && native_filename[0] != '\0' &&
444
+ // Using the ruby_native_filename at the top of the stack has a weird effect on the "top methods" table because
445
+ // e.g. we don't have classnames for methods. This is especially visible in the allocations profile, e.g.
446
+ // what a surprise, you're telling me "libruby.so:new" is the top method always?
447
+ //
448
+ // Until we have a better way of dealing with that, we don't do this replacement for the top frame.
449
+ //
450
+ // Also, dladdr is expected to always return the same pointer to the ruby_native_filename, so that's why we're
451
+ // comparing only pointer values and not the string contents.
452
+ (native_filename != ruby_native_filename || !top_of_the_stack)
453
+ ) {
454
+ *filename_slice = (ddog_CharSlice) {.ptr = native_filename, .len = strlen(native_filename)};
455
+ // Explicitly set the line to 0 as it has no meaning on a native library (e.g. an .so is built of many source files)
456
+ // and anyway often that debug info is not available.
457
+ *line = 0;
458
+ return;
459
+ }
460
+ }
461
+
462
+ *filename_slice = last_ruby_frame_filename;
463
+ *line = last_ruby_line;
464
+ }
465
+
466
+ // `native_filenames_cache` is used to cache native filename lookup results (Map[void *function_pointer, char *filename])
467
+ //
468
+ // Caching this information is safe because there's no API in Ruby to "unrequire" a native extension. Thus, if we see a
469
+ // frame on the **Ruby** stack with a given `function`, then that `function` was registered with the Ruby VM and
470
+ // belongs to a Ruby extension, so a lot of other bad things would happen if it was dlclosed.
471
+ static const char *get_or_compute_native_filename(void *function, st_table *native_filenames_cache) {
472
+ const char *cached_filename = NULL;
473
+ st_lookup(native_filenames_cache, (st_data_t) function, (st_data_t *) &cached_filename);
474
+ if (cached_filename != NULL) return cached_filename;
475
+
476
+ Dl_info info;
477
+ const char *native_filename = NULL;
478
+ #if defined(HAVE_DLADDR1) && HAVE_DLADDR1
479
+ struct link_map *extra_info = NULL;
480
+ if (dladdr1(function, &info, (void **) &extra_info, RTLD_DL_LINKMAP) != 0 && extra_info != NULL) {
481
+ native_filename = extra_info->l_name != NULL ? extra_info->l_name : info.dli_fname;
482
+ }
483
+ #elif defined(HAVE_DLADDR) && HAVE_DLADDR
484
+ if (dladdr(function, &info) != 0) {
485
+ native_filename = info.dli_fname;
486
+ }
487
+ #endif
488
+
489
+ // We explicitly use an empty string here so as to cache lookups that somehow "failed". Otherwise we would keep trying them every time.
490
+ if (native_filename == NULL) native_filename = "";
491
+
492
+ // An st_table is what Ruby uses for its own hashtables. This allows us to get an easy estimate of the size of the cache:
493
+ // `ObjectSpace.memsize_of((0..100000).map { |it| [it, nil] }.to_h)` => 4194400 bytes as of Ruby 3.2 so that seems reasonable?
494
+ // Note: `st_table_size()` is available from Ruby 3.2+ but not before
495
+ if (native_filenames_cache->num_entries >= 100000) {
496
+ st_clear(native_filenames_cache);
497
+ }
498
+
499
+ st_insert(native_filenames_cache, (st_data_t) function, (st_data_t) native_filename);
500
+ return native_filename;
501
+ }
502
+ #else
503
+ static void set_file_info_for_cfunc(
504
+ ddog_CharSlice *filename_slice,
505
+ int *line,
506
+ ddog_CharSlice last_ruby_frame_filename,
507
+ int last_ruby_line,
508
+ DDTRACE_UNUSED void *function,
509
+ DDTRACE_UNUSED bool top_of_the_stack,
510
+ DDTRACE_UNUSED bool native_filenames_enabled,
511
+ DDTRACE_UNUSED st_table *native_filenames_cache
512
+ ) {
513
+ *filename_slice = last_ruby_frame_filename;
514
+ *line = last_ruby_line;
515
+ }
516
+ #endif
517
+
327
518
  // Rails's ActionView likes to dynamically generate method names with suffixed hashes/ids, resulting in methods with
328
519
  // names such as:
329
520
  // * "_app_views_layouts_explore_html_haml__2304485752546535910_211320" (__number_number suffix -- two underscores)
@@ -340,6 +531,7 @@ static void maybe_trim_template_random_ids(ddog_CharSlice *name_slice, ddog_Char
340
531
  if (filename_slice->len < 3 || memcmp(filename_slice->ptr + filename_slice->len - 3, ".rb", 3) == 0) return;
341
532
 
342
533
  if (name_slice->len > 1024) return;
534
+ if (name_slice->len == 0) return;
343
535
 
344
536
  int pos = ((int) name_slice->len) - 1;
345
537
 
@@ -363,24 +555,12 @@ static void maybe_trim_template_random_ids(ddog_CharSlice *name_slice, ddog_Char
363
555
  name_slice->len = pos;
364
556
  }
365
557
 
366
- static void maybe_add_placeholder_frames_omitted(VALUE thread, sampling_buffer* buffer, char *frames_omitted_message, int frames_omitted_message_size) {
367
- ptrdiff_t frames_omitted = stack_depth_for(thread) - buffer->max_frames;
368
-
369
- if (frames_omitted == 0) return; // Perfect fit!
370
-
371
- // The placeholder frame takes over a space, so if 10 frames were left out and we consume one other space for the
372
- // placeholder, then 11 frames are omitted in total
373
- frames_omitted++;
374
-
375
- snprintf(frames_omitted_message, frames_omitted_message_size, "%td frames omitted", frames_omitted);
376
-
377
- // Important note: `frames_omitted_message` MUST have a lifetime that is at least as long as the call to
378
- // `record_sample`. So be careful where it gets allocated. (We do have tests for this, at least!)
379
- ddog_CharSlice function_name = DDOG_CHARSLICE_C("");
380
- ddog_CharSlice function_filename = {.ptr = frames_omitted_message, .len = strlen(frames_omitted_message)};
381
- buffer->locations[buffer->max_frames - 1] = (ddog_prof_Location) {
558
+ static void add_truncated_frames_placeholder(ddog_prof_Location *locations) {
559
+ // Important note: The strings below are static so we don't need to worry about their lifetime. If we ever want to change
560
+ // this to non-static strings, don't forget to check that lifetimes are properly respected.
561
+ locations[0] = (ddog_prof_Location) {
382
562
  .mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C(""), .build_id_id = {}},
383
- .function = (ddog_prof_Function) {.name = function_name, .filename = function_filename},
563
+ .function = {.name = DDOG_CHARSLICE_C("Truncated Frames"), .filename = DDOG_CHARSLICE_C(""), .filename_id = {}},
384
564
  .line = 0,
385
565
  };
386
566
  }
@@ -439,30 +619,73 @@ void record_placeholder_stack(
439
619
  );
440
620
  }
441
621
 
622
+ bool prepare_sample_thread(VALUE thread, sampling_buffer *buffer) {
623
+ // Since this can get called from inside a signal handler, we don't want to touch the buffer if
624
+ // the thread was actually in the middle of marking it.
625
+ if (buffer->is_marking) return false;
626
+
627
+ buffer->pending_sample = true;
628
+ buffer->pending_sample_result = ddtrace_rb_profile_frames(thread, 0, buffer->max_frames, buffer->stack_buffer);
629
+ return true;
630
+ }
631
+
442
632
  uint16_t sampling_buffer_check_max_frames(int max_frames) {
443
- if (max_frames < 5) rb_raise(rb_eArgError, "Invalid max_frames: value must be >= 5");
444
- if (max_frames > MAX_FRAMES_LIMIT) rb_raise(rb_eArgError, "Invalid max_frames: value must be <= " MAX_FRAMES_LIMIT_AS_STRING);
633
+ if (max_frames < 5) raise_error(rb_eArgError, "Invalid max_frames: value must be >= 5");
634
+ if (max_frames > MAX_FRAMES_LIMIT) raise_error(rb_eArgError, "Invalid max_frames: value must be <= " MAX_FRAMES_LIMIT_AS_STRING);
445
635
  return max_frames;
446
636
  }
447
637
 
448
- sampling_buffer *sampling_buffer_new(uint16_t max_frames, ddog_prof_Location *locations) {
638
+ void sampling_buffer_initialize(sampling_buffer *buffer, uint16_t max_frames) {
449
639
  sampling_buffer_check_max_frames(max_frames);
450
640
 
451
- // Note: never returns NULL; if out of memory, it calls the Ruby out-of-memory handlers
452
- sampling_buffer* buffer = ruby_xcalloc(1, sizeof(sampling_buffer));
453
-
454
641
  buffer->max_frames = max_frames;
455
- buffer->locations = locations;
456
642
  buffer->stack_buffer = ruby_xcalloc(max_frames, sizeof(frame_info));
643
+ buffer->pending_sample = false;
644
+ buffer->is_marking = false;
645
+ buffer->pending_sample_result = 0;
646
+ }
457
647
 
458
- return buffer;
648
+ void sampling_buffer_reinitialize(sampling_buffer *buffer, uint16_t max_frames) {
649
+ sampling_buffer_free(buffer);
650
+ sampling_buffer_initialize(buffer, max_frames);
459
651
  }
460
652
 
461
653
  void sampling_buffer_free(sampling_buffer *buffer) {
462
- if (buffer == NULL) rb_raise(rb_eArgError, "sampling_buffer_free called with NULL buffer");
654
+ if (buffer->max_frames == 0 || buffer->stack_buffer == NULL) {
655
+ raise_error(rb_eArgError, "sampling_buffer_free called with invalid buffer");
656
+ }
463
657
 
464
- // buffer->locations are owned by whoever called sampling_buffer_new, not us
465
658
  ruby_xfree(buffer->stack_buffer);
466
659
 
467
- ruby_xfree(buffer);
660
+ buffer->max_frames = 0;
661
+ buffer->stack_buffer = NULL;
662
+ buffer->pending_sample = false;
663
+ buffer->is_marking = false;
664
+ buffer->pending_sample_result = 0;
665
+ }
666
+
667
+ void sampling_buffer_mark(sampling_buffer *buffer) {
668
+ if (!sampling_buffer_needs_marking(buffer)) {
669
+ rb_bug("sampling_buffer_mark called with no pending sample. `sampling_buffer_needs_marking` should be used before calling mark.");
670
+ }
671
+
672
+ buffer->is_marking = true;
673
+ // Tell the compiler it's not allowed to reorder the `is_marking` flag with the iteration below.
674
+ //
675
+ // Specifically, in the middle of `sampling_buffer_mark` a signal handler may execute and call
676
+ // `prepare_sample_thread` to add a new sample to the buffer. This flag is here to prevent that BUT we need to
677
+ // make sure the signal handler actually sees the flag being set.
678
+ //
679
+ // See https://github.com/ruby/ruby/pull/11036 for a similar change made to the Ruby VM with more context.
680
+ atomic_signal_fence(memory_order_seq_cst);
681
+
682
+ for (int i = 0; i < buffer->pending_sample_result; i++) {
683
+ if (buffer->stack_buffer[i].is_ruby_frame) {
684
+ rb_gc_mark(buffer->stack_buffer[i].as.ruby_frame.iseq);
685
+ }
686
+ }
687
+
688
+ // Make sure iteration completes before `is_marking` is unset...
689
+ atomic_signal_fence(memory_order_seq_cst);
690
+ buffer->is_marking = false;
468
691
  }
@@ -2,19 +2,35 @@
2
2
 
3
3
  #include <datadog/profiling.h>
4
4
 
5
+ #include "private_vm_api_access.h"
5
6
  #include "stack_recorder.h"
6
7
 
7
8
  #define MAX_FRAMES_LIMIT 3000
8
9
  #define MAX_FRAMES_LIMIT_AS_STRING "3000"
9
10
 
10
- typedef struct sampling_buffer sampling_buffer;
11
+ // Used as scratch space during sampling
12
+ typedef struct {
13
+ uint16_t max_frames;
14
+ frame_info *stack_buffer;
15
+ bool pending_sample;
16
+ bool is_marking; // Used to avoid recording a sample when marking
17
+ int pending_sample_result;
18
+ } sampling_buffer;
19
+
20
+ typedef struct {
21
+ ddog_prof_Location *ptr;
22
+ uint16_t len;
23
+ } sample_locations;
11
24
 
12
25
  void sample_thread(
13
26
  VALUE thread,
14
27
  sampling_buffer* buffer,
28
+ sample_locations locations,
15
29
  VALUE recorder_instance,
16
30
  sample_values values,
17
- sample_labels labels
31
+ sample_labels labels,
32
+ bool native_filenames_enabled,
33
+ st_table *native_filenames_cache
18
34
  );
19
35
  void record_placeholder_stack(
20
36
  VALUE recorder_instance,
@@ -22,6 +38,13 @@ void record_placeholder_stack(
22
38
  sample_labels labels,
23
39
  ddog_CharSlice placeholder_stack
24
40
  );
41
+ bool prepare_sample_thread(VALUE thread, sampling_buffer *buffer);
42
+
25
43
  uint16_t sampling_buffer_check_max_frames(int max_frames);
26
- sampling_buffer *sampling_buffer_new(uint16_t max_frames, ddog_prof_Location *locations);
44
+ void sampling_buffer_initialize(sampling_buffer *buffer, uint16_t max_frames);
45
+ void sampling_buffer_reinitialize(sampling_buffer *buffer, uint16_t max_frames);
27
46
  void sampling_buffer_free(sampling_buffer *buffer);
47
+ void sampling_buffer_mark(sampling_buffer *buffer);
48
+ static inline bool sampling_buffer_needs_marking(sampling_buffer *buffer) {
49
+ return buffer->pending_sample && buffer->pending_sample_result > 0;
50
+ }