datadog 2.7.1 → 2.17.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 (417) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +310 -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 +66 -56
  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 +10 -10
  9. data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
  10. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +314 -145
  11. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +1 -4
  12. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +10 -0
  13. data/ext/datadog_profiling_native_extension/encoded_profile.c +79 -0
  14. data/ext/datadog_profiling_native_extension/encoded_profile.h +8 -0
  15. data/ext/datadog_profiling_native_extension/extconf.rb +7 -8
  16. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +2 -0
  17. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +0 -8
  18. data/ext/datadog_profiling_native_extension/heap_recorder.c +61 -174
  19. data/ext/datadog_profiling_native_extension/heap_recorder.h +2 -2
  20. data/ext/datadog_profiling_native_extension/http_transport.c +64 -98
  21. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +68 -1
  22. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +10 -1
  23. data/ext/datadog_profiling_native_extension/profiling.c +19 -8
  24. data/ext/datadog_profiling_native_extension/ruby_helpers.c +8 -8
  25. data/ext/datadog_profiling_native_extension/stack_recorder.c +84 -131
  26. data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -2
  27. data/ext/datadog_profiling_native_extension/time_helpers.h +1 -1
  28. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +47 -0
  29. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +31 -0
  30. data/ext/libdatadog_api/crashtracker.c +17 -15
  31. data/ext/libdatadog_api/crashtracker.h +5 -0
  32. data/ext/libdatadog_api/datadog_ruby_common.c +1 -4
  33. data/ext/libdatadog_api/datadog_ruby_common.h +10 -0
  34. data/ext/libdatadog_api/init.c +15 -0
  35. data/ext/libdatadog_api/library_config.c +122 -0
  36. data/ext/libdatadog_api/library_config.h +19 -0
  37. data/ext/libdatadog_api/macos_development.md +3 -3
  38. data/ext/libdatadog_api/process_discovery.c +117 -0
  39. data/ext/libdatadog_api/process_discovery.h +5 -0
  40. data/ext/libdatadog_extconf_helpers.rb +1 -1
  41. data/lib/datadog/appsec/actions_handler/serializable_backtrace.rb +89 -0
  42. data/lib/datadog/appsec/actions_handler.rb +49 -0
  43. data/lib/datadog/appsec/anonymizer.rb +16 -0
  44. data/lib/datadog/appsec/api_security/lru_cache.rb +49 -0
  45. data/lib/datadog/appsec/api_security.rb +9 -0
  46. data/lib/datadog/appsec/assets/waf_rules/README.md +50 -5
  47. data/lib/datadog/appsec/assets/waf_rules/processors.json +239 -10
  48. data/lib/datadog/appsec/assets/waf_rules/recommended.json +355 -157
  49. data/lib/datadog/appsec/assets/waf_rules/scanners.json +926 -17
  50. data/lib/datadog/appsec/assets/waf_rules/strict.json +62 -32
  51. data/lib/datadog/appsec/autoload.rb +1 -1
  52. data/lib/datadog/appsec/component.rb +41 -33
  53. data/lib/datadog/appsec/compressed_json.rb +40 -0
  54. data/lib/datadog/appsec/configuration/settings.rb +152 -25
  55. data/lib/datadog/appsec/context.rb +74 -0
  56. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +92 -0
  57. data/lib/datadog/appsec/contrib/active_record/integration.rb +41 -0
  58. data/lib/datadog/appsec/contrib/active_record/patcher.rb +101 -0
  59. data/lib/datadog/appsec/contrib/auto_instrument.rb +1 -1
  60. data/lib/datadog/appsec/contrib/devise/configuration.rb +52 -0
  61. data/lib/datadog/appsec/contrib/devise/data_extractor.rb +78 -0
  62. data/lib/datadog/appsec/contrib/devise/ext.rb +22 -0
  63. data/lib/datadog/appsec/contrib/devise/integration.rb +1 -2
  64. data/lib/datadog/appsec/contrib/devise/patcher.rb +33 -25
  65. data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +102 -0
  66. data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +69 -0
  67. data/lib/datadog/appsec/contrib/devise/{patcher/rememberable_patch.rb → patches/skip_signin_tracking_patch.rb} +3 -3
  68. data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +106 -0
  69. data/lib/datadog/appsec/contrib/excon/integration.rb +41 -0
  70. data/lib/datadog/appsec/contrib/excon/patcher.rb +28 -0
  71. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +42 -0
  72. data/lib/datadog/appsec/contrib/faraday/connection_patch.rb +22 -0
  73. data/lib/datadog/appsec/contrib/faraday/integration.rb +42 -0
  74. data/lib/datadog/appsec/contrib/faraday/patcher.rb +53 -0
  75. data/lib/datadog/appsec/contrib/faraday/rack_builder_patch.rb +22 -0
  76. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +41 -0
  77. data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +1 -7
  78. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +17 -30
  79. data/lib/datadog/appsec/contrib/graphql/integration.rb +1 -1
  80. data/lib/datadog/appsec/contrib/graphql/patcher.rb +0 -3
  81. data/lib/datadog/appsec/contrib/rack/ext.rb +34 -0
  82. data/lib/datadog/appsec/contrib/rack/gateway/response.rb +3 -3
  83. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +78 -98
  84. data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
  85. data/lib/datadog/appsec/contrib/rack/patcher.rb +0 -3
  86. data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +10 -11
  87. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +52 -68
  88. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +16 -33
  89. data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
  90. data/lib/datadog/appsec/contrib/rails/patcher.rb +25 -38
  91. data/lib/datadog/appsec/contrib/rest_client/integration.rb +45 -0
  92. data/lib/datadog/appsec/contrib/rest_client/patcher.rb +28 -0
  93. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +38 -0
  94. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +31 -68
  95. data/lib/datadog/appsec/contrib/sinatra/integration.rb +1 -1
  96. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +5 -31
  97. data/lib/datadog/appsec/event.rb +96 -135
  98. data/lib/datadog/appsec/ext.rb +12 -3
  99. data/lib/datadog/appsec/instrumentation/gateway/argument.rb +7 -2
  100. data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +24 -0
  101. data/lib/datadog/appsec/instrumentation/gateway.rb +17 -22
  102. data/lib/datadog/appsec/metrics/collector.rb +38 -0
  103. data/lib/datadog/appsec/metrics/exporter.rb +35 -0
  104. data/lib/datadog/appsec/metrics/telemetry.rb +23 -0
  105. data/lib/datadog/appsec/metrics.rb +13 -0
  106. data/lib/datadog/appsec/monitor/gateway/watcher.rb +52 -32
  107. data/lib/datadog/appsec/processor/rule_loader.rb +26 -31
  108. data/lib/datadog/appsec/processor/rule_merger.rb +7 -6
  109. data/lib/datadog/appsec/processor.rb +5 -4
  110. data/lib/datadog/appsec/remote.rb +26 -12
  111. data/lib/datadog/appsec/response.rb +19 -85
  112. data/lib/datadog/appsec/security_engine/result.rb +67 -0
  113. data/lib/datadog/appsec/security_engine/runner.rb +88 -0
  114. data/lib/datadog/appsec/security_engine.rb +9 -0
  115. data/lib/datadog/appsec/security_event.rb +39 -0
  116. data/lib/datadog/appsec/utils.rb +0 -2
  117. data/lib/datadog/appsec.rb +23 -10
  118. data/lib/datadog/auto_instrument.rb +3 -0
  119. data/lib/datadog/core/buffer/random.rb +18 -2
  120. data/lib/datadog/core/configuration/agent_settings_resolver.rb +42 -14
  121. data/lib/datadog/core/configuration/agentless_settings_resolver.rb +176 -0
  122. data/lib/datadog/core/configuration/components.rb +76 -32
  123. data/lib/datadog/core/configuration/components_state.rb +23 -0
  124. data/lib/datadog/core/configuration/ext.rb +5 -1
  125. data/lib/datadog/core/configuration/option.rb +79 -43
  126. data/lib/datadog/core/configuration/option_definition.rb +6 -4
  127. data/lib/datadog/core/configuration/options.rb +3 -3
  128. data/lib/datadog/core/configuration/settings.rb +100 -41
  129. data/lib/datadog/core/configuration/stable_config.rb +23 -0
  130. data/lib/datadog/core/configuration.rb +43 -11
  131. data/lib/datadog/{tracing → core}/contrib/rails/utils.rb +1 -3
  132. data/lib/datadog/core/crashtracking/component.rb +4 -13
  133. data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
  134. data/lib/datadog/core/encoding.rb +17 -1
  135. data/lib/datadog/core/environment/agent_info.rb +78 -0
  136. data/lib/datadog/core/environment/cgroup.rb +10 -12
  137. data/lib/datadog/core/environment/container.rb +38 -40
  138. data/lib/datadog/core/environment/ext.rb +6 -6
  139. data/lib/datadog/core/environment/git.rb +1 -0
  140. data/lib/datadog/core/environment/identity.rb +3 -3
  141. data/lib/datadog/core/environment/platform.rb +3 -3
  142. data/lib/datadog/core/environment/variable_helpers.rb +1 -1
  143. data/lib/datadog/core/error.rb +11 -9
  144. data/lib/datadog/core/logger.rb +2 -2
  145. data/lib/datadog/core/metrics/client.rb +27 -27
  146. data/lib/datadog/core/metrics/logging.rb +5 -5
  147. data/lib/datadog/core/process_discovery.rb +32 -0
  148. data/lib/datadog/core/rate_limiter.rb +4 -2
  149. data/lib/datadog/core/remote/client/capabilities.rb +6 -0
  150. data/lib/datadog/core/remote/client.rb +107 -92
  151. data/lib/datadog/core/remote/component.rb +18 -19
  152. data/lib/datadog/core/remote/configuration/digest.rb +7 -7
  153. data/lib/datadog/core/remote/configuration/path.rb +1 -1
  154. data/lib/datadog/core/remote/configuration/repository.rb +2 -1
  155. data/lib/datadog/core/remote/negotiation.rb +9 -9
  156. data/lib/datadog/core/remote/transport/config.rb +4 -3
  157. data/lib/datadog/core/remote/transport/http/api.rb +13 -18
  158. data/lib/datadog/core/remote/transport/http/client.rb +5 -4
  159. data/lib/datadog/core/remote/transport/http/config.rb +27 -55
  160. data/lib/datadog/core/remote/transport/http/negotiation.rb +8 -51
  161. data/lib/datadog/core/remote/transport/http.rb +25 -94
  162. data/lib/datadog/core/remote/transport/negotiation.rb +17 -4
  163. data/lib/datadog/core/remote/worker.rb +10 -7
  164. data/lib/datadog/core/runtime/metrics.rb +12 -5
  165. data/lib/datadog/core/telemetry/component.rb +84 -49
  166. data/lib/datadog/core/telemetry/emitter.rb +23 -11
  167. data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +65 -0
  168. data/lib/datadog/core/telemetry/event/app_closing.rb +18 -0
  169. data/lib/datadog/core/telemetry/event/app_dependencies_loaded.rb +33 -0
  170. data/lib/datadog/core/telemetry/event/app_heartbeat.rb +18 -0
  171. data/lib/datadog/core/telemetry/event/app_integrations_change.rb +58 -0
  172. data/lib/datadog/core/telemetry/event/app_started.rb +179 -0
  173. data/lib/datadog/core/telemetry/event/base.rb +40 -0
  174. data/lib/datadog/core/telemetry/event/distributions.rb +18 -0
  175. data/lib/datadog/core/telemetry/event/generate_metrics.rb +43 -0
  176. data/lib/datadog/core/telemetry/event/log.rb +76 -0
  177. data/lib/datadog/core/telemetry/event/message_batch.rb +42 -0
  178. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +43 -0
  179. data/lib/datadog/core/telemetry/event.rb +17 -383
  180. data/lib/datadog/core/telemetry/ext.rb +1 -0
  181. data/lib/datadog/core/telemetry/http/adapters/net.rb +12 -97
  182. data/lib/datadog/core/telemetry/logger.rb +1 -1
  183. data/lib/datadog/core/telemetry/logging.rb +2 -2
  184. data/lib/datadog/core/telemetry/metric.rb +28 -6
  185. data/lib/datadog/core/telemetry/request.rb +4 -4
  186. data/lib/datadog/core/telemetry/transport/http/api.rb +43 -0
  187. data/lib/datadog/core/telemetry/transport/http/client.rb +49 -0
  188. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +92 -0
  189. data/lib/datadog/core/telemetry/transport/http.rb +63 -0
  190. data/lib/datadog/core/telemetry/transport/telemetry.rb +51 -0
  191. data/lib/datadog/core/telemetry/worker.rb +128 -25
  192. data/lib/datadog/core/transport/http/adapters/test.rb +2 -1
  193. data/lib/datadog/core/transport/http/adapters/unix_socket.rb +1 -1
  194. data/lib/datadog/{tracing → core}/transport/http/api/instance.rb +18 -1
  195. data/lib/datadog/core/transport/http/api/spec.rb +36 -0
  196. data/lib/datadog/{tracing → core}/transport/http/builder.rb +53 -31
  197. data/lib/datadog/core/transport/http.rb +75 -0
  198. data/lib/datadog/core/transport/response.rb +4 -0
  199. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +6 -6
  200. data/lib/datadog/core/utils/duration.rb +32 -32
  201. data/lib/datadog/core/utils/forking.rb +2 -2
  202. data/lib/datadog/core/utils/network.rb +6 -6
  203. data/lib/datadog/core/utils/only_once_successful.rb +16 -5
  204. data/lib/datadog/core/utils/time.rb +20 -0
  205. data/lib/datadog/core/utils/truncation.rb +21 -0
  206. data/lib/datadog/core/vendor/multipart-post/multipart/post/composite_read_io.rb +1 -1
  207. data/lib/datadog/core/vendor/multipart-post/multipart/post/multipartable.rb +8 -8
  208. data/lib/datadog/core/vendor/multipart-post/multipart/post/parts.rb +7 -7
  209. data/lib/datadog/core/worker.rb +1 -1
  210. data/lib/datadog/core/workers/async.rb +29 -12
  211. data/lib/datadog/core/workers/interval_loop.rb +12 -1
  212. data/lib/datadog/core/workers/runtime_metrics.rb +2 -2
  213. data/lib/datadog/core.rb +8 -0
  214. data/lib/datadog/di/base.rb +115 -0
  215. data/lib/datadog/di/boot.rb +34 -0
  216. data/lib/datadog/di/code_tracker.rb +26 -15
  217. data/lib/datadog/di/component.rb +23 -14
  218. data/lib/datadog/di/configuration/settings.rb +25 -1
  219. data/lib/datadog/di/contrib/active_record.rb +1 -0
  220. data/lib/datadog/di/contrib/railtie.rb +15 -0
  221. data/lib/datadog/di/contrib.rb +28 -0
  222. data/lib/datadog/di/error.rb +5 -0
  223. data/lib/datadog/di/instrumenter.rb +111 -20
  224. data/lib/datadog/di/logger.rb +30 -0
  225. data/lib/datadog/di/preload.rb +18 -0
  226. data/lib/datadog/di/probe.rb +14 -7
  227. data/lib/datadog/di/probe_builder.rb +1 -0
  228. data/lib/datadog/di/probe_manager.rb +11 -5
  229. data/lib/datadog/di/probe_notification_builder.rb +34 -8
  230. data/lib/datadog/di/probe_notifier_worker.rb +52 -26
  231. data/lib/datadog/di/redactor.rb +0 -1
  232. data/lib/datadog/di/remote.rb +147 -0
  233. data/lib/datadog/di/serializer.rb +14 -7
  234. data/lib/datadog/di/transport/diagnostics.rb +62 -0
  235. data/lib/datadog/di/transport/http/api.rb +42 -0
  236. data/lib/datadog/di/transport/http/client.rb +47 -0
  237. data/lib/datadog/di/transport/http/diagnostics.rb +65 -0
  238. data/lib/datadog/di/transport/http/input.rb +67 -0
  239. data/lib/datadog/di/transport/http.rb +57 -0
  240. data/lib/datadog/di/transport/input.rb +62 -0
  241. data/lib/datadog/di/utils.rb +103 -0
  242. data/lib/datadog/di.rb +14 -76
  243. data/lib/datadog/error_tracking/collector.rb +87 -0
  244. data/lib/datadog/error_tracking/component.rb +167 -0
  245. data/lib/datadog/error_tracking/configuration/settings.rb +63 -0
  246. data/lib/datadog/error_tracking/configuration.rb +11 -0
  247. data/lib/datadog/error_tracking/ext.rb +18 -0
  248. data/lib/datadog/error_tracking/extensions.rb +16 -0
  249. data/lib/datadog/error_tracking/filters.rb +77 -0
  250. data/lib/datadog/error_tracking.rb +18 -0
  251. data/lib/datadog/kit/appsec/events.rb +15 -3
  252. data/lib/datadog/kit/identity.rb +9 -5
  253. data/lib/datadog/opentelemetry/api/baggage.rb +90 -0
  254. data/lib/datadog/opentelemetry/api/baggage.rbs +26 -0
  255. data/lib/datadog/opentelemetry/api/context.rb +16 -2
  256. data/lib/datadog/opentelemetry/sdk/trace/span.rb +1 -1
  257. data/lib/datadog/opentelemetry.rb +2 -1
  258. data/lib/datadog/profiling/collectors/code_provenance.rb +1 -1
  259. data/lib/datadog/profiling/collectors/info.rb +3 -0
  260. data/lib/datadog/profiling/collectors/thread_context.rb +1 -1
  261. data/lib/datadog/profiling/component.rb +60 -76
  262. data/lib/datadog/profiling/encoded_profile.rb +11 -0
  263. data/lib/datadog/profiling/exporter.rb +3 -4
  264. data/lib/datadog/profiling/ext.rb +0 -2
  265. data/lib/datadog/profiling/flush.rb +5 -8
  266. data/lib/datadog/profiling/http_transport.rb +6 -85
  267. data/lib/datadog/profiling/load_native_extension.rb +1 -33
  268. data/lib/datadog/profiling/scheduler.rb +8 -1
  269. data/lib/datadog/profiling/stack_recorder.rb +4 -4
  270. data/lib/datadog/profiling/tag_builder.rb +1 -5
  271. data/lib/datadog/profiling.rb +6 -2
  272. data/lib/datadog/tracing/analytics.rb +1 -1
  273. data/lib/datadog/tracing/component.rb +16 -12
  274. data/lib/datadog/tracing/configuration/ext.rb +8 -1
  275. data/lib/datadog/tracing/configuration/settings.rb +22 -10
  276. data/lib/datadog/tracing/context_provider.rb +1 -1
  277. data/lib/datadog/tracing/contrib/action_cable/integration.rb +5 -2
  278. data/lib/datadog/tracing/contrib/action_mailer/integration.rb +6 -2
  279. data/lib/datadog/tracing/contrib/action_pack/integration.rb +5 -2
  280. data/lib/datadog/tracing/contrib/action_view/integration.rb +5 -2
  281. data/lib/datadog/tracing/contrib/active_job/integration.rb +5 -2
  282. data/lib/datadog/tracing/contrib/active_record/integration.rb +7 -3
  283. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +7 -2
  284. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +36 -1
  285. data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +4 -0
  286. data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +14 -4
  287. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +10 -0
  288. data/lib/datadog/tracing/contrib/active_support/integration.rb +5 -2
  289. data/lib/datadog/tracing/contrib/auto_instrument.rb +2 -2
  290. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +10 -0
  291. data/lib/datadog/tracing/contrib/aws/integration.rb +3 -0
  292. data/lib/datadog/tracing/contrib/aws/parsed_context.rb +5 -1
  293. data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +3 -0
  294. data/lib/datadog/tracing/contrib/configuration/settings.rb +1 -1
  295. data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +4 -0
  296. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +6 -1
  297. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -5
  298. data/lib/datadog/tracing/contrib/excon/middleware.rb +5 -3
  299. data/lib/datadog/tracing/contrib/ext.rb +1 -0
  300. data/lib/datadog/tracing/contrib/extensions.rb +29 -3
  301. data/lib/datadog/tracing/contrib/faraday/middleware.rb +5 -3
  302. data/lib/datadog/tracing/contrib/graphql/configuration/error_extension_env_parser.rb +21 -0
  303. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +11 -0
  304. data/lib/datadog/tracing/contrib/graphql/ext.rb +5 -0
  305. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +102 -11
  306. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +7 -1
  307. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +3 -0
  308. data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +0 -15
  309. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +4 -1
  310. data/lib/datadog/tracing/contrib/http/instrumentation.rb +6 -10
  311. data/lib/datadog/tracing/contrib/http/integration.rb +3 -0
  312. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -16
  313. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +7 -15
  314. data/lib/datadog/tracing/contrib/httprb/integration.rb +3 -0
  315. data/lib/datadog/tracing/contrib/kafka/integration.rb +3 -0
  316. data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +27 -0
  317. data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +48 -0
  318. data/lib/datadog/tracing/contrib/karafka/ext.rb +27 -0
  319. data/lib/datadog/tracing/contrib/karafka/integration.rb +45 -0
  320. data/lib/datadog/tracing/contrib/karafka/monitor.rb +66 -0
  321. data/lib/datadog/tracing/contrib/karafka/patcher.rb +71 -0
  322. data/lib/datadog/tracing/contrib/karafka.rb +37 -0
  323. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +8 -0
  324. data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -0
  325. data/lib/datadog/tracing/contrib/mongodb/integration.rb +3 -0
  326. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +18 -1
  327. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +17 -0
  328. data/lib/datadog/tracing/contrib/opensearch/ext.rb +9 -0
  329. data/lib/datadog/tracing/contrib/opensearch/integration.rb +3 -0
  330. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +5 -1
  331. data/lib/datadog/tracing/contrib/patcher.rb +5 -2
  332. data/lib/datadog/tracing/contrib/presto/integration.rb +3 -0
  333. data/lib/datadog/tracing/contrib/rack/header_collection.rb +11 -1
  334. data/lib/datadog/tracing/contrib/rack/integration.rb +2 -2
  335. data/lib/datadog/tracing/contrib/rack/middlewares.rb +1 -1
  336. data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
  337. data/lib/datadog/tracing/contrib/rails/framework.rb +2 -2
  338. data/lib/datadog/tracing/contrib/rails/patcher.rb +1 -1
  339. data/lib/datadog/tracing/contrib/rest_client/integration.rb +3 -0
  340. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +5 -3
  341. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +6 -1
  342. data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +3 -0
  343. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +1 -1
  344. data/lib/datadog/tracing/contrib/span_attribute_schema.rb +6 -1
  345. data/lib/datadog/tracing/contrib/support.rb +28 -0
  346. data/lib/datadog/tracing/contrib.rb +1 -0
  347. data/lib/datadog/tracing/correlation.rb +9 -2
  348. data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
  349. data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
  350. data/lib/datadog/tracing/distributed/baggage.rb +131 -0
  351. data/lib/datadog/tracing/distributed/datadog.rb +4 -2
  352. data/lib/datadog/tracing/distributed/propagation.rb +25 -4
  353. data/lib/datadog/tracing/distributed/propagation_policy.rb +42 -0
  354. data/lib/datadog/tracing/metadata/errors.rb +4 -4
  355. data/lib/datadog/tracing/metadata/ext.rb +5 -0
  356. data/lib/datadog/tracing/metadata/metastruct.rb +36 -0
  357. data/lib/datadog/tracing/metadata/metastruct_tagging.rb +42 -0
  358. data/lib/datadog/tracing/metadata.rb +2 -0
  359. data/lib/datadog/tracing/sampling/rate_sampler.rb +2 -1
  360. data/lib/datadog/tracing/sampling/span/rule.rb +0 -1
  361. data/lib/datadog/tracing/span.rb +22 -5
  362. data/lib/datadog/tracing/span_event.rb +124 -4
  363. data/lib/datadog/tracing/span_operation.rb +52 -16
  364. data/lib/datadog/tracing/sync_writer.rb +9 -5
  365. data/lib/datadog/tracing/trace_digest.rb +9 -2
  366. data/lib/datadog/tracing/trace_operation.rb +44 -24
  367. data/lib/datadog/tracing/trace_segment.rb +6 -4
  368. data/lib/datadog/tracing/tracer.rb +60 -12
  369. data/lib/datadog/tracing/transport/http/api.rb +5 -4
  370. data/lib/datadog/tracing/transport/http/client.rb +5 -4
  371. data/lib/datadog/tracing/transport/http/traces.rb +13 -44
  372. data/lib/datadog/tracing/transport/http.rb +13 -70
  373. data/lib/datadog/tracing/transport/serializable_trace.rb +31 -7
  374. data/lib/datadog/tracing/transport/trace_formatter.rb +7 -0
  375. data/lib/datadog/tracing/transport/traces.rb +47 -13
  376. data/lib/datadog/tracing/utils.rb +1 -1
  377. data/lib/datadog/tracing/workers/trace_writer.rb +8 -5
  378. data/lib/datadog/tracing/workers.rb +5 -4
  379. data/lib/datadog/tracing/writer.rb +10 -6
  380. data/lib/datadog/tracing.rb +16 -3
  381. data/lib/datadog/version.rb +2 -2
  382. data/lib/datadog.rb +2 -0
  383. metadata +143 -50
  384. data/ext/datadog_profiling_loader/datadog_profiling_loader.c +0 -142
  385. data/ext/datadog_profiling_loader/extconf.rb +0 -60
  386. data/lib/datadog/appsec/contrib/devise/event.rb +0 -57
  387. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +0 -77
  388. data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +0 -54
  389. data/lib/datadog/appsec/contrib/devise/resource.rb +0 -35
  390. data/lib/datadog/appsec/contrib/devise/tracking.rb +0 -57
  391. data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +0 -46
  392. data/lib/datadog/appsec/contrib/patcher.rb +0 -12
  393. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +0 -69
  394. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +0 -47
  395. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +0 -53
  396. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +0 -53
  397. data/lib/datadog/appsec/contrib/sinatra/ext.rb +0 -14
  398. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +0 -48
  399. data/lib/datadog/appsec/monitor/reactive/set_user.rb +0 -45
  400. data/lib/datadog/appsec/processor/actions.rb +0 -49
  401. data/lib/datadog/appsec/processor/context.rb +0 -107
  402. data/lib/datadog/appsec/reactive/address_hash.rb +0 -22
  403. data/lib/datadog/appsec/reactive/engine.rb +0 -47
  404. data/lib/datadog/appsec/reactive/operation.rb +0 -68
  405. data/lib/datadog/appsec/reactive/subscriber.rb +0 -19
  406. data/lib/datadog/appsec/scope.rb +0 -58
  407. data/lib/datadog/appsec/utils/trace_operation.rb +0 -15
  408. data/lib/datadog/core/crashtracking/agent_base_url.rb +0 -21
  409. data/lib/datadog/core/remote/transport/http/api/instance.rb +0 -39
  410. data/lib/datadog/core/remote/transport/http/api/spec.rb +0 -21
  411. data/lib/datadog/core/remote/transport/http/builder.rb +0 -219
  412. data/lib/datadog/core/telemetry/http/env.rb +0 -20
  413. data/lib/datadog/core/telemetry/http/ext.rb +0 -28
  414. data/lib/datadog/core/telemetry/http/response.rb +0 -70
  415. data/lib/datadog/core/telemetry/http/transport.rb +0 -90
  416. data/lib/datadog/di/transport.rb +0 -81
  417. data/lib/datadog/tracing/transport/http/api/spec.rb +0 -19
