datadog 2.7.1 → 2.18.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 (441) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +353 -1
  3. data/ext/datadog_profiling_native_extension/clock_id.h +2 -2
  4. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +78 -102
  5. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
  6. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +1 -1
  7. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +16 -16
  8. data/ext/datadog_profiling_native_extension/collectors_stack.c +235 -57
  9. data/ext/datadog_profiling_native_extension/collectors_stack.h +21 -5
  10. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +376 -156
  11. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +1 -0
  12. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +1 -4
  13. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +10 -0
  14. data/ext/datadog_profiling_native_extension/encoded_profile.c +79 -0
  15. data/ext/datadog_profiling_native_extension/encoded_profile.h +8 -0
  16. data/ext/datadog_profiling_native_extension/extconf.rb +14 -8
  17. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +2 -0
  18. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +0 -8
  19. data/ext/datadog_profiling_native_extension/heap_recorder.c +295 -532
  20. data/ext/datadog_profiling_native_extension/heap_recorder.h +6 -8
  21. data/ext/datadog_profiling_native_extension/http_transport.c +64 -98
  22. data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +22 -0
  23. data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +8 -5
  24. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +69 -1
  25. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +16 -4
  26. data/ext/datadog_profiling_native_extension/profiling.c +19 -8
  27. data/ext/datadog_profiling_native_extension/ruby_helpers.c +9 -21
  28. data/ext/datadog_profiling_native_extension/ruby_helpers.h +2 -10
  29. data/ext/datadog_profiling_native_extension/stack_recorder.c +231 -181
  30. data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -2
  31. data/ext/datadog_profiling_native_extension/time_helpers.h +1 -1
  32. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +47 -0
  33. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +31 -0
  34. data/ext/libdatadog_api/crashtracker.c +17 -15
  35. data/ext/libdatadog_api/crashtracker.h +5 -0
  36. data/ext/libdatadog_api/datadog_ruby_common.c +1 -4
  37. data/ext/libdatadog_api/datadog_ruby_common.h +10 -0
  38. data/ext/libdatadog_api/extconf.rb +2 -2
  39. data/ext/libdatadog_api/init.c +15 -0
  40. data/ext/libdatadog_api/library_config.c +164 -0
  41. data/ext/libdatadog_api/library_config.h +25 -0
  42. data/ext/libdatadog_api/macos_development.md +3 -3
  43. data/ext/libdatadog_api/process_discovery.c +112 -0
  44. data/ext/libdatadog_api/process_discovery.h +5 -0
  45. data/ext/libdatadog_extconf_helpers.rb +2 -2
  46. data/lib/datadog/appsec/actions_handler/serializable_backtrace.rb +89 -0
  47. data/lib/datadog/appsec/actions_handler.rb +49 -0
  48. data/lib/datadog/appsec/anonymizer.rb +16 -0
  49. data/lib/datadog/appsec/api_security/lru_cache.rb +56 -0
  50. data/lib/datadog/appsec/api_security/route_extractor.rb +65 -0
  51. data/lib/datadog/appsec/api_security/sampler.rb +59 -0
  52. data/lib/datadog/appsec/api_security.rb +23 -0
  53. data/lib/datadog/appsec/assets/waf_rules/README.md +50 -5
  54. data/lib/datadog/appsec/assets/waf_rules/recommended.json +623 -253
  55. data/lib/datadog/appsec/assets/waf_rules/strict.json +69 -107
  56. data/lib/datadog/appsec/autoload.rb +1 -1
  57. data/lib/datadog/appsec/component.rb +49 -65
  58. data/lib/datadog/appsec/compressed_json.rb +40 -0
  59. data/lib/datadog/appsec/configuration/settings.rb +212 -27
  60. data/lib/datadog/appsec/context.rb +74 -0
  61. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +92 -0
  62. data/lib/datadog/appsec/contrib/active_record/integration.rb +41 -0
  63. data/lib/datadog/appsec/contrib/active_record/patcher.rb +101 -0
  64. data/lib/datadog/appsec/contrib/auto_instrument.rb +1 -1
  65. data/lib/datadog/appsec/contrib/devise/configuration.rb +52 -0
  66. data/lib/datadog/appsec/contrib/devise/data_extractor.rb +78 -0
  67. data/lib/datadog/appsec/contrib/devise/ext.rb +22 -0
  68. data/lib/datadog/appsec/contrib/devise/integration.rb +1 -2
  69. data/lib/datadog/appsec/contrib/devise/patcher.rb +33 -25
  70. data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +102 -0
  71. data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +69 -0
  72. data/lib/datadog/appsec/contrib/devise/{patcher/rememberable_patch.rb → patches/skip_signin_tracking_patch.rb} +3 -3
  73. data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +106 -0
  74. data/lib/datadog/appsec/contrib/excon/integration.rb +41 -0
  75. data/lib/datadog/appsec/contrib/excon/patcher.rb +28 -0
  76. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +42 -0
  77. data/lib/datadog/appsec/contrib/faraday/connection_patch.rb +22 -0
  78. data/lib/datadog/appsec/contrib/faraday/integration.rb +42 -0
  79. data/lib/datadog/appsec/contrib/faraday/patcher.rb +53 -0
  80. data/lib/datadog/appsec/contrib/faraday/rack_builder_patch.rb +22 -0
  81. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +41 -0
  82. data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +1 -7
  83. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +17 -30
  84. data/lib/datadog/appsec/contrib/graphql/integration.rb +1 -1
  85. data/lib/datadog/appsec/contrib/graphql/patcher.rb +0 -3
  86. data/lib/datadog/appsec/contrib/rack/ext.rb +34 -0
  87. data/lib/datadog/appsec/contrib/rack/gateway/response.rb +3 -3
  88. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +78 -98
  89. data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
  90. data/lib/datadog/appsec/contrib/rack/patcher.rb +0 -3
  91. data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +10 -11
  92. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +73 -78
  93. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +16 -33
  94. data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
  95. data/lib/datadog/appsec/contrib/rails/patcher.rb +25 -38
  96. data/lib/datadog/appsec/contrib/rest_client/integration.rb +45 -0
  97. data/lib/datadog/appsec/contrib/rest_client/patcher.rb +28 -0
  98. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +38 -0
  99. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +31 -68
  100. data/lib/datadog/appsec/contrib/sinatra/integration.rb +1 -1
  101. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +5 -31
  102. data/lib/datadog/appsec/event.rb +96 -135
  103. data/lib/datadog/appsec/ext.rb +12 -3
  104. data/lib/datadog/appsec/instrumentation/gateway/argument.rb +7 -2
  105. data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +24 -0
  106. data/lib/datadog/appsec/instrumentation/gateway.rb +17 -22
  107. data/lib/datadog/appsec/metrics/collector.rb +38 -0
  108. data/lib/datadog/appsec/metrics/exporter.rb +35 -0
  109. data/lib/datadog/appsec/metrics/telemetry.rb +23 -0
  110. data/lib/datadog/appsec/metrics.rb +13 -0
  111. data/lib/datadog/appsec/monitor/gateway/watcher.rb +52 -32
  112. data/lib/datadog/appsec/processor/rule_loader.rb +30 -36
  113. data/lib/datadog/appsec/remote.rb +31 -57
  114. data/lib/datadog/appsec/response.rb +19 -85
  115. data/lib/datadog/appsec/security_engine/engine.rb +194 -0
  116. data/lib/datadog/appsec/security_engine/result.rb +67 -0
  117. data/lib/datadog/appsec/security_engine/runner.rb +87 -0
  118. data/lib/datadog/appsec/security_engine.rb +9 -0
  119. data/lib/datadog/appsec/security_event.rb +39 -0
  120. data/lib/datadog/appsec/utils.rb +0 -2
  121. data/lib/datadog/appsec.rb +22 -12
  122. data/lib/datadog/auto_instrument.rb +3 -0
  123. data/lib/datadog/core/buffer/random.rb +18 -2
  124. data/lib/datadog/core/configuration/agent_settings.rb +52 -0
  125. data/lib/datadog/core/configuration/agent_settings_resolver.rb +4 -18
  126. data/lib/datadog/core/configuration/agentless_settings_resolver.rb +176 -0
  127. data/lib/datadog/core/configuration/components.rb +74 -32
  128. data/lib/datadog/core/configuration/components_state.rb +23 -0
  129. data/lib/datadog/core/configuration/ext.rb +5 -1
  130. data/lib/datadog/core/configuration/option.rb +81 -45
  131. data/lib/datadog/core/configuration/option_definition.rb +6 -4
  132. data/lib/datadog/core/configuration/options.rb +3 -3
  133. data/lib/datadog/core/configuration/settings.rb +121 -50
  134. data/lib/datadog/core/configuration/stable_config.rb +22 -0
  135. data/lib/datadog/core/configuration.rb +43 -11
  136. data/lib/datadog/{tracing → core}/contrib/rails/utils.rb +1 -3
  137. data/lib/datadog/core/crashtracking/component.rb +4 -13
  138. data/lib/datadog/core/crashtracking/tag_builder.rb +4 -22
  139. data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
  140. data/lib/datadog/core/encoding.rb +17 -1
  141. data/lib/datadog/core/environment/agent_info.rb +78 -0
  142. data/lib/datadog/core/environment/cgroup.rb +10 -12
  143. data/lib/datadog/core/environment/container.rb +38 -40
  144. data/lib/datadog/core/environment/ext.rb +6 -6
  145. data/lib/datadog/core/environment/git.rb +1 -0
  146. data/lib/datadog/core/environment/identity.rb +3 -3
  147. data/lib/datadog/core/environment/platform.rb +3 -3
  148. data/lib/datadog/core/environment/variable_helpers.rb +1 -1
  149. data/lib/datadog/core/error.rb +11 -9
  150. data/lib/datadog/core/logger.rb +2 -2
  151. data/lib/datadog/core/metrics/client.rb +27 -27
  152. data/lib/datadog/core/metrics/logging.rb +5 -5
  153. data/lib/datadog/core/process_discovery/tracer_memfd.rb +15 -0
  154. data/lib/datadog/core/process_discovery.rb +36 -0
  155. data/lib/datadog/core/rate_limiter.rb +4 -2
  156. data/lib/datadog/core/remote/client/capabilities.rb +6 -0
  157. data/lib/datadog/core/remote/client.rb +107 -92
  158. data/lib/datadog/core/remote/component.rb +18 -19
  159. data/lib/datadog/core/remote/configuration/digest.rb +7 -7
  160. data/lib/datadog/core/remote/configuration/path.rb +1 -1
  161. data/lib/datadog/core/remote/configuration/repository.rb +14 -1
  162. data/lib/datadog/core/remote/negotiation.rb +9 -9
  163. data/lib/datadog/core/remote/transport/config.rb +4 -3
  164. data/lib/datadog/core/remote/transport/http/api.rb +13 -18
  165. data/lib/datadog/core/remote/transport/http/client.rb +5 -4
  166. data/lib/datadog/core/remote/transport/http/config.rb +27 -55
  167. data/lib/datadog/core/remote/transport/http/negotiation.rb +8 -51
  168. data/lib/datadog/core/remote/transport/http.rb +25 -94
  169. data/lib/datadog/core/remote/transport/negotiation.rb +17 -4
  170. data/lib/datadog/core/remote/worker.rb +10 -7
  171. data/lib/datadog/core/runtime/metrics.rb +12 -5
  172. data/lib/datadog/core/tag_builder.rb +56 -0
  173. data/lib/datadog/core/telemetry/component.rb +84 -49
  174. data/lib/datadog/core/telemetry/emitter.rb +23 -11
  175. data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +66 -0
  176. data/lib/datadog/core/telemetry/event/app_closing.rb +18 -0
  177. data/lib/datadog/core/telemetry/event/app_dependencies_loaded.rb +33 -0
  178. data/lib/datadog/core/telemetry/event/app_heartbeat.rb +18 -0
  179. data/lib/datadog/core/telemetry/event/app_integrations_change.rb +58 -0
  180. data/lib/datadog/core/telemetry/event/app_started.rb +269 -0
  181. data/lib/datadog/core/telemetry/event/base.rb +40 -0
  182. data/lib/datadog/core/telemetry/event/distributions.rb +18 -0
  183. data/lib/datadog/core/telemetry/event/generate_metrics.rb +43 -0
  184. data/lib/datadog/core/telemetry/event/log.rb +76 -0
  185. data/lib/datadog/core/telemetry/event/message_batch.rb +42 -0
  186. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +43 -0
  187. data/lib/datadog/core/telemetry/event.rb +17 -383
  188. data/lib/datadog/core/telemetry/ext.rb +1 -0
  189. data/lib/datadog/core/telemetry/http/adapters/net.rb +12 -97
  190. data/lib/datadog/core/telemetry/logger.rb +5 -4
  191. data/lib/datadog/core/telemetry/logging.rb +12 -6
  192. data/lib/datadog/core/telemetry/metric.rb +28 -6
  193. data/lib/datadog/core/telemetry/request.rb +4 -4
  194. data/lib/datadog/core/telemetry/transport/http/api.rb +43 -0
  195. data/lib/datadog/core/telemetry/transport/http/client.rb +49 -0
  196. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +92 -0
  197. data/lib/datadog/core/telemetry/transport/http.rb +63 -0
  198. data/lib/datadog/core/telemetry/transport/telemetry.rb +51 -0
  199. data/lib/datadog/core/telemetry/worker.rb +128 -25
  200. data/lib/datadog/core/transport/http/adapters/net.rb +17 -2
  201. data/lib/datadog/core/transport/http/adapters/test.rb +2 -1
  202. data/lib/datadog/core/transport/http/adapters/unix_socket.rb +1 -1
  203. data/lib/datadog/{tracing → core}/transport/http/api/instance.rb +18 -1
  204. data/lib/datadog/core/transport/http/api/spec.rb +36 -0
  205. data/lib/datadog/{tracing → core}/transport/http/builder.rb +53 -31
  206. data/lib/datadog/core/transport/http/env.rb +8 -0
  207. data/lib/datadog/core/transport/http.rb +75 -0
  208. data/lib/datadog/core/transport/response.rb +4 -0
  209. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +6 -6
  210. data/lib/datadog/core/utils/duration.rb +32 -32
  211. data/lib/datadog/core/utils/forking.rb +2 -2
  212. data/lib/datadog/core/utils/network.rb +6 -6
  213. data/lib/datadog/core/utils/only_once_successful.rb +16 -5
  214. data/lib/datadog/core/utils/time.rb +20 -0
  215. data/lib/datadog/core/utils/truncation.rb +21 -0
  216. data/lib/datadog/core/utils.rb +7 -0
  217. data/lib/datadog/core/vendor/multipart-post/multipart/post/composite_read_io.rb +1 -1
  218. data/lib/datadog/core/vendor/multipart-post/multipart/post/multipartable.rb +8 -8
  219. data/lib/datadog/core/vendor/multipart-post/multipart/post/parts.rb +7 -7
  220. data/lib/datadog/core/worker.rb +1 -1
  221. data/lib/datadog/core/workers/async.rb +29 -12
  222. data/lib/datadog/core/workers/interval_loop.rb +12 -1
  223. data/lib/datadog/core/workers/runtime_metrics.rb +2 -2
  224. data/lib/datadog/core.rb +8 -0
  225. data/lib/datadog/di/base.rb +115 -0
  226. data/lib/datadog/di/boot.rb +34 -0
  227. data/lib/datadog/di/code_tracker.rb +26 -15
  228. data/lib/datadog/di/component.rb +23 -14
  229. data/lib/datadog/di/configuration/settings.rb +25 -1
  230. data/lib/datadog/di/contrib/active_record.rb +1 -0
  231. data/lib/datadog/di/contrib/railtie.rb +15 -0
  232. data/lib/datadog/di/contrib.rb +28 -0
  233. data/lib/datadog/di/error.rb +5 -0
  234. data/lib/datadog/di/instrumenter.rb +162 -21
  235. data/lib/datadog/di/logger.rb +30 -0
  236. data/lib/datadog/di/preload.rb +18 -0
  237. data/lib/datadog/di/probe.rb +14 -7
  238. data/lib/datadog/di/probe_builder.rb +1 -0
  239. data/lib/datadog/di/probe_manager.rb +11 -5
  240. data/lib/datadog/di/probe_notification_builder.rb +54 -38
  241. data/lib/datadog/di/probe_notifier_worker.rb +60 -26
  242. data/lib/datadog/di/redactor.rb +0 -1
  243. data/lib/datadog/di/remote.rb +147 -0
  244. data/lib/datadog/di/serializer.rb +19 -8
  245. data/lib/datadog/di/transport/diagnostics.rb +62 -0
  246. data/lib/datadog/di/transport/http/api.rb +42 -0
  247. data/lib/datadog/di/transport/http/client.rb +47 -0
  248. data/lib/datadog/di/transport/http/diagnostics.rb +65 -0
  249. data/lib/datadog/di/transport/http/input.rb +77 -0
  250. data/lib/datadog/di/transport/http.rb +57 -0
  251. data/lib/datadog/di/transport/input.rb +70 -0
  252. data/lib/datadog/di/utils.rb +103 -0
  253. data/lib/datadog/di.rb +14 -76
  254. data/lib/datadog/error_tracking/collector.rb +87 -0
  255. data/lib/datadog/error_tracking/component.rb +167 -0
  256. data/lib/datadog/error_tracking/configuration/settings.rb +63 -0
  257. data/lib/datadog/error_tracking/configuration.rb +11 -0
  258. data/lib/datadog/error_tracking/ext.rb +18 -0
  259. data/lib/datadog/error_tracking/extensions.rb +16 -0
  260. data/lib/datadog/error_tracking/filters.rb +77 -0
  261. data/lib/datadog/error_tracking.rb +18 -0
  262. data/lib/datadog/kit/appsec/events.rb +15 -3
  263. data/lib/datadog/kit/identity.rb +9 -5
  264. data/lib/datadog/opentelemetry/api/baggage.rb +90 -0
  265. data/lib/datadog/opentelemetry/api/baggage.rbs +26 -0
  266. data/lib/datadog/opentelemetry/api/context.rb +16 -2
  267. data/lib/datadog/opentelemetry/sdk/trace/span.rb +1 -1
  268. data/lib/datadog/opentelemetry.rb +2 -1
  269. data/lib/datadog/profiling/collectors/code_provenance.rb +18 -9
  270. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +4 -0
  271. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -0
  272. data/lib/datadog/profiling/collectors/info.rb +3 -0
  273. data/lib/datadog/profiling/collectors/thread_context.rb +17 -2
  274. data/lib/datadog/profiling/component.rb +64 -82
  275. data/lib/datadog/profiling/encoded_profile.rb +11 -0
  276. data/lib/datadog/profiling/exporter.rb +3 -4
  277. data/lib/datadog/profiling/ext.rb +0 -14
  278. data/lib/datadog/profiling/flush.rb +5 -8
  279. data/lib/datadog/profiling/http_transport.rb +8 -87
  280. data/lib/datadog/profiling/load_native_extension.rb +1 -33
  281. data/lib/datadog/profiling/profiler.rb +2 -0
  282. data/lib/datadog/profiling/scheduler.rb +10 -2
  283. data/lib/datadog/profiling/stack_recorder.rb +9 -9
  284. data/lib/datadog/profiling/tag_builder.rb +5 -41
  285. data/lib/datadog/profiling/tasks/setup.rb +2 -0
  286. data/lib/datadog/profiling.rb +6 -2
  287. data/lib/datadog/tracing/analytics.rb +1 -1
  288. data/lib/datadog/tracing/component.rb +16 -12
  289. data/lib/datadog/tracing/configuration/ext.rb +8 -1
  290. data/lib/datadog/tracing/configuration/settings.rb +22 -10
  291. data/lib/datadog/tracing/context_provider.rb +1 -1
  292. data/lib/datadog/tracing/contrib/action_cable/integration.rb +5 -2
  293. data/lib/datadog/tracing/contrib/action_mailer/integration.rb +6 -2
  294. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +15 -0
  295. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +19 -12
  296. data/lib/datadog/tracing/contrib/action_pack/ext.rb +2 -0
  297. data/lib/datadog/tracing/contrib/action_pack/integration.rb +5 -2
  298. data/lib/datadog/tracing/contrib/action_view/integration.rb +5 -2
  299. data/lib/datadog/tracing/contrib/active_job/integration.rb +5 -2
  300. data/lib/datadog/tracing/contrib/active_record/integration.rb +7 -3
  301. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +7 -2
  302. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +36 -1
  303. data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +4 -0
  304. data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +14 -4
  305. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +10 -0
  306. data/lib/datadog/tracing/contrib/active_support/integration.rb +5 -2
  307. data/lib/datadog/tracing/contrib/auto_instrument.rb +2 -2
  308. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +10 -0
  309. data/lib/datadog/tracing/contrib/aws/integration.rb +3 -0
  310. data/lib/datadog/tracing/contrib/aws/parsed_context.rb +5 -1
  311. data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +3 -0
  312. data/lib/datadog/tracing/contrib/configuration/settings.rb +1 -1
  313. data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +4 -0
  314. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
  315. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -5
  316. data/lib/datadog/tracing/contrib/excon/middleware.rb +5 -3
  317. data/lib/datadog/tracing/contrib/ext.rb +1 -0
  318. data/lib/datadog/tracing/contrib/extensions.rb +29 -3
  319. data/lib/datadog/tracing/contrib/faraday/middleware.rb +5 -3
  320. data/lib/datadog/tracing/contrib/graphql/configuration/error_extension_env_parser.rb +21 -0
  321. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +11 -0
  322. data/lib/datadog/tracing/contrib/graphql/ext.rb +5 -0
  323. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +102 -11
  324. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +7 -1
  325. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +3 -0
  326. data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +0 -15
  327. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +4 -1
  328. data/lib/datadog/tracing/contrib/http/instrumentation.rb +6 -10
  329. data/lib/datadog/tracing/contrib/http/integration.rb +3 -0
  330. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -16
  331. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +7 -15
  332. data/lib/datadog/tracing/contrib/httprb/integration.rb +3 -0
  333. data/lib/datadog/tracing/contrib/kafka/integration.rb +3 -0
  334. data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +27 -0
  335. data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +48 -0
  336. data/lib/datadog/tracing/contrib/karafka/ext.rb +27 -0
  337. data/lib/datadog/tracing/contrib/karafka/integration.rb +45 -0
  338. data/lib/datadog/tracing/contrib/karafka/monitor.rb +66 -0
  339. data/lib/datadog/tracing/contrib/karafka/patcher.rb +71 -0
  340. data/lib/datadog/tracing/contrib/karafka.rb +37 -0
  341. data/lib/datadog/tracing/contrib/lograge/patcher.rb +4 -2
  342. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +8 -0
  343. data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -0
  344. data/lib/datadog/tracing/contrib/mongodb/integration.rb +3 -0
  345. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +18 -1
  346. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +17 -0
  347. data/lib/datadog/tracing/contrib/opensearch/ext.rb +9 -0
  348. data/lib/datadog/tracing/contrib/opensearch/integration.rb +3 -0
  349. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +5 -1
  350. data/lib/datadog/tracing/contrib/patcher.rb +5 -2
  351. data/lib/datadog/tracing/contrib/presto/integration.rb +3 -0
  352. data/lib/datadog/tracing/contrib/rack/header_collection.rb +11 -1
  353. data/lib/datadog/tracing/contrib/rack/integration.rb +2 -2
  354. data/lib/datadog/tracing/contrib/rack/middlewares.rb +1 -1
  355. data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
  356. data/lib/datadog/tracing/contrib/rails/framework.rb +2 -2
  357. data/lib/datadog/tracing/contrib/rails/patcher.rb +1 -1
  358. data/lib/datadog/tracing/contrib/rest_client/integration.rb +3 -0
  359. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +5 -3
  360. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +6 -1
  361. data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +3 -0
  362. data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
  363. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +5 -2
  364. data/lib/datadog/tracing/contrib/span_attribute_schema.rb +6 -1
  365. data/lib/datadog/tracing/contrib/support.rb +28 -0
  366. data/lib/datadog/tracing/contrib.rb +1 -0
  367. data/lib/datadog/tracing/correlation.rb +9 -2
  368. data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
  369. data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
  370. data/lib/datadog/tracing/distributed/baggage.rb +131 -0
  371. data/lib/datadog/tracing/distributed/datadog.rb +4 -2
  372. data/lib/datadog/tracing/distributed/propagation.rb +25 -4
  373. data/lib/datadog/tracing/distributed/propagation_policy.rb +42 -0
  374. data/lib/datadog/tracing/metadata/errors.rb +4 -4
  375. data/lib/datadog/tracing/metadata/ext.rb +5 -0
  376. data/lib/datadog/tracing/metadata/metastruct.rb +36 -0
  377. data/lib/datadog/tracing/metadata/metastruct_tagging.rb +42 -0
  378. data/lib/datadog/tracing/metadata.rb +2 -0
  379. data/lib/datadog/tracing/sampling/rate_sampler.rb +2 -1
  380. data/lib/datadog/tracing/sampling/span/rule.rb +0 -1
  381. data/lib/datadog/tracing/span.rb +22 -5
  382. data/lib/datadog/tracing/span_event.rb +124 -4
  383. data/lib/datadog/tracing/span_operation.rb +52 -16
  384. data/lib/datadog/tracing/sync_writer.rb +10 -6
  385. data/lib/datadog/tracing/trace_digest.rb +9 -2
  386. data/lib/datadog/tracing/trace_operation.rb +55 -27
  387. data/lib/datadog/tracing/trace_segment.rb +6 -4
  388. data/lib/datadog/tracing/tracer.rb +66 -14
  389. data/lib/datadog/tracing/transport/http/api.rb +5 -4
  390. data/lib/datadog/tracing/transport/http/client.rb +5 -4
  391. data/lib/datadog/tracing/transport/http/traces.rb +13 -44
  392. data/lib/datadog/tracing/transport/http.rb +13 -70
  393. data/lib/datadog/tracing/transport/serializable_trace.rb +31 -7
  394. data/lib/datadog/tracing/transport/trace_formatter.rb +7 -0
  395. data/lib/datadog/tracing/transport/traces.rb +47 -13
  396. data/lib/datadog/tracing/utils.rb +1 -1
  397. data/lib/datadog/tracing/workers/trace_writer.rb +8 -5
  398. data/lib/datadog/tracing/workers.rb +5 -4
  399. data/lib/datadog/tracing/writer.rb +10 -6
  400. data/lib/datadog/tracing.rb +16 -3
  401. data/lib/datadog/version.rb +2 -2
  402. data/lib/datadog.rb +2 -0
  403. metadata +149 -54
  404. data/ext/datadog_profiling_loader/datadog_profiling_loader.c +0 -142
  405. data/ext/datadog_profiling_loader/extconf.rb +0 -60
  406. data/lib/datadog/appsec/assets/waf_rules/processors.json +0 -92
  407. data/lib/datadog/appsec/assets/waf_rules/scanners.json +0 -114
  408. data/lib/datadog/appsec/contrib/devise/event.rb +0 -57
  409. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +0 -77
  410. data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +0 -54
  411. data/lib/datadog/appsec/contrib/devise/resource.rb +0 -35
  412. data/lib/datadog/appsec/contrib/devise/tracking.rb +0 -57
  413. data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +0 -46
  414. data/lib/datadog/appsec/contrib/patcher.rb +0 -12
  415. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +0 -69
  416. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +0 -47
  417. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +0 -53
  418. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +0 -53
  419. data/lib/datadog/appsec/contrib/sinatra/ext.rb +0 -14
  420. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +0 -48
  421. data/lib/datadog/appsec/monitor/reactive/set_user.rb +0 -45
  422. data/lib/datadog/appsec/processor/actions.rb +0 -49
  423. data/lib/datadog/appsec/processor/context.rb +0 -107
  424. data/lib/datadog/appsec/processor/rule_merger.rb +0 -170
  425. data/lib/datadog/appsec/processor.rb +0 -106
  426. data/lib/datadog/appsec/reactive/address_hash.rb +0 -22
  427. data/lib/datadog/appsec/reactive/engine.rb +0 -47
  428. data/lib/datadog/appsec/reactive/operation.rb +0 -68
  429. data/lib/datadog/appsec/reactive/subscriber.rb +0 -19
  430. data/lib/datadog/appsec/scope.rb +0 -58
  431. data/lib/datadog/appsec/utils/trace_operation.rb +0 -15
  432. data/lib/datadog/core/crashtracking/agent_base_url.rb +0 -21
  433. data/lib/datadog/core/remote/transport/http/api/instance.rb +0 -39
  434. data/lib/datadog/core/remote/transport/http/api/spec.rb +0 -21
  435. data/lib/datadog/core/remote/transport/http/builder.rb +0 -219
  436. data/lib/datadog/core/telemetry/http/env.rb +0 -20
  437. data/lib/datadog/core/telemetry/http/ext.rb +0 -28
  438. data/lib/datadog/core/telemetry/http/response.rb +0 -70
  439. data/lib/datadog/core/telemetry/http/transport.rb +0 -90
  440. data/lib/datadog/di/transport.rb +0 -81
  441. data/lib/datadog/tracing/transport/http/api/spec.rb +0 -19
