datadog 2.12.1 → 2.19.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 (346) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +243 -2
  3. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +63 -56
  4. data/ext/datadog_profiling_native_extension/collectors_stack.c +263 -76
  5. data/ext/datadog_profiling_native_extension/collectors_stack.h +20 -3
  6. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +78 -26
  7. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +1 -0
  8. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +1 -4
  9. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +10 -0
  10. data/ext/datadog_profiling_native_extension/encoded_profile.c +79 -0
  11. data/ext/datadog_profiling_native_extension/encoded_profile.h +8 -0
  12. data/ext/datadog_profiling_native_extension/extconf.rb +10 -0
  13. data/ext/datadog_profiling_native_extension/heap_recorder.c +247 -364
  14. data/ext/datadog_profiling_native_extension/heap_recorder.h +4 -6
  15. data/ext/datadog_profiling_native_extension/http_transport.c +60 -94
  16. data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +22 -0
  17. data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +8 -5
  18. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +41 -21
  19. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +6 -4
  20. data/ext/datadog_profiling_native_extension/profiling.c +2 -0
  21. data/ext/datadog_profiling_native_extension/ruby_helpers.c +1 -13
  22. data/ext/datadog_profiling_native_extension/ruby_helpers.h +3 -11
  23. data/ext/datadog_profiling_native_extension/stack_recorder.c +173 -76
  24. data/ext/libdatadog_api/crashtracker.c +11 -12
  25. data/ext/libdatadog_api/crashtracker.h +5 -0
  26. data/ext/libdatadog_api/datadog_ruby_common.c +1 -4
  27. data/ext/libdatadog_api/datadog_ruby_common.h +10 -0
  28. data/ext/libdatadog_api/extconf.rb +2 -2
  29. data/ext/libdatadog_api/init.c +15 -0
  30. data/ext/libdatadog_api/library_config.c +164 -0
  31. data/ext/libdatadog_api/library_config.h +25 -0
  32. data/ext/libdatadog_api/macos_development.md +3 -3
  33. data/ext/libdatadog_api/process_discovery.c +112 -0
  34. data/ext/libdatadog_api/process_discovery.h +5 -0
  35. data/ext/libdatadog_extconf_helpers.rb +2 -2
  36. data/lib/datadog/appsec/actions_handler/serializable_backtrace.rb +89 -0
  37. data/lib/datadog/appsec/actions_handler.rb +24 -2
  38. data/lib/datadog/appsec/anonymizer.rb +16 -0
  39. data/lib/datadog/appsec/api_security/lru_cache.rb +56 -0
  40. data/lib/datadog/appsec/api_security/route_extractor.rb +71 -0
  41. data/lib/datadog/appsec/api_security/sampler.rb +59 -0
  42. data/lib/datadog/appsec/api_security.rb +23 -0
  43. data/lib/datadog/appsec/assets/waf_rules/README.md +50 -5
  44. data/lib/datadog/appsec/assets/waf_rules/recommended.json +257 -85
  45. data/lib/datadog/appsec/assets/waf_rules/strict.json +10 -78
  46. data/lib/datadog/appsec/autoload.rb +1 -1
  47. data/lib/datadog/appsec/component.rb +46 -61
  48. data/lib/datadog/appsec/compressed_json.rb +40 -0
  49. data/lib/datadog/appsec/configuration/settings.rb +153 -30
  50. data/lib/datadog/appsec/context.rb +7 -7
  51. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +10 -12
  52. data/lib/datadog/appsec/contrib/active_record/integration.rb +2 -2
  53. data/lib/datadog/appsec/contrib/active_record/patcher.rb +22 -22
  54. data/lib/datadog/appsec/contrib/auto_instrument.rb +1 -1
  55. data/lib/datadog/appsec/contrib/devise/configuration.rb +7 -31
  56. data/lib/datadog/appsec/contrib/devise/data_extractor.rb +78 -0
  57. data/lib/datadog/appsec/contrib/devise/ext.rb +22 -0
  58. data/lib/datadog/appsec/contrib/devise/integration.rb +1 -2
  59. data/lib/datadog/appsec/contrib/devise/patcher.rb +34 -23
  60. data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +102 -0
  61. data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +69 -0
  62. data/lib/datadog/appsec/contrib/devise/{patcher/rememberable_patch.rb → patches/skip_signin_tracking_patch.rb} +2 -2
  63. data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +106 -0
  64. data/lib/datadog/appsec/contrib/excon/integration.rb +1 -1
  65. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +9 -10
  66. data/lib/datadog/appsec/contrib/faraday/integration.rb +1 -1
  67. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +8 -9
  68. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +8 -9
  69. data/lib/datadog/appsec/contrib/graphql/integration.rb +1 -1
  70. data/lib/datadog/appsec/contrib/rack/ext.rb +34 -0
  71. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +49 -32
  72. data/lib/datadog/appsec/contrib/rack/integration.rb +1 -1
  73. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +42 -30
  74. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +11 -13
  75. data/lib/datadog/appsec/contrib/rails/integration.rb +1 -1
  76. data/lib/datadog/appsec/contrib/rails/patcher.rb +21 -21
  77. data/lib/datadog/appsec/contrib/rest_client/integration.rb +1 -1
  78. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +10 -11
  79. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +17 -23
  80. data/lib/datadog/appsec/contrib/sinatra/integration.rb +1 -1
  81. data/lib/datadog/appsec/event.rb +96 -135
  82. data/lib/datadog/appsec/ext.rb +4 -2
  83. data/lib/datadog/appsec/instrumentation/gateway/argument.rb +7 -2
  84. data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +24 -0
  85. data/lib/datadog/appsec/instrumentation/gateway.rb +17 -22
  86. data/lib/datadog/appsec/metrics/telemetry.rb +1 -1
  87. data/lib/datadog/appsec/monitor/gateway/watcher.rb +49 -14
  88. data/lib/datadog/appsec/processor/rule_loader.rb +30 -33
  89. data/lib/datadog/appsec/remote.rb +31 -59
  90. data/lib/datadog/appsec/response.rb +6 -6
  91. data/lib/datadog/appsec/security_engine/engine.rb +194 -0
  92. data/lib/datadog/appsec/security_engine/runner.rb +13 -14
  93. data/lib/datadog/appsec/security_event.rb +39 -0
  94. data/lib/datadog/appsec/utils.rb +0 -2
  95. data/lib/datadog/appsec.rb +5 -8
  96. data/lib/datadog/core/buffer/random.rb +18 -2
  97. data/lib/datadog/core/configuration/agent_settings.rb +52 -0
  98. data/lib/datadog/core/configuration/agent_settings_resolver.rb +4 -46
  99. data/lib/datadog/core/configuration/agentless_settings_resolver.rb +176 -0
  100. data/lib/datadog/core/configuration/components.rb +48 -31
  101. data/lib/datadog/core/configuration/components_state.rb +23 -0
  102. data/lib/datadog/core/configuration/ext.rb +4 -0
  103. data/lib/datadog/core/configuration/option.rb +81 -45
  104. data/lib/datadog/core/configuration/option_definition.rb +4 -4
  105. data/lib/datadog/core/configuration/options.rb +3 -3
  106. data/lib/datadog/core/configuration/settings.rb +109 -44
  107. data/lib/datadog/core/configuration/stable_config.rb +22 -0
  108. data/lib/datadog/core/configuration.rb +40 -16
  109. data/lib/datadog/core/crashtracking/component.rb +3 -10
  110. data/lib/datadog/core/crashtracking/tag_builder.rb +4 -22
  111. data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
  112. data/lib/datadog/core/encoding.rb +1 -1
  113. data/lib/datadog/core/environment/agent_info.rb +4 -3
  114. data/lib/datadog/core/environment/cgroup.rb +10 -12
  115. data/lib/datadog/core/environment/container.rb +38 -40
  116. data/lib/datadog/core/environment/ext.rb +6 -6
  117. data/lib/datadog/core/environment/git.rb +1 -0
  118. data/lib/datadog/core/environment/identity.rb +3 -3
  119. data/lib/datadog/core/environment/platform.rb +3 -3
  120. data/lib/datadog/core/environment/variable_helpers.rb +1 -1
  121. data/lib/datadog/core/error.rb +11 -9
  122. data/lib/datadog/core/logger.rb +2 -2
  123. data/lib/datadog/core/metrics/client.rb +20 -21
  124. data/lib/datadog/core/metrics/logging.rb +5 -5
  125. data/lib/datadog/core/process_discovery/tracer_memfd.rb +15 -0
  126. data/lib/datadog/core/process_discovery.rb +36 -0
  127. data/lib/datadog/core/rate_limiter.rb +4 -2
  128. data/lib/datadog/core/remote/client.rb +40 -32
  129. data/lib/datadog/core/remote/component.rb +6 -9
  130. data/lib/datadog/core/remote/configuration/digest.rb +7 -7
  131. data/lib/datadog/core/remote/configuration/path.rb +1 -1
  132. data/lib/datadog/core/remote/configuration/repository.rb +14 -1
  133. data/lib/datadog/core/remote/negotiation.rb +9 -9
  134. data/lib/datadog/core/remote/transport/config.rb +4 -3
  135. data/lib/datadog/core/remote/transport/http/client.rb +5 -4
  136. data/lib/datadog/core/remote/transport/http/config.rb +27 -37
  137. data/lib/datadog/core/remote/transport/http/negotiation.rb +7 -33
  138. data/lib/datadog/core/remote/transport/http.rb +22 -57
  139. data/lib/datadog/core/remote/transport/negotiation.rb +4 -3
  140. data/lib/datadog/core/runtime/metrics.rb +12 -5
  141. data/lib/datadog/core/tag_builder.rb +56 -0
  142. data/lib/datadog/core/telemetry/component.rb +81 -52
  143. data/lib/datadog/core/telemetry/emitter.rb +23 -11
  144. data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +66 -0
  145. data/lib/datadog/core/telemetry/event/app_closing.rb +18 -0
  146. data/lib/datadog/core/telemetry/event/app_dependencies_loaded.rb +33 -0
  147. data/lib/datadog/core/telemetry/event/app_heartbeat.rb +18 -0
  148. data/lib/datadog/core/telemetry/event/app_integrations_change.rb +58 -0
  149. data/lib/datadog/core/telemetry/event/app_started.rb +287 -0
  150. data/lib/datadog/core/telemetry/event/base.rb +40 -0
  151. data/lib/datadog/core/telemetry/event/distributions.rb +18 -0
  152. data/lib/datadog/core/telemetry/event/generate_metrics.rb +43 -0
  153. data/lib/datadog/core/telemetry/event/log.rb +76 -0
  154. data/lib/datadog/core/telemetry/event/message_batch.rb +42 -0
  155. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +43 -0
  156. data/lib/datadog/core/telemetry/event.rb +17 -472
  157. data/lib/datadog/core/telemetry/http/adapters/net.rb +12 -97
  158. data/lib/datadog/core/telemetry/logger.rb +5 -4
  159. data/lib/datadog/core/telemetry/logging.rb +11 -5
  160. data/lib/datadog/core/telemetry/metric.rb +8 -8
  161. data/lib/datadog/core/telemetry/request.rb +4 -4
  162. data/lib/datadog/core/telemetry/transport/http/api.rb +43 -0
  163. data/lib/datadog/core/telemetry/transport/http/client.rb +49 -0
  164. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +92 -0
  165. data/lib/datadog/core/telemetry/transport/http.rb +63 -0
  166. data/lib/datadog/core/telemetry/transport/telemetry.rb +51 -0
  167. data/lib/datadog/core/telemetry/worker.rb +90 -24
  168. data/lib/datadog/core/transport/http/adapters/net.rb +17 -2
  169. data/lib/datadog/core/transport/http/adapters/test.rb +2 -1
  170. data/lib/datadog/core/transport/http/api/instance.rb +17 -0
  171. data/lib/datadog/core/transport/http/api/spec.rb +17 -0
  172. data/lib/datadog/core/transport/http/builder.rb +19 -17
  173. data/lib/datadog/core/transport/http/env.rb +8 -0
  174. data/lib/datadog/core/transport/http.rb +39 -2
  175. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +6 -6
  176. data/lib/datadog/core/utils/duration.rb +32 -32
  177. data/lib/datadog/core/utils/forking.rb +2 -2
  178. data/lib/datadog/core/utils/network.rb +6 -6
  179. data/lib/datadog/core/utils/only_once_successful.rb +16 -5
  180. data/lib/datadog/core/utils/time.rb +20 -0
  181. data/lib/datadog/core/utils/truncation.rb +21 -0
  182. data/lib/datadog/core/utils.rb +7 -0
  183. data/lib/datadog/core/vendor/multipart-post/multipart/post/composite_read_io.rb +1 -1
  184. data/lib/datadog/core/vendor/multipart-post/multipart/post/multipartable.rb +8 -8
  185. data/lib/datadog/core/vendor/multipart-post/multipart/post/parts.rb +7 -7
  186. data/lib/datadog/core/worker.rb +1 -1
  187. data/lib/datadog/core/workers/async.rb +29 -12
  188. data/lib/datadog/core/workers/interval_loop.rb +12 -1
  189. data/lib/datadog/core/workers/runtime_metrics.rb +2 -2
  190. data/lib/datadog/core.rb +8 -0
  191. data/lib/datadog/di/boot.rb +34 -0
  192. data/lib/datadog/di/component.rb +0 -2
  193. data/lib/datadog/di/instrumenter.rb +48 -5
  194. data/lib/datadog/di/probe_notification_builder.rb +38 -43
  195. data/lib/datadog/di/probe_notifier_worker.rb +25 -17
  196. data/lib/datadog/di/remote.rb +2 -0
  197. data/lib/datadog/di/serializer.rb +10 -2
  198. data/lib/datadog/di/transport/diagnostics.rb +4 -3
  199. data/lib/datadog/di/transport/http/api.rb +2 -12
  200. data/lib/datadog/di/transport/http/client.rb +4 -3
  201. data/lib/datadog/di/transport/http/diagnostics.rb +7 -34
  202. data/lib/datadog/di/transport/http/input.rb +18 -35
  203. data/lib/datadog/di/transport/http.rb +14 -62
  204. data/lib/datadog/di/transport/input.rb +14 -5
  205. data/lib/datadog/di/utils.rb +5 -0
  206. data/lib/datadog/di.rb +0 -33
  207. data/lib/datadog/error_tracking/collector.rb +87 -0
  208. data/lib/datadog/error_tracking/component.rb +167 -0
  209. data/lib/datadog/error_tracking/configuration/settings.rb +63 -0
  210. data/lib/datadog/error_tracking/configuration.rb +11 -0
  211. data/lib/datadog/error_tracking/ext.rb +18 -0
  212. data/lib/datadog/error_tracking/extensions.rb +16 -0
  213. data/lib/datadog/error_tracking/filters.rb +77 -0
  214. data/lib/datadog/error_tracking.rb +18 -0
  215. data/lib/datadog/kit/appsec/events/v2.rb +195 -0
  216. data/lib/datadog/kit/appsec/events.rb +12 -0
  217. data/lib/datadog/kit/identity.rb +5 -1
  218. data/lib/datadog/opentelemetry/api/baggage.rb +90 -0
  219. data/lib/datadog/opentelemetry/api/baggage.rbs +26 -0
  220. data/lib/datadog/opentelemetry/api/context.rb +16 -2
  221. data/lib/datadog/opentelemetry/sdk/trace/span.rb +1 -1
  222. data/lib/datadog/opentelemetry.rb +2 -1
  223. data/lib/datadog/profiling/collectors/code_provenance.rb +18 -9
  224. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +6 -0
  225. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -0
  226. data/lib/datadog/profiling/collectors/info.rb +44 -0
  227. data/lib/datadog/profiling/collectors/thread_context.rb +17 -2
  228. data/lib/datadog/profiling/component.rb +8 -9
  229. data/lib/datadog/profiling/encoded_profile.rb +11 -0
  230. data/lib/datadog/profiling/exporter.rb +12 -7
  231. data/lib/datadog/profiling/ext.rb +0 -14
  232. data/lib/datadog/profiling/flush.rb +5 -8
  233. data/lib/datadog/profiling/http_transport.rb +7 -61
  234. data/lib/datadog/profiling/profiler.rb +2 -0
  235. data/lib/datadog/profiling/scheduler.rb +10 -2
  236. data/lib/datadog/profiling/sequence_tracker.rb +44 -0
  237. data/lib/datadog/profiling/stack_recorder.rb +9 -9
  238. data/lib/datadog/profiling/tag_builder.rb +7 -41
  239. data/lib/datadog/profiling/tasks/setup.rb +2 -0
  240. data/lib/datadog/profiling.rb +7 -2
  241. data/lib/datadog/single_step_instrument.rb +9 -0
  242. data/lib/datadog/tracing/analytics.rb +1 -1
  243. data/lib/datadog/tracing/component.rb +15 -12
  244. data/lib/datadog/tracing/configuration/ext.rb +7 -1
  245. data/lib/datadog/tracing/configuration/settings.rb +18 -2
  246. data/lib/datadog/tracing/context_provider.rb +1 -1
  247. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +15 -0
  248. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +19 -12
  249. data/lib/datadog/tracing/contrib/action_pack/ext.rb +2 -0
  250. data/lib/datadog/tracing/contrib/active_record/integration.rb +1 -1
  251. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +11 -2
  252. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +33 -0
  253. data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +4 -0
  254. data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +2 -4
  255. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +13 -0
  256. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +10 -0
  257. data/lib/datadog/tracing/contrib/aws/parsed_context.rb +5 -1
  258. data/lib/datadog/tracing/contrib/configuration/settings.rb +1 -1
  259. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -5
  260. data/lib/datadog/tracing/contrib/excon/middleware.rb +5 -3
  261. data/lib/datadog/tracing/contrib/ext.rb +1 -0
  262. data/lib/datadog/tracing/contrib/faraday/middleware.rb +5 -3
  263. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +7 -1
  264. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +3 -0
  265. data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +0 -15
  266. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +4 -1
  267. data/lib/datadog/tracing/contrib/http/instrumentation.rb +6 -10
  268. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -16
  269. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +7 -15
  270. data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +27 -0
  271. data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +48 -0
  272. data/lib/datadog/tracing/contrib/karafka/ext.rb +27 -0
  273. data/lib/datadog/tracing/contrib/karafka/integration.rb +45 -0
  274. data/lib/datadog/tracing/contrib/karafka/monitor.rb +66 -0
  275. data/lib/datadog/tracing/contrib/karafka/patcher.rb +71 -0
  276. data/lib/datadog/tracing/contrib/karafka.rb +37 -0
  277. data/lib/datadog/tracing/contrib/lograge/patcher.rb +4 -2
  278. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +8 -0
  279. data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -0
  280. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +18 -1
  281. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +16 -6
  282. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +17 -0
  283. data/lib/datadog/tracing/contrib/opensearch/ext.rb +9 -0
  284. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +5 -1
  285. data/lib/datadog/tracing/contrib/patcher.rb +5 -2
  286. data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
  287. data/lib/datadog/tracing/contrib/rails/patcher.rb +4 -1
  288. data/lib/datadog/tracing/contrib/rails/runner.rb +61 -40
  289. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +5 -3
  290. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +6 -1
  291. data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +3 -0
  292. data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
  293. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +5 -2
  294. data/lib/datadog/tracing/contrib/support.rb +28 -0
  295. data/lib/datadog/tracing/contrib.rb +1 -0
  296. data/lib/datadog/tracing/correlation.rb +9 -2
  297. data/lib/datadog/tracing/diagnostics/environment_logger.rb +3 -1
  298. data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
  299. data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
  300. data/lib/datadog/tracing/distributed/baggage.rb +131 -0
  301. data/lib/datadog/tracing/distributed/datadog.rb +4 -2
  302. data/lib/datadog/tracing/distributed/propagation.rb +25 -4
  303. data/lib/datadog/tracing/distributed/propagation_policy.rb +42 -0
  304. data/lib/datadog/tracing/metadata/errors.rb +4 -4
  305. data/lib/datadog/tracing/metadata/ext.rb +5 -0
  306. data/lib/datadog/tracing/metadata/metastruct.rb +36 -0
  307. data/lib/datadog/tracing/metadata/metastruct_tagging.rb +42 -0
  308. data/lib/datadog/tracing/metadata.rb +2 -0
  309. data/lib/datadog/tracing/sampling/rate_sampler.rb +2 -1
  310. data/lib/datadog/tracing/sampling/span/rule.rb +0 -1
  311. data/lib/datadog/tracing/span.rb +10 -1
  312. data/lib/datadog/tracing/span_event.rb +2 -2
  313. data/lib/datadog/tracing/span_operation.rb +68 -16
  314. data/lib/datadog/tracing/sync_writer.rb +2 -3
  315. data/lib/datadog/tracing/trace_digest.rb +9 -2
  316. data/lib/datadog/tracing/trace_operation.rb +55 -27
  317. data/lib/datadog/tracing/trace_segment.rb +6 -4
  318. data/lib/datadog/tracing/tracer.rb +51 -7
  319. data/lib/datadog/tracing/transport/http/api.rb +2 -10
  320. data/lib/datadog/tracing/transport/http/client.rb +5 -4
  321. data/lib/datadog/tracing/transport/http/traces.rb +13 -41
  322. data/lib/datadog/tracing/transport/http.rb +11 -44
  323. data/lib/datadog/tracing/transport/serializable_trace.rb +3 -1
  324. data/lib/datadog/tracing/transport/trace_formatter.rb +7 -0
  325. data/lib/datadog/tracing/transport/traces.rb +26 -9
  326. data/lib/datadog/tracing/utils.rb +1 -1
  327. data/lib/datadog/tracing/workers/trace_writer.rb +2 -6
  328. data/lib/datadog/tracing/writer.rb +2 -6
  329. data/lib/datadog/tracing.rb +16 -3
  330. data/lib/datadog/version.rb +2 -2
  331. data/lib/datadog.rb +8 -2
  332. metadata +88 -23
  333. data/lib/datadog/appsec/assets/waf_rules/processors.json +0 -92
  334. data/lib/datadog/appsec/assets/waf_rules/scanners.json +0 -114
  335. data/lib/datadog/appsec/contrib/devise/event.rb +0 -54
  336. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +0 -72
  337. data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +0 -47
  338. data/lib/datadog/appsec/contrib/devise/resource.rb +0 -35
  339. data/lib/datadog/appsec/contrib/devise/tracking.rb +0 -57
  340. data/lib/datadog/appsec/processor/rule_merger.rb +0 -170
  341. data/lib/datadog/appsec/processor.rb +0 -107
  342. data/lib/datadog/appsec/utils/trace_operation.rb +0 -15
  343. data/lib/datadog/core/telemetry/http/env.rb +0 -20
  344. data/lib/datadog/core/telemetry/http/ext.rb +0 -28
  345. data/lib/datadog/core/telemetry/http/response.rb +0 -70
  346. data/lib/datadog/core/telemetry/http/transport.rb +0 -90