@@ -4,6 +4,7 @@
4
4
  #include "helpers.h"
5
5
  #include "libdatadog_helpers.h"
6
6
  #include "ruby_helpers.h"
7
+ #include "encoded_profile.h"
7
8
 
8
9
  // Used to report profiling data to Datadog.
9
10
  // This file implements the native bits of the Datadog::Profiling::HttpTransport class
@@ -13,33 +14,23 @@ static VALUE error_symbol = Qnil; // :error in Ruby
13
14
 
14
15
  static VALUE library_version_string = Qnil;
15
16
 
16
- struct call_exporter_without_gvl_arguments {
17
- ddog_prof_Exporter *exporter;
18
- ddog_prof_Exporter_Request_BuildResult *build_result;
17
+ typedef struct {
18
+ ddog_prof_ProfileExporter *exporter;
19
+ ddog_prof_Request_Result *build_result;
19
20
  ddog_CancellationToken *cancel_token;
20
- ddog_prof_Exporter_SendResult result;
21
+ ddog_prof_Result_HttpStatus result;
21
22
  bool send_ran;
22
- };
23
+ } call_exporter_without_gvl_arguments;
23
24
 
24
25
  static inline ddog_ByteSlice byte_slice_from_ruby_string(VALUE string);
25
26
  static VALUE _native_validate_exporter(VALUE self, VALUE exporter_configuration);