@@ -17,7 +17,7 @@
17
17
  #include "setup_signal_handler.h"
18
18
  #include "time_helpers.h"
19
19
 
20
- // Used to trigger the execution of Collectors::ThreadState, which implements all of the sampling logic
20
+ // Used to trigger the execution of Collectors::ThreadContext, which implements all of the sampling logic
21
21
  // itself; this class only implements the "when to do it" part.
22
22
  //
23
23
  // This file implements the native bits of the Datadog::Profiling::Collectors::CpuAndWallTimeWorker class
@@ -33,7 +33,7 @@
33
33
  // Currently, sampling Ruby threads requires calling Ruby VM APIs that are only safe to call while holding on to the
34
34
  // global VM lock (and are not async-signal safe -- cannot be called from a signal handler).
35
35
  //
36
- // @ivoanjo: As a note, I don't think we should think of this constraint as set in stone. Since can reach into the Ruby
36
+ // @ivoanjo: As a note, I don't think we should think of this constraint as set in stone. Since we can reach inside the Ruby
37
37
  // internals, we may be able to figure out a way of overcoming it. But it's definitely going to be hard so for now
38
38
  // we're considering it as a given.
39
39
  //
@@ -92,7 +92,7 @@ unsigned int MAX_ALLOC_WEIGHT = 10000;
92
92
  #endif
