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
@@ -8,6 +8,7 @@
8
8
  #include "ruby_helpers.h"
9
9
  #include "time_helpers.h"
10
10
  #include "heap_recorder.h"
11
+ #include "encoded_profile.h"
11
12
 
12
13
  // Used to wrap a ddog_prof_Profile in a Ruby object and expose Ruby-level serialization APIs
13
14
  // This file implements the native bits of the Datadog::Profiling::StackRecorder class
@@ -181,6 +182,7 @@ typedef struct {
181
182
  typedef struct {
182
183
  ddog_prof_Profile profile;
183
184
  stats_slot stats;
185
+ ddog_Timespec start_timestamp;
184
186
  } profile_slot;
185
187
 
186
188
  // Contains native state for each instance
@@ -194,6 +196,10 @@ typedef struct {
194
196
  pthread_mutex_t mutex_slot_two;
195
197
  profile_slot profile_slot_two;
196
198
 
199
+ ddog_prof_ManagedStringStorage string_storage;
200
+ ddog_prof_ManagedStringId label_key_allocation_class;
201
+ ddog_prof_ManagedStringId label_key_gc_gen_age;
202
+
197
203
  short active_slot; // MUST NEVER BE ACCESSED FROM record_sample; this is NOT for the sampler thread to use.
198
204
 
199
205
  uint8_t position_for[ALL_VALUE_TYPES_COUNT];
@@ -228,6 +234,7 @@ typedef struct {
228
234
  ddog_prof_Profile_SerializeResult result;
229
235
  long heap_profile_build_time_ns;
230
236
  long serialize_no_gvl_time_ns;
237
+ ddog_prof_MaybeError advance_gen_result;
231
238
 
232
239
  // Set by both
233
240
  bool serialize_ran;
@@ -252,9 +259,8 @@ static ddog_Timespec system_epoch_now_timespec(void);
252
259
  static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE recorder_instance);
253
260
  static void serializer_set_start_timestamp_for_next_profile(stack_recorder_state *state, ddog_Timespec start_time);
254
261
  static VALUE _native_record_endpoint(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE local_root_span_id, VALUE endpoint);
255
- static void reset_profile_slot(profile_slot *slot, ddog_Timespec *start_time /* Can be null */);
262
+ static void reset_profile_slot(profile_slot *slot, ddog_Timespec start_timestamp);
256
263
  static VALUE _native_track_object(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE new_obj, VALUE weight, VALUE alloc_class);
257
- static VALUE _native_check_heap_hashes(DDTRACE_UNUSED VALUE _self, VALUE locations);
258
264
  static VALUE _native_start_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
259
265
  static VALUE _native_end_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
260
266
  static VALUE _native_debug_heap_recorder(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
@@ -263,6 +269,8 @@ static VALUE build_profile_stats(profile_slot *slot, long serialization_time_ns,
263
269
  static VALUE _native_is_object_recorded(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE object_id);
264
270
  static VALUE _native_heap_recorder_reset_last_update(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
265
271
  static VALUE _native_recorder_after_gc_step(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
272
+ static VALUE _native_benchmark_intern(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE string, VALUE times, VALUE use_all);
273
+ static VALUE _native_test_managed_string_storage_produces_valid_profiles(DDTRACE_UNUSED VALUE _self);
266
274
 
267
275
  void stack_recorder_init(VALUE profiling_module) {
268
276
  VALUE stack_recorder_class = rb_define_class_under(profiling_module, "StackRecorder", rb_cObject);
@@ -288,7 +296,6 @@ void stack_recorder_init(VALUE profiling_module) {
288
296
  rb_define_singleton_method(testing_module, "_native_slot_two_mutex_locked?", _native_is_slot_two_mutex_locked, 1);
289
297
  rb_define_singleton_method(testing_module, "_native_record_endpoint", _native_record_endpoint, 3);
290
298
  rb_define_singleton_method(testing_module, "_native_track_object", _native_track_object, 4);
291
- rb_define_singleton_method(testing_module, "_native_check_heap_hashes", _native_check_heap_hashes, 1);
292
299
  rb_define_singleton_method(testing_module, "_native_start_fake_slow_heap_serialization",
293
300
  _native_start_fake_slow_heap_serialization, 1);
294
301
  rb_define_singleton_method(testing_module, "_native_end_fake_slow_heap_serialization",
@@ -298,6 +305,8 @@ void stack_recorder_init(VALUE profiling_module) {
298
305
  rb_define_singleton_method(testing_module, "_native_is_object_recorded?", _native_is_object_recorded, 2);
299
306
  rb_define_singleton_method(testing_module, "_native_heap_recorder_reset_last_update", _native_heap_recorder_reset_last_update, 1);
300
307
  rb_define_singleton_method(testing_module, "_native_recorder_after_gc_step", _native_recorder_after_gc_step, 1);
308
+ rb_define_singleton_method(testing_module, "_native_benchmark_intern", _native_benchmark_intern, 4);
309
+ rb_define_singleton_method(testing_module, "_native_test_managed_string_storage_produces_valid_profiles", _native_test_managed_string_storage_produces_valid_profiles, 0);
301
310
 
302
311
  ok_symbol = ID2SYM(rb_intern_const("ok"));
303
312
  error_symbol = ID2SYM(rb_intern_const("error"));
@@ -332,17 +341,27 @@ static VALUE _native_new(VALUE klass) {
332
341
  .serialization_time_ns_min = INT64_MAX,
333
342
  };
334
343
 
335
- // Note: At this point, slot_one_profile/slot_two_profile contain null pointers. Libdatadog validates pointers
344
+ // Note: At this point, slot_one_profile/slot_two_profile/string_storage contain null pointers. Libdatadog validates pointers
336
345
  // before using them so it's ok for us to go ahead and create the StackRecorder object.
337
346
 
338
347
  VALUE stack_recorder = TypedData_Wrap_Struct(klass, &stack_recorder_typed_data, state);
339
348
 
349
+ ddog_prof_ManagedStringStorageNewResult string_storage = ddog_prof_ManagedStringStorage_new();
350
+
351
+ if (string_storage.tag == DDOG_PROF_MANAGED_STRING_STORAGE_NEW_RESULT_ERR) {
352
+ rb_raise(rb_eRuntimeError, "Failed to initialize string storage: %"PRIsVALUE, get_error_details_and_drop(&string_storage.err));
353
+ }
354
+
355
+ state->string_storage = string_storage.ok;
356
+ state->label_key_allocation_class = intern_or_raise(state->string_storage, DDOG_CHARSLICE_C("allocation class"));
357
+ state->label_key_gc_gen_age = intern_or_raise(state->string_storage, DDOG_CHARSLICE_C("gc gen age"));
358
+
359
+ initialize_profiles(state, sample_types);
360
+
340
361
  // NOTE: We initialize this because we want a new recorder to be operational even before #initialize runs and our
341
362
  // default is everything enabled. However, if during recording initialization it turns out we don't want
342
363
  // heap samples, we will free and reset heap_recorder back to NULL.
343
- state->heap_recorder = heap_recorder_new();
344
-
345
- initialize_profiles(state, sample_types);
364
+ state->heap_recorder = heap_recorder_new(state->string_storage);
346
365
 
347
366
  return stack_recorder;
348
367
  }
@@ -358,24 +377,26 @@ static void initialize_slot_concurrency_control(stack_recorder_state *state) {
358
377
  }
359
378
 
360
379
  static void initialize_profiles(stack_recorder_state *state, ddog_prof_Slice_ValueType sample_types) {
380
+ ddog_Timespec start_timestamp = system_epoch_now_timespec();
381
+
361
382
  ddog_prof_Profile_NewResult slot_one_profile_result =
362
- ddog_prof_Profile_new(sample_types, NULL /* period is optional */, NULL /* start_time is optional */);
383
+ ddog_prof_Profile_with_string_storage(sample_types, NULL /* period is optional */, state->string_storage);
363
384
 
364
385
  if (slot_one_profile_result.tag == DDOG_PROF_PROFILE_NEW_RESULT_ERR) {
365
386
  rb_raise(rb_eRuntimeError, "Failed to initialize slot one profile: %"PRIsVALUE, get_error_details_and_drop(&slot_one_profile_result.err));
366
387
  }
367
388
 
368
- state->profile_slot_one = (profile_slot) { .profile = slot_one_profile_result.ok };
389
+ state->profile_slot_one = (profile_slot) { .profile = slot_one_profile_result.ok, .start_timestamp = start_timestamp };
369
390
 
370
391
  ddog_prof_Profile_NewResult slot_two_profile_result =
371
- ddog_prof_Profile_new(sample_types, NULL /* period is optional */, NULL /* start_time is optional */);
392
+ ddog_prof_Profile_with_string_storage(sample_types, NULL /* period is optional */, state->string_storage);
372
393
 
373
394
  if (slot_two_profile_result.tag == DDOG_PROF_PROFILE_NEW_RESULT_ERR) {
374
395
  // Note: No need to take any special care of slot one, it'll get cleaned up by stack_recorder_typed_data_free
375
396
  rb_raise(rb_eRuntimeError, "Failed to initialize slot two profile: %"PRIsVALUE, get_error_details_and_drop(&slot_two_profile_result.err));
376
397
  }
377
398
 
378
- state->profile_slot_two = (profile_slot) { .profile = slot_two_profile_result.ok };
399
+ state->profile_slot_two = (profile_slot) { .profile = slot_two_profile_result.ok, .start_timestamp = start_timestamp };
379
400
  }
380
401
 
381
402
  static void stack_recorder_typed_data_free(void *state_ptr) {
@@ -389,6 +410,8 @@ static void stack_recorder_typed_data_free(void *state_ptr) {
389
410
 
390
411
  heap_recorder_free(state->heap_recorder);
391
412
 
413
+ ddog_prof_ManagedStringStorage_drop(state->string_storage);
414
+
392
415
  ruby_xfree(state);
393
416
  }
394
417
 
@@ -515,6 +538,8 @@ static VALUE _native_serialize(DDTRACE_UNUSED VALUE _self, VALUE recorder_instan
515
538
  long heap_iteration_prep_start_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE);
516
539
  // Prepare the iteration on heap recorder we'll be doing outside the GVL. The preparation needs to
517
540
  // happen while holding on to the GVL.
541
+ // NOTE: While rare, it's possible for the GVL to be released inside this function (see comments on `heap_recorder_update`)
542
+ // and thus don't assume this is an "atomic" step -- other threads may get some running time in the meanwhile.
518
543
  heap_recorder_prepare_iteration(state->heap_recorder);
519
544
  long heap_iteration_prep_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - heap_iteration_prep_start_time_ns;
520
545
 
@@ -523,7 +548,7 @@ static VALUE _native_serialize(DDTRACE_UNUSED VALUE _self, VALUE recorder_instan
523
548
  call_serialize_without_gvl_arguments args = {
524
549
  .state = state,
525
550
  .finish_timestamp = finish_timestamp,
526
- .serialize_ran = false
551
+ .serialize_ran = false,
527
552
  };
528
553
 
529
554
  while (!args.serialize_ran) {
@@ -547,13 +572,9 @@ static VALUE _native_serialize(DDTRACE_UNUSED VALUE _self, VALUE recorder_instan
547
572
  // really cover the full serialization process but it gives a more useful number since it bypasses
548
573
  // the noise of acquiring GVLs and dealing with interruptions which is highly specific to runtime
549
574
  // conditions and over which we really have no control about.
550
- long serialization_time_ns = args.serialize_no_gvl_time_ns;
551
- if (serialization_time_ns >= 0) {
552
- // Only update stats if our serialization time is valid.
553
- state->stats_lifetime.serialization_time_ns_max = long_max_of(state->stats_lifetime.serialization_time_ns_max, serialization_time_ns);
554
- state->stats_lifetime.serialization_time_ns_min = long_min_of(state->stats_lifetime.serialization_time_ns_min, serialization_time_ns);
555
- state->stats_lifetime.serialization_time_ns_total += serialization_time_ns;
556
- }
575
+ state->stats_lifetime.serialization_time_ns_max = long_max_of(state->stats_lifetime.serialization_time_ns_max, args.serialize_no_gvl_time_ns);
576
+ state->stats_lifetime.serialization_time_ns_min = long_min_of(state->stats_lifetime.serialization_time_ns_min, args.serialize_no_gvl_time_ns);
577
+ state->stats_lifetime.serialization_time_ns_total += args.serialize_no_gvl_time_ns;
557
578
 
558
579
  ddog_prof_Profile_SerializeResult serialized_profile = args.result;
559
580
 
@@ -562,20 +583,22 @@ static VALUE _native_serialize(DDTRACE_UNUSED VALUE _self, VALUE recorder_instan
562
583
  return rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&serialized_profile.err));
563
584
  }
564
585
 
586
+ // Note: If we got here, the profile serialized correctly.
587
+ // Once we wrap this into a Ruby object, our `EncodedProfile` class will automatically manage memory for it and we
588
+ // can raise exceptions without worrying about leaking the profile.
565
589
  state->stats_lifetime.serialization_successes++;
590
+ VALUE encoded_profile = from_ddog_prof_EncodedProfile(serialized_profile.ok);
566
591
 
567
- VALUE encoded_pprof = ruby_string_from_vec_u8(serialized_profile.ok.buffer);
568
-
569
- ddog_Timespec ddprof_start = serialized_profile.ok.start;
570
- ddog_Timespec ddprof_finish = serialized_profile.ok.end;
571
-
572
- ddog_prof_EncodedProfile_drop(&serialized_profile.ok);
592
+ ddog_prof_MaybeError result = args.advance_gen_result;
593
+ if (result.tag == DDOG_PROF_OPTION_ERROR_SOME_ERROR) {
594
+ rb_raise(rb_eRuntimeError, "Failed to advance string storage gen: %"PRIsVALUE, get_error_details_and_drop(&result.some));
595
+ }
573
596
 
574
- VALUE start = ruby_time_from(ddprof_start);
575
- VALUE finish = ruby_time_from(ddprof_finish);
576
- VALUE profile_stats = build_profile_stats(args.slot, serialization_time_ns, heap_iteration_prep_time_ns, args.heap_profile_build_time_ns);
597
+ VALUE start = ruby_time_from(args.slot->start_timestamp);
598
+ VALUE finish = ruby_time_from(finish_timestamp);
599
+ VALUE profile_stats = build_profile_stats(args.slot, args.serialize_no_gvl_time_ns, heap_iteration_prep_time_ns, args.heap_profile_build_time_ns);
577
600
 
578
- return rb_ary_new_from_args(2, ok_symbol, rb_ary_new_from_args(4, start, finish, encoded_pprof, profile_stats));
601
+ return rb_ary_new_from_args(2, ok_symbol, rb_ary_new_from_args(4, start, finish, encoded_profile, profile_stats));
579
602
  }
580
603
 
581
604
  static VALUE ruby_time_from(ddog_Timespec ddprof_time) {
@@ -696,18 +719,15 @@ static bool add_heap_sample_to_active_profile_without_gvl(heap_recorder_iteratio
696
719
  ddog_prof_Label labels[2];
697
720
  size_t label_offset = 0;
698
721
 
699
- if (object_data->class != NULL) {
722
+ if (object_data->class.value > 0) {
700
723
  labels[label_offset++] = (ddog_prof_Label) {
701
- .key = DDOG_CHARSLICE_C("allocation class"),
702
- .str = (ddog_CharSlice) {
703
- .ptr = object_data->class,
704
- .len = strlen(object_data->class),
705
- },
724
+ .key_id = context->state->label_key_allocation_class,
725
+ .str_id = object_data->class,
706
726
  .num = 0, // This shouldn't be needed but the tracer-2.7 docker image ships a buggy gcc that complains about this
707
727
  };
708
728
  }
709
729
  labels[label_offset++] = (ddog_prof_Label) {
710
- .key = DDOG_CHARSLICE_C("gc gen age"),
730
+ .key_id = context->state->label_key_gc_gen_age,
711
731
  .num = object_data->gen_age,
712
732
  };
713
733
 
@@ -763,7 +783,6 @@ static void *call_serialize_without_gvl(void *call_args) {
763
783
  long serialize_no_gvl_start_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE);
764
784
 
765
785
  profile_slot *slot_now_inactive = serializer_flip_active_and_inactive_slots(args->state);
766
-
767
786
  args->slot = slot_now_inactive;
768
787
 
769
788
  // Now that we have the inactive profile with all but heap samples, lets fill it with heap data
@@ -772,15 +791,16 @@ static void *call_serialize_without_gvl(void *call_args) {
772
791
  args->heap_profile_build_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - serialize_no_gvl_start_time_ns;
773
792
 
774
793
  // Note: The profile gets reset by the serialize call
775
- args->result = ddog_prof_Profile_serialize(&args->slot->profile, &args->finish_timestamp, NULL /* duration_nanos is optional */, NULL /* start_time is optional */);
794
+ args->result = ddog_prof_Profile_serialize(&args->slot->profile, &args->slot->start_timestamp, &args->finish_timestamp);
795
+ args->advance_gen_result = ddog_prof_ManagedStringStorage_advance_gen(args->state->string_storage);
776
796
  args->serialize_ran = true;
777
- args->serialize_no_gvl_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - serialize_no_gvl_start_time_ns;
797
+ args->serialize_no_gvl_time_ns = long_max_of(0, monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - serialize_no_gvl_start_time_ns);
778
798
 
779
799
  return NULL; // Unused
780
800
  }
781
801
 
782
802
  VALUE enforce_recorder_instance(VALUE object) {
783
- Check_TypedStruct(object, &stack_recorder_typed_data);
803
+ ENFORCE_TYPED_DATA(object, &stack_recorder_typed_data);
784
804
  return object;
785
805
  }
786
806
 
@@ -889,9 +909,9 @@ static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE recorder_
889
909
  // In case the fork happened halfway through `serializer_flip_active_and_inactive_slots` execution and the
890
910
  // resulting state is inconsistent, we make sure to reset it back to the initial state.
891
911
  initialize_slot_concurrency_control(state);
892
-
893
- reset_profile_slot(&state->profile_slot_one, /* start_time: */ NULL);
894
- reset_profile_slot(&state->profile_slot_two, /* start_time: */ NULL);
912
+ ddog_Timespec start_timestamp = system_epoch_now_timespec();
913
+ reset_profile_slot(&state->profile_slot_one, start_timestamp);
914
+ reset_profile_slot(&state->profile_slot_two, start_timestamp);
895
915
 
896
916
  heap_recorder_after_fork(state->heap_recorder);
897
917
 
@@ -903,7 +923,7 @@ static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE recorder_
903
923
  static void serializer_set_start_timestamp_for_next_profile(stack_recorder_state *state, ddog_Timespec start_time) {
904
924
  // Before making this profile active, we reset it so that it uses the correct start_time for its start
905
925
  profile_slot *next_profile_slot = (state->active_slot == 1) ? &state->profile_slot_two : &state->profile_slot_one;
906
- reset_profile_slot(next_profile_slot, &start_time);
926
+ reset_profile_slot(next_profile_slot, start_time);
907
927
  }
908
928
 
909
929
  static VALUE _native_record_endpoint(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE local_root_span_id, VALUE endpoint) {
@@ -918,41 +938,12 @@ static VALUE _native_track_object(DDTRACE_UNUSED VALUE _self, VALUE recorder_ins
918
938
  return Qtrue;
919
939
  }
920
940
 
921
- static VALUE _native_check_heap_hashes(DDTRACE_UNUSED VALUE _self, VALUE locations) {
922
- ENFORCE_TYPE(locations, T_ARRAY);
923
- size_t locations_len = rb_array_len(locations);
924
- ddog_prof_Location locations_arr[locations_len];
925
- for (size_t i = 0; i < locations_len; i++) {
926
- VALUE location = rb_ary_entry(locations, i);
927
- ENFORCE_TYPE(location, T_ARRAY);
928
- VALUE name = rb_ary_entry(location, 0);
929
- VALUE filename = rb_ary_entry(location, 1);
930
- VALUE line = rb_ary_entry(location, 2);
931
- ENFORCE_TYPE(name, T_STRING);
932
- ENFORCE_TYPE(filename, T_STRING);
933
- ENFORCE_TYPE(line, T_FIXNUM);
934
- locations_arr[i] = (ddog_prof_Location) {
935
- .line = line,
936
- .function = (ddog_prof_Function) {
937
- .name = char_slice_from_ruby_string(name),
938
- .filename = char_slice_from_ruby_string(filename),
939
- }
940
- };
941
- }
942
- ddog_prof_Slice_Location ddog_locations = {
943
- .len = locations_len,
944
- .ptr = locations_arr,
945
- };
946
- heap_recorder_testonly_assert_hash_matches(ddog_locations);
947
-
948
- return Qnil;
949
- }
950
-
951
- static void reset_profile_slot(profile_slot *slot, ddog_Timespec *start_time /* Can be null */) {
952
- ddog_prof_Profile_Result reset_result = ddog_prof_Profile_reset(&slot->profile, start_time);
941
+ static void reset_profile_slot(profile_slot *slot, ddog_Timespec start_timestamp) {
942
+ ddog_prof_Profile_Result reset_result = ddog_prof_Profile_reset(&slot->profile);
953
943
  if (reset_result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
954
944
  rb_raise(rb_eRuntimeError, "Failed to reset profile: %"PRIsVALUE, get_error_details_and_drop(&reset_result.err));
955
945
  }
946
+ slot->start_timestamp = start_timestamp;
956
947
  slot->stats = (stats_slot) {};
957
948
  }
958
949
 
@@ -1046,3 +1037,109 @@ static VALUE _native_recorder_after_gc_step(DDTRACE_UNUSED VALUE _self, VALUE re
1046
1037
  recorder_after_gc_step(recorder_instance);
1047
1038
  return Qtrue;
1048
1039
  }
1040
+
1041
+ static VALUE _native_benchmark_intern(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE string, VALUE times, VALUE use_all) {
1042
+ ENFORCE_TYPE(string, T_STRING);
1043
+ ENFORCE_TYPE(times, T_FIXNUM);
1044
+ ENFORCE_BOOLEAN(use_all);
1045
+
1046
+ stack_recorder_state *state;
1047
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
1048
+
1049
+ heap_recorder_testonly_benchmark_intern(state->heap_recorder, char_slice_from_ruby_string(string), FIX2INT(times), use_all == Qtrue);
1050
+
1051
+ return Qtrue;
1052
+ }
1053
+
1054
+ // See comments in rspec test for details on what we're testing here.
1055
+ static VALUE _native_test_managed_string_storage_produces_valid_profiles(DDTRACE_UNUSED VALUE _self) {
1056
+ ddog_prof_ManagedStringStorageNewResult string_storage = ddog_prof_ManagedStringStorage_new();
1057
+
1058
+ if (string_storage.tag == DDOG_PROF_MANAGED_STRING_STORAGE_NEW_RESULT_ERR) {
1059
+ rb_raise(rb_eRuntimeError, "Failed to initialize string storage: %"PRIsVALUE, get_error_details_and_drop(&string_storage.err));
1060
+ }
1061
+
1062
+ ddog_prof_Slice_ValueType sample_types = {.ptr = all_value_types, .len = ALL_VALUE_TYPES_COUNT};
1063
+ ddog_prof_Profile_NewResult profile = ddog_prof_Profile_with_string_storage(sample_types, NULL, string_storage.ok);
1064
+
1065
+ if (profile.tag == DDOG_PROF_PROFILE_NEW_RESULT_ERR) {
1066
+ rb_raise(rb_eRuntimeError, "Failed to initialize profile: %"PRIsVALUE, get_error_details_and_drop(&profile.err));
1067
+ }
1068
+
1069
+ ddog_prof_ManagedStringId hello = intern_or_raise(string_storage.ok, DDOG_CHARSLICE_C("hello"));
1070
+ ddog_prof_ManagedStringId world = intern_or_raise(string_storage.ok, DDOG_CHARSLICE_C("world"));
1071
+ ddog_prof_ManagedStringId key = intern_or_raise(string_storage.ok, DDOG_CHARSLICE_C("key"));
1072
+
1073
+ int64_t metric_values[] = {1, 2, 3, 4, 5, 6, 7, 8};
1074
+ ddog_prof_Label labels[] = {{.key_id = key, .str_id = key}};
1075
+
1076
+ ddog_prof_Location locations[] = {
1077
+ (ddog_prof_Location) {
1078
+ .mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C(""), .build_id_id = {}},
1079
+ .function = {
1080
+ .name = DDOG_CHARSLICE_C(""),
1081
+ .name_id = hello,
1082
+ .filename = DDOG_CHARSLICE_C(""),
1083
+ .filename_id = world,
1084
+ },
1085
+ .line = 1,
1086
+ }
1087
+ };
1088
+
1089
+ ddog_prof_Profile_Result result = ddog_prof_Profile_add(
1090
+ &profile.ok,
1091
+ (ddog_prof_Sample) {
1092
+ .locations = (ddog_prof_Slice_Location) { .ptr = locations, .len = 1},
1093
+ .values = (ddog_Slice_I64) {.ptr = metric_values, .len = 8},
1094
+ .labels = (ddog_prof_Slice_Label) { .ptr = labels, .len = 1 }
1095
+ },
1096
+ 0
1097
+ );
1098
+
1099
+ if (result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
1100
+ rb_raise(rb_eArgError, "Failed to record sample: %"PRIsVALUE, get_error_details_and_drop(&result.err));
1101
+ }
1102
+
1103
+ ddog_Timespec finish_timestamp = system_epoch_now_timespec();
1104
+ ddog_Timespec start_timestamp = {.seconds = finish_timestamp.seconds - 60};
1105
+ ddog_prof_Profile_SerializeResult serialize_result = ddog_prof_Profile_serialize(&profile.ok, &start_timestamp, &finish_timestamp);
1106
+
1107
+ if (serialize_result.tag == DDOG_PROF_PROFILE_SERIALIZE_RESULT_ERR) {
1108
+ rb_raise(rb_eRuntimeError, "Failed to serialize: %"PRIsVALUE, get_error_details_and_drop(&serialize_result.err));
1109
+ }
1110
+
1111
+ ddog_prof_MaybeError advance_gen_result = ddog_prof_ManagedStringStorage_advance_gen(string_storage.ok);
1112
+
1113
+ if (advance_gen_result.tag == DDOG_PROF_OPTION_ERROR_SOME_ERROR) {
1114
+ rb_raise(rb_eRuntimeError, "Failed to advance string storage gen: %"PRIsVALUE, get_error_details_and_drop(&advance_gen_result.some));
1115
+ }
1116
+
1117
+ VALUE encoded_pprof_1 = from_ddog_prof_EncodedProfile(serialize_result.ok);
1118
+
1119
+ result = ddog_prof_Profile_add(
1120
+ &profile.ok,
1121
+ (ddog_prof_Sample) {
1122
+ .locations = (ddog_prof_Slice_Location) { .ptr = locations, .len = 1},
1123
+ .values = (ddog_Slice_I64) {.ptr = metric_values, .len = 8},
1124
+ .labels = (ddog_prof_Slice_Label) { .ptr = labels, .len = 1 }
1125
+ },
1126
+ 0
1127
+ );
1128
+
1129
+ if (result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
1130
+ rb_raise(rb_eArgError, "Failed to record sample: %"PRIsVALUE, get_error_details_and_drop(&result.err));
1131
+ }
1132
+
1133
+ serialize_result = ddog_prof_Profile_serialize(&profile.ok, &start_timestamp, &finish_timestamp);
1134
+
1135
+ if (serialize_result.tag == DDOG_PROF_PROFILE_SERIALIZE_RESULT_ERR) {
1136
+ rb_raise(rb_eArgError, "Failed to serialize: %"PRIsVALUE, get_error_details_and_drop(&serialize_result.err));
1137
+ }
1138
+
1139
+ VALUE encoded_pprof_2 = from_ddog_prof_EncodedProfile(serialize_result.ok);
1140
+
1141
+ ddog_prof_Profile_drop(&profile.ok);
1142
+ ddog_prof_ManagedStringStorage_drop(string_storage.ok);
1143
+
1144
+ return rb_ary_new_from_args(2, encoded_pprof_1, encoded_pprof_2);
1145
+ }
@@ -5,20 +5,14 @@
5
5
 
6
6
  static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self);
7
7
  static VALUE _native_stop(DDTRACE_UNUSED VALUE _self);
8
- static void crashtracker_init(VALUE crashtracking_module);
8
+
9
+ static bool first_init = true;
9
10
 
10
11
  // Used to report Ruby VM crashes.
11
12
  // Once initialized, segfaults will be reported automatically using libdatadog.
12
13
 
13
- void DDTRACE_EXPORT Init_libdatadog_api(void) {
14
- VALUE datadog_module = rb_define_module("Datadog");
15
- VALUE core_module = rb_define_module_under(datadog_module, "Core");
14
+ void crashtracker_init(VALUE core_module) {
16
15
  VALUE crashtracking_module = rb_define_module_under(core_module, "Crashtracking");
17
-
18
- crashtracker_init(crashtracking_module);
19
- }
20
-
21
- void crashtracker_init(VALUE crashtracking_module) {
22
16
  VALUE crashtracker_class = rb_define_class_under(crashtracking_module, "Component", rb_cObject);
23
17
 
24
18
  rb_define_singleton_method(crashtracker_class, "_native_start_or_update_on_fork", _native_start_or_update_on_fork, -1);
@@ -70,7 +64,7 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
70
64
  // "Process.kill('SEGV', Process.pid)" gets run.
71
65
  //
72
66
  // This actually changed in libdatadog 14, so I could see no issues with `create_alt_stack = true`, but not
73
- // overridding what Ruby set up seems a saner default to keep anyway.
67
+ // overriding what Ruby set up seems a saner default to keep anyway.
74
68
  .create_alt_stack = false,
75
69
  .use_alt_stack = true,
76
70
  .endpoint = endpoint,
@@ -100,9 +94,14 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
100
94
 
101
95
  ddog_VoidResult result =
102
96
  action == start_action ?
103
- ddog_crasht_init(config, receiver_config, metadata) :
97
+ (first_init ?
98
+ ddog_crasht_init(config, receiver_config, metadata) :
99
+ ddog_crasht_reconfigure(config, receiver_config, metadata)
100
+ ) :
104
101
  ddog_crasht_update_on_fork(config, receiver_config, metadata);
105
102
 
103
+ first_init = false;
104
+
106
105
  // Clean up before potentially raising any exceptions
107
106
  ddog_Vec_Tag_drop(tags);
108
107
  ddog_endpoint_drop(endpoint);
@@ -116,7 +115,7 @@ static VALUE _native_start_or_update_on_fork(int argc, VALUE *argv, DDTRACE_UNUS
116
115
  }
117
116
 
118
117
  static VALUE _native_stop(DDTRACE_UNUSED VALUE _self) {
119
- ddog_VoidResult result = ddog_crasht_shutdown();
118
+ ddog_VoidResult result = ddog_crasht_disable();
120
119
 
121
120
  if (result.tag == DDOG_VOID_RESULT_ERR) {
122
121
  rb_raise(rb_eRuntimeError, "Failed to stop the crash tracker: %"PRIsVALUE, get_error_details_and_drop(&result.err));
@@ -0,0 +1,5 @@
1
+ #pragma once
2
+
3
+ #include "datadog_ruby_common.h"
4
+
5
+ void crashtracker_init(VALUE core_module);
@@ -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
 
@@ -72,8 +72,8 @@ if ENV['DDTRACE_DEBUG'] == 'true'
72
72
  end
73
73
 
74
74
  # If we got here, libdatadog is available and loaded
75
- ENV['PKG_CONFIG_PATH'] = "#{ENV['PKG_CONFIG_PATH']}:#{Libdatadog.pkgconfig_folder}"
76
- Logging.message("[datadog] PKG_CONFIG_PATH set to #{ENV['PKG_CONFIG_PATH'].inspect}\n")
75
+ ENV['PKG_CONFIG_PATH'] = "#{ENV["PKG_CONFIG_PATH"]}:#{Libdatadog.pkgconfig_folder}"
76
+ Logging.message("[datadog] PKG_CONFIG_PATH set to #{ENV["PKG_CONFIG_PATH"].inspect}\n")
77
77
  $stderr.puts("Using libdatadog #{Libdatadog::VERSION} from #{Libdatadog.pkgconfig_folder}")
78
78
 
79
79
  unless pkg_config('datadog_profiling_with_rpath')
@@ -0,0 +1,15 @@
1
+ #include <ruby.h>
2
+
3
+ #include "datadog_ruby_common.h"
4
+ #include "crashtracker.h"
5
+ #include "process_discovery.h"
6
+ #include "library_config.h"
7
+
8
+ void DDTRACE_EXPORT Init_libdatadog_api(void) {
9
+ VALUE datadog_module = rb_define_module("Datadog");
10
+ VALUE core_module = rb_define_module_under(datadog_module, "Core");
11
+
12
+ crashtracker_init(core_module);
13
+ process_discovery_init(core_module);
14
+ library_config_init(core_module);
15
+ }