26
- static ddog_prof_Exporter_NewResult create_exporter(VALUE exporter_configuration, VALUE tags_as_array);
27
- static VALUE handle_exporter_failure(ddog_prof_Exporter_NewResult exporter_result);
27
+ static ddog_prof_ProfileExporter_Result create_exporter(VALUE exporter_configuration, VALUE tags_as_array);
28
+ static VALUE handle_exporter_failure(ddog_prof_ProfileExporter_Result exporter_result);
28
29
  static VALUE _native_do_export(
29
30
  VALUE self,
30
31
  VALUE exporter_configuration,
31
32
  VALUE upload_timeout_milliseconds,
32
- VALUE start_timespec_seconds,
33
- VALUE start_timespec_nanoseconds,
34
- VALUE finish_timespec_seconds,
35
- VALUE finish_timespec_nanoseconds,
36
- VALUE pprof_file_name,
37
- VALUE pprof_data,
38
- VALUE code_provenance_file_name,
39
- VALUE code_provenance_data,
40
- VALUE tags_as_array,
41
- VALUE internal_metadata_json,
42
- VALUE info_json
33
+ VALUE flush
43
34
  );
44
35
  static void *call_exporter_without_gvl(void *call_args);
45
36
  static void interrupt_exporter_call(void *cancel_token);