93
93
 
94
94
  // Contains state for a single CpuAndWallTimeWorker instance
95
- struct cpu_and_wall_time_worker_state {
95
+ typedef struct {
96
96
  // These are immutable after initialization
97
97
 
98
98
  bool gc_profiling_enabled;
@@ -122,7 +122,11 @@ struct cpu_and_wall_time_worker_state {
122
122
  // Others
123
123
 
124
124
  // Used to detect/avoid nested sampling, e.g. when on_newobj_event gets triggered by a memory allocation
125
- // that happens during another sample.
125
+ // that happens during another sample, or when the signal handler gets triggered while we're already in the middle of
126
+ // sampling.
127
+ //
128
+ // @ivoanjo: Right now we always sample inside `safely_call`; if that ever changes, this flag may need to become
129
+ // volatile/atomic/have some barriers to ensure it's visible during e.g. signal handlers.
126
130
  bool during_sample;
127
131
 
128
132
  #ifndef NO_GVL_INSTRUMENTATION
@@ -145,16 +149,6 @@ struct cpu_and_wall_time_worker_state {
145
149
  // How many times we actually tried to interrupt a thread for sampling
146
150
  unsigned int interrupt_thread_attempts;
147
151
 
148
- // # Stats for the results of calling rb_postponed_job_register_one
149
- // The same function was already waiting to be executed
150
- unsigned int postponed_job_skipped_already_existed;
151
- // The function was added to the queue successfully
152
- unsigned int postponed_job_success;
153
- // The queue was full
154
- unsigned int postponed_job_full;
155
- // The function returned an unknown result code
156
- unsigned int postponed_job_unknown_result;
157
-
158
152
  // # CPU/Walltime sampling stats
159
153
  // How many times we actually CPU/wall sampled
160
154
  unsigned int cpu_sampled;
@@ -187,7 +181,7 @@ struct cpu_and_wall_time_worker_state {
187
181
  uint64_t gvl_sampling_time_ns_max;
188
182
  uint64_t gvl_sampling_time_ns_total;
189
183
  } stats;
190
- };
184
+ } cpu_and_wall_time_worker_state;
191
185
 
192
186
  static VALUE _native_new(VALUE klass);
193
187
  static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self);
@@ -195,7 +189,7 @@ static void cpu_and_wall_time_worker_typed_data_mark(void *state_ptr);
195
189
  static VALUE _native_sampling_loop(VALUE self, VALUE instance);
196
190
  static VALUE _native_stop(DDTRACE_UNUSED VALUE _self, VALUE self_instance, VALUE worker_thread);
197
191
  static VALUE stop(VALUE self_instance, VALUE optional_exception);
198
- static void stop_state(struct cpu_and_wall_time_worker_state *state, VALUE optional_exception);
192
+ static void stop_state(cpu_and_wall_time_worker_state *state, VALUE optional_exception);
199
193
  static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED siginfo_t *_info, DDTRACE_UNUSED void *_ucontext);
