cw-datadog 2.23.0.2

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 (944) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5142 -0
  3. data/LICENSE +6 -0
  4. data/LICENSE-3rdparty.csv +7 -0
  5. data/LICENSE.Apache +200 -0
  6. data/LICENSE.BSD3 +24 -0
  7. data/NOTICE +4 -0
  8. data/README.md +24 -0
  9. data/bin/ddprofrb +15 -0
  10. data/ext/LIBDATADOG_DEVELOPMENT.md +3 -0
  11. data/ext/datadog_profiling_native_extension/NativeExtensionDesign.md +156 -0
  12. data/ext/datadog_profiling_native_extension/clock_id.h +23 -0
  13. data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +55 -0
  14. data/ext/datadog_profiling_native_extension/clock_id_noop.c +21 -0
  15. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +1423 -0
  16. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +447 -0
  17. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +131 -0
  18. data/ext/datadog_profiling_native_extension/collectors_dynamic_sampling_rate.c +150 -0
  19. data/ext/datadog_profiling_native_extension/collectors_dynamic_sampling_rate.h +18 -0
  20. data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +156 -0
  21. data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.h +5 -0
  22. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +248 -0
  23. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.h +3 -0
  24. data/ext/datadog_profiling_native_extension/collectors_stack.c +659 -0
  25. data/ext/datadog_profiling_native_extension/collectors_stack.h +44 -0
  26. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +2221 -0
  27. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +31 -0
  28. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +80 -0
  29. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +63 -0
  30. data/ext/datadog_profiling_native_extension/encoded_profile.c +79 -0
  31. data/ext/datadog_profiling_native_extension/encoded_profile.h +8 -0
  32. data/ext/datadog_profiling_native_extension/extconf.rb +321 -0
  33. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +52 -0
  34. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +67 -0
  35. data/ext/datadog_profiling_native_extension/heap_recorder.c +998 -0
  36. data/ext/datadog_profiling_native_extension/heap_recorder.h +177 -0
  37. data/ext/datadog_profiling_native_extension/helpers.h +12 -0
  38. data/ext/datadog_profiling_native_extension/http_transport.c +280 -0
  39. data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +84 -0
  40. data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +28 -0
  41. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +244 -0
  42. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +881 -0
  43. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +81 -0
  44. data/ext/datadog_profiling_native_extension/profiling.c +284 -0
  45. data/ext/datadog_profiling_native_extension/ruby_helpers.c +235 -0
  46. data/ext/datadog_profiling_native_extension/ruby_helpers.h +88 -0
  47. data/ext/datadog_profiling_native_extension/setup_signal_handler.c +115 -0
  48. data/ext/datadog_profiling_native_extension/setup_signal_handler.h +12 -0
  49. data/ext/datadog_profiling_native_extension/stack_recorder.c +1145 -0
  50. data/ext/datadog_profiling_native_extension/stack_recorder.h +31 -0
  51. data/ext/datadog_profiling_native_extension/time_helpers.c +38 -0
  52. data/ext/datadog_profiling_native_extension/time_helpers.h +56 -0
  53. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +47 -0
  54. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +31 -0
  55. data/ext/libdatadog_api/crashtracker.c +125 -0
  56. data/ext/libdatadog_api/crashtracker.h +5 -0
  57. data/ext/libdatadog_api/datadog_ruby_common.c +80 -0
  58. data/ext/libdatadog_api/datadog_ruby_common.h +63 -0
  59. data/ext/libdatadog_api/ddsketch.c +106 -0
  60. data/ext/libdatadog_api/extconf.rb +110 -0
  61. data/ext/libdatadog_api/init.c +18 -0
  62. data/ext/libdatadog_api/library_config.c +172 -0
  63. data/ext/libdatadog_api/library_config.h +25 -0
  64. data/ext/libdatadog_api/process_discovery.c +118 -0
  65. data/ext/libdatadog_api/process_discovery.h +5 -0
  66. data/ext/libdatadog_extconf_helpers.rb +140 -0
  67. data/lib/datadog/appsec/actions_handler/serializable_backtrace.rb +89 -0
  68. data/lib/datadog/appsec/actions_handler.rb +49 -0
  69. data/lib/datadog/appsec/anonymizer.rb +16 -0
  70. data/lib/datadog/appsec/api_security/endpoint_collection/grape_route_serializer.rb +26 -0
  71. data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +59 -0
  72. data/lib/datadog/appsec/api_security/endpoint_collection/rails_route_serializer.rb +29 -0
  73. data/lib/datadog/appsec/api_security/endpoint_collection/sinatra_route_serializer.rb +26 -0
  74. data/lib/datadog/appsec/api_security/endpoint_collection.rb +10 -0
  75. data/lib/datadog/appsec/api_security/route_extractor.rb +77 -0
  76. data/lib/datadog/appsec/api_security/sampler.rb +60 -0
  77. data/lib/datadog/appsec/api_security.rb +23 -0
  78. data/lib/datadog/appsec/assets/blocked.html +99 -0
  79. data/lib/datadog/appsec/assets/blocked.json +1 -0
  80. data/lib/datadog/appsec/assets/blocked.text +5 -0
  81. data/lib/datadog/appsec/assets/waf_rules/README.md +46 -0
  82. data/lib/datadog/appsec/assets/waf_rules/recommended.json +10504 -0
  83. data/lib/datadog/appsec/assets/waf_rules/strict.json +3066 -0
  84. data/lib/datadog/appsec/assets.rb +46 -0
  85. data/lib/datadog/appsec/autoload.rb +13 -0
  86. data/lib/datadog/appsec/component.rb +89 -0
  87. data/lib/datadog/appsec/compressed_json.rb +40 -0
  88. data/lib/datadog/appsec/configuration/settings.rb +409 -0
  89. data/lib/datadog/appsec/configuration.rb +11 -0
  90. data/lib/datadog/appsec/context.rb +97 -0
  91. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +94 -0
  92. data/lib/datadog/appsec/contrib/active_record/integration.rb +41 -0
  93. data/lib/datadog/appsec/contrib/active_record/patcher.rb +101 -0
  94. data/lib/datadog/appsec/contrib/auto_instrument.rb +25 -0
  95. data/lib/datadog/appsec/contrib/devise/configuration.rb +52 -0
  96. data/lib/datadog/appsec/contrib/devise/data_extractor.rb +78 -0
  97. data/lib/datadog/appsec/contrib/devise/ext.rb +35 -0
  98. data/lib/datadog/appsec/contrib/devise/integration.rb +41 -0
  99. data/lib/datadog/appsec/contrib/devise/patcher.rb +63 -0
  100. data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +103 -0
  101. data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +70 -0
  102. data/lib/datadog/appsec/contrib/devise/patches/skip_signin_tracking_patch.rb +21 -0
  103. data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +106 -0
  104. data/lib/datadog/appsec/contrib/excon/integration.rb +41 -0
  105. data/lib/datadog/appsec/contrib/excon/patcher.rb +28 -0
  106. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +42 -0
  107. data/lib/datadog/appsec/contrib/faraday/connection_patch.rb +22 -0
  108. data/lib/datadog/appsec/contrib/faraday/integration.rb +42 -0
  109. data/lib/datadog/appsec/contrib/faraday/patcher.rb +53 -0
  110. data/lib/datadog/appsec/contrib/faraday/rack_builder_patch.rb +22 -0
  111. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +42 -0
  112. data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +29 -0
  113. data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +109 -0
  114. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +56 -0
  115. data/lib/datadog/appsec/contrib/graphql/integration.rb +54 -0
  116. data/lib/datadog/appsec/contrib/graphql/patcher.rb +34 -0
  117. data/lib/datadog/appsec/contrib/integration.rb +37 -0
  118. data/lib/datadog/appsec/contrib/rack/ext.rb +47 -0
  119. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +101 -0
  120. data/lib/datadog/appsec/contrib/rack/gateway/response.rb +30 -0
  121. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +141 -0
  122. data/lib/datadog/appsec/contrib/rack/integration.rb +44 -0
  123. data/lib/datadog/appsec/contrib/rack/patcher.rb +31 -0
  124. data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +43 -0
  125. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +218 -0
  126. data/lib/datadog/appsec/contrib/rails/ext.rb +13 -0
  127. data/lib/datadog/appsec/contrib/rails/framework.rb +16 -0
  128. data/lib/datadog/appsec/contrib/rails/gateway/request.rb +67 -0
  129. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +78 -0
  130. data/lib/datadog/appsec/contrib/rails/integration.rb +43 -0
  131. data/lib/datadog/appsec/contrib/rails/patcher.rb +171 -0
  132. data/lib/datadog/appsec/contrib/rails/patches/process_action_patch.rb +27 -0
  133. data/lib/datadog/appsec/contrib/rails/patches/render_to_body_patch.rb +33 -0
  134. data/lib/datadog/appsec/contrib/rails/request.rb +36 -0
  135. data/lib/datadog/appsec/contrib/rails/request_middleware.rb +20 -0
  136. data/lib/datadog/appsec/contrib/rest_client/integration.rb +45 -0
  137. data/lib/datadog/appsec/contrib/rest_client/patcher.rb +28 -0
  138. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +39 -0
  139. data/lib/datadog/appsec/contrib/sinatra/framework.rb +20 -0
  140. data/lib/datadog/appsec/contrib/sinatra/gateway/request.rb +17 -0
  141. data/lib/datadog/appsec/contrib/sinatra/gateway/route_params.rb +23 -0
  142. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +105 -0
  143. data/lib/datadog/appsec/contrib/sinatra/integration.rb +43 -0
  144. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +132 -0
  145. data/lib/datadog/appsec/contrib/sinatra/patches/json_patch.rb +31 -0
  146. data/lib/datadog/appsec/contrib/sinatra/request_middleware.rb +20 -0
  147. data/lib/datadog/appsec/event.rb +139 -0
  148. data/lib/datadog/appsec/ext.rb +23 -0
  149. data/lib/datadog/appsec/extensions.rb +16 -0
  150. data/lib/datadog/appsec/instrumentation/gateway/argument.rb +43 -0
  151. data/lib/datadog/appsec/instrumentation/gateway/middleware.rb +24 -0
  152. data/lib/datadog/appsec/instrumentation/gateway.rb +59 -0
  153. data/lib/datadog/appsec/instrumentation.rb +9 -0
  154. data/lib/datadog/appsec/metrics/collector.rb +58 -0
  155. data/lib/datadog/appsec/metrics/exporter.rb +35 -0
  156. data/lib/datadog/appsec/metrics/telemetry.rb +23 -0
  157. data/lib/datadog/appsec/metrics/telemetry_exporter.rb +29 -0
  158. data/lib/datadog/appsec/metrics.rb +14 -0
  159. data/lib/datadog/appsec/monitor/gateway/watcher.rb +85 -0
  160. data/lib/datadog/appsec/monitor.rb +11 -0
  161. data/lib/datadog/appsec/processor/rule_loader.rb +119 -0
  162. data/lib/datadog/appsec/rate_limiter.rb +45 -0
  163. data/lib/datadog/appsec/remote.rb +119 -0
  164. data/lib/datadog/appsec/response.rb +99 -0
  165. data/lib/datadog/appsec/sample_rate.rb +21 -0
  166. data/lib/datadog/appsec/security_engine/engine.rb +176 -0
  167. data/lib/datadog/appsec/security_engine/result.rb +102 -0
  168. data/lib/datadog/appsec/security_engine/runner.rb +111 -0
  169. data/lib/datadog/appsec/security_engine.rb +9 -0
  170. data/lib/datadog/appsec/security_event.rb +37 -0
  171. data/lib/datadog/appsec/thread_safe_ref.rb +61 -0
  172. data/lib/datadog/appsec/trace_keeper.rb +24 -0
  173. data/lib/datadog/appsec/utils/hash_coercion.rb +23 -0
  174. data/lib/datadog/appsec/utils/http/media_range.rb +201 -0
  175. data/lib/datadog/appsec/utils/http/media_type.rb +87 -0
  176. data/lib/datadog/appsec/utils/http.rb +11 -0
  177. data/lib/datadog/appsec/utils.rb +9 -0
  178. data/lib/datadog/appsec.rb +65 -0
  179. data/lib/datadog/auto_instrument.rb +19 -0
  180. data/lib/datadog/auto_instrument_base.rb +9 -0
  181. data/lib/datadog/core/buffer/cruby.rb +55 -0
  182. data/lib/datadog/core/buffer/random.rb +150 -0
  183. data/lib/datadog/core/buffer/thread_safe.rb +58 -0
  184. data/lib/datadog/core/chunker.rb +35 -0
  185. data/lib/datadog/core/cloudwise/IMPLEMENTATION_V2.md +517 -0
  186. data/lib/datadog/core/cloudwise/QUICKSTART.md +398 -0
  187. data/lib/datadog/core/cloudwise/README.md +722 -0
  188. data/lib/datadog/core/cloudwise/app_registration_worker.rb +90 -0
  189. data/lib/datadog/core/cloudwise/client.rb +490 -0
  190. data/lib/datadog/core/cloudwise/component.rb +351 -0
  191. data/lib/datadog/core/cloudwise/heartbeat_worker.rb +137 -0
  192. data/lib/datadog/core/cloudwise/host_id_worker.rb +85 -0
  193. data/lib/datadog/core/cloudwise/license_worker.rb +108 -0
  194. data/lib/datadog/core/cloudwise/probe_state.rb +160 -0
  195. data/lib/datadog/core/configuration/agent_settings.rb +52 -0
  196. data/lib/datadog/core/configuration/agent_settings_resolver.rb +339 -0
  197. data/lib/datadog/core/configuration/agentless_settings_resolver.rb +176 -0
  198. data/lib/datadog/core/configuration/base.rb +91 -0
  199. data/lib/datadog/core/configuration/components.rb +386 -0
  200. data/lib/datadog/core/configuration/components_state.rb +23 -0
  201. data/lib/datadog/core/configuration/config_helper.rb +100 -0
  202. data/lib/datadog/core/configuration/deprecations.rb +36 -0
  203. data/lib/datadog/core/configuration/ext.rb +49 -0
  204. data/lib/datadog/core/configuration/option.rb +368 -0
  205. data/lib/datadog/core/configuration/option_definition.rb +158 -0
  206. data/lib/datadog/core/configuration/options.rb +134 -0
  207. data/lib/datadog/core/configuration/settings.rb +1087 -0
  208. data/lib/datadog/core/configuration/stable_config.rb +32 -0
  209. data/lib/datadog/core/configuration/supported_configurations.rb +347 -0
  210. data/lib/datadog/core/configuration.rb +328 -0
  211. data/lib/datadog/core/contrib/rails/utils.rb +24 -0
  212. data/lib/datadog/core/crashtracking/component.rb +105 -0
  213. data/lib/datadog/core/crashtracking/tag_builder.rb +21 -0
  214. data/lib/datadog/core/ddsketch.rb +19 -0
  215. data/lib/datadog/core/deprecations.rb +58 -0
  216. data/lib/datadog/core/diagnostics/environment_logger.rb +170 -0
  217. data/lib/datadog/core/diagnostics/health.rb +19 -0
  218. data/lib/datadog/core/encoding.rb +90 -0
  219. data/lib/datadog/core/environment/agent_info.rb +78 -0
  220. data/lib/datadog/core/environment/cgroup.rb +51 -0
  221. data/lib/datadog/core/environment/class_count.rb +21 -0
  222. data/lib/datadog/core/environment/container.rb +89 -0
  223. data/lib/datadog/core/environment/execution.rb +103 -0
  224. data/lib/datadog/core/environment/ext.rb +45 -0
  225. data/lib/datadog/core/environment/gc.rb +20 -0
  226. data/lib/datadog/core/environment/git.rb +26 -0
  227. data/lib/datadog/core/environment/identity.rb +84 -0
  228. data/lib/datadog/core/environment/platform.rb +46 -0
  229. data/lib/datadog/core/environment/socket.rb +24 -0
  230. data/lib/datadog/core/environment/thread_count.rb +20 -0
  231. data/lib/datadog/core/environment/variable_helpers.rb +53 -0
  232. data/lib/datadog/core/environment/vm_cache.rb +64 -0
  233. data/lib/datadog/core/environment/yjit.rb +69 -0
  234. data/lib/datadog/core/error.rb +102 -0
  235. data/lib/datadog/core/extensions.rb +16 -0
  236. data/lib/datadog/core/git/ext.rb +16 -0
  237. data/lib/datadog/core/header_collection.rb +43 -0
  238. data/lib/datadog/core/logger.rb +45 -0
  239. data/lib/datadog/core/logging/ext.rb +13 -0
  240. data/lib/datadog/core/metrics/client.rb +206 -0
  241. data/lib/datadog/core/metrics/ext.rb +18 -0
  242. data/lib/datadog/core/metrics/helpers.rb +25 -0
  243. data/lib/datadog/core/metrics/logging.rb +44 -0
  244. data/lib/datadog/core/metrics/metric.rb +14 -0
  245. data/lib/datadog/core/metrics/options.rb +52 -0
  246. data/lib/datadog/core/pin.rb +71 -0
  247. data/lib/datadog/core/process_discovery/tracer_memfd.rb +13 -0
  248. data/lib/datadog/core/process_discovery.rb +61 -0
  249. data/lib/datadog/core/rate_limiter.rb +185 -0
  250. data/lib/datadog/core/remote/client/capabilities.rb +70 -0
  251. data/lib/datadog/core/remote/client.rb +245 -0
  252. data/lib/datadog/core/remote/component.rb +161 -0
  253. data/lib/datadog/core/remote/configuration/content.rb +111 -0
  254. data/lib/datadog/core/remote/configuration/digest.rb +62 -0
  255. data/lib/datadog/core/remote/configuration/path.rb +90 -0
  256. data/lib/datadog/core/remote/configuration/repository.rb +307 -0
  257. data/lib/datadog/core/remote/configuration/target.rb +74 -0
  258. data/lib/datadog/core/remote/configuration.rb +18 -0
  259. data/lib/datadog/core/remote/dispatcher.rb +59 -0
  260. data/lib/datadog/core/remote/ext.rb +13 -0
  261. data/lib/datadog/core/remote/negotiation.rb +70 -0
  262. data/lib/datadog/core/remote/tie/tracing.rb +39 -0
  263. data/lib/datadog/core/remote/tie.rb +29 -0
  264. data/lib/datadog/core/remote/transport/config.rb +61 -0
  265. data/lib/datadog/core/remote/transport/http/api.rb +53 -0
  266. data/lib/datadog/core/remote/transport/http/client.rb +49 -0
  267. data/lib/datadog/core/remote/transport/http/config.rb +252 -0
  268. data/lib/datadog/core/remote/transport/http/negotiation.rb +103 -0
  269. data/lib/datadog/core/remote/transport/http.rb +83 -0
  270. data/lib/datadog/core/remote/transport/negotiation.rb +75 -0
  271. data/lib/datadog/core/remote/worker.rb +105 -0
  272. data/lib/datadog/core/remote.rb +24 -0
  273. data/lib/datadog/core/runtime/ext.rb +40 -0
  274. data/lib/datadog/core/runtime/metrics.rb +202 -0
  275. data/lib/datadog/core/semaphore.rb +35 -0
  276. data/lib/datadog/core/tag_builder.rb +52 -0
  277. data/lib/datadog/core/telemetry/component.rb +206 -0
  278. data/lib/datadog/core/telemetry/emitter.rb +56 -0
  279. data/lib/datadog/core/telemetry/event/app_client_configuration_change.rb +66 -0
  280. data/lib/datadog/core/telemetry/event/app_closing.rb +18 -0
  281. data/lib/datadog/core/telemetry/event/app_dependencies_loaded.rb +33 -0
  282. data/lib/datadog/core/telemetry/event/app_endpoints_loaded.rb +30 -0
  283. data/lib/datadog/core/telemetry/event/app_heartbeat.rb +18 -0
  284. data/lib/datadog/core/telemetry/event/app_integrations_change.rb +58 -0
  285. data/lib/datadog/core/telemetry/event/app_started.rb +287 -0
  286. data/lib/datadog/core/telemetry/event/base.rb +40 -0
  287. data/lib/datadog/core/telemetry/event/distributions.rb +18 -0
  288. data/lib/datadog/core/telemetry/event/generate_metrics.rb +43 -0
  289. data/lib/datadog/core/telemetry/event/log.rb +76 -0
  290. data/lib/datadog/core/telemetry/event/message_batch.rb +42 -0
  291. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +43 -0
  292. data/lib/datadog/core/telemetry/event.rb +37 -0
  293. data/lib/datadog/core/telemetry/ext.rb +20 -0
  294. data/lib/datadog/core/telemetry/http/adapters/net.rb +26 -0
  295. data/lib/datadog/core/telemetry/logger.rb +52 -0
  296. data/lib/datadog/core/telemetry/logging.rb +71 -0
  297. data/lib/datadog/core/telemetry/metric.rb +189 -0
  298. data/lib/datadog/core/telemetry/metrics_collection.rb +81 -0
  299. data/lib/datadog/core/telemetry/metrics_manager.rb +81 -0
  300. data/lib/datadog/core/telemetry/request.rb +71 -0
  301. data/lib/datadog/core/telemetry/transport/http/api.rb +43 -0
  302. data/lib/datadog/core/telemetry/transport/http/client.rb +49 -0
  303. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +92 -0
  304. data/lib/datadog/core/telemetry/transport/http.rb +63 -0
  305. data/lib/datadog/core/telemetry/transport/telemetry.rb +51 -0
  306. data/lib/datadog/core/telemetry/worker.rb +276 -0
  307. data/lib/datadog/core/transport/ext.rb +44 -0
  308. data/lib/datadog/core/transport/http/adapters/net.rb +175 -0
  309. data/lib/datadog/core/transport/http/adapters/registry.rb +29 -0
  310. data/lib/datadog/core/transport/http/adapters/test.rb +90 -0
  311. data/lib/datadog/core/transport/http/adapters/unix_socket.rb +83 -0
  312. data/lib/datadog/core/transport/http/api/endpoint.rb +31 -0
  313. data/lib/datadog/core/transport/http/api/fallbacks.rb +26 -0
  314. data/lib/datadog/core/transport/http/api/instance.rb +54 -0
  315. data/lib/datadog/core/transport/http/api/map.rb +18 -0
  316. data/lib/datadog/core/transport/http/api/spec.rb +36 -0
  317. data/lib/datadog/core/transport/http/builder.rb +184 -0
  318. data/lib/datadog/core/transport/http/env.rb +70 -0
  319. data/lib/datadog/core/transport/http/response.rb +60 -0
  320. data/lib/datadog/core/transport/http.rb +75 -0
  321. data/lib/datadog/core/transport/parcel.rb +22 -0
  322. data/lib/datadog/core/transport/request.rb +17 -0
  323. data/lib/datadog/core/transport/response.rb +71 -0
  324. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +102 -0
  325. data/lib/datadog/core/utils/base64.rb +22 -0
  326. data/lib/datadog/core/utils/duration.rb +52 -0
  327. data/lib/datadog/core/utils/forking.rb +63 -0
  328. data/lib/datadog/core/utils/hash.rb +79 -0
  329. data/lib/datadog/core/utils/lru_cache.rb +45 -0
  330. data/lib/datadog/core/utils/network.rb +142 -0
  331. data/lib/datadog/core/utils/only_once.rb +42 -0
  332. data/lib/datadog/core/utils/only_once_successful.rb +87 -0
  333. data/lib/datadog/core/utils/safe_dup.rb +40 -0
  334. data/lib/datadog/core/utils/sequence.rb +26 -0
  335. data/lib/datadog/core/utils/time.rb +84 -0
  336. data/lib/datadog/core/utils/truncation.rb +21 -0
  337. data/lib/datadog/core/utils/url.rb +25 -0
  338. data/lib/datadog/core/utils.rb +101 -0
  339. data/lib/datadog/core/vendor/multipart-post/LICENSE +11 -0
  340. data/lib/datadog/core/vendor/multipart-post/multipart/post/composite_read_io.rb +118 -0
  341. data/lib/datadog/core/vendor/multipart-post/multipart/post/multipartable.rb +59 -0
  342. data/lib/datadog/core/vendor/multipart-post/multipart/post/parts.rb +137 -0
  343. data/lib/datadog/core/vendor/multipart-post/multipart/post/version.rb +11 -0
  344. data/lib/datadog/core/vendor/multipart-post/multipart/post.rb +10 -0
  345. data/lib/datadog/core/vendor/multipart-post/multipart.rb +14 -0
  346. data/lib/datadog/core/vendor/multipart-post/net/http/post/multipart.rb +34 -0
  347. data/lib/datadog/core/worker.rb +24 -0
  348. data/lib/datadog/core/workers/async.rb +202 -0
  349. data/lib/datadog/core/workers/interval_loop.rb +134 -0
  350. data/lib/datadog/core/workers/polling.rb +59 -0
  351. data/lib/datadog/core/workers/queue.rb +44 -0
  352. data/lib/datadog/core/workers/runtime_metrics.rb +62 -0
  353. data/lib/datadog/core.rb +38 -0
  354. data/lib/datadog/data_streams/configuration/settings.rb +49 -0
  355. data/lib/datadog/data_streams/configuration.rb +11 -0
  356. data/lib/datadog/data_streams/ext.rb +11 -0
  357. data/lib/datadog/data_streams/extensions.rb +16 -0
  358. data/lib/datadog/data_streams/pathway_context.rb +169 -0
  359. data/lib/datadog/data_streams/processor.rb +509 -0
  360. data/lib/datadog/data_streams/transport/http/api.rb +33 -0
  361. data/lib/datadog/data_streams/transport/http/client.rb +49 -0
  362. data/lib/datadog/data_streams/transport/http/stats.rb +87 -0
  363. data/lib/datadog/data_streams/transport/http.rb +41 -0
  364. data/lib/datadog/data_streams/transport/stats.rb +60 -0
  365. data/lib/datadog/data_streams.rb +100 -0
  366. data/lib/datadog/di/base.rb +115 -0
  367. data/lib/datadog/di/boot.rb +43 -0
  368. data/lib/datadog/di/code_tracker.rb +204 -0
  369. data/lib/datadog/di/component.rb +122 -0
  370. data/lib/datadog/di/configuration/settings.rb +212 -0
  371. data/lib/datadog/di/configuration.rb +11 -0
  372. data/lib/datadog/di/context.rb +70 -0
  373. data/lib/datadog/di/contrib/active_record.rb +12 -0
  374. data/lib/datadog/di/contrib/railtie.rb +15 -0
  375. data/lib/datadog/di/contrib.rb +28 -0
  376. data/lib/datadog/di/el/compiler.rb +164 -0
  377. data/lib/datadog/di/el/evaluator.rb +159 -0
  378. data/lib/datadog/di/el/expression.rb +42 -0
  379. data/lib/datadog/di/el.rb +5 -0
  380. data/lib/datadog/di/error.rb +82 -0
  381. data/lib/datadog/di/extensions.rb +16 -0
  382. data/lib/datadog/di/instrumenter.rb +566 -0
  383. data/lib/datadog/di/logger.rb +30 -0
  384. data/lib/datadog/di/preload.rb +18 -0
  385. data/lib/datadog/di/probe.rb +231 -0
  386. data/lib/datadog/di/probe_builder.rb +86 -0
  387. data/lib/datadog/di/probe_file_loader/railtie.rb +15 -0
  388. data/lib/datadog/di/probe_file_loader.rb +82 -0
  389. data/lib/datadog/di/probe_manager.rb +261 -0
  390. data/lib/datadog/di/probe_notification_builder.rb +236 -0
  391. data/lib/datadog/di/probe_notifier_worker.rb +305 -0
  392. data/lib/datadog/di/proc_responder.rb +32 -0
  393. data/lib/datadog/di/redactor.rb +187 -0
  394. data/lib/datadog/di/remote.rb +145 -0
  395. data/lib/datadog/di/serializer.rb +422 -0
  396. data/lib/datadog/di/transport/diagnostics.rb +62 -0
  397. data/lib/datadog/di/transport/http/api.rb +42 -0
  398. data/lib/datadog/di/transport/http/client.rb +47 -0
  399. data/lib/datadog/di/transport/http/diagnostics.rb +65 -0
  400. data/lib/datadog/di/transport/http/input.rb +77 -0
  401. data/lib/datadog/di/transport/http.rb +57 -0
  402. data/lib/datadog/di/transport/input.rb +70 -0
  403. data/lib/datadog/di/utils.rb +142 -0
  404. data/lib/datadog/di.rb +36 -0
  405. data/lib/datadog/error_tracking/collector.rb +87 -0
  406. data/lib/datadog/error_tracking/component.rb +167 -0
  407. data/lib/datadog/error_tracking/configuration/settings.rb +63 -0
  408. data/lib/datadog/error_tracking/configuration.rb +11 -0
  409. data/lib/datadog/error_tracking/ext.rb +18 -0
  410. data/lib/datadog/error_tracking/extensions.rb +16 -0
  411. data/lib/datadog/error_tracking/filters.rb +77 -0
  412. data/lib/datadog/error_tracking.rb +18 -0
  413. data/lib/datadog/kit/appsec/events/v2.rb +196 -0
  414. data/lib/datadog/kit/appsec/events.rb +180 -0
  415. data/lib/datadog/kit/enable_core_dumps.rb +49 -0
  416. data/lib/datadog/kit/identity.rb +114 -0
  417. data/lib/datadog/kit.rb +11 -0
  418. data/lib/datadog/opentelemetry/api/baggage.rb +90 -0
  419. data/lib/datadog/opentelemetry/api/baggage.rbs +26 -0
  420. data/lib/datadog/opentelemetry/api/context.rb +208 -0
  421. data/lib/datadog/opentelemetry/api/trace/span.rb +14 -0
  422. data/lib/datadog/opentelemetry/sdk/configurator.rb +37 -0
  423. data/lib/datadog/opentelemetry/sdk/id_generator.rb +26 -0
  424. data/lib/datadog/opentelemetry/sdk/propagator.rb +89 -0
  425. data/lib/datadog/opentelemetry/sdk/span_processor.rb +169 -0
  426. data/lib/datadog/opentelemetry/sdk/trace/span.rb +182 -0
  427. data/lib/datadog/opentelemetry/trace.rb +59 -0
  428. data/lib/datadog/opentelemetry.rb +52 -0
  429. data/lib/datadog/profiling/collectors/code_provenance.rb +150 -0
  430. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +147 -0
  431. data/lib/datadog/profiling/collectors/dynamic_sampling_rate.rb +14 -0
  432. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +69 -0
  433. data/lib/datadog/profiling/collectors/info.rb +156 -0
  434. data/lib/datadog/profiling/collectors/stack.rb +13 -0
  435. data/lib/datadog/profiling/collectors/thread_context.rb +102 -0
  436. data/lib/datadog/profiling/component.rb +445 -0
  437. data/lib/datadog/profiling/encoded_profile.rb +11 -0
  438. data/lib/datadog/profiling/exporter.rb +111 -0
  439. data/lib/datadog/profiling/ext/dir_monkey_patches.rb +410 -0
  440. data/lib/datadog/profiling/ext.rb +22 -0
  441. data/lib/datadog/profiling/flush.rb +40 -0
  442. data/lib/datadog/profiling/http_transport.rb +67 -0
  443. data/lib/datadog/profiling/load_native_extension.rb +9 -0
  444. data/lib/datadog/profiling/native_extension.rb +20 -0
  445. data/lib/datadog/profiling/preload.rb +5 -0
  446. data/lib/datadog/profiling/profiler.rb +70 -0
  447. data/lib/datadog/profiling/scheduler.rb +153 -0
  448. data/lib/datadog/profiling/sequence_tracker.rb +44 -0
  449. data/lib/datadog/profiling/stack_recorder.rb +104 -0
  450. data/lib/datadog/profiling/tag_builder.rb +59 -0
  451. data/lib/datadog/profiling/tasks/exec.rb +50 -0
  452. data/lib/datadog/profiling/tasks/help.rb +18 -0
  453. data/lib/datadog/profiling/tasks/setup.rb +43 -0
  454. data/lib/datadog/profiling.rb +167 -0
  455. data/lib/datadog/single_step_instrument.rb +21 -0
  456. data/lib/datadog/tracing/analytics.rb +25 -0
  457. data/lib/datadog/tracing/buffer.rb +129 -0
  458. data/lib/datadog/tracing/client_ip.rb +61 -0
  459. data/lib/datadog/tracing/component.rb +216 -0
  460. data/lib/datadog/tracing/configuration/dynamic/option.rb +71 -0
  461. data/lib/datadog/tracing/configuration/dynamic.rb +100 -0
  462. data/lib/datadog/tracing/configuration/ext.rb +118 -0
  463. data/lib/datadog/tracing/configuration/http.rb +74 -0
  464. data/lib/datadog/tracing/configuration/settings.rb +579 -0
  465. data/lib/datadog/tracing/context.rb +68 -0
  466. data/lib/datadog/tracing/context_provider.rb +82 -0
  467. data/lib/datadog/tracing/contrib/action_cable/configuration/settings.rb +39 -0
  468. data/lib/datadog/tracing/contrib/action_cable/event.rb +71 -0
  469. data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +58 -0
  470. data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +63 -0
  471. data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +59 -0
  472. data/lib/datadog/tracing/contrib/action_cable/events.rb +37 -0
  473. data/lib/datadog/tracing/contrib/action_cable/ext.rb +33 -0
  474. data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +86 -0
  475. data/lib/datadog/tracing/contrib/action_cable/integration.rb +53 -0
  476. data/lib/datadog/tracing/contrib/action_cable/patcher.rb +31 -0
  477. data/lib/datadog/tracing/contrib/action_mailer/configuration/settings.rb +43 -0
  478. data/lib/datadog/tracing/contrib/action_mailer/event.rb +50 -0
  479. data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +65 -0
  480. data/lib/datadog/tracing/contrib/action_mailer/events/process.rb +48 -0
  481. data/lib/datadog/tracing/contrib/action_mailer/events.rb +34 -0
  482. data/lib/datadog/tracing/contrib/action_mailer/ext.rb +34 -0
  483. data/lib/datadog/tracing/contrib/action_mailer/integration.rb +54 -0
  484. data/lib/datadog/tracing/contrib/action_mailer/patcher.rb +29 -0
  485. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +158 -0
  486. data/lib/datadog/tracing/contrib/action_pack/action_controller/patcher.rb +29 -0
  487. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/instrumentation.rb +85 -0
  488. data/lib/datadog/tracing/contrib/action_pack/action_dispatch/patcher.rb +33 -0
  489. data/lib/datadog/tracing/contrib/action_pack/configuration/settings.rb +40 -0
  490. data/lib/datadog/tracing/contrib/action_pack/ext.rb +25 -0
  491. data/lib/datadog/tracing/contrib/action_pack/integration.rb +54 -0
  492. data/lib/datadog/tracing/contrib/action_pack/patcher.rb +29 -0
  493. data/lib/datadog/tracing/contrib/action_pack/utils.rb +39 -0
  494. data/lib/datadog/tracing/contrib/action_view/configuration/settings.rb +43 -0
  495. data/lib/datadog/tracing/contrib/action_view/event.rb +35 -0
  496. data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +50 -0
  497. data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +57 -0
  498. data/lib/datadog/tracing/contrib/action_view/events.rb +34 -0
  499. data/lib/datadog/tracing/contrib/action_view/ext.rb +25 -0
  500. data/lib/datadog/tracing/contrib/action_view/integration.rb +61 -0
  501. data/lib/datadog/tracing/contrib/action_view/patcher.rb +34 -0
  502. data/lib/datadog/tracing/contrib/action_view/utils.rb +36 -0
  503. data/lib/datadog/tracing/contrib/active_job/configuration/settings.rb +39 -0
  504. data/lib/datadog/tracing/contrib/active_job/event.rb +58 -0
  505. data/lib/datadog/tracing/contrib/active_job/events/discard.rb +50 -0
  506. data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +49 -0
  507. data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +49 -0
  508. data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +51 -0
  509. data/lib/datadog/tracing/contrib/active_job/events/perform.rb +49 -0
  510. data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +50 -0
  511. data/lib/datadog/tracing/contrib/active_job/events.rb +42 -0
  512. data/lib/datadog/tracing/contrib/active_job/ext.rb +40 -0
  513. data/lib/datadog/tracing/contrib/active_job/integration.rb +53 -0
  514. data/lib/datadog/tracing/contrib/active_job/log_injection.rb +38 -0
  515. data/lib/datadog/tracing/contrib/active_job/patcher.rb +40 -0
  516. data/lib/datadog/tracing/contrib/active_model_serializers/configuration/settings.rb +37 -0
  517. data/lib/datadog/tracing/contrib/active_model_serializers/event.rb +68 -0
  518. data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +45 -0
  519. data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +47 -0
  520. data/lib/datadog/tracing/contrib/active_model_serializers/events.rb +34 -0
  521. data/lib/datadog/tracing/contrib/active_model_serializers/ext.rb +25 -0
  522. data/lib/datadog/tracing/contrib/active_model_serializers/integration.rb +44 -0
  523. data/lib/datadog/tracing/contrib/active_model_serializers/patcher.rb +32 -0
  524. data/lib/datadog/tracing/contrib/active_record/configuration/makara_resolver.rb +36 -0
  525. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +152 -0
  526. data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +48 -0
  527. data/lib/datadog/tracing/contrib/active_record/event.rb +30 -0
  528. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +60 -0
  529. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +80 -0
  530. data/lib/datadog/tracing/contrib/active_record/events.rb +34 -0
  531. data/lib/datadog/tracing/contrib/active_record/ext.rb +30 -0
  532. data/lib/datadog/tracing/contrib/active_record/integration.rb +71 -0
  533. data/lib/datadog/tracing/contrib/active_record/patcher.rb +27 -0
  534. data/lib/datadog/tracing/contrib/active_record/utils.rb +128 -0
  535. data/lib/datadog/tracing/contrib/active_support/cache/event.rb +32 -0
  536. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +171 -0
  537. data/lib/datadog/tracing/contrib/active_support/cache/events.rb +34 -0
  538. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +225 -0
  539. data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +57 -0
  540. data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +60 -0
  541. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +70 -0
  542. data/lib/datadog/tracing/contrib/active_support/ext.rb +32 -0
  543. data/lib/datadog/tracing/contrib/active_support/integration.rb +55 -0
  544. data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +95 -0
  545. data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +83 -0
  546. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +166 -0
  547. data/lib/datadog/tracing/contrib/active_support/patcher.rb +27 -0
  548. data/lib/datadog/tracing/contrib/analytics.rb +33 -0
  549. data/lib/datadog/tracing/contrib/auto_instrument.rb +53 -0
  550. data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +53 -0
  551. data/lib/datadog/tracing/contrib/aws/ext.rb +50 -0
  552. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +136 -0
  553. data/lib/datadog/tracing/contrib/aws/integration.rb +50 -0
  554. data/lib/datadog/tracing/contrib/aws/parsed_context.rb +70 -0
  555. data/lib/datadog/tracing/contrib/aws/patcher.rb +61 -0
  556. data/lib/datadog/tracing/contrib/aws/service/base.rb +17 -0
  557. data/lib/datadog/tracing/contrib/aws/service/dynamodb.rb +22 -0
  558. data/lib/datadog/tracing/contrib/aws/service/eventbridge.rb +22 -0
  559. data/lib/datadog/tracing/contrib/aws/service/kinesis.rb +32 -0
  560. data/lib/datadog/tracing/contrib/aws/service/s3.rb +22 -0
  561. data/lib/datadog/tracing/contrib/aws/service/sns.rb +30 -0
  562. data/lib/datadog/tracing/contrib/aws/service/sqs.rb +27 -0
  563. data/lib/datadog/tracing/contrib/aws/service/states.rb +40 -0
  564. data/lib/datadog/tracing/contrib/aws/services.rb +139 -0
  565. data/lib/datadog/tracing/contrib/cloudwise/propagation.rb +315 -0
  566. data/lib/datadog/tracing/contrib/component.rb +41 -0
  567. data/lib/datadog/tracing/contrib/concurrent_ruby/async_patch.rb +20 -0
  568. data/lib/datadog/tracing/contrib/concurrent_ruby/configuration/settings.rb +24 -0
  569. data/lib/datadog/tracing/contrib/concurrent_ruby/context_composite_executor_service.rb +53 -0
  570. data/lib/datadog/tracing/contrib/concurrent_ruby/ext.rb +16 -0
  571. data/lib/datadog/tracing/contrib/concurrent_ruby/future_patch.rb +20 -0
  572. data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +47 -0
  573. data/lib/datadog/tracing/contrib/concurrent_ruby/patcher.rb +49 -0
  574. data/lib/datadog/tracing/contrib/concurrent_ruby/promises_future_patch.rb +22 -0
  575. data/lib/datadog/tracing/contrib/configurable.rb +102 -0
  576. data/lib/datadog/tracing/contrib/configuration/resolver.rb +128 -0
  577. data/lib/datadog/tracing/contrib/configuration/resolvers/pattern_resolver.rb +43 -0
  578. data/lib/datadog/tracing/contrib/configuration/settings.rb +43 -0
  579. data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +58 -0
  580. data/lib/datadog/tracing/contrib/dalli/ext.rb +41 -0
  581. data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +75 -0
  582. data/lib/datadog/tracing/contrib/dalli/integration.rb +52 -0
  583. data/lib/datadog/tracing/contrib/dalli/patcher.rb +28 -0
  584. data/lib/datadog/tracing/contrib/dalli/quantize.rb +26 -0
  585. data/lib/datadog/tracing/contrib/delayed_job/configuration/settings.rb +49 -0
  586. data/lib/datadog/tracing/contrib/delayed_job/ext.rb +29 -0
  587. data/lib/datadog/tracing/contrib/delayed_job/integration.rb +43 -0
  588. data/lib/datadog/tracing/contrib/delayed_job/patcher.rb +37 -0
  589. data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +108 -0
  590. data/lib/datadog/tracing/contrib/delayed_job/server_internal_tracer/worker.rb +34 -0
  591. data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +61 -0
  592. data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +35 -0
  593. data/lib/datadog/tracing/contrib/elasticsearch/integration.rb +50 -0
  594. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +172 -0
  595. data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +87 -0
  596. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +56 -0
  597. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +229 -0
  598. data/lib/datadog/tracing/contrib/ethon/ext.rb +33 -0
  599. data/lib/datadog/tracing/contrib/ethon/integration.rb +48 -0
  600. data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +102 -0
  601. data/lib/datadog/tracing/contrib/ethon/patcher.rb +30 -0
  602. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +82 -0
  603. data/lib/datadog/tracing/contrib/excon/ext.rb +31 -0
  604. data/lib/datadog/tracing/contrib/excon/integration.rb +48 -0
  605. data/lib/datadog/tracing/contrib/excon/middleware.rb +201 -0
  606. data/lib/datadog/tracing/contrib/excon/patcher.rb +31 -0
  607. data/lib/datadog/tracing/contrib/ext.rb +70 -0
  608. data/lib/datadog/tracing/contrib/extensions.rb +255 -0
  609. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +81 -0
  610. data/lib/datadog/tracing/contrib/faraday/connection.rb +22 -0
  611. data/lib/datadog/tracing/contrib/faraday/ext.rb +31 -0
  612. data/lib/datadog/tracing/contrib/faraday/integration.rb +48 -0
  613. data/lib/datadog/tracing/contrib/faraday/middleware.rb +128 -0
  614. data/lib/datadog/tracing/contrib/faraday/patcher.rb +56 -0
  615. data/lib/datadog/tracing/contrib/faraday/rack_builder.rb +22 -0
  616. data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +59 -0
  617. data/lib/datadog/tracing/contrib/grape/endpoint.rb +316 -0
  618. data/lib/datadog/tracing/contrib/grape/ext.rb +30 -0
  619. data/lib/datadog/tracing/contrib/grape/instrumentation.rb +37 -0
  620. data/lib/datadog/tracing/contrib/grape/integration.rb +44 -0
  621. data/lib/datadog/tracing/contrib/grape/patcher.rb +33 -0
  622. data/lib/datadog/tracing/contrib/graphql/configuration/error_extension_env_parser.rb +21 -0
  623. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +73 -0
  624. data/lib/datadog/tracing/contrib/graphql/ext.rb +26 -0
  625. data/lib/datadog/tracing/contrib/graphql/integration.rb +56 -0
  626. data/lib/datadog/tracing/contrib/graphql/patcher.rb +58 -0
  627. data/lib/datadog/tracing/contrib/graphql/trace_patcher.rb +24 -0
  628. data/lib/datadog/tracing/contrib/graphql/tracing_patcher.rb +28 -0
  629. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +297 -0
  630. data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +31 -0
  631. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +58 -0
  632. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +123 -0
  633. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +96 -0
  634. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor.rb +107 -0
  635. data/lib/datadog/tracing/contrib/grpc/distributed/fetcher.rb +26 -0
  636. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +49 -0
  637. data/lib/datadog/tracing/contrib/grpc/ext.rb +29 -0
  638. data/lib/datadog/tracing/contrib/grpc/formatting.rb +127 -0
  639. data/lib/datadog/tracing/contrib/grpc/integration.rb +50 -0
  640. data/lib/datadog/tracing/contrib/grpc/intercept_with_datadog.rb +53 -0
  641. data/lib/datadog/tracing/contrib/grpc/patcher.rb +34 -0
  642. data/lib/datadog/tracing/contrib/grpc.rb +45 -0
  643. data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +47 -0
  644. data/lib/datadog/tracing/contrib/hanami/configuration/settings.rb +23 -0
  645. data/lib/datadog/tracing/contrib/hanami/ext.rb +24 -0
  646. data/lib/datadog/tracing/contrib/hanami/integration.rb +44 -0
  647. data/lib/datadog/tracing/contrib/hanami/patcher.rb +33 -0
  648. data/lib/datadog/tracing/contrib/hanami/plugin.rb +23 -0
  649. data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +41 -0
  650. data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +42 -0
  651. data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +34 -0
  652. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +77 -0
  653. data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +38 -0
  654. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +48 -0
  655. data/lib/datadog/tracing/contrib/http/ext.rb +30 -0
  656. data/lib/datadog/tracing/contrib/http/instrumentation.rb +152 -0
  657. data/lib/datadog/tracing/contrib/http/integration.rb +52 -0
  658. data/lib/datadog/tracing/contrib/http/patcher.rb +30 -0
  659. data/lib/datadog/tracing/contrib/http.rb +45 -0
  660. data/lib/datadog/tracing/contrib/http_annotation_helper.rb +17 -0
  661. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +76 -0
  662. data/lib/datadog/tracing/contrib/httpclient/ext.rb +31 -0
  663. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +132 -0
  664. data/lib/datadog/tracing/contrib/httpclient/integration.rb +48 -0
  665. data/lib/datadog/tracing/contrib/httpclient/patcher.rb +29 -0
  666. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +76 -0
  667. data/lib/datadog/tracing/contrib/httprb/ext.rb +30 -0
  668. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +146 -0
  669. data/lib/datadog/tracing/contrib/httprb/integration.rb +51 -0
  670. data/lib/datadog/tracing/contrib/httprb/patcher.rb +29 -0
  671. data/lib/datadog/tracing/contrib/integration.rb +78 -0
  672. data/lib/datadog/tracing/contrib/kafka/configuration/settings.rb +39 -0
  673. data/lib/datadog/tracing/contrib/kafka/consumer_event.rb +19 -0
  674. data/lib/datadog/tracing/contrib/kafka/consumer_group_event.rb +18 -0
  675. data/lib/datadog/tracing/contrib/kafka/event.rb +53 -0
  676. data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +42 -0
  677. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +49 -0
  678. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +47 -0
  679. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +47 -0
  680. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/join_group.rb +37 -0
  681. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/leave_group.rb +37 -0
  682. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/sync_group.rb +37 -0
  683. data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +41 -0
  684. data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +44 -0
  685. data/lib/datadog/tracing/contrib/kafka/events.rb +48 -0
  686. data/lib/datadog/tracing/contrib/kafka/ext.rb +55 -0
  687. data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +66 -0
  688. data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +66 -0
  689. data/lib/datadog/tracing/contrib/kafka/integration.rb +47 -0
  690. data/lib/datadog/tracing/contrib/kafka/patcher.rb +43 -0
  691. data/lib/datadog/tracing/contrib/karafka/configuration/settings.rb +27 -0
  692. data/lib/datadog/tracing/contrib/karafka/distributed/propagation.rb +48 -0
  693. data/lib/datadog/tracing/contrib/karafka/ext.rb +27 -0
  694. data/lib/datadog/tracing/contrib/karafka/integration.rb +45 -0
  695. data/lib/datadog/tracing/contrib/karafka/monitor.rb +77 -0
  696. data/lib/datadog/tracing/contrib/karafka/patcher.rb +89 -0
  697. data/lib/datadog/tracing/contrib/karafka.rb +37 -0
  698. data/lib/datadog/tracing/contrib/lograge/configuration/settings.rb +24 -0
  699. data/lib/datadog/tracing/contrib/lograge/ext.rb +15 -0
  700. data/lib/datadog/tracing/contrib/lograge/instrumentation.rb +31 -0
  701. data/lib/datadog/tracing/contrib/lograge/integration.rb +50 -0
  702. data/lib/datadog/tracing/contrib/lograge/patcher.rb +46 -0
  703. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +64 -0
  704. data/lib/datadog/tracing/contrib/mongodb/ext.rb +39 -0
  705. data/lib/datadog/tracing/contrib/mongodb/instrumentation.rb +47 -0
  706. data/lib/datadog/tracing/contrib/mongodb/integration.rb +51 -0
  707. data/lib/datadog/tracing/contrib/mongodb/parsers.rb +49 -0
  708. data/lib/datadog/tracing/contrib/mongodb/patcher.rb +34 -0
  709. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +160 -0
  710. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +69 -0
  711. data/lib/datadog/tracing/contrib/mysql2/ext.rb +28 -0
  712. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +109 -0
  713. data/lib/datadog/tracing/contrib/mysql2/integration.rb +43 -0
  714. data/lib/datadog/tracing/contrib/mysql2/patcher.rb +31 -0
  715. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +71 -0
  716. data/lib/datadog/tracing/contrib/opensearch/ext.rb +48 -0
  717. data/lib/datadog/tracing/contrib/opensearch/integration.rb +46 -0
  718. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +144 -0
  719. data/lib/datadog/tracing/contrib/opensearch/quantize.rb +81 -0
  720. data/lib/datadog/tracing/contrib/patchable.rb +109 -0
  721. data/lib/datadog/tracing/contrib/patcher.rb +87 -0
  722. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +69 -0
  723. data/lib/datadog/tracing/contrib/pg/ext.rb +35 -0
  724. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +214 -0
  725. data/lib/datadog/tracing/contrib/pg/integration.rb +43 -0
  726. data/lib/datadog/tracing/contrib/pg/patcher.rb +31 -0
  727. data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +52 -0
  728. data/lib/datadog/tracing/contrib/presto/ext.rb +38 -0
  729. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +138 -0
  730. data/lib/datadog/tracing/contrib/presto/integration.rb +46 -0
  731. data/lib/datadog/tracing/contrib/presto/patcher.rb +25 -0
  732. data/lib/datadog/tracing/contrib/propagation/sql_comment/comment.rb +41 -0
  733. data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +61 -0
  734. data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +32 -0
  735. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +67 -0
  736. data/lib/datadog/tracing/contrib/que/configuration/settings.rb +55 -0
  737. data/lib/datadog/tracing/contrib/que/ext.rb +33 -0
  738. data/lib/datadog/tracing/contrib/que/integration.rb +44 -0
  739. data/lib/datadog/tracing/contrib/que/patcher.rb +26 -0
  740. data/lib/datadog/tracing/contrib/que/tracer.rb +63 -0
  741. data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +47 -0
  742. data/lib/datadog/tracing/contrib/racecar/event.rb +81 -0
  743. data/lib/datadog/tracing/contrib/racecar/events/batch.rb +38 -0
  744. data/lib/datadog/tracing/contrib/racecar/events/consume.rb +35 -0
  745. data/lib/datadog/tracing/contrib/racecar/events/message.rb +38 -0
  746. data/lib/datadog/tracing/contrib/racecar/events.rb +36 -0
  747. data/lib/datadog/tracing/contrib/racecar/ext.rb +33 -0
  748. data/lib/datadog/tracing/contrib/racecar/integration.rb +44 -0
  749. data/lib/datadog/tracing/contrib/racecar/patcher.rb +29 -0
  750. data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +59 -0
  751. data/lib/datadog/tracing/contrib/rack/ext.rb +30 -0
  752. data/lib/datadog/tracing/contrib/rack/header_collection.rb +50 -0
  753. data/lib/datadog/tracing/contrib/rack/header_tagging.rb +63 -0
  754. data/lib/datadog/tracing/contrib/rack/integration.rb +50 -0
  755. data/lib/datadog/tracing/contrib/rack/middlewares.rb +475 -0
  756. data/lib/datadog/tracing/contrib/rack/patcher.rb +119 -0
  757. data/lib/datadog/tracing/contrib/rack/request_queue.rb +49 -0
  758. data/lib/datadog/tracing/contrib/rack/route_inference.rb +53 -0
  759. data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +58 -0
  760. data/lib/datadog/tracing/contrib/rails/auto_instrument_railtie.rb +10 -0
  761. data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +76 -0
  762. data/lib/datadog/tracing/contrib/rails/ext.rb +33 -0
  763. data/lib/datadog/tracing/contrib/rails/framework.rb +148 -0
  764. data/lib/datadog/tracing/contrib/rails/integration.rb +52 -0
  765. data/lib/datadog/tracing/contrib/rails/log_injection.rb +29 -0
  766. data/lib/datadog/tracing/contrib/rails/middlewares.rb +46 -0
  767. data/lib/datadog/tracing/contrib/rails/patcher.rb +98 -0
  768. data/lib/datadog/tracing/contrib/rails/railtie.rb +19 -0
  769. data/lib/datadog/tracing/contrib/rails/runner.rb +117 -0
  770. data/lib/datadog/tracing/contrib/rake/configuration/settings.rb +55 -0
  771. data/lib/datadog/tracing/contrib/rake/ext.rb +27 -0
  772. data/lib/datadog/tracing/contrib/rake/instrumentation.rb +103 -0
  773. data/lib/datadog/tracing/contrib/rake/integration.rb +43 -0
  774. data/lib/datadog/tracing/contrib/rake/patcher.rb +33 -0
  775. data/lib/datadog/tracing/contrib/redis/configuration/resolver.rb +49 -0
  776. data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +57 -0
  777. data/lib/datadog/tracing/contrib/redis/ext.rb +36 -0
  778. data/lib/datadog/tracing/contrib/redis/instrumentation.rb +53 -0
  779. data/lib/datadog/tracing/contrib/redis/integration.rb +80 -0
  780. data/lib/datadog/tracing/contrib/redis/patcher.rb +92 -0
  781. data/lib/datadog/tracing/contrib/redis/quantize.rb +80 -0
  782. data/lib/datadog/tracing/contrib/redis/tags.rb +72 -0
  783. data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +85 -0
  784. data/lib/datadog/tracing/contrib/redis/vendor/LICENSE +20 -0
  785. data/lib/datadog/tracing/contrib/redis/vendor/resolver.rb +160 -0
  786. data/lib/datadog/tracing/contrib/registerable.rb +50 -0
  787. data/lib/datadog/tracing/contrib/registry.rb +52 -0
  788. data/lib/datadog/tracing/contrib/resque/configuration/settings.rb +42 -0
  789. data/lib/datadog/tracing/contrib/resque/ext.rb +22 -0
  790. data/lib/datadog/tracing/contrib/resque/integration.rb +48 -0
  791. data/lib/datadog/tracing/contrib/resque/patcher.rb +29 -0
  792. data/lib/datadog/tracing/contrib/resque/resque_job.rb +106 -0
  793. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +55 -0
  794. data/lib/datadog/tracing/contrib/rest_client/ext.rb +29 -0
  795. data/lib/datadog/tracing/contrib/rest_client/integration.rb +46 -0
  796. data/lib/datadog/tracing/contrib/rest_client/patcher.rb +28 -0
  797. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +137 -0
  798. data/lib/datadog/tracing/contrib/roda/configuration/settings.rb +38 -0
  799. data/lib/datadog/tracing/contrib/roda/ext.rb +19 -0
  800. data/lib/datadog/tracing/contrib/roda/instrumentation.rb +78 -0
  801. data/lib/datadog/tracing/contrib/roda/integration.rb +45 -0
  802. data/lib/datadog/tracing/contrib/roda/patcher.rb +30 -0
  803. data/lib/datadog/tracing/contrib/semantic_logger/configuration/settings.rb +24 -0
  804. data/lib/datadog/tracing/contrib/semantic_logger/ext.rb +15 -0
  805. data/lib/datadog/tracing/contrib/semantic_logger/instrumentation.rb +35 -0
  806. data/lib/datadog/tracing/contrib/semantic_logger/integration.rb +52 -0
  807. data/lib/datadog/tracing/contrib/semantic_logger/patcher.rb +29 -0
  808. data/lib/datadog/tracing/contrib/sequel/configuration/settings.rb +37 -0
  809. data/lib/datadog/tracing/contrib/sequel/database.rb +62 -0
  810. data/lib/datadog/tracing/contrib/sequel/dataset.rb +67 -0
  811. data/lib/datadog/tracing/contrib/sequel/ext.rb +23 -0
  812. data/lib/datadog/tracing/contrib/sequel/integration.rb +43 -0
  813. data/lib/datadog/tracing/contrib/sequel/patcher.rb +37 -0
  814. data/lib/datadog/tracing/contrib/sequel/utils.rb +90 -0
  815. data/lib/datadog/tracing/contrib/shoryuken/configuration/settings.rb +43 -0
  816. data/lib/datadog/tracing/contrib/shoryuken/ext.rb +27 -0
  817. data/lib/datadog/tracing/contrib/shoryuken/integration.rb +44 -0
  818. data/lib/datadog/tracing/contrib/shoryuken/patcher.rb +28 -0
  819. data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +65 -0
  820. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +67 -0
  821. data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +47 -0
  822. data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +49 -0
  823. data/lib/datadog/tracing/contrib/sidekiq/ext.rb +45 -0
  824. data/lib/datadog/tracing/contrib/sidekiq/integration.rb +61 -0
  825. data/lib/datadog/tracing/contrib/sidekiq/patcher.rb +90 -0
  826. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/heartbeat.rb +61 -0
  827. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/job_fetch.rb +36 -0
  828. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/redis_info.rb +34 -0
  829. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/scheduled_poller.rb +57 -0
  830. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/stop.rb +34 -0
  831. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +91 -0
  832. data/lib/datadog/tracing/contrib/sidekiq/utils.rb +44 -0
  833. data/lib/datadog/tracing/contrib/sidekiq.rb +37 -0
  834. data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +46 -0
  835. data/lib/datadog/tracing/contrib/sinatra/env.rb +38 -0
  836. data/lib/datadog/tracing/contrib/sinatra/ext.rb +31 -0
  837. data/lib/datadog/tracing/contrib/sinatra/framework.rb +116 -0
  838. data/lib/datadog/tracing/contrib/sinatra/integration.rb +43 -0
  839. data/lib/datadog/tracing/contrib/sinatra/patcher.rb +75 -0
  840. data/lib/datadog/tracing/contrib/sinatra/tracer.rb +90 -0
  841. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +109 -0
  842. data/lib/datadog/tracing/contrib/sneakers/configuration/settings.rb +43 -0
  843. data/lib/datadog/tracing/contrib/sneakers/ext.rb +27 -0
  844. data/lib/datadog/tracing/contrib/sneakers/integration.rb +44 -0
  845. data/lib/datadog/tracing/contrib/sneakers/patcher.rb +27 -0
  846. data/lib/datadog/tracing/contrib/sneakers/tracer.rb +60 -0
  847. data/lib/datadog/tracing/contrib/span_attribute_schema.rb +97 -0
  848. data/lib/datadog/tracing/contrib/status_range_env_parser.rb +33 -0
  849. data/lib/datadog/tracing/contrib/status_range_matcher.rb +32 -0
  850. data/lib/datadog/tracing/contrib/stripe/configuration/settings.rb +37 -0
  851. data/lib/datadog/tracing/contrib/stripe/ext.rb +27 -0
  852. data/lib/datadog/tracing/contrib/stripe/integration.rb +43 -0
  853. data/lib/datadog/tracing/contrib/stripe/patcher.rb +28 -0
  854. data/lib/datadog/tracing/contrib/stripe/request.rb +68 -0
  855. data/lib/datadog/tracing/contrib/sucker_punch/configuration/settings.rb +39 -0
  856. data/lib/datadog/tracing/contrib/sucker_punch/exception_handler.rb +28 -0
  857. data/lib/datadog/tracing/contrib/sucker_punch/ext.rb +28 -0
  858. data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +104 -0
  859. data/lib/datadog/tracing/contrib/sucker_punch/integration.rb +43 -0
  860. data/lib/datadog/tracing/contrib/sucker_punch/patcher.rb +35 -0
  861. data/lib/datadog/tracing/contrib/support.rb +28 -0
  862. data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +63 -0
  863. data/lib/datadog/tracing/contrib/trilogy/ext.rb +27 -0
  864. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +97 -0
  865. data/lib/datadog/tracing/contrib/trilogy/integration.rb +43 -0
  866. data/lib/datadog/tracing/contrib/trilogy/patcher.rb +31 -0
  867. data/lib/datadog/tracing/contrib/utils/database.rb +31 -0
  868. data/lib/datadog/tracing/contrib/utils/quantization/hash.rb +111 -0
  869. data/lib/datadog/tracing/contrib/utils/quantization/http.rb +179 -0
  870. data/lib/datadog/tracing/contrib.rb +82 -0
  871. data/lib/datadog/tracing/correlation.rb +113 -0
  872. data/lib/datadog/tracing/diagnostics/environment_logger.rb +163 -0
  873. data/lib/datadog/tracing/diagnostics/ext.rb +36 -0
  874. data/lib/datadog/tracing/diagnostics/health.rb +40 -0
  875. data/lib/datadog/tracing/distributed/b3_multi.rb +73 -0
  876. data/lib/datadog/tracing/distributed/b3_single.rb +71 -0
  877. data/lib/datadog/tracing/distributed/baggage.rb +196 -0
  878. data/lib/datadog/tracing/distributed/datadog.rb +201 -0
  879. data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +82 -0
  880. data/lib/datadog/tracing/distributed/fetcher.rb +21 -0
  881. data/lib/datadog/tracing/distributed/helpers.rb +65 -0
  882. data/lib/datadog/tracing/distributed/none.rb +20 -0
  883. data/lib/datadog/tracing/distributed/propagation.rb +187 -0
  884. data/lib/datadog/tracing/distributed/propagation_policy.rb +42 -0
  885. data/lib/datadog/tracing/distributed/trace_context.rb +444 -0
  886. data/lib/datadog/tracing/event.rb +74 -0
  887. data/lib/datadog/tracing/flush.rb +96 -0
  888. data/lib/datadog/tracing/metadata/analytics.rb +26 -0
  889. data/lib/datadog/tracing/metadata/errors.rb +32 -0
  890. data/lib/datadog/tracing/metadata/ext.rb +213 -0
  891. data/lib/datadog/tracing/metadata/metastruct.rb +36 -0
  892. data/lib/datadog/tracing/metadata/metastruct_tagging.rb +42 -0
  893. data/lib/datadog/tracing/metadata/tagging.rb +131 -0
  894. data/lib/datadog/tracing/metadata.rb +22 -0
  895. data/lib/datadog/tracing/pipeline/span_filter.rb +48 -0
  896. data/lib/datadog/tracing/pipeline/span_processor.rb +41 -0
  897. data/lib/datadog/tracing/pipeline.rb +63 -0
  898. data/lib/datadog/tracing/remote.rb +85 -0
  899. data/lib/datadog/tracing/runtime/metrics.rb +17 -0
  900. data/lib/datadog/tracing/sampling/all_sampler.rb +24 -0
  901. data/lib/datadog/tracing/sampling/ext.rb +58 -0
  902. data/lib/datadog/tracing/sampling/matcher.rb +119 -0
  903. data/lib/datadog/tracing/sampling/priority_sampler.rb +160 -0
  904. data/lib/datadog/tracing/sampling/rate_by_key_sampler.rb +87 -0
  905. data/lib/datadog/tracing/sampling/rate_by_service_sampler.rb +63 -0
  906. data/lib/datadog/tracing/sampling/rate_sampler.rb +59 -0
  907. data/lib/datadog/tracing/sampling/rule.rb +86 -0
  908. data/lib/datadog/tracing/sampling/rule_sampler.rb +172 -0
  909. data/lib/datadog/tracing/sampling/sampler.rb +32 -0
  910. data/lib/datadog/tracing/sampling/span/ext.rb +25 -0
  911. data/lib/datadog/tracing/sampling/span/matcher.rb +61 -0
  912. data/lib/datadog/tracing/sampling/span/rule.rb +77 -0
  913. data/lib/datadog/tracing/sampling/span/rule_parser.rb +104 -0
  914. data/lib/datadog/tracing/sampling/span/sampler.rb +70 -0
  915. data/lib/datadog/tracing/span.rb +236 -0
  916. data/lib/datadog/tracing/span_event.rb +161 -0
  917. data/lib/datadog/tracing/span_link.rb +92 -0
  918. data/lib/datadog/tracing/span_operation.rb +561 -0
  919. data/lib/datadog/tracing/sync_writer.rb +71 -0
  920. data/lib/datadog/tracing/trace_digest.rb +190 -0
  921. data/lib/datadog/tracing/trace_operation.rb +556 -0
  922. data/lib/datadog/tracing/trace_segment.rb +227 -0
  923. data/lib/datadog/tracing/tracer.rb +644 -0
  924. data/lib/datadog/tracing/transport/http/api.rb +44 -0
  925. data/lib/datadog/tracing/transport/http/client.rb +59 -0
  926. data/lib/datadog/tracing/transport/http/statistics.rb +47 -0
  927. data/lib/datadog/tracing/transport/http/traces.rb +155 -0
  928. data/lib/datadog/tracing/transport/http.rb +44 -0
  929. data/lib/datadog/tracing/transport/io/client.rb +90 -0
  930. data/lib/datadog/tracing/transport/io/response.rb +27 -0
  931. data/lib/datadog/tracing/transport/io/traces.rb +101 -0
  932. data/lib/datadog/tracing/transport/io.rb +30 -0
  933. data/lib/datadog/tracing/transport/serializable_trace.rb +155 -0
  934. data/lib/datadog/tracing/transport/statistics.rb +77 -0
  935. data/lib/datadog/tracing/transport/trace_formatter.rb +276 -0
  936. data/lib/datadog/tracing/transport/traces.rb +258 -0
  937. data/lib/datadog/tracing/utils.rb +99 -0
  938. data/lib/datadog/tracing/workers/trace_writer.rb +199 -0
  939. data/lib/datadog/tracing/workers.rb +126 -0
  940. data/lib/datadog/tracing/writer.rb +190 -0
  941. data/lib/datadog/tracing.rb +214 -0
  942. data/lib/datadog/version.rb +27 -0
  943. data/lib/datadog.rb +20 -0
  944. metadata +1074 -0