@@ -48,7 +39,7 @@ void http_transport_init(VALUE profiling_module) {
48
39
  VALUE http_transport_class = rb_define_class_under(profiling_module, "HttpTransport", rb_cObject);
49
40
 
50
41
  rb_define_singleton_method(http_transport_class, "_native_validate_exporter", _native_validate_exporter, 1);
51
- rb_define_singleton_method(http_transport_class, "_native_do_export", _native_do_export, 13);
42
+ rb_define_singleton_method(http_transport_class, "_native_do_export", _native_do_export, 3);
52
43
 
53
44
  ok_symbol = ID2SYM(rb_intern_const("ok"));
54
45
  error_symbol = ID2SYM(rb_intern_const("error"));
@@ -65,14 +56,14 @@ static inline ddog_ByteSlice byte_slice_from_ruby_string(VALUE string) {
65
56
 
66
57
  static VALUE _native_validate_exporter(DDTRACE_UNUSED VALUE _self, VALUE exporter_configuration) {
67
58
  ENFORCE_TYPE(exporter_configuration, T_ARRAY);
68
- ddog_prof_Exporter_NewResult exporter_result = create_exporter(exporter_configuration, rb_ary_new());
59
+ ddog_prof_ProfileExporter_Result exporter_result = create_exporter(exporter_configuration, rb_ary_new());
69
60
 
70
61
  VALUE failure_tuple = handle_exporter_failure(exporter_result);
71
62
  if (!NIL_P(failure_tuple)) return failure_tuple;
72
63
 
73
64
  // We don't actually need the exporter for now -- we just wanted to validate that we could create it with the
74
65
  // settings we were given
75
- ddog_prof_Exporter_drop(exporter_result.ok);
66
+ ddog_prof_Exporter_drop(&exporter_result.ok);
76
67
 
77
68
  return rb_ary_new_from_args(2, ok_symbol, Qnil);
78
69
  }
@@ -84,26 +75,21 @@ static ddog_prof_Endpoint endpoint_from(VALUE exporter_configuration) {
84
75
  ENFORCE_TYPE(exporter_working_mode, T_SYMBOL);
85
76
  ID working_mode = SYM2ID(exporter_working_mode);
86
77
 
87
- ID agentless_id = rb_intern("agentless");
88
- ID agent_id = rb_intern("agent");
89
-
90
- if (working_mode != agentless_id && working_mode != agent_id) {
91
- rb_raise(rb_eArgError, "Failed to initialize transport: Unexpected working mode, expected :agentless or :agent");
92
- }
93
-
94
- if (working_mode == agentless_id) {
78
+ if (working_mode == rb_intern("agentless")) {
95
79
  VALUE site = rb_ary_entry(exporter_configuration, 1);
96
80
  VALUE api_key = rb_ary_entry(exporter_configuration, 2);
97
81
 
98
82
  return ddog_prof_Endpoint_agentless(char_slice_from_ruby_string(site), char_slice_from_ruby_string(api_key));
99
- } else { // agent_id
83
+ } else if (working_mode == rb_intern("agent")) {
100
84
  VALUE base_url = rb_ary_entry(exporter_configuration, 1);
101
85
 
102
86
  return ddog_prof_Endpoint_agent(char_slice_from_ruby_string(base_url));
87
+ } else {
88
+ rb_raise(rb_eArgError, "Failed to initialize transport: Unexpected working mode, expected :agentless or :agent");
103
89
  }
104
90
  }
105
91
 
106
- static ddog_prof_Exporter_NewResult create_exporter(VALUE exporter_configuration, VALUE tags_as_array) {
92
+ static ddog_prof_ProfileExporter_Result create_exporter(VALUE exporter_configuration, VALUE tags_as_array) {
107
93
  ENFORCE_TYPE(exporter_configuration, T_ARRAY);
108
94
  ENFORCE_TYPE(tags_as_array, T_ARRAY);
109
95
 
@@ -117,7 +103,7 @@ static ddog_prof_Exporter_NewResult create_exporter(VALUE exporter_configuration
117
103
  ddog_CharSlice library_version = char_slice_from_ruby_string(library_version_string);
118
104
  ddog_CharSlice profiling_family = DDOG_CHARSLICE_C("ruby");
119
105
 
120
- ddog_prof_Exporter_NewResult exporter_result =
106
+ ddog_prof_ProfileExporter_Result exporter_result =
121
107
  ddog_prof_Exporter_new(library_name, library_version, profiling_family, &tags, endpoint);
122
108
 
123
109
  ddog_Vec_Tag_drop(tags);
@@ -125,8 +111,12 @@ static ddog_prof_Exporter_NewResult create_exporter(VALUE exporter_configuration
125
111
  return exporter_result;
126
112
  }
127
113
 
128
- static VALUE handle_exporter_failure(ddog_prof_Exporter_NewResult exporter_result) {
129
- return exporter_result.tag == DDOG_PROF_EXPORTER_NEW_RESULT_OK ?
114
+ static void validate_token(ddog_CancellationToken token, const char *file, int line) {
115
+ if (token.inner == NULL) rb_raise(rb_eRuntimeError, "Unexpected: Validation token was empty at %s:%d", file, line);
116
+ }
117
+
118
+ static VALUE handle_exporter_failure(ddog_prof_ProfileExporter_Result exporter_result) {
119
+ return exporter_result.tag == DDOG_PROF_PROFILE_EXPORTER_RESULT_OK_HANDLE_PROFILE_EXPORTER ?
130
120
  Qnil :
131
121
  rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&exporter_result.err));
132
122
  }
@@ -134,39 +124,37 @@ static VALUE handle_exporter_failure(ddog_prof_Exporter_NewResult exporter_resul
134
124
  // Note: This function handles a bunch of libdatadog dynamically-allocated objects, so it MUST not use any Ruby APIs
135
125
  // which can raise exceptions, otherwise the objects will be leaked.
136
126
  static VALUE perform_export(
137
- ddog_prof_Exporter *exporter,
138
- ddog_Timespec start,
139
- ddog_Timespec finish,
127
+ ddog_prof_ProfileExporter *exporter,
128
+ ddog_prof_EncodedProfile *profile,
140
129
  ddog_prof_Exporter_Slice_File files_to_compress_and_export,
141
- ddog_prof_Exporter_Slice_File files_to_export_unmodified,
142
- ddog_Vec_Tag *additional_tags,
143
130
  ddog_CharSlice internal_metadata,
144
131
  ddog_CharSlice info
145
132
  ) {
146
- ddog_prof_ProfiledEndpointsStats *endpoints_stats = NULL; // Not in use yet
147
- ddog_prof_Exporter_Request_BuildResult build_result = ddog_prof_Exporter_Request_build(
133
+ ddog_prof_Request_Result build_result = ddog_prof_Exporter_Request_build(
148
134
  exporter,
149
- start,
150
- finish,
135
+ profile,
151
136
  files_to_compress_and_export,
152
- files_to_export_unmodified,
153
- additional_tags,
154
- endpoints_stats,
137
+ /* files_to_export_unmodified: */ ddog_prof_Exporter_Slice_File_empty(),
138
+ /* optional_additional_tags: */ NULL,
155
139
  &internal_metadata,
156
140
  &info
157
141
  );
158
142
 
159
- if (build_result.tag == DDOG_PROF_EXPORTER_REQUEST_BUILD_RESULT_ERR) {
143
+ if (build_result.tag == DDOG_PROF_REQUEST_RESULT_ERR_HANDLE_REQUEST) {
160
144
  ddog_prof_Exporter_drop(exporter);
161
145
  return rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&build_result.err));
162
146
  }
163
147
 
164
- ddog_CancellationToken *cancel_token = ddog_CancellationToken_new();
148
+ ddog_CancellationToken cancel_token_request = ddog_CancellationToken_new();
149
+ ddog_CancellationToken cancel_token_interrupt = ddog_CancellationToken_clone(&cancel_token_request);
150
+
151
+ validate_token(cancel_token_request, __FILE__, __LINE__);
152
+ validate_token(cancel_token_interrupt, __FILE__, __LINE__);
165
153
 
166
154
  // We'll release the Global VM Lock while we're calling send, so that the Ruby VM can continue to work while this
167
155
  // is pending
168
- struct call_exporter_without_gvl_arguments args =
169
- {.exporter = exporter, .build_result = &build_result, .cancel_token = cancel_token, .send_ran = false};
156
+ call_exporter_without_gvl_arguments args =
157
+ {.exporter = exporter, .build_result = &build_result, .cancel_token = &cancel_token_request, .send_ran = false};
170
158
 
171
159
  // We use rb_thread_call_without_gvl2 instead of rb_thread_call_without_gvl as the gvl2 variant never raises any
172
160
  // exceptions.
@@ -183,14 +171,15 @@ static VALUE perform_export(
183
171
  int pending_exception = 0;
184
172
 
185
173
  while (!args.send_ran && !pending_exception) {
186
- rb_thread_call_without_gvl2(call_exporter_without_gvl, &args, interrupt_exporter_call, cancel_token);
174
+ rb_thread_call_without_gvl2(call_exporter_without_gvl, &args, interrupt_exporter_call, &cancel_token_interrupt);
187
175
 
188
176
  // To make sure we don't leak memory, we never check for pending exceptions if send ran
189
177
  if (!args.send_ran) pending_exception = check_if_pending_exception();
190
178
  }
191
179
 
192
180
  // Cleanup exporter and token, no longer needed
193
- ddog_CancellationToken_drop(cancel_token);
181
+ ddog_CancellationToken_drop(&cancel_token_request);
182
+ ddog_CancellationToken_drop(&cancel_token_interrupt);
194
183
  ddog_prof_Exporter_drop(exporter);
195
184
 
196
185
  if (pending_exception) {
@@ -203,10 +192,10 @@ static VALUE perform_export(
203
192
 
204
193
  // The request itself does not need to be freed as libdatadog takes ownership of it as part of sending.
205
194
 
206
- ddog_prof_Exporter_SendResult result = args.result;
195
+ ddog_prof_Result_HttpStatus result = args.result;
207
196
 
208
- return result.tag == DDOG_PROF_EXPORTER_SEND_RESULT_HTTP_RESPONSE ?
209
- rb_ary_new_from_args(2, ok_symbol, UINT2NUM(result.http_response.code)) :
197
+ return result.tag == DDOG_PROF_RESULT_HTTP_STATUS_OK_HTTP_STATUS ?
198
+ rb_ary_new_from_args(2, ok_symbol, UINT2NUM(result.ok.code)) :
210
199
  rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&result.err));
211
200
  }
212
201
 
@@ -214,26 +203,19 @@ static VALUE _native_do_export(
214
203
  DDTRACE_UNUSED VALUE _self,
215
204
  VALUE exporter_configuration,
216
205
  VALUE upload_timeout_milliseconds,
217
- VALUE start_timespec_seconds,
218
- VALUE start_timespec_nanoseconds,
219
- VALUE finish_timespec_seconds,
220
- VALUE finish_timespec_nanoseconds,
221
- VALUE pprof_file_name,
222
- VALUE pprof_data,
223
- VALUE code_provenance_file_name,
224
- VALUE code_provenance_data,
225
- VALUE tags_as_array,
226
- VALUE internal_metadata_json,
227
- VALUE info_json
206
+ VALUE flush
228
207
  ) {
208
+ VALUE encoded_profile = rb_funcall(flush, rb_intern("encoded_profile"), 0);
209
+ VALUE code_provenance_file_name = rb_funcall(flush, rb_intern("code_provenance_file_name"), 0);
210
+ VALUE code_provenance_data = rb_funcall(flush, rb_intern("code_provenance_data"), 0);
211
+ VALUE tags_as_array = rb_funcall(flush, rb_intern("tags_as_array"), 0);
212
+ VALUE internal_metadata_json = rb_funcall(flush, rb_intern("internal_metadata_json"), 0);
213
+ VALUE info_json = rb_funcall(flush, rb_intern("info_json"), 0);
214
+
229
215
  ENFORCE_TYPE(upload_timeout_milliseconds, T_FIXNUM);
230
- ENFORCE_TYPE(start_timespec_seconds, T_FIXNUM);
231
- ENFORCE_TYPE(start_timespec_nanoseconds, T_FIXNUM);
232
- ENFORCE_TYPE(finish_timespec_seconds, T_FIXNUM);
233
- ENFORCE_TYPE(finish_timespec_nanoseconds, T_FIXNUM);
234
- ENFORCE_TYPE(pprof_file_name, T_STRING);
235
- ENFORCE_TYPE(pprof_data, T_STRING);
216
+ enforce_encoded_profile_instance(encoded_profile);
236
217
  ENFORCE_TYPE(code_provenance_file_name, T_STRING);
218
+ ENFORCE_TYPE(tags_as_array, T_ARRAY);
237
219
  ENFORCE_TYPE(internal_metadata_json, T_STRING);
238
220
  ENFORCE_TYPE(info_json, T_STRING);
239
221
 
@@ -243,23 +225,9 @@ static VALUE _native_do_export(
243
225
 
244
226
  uint64_t timeout_milliseconds = NUM2ULONG(upload_timeout_milliseconds);
245
227
 
246
- ddog_Timespec start =
247
- {.seconds = NUM2LONG(start_timespec_seconds), .nanoseconds = NUM2UINT(start_timespec_nanoseconds)};
248
- ddog_Timespec finish =
249
- {.seconds = NUM2LONG(finish_timespec_seconds), .nanoseconds = NUM2UINT(finish_timespec_nanoseconds)};
250
-
251
228
  int to_compress_length = have_code_provenance ? 1 : 0;
252
229
  ddog_prof_Exporter_File to_compress[to_compress_length];
253
- int already_compressed_length = 1; // pprof
254
- ddog_prof_Exporter_File already_compressed[already_compressed_length];
255
-
256
230
  ddog_prof_Exporter_Slice_File files_to_compress_and_export = {.ptr = to_compress, .len = to_compress_length};
257
- ddog_prof_Exporter_Slice_File files_to_export_unmodified = {.ptr = already_compressed, .len = already_compressed_length};
258
-
259
- already_compressed[0] = (ddog_prof_Exporter_File) {
260
- .name = char_slice_from_ruby_string(pprof_file_name),
261
- .file = byte_slice_from_ruby_string(pprof_data),
262
- };
263
231
 
264
232
  if (have_code_provenance) {
265
233
  to_compress[0] = (ddog_prof_Exporter_File) {
@@ -268,39 +236,35 @@ static VALUE _native_do_export(
268
236
  };
269
237
  }
270
238
 
271
- ddog_Vec_Tag *null_additional_tags = NULL;
272
239
  ddog_CharSlice internal_metadata = char_slice_from_ruby_string(internal_metadata_json);
273
240
  ddog_CharSlice info = char_slice_from_ruby_string(info_json);
274
241
 
275
- ddog_prof_Exporter_NewResult exporter_result = create_exporter(exporter_configuration, tags_as_array);
242
+ ddog_prof_ProfileExporter_Result exporter_result = create_exporter(exporter_configuration, tags_as_array);
276
243
  // Note: Do not add anything that can raise exceptions after this line, as otherwise the exporter memory will leak
277
244
 
278
245
  VALUE failure_tuple = handle_exporter_failure(exporter_result);
279
246
  if (!NIL_P(failure_tuple)) return failure_tuple;
280
247
 
281
- ddog_prof_MaybeError timeout_result = ddog_prof_Exporter_set_timeout(exporter_result.ok, timeout_milliseconds);
282
- if (timeout_result.tag == DDOG_PROF_OPTION_ERROR_SOME_ERROR) {
248
+ ddog_VoidResult timeout_result = ddog_prof_Exporter_set_timeout(&exporter_result.ok, timeout_milliseconds);
249
+ if (timeout_result.tag == DDOG_VOID_RESULT_ERR) {
283
250
  // NOTE: Seems a bit harsh to fail the upload if we can't set a timeout. OTOH, this is only expected to fail
284
251
  // if the exporter is not well built. Because such a situation should already be caught above I think it's
285
252
  // preferable to leave this here as a virtually unreachable exception rather than ignoring it.
286
- ddog_prof_Exporter_drop(exporter_result.ok);
287
- return rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&timeout_result.some));
253
+ ddog_prof_Exporter_drop(&exporter_result.ok);
254
+ return rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&timeout_result.err));
288
255
  }
289
256
 
290
257
  return perform_export(
291
- exporter_result.ok,
292
- start,
293
- finish,
258
+ &exporter_result.ok,
259
+ to_ddog_prof_EncodedProfile(encoded_profile),
294
260
  files_to_compress_and_export,
295
- files_to_export_unmodified,
296
- null_additional_tags,
297
261
  internal_metadata,
298
262
  info
299
263
  );
300
264
  }
301
265
 
302
266
  static void *call_exporter_without_gvl(void *call_args) {
303
- struct call_exporter_without_gvl_arguments *args = (struct call_exporter_without_gvl_arguments*) call_args;
267
+ call_exporter_without_gvl_arguments *args = (call_exporter_without_gvl_arguments*) call_args;
304
268
 
305
269
  args->result = ddog_prof_Exporter_send(args->exporter, &args->build_result->ok, args->cancel_token);
306
270
  args->send_ran = true;
@@ -310,5 +274,7 @@ static void *call_exporter_without_gvl(void *call_args) {
310
274
 
311
275
  // Called by Ruby when it wants to interrupt call_exporter_without_gvl above, e.g. when the app wants to exit cleanly
312
276
  static void interrupt_exporter_call(void *cancel_token) {
277
+ // TODO: False here can mean two things: it was already cancelled OR it failed to cancel.
278
+ // Would be nice to change libdatadog to be able to distinguish between them...
313
279
  ddog_CancellationToken_cancel((ddog_CancellationToken *) cancel_token);
314
280
  }
@@ -40,6 +40,13 @@
40
40
  #endif
41
41
  #endif
42
42
 
43
+ // This file can't include datadog_ruby_common.h so we replicate this here
44
+ #ifdef __GNUC__
45
+ #define DDTRACE_UNUSED __attribute__((unused))
46
+ #else
47
+ #define DDTRACE_UNUSED
48
+ #endif
49
+
43
50
  #define PRIVATE_VM_API_ACCESS_SKIP_RUBY_INCLUDES
44
51
  #include "private_vm_api_access.h"
45
52
 
@@ -158,7 +165,7 @@ bool is_current_thread_holding_the_gvl(void) {
158
165
  //
159
166
  // Thus an incorrect `is_current_thread_holding_the_gvl` result may lead to issues inside `rb_postponed_job_register_one`.
160
167
  //
161
- // For this reason we currently do not enable the new Ruby profiler on Ruby 2.5 by default, and we print a
168
+ // For this reason we default to use the "no signals workaround" on Ruby 2.5 by default, and we print a
162
169
  // warning when customers force-enable it.
163
170
  bool gvl_acquired = vm->gvl.acquired != 0;
164
171
  rb_thread_t *current_owner = vm->running_thread;
@@ -305,6 +312,7 @@ VALUE thread_name_for(VALUE thread) {
305
312
  // to support our custom rb_profile_frames (see below)
306
313
  // Modifications:
307
314
  // * Support int first_lineno for Ruby 3.2.0+ (https://github.com/ruby/ruby/pull/6430)
315
+ // * Validate iseq and pos before calling `rb_iseq_line_no` as a safety measure (see comment below for details)
308
316
  //
309
317
  // `node_id` gets used depending on Ruby VM compilation settings (USE_ISEQ_NODE_ID being defined).
310
318
  // To avoid getting false "unused argument" warnings in setups where it's not used, we need to do this weird dance
@@ -351,6 +359,13 @@ calc_pos(const rb_iseq_t *iseq, const VALUE *pc, int *lineno, int *node_id)
351
359
  __builtin_trap();
352
360
  }
353
361
  #endif
362
+
363
+ // In PROF-11475 we spotted a crash when calling `rb_iseq_line_no` from this method. We couldn't reproduce or
364
+ // figure out the root cause, but "just in case", we're validating that the iseq looks valid and that the
365
+ // `n` used for the position is also sane, and if they don't look good, we don't calculate the line, rather
366
+ // than potentially trigger any issues.
367
+ if (RB_UNLIKELY(!RB_TYPE_P((VALUE) iseq, T_IMEMO) || n < 0 || n > ISEQ_BODY(iseq)->iseq_size)) return 0;
368
+
354
369
  if (lineno) *lineno = rb_iseq_line_no(iseq, pos);
355
370
  #ifdef USE_ISEQ_NODE_ID
356
371
  if (node_id) *node_id = rb_iseq_node_id(iseq, pos);
@@ -800,3 +815,55 @@ static inline int ddtrace_imemo_type(VALUE imemo) {
800
815
  return current_thread;
801
816
  }
802
817
  #endif
818
+
819
+ // Is the VM smack in the middle of raising an exception?
820
+ bool is_raised_flag_set(VALUE thread) { return thread_struct_from_object(thread)->ec->raised_flag > 0; }
821
+
822
+ #ifndef NO_CURRENT_FIBER_FOR
823
+ // The following three declarations are all
824
+ // taken from upstream cont.c at commit d97884a58be32e829fd03a80cd521f4733d65c79 (February 2025, master branch)
825
+ // (See the Ruby project copyright and license above)
826
+ // to enable building `current_fiber_for`.
827
+ //
828
+ // We needed to copy them because they aren't otherwise exposed in any VM APIs or headers.
829
+ // @ivoanjo: I manually checked the Ruby 3.1, 3.2, 3.3 and 3.4 branches + master, and the parts we care about in these
830
+ // structures have not changed in many years (in fact, last change I spotted was for 2.7).
831
+ enum context_type {
832
+ CONTINUATION_CONTEXT = 0,
833
+ FIBER_CONTEXT = 1
834
+ };
835
+
836
+ typedef struct rb_context_struct { // This declaration is incomplete -- only contains up to `self` which is the part we care about
837
+ enum context_type type;
838
+ int argc;
839
+ int kw_splat;
840
+ VALUE self;
841
+ } rb_context_t;
842
+
843
+ struct rb_fiber_struct { // This declaration is incomplete -- only contains the first entry which is the part we care about
844
+ rb_context_t cont;
845
+ };
846
+
847
+ VALUE current_fiber_for(VALUE thread) {
848
+ VALUE self = thread_struct_from_object(thread)->ec->fiber_ptr->cont.self;
849
+ return self == 0 ? Qnil : self;
850
+ }
851
+
852
+ void self_test_current_fiber_for(void) {
853
+ VALUE expected_current_fiber = current_fiber_for(rb_thread_current());
854
+ VALUE actual_current_fiber = rb_fiber_current();
855
+
856
+ if (expected_current_fiber == Qnil) {
857
+ // On purpose above we tried reading before calling `rb_fiber_current()` so the fiber may have not existed yet.
858
+ // But now it should be there.
859
+ expected_current_fiber = current_fiber_for(rb_thread_current());
860
+ }
861
+
862
+ if (expected_current_fiber != actual_current_fiber) rb_raise(rb_eRuntimeError, "current_fiber_for() self-test failed");
863
+ }
864
+ #else
865
+ NORETURN(VALUE current_fiber_for(DDTRACE_UNUSED VALUE thread));
866
+
867
+ VALUE current_fiber_for(DDTRACE_UNUSED VALUE thread) { rb_raise(rb_eRuntimeError, "Not implemented for Ruby < 3.1"); }
868
+ void self_test_current_fiber_for(void) { } // Nothing to do
869
+ #endif
@@ -18,7 +18,7 @@ typedef struct {
18
18
  rb_nativethread_id_t owner;
19
19
  } current_gvl_owner;
20
20
 
21
- typedef struct frame_info {
21
+ typedef struct {
22
22
  union {
23
23
  struct {
24
24
  VALUE iseq;
@@ -44,6 +44,7 @@ bool is_thread_alive(VALUE thread);
44
44
  VALUE thread_name_for(VALUE thread);
45
45
 
46
46
  int ddtrace_rb_profile_frames(VALUE thread, int start, int limit, frame_info *stack_buffer);
47
+
47
48
  // Returns true if the current thread belongs to the main Ractor or if Ruby has no Ractor support
48
49
  bool ddtrace_rb_ractor_main_p(void);
49
50
 
@@ -68,3 +69,11 @@ const char *imemo_kind(VALUE imemo);
68
69
 
69
70
  #define ENFORCE_THREAD(value) \
70
71
  { if (RB_UNLIKELY(!rb_typeddata_is_kind_of(value, RTYPEDDATA_TYPE(rb_thread_current())))) raise_unexpected_type(value, ADD_QUOTES(value), "Thread", __FILE__, __LINE__, __func__); }
72
+
73
+ bool is_raised_flag_set(VALUE thread);
74
+
75
+ // Can be nil if `rb_fiber_current()` or similar has not been called (gets allocated lazily)
76
+ // Only implemented for Ruby 3.1+
77
+ VALUE current_fiber_for(VALUE thread);
78
+
79
+ void self_test_current_fiber_for(void);
@@ -11,6 +11,7 @@
11
11
  #include "ruby_helpers.h"
12
12
  #include "setup_signal_handler.h"
13
13
  #include "time_helpers.h"
14
+ #include "unsafe_api_calls_check.h"
14
15
 
15
16
  // Each class/module here is implemented in their separate file
16
17
  void collectors_cpu_and_wall_time_worker_init(VALUE profiling_module);
@@ -19,6 +20,7 @@ void collectors_dynamic_sampling_rate_init(VALUE profiling_module);
19
20
  void collectors_idle_sampling_helper_init(VALUE profiling_module);
20
21
  void collectors_stack_init(VALUE profiling_module);
21
22
  void collectors_thread_context_init(VALUE profiling_module);
23
+ void encoded_profile_init(VALUE profiling_module);
22
24
  void http_transport_init(VALUE profiling_module);
23
25
  void stack_recorder_init(VALUE profiling_module);
24
26
 
@@ -40,6 +42,12 @@ static VALUE _native_malloc_stats(DDTRACE_UNUSED VALUE _self);
40
42
  static VALUE _native_safe_object_info(DDTRACE_UNUSED VALUE _self, VALUE obj);
41
43
 
42
44
  void DDTRACE_EXPORT Init_datadog_profiling_native_extension(void) {
45
+ // The profiler still has a lot of limitations around being used in Ractors BUT for now we're choosing to take care of those
46
+ // on our side, rather than asking Ruby to block calling our APIs from Ractors.
47
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
48
+ rb_ext_ractor_safe(true);
49
+ #endif
50
+
43
51
  VALUE datadog_module = rb_define_module("Datadog");
44
52
  VALUE profiling_module = rb_define_module_under(datadog_module, "Profiling");
45
53
  VALUE native_extension_module = rb_define_module_under(profiling_module, "NativeExtension");
@@ -54,8 +62,10 @@ void DDTRACE_EXPORT Init_datadog_profiling_native_extension(void) {
54
62
  collectors_idle_sampling_helper_init(profiling_module);
55
63
  collectors_stack_init(profiling_module);
56
64
  collectors_thread_context_init(profiling_module);
65
+ encoded_profile_init(profiling_module);
57
66
  http_transport_init(profiling_module);
58
67
  stack_recorder_init(profiling_module);
68
+ unsafe_api_calls_check_init();
59
69
 
60
70
  // Hosts methods used for testing the native code using RSpec
61
71
  VALUE testing_module = rb_define_module_under(native_extension_module, "Testing");
@@ -78,21 +88,22 @@ void DDTRACE_EXPORT Init_datadog_profiling_native_extension(void) {
78
88
 
79
89
  static VALUE native_working_p(DDTRACE_UNUSED VALUE _self) {
80
90
  self_test_clock_id();
91
+ self_test_current_fiber_for();
81
92
  self_test_mn_enabled();
82
93
 
83
94
  return Qtrue;
84
95
  }
85
96
 
86
- struct trigger_grab_gvl_and_raise_arguments {
97
+ typedef struct {
87
98
  VALUE exception_class;
88
99
  char *test_message;
89
100
  int test_message_arg;
90
- };
101
+ } trigger_grab_gvl_and_raise_arguments;
91
102
 
92
103
  static VALUE _native_grab_gvl_and_raise(DDTRACE_UNUSED VALUE _self, VALUE exception_class, VALUE test_message, VALUE test_message_arg, VALUE release_gvl) {
93
104
  ENFORCE_TYPE(test_message, T_STRING);
94
105
 
95
- struct trigger_grab_gvl_and_raise_arguments args;
106
+ trigger_grab_gvl_and_raise_arguments args;
96
107
 
97
108
  args.exception_class = exception_class;
98
109
  args.test_message = StringValueCStr(test_message);
@@ -108,7 +119,7 @@ static VALUE _native_grab_gvl_and_raise(DDTRACE_UNUSED VALUE _self, VALUE except
108
119
  }
109
120
 
110
121
  static void *trigger_grab_gvl_and_raise(void *trigger_args) {
111
- struct trigger_grab_gvl_and_raise_arguments *args = (struct trigger_grab_gvl_and_raise_arguments *) trigger_args;
122
+ trigger_grab_gvl_and_raise_arguments *args = (trigger_grab_gvl_and_raise_arguments *) trigger_args;
112
123
 
113
124
  if (args->test_message_arg >= 0) {
114
125
  grab_gvl_and_raise(args->exception_class, "%s%d", args->test_message, args->test_message_arg);
@@ -119,16 +130,16 @@ static void *trigger_grab_gvl_and_raise(void *trigger_args) {
119
130
  return NULL;
120
131
  }
121
132
 
122
- struct trigger_grab_gvl_and_raise_syserr_arguments {
133
+ typedef struct {
123
134
  int syserr_errno;
124
135
  char *test_message;
125
136
  int test_message_arg;
126
- };
137
+ } trigger_grab_gvl_and_raise_syserr_arguments;
127
138
 
128
139
  static VALUE _native_grab_gvl_and_raise_syserr(DDTRACE_UNUSED VALUE _self, VALUE syserr_errno, VALUE test_message, VALUE test_message_arg, VALUE release_gvl) {
129
140
  ENFORCE_TYPE(test_message, T_STRING);
130
141
 
131
- struct trigger_grab_gvl_and_raise_syserr_arguments args;
142
+ trigger_grab_gvl_and_raise_syserr_arguments args;
132
143
 
133
144
  args.syserr_errno = NUM2INT(syserr_errno);
134
145
  args.test_message = StringValueCStr(test_message);
@@ -144,7 +155,7 @@ static VALUE _native_grab_gvl_and_raise_syserr(DDTRACE_UNUSED VALUE _self, VALUE
144
155
  }
145
156
 
146
157
  static void *trigger_grab_gvl_and_raise_syserr(void *trigger_args) {
147
- struct trigger_grab_gvl_and_raise_syserr_arguments *args = (struct trigger_grab_gvl_and_raise_syserr_arguments *) trigger_args;
158
+ trigger_grab_gvl_and_raise_syserr_arguments *args = (trigger_grab_gvl_and_raise_syserr_arguments *) trigger_args;
148
159
 
149
160
  if (args->test_message_arg >= 0) {
150
161
  grab_gvl_and_raise_syserr(args->syserr_errno, "%s%d", args->test_message, args->test_message_arg);
@@ -23,18 +23,18 @@ void ruby_helpers_init(void) {
23
23
 
24
24
  #define MAX_RAISE_MESSAGE_SIZE 256
25
25
 
26
- struct raise_arguments {
26
+ typedef struct {
27
27
  VALUE exception_class;
28
28
  char exception_message[MAX_RAISE_MESSAGE_SIZE];
29
- };
29
+ } raise_args;
30
30
 
31
31
  static void *trigger_raise(void *raise_arguments) {
32
- struct raise_arguments *args = (struct raise_arguments *) raise_arguments;
32
+ raise_args *args = (raise_args *) raise_arguments;
33
33
  rb_raise(args->exception_class, "%s", args->exception_message);
34
34
  }
35
35
 
36
36
  void grab_gvl_and_raise(VALUE exception_class, const char *format_string, ...) {
37
- struct raise_arguments args;
37
+ raise_args args;
38
38
 
39
39
  args.exception_class = exception_class;
40
40
 
@@ -55,18 +55,18 @@ void grab_gvl_and_raise(VALUE exception_class, const char *format_string, ...) {
55
55
  rb_bug("[ddtrace] Unexpected: Reached the end of grab_gvl_and_raise while raising '%s'\n", args.exception_message);
56
56
  }
57
57
 
58
- struct syserr_raise_arguments {
58
+ typedef struct {
59
59
  int syserr_errno;
60
60
  char exception_message[MAX_RAISE_MESSAGE_SIZE];
61
- };
61
+ } syserr_raise_args;
62
62
 
63
63
  static void *trigger_syserr_raise(void *syserr_raise_arguments) {
64
- struct syserr_raise_arguments *args = (struct syserr_raise_arguments *) syserr_raise_arguments;
64
+ syserr_raise_args *args = (syserr_raise_args *) syserr_raise_arguments;
65
65
  rb_syserr_fail(args->syserr_errno, args->exception_message);
66
66
  }
67
67
 
68
68
  void grab_gvl_and_raise_syserr(int syserr_errno, const char *format_string, ...) {
69
- struct syserr_raise_arguments args;
69
+ syserr_raise_args args;
70
70
 
71
71
  args.syserr_errno = syserr_errno;
72
72