200
194
  static void *run_sampling_trigger_loop(void *state_ptr);
201
195
  static void interrupt_sampling_trigger_loop(void *state_ptr);
@@ -221,14 +215,14 @@ static VALUE _native_stats(DDTRACE_UNUSED VALUE self, VALUE instance);
221
215
  static VALUE _native_stats_reset_not_thread_safe(DDTRACE_UNUSED VALUE self, VALUE instance);
222
216
  void *simulate_sampling_signal_delivery(DDTRACE_UNUSED void *_unused);
223
217
  static void grab_gvl_and_sample(void);
224
- static void reset_stats_not_thread_safe(struct cpu_and_wall_time_worker_state *state);
218
+ static void reset_stats_not_thread_safe(cpu_and_wall_time_worker_state *state);
225
219
  static void sleep_for(uint64_t time_ns);
226
220
  static VALUE _native_allocation_count(DDTRACE_UNUSED VALUE self);
227
221
  static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *unused2);
228
- static void disable_tracepoints(struct cpu_and_wall_time_worker_state *state);
222
+ static void disable_tracepoints(cpu_and_wall_time_worker_state *state);
229
223
  static VALUE _native_with_blocked_sigprof(DDTRACE_UNUSED VALUE self);
230
224
  static VALUE rescued_sample_allocation(VALUE tracepoint_data);
231
- static void delayed_error(struct cpu_and_wall_time_worker_state *state, const char *error);
225
+ static void delayed_error(cpu_and_wall_time_worker_state *state, const char *error);
232
226
  static VALUE _native_delayed_error(DDTRACE_UNUSED VALUE self, VALUE instance, VALUE error_msg);
233
227
  static VALUE _native_hold_signals(DDTRACE_UNUSED VALUE self);
234
228
  static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self);