@@ -0,0 +1,998 @@
1
+ #include "heap_recorder.h"
2
+ #include "ruby/st.h"
3
+ #include "ruby_helpers.h"
4
+ #include "collectors_stack.h"
5
+ #include "libdatadog_helpers.h"
6
+ #include "time_helpers.h"
7
+
8
+ // Note on calloc vs ruby_xcalloc use:
9
+ // * Whenever we're allocating memory after being called by the Ruby VM in a "regular" situation (e.g. initializer)
10
+ // we should use `ruby_xcalloc` to give the VM visibility into what we're doing + give it a chance to manage GC
11
+ // * BUT, when we're being called during a sample, being in the middle of an object allocation is a very special
12
+ // situation for the VM to be in, and we've found the hard way (e.g. https://bugs.ruby-lang.org/issues/20629 and
13
+ // https://github.com/DataDog/dd-trace-rb/pull/4240 ) that it can be easy to do things the VM didn't expect.
14
+ // * Thus, out of caution and to avoid future potential issues such as the ones above, whenever we allocate memory
15
+ // during **sampling** we use `calloc` instead of `ruby_xcalloc`. Note that we've never seen issues from using
16
+ // `ruby_xcalloc` at any time, so this is a **precaution** not a "we've seen it break". But it seems a harmless
17
+ // one to use.
18
+ // This applies to both heap_recorder.c and collectors_thread_context.c
19
+
20
+ // Minimum age (in GC generations) of heap objects we want to include in heap
21
+ // recorder iterations. Object with age 0 represent objects that have yet to undergo
22
+ // a GC and, thus, may just be noise/trash at instant of iteration and are usually not
23
+ // relevant for heap profiles as the great majority should be trivially reclaimed
24
+ // during the next GC.
25
+ #define ITERATION_MIN_AGE 1
26
+ // Copied from https://github.com/ruby/ruby/blob/15135030e5808d527325feaaaf04caeb1b44f8b5/gc/default.c#L725C1-L725C27
27
+ // to align with Ruby's GC definition of what constitutes an old object which are only
28
+ // supposed to be reclaimed in major GCs.
29
+ #define OLD_AGE 3
30
+ // Wait at least 2 seconds before asking heap recorder to explicitly update itself. Heap recorder
31
+ // data will only materialize at profile serialization time but updating often helps keep our
32
+ // heap tracking data small since every GC should get rid of a bunch of temporary objects. The
33
+ // more we clean up before profile flush, the less work we'll have to do all-at-once when preparing
34
+ // to flush heap data and holding the GVL which should hopefully help with reducing latency impact.
35
+ #define MIN_TIME_BETWEEN_HEAP_RECORDER_UPDATES_NS SECONDS_AS_NS(2)
36
+
37
+ // A compact representation of a stacktrace frame for a heap allocation.
38
+ typedef struct {
39
+ ddog_prof_ManagedStringId name;
40
+ ddog_prof_ManagedStringId filename;
41
+ int32_t line;
42
+ } heap_frame;
43
+
44
+ // We use memcmp/st_hash below to compare/hash an entire array of heap_frames, so want to make sure no padding is added
45
+ // We could define the structure to be packed, but that seems even weirder across compilers, and this seems more portable?
46
+ _Static_assert(
47
+ sizeof(heap_frame) == sizeof(ddog_prof_ManagedStringId) * 2 + sizeof(int32_t),
48
+ "Size of heap_frame does not match the sum of its members. Padding detected."
49
+ );
50
+
51
+ // A compact representation of a stacktrace for a heap allocation.
52
+ // Used to dedup heap allocation stacktraces across multiple objects sharing the same allocation location.
53
+ typedef struct {
54
+ // How many objects are currently tracked in object_records recorder for this heap record.
55
+ uint32_t num_tracked_objects;
56
+
57
+ uint16_t frames_len;
58
+ heap_frame frames[];
59
+ } heap_record;
60
+ static heap_record* heap_record_new(heap_recorder*, ddog_prof_Slice_Location);
61
+ static void heap_record_free(heap_recorder*, heap_record*);
62
+
63
+ #if MAX_FRAMES_LIMIT > UINT16_MAX
64
+ #error Frames len type not compatible with MAX_FRAMES_LIMIT
65
+ #endif
66
+
67
+ static int heap_record_cmp_st(st_data_t, st_data_t);
68
+ static st_index_t heap_record_hash_st(st_data_t);
69
+ static const struct st_hash_type st_hash_type_heap_record = { .compare = heap_record_cmp_st, .hash = heap_record_hash_st };
70
+
71
+ // An object record is used for storing data about currently tracked live objects
72
+ typedef struct {
73
+ long obj_id;
74
+ heap_record *heap_record;
75
+ live_object_data object_data;
76
+ } object_record;
77
+ static object_record* object_record_new(long, heap_record*, live_object_data);
78
+ static void object_record_free(heap_recorder*, object_record*);
79
+ static VALUE object_record_inspect(heap_recorder*, object_record*);
80
+ static object_record SKIPPED_RECORD = {0};
81
+
82
+ struct heap_recorder {
83
+ // Config
84
+ // Whether the recorder should try to determine approximate sizes for tracked objects.
85
+ bool size_enabled;
86
+ uint sample_rate;
87
+
88
+ // Map[key: heap_record*, record: nothing] (This is a set, basically)
89
+ // NOTE: This table is currently only protected by the GVL since we never interact with it
90
+ // outside the GVL.
91
+ // NOTE: This table has ownership of its heap_records.
92
+ //
93
+ // This is a cpu/memory trade-off: Maintaining the "heap_records" map means we spend extra CPU when sampling as we need
94
+ // to do de-duplication, but we reduce the memory footprint of the heap profiler.
95
+ // In the future, it may be worth revisiting if we can move this inside libdatadog: if libdatadog was able to track
96
+ // entire stacks for us, then we wouldn't need to do it on the Ruby side.
97
+ st_table *heap_records;
98
+
99
+ // Map[obj_id: long, record: object_record*]
100
+ // NOTE: This table is currently only protected by the GVL since we never interact with it
101
+ // outside the GVL.
102
+ // NOTE: This table has ownership of its object_records. The keys are longs and so are
103
+ // passed as values.
104
+ //
105
+ // TODO: @ivoanjo We've evolved to actually never need to look up on object_records (we only insert and iterate),
106
+ // so right now this seems to be just a really really fancy self-resizing list/set.
107
+ // If we replace this with a list, we could record the latest id and compare it when inserting to make sure our
108
+ // assumption of ids never reused + always increasing always holds. (This as an alternative to checking for duplicates)
109
+ st_table *object_records;
110
+
111
+ // Map[obj_id: long, record: object_record*]
112
+ // NOTE: This is a snapshot of object_records built ahead of a iteration. Outside of an
113
+ // iteration context, this table will be NULL. During an iteration, there will be no
114
+ // mutation of the data so iteration can occur without acquiring a lock.
115
+ // NOTE: Contrary to object_records, this table has no ownership of its data.
116
+ st_table *object_records_snapshot;
117
+ // Are we currently updating or not?
118
+ bool updating;
119
+ // The GC gen/epoch/count in which we are updating (or last updated if not currently updating).
120
+ //
121
+ // This enables us to calculate the age of objects considered in the update by comparing it
122
+ // against an object's alloc_gen.
123
+ size_t update_gen;
124
+ // Whether the current update (or last update if not currently updating) is including old
125
+ // objects or not.
126
+ bool update_include_old;
127
+ // When did we do the last update of heap recorder?
128
+ long last_update_ns;
129
+
130
+ // Data for a heap recording that was started but not yet ended
131
+ object_record *active_recording;
132
+
133
+ // Reusable arrays, implementing a flyweight pattern for things like iteration
134
+ #define REUSABLE_LOCATIONS_SIZE MAX_FRAMES_LIMIT
135
+ ddog_prof_Location *reusable_locations;
136
+
137
+ #define REUSABLE_FRAME_DETAILS_SIZE (2 * MAX_FRAMES_LIMIT) // because it'll be used for both function names AND file names)
138
+ ddog_prof_ManagedStringId *reusable_ids;
139
+ ddog_CharSlice *reusable_char_slices;
140
+
141
+ // Sampling state
142
+ uint num_recordings_skipped;
143
+
144
+ ddog_prof_ManagedStringStorage string_storage;
145
+
146
+ struct stats_last_update {
147
+ size_t objects_alive;
148
+ size_t objects_dead;
149
+ size_t objects_skipped;
150
+ size_t objects_frozen;
151
+ } stats_last_update;
152
+
153
+ struct stats_lifetime {
154
+ unsigned long updates_successful;
155
+ unsigned long updates_skipped_concurrent;
156
+ unsigned long updates_skipped_gcgen;
157
+ unsigned long updates_skipped_time;
158
+
159
+ double ewma_young_objects_alive;
160
+ double ewma_young_objects_dead;
161
+ double ewma_young_objects_skipped; // Note: Here "young" refers to the young update; objects skipped includes non-young objects
162
+
163
+ double ewma_objects_alive;
164
+ double ewma_objects_dead;
165
+ double ewma_objects_skipped;
166
+ } stats_lifetime;
167
+ };
168
+
169
+ typedef struct {
170
+ heap_recorder *heap_recorder;
171
+ ddog_prof_Slice_Location locations;
172
+ } end_heap_allocation_args;
173
+
174
+ static heap_record* get_or_create_heap_record(heap_recorder*, ddog_prof_Slice_Location);
175
+ static void cleanup_heap_record_if_unused(heap_recorder*, heap_record*);
176
+ static void on_committed_object_record_cleanup(heap_recorder *heap_recorder, object_record *record);
177
+ static int st_heap_record_entry_free(st_data_t, st_data_t, st_data_t);
178
+ static int st_object_record_entry_free(st_data_t, st_data_t, st_data_t);
179
+ static int st_object_record_update(st_data_t, st_data_t, st_data_t);
180
+ static int st_object_records_iterate(st_data_t, st_data_t, st_data_t);
181
+ static int st_object_records_debug(st_data_t key, st_data_t value, st_data_t extra);
182
+ static int update_object_record_entry(st_data_t*, st_data_t*, st_data_t, int);
183
+ static void commit_recording(heap_recorder *, heap_record *, object_record *active_recording);
184
+ static VALUE end_heap_allocation_recording(VALUE end_heap_allocation_args);
185
+ static void heap_recorder_update(heap_recorder *heap_recorder, bool full_update);
186
+ static inline double ewma_stat(double previous, double current);
187
+ static void unintern_or_raise(heap_recorder *, ddog_prof_ManagedStringId);
188
+ static void unintern_all_or_raise(heap_recorder *recorder, ddog_prof_Slice_ManagedStringId ids);
189
+ static VALUE get_ruby_string_or_raise(heap_recorder*, ddog_prof_ManagedStringId);
190
+
191
+ // ==========================
192
+ // Heap Recorder External API
193
+ //
194
+ // WARN: All these APIs should support receiving a NULL heap_recorder, resulting in a noop.
195
+ //
196
+ // WARN: Except for ::heap_recorder_for_each_live_object, we always assume interaction with these APIs
197
+ // happens under the GVL.
198
+ //
199
+ // ==========================
200
+ heap_recorder* heap_recorder_new(ddog_prof_ManagedStringStorage string_storage) {
201
+ heap_recorder *recorder = ruby_xcalloc(1, sizeof(heap_recorder));
202
+
203
+ recorder->heap_records = st_init_table(&st_hash_type_heap_record);
204
+ recorder->object_records = st_init_numtable();
205
+ recorder->object_records_snapshot = NULL;
206
+ recorder->reusable_locations = ruby_xcalloc(REUSABLE_LOCATIONS_SIZE, sizeof(ddog_prof_Location));
207
+ recorder->reusable_ids = ruby_xcalloc(REUSABLE_FRAME_DETAILS_SIZE, sizeof(ddog_prof_ManagedStringId));
208
+ recorder->reusable_char_slices = ruby_xcalloc(REUSABLE_FRAME_DETAILS_SIZE, sizeof(ddog_CharSlice));
209
+ recorder->active_recording = NULL;
210
+ recorder->size_enabled = true;
211
+ recorder->sample_rate = 1; // By default do no sampling on top of what allocation profiling already does
212
+ recorder->string_storage = string_storage;
213
+
214
+ return recorder;
215
+ }
216
+
217
+ void heap_recorder_free(heap_recorder *heap_recorder) {
218
+ if (heap_recorder == NULL) {
219
+ return;
220
+ }
221
+
222
+ if (heap_recorder->object_records_snapshot != NULL) {
223
+ // if there's an unfinished iteration, clean it up now
224
+ // before we clean up any other state it might depend on
225
+ heap_recorder_finish_iteration(heap_recorder);
226
+ }
227
+
228
+ // Clean-up all object records
229
+ st_foreach(heap_recorder->object_records, st_object_record_entry_free, (st_data_t) heap_recorder);
230
+ st_free_table(heap_recorder->object_records);
231
+
232
+ // Clean-up all heap records (this includes those only referred to by queued_samples)
233
+ st_foreach(heap_recorder->heap_records, st_heap_record_entry_free, (st_data_t) heap_recorder);
234
+ st_free_table(heap_recorder->heap_records);
235
+
236
+ if (heap_recorder->active_recording != NULL && heap_recorder->active_recording != &SKIPPED_RECORD) {
237
+ // If there's a partial object record, clean it up as well
238
+ object_record_free(heap_recorder, heap_recorder->active_recording);
239
+ }
240
+
241
+ ruby_xfree(heap_recorder->reusable_locations);
242
+ ruby_xfree(heap_recorder->reusable_ids);
243
+ ruby_xfree(heap_recorder->reusable_char_slices);
244
+
245
+ ruby_xfree(heap_recorder);
246
+ }
247
+
248
+ void heap_recorder_set_size_enabled(heap_recorder *heap_recorder, bool size_enabled) {
249
+ if (heap_recorder == NULL) {
250
+ return;
251
+ }
252
+
253
+ heap_recorder->size_enabled = size_enabled;
254
+ }
255
+
256
+ void heap_recorder_set_sample_rate(heap_recorder *heap_recorder, int sample_rate) {
257
+ if (heap_recorder == NULL) {
258
+ return;
259
+ }
260
+
261
+ if (sample_rate <= 0) {
262
+ rb_raise(rb_eArgError, "Heap sample rate must be a positive integer value but was %d", sample_rate);
263
+ }
264
+
265
+ heap_recorder->sample_rate = sample_rate;
266
+ heap_recorder->num_recordings_skipped = 0;
267
+ }
268
+
269
+ // WARN: Assumes this gets called before profiler is reinitialized on the fork
270
+ void heap_recorder_after_fork(heap_recorder *heap_recorder) {
271
+ if (heap_recorder == NULL) {
272
+ return;
273
+ }
274
+
275
+ // When forking, the child process gets a copy of the entire state of the parent process, minus
276
+ // threads.
277
+ //
278
+ // This means anything the heap recorder is tracking will still be alive after the fork and
279
+ // should thus be kept. Because this heap recorder implementation does not rely on free
280
+ // tracepoints to track liveness, any frees that happen until we fully reinitialize, will
281
+ // simply be noticed on next heap_recorder_prepare_iteration.
282
+ //
283
+ // There is one small caveat though: fork only preserves one thread and in a Ruby app, that
284
+ // will be the thread holding on to the GVL. Since we support iteration on the heap recorder
285
+ // outside of the GVL, any state specific to that interaction may be inconsistent after fork
286
+ // (e.g. an acquired lock for thread safety). Iteration operates on object_records_snapshot
287
+ // though and that one will be updated on next heap_recorder_prepare_iteration so we really
288
+ // only need to finish any iteration that might have been left unfinished.
289
+ if (heap_recorder->object_records_snapshot != NULL) {
290
+ heap_recorder_finish_iteration(heap_recorder);
291
+ }
292
+
293
+ // Clear lifetime stats since this is essentially a new heap recorder
294
+ heap_recorder->stats_lifetime = (struct stats_lifetime) {0};
295
+ }
296
+
297
+ void start_heap_allocation_recording(heap_recorder *heap_recorder, VALUE new_obj, unsigned int weight, ddog_CharSlice alloc_class) {
298
+ if (heap_recorder == NULL) {
299
+ return;
300
+ }
301
+
302
+ if (heap_recorder->active_recording != NULL) {
303
+ rb_raise(rb_eRuntimeError, "Detected consecutive heap allocation recording starts without end.");
304
+ }
305
+
306
+ if (++heap_recorder->num_recordings_skipped < heap_recorder->sample_rate ||
307
+ #ifdef NO_IMEMO_OBJECT_ID
308
+ // On Ruby 3.5, we can't ask the object_id from IMEMOs (https://github.com/ruby/ruby/pull/13347)
309
+ RB_BUILTIN_TYPE(new_obj) == RUBY_T_IMEMO
310
+ #else
311
+ false
312
+ #endif
313
+ // If we got really unlucky and an allocation showed up during an update (because it triggered an allocation
314
+ // directly OR because the GVL got released in the middle of an update), let's skip this sample as well.
315
+ // See notes on `heap_recorder_update` for details.
316
+ || heap_recorder->updating
317
+ ) {
318
+ heap_recorder->active_recording = &SKIPPED_RECORD;
319
+ return;
320
+ }
321
+
322
+ heap_recorder->num_recordings_skipped = 0;
323
+
324
+ VALUE ruby_obj_id = rb_obj_id(new_obj);
325
+ if (!FIXNUM_P(ruby_obj_id)) {
326
+ rb_raise(rb_eRuntimeError, "Detected a bignum object id. These are not supported by heap profiling.");
327
+ }
328
+
329
+ heap_recorder->active_recording = object_record_new(
330
+ FIX2LONG(ruby_obj_id),
331
+ NULL,
332
+ (live_object_data) {
333
+ .weight = weight * heap_recorder->sample_rate,
334
+ .class = intern_or_raise(heap_recorder->string_storage, alloc_class),
335
+ .alloc_gen = rb_gc_count(),
336
+ }
337
+ );
338
+ }
339
+
340
+ // end_heap_allocation_recording_with_rb_protect gets called while the stack_recorder is holding one of the profile
341
+ // locks. To enable us to correctly unlock the profile on exception, we wrap the call to end_heap_allocation_recording
342
+ // with an rb_protect.
343
+ __attribute__((warn_unused_result))
344
+ int end_heap_allocation_recording_with_rb_protect(heap_recorder *heap_recorder, ddog_prof_Slice_Location locations) {
345
+ if (heap_recorder == NULL) {
346
+ return 0;
347
+ }
348
+ if (heap_recorder->active_recording == &SKIPPED_RECORD) {
349
+ // Short circuit, in this case there's nothing to be done
350
+ heap_recorder->active_recording = NULL;
351
+ return 0;
352
+ }
353
+
354
+
355
+ int exception_state;
356
+ end_heap_allocation_args args = {
357
+ .heap_recorder = heap_recorder,
358
+ .locations = locations,
359
+ };
360
+ rb_protect(end_heap_allocation_recording, (VALUE) &args, &exception_state);
361
+ return exception_state;
362
+ }
363
+
364
+ static VALUE end_heap_allocation_recording(VALUE protect_args) {
365
+ end_heap_allocation_args *args = (end_heap_allocation_args *) protect_args;
366
+
367
+ heap_recorder *heap_recorder = args->heap_recorder;
368
+ ddog_prof_Slice_Location locations = args->locations;
369
+
370
+ object_record *active_recording = heap_recorder->active_recording;
371
+
372
+ if (active_recording == NULL) {
373
+ // Recording ended without having been started?
374
+ rb_raise(rb_eRuntimeError, "Ended a heap recording that was not started");
375
+ }
376
+ // From now on, mark the global active recording as invalid so we can short-circuit at any point
377
+ // and not end up with a still active recording. the local active_recording still holds the
378
+ // data required for committing though.
379
+ heap_recorder->active_recording = NULL;
380
+
381
+ if (active_recording == &SKIPPED_RECORD) { // special marker when we decided to skip due to sampling
382
+ // Note: Remember to update the short circuit in end_heap_allocation_recording_with_rb_protect if this logic changes
383
+ return Qnil;
384
+ }
385
+
386
+ heap_record *heap_record = get_or_create_heap_record(heap_recorder, locations);
387
+
388
+ // And then commit the new allocation.
389
+ commit_recording(heap_recorder, heap_record, active_recording);
390
+
391
+ return Qnil;
392
+ }
393
+
394
+ void heap_recorder_update_young_objects(heap_recorder *heap_recorder) {
395
+ if (heap_recorder == NULL) {
396
+ return;
397
+ }
398
+
399
+ heap_recorder_update(heap_recorder, /* full_update: */ false);
400
+ }
401
+
402
+ // NOTE: This function needs and assumes it gets called with the GVL being held.
403
+ // But importantly **some of the operations inside `st_object_record_update` may cause a thread switch**,
404
+ // so we can't assume a single update happens in a single "atomic" step -- other threads may get some running time
405
+ // in the meanwhile.
406
+ static void heap_recorder_update(heap_recorder *heap_recorder, bool full_update) {
407
+ if (heap_recorder->updating) {
408
+ if (full_update) {
409
+ // There's another thread that's already doing an update :(
410
+ //
411
+ // Because there's a lock on the `StackRecorder` (see @no_concurrent_serialize_mutex) then it's not possible that
412
+ // the other update is a full update.
413
+ // Thus we expect is happening is that the GVL got released by the other thread in the middle of a non-full update
414
+ // and the scheduler thread decided now was a great time to serialize the profile.
415
+ //
416
+ // So, let's yield the time on the current thread until Ruby goes back to the other thread doing the update and
417
+ // it finishes cleanly.
418
+ while (heap_recorder->updating) { rb_thread_schedule(); }
419
+ } else {
420
+ // Non-full updates are optional, so let's walk away
421
+ heap_recorder->stats_lifetime.updates_skipped_concurrent++;
422
+ return;
423
+ }
424
+ }
425
+
426
+ if (heap_recorder->object_records_snapshot != NULL) {
427
+ // While serialization is happening, it runs without the GVL and uses the object_records_snapshot.
428
+ // Although we iterate on a snapshot of object_records, these records point to other data that has not been
429
+ // snapshotted for efficiency reasons (e.g. heap_records). Since updating may invalidate
430
+ // some of that non-snapshotted data, let's refrain from doing updates during iteration. This also enforces the
431
+ // semantic that iteration will operate as a point-in-time snapshot.
432
+ return;
433
+ }
434
+
435
+ size_t current_gc_gen = rb_gc_count();
436
+ long now_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE);
437
+
438
+ if (!full_update) {
439
+ if (current_gc_gen == heap_recorder->update_gen) {
440
+ // Are we still in the same GC gen as last update? If so, skip updating since things should not have
441
+ // changed significantly since last time.
442
+ // NOTE: This is mostly a performance decision. I suppose some objects may be cleaned up in intermediate
443
+ // GC steps and sizes may change. But because we have to iterate through all our tracked
444
+ // object records to do an update, let's wait until all steps for a particular GC generation
445
+ // have finished to do so. We may revisit this once we have a better liveness checking mechanism.
446
+ heap_recorder->stats_lifetime.updates_skipped_gcgen++;
447
+ return;
448
+ }
449
+
450
+ if (now_ns > 0 && (now_ns - heap_recorder->last_update_ns) < MIN_TIME_BETWEEN_HEAP_RECORDER_UPDATES_NS) {
451
+ // We did an update not too long ago. Let's skip this one to avoid over-taxing the system.
452
+ heap_recorder->stats_lifetime.updates_skipped_time++;
453
+ return;
454
+ }
455
+ }
456
+
457
+ heap_recorder->updating = true;
458
+ // Reset last update stats, we'll be building them from scratch during the st_foreach call below
459
+ heap_recorder->stats_last_update = (struct stats_last_update) {0};
460
+
461
+ heap_recorder->update_gen = current_gc_gen;
462
+ heap_recorder->update_include_old = full_update;
463
+
464
+ st_foreach(heap_recorder->object_records, st_object_record_update, (st_data_t) heap_recorder);
465
+
466
+ heap_recorder->last_update_ns = now_ns;
467
+ heap_recorder->stats_lifetime.updates_successful++;
468
+
469
+ // Lifetime stats updating
470
+ if (!full_update) {
471
+ heap_recorder->stats_lifetime.ewma_young_objects_alive = ewma_stat(heap_recorder->stats_lifetime.ewma_young_objects_alive, heap_recorder->stats_last_update.objects_alive);
472
+ heap_recorder->stats_lifetime.ewma_young_objects_dead = ewma_stat(heap_recorder->stats_lifetime.ewma_young_objects_dead, heap_recorder->stats_last_update.objects_dead);
473
+ heap_recorder->stats_lifetime.ewma_young_objects_skipped = ewma_stat(heap_recorder->stats_lifetime.ewma_young_objects_skipped, heap_recorder->stats_last_update.objects_skipped);
474
+ } else {
475
+ heap_recorder->stats_lifetime.ewma_objects_alive = ewma_stat(heap_recorder->stats_lifetime.ewma_objects_alive, heap_recorder->stats_last_update.objects_alive);
476
+ heap_recorder->stats_lifetime.ewma_objects_dead = ewma_stat(heap_recorder->stats_lifetime.ewma_objects_dead, heap_recorder->stats_last_update.objects_dead);
477
+ heap_recorder->stats_lifetime.ewma_objects_skipped = ewma_stat(heap_recorder->stats_lifetime.ewma_objects_skipped, heap_recorder->stats_last_update.objects_skipped);
478
+ }
479
+
480
+ heap_recorder->updating = false;
481
+ }
482
+
483
+ void heap_recorder_prepare_iteration(heap_recorder *heap_recorder) {
484
+ if (heap_recorder == NULL) {
485
+ return;
486
+ }
487
+
488
+ if (heap_recorder->object_records_snapshot != NULL) {
489
+ // we could trivially handle this but we raise to highlight and catch unexpected usages.
490
+ rb_raise(rb_eRuntimeError, "New heap recorder iteration prepared without the previous one having been finished.");
491
+ }
492
+
493
+ heap_recorder_update(heap_recorder, /* full_update: */ true);
494
+
495
+ heap_recorder->object_records_snapshot = st_copy(heap_recorder->object_records);
496
+ if (heap_recorder->object_records_snapshot == NULL) {
497
+ rb_raise(rb_eRuntimeError, "Failed to create heap snapshot.");
498
+ }
499
+ }
500
+
501
+ void heap_recorder_finish_iteration(heap_recorder *heap_recorder) {
502
+ if (heap_recorder == NULL) {
503
+ return;
504
+ }
505
+
506
+ if (heap_recorder->object_records_snapshot == NULL) {
507
+ // we could trivially handle this but we raise to highlight and catch unexpected usages.
508
+ rb_raise(rb_eRuntimeError, "Heap recorder iteration finished without having been prepared.");
509
+ }
510
+
511
+ st_free_table(heap_recorder->object_records_snapshot);
512
+ heap_recorder->object_records_snapshot = NULL;
513
+ }
514
+
515
+ // Internal data we need while performing iteration over live objects.
516
+ typedef struct {
517
+ // The callback we need to call for each object.
518
+ bool (*for_each_callback)(heap_recorder_iteration_data stack_data, void *extra_arg);
519
+ // The extra arg to pass as the second parameter to the callback.
520
+ void *for_each_callback_extra_arg;
521
+ // A reference to the heap recorder so we can access extra stuff like reusable_locations.
522
+ heap_recorder *heap_recorder;
523
+ } iteration_context;
524
+
525
+ // WARN: Assume iterations can run without the GVL for performance reasons. Do not raise, allocate or
526
+ // do NoGVL-unsafe interactions with the Ruby runtime. Any such interactions should be done during
527
+ // heap_recorder_prepare_iteration or heap_recorder_finish_iteration.
528
+ bool heap_recorder_for_each_live_object(
529
+ heap_recorder *heap_recorder,
530
+ bool (*for_each_callback)(heap_recorder_iteration_data stack_data, void *extra_arg),
531
+ void *for_each_callback_extra_arg) {
532
+ if (heap_recorder == NULL) {
533
+ return true;
534
+ }
535
+
536
+ if (heap_recorder->object_records_snapshot == NULL) {
537
+ return false;
538
+ }
539
+
540
+ iteration_context context;
541
+ context.for_each_callback = for_each_callback;
542
+ context.for_each_callback_extra_arg = for_each_callback_extra_arg;
543
+ context.heap_recorder = heap_recorder;
544
+ st_foreach(heap_recorder->object_records_snapshot, st_object_records_iterate, (st_data_t) &context);
545
+ return true;
546
+ }
547
+
548
+ VALUE heap_recorder_state_snapshot(heap_recorder *heap_recorder) {
549
+ VALUE arguments[] = {
550
+ ID2SYM(rb_intern("num_object_records")), /* => */ LONG2NUM(heap_recorder->object_records->num_entries),
551
+ ID2SYM(rb_intern("num_heap_records")), /* => */ LONG2NUM(heap_recorder->heap_records->num_entries),
552
+
553
+ // Stats as of last update
554
+ ID2SYM(rb_intern("last_update_objects_alive")), /* => */ LONG2NUM(heap_recorder->stats_last_update.objects_alive),
555
+ ID2SYM(rb_intern("last_update_objects_dead")), /* => */ LONG2NUM(heap_recorder->stats_last_update.objects_dead),
556
+ ID2SYM(rb_intern("last_update_objects_skipped")), /* => */ LONG2NUM(heap_recorder->stats_last_update.objects_skipped),
557
+ ID2SYM(rb_intern("last_update_objects_frozen")), /* => */ LONG2NUM(heap_recorder->stats_last_update.objects_frozen),
558
+
559
+ // Lifetime stats
560
+ ID2SYM(rb_intern("lifetime_updates_successful")), /* => */ LONG2NUM(heap_recorder->stats_lifetime.updates_successful),
561
+ ID2SYM(rb_intern("lifetime_updates_skipped_concurrent")), /* => */ LONG2NUM(heap_recorder->stats_lifetime.updates_skipped_concurrent),
562
+ ID2SYM(rb_intern("lifetime_updates_skipped_gcgen")), /* => */ LONG2NUM(heap_recorder->stats_lifetime.updates_skipped_gcgen),
563
+ ID2SYM(rb_intern("lifetime_updates_skipped_time")), /* => */ LONG2NUM(heap_recorder->stats_lifetime.updates_skipped_time),
564
+ ID2SYM(rb_intern("lifetime_ewma_young_objects_alive")), /* => */ DBL2NUM(heap_recorder->stats_lifetime.ewma_young_objects_alive),
565
+ ID2SYM(rb_intern("lifetime_ewma_young_objects_dead")), /* => */ DBL2NUM(heap_recorder->stats_lifetime.ewma_young_objects_dead),
566
+ // Note: Here "young" refers to the young update; objects skipped includes non-young objects
567
+ ID2SYM(rb_intern("lifetime_ewma_young_objects_skipped")), /* => */ DBL2NUM(heap_recorder->stats_lifetime.ewma_young_objects_skipped),
568
+ ID2SYM(rb_intern("lifetime_ewma_objects_alive")), /* => */ DBL2NUM(heap_recorder->stats_lifetime.ewma_objects_alive),
569
+ ID2SYM(rb_intern("lifetime_ewma_objects_dead")), /* => */ DBL2NUM(heap_recorder->stats_lifetime.ewma_objects_dead),
570
+ ID2SYM(rb_intern("lifetime_ewma_objects_skipped")), /* => */ DBL2NUM(heap_recorder->stats_lifetime.ewma_objects_skipped),
571
+ };
572
+ VALUE hash = rb_hash_new();
573
+ for (long unsigned int i = 0; i < VALUE_COUNT(arguments); i += 2) rb_hash_aset(hash, arguments[i], arguments[i+1]);
574
+ return hash;
575
+ }
576
+
577
+ typedef struct {
578
+ heap_recorder *recorder;
579
+ VALUE debug_str;
580
+ } debug_context;
581
+
582
+ VALUE heap_recorder_testonly_debug(heap_recorder *heap_recorder) {
583
+ if (heap_recorder == NULL) {
584
+ rb_raise(rb_eArgError, "heap_recorder is NULL");
585
+ }
586
+
587
+ VALUE debug_str = rb_str_new2("object records:\n");
588
+ debug_context context = (debug_context) {.recorder = heap_recorder, .debug_str = debug_str};
589
+ st_foreach(heap_recorder->object_records, st_object_records_debug, (st_data_t) &context);
590
+
591
+ rb_str_catf(debug_str, "state snapshot: %"PRIsVALUE"\n------\n", heap_recorder_state_snapshot(heap_recorder));
592
+
593
+ return debug_str;
594
+ }
595
+
596
+ // ==========================
597
+ // Heap Recorder Internal API
598
+ // ==========================
599
+ static int st_heap_record_entry_free(st_data_t key, DDTRACE_UNUSED st_data_t value, st_data_t extra_arg) {
600
+ heap_recorder *recorder = (heap_recorder *) extra_arg;
601
+ heap_record_free(recorder, (heap_record *) key);
602
+ return ST_DELETE;
603
+ }
604
+
605
+ static int st_object_record_entry_free(DDTRACE_UNUSED st_data_t key, st_data_t value, st_data_t extra_arg) {
606
+ heap_recorder *recorder = (heap_recorder *) extra_arg;
607
+ object_record_free(recorder, (object_record *) value);
608
+ return ST_DELETE;
609
+ }
610
+
611
+ // NOTE: Some operations inside this function can cause the GVL to be released! Plan accordingly.
612
+ static int st_object_record_update(st_data_t key, st_data_t value, st_data_t extra_arg) {
613
+ long obj_id = (long) key;
614
+ object_record *record = (object_record*) value;
615
+ heap_recorder *recorder = (heap_recorder*) extra_arg;
616
+
617
+ VALUE ref;
618
+
619
+ size_t update_gen = recorder->update_gen;
620
+ size_t alloc_gen = record->object_data.alloc_gen;
621
+ // Guard against potential overflows given unsigned types here.
622
+ record->object_data.gen_age = alloc_gen < update_gen ? update_gen - alloc_gen : 0;
623
+
624
+ if (record->object_data.gen_age == 0) {
625
+ // Objects that belong to the current GC gen have not had a chance to be cleaned up yet
626
+ // and won't show up in the iteration anyway so no point in checking their liveness/sizes.
627
+ recorder->stats_last_update.objects_skipped++;
628
+ return ST_CONTINUE;
629
+ }
630
+
631
+ if (!recorder->update_include_old && record->object_data.gen_age >= OLD_AGE) {
632
+ // The current update is not including old objects but this record is for an old object, skip its update.
633
+ recorder->stats_last_update.objects_skipped++;
634
+ return ST_CONTINUE;
635
+ }
636
+
637
+ if (!ruby_ref_from_id(LONG2NUM(obj_id), &ref)) { // Note: This function call can cause the GVL to be released
638
+ // Id no longer associated with a valid ref. Need to delete this object record!
639
+ on_committed_object_record_cleanup(recorder, record);
640
+ recorder->stats_last_update.objects_dead++;
641
+ return ST_DELETE;
642
+ }
643
+
644
+ // If we got this far, then we found a valid live object for the tracked id.
645
+
646
+ if (
647
+ recorder->size_enabled &&
648
+ recorder->update_include_old && // We only update sizes when doing a full update
649
+ !record->object_data.is_frozen
650
+ ) {
651
+ // if we were asked to update sizes and this object was not already seen as being frozen,
652
+ // update size again.
653
+ record->object_data.size = ruby_obj_memsize_of(ref); // Note: This function call can cause the GVL to be released... maybe?
654
+ // (With T_DATA for instance, since it can be a custom method supplied by extensions)
655
+ // Check if it's now frozen so we skip a size update next time
656
+ record->object_data.is_frozen = RB_OBJ_FROZEN(ref);
657
+ }
658
+
659
+ // Ensure that ref is kept on the stack so the Ruby garbage collector does not try to clean up the object before this
660
+ // point.
661
+ RB_GC_GUARD(ref);
662
+
663
+ recorder->stats_last_update.objects_alive++;
664
+ if (record->object_data.is_frozen) {
665
+ recorder->stats_last_update.objects_frozen++;
666
+ }
667
+
668
+ return ST_CONTINUE;
669
+ }
670
+
671
+ // WARN: This can get called outside the GVL. NO HEAP ALLOCATIONS OR EXCEPTIONS ARE ALLOWED.
672
+ static int st_object_records_iterate(DDTRACE_UNUSED st_data_t key, st_data_t value, st_data_t extra) {
673
+ object_record *record = (object_record*) value;
674
+ const heap_record *stack = record->heap_record;
675
+ iteration_context *context = (iteration_context*) extra;
676
+
677
+ const heap_recorder *recorder = context->heap_recorder;
678
+
679
+ if (record->object_data.gen_age < ITERATION_MIN_AGE) {
680
+ // Skip objects that should not be included in iteration
681
+ return ST_CONTINUE;
682
+ }
683
+
684
+ ddog_prof_Location *locations = recorder->reusable_locations;
685
+ for (uint16_t i = 0; i < stack->frames_len; i++) {
686
+ const heap_frame *frame = &stack->frames[i];
687
+ locations[i] = (ddog_prof_Location) {
688
+ .mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C(""), .build_id_id = {}},
689
+ .function = {
690
+ .name = DDOG_CHARSLICE_C(""),
691
+ .name_id = frame->name,
692
+ .filename = DDOG_CHARSLICE_C(""),
693
+ .filename_id = frame->filename,
694
+ },
695
+ .line = frame->line,
696
+ };
697
+ }
698
+
699
+ heap_recorder_iteration_data iteration_data;
700
+ iteration_data.object_data = record->object_data;
701
+ iteration_data.locations = (ddog_prof_Slice_Location) {.ptr = locations, .len = stack->frames_len};
702
+
703
+ // This is expected to be StackRecorder's add_heap_sample_to_active_profile_without_gvl
704
+ if (!context->for_each_callback(iteration_data, context->for_each_callback_extra_arg)) {
705
+ return ST_STOP;
706
+ }
707
+
708
+ return ST_CONTINUE;
709
+ }
710
+
711
+ static int st_object_records_debug(DDTRACE_UNUSED st_data_t key, st_data_t value, st_data_t extra) {
712
+ debug_context *context = (debug_context*) extra;
713
+ VALUE debug_str = context->debug_str;
714
+
715
+ object_record *record = (object_record*) value;
716
+
717
+ rb_str_catf(debug_str, "%"PRIsVALUE"\n", object_record_inspect(context->recorder, record));
718
+
719
+ return ST_CONTINUE;
720
+ }
721
+
722
+ static int update_object_record_entry(DDTRACE_UNUSED st_data_t *key, st_data_t *value, st_data_t new_object_record, int existing) {
723
+ if (!existing) {
724
+ (*value) = (st_data_t) new_object_record; // Expected to be a `object_record *`
725
+ } else {
726
+ // If key already existed, we don't touch the existing value, so it can be used for diagnostics
727
+ }
728
+ return ST_CONTINUE;
729
+ }
730
+
731
+ static void commit_recording(heap_recorder *heap_recorder, heap_record *heap_record, object_record *active_recording) {
732
+ // Link the object record with the corresponding heap record. This was the last remaining thing we
733
+ // needed to fully build the object_record.
734
+ active_recording->heap_record = heap_record;
735
+ if (heap_record->num_tracked_objects == UINT32_MAX) {
736
+ rb_raise(rb_eRuntimeError, "Reached maximum number of tracked objects for heap record");
737
+ }
738
+ heap_record->num_tracked_objects++;
739
+
740
+ int existing_error = st_update(heap_recorder->object_records, active_recording->obj_id, update_object_record_entry, (st_data_t) active_recording);
741
+ if (existing_error) {
742
+ object_record *existing_record = NULL;
743
+ st_lookup(heap_recorder->object_records, active_recording->obj_id, (st_data_t *) &existing_record);
744
+ if (existing_record == NULL) rb_raise(rb_eRuntimeError, "Unexpected NULL when reading existing record");
745
+
746
+ VALUE existing_inspect = object_record_inspect(heap_recorder, existing_record);
747
+ VALUE new_inspect = object_record_inspect(heap_recorder, active_recording);
748
+ rb_raise(rb_eRuntimeError, "Object ids are supposed to be unique. We got 2 allocation recordings with "
749
+ "the same id. previous={%"PRIsVALUE"} new={%"PRIsVALUE"}", existing_inspect, new_inspect);
750
+ }
751
+ }
752
+
753
+ static int update_heap_record_entry_with_new_allocation(st_data_t *key, st_data_t *value, st_data_t data, int existing) {
754
+ heap_record **new_or_existing_record = (heap_record **) data;
755
+ (*new_or_existing_record) = (heap_record *) (*key);
756
+
757
+ if (!existing) {
758
+ (*value) = (st_data_t) true; // We're only using this hash as a set
759
+ }
760
+
761
+ return ST_CONTINUE;
762
+ }
763
+
764
+ static heap_record* get_or_create_heap_record(heap_recorder *heap_recorder, ddog_prof_Slice_Location locations) {
765
+ // See note on "heap_records" definition for why we keep this map.
766
+ heap_record *stack = heap_record_new(heap_recorder, locations);
767
+
768
+ heap_record *new_or_existing_record = NULL; // Will be set inside update_heap_record_entry_with_new_allocation
769
+ bool existing = st_update(heap_recorder->heap_records, (st_data_t) stack, update_heap_record_entry_with_new_allocation, (st_data_t) &new_or_existing_record);
770
+ if (existing) {
771
+ heap_record_free(heap_recorder, stack);
772
+ }
773
+
774
+ return new_or_existing_record;
775
+ }
776
+
777
+ static void cleanup_heap_record_if_unused(heap_recorder *heap_recorder, heap_record *heap_record) {
778
+ if (heap_record->num_tracked_objects > 0) {
779
+ // still being used! do nothing...
780
+ return;
781
+ }
782
+
783
+ if (!st_delete(heap_recorder->heap_records, (st_data_t*) &heap_record, NULL)) {
784
+ rb_raise(rb_eRuntimeError, "Attempted to cleanup an untracked heap_record");
785
+ };
786
+ heap_record_free(heap_recorder, heap_record);
787
+ }
788
+
789
+ static void on_committed_object_record_cleanup(heap_recorder *heap_recorder, object_record *record) {
790
+ // @ivoanjo: We've seen a segfault crash in the field in this function (October 2024) which we're still trying to investigate.
791
+ // (See PROF-10656 Datadog-internal for details). Just in case, I've sprinkled a bunch of NULL tests in this function for now.
792
+ // Once we figure out the issue we can get rid of them again.
793
+
794
+ if (heap_recorder == NULL) rb_raise(rb_eRuntimeError, "heap_recorder was NULL in on_committed_object_record_cleanup");
795
+ if (heap_recorder->heap_records == NULL) rb_raise(rb_eRuntimeError, "heap_recorder->heap_records was NULL in on_committed_object_record_cleanup");
796
+ if (record == NULL) rb_raise(rb_eRuntimeError, "record was NULL in on_committed_object_record_cleanup");
797
+
798
+ // Starting with the associated heap record. There will now be one less tracked object pointing to it
799
+ heap_record *heap_record = record->heap_record;
800
+
801
+ if (heap_record == NULL) rb_raise(rb_eRuntimeError, "heap_record was NULL in on_committed_object_record_cleanup");
802
+
803
+ heap_record->num_tracked_objects--;
804
+
805
+ // One less object using this heap record, it may have become unused...
806
+ cleanup_heap_record_if_unused(heap_recorder, heap_record);
807
+
808
+ object_record_free(heap_recorder, record);
809
+ }
810
+
811
+ // =================
812
+ // Object Record API
813
+ // =================
814
+ object_record* object_record_new(long obj_id, heap_record *heap_record, live_object_data object_data) {
815
+ object_record *record = calloc(1, sizeof(object_record)); // See "note on calloc vs ruby_xcalloc use" above
816
+ record->obj_id = obj_id;
817
+ record->heap_record = heap_record;
818
+ record->object_data = object_data;
819
+ return record;
820
+ }
821
+
822
+ void object_record_free(heap_recorder *recorder, object_record *record) {
823
+ unintern_or_raise(recorder, record->object_data.class);
824
+ free(record); // See "note on calloc vs ruby_xcalloc use" above
825
+ }
826
+
827
+ VALUE object_record_inspect(heap_recorder *recorder, object_record *record) {
828
+ heap_frame top_frame = record->heap_record->frames[0];
829
+ VALUE filename = get_ruby_string_or_raise(recorder, top_frame.filename);
830
+ live_object_data object_data = record->object_data;
831
+
832
+ VALUE inspect = rb_sprintf("obj_id=%ld weight=%d size=%zu location=%"PRIsVALUE":%d alloc_gen=%zu gen_age=%zu frozen=%d ",
833
+ record->obj_id, object_data.weight, object_data.size, filename,
834
+ (int) top_frame.line, object_data.alloc_gen, object_data.gen_age, object_data.is_frozen);
835
+
836
+ if (record->object_data.class.value > 0) {
837
+ VALUE class = get_ruby_string_or_raise(recorder, record->object_data.class);
838
+
839
+ rb_str_catf(inspect, "class=%"PRIsVALUE" ", class);
840
+ }
841
+ VALUE ref;
842
+
843
+ if (!ruby_ref_from_id(LONG2NUM(record->obj_id), &ref)) {
844
+ rb_str_catf(inspect, "object=<invalid>");
845
+ } else {
846
+ rb_str_catf(inspect, "value=%p ", (void *) ref);
847
+ VALUE ruby_inspect = ruby_safe_inspect(ref);
848
+ if (ruby_inspect != Qnil) {
849
+ rb_str_catf(inspect, "object=%"PRIsVALUE, ruby_inspect);
850
+ } else {
851
+ rb_str_catf(inspect, "object=%s", ruby_value_type_to_string(rb_type(ref)));
852
+ }
853
+ }
854
+
855
+ return inspect;
856
+ }
857
+
858
+ // ==============
859
+ // Heap Record API
860
+ // ==============
861
+ heap_record* heap_record_new(heap_recorder *recorder, ddog_prof_Slice_Location locations) {
862
+ uint16_t frames_len = locations.len;
863
+ if (frames_len > MAX_FRAMES_LIMIT) {
864
+ // This is not expected as MAX_FRAMES_LIMIT is shared with the stacktrace construction mechanism
865
+ rb_raise(rb_eRuntimeError, "Found stack with more than %d frames (%d)", MAX_FRAMES_LIMIT, frames_len);
866
+ }
867
+ heap_record *stack = calloc(1, sizeof(heap_record) + frames_len * sizeof(heap_frame)); // See "note on calloc vs ruby_xcalloc use" above
868
+ stack->num_tracked_objects = 0;
869
+ stack->frames_len = frames_len;
870
+
871
+ // Intern all these strings...
872
+ ddog_CharSlice *strings = recorder->reusable_char_slices;
873
+ // Put all the char slices in the same array; we'll pull them out in the same order from the ids array
874
+ for (uint16_t i = 0; i < stack->frames_len; i++) {
875
+ const ddog_prof_Location *location = &locations.ptr[i];
876
+ strings[i] = location->function.filename;
877
+ strings[i + stack->frames_len] = location->function.name;
878
+ }
879
+ intern_all_or_raise(recorder->string_storage, (ddog_prof_Slice_CharSlice) { .ptr = strings, .len = stack->frames_len * 2 }, recorder->reusable_ids, stack->frames_len * 2);
880
+
881
+ // ...and record them for later use
882
+ for (uint16_t i = 0; i < stack->frames_len; i++) {
883
+ stack->frames[i] = (heap_frame) {
884
+ .filename = recorder->reusable_ids[i],
885
+ .name = recorder->reusable_ids[i + stack->frames_len],
886
+ // ddog_prof_Location is a int64_t. We don't expect to have to profile files with more than
887
+ // 2M lines so this cast should be fairly safe?
888
+ .line = (int32_t) locations.ptr[i].line,
889
+ };
890
+ }
891
+
892
+ return stack;
893
+ }
894
+
895
+ void heap_record_free(heap_recorder *recorder, heap_record *stack) {
896
+ ddog_prof_ManagedStringId *ids = recorder->reusable_ids;
897
+
898
+ // Put all the ids in the same array; doesn't really matter the order
899
+ for (u_int16_t i = 0; i < stack->frames_len; i++) {
900
+ ids[i] = stack->frames[i].filename;
901
+ ids[i + stack->frames_len] = stack->frames[i].name;
902
+ }
903
+ unintern_all_or_raise(recorder, (ddog_prof_Slice_ManagedStringId) { .ptr = ids, .len = stack->frames_len * 2 });
904
+
905
+ free(stack); // See "note on calloc vs ruby_xcalloc use" above
906
+ }
907
+
908
+ // The entire stack is represented by ids (name, filename) and lines (integers) so we can treat is as just
909
+ // a big string of bytes and compare it all in one go.
910
+ int heap_record_cmp_st(st_data_t key1, st_data_t key2) {
911
+ heap_record *stack1 = (heap_record*) key1;
912
+ heap_record *stack2 = (heap_record*) key2;
913
+
914
+ if (stack1->frames_len != stack2->frames_len) {
915
+ return ((int) stack1->frames_len) - ((int) stack2->frames_len);
916
+ } else {
917
+ return memcmp(stack1->frames, stack2->frames, stack1->frames_len * sizeof(heap_frame));
918
+ }
919
+ }
920
+
921
+ // Initial seed for hash function, same as Ruby uses
922
+ #define FNV1_32A_INIT 0x811c9dc5
923
+
924
+ // The entire stack is represented by ids (name, filename) and lines (integers) so we can treat is as just
925
+ // a big string of bytes and hash it all in one go.
926
+ st_index_t heap_record_hash_st(st_data_t key) {
927
+ heap_record *stack = (heap_record*) key;
928
+ return st_hash(stack->frames, stack->frames_len * sizeof(heap_frame), FNV1_32A_INIT);
929
+ }
930
+
931
+ static void unintern_or_raise(heap_recorder *recorder, ddog_prof_ManagedStringId id) {
932
+ if (id.value == 0) return; // Empty string, nothing to do
933
+
934
+ ddog_prof_MaybeError result = ddog_prof_ManagedStringStorage_unintern(recorder->string_storage, id);
935
+ if (result.tag == DDOG_PROF_OPTION_ERROR_SOME_ERROR) {
936
+ rb_raise(rb_eRuntimeError, "Failed to unintern id: %"PRIsVALUE, get_error_details_and_drop(&result.some));
937
+ }
938
+ }
939
+
940
+ static void unintern_all_or_raise(heap_recorder *recorder, ddog_prof_Slice_ManagedStringId ids) {
941
+ ddog_prof_MaybeError result = ddog_prof_ManagedStringStorage_unintern_all(recorder->string_storage, ids);
942
+ if (result.tag == DDOG_PROF_OPTION_ERROR_SOME_ERROR) {
943
+ rb_raise(rb_eRuntimeError, "Failed to unintern_all: %"PRIsVALUE, get_error_details_and_drop(&result.some));
944
+ }
945
+ }
946
+
947
+ static VALUE get_ruby_string_or_raise(heap_recorder *recorder, ddog_prof_ManagedStringId id) {
948
+ ddog_StringWrapperResult get_string_result = ddog_prof_ManagedStringStorage_get_string(recorder->string_storage, id);
949
+ if (get_string_result.tag == DDOG_STRING_WRAPPER_RESULT_ERR) {
950
+ rb_raise(rb_eRuntimeError, "Failed to get string: %"PRIsVALUE, get_error_details_and_drop(&get_string_result.err));
951
+ }
952
+ VALUE ruby_string = ruby_string_from_vec_u8(get_string_result.ok.message);
953
+ ddog_StringWrapper_drop((ddog_StringWrapper *) &get_string_result.ok);
954
+
955
+ return ruby_string;
956
+ }
957
+
958
+ static inline double ewma_stat(double previous, double current) {
959
+ double alpha = 0.3;
960
+ return (1 - alpha) * previous + alpha * current;
961
+ }
962
+
963
+ VALUE heap_recorder_testonly_is_object_recorded(heap_recorder *heap_recorder, VALUE obj_id) {
964
+ if (heap_recorder == NULL) {
965
+ rb_raise(rb_eArgError, "heap_recorder is NULL");
966
+ }
967
+
968
+ // Check if object records contains an object with this object_id
969
+ return st_is_member(heap_recorder->object_records, FIX2LONG(obj_id)) ? Qtrue : Qfalse;
970
+ }
971
+
972
+ void heap_recorder_testonly_reset_last_update(heap_recorder *heap_recorder) {
973
+ if (heap_recorder == NULL) {
974
+ rb_raise(rb_eArgError, "heap_recorder is NULL");
975
+ }
976
+
977
+ heap_recorder->last_update_ns = 0;
978
+ }
979
+
980
+ void heap_recorder_testonly_benchmark_intern(heap_recorder *heap_recorder, ddog_CharSlice string, int times, bool use_all) {
981
+ if (heap_recorder == NULL) rb_raise(rb_eArgError, "heap profiling must be enabled");
982
+ if (times > REUSABLE_FRAME_DETAILS_SIZE) rb_raise(rb_eArgError, "times cannot be > than REUSABLE_FRAME_DETAILS_SIZE");
983
+
984
+ if (use_all) {
985
+ ddog_CharSlice *strings = heap_recorder->reusable_char_slices;
986
+
987
+ for (int i = 0; i < times; i++) strings[i] = string;
988
+
989
+ intern_all_or_raise(
990
+ heap_recorder->string_storage,
991
+ (ddog_prof_Slice_CharSlice) { .ptr = strings, .len = times },
992
+ heap_recorder->reusable_ids,
993
+ times
994
+ );
995
+ } else {
996
+ for (int i = 0; i < times; i++) intern_or_raise(heap_recorder->string_storage, string);
997
+ }
998
+ }