@@ -11,6 +11,7 @@
11
11
  #include "stack_recorder.h"
12
12
  #include "time_helpers.h"
13
13
  #include "unsafe_api_calls_check.h"
14
+ #include "extconf.h"
14
15
 
15
16
  // Used to trigger sampling of threads, based on external "events", such as:
16
17
  // * periodic timer for cpu-time and wall-time
@@ -124,6 +125,7 @@ typedef struct {
124
125
  ddog_prof_Location *locations;
125
126
  uint16_t max_frames;
126
127
  // Hashmap <Thread Object, per_thread_context>
128
+ // Note: Be very careful when mutating this map, as it gets read e.g. in the middle of GC and signal handlers.
127
129
  st_table *hash_map_per_thread_context;
128
130
  // Datadog::Profiling::StackRecorder instance
129
131
  VALUE recorder_instance;
@@ -153,6 +155,10 @@ typedef struct {
153
155
  // Qtrue serves as a marker we've not yet extracted it; when we try to extract it, we set it to an object if
154
156
  // successful and Qnil if not.
155
157
  VALUE otel_current_span_key;
158
+ // Used to enable native filenames in stack traces
159
+ bool native_filenames_enabled;
160
+ // Used to cache native filename lookup results (Map[void *function_pointer, char *filename])
161
+ st_table *native_filenames_cache;
156
162
 
157
163
  struct stats {
158
164
  // Track how many garbage collection samples we've taken.
@@ -172,7 +178,7 @@ typedef struct {
172
178
 
173
179
  // Tracks per-thread state
174
180
  typedef struct {
175
- sampling_buffer *sampling_buffer;
181
+ sampling_buffer sampling_buffer;
176
182
  char thread_id[THREAD_ID_LIMIT_CHARS];
177
183
  ddog_CharSlice thread_id_char_slice;
178
184
  char thread_invoke_location[THREAD_INVOKE_LOCATION_LIMIT_CHARS];
@@ -205,14 +211,14 @@ typedef struct {
205
211
 
206
212
  static void thread_context_collector_typed_data_mark(void *state_ptr);
207
213
  static void thread_context_collector_typed_data_free(void *state_ptr);
208
- static int hash_map_per_thread_context_mark(st_data_t key_thread, st_data_t _value, st_data_t _argument);
214
+ static int hash_map_per_thread_context_mark(st_data_t key_thread, st_data_t value_thread_context, DDTRACE_UNUSED st_data_t _argument);
209
215
  static int hash_map_per_thread_context_free_values(st_data_t _thread, st_data_t value_per_thread_context, st_data_t _argument);
210
216
  static VALUE _native_new(VALUE klass);
211
217
  static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self);
212
218
  static VALUE _native_sample(VALUE self, VALUE collector_instance, VALUE profiler_overhead_stack_thread, VALUE allow_exception);
213
219
  static VALUE _native_on_gc_start(VALUE self, VALUE collector_instance);
214
220
  static VALUE _native_on_gc_finish(VALUE self, VALUE collector_instance);
215
- static VALUE _native_sample_after_gc(DDTRACE_UNUSED VALUE self, VALUE collector_instance, VALUE reset_monotonic_to_system_state, VALUE allow_exception);
221
+ static VALUE _native_sample_after_gc(DDTRACE_UNUSED VALUE self, VALUE collector_instance, VALUE allow_exception);
216
222
  static void update_metrics_and_sample(
217
223
  thread_context_collector_state *state,
218
224
  VALUE thread_being_sampled,
@@ -297,6 +303,8 @@ static void otel_without_ddtrace_trace_identifiers_for(
297
303
  static otel_span otel_span_from(VALUE otel_context, VALUE otel_current_span_key);
298
304
  static uint64_t otel_span_id_to_uint(VALUE otel_span_id);
299
305
  static VALUE safely_lookup_hash_without_going_into_ruby_code(VALUE hash, VALUE key);
306
+ static VALUE _native_system_epoch_time_now_ns(DDTRACE_UNUSED VALUE self, VALUE collector_instance);
307
+ static VALUE _native_prepare_sample_inside_signal_handler(DDTRACE_UNUSED VALUE self, VALUE collector_instance);
300
308
 
301
309
  void collectors_thread_context_init(VALUE profiling_module) {
302
310
  VALUE collectors_module = rb_define_module_under(profiling_module, "Collectors");
@@ -321,13 +329,15 @@ void collectors_thread_context_init(VALUE profiling_module) {
321
329
  rb_define_singleton_method(testing_module, "_native_sample_allocation", _native_sample_allocation, 3);
322
330
  rb_define_singleton_method(testing_module, "_native_on_gc_start", _native_on_gc_start, 1);
323
331
  rb_define_singleton_method(testing_module, "_native_on_gc_finish", _native_on_gc_finish, 1);
324
- rb_define_singleton_method(testing_module, "_native_sample_after_gc", _native_sample_after_gc, 3);
332
+ rb_define_singleton_method(testing_module, "_native_sample_after_gc", _native_sample_after_gc, 2);
325
333
  rb_define_singleton_method(testing_module, "_native_thread_list", _native_thread_list, 0);
326
334
  rb_define_singleton_method(testing_module, "_native_per_thread_context", _native_per_thread_context, 1);
327
335
  rb_define_singleton_method(testing_module, "_native_stats", _native_stats, 1);
328
336
  rb_define_singleton_method(testing_module, "_native_gc_tracking", _native_gc_tracking, 1);
329
337
  rb_define_singleton_method(testing_module, "_native_new_empty_thread", _native_new_empty_thread, 0);
330
338
  rb_define_singleton_method(testing_module, "_native_sample_skipped_allocation_samples", _native_sample_skipped_allocation_samples, 2);
339
+ rb_define_singleton_method(testing_module, "_native_system_epoch_time_now_ns", _native_system_epoch_time_now_ns, 1);
340
+ rb_define_singleton_method(testing_module, "_native_prepare_sample_inside_signal_handler", _native_prepare_sample_inside_signal_handler, 1);
331
341
  #ifndef NO_GVL_INSTRUMENTATION
332
342
  rb_define_singleton_method(testing_module, "_native_on_gvl_waiting", _native_on_gvl_waiting, 1);
333
343
  rb_define_singleton_method(testing_module, "_native_gvl_waiting_at_for", _native_gvl_waiting_at_for, 1);
@@ -403,13 +413,21 @@ static void thread_context_collector_typed_data_free(void *state_ptr) {
403
413
  // ...and then the map
404
414
  st_free_table(state->hash_map_per_thread_context);
405
415
 
416
+ st_free_table(state->native_filenames_cache);
417
+
406
418
  ruby_xfree(state);
407
419
  }
408
420
 
409
421
  // Mark Ruby thread references we keep as keys in hash_map_per_thread_context
410
- static int hash_map_per_thread_context_mark(st_data_t key_thread, DDTRACE_UNUSED st_data_t _value, DDTRACE_UNUSED st_data_t _argument) {
422
+ static int hash_map_per_thread_context_mark(st_data_t key_thread, st_data_t value_thread_context, DDTRACE_UNUSED st_data_t _argument) {
411
423
  VALUE thread = (VALUE) key_thread;
424
+ per_thread_context *thread_context = (per_thread_context *) value_thread_context;
425
+
412
426
  rb_gc_mark(thread);
427
+ if (sampling_buffer_needs_marking(&thread_context->sampling_buffer)) {
428
+ sampling_buffer_mark(&thread_context->sampling_buffer);
429
+ }
430
+
413
431
  return ST_CONTINUE;
414
432
  }
415
433
 
@@ -438,6 +456,8 @@ static VALUE _native_new(VALUE klass) {
438
456
  state->thread_list_buffer = thread_list_buffer;
439
457
  state->endpoint_collection_enabled = true;
440
458
  state->timeline_enabled = true;
459
+ state->native_filenames_enabled = false;
460
+ state->native_filenames_cache = st_init_numtable();
441
461
  state->otel_context_enabled = OTEL_CONTEXT_ENABLED_FALSE;
442
462
  state->otel_context_source = OTEL_CONTEXT_SOURCE_UNKNOWN;
443
463
  state->time_converter_state = (monotonic_to_system_epoch_state) MONOTONIC_TO_SYSTEM_EPOCH_INITIALIZER;
@@ -472,11 +492,13 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
472
492
  VALUE timeline_enabled = rb_hash_fetch(options, ID2SYM(rb_intern("timeline_enabled")));
473
493
  VALUE waiting_for_gvl_threshold_ns = rb_hash_fetch(options, ID2SYM(rb_intern("waiting_for_gvl_threshold_ns")));
474
494
  VALUE otel_context_enabled = rb_hash_fetch(options, ID2SYM(rb_intern("otel_context_enabled")));
495
+ VALUE native_filenames_enabled = rb_hash_fetch(options, ID2SYM(rb_intern("native_filenames_enabled")));
475
496
 
476
497
  ENFORCE_TYPE(max_frames, T_FIXNUM);
477
498
  ENFORCE_BOOLEAN(endpoint_collection_enabled);
478
499
  ENFORCE_BOOLEAN(timeline_enabled);
479
500
  ENFORCE_TYPE(waiting_for_gvl_threshold_ns, T_FIXNUM);
501
+ ENFORCE_BOOLEAN(native_filenames_enabled);
480
502
 
481
503
  thread_context_collector_state *state;
482
504
  TypedData_Get_Struct(self_instance, thread_context_collector_state, &thread_context_collector_typed_data, state);
@@ -488,6 +510,7 @@ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _sel
488
510
  state->recorder_instance = enforce_recorder_instance(recorder_instance);
489
511
  state->endpoint_collection_enabled = (endpoint_collection_enabled == Qtrue);
490
512
  state->timeline_enabled = (timeline_enabled == Qtrue);
513
+ state->native_filenames_enabled = (native_filenames_enabled == Qtrue);
491
514
  if (otel_context_enabled == Qfalse || otel_context_enabled == Qnil) {
492
515
  state->otel_context_enabled = OTEL_CONTEXT_ENABLED_FALSE;
493
516
  } else if (otel_context_enabled == ID2SYM(rb_intern("only"))) {
@@ -551,19 +574,9 @@ static VALUE _native_on_gc_finish(DDTRACE_UNUSED VALUE self, VALUE collector_ins
551
574
  return Qtrue;
552
575
  }
553
576
 
554
- // This method exists only to enable testing Datadog::Profiling::Collectors::ThreadContext behavior using RSpec.
555
- // It SHOULD NOT be used for other purposes.
556
- static VALUE _native_sample_after_gc(DDTRACE_UNUSED VALUE self, VALUE collector_instance, VALUE reset_monotonic_to_system_state, VALUE allow_exception) {
557
- ENFORCE_BOOLEAN(reset_monotonic_to_system_state);
577
+ static VALUE _native_sample_after_gc(DDTRACE_UNUSED VALUE self, VALUE collector_instance, VALUE allow_exception) {
558
578
  ENFORCE_BOOLEAN(allow_exception);
559
579
 
560
- thread_context_collector_state *state;
561
- TypedData_Get_Struct(collector_instance, thread_context_collector_state, &thread_context_collector_typed_data, state);
562
-
563
- if (reset_monotonic_to_system_state == Qtrue) {
564
- state->time_converter_state = (monotonic_to_system_epoch_state) MONOTONIC_TO_SYSTEM_EPOCH_INITIALIZER;
565
- }
566
-
567
580
  if (allow_exception == Qfalse) debug_enter_unsafe_context();
568
581
 
569
582
  thread_context_collector_sample_after_gc(collector_instance);
@@ -607,7 +620,7 @@ void thread_context_collector_sample(VALUE self_instance, long current_monotonic
607
620
  /* thread_being_sampled: */ thread,
608
621
  /* stack_from_thread: */ thread,
609
622
  thread_context,
610
- thread_context->sampling_buffer,
623
+ &thread_context->sampling_buffer,
611
624
  current_cpu_time_ns,
612
625
  current_monotonic_wall_time_ns
613
626
  );
@@ -625,7 +638,7 @@ void thread_context_collector_sample(VALUE self_instance, long current_monotonic
625
638
  /* stack_from_thread: */ profiler_overhead_stack_thread,
626
639
  current_thread_context,
627
640
  // Here we use the overhead thread's sampling buffer so as to not invalidate the cache in the buffer of the thread being sampled
628
- get_or_create_context_for(profiler_overhead_stack_thread, state)->sampling_buffer,
641
+ &get_or_create_context_for(profiler_overhead_stack_thread, state)->sampling_buffer,
629
642
  cpu_time_now_ns(current_thread_context),
630
643
  monotonic_wall_time_now_ns(RAISE_ON_FAILURE)
631
644
  );
@@ -1006,7 +1019,9 @@ static void trigger_sample_for_thread(
1006
1019
  .state_label = state_label,
1007
1020
  .end_timestamp_ns = end_timestamp_ns,
1008
1021
  .is_gvl_waiting_state = is_gvl_waiting_state,
1009
- }
1022
+ },
1023
+ state->native_filenames_enabled,
1024
+ state->native_filenames_cache
1010
1025
  );
1011
1026
  }
1012
1027
 
@@ -1031,7 +1046,7 @@ static per_thread_context *get_or_create_context_for(VALUE thread, thread_contex
1031
1046
  if (st_lookup(state->hash_map_per_thread_context, (st_data_t) thread, &value_context)) {
1032
1047
  thread_context = (per_thread_context*) value_context;
1033
1048
  } else {
1034
- thread_context = ruby_xcalloc(1, sizeof(per_thread_context));
1049
+ thread_context = calloc(1, sizeof(per_thread_context)); // See "note on calloc vs ruby_xcalloc use" in heap_recorder.c
1035
1050
  initialize_context(thread, thread_context, state);
1036
1051
  st_insert(state->hash_map_per_thread_context, (st_data_t) thread, (st_data_t) thread_context);
1037
1052
  }
@@ -1072,7 +1087,7 @@ static bool is_logging_gem_monkey_patch(VALUE invoke_file_location) {
1072
1087
  }
1073
1088
 
1074
1089
  static void initialize_context(VALUE thread, per_thread_context *thread_context, thread_context_collector_state *state) {
1075
- thread_context->sampling_buffer = sampling_buffer_new(state->max_frames, state->locations);
1090
+ sampling_buffer_initialize(&thread_context->sampling_buffer, state->max_frames, state->locations);
1076
1091
 
1077
1092
  snprintf(thread_context->thread_id, THREAD_ID_LIMIT_CHARS, "%"PRIu64" (%lu)", native_thread_id_for(thread), (unsigned long) thread_id_for(thread));
1078
1093
  thread_context->thread_id_char_slice = (ddog_CharSlice) {.ptr = thread_context->thread_id, .len = strlen(thread_context->thread_id)};
@@ -1129,8 +1144,8 @@ static void initialize_context(VALUE thread, per_thread_context *thread_context,
1129
1144
  }
1130
1145
 
1131
1146
  static void free_context(per_thread_context* thread_context) {
1132
- sampling_buffer_free(thread_context->sampling_buffer);
1133
- ruby_xfree(thread_context);
1147
+ sampling_buffer_free(&thread_context->sampling_buffer);
1148
+ free(thread_context); // See "note on calloc vs ruby_xcalloc use" in heap_recorder.c
1134
1149
  }
1135
1150
 
1136
1151
  static VALUE _native_inspect(DDTRACE_UNUSED VALUE _self, VALUE collector_instance) {
@@ -1149,6 +1164,9 @@ static VALUE _native_inspect(DDTRACE_UNUSED VALUE _self, VALUE collector_instanc
1149
1164
  rb_str_concat(result, rb_sprintf(" stats=%"PRIsVALUE, stats_as_ruby_hash(state)));
1150
1165
  rb_str_concat(result, rb_sprintf(" endpoint_collection_enabled=%"PRIsVALUE, state->endpoint_collection_enabled ? Qtrue : Qfalse));
1151
1166
  rb_str_concat(result, rb_sprintf(" timeline_enabled=%"PRIsVALUE, state->timeline_enabled ? Qtrue : Qfalse));
1167
+ rb_str_concat(result, rb_sprintf(" native_filenames_enabled=%"PRIsVALUE, state->native_filenames_enabled ? Qtrue : Qfalse));
1168
+ // Note: `st_table_size()` is available from Ruby 3.2+ but not before
1169
+ rb_str_concat(result, rb_sprintf(" native_filenames_cache_size=%zu", state->native_filenames_cache->num_entries));
1152
1170
  rb_str_concat(result, rb_sprintf(" otel_context_enabled=%d", state->otel_context_enabled));
1153
1171
  rb_str_concat(result, rb_sprintf(
1154
1172
  " time_converter_state={.system_epoch_ns_reference=%ld, .delta_to_epoch_ns=%ld}",
@@ -1316,7 +1334,7 @@ static long thread_id_for(VALUE thread) {
1316
1334
  }
1317
1335
 
1318
1336
  VALUE enforce_thread_context_collector_instance(VALUE object) {
1319
- Check_TypedStruct(object, &thread_context_collector_typed_data);
1337
+ ENFORCE_TYPED_DATA(object, &thread_context_collector_typed_data);
1320
1338
  return object;
1321
1339
  }
1322
1340
 
@@ -1444,6 +1462,26 @@ static VALUE thread_list(thread_context_collector_state *state) {
1444
1462
  return result;
1445
1463
  }
1446
1464
 
1465
+ // Inside a signal handler, we don't want to do the whole work of recording a sample, but we only record the stack of
1466
+ // the current thread.
1467
+ //
1468
+ // Assumptions for this function are same as for `thread_context_collector_sample` except that this function is
1469
+ // expected to be called from a signal handler and to be async-signal-safe.
1470
+ //
1471
+ // Also, no allocation (Ruby or malloc) can happen.
1472
+ bool thread_context_collector_prepare_sample_inside_signal_handler(VALUE self_instance) {
1473
+ thread_context_collector_state *state;
1474
+ if (!rb_typeddata_is_kind_of(self_instance, &thread_context_collector_typed_data)) return false;
1475
+ // This should never fail if the above check passes
1476
+ TypedData_Get_Struct(self_instance, thread_context_collector_state, &thread_context_collector_typed_data, state);
1477
+
1478
+ VALUE current_thread = rb_thread_current();
1479
+ per_thread_context *thread_context = get_context_for(current_thread, state);
1480
+ if (thread_context == NULL) return false;
1481
+
1482
+ return prepare_sample_thread(current_thread, &thread_context->sampling_buffer);
1483
+ }
1484
+
1447
1485
  void thread_context_collector_sample_allocation(VALUE self_instance, unsigned int sample_weight, VALUE new_object) {
1448
1486
  thread_context_collector_state *state;
1449
1487
  TypedData_Get_Struct(self_instance, thread_context_collector_state, &thread_context_collector_typed_data, state);
@@ -1523,7 +1561,7 @@ void thread_context_collector_sample_allocation(VALUE self_instance, unsigned in
1523
1561
  /* thread: */ current_thread,
1524
1562
  /* stack_from_thread: */ current_thread,
1525
1563
  thread_context,
1526
- thread_context->sampling_buffer,
1564
+ &thread_context->sampling_buffer,
1527
1565
  (sample_values) {.alloc_samples = sample_weight, .alloc_samples_unscaled = 1, .heap_sample = true},
1528
1566
  INVALID_TIME, // For now we're not collecting timestamps for allocation events, as per profiling team internal discussions
1529
1567
  &ruby_vm_type,
@@ -1949,7 +1987,7 @@ static uint64_t otel_span_id_to_uint(VALUE otel_span_id) {
1949
1987
  /* thread_being_sampled: */ current_thread,
1950
1988
  /* stack_from_thread: */ current_thread,
1951
1989
  thread_context,
1952
- thread_context->sampling_buffer,
1990
+ &thread_context->sampling_buffer,
1953
1991
  cpu_time_for_thread,
1954
1992
  current_monotonic_wall_time_ns
1955
1993
  );
@@ -2167,3 +2205,17 @@ static VALUE safely_lookup_hash_without_going_into_ruby_code(VALUE hash, VALUE k
2167
2205
 
2168
2206
  return state.result;
2169
2207
  }
2208
+
2209
+ static VALUE _native_system_epoch_time_now_ns(DDTRACE_UNUSED VALUE self, VALUE collector_instance) {
2210
+ thread_context_collector_state *state;
2211
+ TypedData_Get_Struct(collector_instance, thread_context_collector_state, &thread_context_collector_typed_data, state);
2212
+
2213
+ long current_monotonic_wall_time_ns = monotonic_wall_time_now_ns(RAISE_ON_FAILURE);
2214
+ long system_epoch_time_ns = monotonic_to_system_epoch_ns(&state->time_converter_state, current_monotonic_wall_time_ns);
2215
+
2216
+ return LONG2NUM(system_epoch_time_ns);
2217
+ }
2218
+
2219
+ static VALUE _native_prepare_sample_inside_signal_handler(DDTRACE_UNUSED VALUE self, VALUE collector_instance) {
2220
+ return thread_context_collector_prepare_sample_inside_signal_handler(collector_instance) ? Qtrue : Qfalse;
2221
+ }
@@ -10,6 +10,7 @@ void thread_context_collector_sample(
10
10
  long current_monotonic_wall_time_ns,
11
11
  VALUE profiler_overhead_stack_thread
12
12
  );
13
+ __attribute__((warn_unused_result)) bool thread_context_collector_prepare_sample_inside_signal_handler(VALUE self_instance);
13
14
  void thread_context_collector_sample_allocation(VALUE self_instance, unsigned int sample_weight, VALUE new_object);
14
15
  void thread_context_collector_sample_skipped_allocation_samples(VALUE self_instance, unsigned int skipped_samples);
15
16
  VALUE thread_context_collector_sample_after_gc(VALUE self_instance);
@@ -29,10 +29,7 @@ VALUE datadog_gem_version(void) {
29
29
  }
30
30
 
31
31
  static VALUE log_failure_to_process_tag(VALUE err_details) {
32
- VALUE datadog_module = rb_const_get(rb_cObject, rb_intern("Datadog"));
33
- VALUE logger = rb_funcall(datadog_module, rb_intern("logger"), 0);
34
-
35
- return rb_funcall(logger, rb_intern("warn"), 1, rb_sprintf("Failed to convert tag: %"PRIsVALUE, err_details));
32
+ return log_warning(rb_sprintf("Failed to convert tag: %"PRIsVALUE, err_details));
36
33
  }
37
34
 
38
35
  __attribute__((warn_unused_result))
@@ -27,6 +27,9 @@
27
27
  #define ENFORCE_BOOLEAN(value) \
28
28
  { if (RB_UNLIKELY(value != Qtrue && value != Qfalse)) raise_unexpected_type(value, ADD_QUOTES(value), "true or false", __FILE__, __LINE__, __func__); }
29
29
 
30
+ #define ENFORCE_TYPED_DATA(value, type) \
31
+ { if (RB_UNLIKELY(!rb_typeddata_is_kind_of(value, type))) raise_unexpected_type(value, ADD_QUOTES(value), "TypedData of type " ADD_QUOTES(type), __FILE__, __LINE__, __func__); }
32
+
30
33
  NORETURN(void raise_unexpected_type(VALUE value, const char *value_name, const char *type_name, const char *file, int line, const char* function_name));
31
34
 
32
35
  // Helper to retrieve Datadog::VERSION::STRING
@@ -38,6 +41,13 @@ static inline ddog_CharSlice char_slice_from_ruby_string(VALUE string) {
38
41
  return char_slice;
39
42
  }
40
43
 
44
+ static inline VALUE log_warning(VALUE warning) {
45
+ VALUE datadog_module = rb_const_get(rb_cObject, rb_intern("Datadog"));
46
+ VALUE logger = rb_funcall(datadog_module, rb_intern("logger"), 0);
47
+
48
+ return rb_funcall(logger, rb_intern("warn"), 1, warning);
49
+ }
50
+
41
51
  __attribute__((warn_unused_result))
42
52
  ddog_Vec_Tag convert_tags(VALUE tags_as_array);
43
53
 
@@ -0,0 +1,79 @@
1
+ #include "encoded_profile.h"
2
+ #include "datadog_ruby_common.h"
3
+ #include "libdatadog_helpers.h"
4
+
5
+ // This class exists to wrap a ddog_prof_EncodedProfile into a Ruby object
6
+ // This file implements the native bits of the Datadog::Profiling::EncodedProfile class
7
+
8
+ static void encoded_profile_typed_data_free(void *state_ptr);
9
+ static VALUE _native_bytes(VALUE self);
10
+
11
+ static VALUE encoded_profile_class = Qnil;
12
+
13
+ void encoded_profile_init(VALUE profiling_module) {
14
+ encoded_profile_class = rb_define_class_under(profiling_module, "EncodedProfile", rb_cObject);
15
+
16
+ rb_undef_alloc_func(encoded_profile_class); // Class cannot be created from Ruby code
17
+ rb_global_variable(&encoded_profile_class);
18
+
19
+ rb_define_method(encoded_profile_class, "_native_bytes", _native_bytes, 0);
20
+ }
21
+
22
+ // This structure is used to define a Ruby object that stores a `ddog_prof_EncodedProfile`
23
+ // See also https://github.com/ruby/ruby/blob/master/doc/extension.rdoc for how this works
24
+ static const rb_data_type_t encoded_profile_typed_data = {
25
+ .wrap_struct_name = "Datadog::Profiling::EncodedProfile",
26
+ .function = {
27
+ .dmark = NULL, // We don't store references to Ruby objects so we don't need to mark any of them
28
+ .dfree = encoded_profile_typed_data_free,
29
+ .dsize = NULL, // We don't track memory usage (although it'd be cool if we did!)
30
+ //.dcompact = NULL, // Not needed -- we don't store references to Ruby objects
31
+ },
32
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
33
+ };
34
+
35
+ VALUE from_ddog_prof_EncodedProfile(ddog_prof_EncodedProfile profile) {
36
+ ddog_prof_EncodedProfile *state = ruby_xcalloc(1, sizeof(ddog_prof_EncodedProfile));
37
+ *state = profile;
38
+ return TypedData_Wrap_Struct(encoded_profile_class, &encoded_profile_typed_data, state);
39
+ }
40
+
41
+ static ddog_ByteSlice get_bytes(ddog_prof_EncodedProfile *state) {
42
+ ddog_prof_Result_ByteSlice raw_bytes = ddog_prof_EncodedProfile_bytes(state);
43
+ if (raw_bytes.tag == DDOG_PROF_RESULT_BYTE_SLICE_ERR_BYTE_SLICE) {
44
+ rb_raise(rb_eRuntimeError, "Failed to get bytes from profile: %"PRIsVALUE, get_error_details_and_drop(&raw_bytes.err));
45
+ }
46
+ return raw_bytes.ok;
47
+ }
48
+
49
+ static ddog_prof_EncodedProfile *internal_to_ddog_prof_EncodedProfile(VALUE object) {
50
+ ddog_prof_EncodedProfile *state;
51
+ TypedData_Get_Struct(object, ddog_prof_EncodedProfile, &encoded_profile_typed_data, state);
52
+ return state;
53
+ }
54
+
55
+ ddog_prof_EncodedProfile *to_ddog_prof_EncodedProfile(VALUE object) {
56
+ ddog_prof_EncodedProfile *state = internal_to_ddog_prof_EncodedProfile(object);
57
+ get_bytes(state); // Validate profile is still usable -- if it's not, this will raise an exception
58
+ return state;
59
+ }
60
+
61
+ static void encoded_profile_typed_data_free(void *state_ptr) {
62
+ ddog_prof_EncodedProfile *state = (ddog_prof_EncodedProfile *) state_ptr;
63
+
64
+ // This drops the profile itself
65
+ ddog_prof_EncodedProfile_drop(state);
66
+
67
+ // This drops the tiny bit of memory we allocated to contain the ` ddog_prof_EncodedProfile` struct
68
+ ruby_xfree(state);
69
+ }
70
+
71
+ static VALUE _native_bytes(VALUE self) {
72
+ ddog_ByteSlice bytes = get_bytes(internal_to_ddog_prof_EncodedProfile(self));
73
+ return rb_str_new((const char *) bytes.ptr, bytes.len);
74
+ }
75
+
76
+ VALUE enforce_encoded_profile_instance(VALUE object) {
77
+ ENFORCE_TYPED_DATA(object, &encoded_profile_typed_data);
78
+ return object;
79
+ }
@@ -0,0 +1,8 @@
1
+ #pragma once
2
+
3
+ #include <ruby.h>
4
+ #include <datadog/profiling.h>
5
+
6
+ VALUE from_ddog_prof_EncodedProfile(ddog_prof_EncodedProfile profile);
7
+ VALUE enforce_encoded_profile_instance(VALUE object);
8
+ ddog_prof_EncodedProfile *to_ddog_prof_EncodedProfile(VALUE object);
@@ -131,6 +131,16 @@ end
131
131
 
132
132
  have_func "malloc_stats"
133
133
 
134
+ # Used to get native filenames (dladdr1 is preferred, so we only check for the other if not available)
135
+ # Note it's possible none are available
136
+ if have_header("dlfcn.h")
137
+ (have_struct_member("struct link_map", "l_name", "link.h") && have_func("dladdr1")) ||
138
+ have_func("dladdr")
139
+ end
140
+
141
+ # On Ruby 3.5, we can't ask the object_id from IMEMOs (https://github.com/ruby/ruby/pull/13347)
142
+ $defs << "-DNO_IMEMO_OBJECT_ID" unless RUBY_VERSION < "3.5"
143
+
134
144
  # On Ruby 2.5 and 3.3, this symbol was not visible. It is on 2.6 to 3.2, as well as 3.4+
135
145
  $defs << "-DNO_RB_OBJ_INFO" if RUBY_VERSION.start_with?("2.5", "3.3")
136
146