@@ -262,7 +256,7 @@ static VALUE _native_gvl_profiling_hook_active(DDTRACE_UNUSED VALUE self, VALUE
262
256
  // This global state is needed because a bunch of functions on this file need to access it from situations
263
257
  // (e.g. signal handler) where it's impossible or just awkward to pass it as an argument.
264
258
  static VALUE active_sampler_instance = Qnil;
265
- static struct cpu_and_wall_time_worker_state *active_sampler_instance_state = NULL;
259
+ static cpu_and_wall_time_worker_state *active_sampler_instance_state = NULL;
266
260
 
267
261
  // See handle_sampling_signal for details on what this does
268
262
  #ifdef NO_POSTPONED_TRIGGER
@@ -334,7 +328,7 @@ void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module) {
334
328
  rb_define_singleton_method(testing_module, "_native_gvl_profiling_hook_active", _native_gvl_profiling_hook_active, 1);
335
329
  }
336
330
 
337
- // This structure is used to define a Ruby object that stores a pointer to a struct cpu_and_wall_time_worker_state
331
+ // This structure is used to define a Ruby object that stores a pointer to a cpu_and_wall_time_worker_state
338
332
  // See also https://github.com/ruby/ruby/blob/master/doc/extension.rdoc for how this works
339
333
  static const rb_data_type_t cpu_and_wall_time_worker_typed_data = {
340
334
  .wrap_struct_name = "Datadog::Profiling::Collectors::CpuAndWallTimeWorker",
@@ -350,7 +344,7 @@ static const rb_data_type_t cpu_and_wall_time_worker_typed_data = {
350
344
  static VALUE _native_new(VALUE klass) {
351
345
  long now = monotonic_wall_time_now_ns(RAISE_ON_FAILURE);
352
346
 
353
- struct cpu_and_wall_time_worker_state *state = ruby_xcalloc(1, sizeof(struct cpu_and_wall_time_worker_state));
347
+ cpu_and_wall_time_worker_state *state = ruby_xcalloc(1, sizeof(cpu_and_wall_time_worker_state));
354
348
 
355
349
  // Note: Any exceptions raised from this note until the TypedData_Wrap_Struct call will lead to the state memory
356
350
  // being leaked.
@@ -414,8 +408,8 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
414
408
  ENFORCE_BOOLEAN(gvl_profiling_enabled);
415
409
  ENFORCE_BOOLEAN(skip_idle_samples_for_testing)
416
410
 
417
- struct cpu_and_wall_time_worker_state *state;
418
- TypedData_Get_Struct(self_instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
411
+ cpu_and_wall_time_worker_state *state;
412
+ TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
419
413
 
420
414
  state->gc_profiling_enabled = (gc_profiling_enabled == Qtrue);
421
415
  state->no_signals_workaround_enabled = (no_signals_workaround_enabled == Qtrue);
@@ -445,7 +439,7 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
445
439
 
446
440
  // Since our state contains references to Ruby objects, we need to tell the Ruby GC about them
447
441
  static void cpu_and_wall_time_worker_typed_data_mark(void *state_ptr) {
448
- struct cpu_and_wall_time_worker_state *state = (struct cpu_and_wall_time_worker_state *) state_ptr;
442
+ cpu_and_wall_time_worker_state *state = (cpu_and_wall_time_worker_state *) state_ptr;
449
443
 
450
444
  rb_gc_mark(state->thread_context_collector_instance);
451
445
  rb_gc_mark(state->idle_sampling_helper_instance);
@@ -457,8 +451,8 @@ static void cpu_and_wall_time_worker_typed_data_mark(void *state_ptr) {
457
451
 
458
452
  // Called in a background thread created in CpuAndWallTimeWorker#start
459
453
  static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
460
- struct cpu_and_wall_time_worker_state *state;
461
- TypedData_Get_Struct(instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
454
+ cpu_and_wall_time_worker_state *state;
455
+ TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
462
456
 
463
457
  // If we already got a delayed exception registered even before starting, raise before starting
464
458
  if (state->failure_exception != Qnil) {
@@ -466,7 +460,7 @@ static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
466
460
  rb_exc_raise(state->failure_exception);
467
461
  }
468
462
 
469
- struct cpu_and_wall_time_worker_state *old_state = active_sampler_instance_state;
463
+ cpu_and_wall_time_worker_state *old_state = active_sampler_instance_state;
470
464
  if (old_state != NULL) {
471
465
  if (is_thread_alive(old_state->owner_thread)) {
472
466
  rb_raise(
@@ -546,15 +540,15 @@ static VALUE _native_sampling_loop(DDTRACE_UNUSED VALUE _self, VALUE instance) {
546
540
  }
547
541
 
548
542
  static VALUE _native_stop(DDTRACE_UNUSED VALUE _self, VALUE self_instance, VALUE worker_thread) {
549
- struct cpu_and_wall_time_worker_state *state;
550
- TypedData_Get_Struct(self_instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
543
+ cpu_and_wall_time_worker_state *state;
544
+ TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
551
545
 
552
546
  state->stop_thread = worker_thread;
553
547
 
554
548
  return stop(self_instance, /* optional_exception: */ Qnil);
555
549
  }
556
550
 
557
- static void stop_state(struct cpu_and_wall_time_worker_state *state, VALUE optional_exception) {
551
+ static void stop_state(cpu_and_wall_time_worker_state *state, VALUE optional_exception) {
558
552
  atomic_store(&state->should_run, false);
559
553
  state->failure_exception = optional_exception;
560
554
 
@@ -563,8 +557,8 @@ static void stop_state(struct cpu_and_wall_time_worker_state *state, VALUE optio
563
557
  }
564
558
 
565
559
  static VALUE stop(VALUE self_instance, VALUE optional_exception) {
566
- struct cpu_and_wall_time_worker_state *state;
567
- TypedData_Get_Struct(self_instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
560
+ cpu_and_wall_time_worker_state *state;
561
+ TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
568
562
 
569
563
  stop_state(state, optional_exception);
570
564
 
@@ -575,7 +569,7 @@ static VALUE stop(VALUE self_instance, VALUE optional_exception) {
575
569
  // We need to be careful not to change any state that may be observed OR to restore it if we do. For instance, if anything
576
570
  // we do here can set `errno`, then we must be careful to restore the old `errno` after the fact.
577
571
  static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED siginfo_t *_info, DDTRACE_UNUSED void *_ucontext) {
578
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
572
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
579
573
 
580
574
  // This can potentially happen if the CpuAndWallTimeWorker was stopped while the signal delivery was happening; nothing to do
581
575
  if (state == NULL) return;
@@ -589,25 +583,17 @@ static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED si
589
583
  return;
590
584
  }
591
585
 
592
- // We implicitly assume there can be no concurrent nor nested calls to handle_sampling_signal because
593
- // a) we get triggered using SIGPROF, and the docs state a second SIGPROF will not interrupt an existing one
586
+ // We assume there can be no concurrent nor nested calls to handle_sampling_signal because
587
+ // a) we get triggered using SIGPROF, and the docs state a second SIGPROF will not interrupt an existing one (see sigaction docs on sa_mask)
594
588
  // b) we validate we are in the thread that has the global VM lock; if a different thread gets a signal, it will return early
595
589
  // because it will not have the global VM lock
596
590
 
597
- // Note: rb_postponed_job_register_one ensures that if there's a previous sample_from_postponed_job queued for execution
598
- // then we will not queue a second one. It does this by doing a linear scan on the existing jobs; in the future we
599
- // may want to implement that check ourselves.
600
-
601
591
  state->stats.signal_handler_enqueued_sample++;
602
592
 
603
- // Note: If we ever want to get rid of rb_postponed_job_register_one, remember not to clobber Ruby exceptions, as
604
- // this function does this helpful job for us now -- https://github.com/ruby/ruby/commit/a98e343d39c4d7bf1e2190b076720f32d9f298b3.
605
593
  #ifndef NO_POSTPONED_TRIGGER // Ruby 3.3+
606
594
  rb_postponed_job_trigger(sample_from_postponed_job_handle);
607
- state->stats.postponed_job_success++; // Always succeeds
608
595
  #else
609
-
610
- // This is a workaround for https://bugs.ruby-lang.org/issues/19991 (for Ruby < 3.3)
596
+ // Passing in `gc_finalize_deferred_workaround` is a workaround for https://bugs.ruby-lang.org/issues/19991 (for Ruby < 3.3)
611
597
  //
612
598
  // TL;DR the `rb_postponed_job_register_one` API is not atomic (which is why it got replaced by `rb_postponed_job_trigger`)
613
599
  // and in rare cases can cause VM crashes.
@@ -631,26 +617,13 @@ static void handle_sampling_signal(DDTRACE_UNUSED int _signal, DDTRACE_UNUSED si
631
617
  //
632
618
  // Thus, our workaround is simple: we pass in objspace as our argument, just in case the clobbering happens.
633
619
  // In the happy path, we never use this argument so it makes no difference. In the buggy path, we avoid crashing the VM.
634
- int result = rb_postponed_job_register(0, sample_from_postponed_job, gc_finalize_deferred_workaround /* instead of NULL */);
635
-
636
- // Officially, the result of rb_postponed_job_register_one is documented as being opaque, but in practice it does not
637
- // seem to have changed between Ruby 2.3 and 3.2, and so we track it as a debugging mechanism
638
- switch (result) {
639
- case 0:
640
- state->stats.postponed_job_full++; break;
641
- case 1:
642
- state->stats.postponed_job_success++; break;
643
- case 2:
644
- state->stats.postponed_job_skipped_already_existed++; break;
645
- default:
646
- state->stats.postponed_job_unknown_result++;
647
- }
620
+ rb_postponed_job_register(0, sample_from_postponed_job, gc_finalize_deferred_workaround /* instead of NULL */);
648
621
  #endif
649
622
  }
650
623
 
651
624
  // The actual sampling trigger loop always runs **without** the global vm lock.
652
625
  static void *run_sampling_trigger_loop(void *state_ptr) {
653
- struct cpu_and_wall_time_worker_state *state = (struct cpu_and_wall_time_worker_state *) state_ptr;
626
+ cpu_and_wall_time_worker_state *state = (cpu_and_wall_time_worker_state *) state_ptr;
654
627
 
655
628
  uint64_t minimum_time_between_signals = MILLIS_AS_NS(10);
656
629
 
@@ -709,13 +682,15 @@ static void *run_sampling_trigger_loop(void *state_ptr) {
709
682
 
710
683
  // This is called by the Ruby VM when it wants to shut down the background thread
711
684
  static void interrupt_sampling_trigger_loop(void *state_ptr) {
712
- struct cpu_and_wall_time_worker_state *state = (struct cpu_and_wall_time_worker_state *) state_ptr;
685
+ cpu_and_wall_time_worker_state *state = (cpu_and_wall_time_worker_state *) state_ptr;
713
686
 
714
687
  atomic_store(&state->should_run, false);
715
688
  }
716
689
 
690
+ // Note: If we ever want to get rid of the postponed job execution, remember not to clobber Ruby exceptions, as
691
+ // this function does this helpful job for us now -- https://github.com/ruby/ruby/commit/a98e343d39c4d7bf1e2190b076720f32d9f298b3.
717
692
  static void sample_from_postponed_job(DDTRACE_UNUSED void *_unused) {
718
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
693
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
719
694
 
720
695
  // This can potentially happen if the CpuAndWallTimeWorker was stopped while the postponed job was waiting to be executed; nothing to do
721
696
  if (state == NULL) return;
@@ -735,8 +710,8 @@ static void sample_from_postponed_job(DDTRACE_UNUSED void *_unused) {
735
710
  }
736
711
 
737
712
  static VALUE rescued_sample_from_postponed_job(VALUE self_instance) {
738
- struct cpu_and_wall_time_worker_state *state;
739
- TypedData_Get_Struct(self_instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
713
+ cpu_and_wall_time_worker_state *state;
714
+ TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
740
715
 
741
716
  long wall_time_ns_before_sample = monotonic_wall_time_now_ns(RAISE_ON_FAILURE);
742
717
 
@@ -791,8 +766,8 @@ static VALUE _native_current_sigprof_signal_handler(DDTRACE_UNUSED VALUE self) {
791
766
  }
792
767
 
793
768
  static VALUE release_gvl_and_run_sampling_trigger_loop(VALUE instance) {
794
- struct cpu_and_wall_time_worker_state *state;
795
- TypedData_Get_Struct(instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
769
+ cpu_and_wall_time_worker_state *state;
770
+ TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
796
771
 
797
772
  // Final preparations: Setup signal handler and enable tracepoints. We run these here and not in `_native_sampling_loop`
798
773
  // because they may raise exceptions.
@@ -842,7 +817,7 @@ static VALUE release_gvl_and_run_sampling_trigger_loop(VALUE instance) {
842
817
  // This method exists only to enable testing Datadog::Profiling::Collectors::CpuAndWallTimeWorker behavior using RSpec.
843
818
  // It SHOULD NOT be used for other purposes.
844
819
  static VALUE _native_is_running(DDTRACE_UNUSED VALUE self, VALUE instance) {
845
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
820
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
846
821
 
847
822
  return (state != NULL && is_thread_alive(state->owner_thread) && state->self_instance == instance) ? Qtrue : Qfalse;
848
823
  }
@@ -875,8 +850,8 @@ static VALUE _native_trigger_sample(DDTRACE_UNUSED VALUE self) {
875
850
  // This method exists only to enable testing Datadog::Profiling::Collectors::CpuAndWallTimeWorker behavior using RSpec.
876
851
  // It SHOULD NOT be used for other purposes.
877
852
  static VALUE _native_gc_tracepoint(DDTRACE_UNUSED VALUE self, VALUE instance) {
878
- struct cpu_and_wall_time_worker_state *state;
879
- TypedData_Get_Struct(instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
853
+ cpu_and_wall_time_worker_state *state;
854
+ TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
880
855
 
881
856
  return state->gc_tracepoint;
882
857
  }
@@ -902,7 +877,7 @@ static void on_gc_event(VALUE tracepoint_data, DDTRACE_UNUSED void *unused) {
902
877
  int event = rb_tracearg_event_flag(rb_tracearg_from_tracepoint(tracepoint_data));
903
878
  if (event != RUBY_INTERNAL_EVENT_GC_ENTER && event != RUBY_INTERNAL_EVENT_GC_EXIT) return; // Unknown event
904
879
 
905
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
880
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
906
881
 
907
882
  // This should not happen in a normal situation because the tracepoint is always enabled after the instance is set
908
883
  // and disabled before it is cleared, but just in case...
@@ -926,7 +901,7 @@ static void on_gc_event(VALUE tracepoint_data, DDTRACE_UNUSED void *unused) {
926
901
  }
927
902
 
928
903
  static void after_gc_from_postponed_job(DDTRACE_UNUSED void *_unused) {
929
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
904
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
930
905
 
931
906
  // This can potentially happen if the CpuAndWallTimeWorker was stopped while the postponed job was waiting to be executed; nothing to do
932
907
  if (state == NULL) return;
@@ -981,8 +956,8 @@ static VALUE _native_simulate_sample_from_postponed_job(DDTRACE_UNUSED VALUE sel
981
956
  // In the future, if we add more other components with tracepoints, we will need to coordinate stopping all such
982
957
  // tracepoints before doing the other cleaning steps.
983
958
  static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE instance) {
984
- struct cpu_and_wall_time_worker_state *state;
985
- TypedData_Get_Struct(instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
959
+ cpu_and_wall_time_worker_state *state;
960
+ TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
986
961
 
987
962
  // Disable all tracepoints, so that there are no more attempts to mutate the profile
988
963
  disable_tracepoints(state);
@@ -1000,8 +975,8 @@ static VALUE _native_is_sigprof_blocked_in_current_thread(DDTRACE_UNUSED VALUE s
1000
975
  }
1001
976
 
1002
977
  static VALUE _native_stats(DDTRACE_UNUSED VALUE self, VALUE instance) {
1003
- struct cpu_and_wall_time_worker_state *state;
1004
- TypedData_Get_Struct(instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
978
+ cpu_and_wall_time_worker_state *state;
979
+ TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
1005
980
 
1006
981
  unsigned long total_cpu_samples_attempted = state->stats.cpu_sampled + state->stats.cpu_skipped;
1007
982
  VALUE effective_cpu_sample_rate =
@@ -1020,10 +995,6 @@ static VALUE _native_stats(DDTRACE_UNUSED VALUE self, VALUE instance) {
1020
995
  ID2SYM(rb_intern("simulated_signal_delivery")), /* => */ UINT2NUM(state->stats.simulated_signal_delivery),
1021
996
  ID2SYM(rb_intern("signal_handler_enqueued_sample")), /* => */ UINT2NUM(state->stats.signal_handler_enqueued_sample),
1022
997
  ID2SYM(rb_intern("signal_handler_wrong_thread")), /* => */ UINT2NUM(state->stats.signal_handler_wrong_thread),
1023
- ID2SYM(rb_intern("postponed_job_skipped_already_existed")), /* => */ UINT2NUM(state->stats.postponed_job_skipped_already_existed),
1024
- ID2SYM(rb_intern("postponed_job_success")), /* => */ UINT2NUM(state->stats.postponed_job_success),
1025
- ID2SYM(rb_intern("postponed_job_full")), /* => */ UINT2NUM(state->stats.postponed_job_full),
1026
- ID2SYM(rb_intern("postponed_job_unknown_result")), /* => */ UINT2NUM(state->stats.postponed_job_unknown_result),
1027
998
  ID2SYM(rb_intern("interrupt_thread_attempts")), /* => */ UINT2NUM(state->stats.interrupt_thread_attempts),
1028
999
 
1029
1000
  // CPU Stats
@@ -1059,22 +1030,21 @@ static VALUE _native_stats(DDTRACE_UNUSED VALUE self, VALUE instance) {
1059
1030
  }
1060
1031
 
1061
1032
  static VALUE _native_stats_reset_not_thread_safe(DDTRACE_UNUSED VALUE self, VALUE instance) {
1062
- struct cpu_and_wall_time_worker_state *state;
1063
- TypedData_Get_Struct(instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
1033
+ cpu_and_wall_time_worker_state *state;
1034
+ TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
1064
1035
  reset_stats_not_thread_safe(state);
1065
1036
  return Qnil;
1066
1037
  }
1067
1038
 
1068
1039
  void *simulate_sampling_signal_delivery(DDTRACE_UNUSED void *_unused) {
1069
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1040
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1070
1041
 
1071
1042
  // This can potentially happen if the CpuAndWallTimeWorker was stopped while the IdleSamplingHelper was trying to execute this action
1072
1043
  if (state == NULL) return NULL;
1073
1044
 
1074
1045
  state->stats.simulated_signal_delivery++;
1075
1046
 
1076
- // @ivoanjo: We could instead directly call sample_from_postponed_job, but I chose to go through the signal handler
1077
- // so that the simulated case is as close to the original one as well (including any metrics increases, etc).
1047
+ // `handle_sampling_signal` does a few things extra on top of `sample_from_postponed_job` so that's why we don't shortcut here
1078
1048
  handle_sampling_signal(0, NULL, NULL);
1079
1049
 
1080
1050
  return NULL; // Unused
@@ -1082,7 +1052,7 @@ void *simulate_sampling_signal_delivery(DDTRACE_UNUSED void *_unused) {
1082
1052
 
1083
1053
  static void grab_gvl_and_sample(void) { rb_thread_call_with_gvl(simulate_sampling_signal_delivery, NULL); }
1084
1054
 
1085
- static void reset_stats_not_thread_safe(struct cpu_and_wall_time_worker_state *state) {
1055
+ static void reset_stats_not_thread_safe(cpu_and_wall_time_worker_state *state) {
1086
1056
  // NOTE: This is not really thread safe so ongoing sampling operations that are concurrent with a reset can have their stats:
1087
1057
  // * Lost (writes after stats retrieval but before reset).
1088
1058
  // * Included in the previous stats window (writes before stats retrieval and reset).
@@ -1116,7 +1086,7 @@ static void sleep_for(uint64_t time_ns) {
1116
1086
  }
1117
1087
 
1118
1088
  static VALUE _native_allocation_count(DDTRACE_UNUSED VALUE self) {
1119
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state;
1089
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state;
1120
1090
 
1121
1091
  bool are_allocations_being_tracked = state != NULL && state->allocation_profiling_enabled && state->allocation_counting_enabled;
1122
1092
 
@@ -1149,7 +1119,7 @@ static VALUE _native_allocation_count(DDTRACE_UNUSED VALUE self) {
1149
1119
  // call `rb_tracearg_from_tracepoint(anything)` anywhere during this function or its callees to get the data, so that's
1150
1120
  // why it's not being passed as an argument.
1151
1121
  static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *unused2) {
1152
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1122
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1153
1123
 
1154
1124
  // This should not happen in a normal situation because the tracepoint is always enabled after the instance is set
1155
1125
  // and disabled before it is cleared, but just in case...
@@ -1171,6 +1141,16 @@ static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *u
1171
1141
  return;
1172
1142
  }
1173
1143
 
1144
+ // If Ruby is in the middle of raising an exception, we don't want to try to sample. This is because if we accidentally
1145
+ // trigger an exception inside the profiler code, bad things will happen (specifically, Ruby will try to kill off the
1146
+ // thread even though we may try to catch the exception).
1147
+ //
1148
+ // Note that "in the middle of raising an exception" means the exception itself has already been allocated.
1149
+ // What's getting allocated now is probably the backtrace objects (@ivoanjo or at least that's what I've observed)
1150
+ if (is_raised_flag_set(rb_thread_current())) {
1151
+ return;
1152
+ }
1153
+
1174
1154
  // Hot path: Dynamic sampling rate is usually enabled and the sampling decision is usually false
1175
1155
  if (RB_LIKELY(state->dynamic_sampling_rate_enabled && !discrete_dynamic_sampler_should_sample(&state->allocation_sampler))) {
1176
1156
  state->stats.allocation_skipped++;
@@ -1197,10 +1177,6 @@ static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *u
1197
1177
  &state->allocation_sampler, HANDLE_CLOCK_FAILURE(monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE))
1198
1178
  );
1199
1179
 
1200
- // @ivoanjo: Strictly speaking, this is not needed because Ruby should not call the same tracepoint while a previous
1201
- // invocation is still pending, (e.g. it wouldn't call `on_newobj_event` while it's already running), but I decided
1202
- // to keep this here for consistency -- every call to the thread context (other than the special gc calls which are
1203
- // defined as not being able to allocate) sets this.
1204
1180
  state->during_sample = true;
1205
1181
 
1206
1182
  // Rescue against any exceptions that happen during sampling
@@ -1225,7 +1201,7 @@ static void on_newobj_event(DDTRACE_UNUSED VALUE unused1, DDTRACE_UNUSED void *u
1225
1201
  state->during_sample = false;
1226
1202
  }
1227
1203
 
1228
- static void disable_tracepoints(struct cpu_and_wall_time_worker_state *state) {
1204
+ static void disable_tracepoints(cpu_and_wall_time_worker_state *state) {
1229
1205
  if (state->gc_tracepoint != Qnil) {
1230
1206
  rb_tracepoint_disable(state->gc_tracepoint);
1231
1207
  }
@@ -1254,7 +1230,7 @@ static VALUE _native_with_blocked_sigprof(DDTRACE_UNUSED VALUE self) {
1254
1230
  }
1255
1231
 
1256
1232
  static VALUE rescued_sample_allocation(DDTRACE_UNUSED VALUE unused) {
1257
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1233
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1258
1234
 
1259
1235
  // This should not happen in a normal situation because on_newobj_event already checked for this, but just in case...
1260
1236
  if (state == NULL) return Qnil;
@@ -1283,7 +1259,7 @@ static VALUE rescued_sample_allocation(DDTRACE_UNUSED VALUE unused) {
1283
1259
  return Qnil;
1284
1260
  }
1285
1261
 
1286
- static void delayed_error(struct cpu_and_wall_time_worker_state *state, const char *error) {
1262
+ static void delayed_error(cpu_and_wall_time_worker_state *state, const char *error) {
1287
1263
  // If we can't raise an immediate exception at the calling site, use the asynchronous flow through the main worker loop.
1288
1264
  stop_state(state, rb_exc_new_cstr(rb_eRuntimeError, error));
1289
1265
  }
@@ -1291,8 +1267,8 @@ static void delayed_error(struct cpu_and_wall_time_worker_state *state, const ch
1291
1267
  static VALUE _native_delayed_error(DDTRACE_UNUSED VALUE self, VALUE instance, VALUE error_msg) {
1292
1268
  ENFORCE_TYPE(error_msg, T_STRING);
1293
1269
 
1294
- struct cpu_and_wall_time_worker_state *state;
1295
- TypedData_Get_Struct(instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
1270
+ cpu_and_wall_time_worker_state *state;
1271
+ TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
1296
1272
 
1297
1273
  delayed_error(state, rb_string_value_cstr(&error_msg));
1298
1274
 
@@ -1345,7 +1321,7 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
1345
1321
  rb_postponed_job_register_one(0, after_gvl_running_from_postponed_job, NULL);
1346
1322
  #endif
1347
1323
  } else if (result == ON_GVL_RUNNING_DONT_SAMPLE) {
1348
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1324
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1349
1325
 
1350
1326
  if (state == NULL) return; // This should not happen, but just in case...
1351
1327
 
@@ -1358,7 +1334,7 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
1358
1334
  }
1359
1335
 
1360
1336
  static void after_gvl_running_from_postponed_job(DDTRACE_UNUSED void *_unused) {
1361
- struct cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1337
+ cpu_and_wall_time_worker_state *state = active_sampler_instance_state; // Read from global variable, see "sampler global state safety" note above
1362
1338
 
1363
1339
  // This can potentially happen if the CpuAndWallTimeWorker was stopped while the postponed job was waiting to be executed; nothing to do
1364
1340
  if (state == NULL) return;
@@ -1372,8 +1348,8 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
1372
1348
  }
1373
1349
 
1374
1350
  static VALUE rescued_after_gvl_running_from_postponed_job(VALUE self_instance) {
1375
- struct cpu_and_wall_time_worker_state *state;
1376
- TypedData_Get_Struct(self_instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
1351
+ cpu_and_wall_time_worker_state *state;
1352
+ TypedData_Get_Struct(self_instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
1377
1353
 
1378
1354
  long wall_time_ns_before_sample = monotonic_wall_time_now_ns(RAISE_ON_FAILURE);
1379
1355
  thread_context_collector_sample_after_gvl_running(state->thread_context_collector_instance, rb_thread_current(), wall_time_ns_before_sample);
@@ -1394,8 +1370,8 @@ static VALUE _native_resume_signals(DDTRACE_UNUSED VALUE self) {
1394
1370
  }
1395
1371
 
1396
1372
  static VALUE _native_gvl_profiling_hook_active(DDTRACE_UNUSED VALUE self, VALUE instance) {
1397
- struct cpu_and_wall_time_worker_state *state;
1398
- TypedData_Get_Struct(instance, struct cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
1373
+ cpu_and_wall_time_worker_state *state;
1374
+ TypedData_Get_Struct(instance, cpu_and_wall_time_worker_state, &cpu_and_wall_time_worker_typed_data, state);
1399
1375
 
1400
1376
  return state->gvl_profiling_hook != NULL ? Qtrue : Qfalse;
1401
1377
  }
@@ -333,7 +333,7 @@ static VALUE _native_should_sample(VALUE self, VALUE now);
333
333
  static VALUE _native_after_sample(VALUE self, VALUE now);
334
334
  static VALUE _native_state_snapshot(VALUE self);
335
335
 
336
- typedef struct sampler_state {
336
+ typedef struct {
337
337
  discrete_dynamic_sampler sampler;
338
338
  } sampler_state;
339
339
 
@@ -16,7 +16,7 @@
16
16
  // every event and is thus, in theory, susceptible to some pattern
17
17
  // biases. In practice, the dynamic readjustment of sampling interval
18
18
  // and randomized starting point should help with avoiding heavy biases.
19
- typedef struct discrete_dynamic_sampler {
19
+ typedef struct {
20
20
  // --- Config ---
21
21
  // Name of this sampler for debug logs.
22
22
  const char *debug_name;
@@ -21,15 +21,15 @@
21
21
  typedef enum { ACTION_WAIT, ACTION_RUN, ACTION_STOP } action;
22
22
 
23
23
  // Contains state for a single CpuAndWallTimeWorker instance
24
- struct idle_sampling_loop_state {
24
+ typedef struct {
25
25
  pthread_mutex_t wakeup_mutex;
26
26
  pthread_cond_t wakeup;
27
27
  action requested_action;
28
28
  void (*run_action_function)(void);
29
- };
29
+ } idle_sampling_loop_state;
30
30
 
31
31
  static VALUE _native_new(VALUE klass);
32
- static void reset_state(struct idle_sampling_loop_state *state);
32
+ static void reset_state(idle_sampling_loop_state *state);
33
33
  static VALUE _native_idle_sampling_loop(DDTRACE_UNUSED VALUE self, VALUE self_instance);
34
34
  static VALUE _native_stop(DDTRACE_UNUSED VALUE self, VALUE self_instance);
35
35
  static void *run_idle_sampling_loop(void *state_ptr);
@@ -62,7 +62,7 @@ void collectors_idle_sampling_helper_init(VALUE profiling_module) {
62
62
  rb_define_singleton_method(testing_module, "_native_idle_sampling_helper_request_action", _native_idle_sampling_helper_request_action, 1);
63
63
  }
64
64
 
65
- // This structure is used to define a Ruby object that stores a pointer to a struct idle_sampling_loop_state
65
+ // This structure is used to define a Ruby object that stores a pointer to a idle_sampling_loop_state
66
66
  // See also https://github.com/ruby/ruby/blob/master/doc/extension.rdoc for how this works
67
67
  static const rb_data_type_t idle_sampling_helper_typed_data = {
68
68
  .wrap_struct_name = "Datadog::Profiling::Collectors::IdleSamplingHelper",
@@ -76,7 +76,7 @@ static const rb_data_type_t idle_sampling_helper_typed_data = {
76
76
  };
77
77
 
78
78
  static VALUE _native_new(VALUE klass) {
79
- struct idle_sampling_loop_state *state = ruby_xcalloc(1, sizeof(struct idle_sampling_loop_state));
79
+ idle_sampling_loop_state *state = ruby_xcalloc(1, sizeof(idle_sampling_loop_state));
80
80
 
81
81
  // Note: Any exceptions raised from this note until the TypedData_Wrap_Struct call will lead to the state memory
82
82
  // being leaked.
@@ -90,7 +90,7 @@ static VALUE _native_new(VALUE klass) {
90
90
  return TypedData_Wrap_Struct(klass, &idle_sampling_helper_typed_data, state);
91
91
  }
92
92
 
93
- static void reset_state(struct idle_sampling_loop_state *state) {
93
+ static void reset_state(idle_sampling_loop_state *state) {
94
94
  state->wakeup_mutex = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
95
95
  state->wakeup = (pthread_cond_t) PTHREAD_COND_INITIALIZER;
96
96
  state->requested_action = ACTION_WAIT;
@@ -101,8 +101,8 @@ static void reset_state(struct idle_sampling_loop_state *state) {
101
101
  // a pristine state before recreating the worker thread (this includes resetting the mutex in case it was left
102
102
  // locked halfway through the VM forking)
103
103
  static VALUE _native_reset(DDTRACE_UNUSED VALUE self, VALUE self_instance) {
104
- struct idle_sampling_loop_state *state;
105
- TypedData_Get_Struct(self_instance, struct idle_sampling_loop_state, &idle_sampling_helper_typed_data, state);
104
+ idle_sampling_loop_state *state;
105
+ TypedData_Get_Struct(self_instance, idle_sampling_loop_state, &idle_sampling_helper_typed_data, state);
106
106
 
107
107
  reset_state(state);
108
108
 
@@ -110,8 +110,8 @@ static VALUE _native_reset(DDTRACE_UNUSED VALUE self, VALUE self_instance) {
110
110
  }
111
111
 
112
112
  static VALUE _native_idle_sampling_loop(DDTRACE_UNUSED VALUE self, VALUE self_instance) {
113
- struct idle_sampling_loop_state *state;
114
- TypedData_Get_Struct(self_instance, struct idle_sampling_loop_state, &idle_sampling_helper_typed_data, state);
113
+ idle_sampling_loop_state *state;
114
+ TypedData_Get_Struct(self_instance, idle_sampling_loop_state, &idle_sampling_helper_typed_data, state);
115
115
 
116
116
  // Release GVL and run the loop waiting for requests
117
117
  rb_thread_call_without_gvl(run_idle_sampling_loop, state, interrupt_idle_sampling_loop, state);
@@ -120,7 +120,7 @@ static VALUE _native_idle_sampling_loop(DDTRACE_UNUSED VALUE self, VALUE self_in
120
120
  }
121
121
 
122
122
  static void *run_idle_sampling_loop(void *state_ptr) {
123
- struct idle_sampling_loop_state *state = (struct idle_sampling_loop_state *) state_ptr;
123
+ idle_sampling_loop_state *state = (idle_sampling_loop_state *) state_ptr;
124
124
  int error = 0;
125
125
 
126
126
  while (true) {
@@ -164,7 +164,7 @@ static void *run_idle_sampling_loop(void *state_ptr) {
164
164
  }
165
165
 
166
166
  static void interrupt_idle_sampling_loop(void *state_ptr) {
167
- struct idle_sampling_loop_state *state = (struct idle_sampling_loop_state *) state_ptr;
167
+ idle_sampling_loop_state *state = (idle_sampling_loop_state *) state_ptr;
168
168
  int error = 0;
169
169
 
170
170
  // Note about the error handling in this situation: Something bad happening at this stage is really really awkward to
@@ -189,8 +189,8 @@ static void interrupt_idle_sampling_loop(void *state_ptr) {
189
189
  }
190
190
 
191
191
  static VALUE _native_stop(DDTRACE_UNUSED VALUE self, VALUE self_instance) {
192
- struct idle_sampling_loop_state *state;
193
- TypedData_Get_Struct(self_instance, struct idle_sampling_loop_state, &idle_sampling_helper_typed_data, state);
192
+ idle_sampling_loop_state *state;
193
+ TypedData_Get_Struct(self_instance, idle_sampling_loop_state, &idle_sampling_helper_typed_data, state);
194
194
 
195
195
  ENFORCE_SUCCESS_GVL(pthread_mutex_lock(&state->wakeup_mutex));
196
196
  state->requested_action = ACTION_STOP;
@@ -204,12 +204,12 @@ static VALUE _native_stop(DDTRACE_UNUSED VALUE self, VALUE self_instance) {
204
204
 
205
205
  // Assumption: Function gets called without the global VM lock
206
206
  void idle_sampling_helper_request_action(VALUE self_instance, void (*run_action_function)(void)) {
207
- struct idle_sampling_loop_state *state;
207
+ idle_sampling_loop_state *state;
208
208
  if (!rb_typeddata_is_kind_of(self_instance, &idle_sampling_helper_typed_data)) {
209
209
  grab_gvl_and_raise(rb_eTypeError, "Wrong argument for idle_sampling_helper_request_action");
210
210
  }
211
211
  // This should never fail the the above check passes
212
- TypedData_Get_Struct(self_instance, struct idle_sampling_loop_state, &idle_sampling_helper_typed_data, state);
212
+ TypedData_Get_Struct(self_instance, idle_sampling_loop_state, &idle_sampling_helper_typed_data, state);
213
213
 
214
214
  ENFORCE_SUCCESS_NO_GVL(pthread_mutex_lock(&state->wakeup_mutex));
215
215
  if (state->requested_action == ACTION_WAIT) {