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,1145 @@
1
+ #include <ruby.h>
2
+ #include <ruby/thread.h>
3
+ #include <pthread.h>
4
+ #include <errno.h>
5
+ #include "helpers.h"
6
+ #include "stack_recorder.h"
7
+ #include "libdatadog_helpers.h"
8
+ #include "ruby_helpers.h"
9
+ #include "time_helpers.h"
10
+ #include "heap_recorder.h"
11
+ #include "encoded_profile.h"
12
+
13
+ // Used to wrap a ddog_prof_Profile in a Ruby object and expose Ruby-level serialization APIs
14
+ // This file implements the native bits of the Datadog::Profiling::StackRecorder class
15
+
16
+ // ---
17
+ // ## Synchronization mechanism for safe parallel access design notes
18
+ //
19
+ // The state of the StackRecorder is managed using a set of locks to avoid concurrency issues.
20
+ //
21
+ // This is needed because the state is expected to be accessed, in parallel, by two different threads.
22
+ //
23
+ // 1. The thread that is taking a stack sample and that called `record_sample`, let's call it the **sampler thread**.
24
+ // In the current implementation of the profiler, there can only exist one **sampler thread** at a time; if this
25
+ // constraint changes, we should revise the design of the StackRecorder.
26
+ //
27
+ // 2. The thread that serializes and reports profiles, let's call it the **serializer thread**. We enforce that there
28
+ // cannot be more than one thread attempting to serialize profiles at a time.
29
+ //
30
+ // If both the sampler and serializer threads are trying to access the same `ddog_prof_Profile` in parallel, we will
31
+ // have a concurrency issue. Thus, the StackRecorder has an added mechanism to avoid this.
32
+ //
33
+ // As an additional constraint, the **sampler thread** has absolute priority and must never block while
34
+ // recording a sample.
35
+ //
36
+ // ### The solution: Keep two profiles at the same time
37
+ //
38
+ // To solve for the constraints above, the StackRecorder keeps two `ddog_prof_Profile` profile instances inside itself.
39
+ // They are called the `slot_one_profile` and `slot_two_profile`.
40
+ //
41
+ // Each profile is paired with its own mutex. `slot_one_profile` is protected by `slot_one_mutex` and `slot_two_profile`
42
+ // is protected by `slot_two_mutex`.
43
+ //
44
+ // We additionally introduce the concept of **active** and **inactive** profile slots. At any point, the sampler thread
45
+ // can probe the mutexes to discover which of the profiles corresponds to the active slot, and then records samples in it.
46
+ // When the serializer thread is ready to serialize data, it flips the active and inactive slots; it reports the data
47
+ // on the previously-active profile slot, and the sampler thread can continue to record in the previously-inactive
48
+ // profile slot.
49
+ //
50
+ // Thus, the sampler and serializer threads never cross paths, avoiding concurrency issues. The sampler thread writes to
51
+ // the active profile slot, and the serializer thread reads from the inactive profile slot.
52
+ //
53
+ // ### Locking protocol, high-level
54
+ //
55
+ // The active profile slot is the slot for which its corresponding mutex **is unlocked**. That is, if the sampler
56
+ // thread can grab a lock for a profile slot, then that slot is the active one. (Here you see where the constraint
57
+ // stated above that only one sampler thread can exist kicks in -- this part would need to be more complex if multiple
58
+ // sampler threads were in play.)
59
+ //
60
+ // As a counterpart, the inactive profile slot mutex is **kept locked** until such time the serializer
61
+ // thread is ready to work and decides to flip the slots.
62
+ //
63
+ // When a new StackRecorder is initialized, the `slot_one_mutex` is unlocked, and the `slot_two_mutex` is kept locked,
64
+ // that is, a new instance always starts with slot one active.
65
+ //
66
+ // Additionally, an `active_slot` field is kept, containing a `1` or `2`; this is only kept for the serializer thread
67
+ // to use as a simplification, as well as for testing and debugging; the **sampler thread must never use the `active_slot`
68
+ // field**.
69
+ //
70
+ // ### Locking protocol, from the sampler thread side
71
+ //
72
+ // When the sampler thread wants to record a sample, it goes through the following steps to discover which is the
73
+ // active profile slot:
74
+ //
75
+ // 1. `pthread_mutex_trylock(slot_one_mutex)`. If it succeeds to grab the lock, this means the active profile slot is
76
+ // slot one. If it fails, we move to the next step.
77
+ //
78
+ // 2. `pthread_mutex_trylock(slot_two_mutex)`. If it succeeds to grab the lock, this means the active profile slot is
79
+ // slot two. If it fails, we move to the next step.
80
+ //
81
+ // 3. What does it mean for the sampler thread to have observed both `slot_one_mutex` as well as `slot_two_mutex` as
82
+ // being locked? There are two options:
83
+ // a. The sampler thread got really unlucky. When it tried to grab the `slot_one_mutex`, the active profile slot was
84
+ // the second one BUT then the serializer thread flipped the slots, and by the time the sampler thread probed the
85
+ // `slot_two_mutex`, that one was taken. Since the serializer thread is expected only to work once a minute,
86
+ // we retry steps 1. and 2. and should be able to find an active slot.
87
+ // b. Something is incorrect in the StackRecorder state. In this situation, the sampler thread should give up on
88
+ // sampling and enter an error state.
89
+ //
90
+ // Note that in the steps above, and because the sampler thread uses `trylock` to probe the mutexes, that the
91
+ // sampler thread never blocks. It either is able to find an active profile slot in a bounded amount of steps or it
92
+ // enters an error state.
93
+ //
94
+ // This guarantees that sampler performance is never constrained by serializer performance.
95
+ //
96
+ // ### Locking protocol, from the serializer thread side
97
+ //
98
+ // When the serializer thread wants to serialize a profile, it first flips the active and inactive profile slots.
99
+ //
100
+ // The flipping action is described below. Consider previously-inactive and previously-active as the state of the slots
101
+ // before the flipping happens.
102
+ //
103
+ // The flipping steps are the following:
104
+ //
105
+ // 1. Release the mutex for the previously-inactive profile slot. That slot, as seen by the sampler thread, is now
106
+ // active.
107
+ //
108
+ // 2. Grab the mutex for the previously-active profile slot. Note that this can lead to the serializer thread blocking,
109
+ // if the sampler thread is holding this mutex. After the mutex is grabbed, the previously-active slot becomes inactive,
110
+ // as seen by the sampler thread.
111
+ //
112
+ // 3. Update `active_slot`.
113
+ //
114
+ // After flipping the profile slots, the serializer thread is now free to serialize the inactive profile slot. The slot
115
+ // is kept inactive until the next time the serializer thread wants to serialize data.
116
+ //
117
+ // Note there can be a brief period between steps 1 and 2 where the serializer thread holds no lock, which means that
118
+ // the sampler thread can pick either slot. This is OK: if the sampler thread picks the previously-inactive slot, the
119
+ // samples will be reported on the next serialization; if the sampler thread picks the previously-active slot, the
120
+ // samples are still included in the current serialization. Either option is correct.
121
+ //
122
+ // ### Additional notes
123
+ //
124
+ // Q: Can the sampler thread and the serializer thread ever be the same thread? (E.g. sampling in interrupt handler)
125
+ // A: No; the current profiler design requires that sampling happens only on the thread that is holding the Global VM
126
+ // Lock (GVL). The serializer thread flipping occurs after the serializer thread releases the GVL, and thus the
127
+ // serializer thread will not be able to host the sampling process.
128
+ //
129
+ // ---
130
+
131
+ static VALUE ok_symbol = Qnil; // :ok in Ruby
132
+ static VALUE error_symbol = Qnil; // :error in Ruby
133
+
134
+ // Note: Please DO NOT use `VALUE_STRING` anywhere else, instead use `DDOG_CHARSLICE_C`.
135
+ // `VALUE_STRING` is only needed because older versions of gcc (4.9.2, used in our Ruby 2.2 CI test images)
136
+ // tripped when compiling `enabled_value_types` using `-std=gnu99` due to the extra cast that is included in
137
+ // `DDOG_CHARSLICE_C` with the following error:
138
+ //
139
+ // ```
140
+ // compiling ../../../../ext/ddtrace_profiling_native_extension/stack_recorder.c
141
+ // ../../../../ext/ddtrace_profiling_native_extension/stack_recorder.c:23:1: error: initializer element is not constant
142
+ // static const ddog_prof_ValueType enabled_value_types[] = {CPU_TIME_VALUE, CPU_SAMPLES_VALUE, WALL_TIME_VALUE};
143
+ // ^
144
+ // ```
145
+ #define VALUE_STRING(string) {.ptr = "" string, .len = sizeof(string) - 1}
146
+
147
+ #define CPU_TIME_VALUE {.type_ = VALUE_STRING("cpu-time"), .unit = VALUE_STRING("nanoseconds")}
148
+ #define CPU_TIME_VALUE_ID 0
149
+ #define CPU_SAMPLES_VALUE {.type_ = VALUE_STRING("cpu-samples"), .unit = VALUE_STRING("count")}
150
+ #define CPU_SAMPLES_VALUE_ID 1
151
+ #define WALL_TIME_VALUE {.type_ = VALUE_STRING("wall-time"), .unit = VALUE_STRING("nanoseconds")}
152
+ #define WALL_TIME_VALUE_ID 2
153
+ #define ALLOC_SAMPLES_VALUE {.type_ = VALUE_STRING("alloc-samples"), .unit = VALUE_STRING("count")}
154
+ #define ALLOC_SAMPLES_VALUE_ID 3
155
+ #define ALLOC_SAMPLES_UNSCALED_VALUE {.type_ = VALUE_STRING("alloc-samples-unscaled"), .unit = VALUE_STRING("count")}
156
+ #define ALLOC_SAMPLES_UNSCALED_VALUE_ID 4
157
+ #define HEAP_SAMPLES_VALUE {.type_ = VALUE_STRING("heap-live-samples"), .unit = VALUE_STRING("count")}
158
+ #define HEAP_SAMPLES_VALUE_ID 5
159
+ #define HEAP_SIZE_VALUE {.type_ = VALUE_STRING("heap-live-size"), .unit = VALUE_STRING("bytes")}
160
+ #define HEAP_SIZE_VALUE_ID 6
161
+ #define TIMELINE_VALUE {.type_ = VALUE_STRING("timeline"), .unit = VALUE_STRING("nanoseconds")}
162
+ #define TIMELINE_VALUE_ID 7
163
+
164
+ static const ddog_prof_ValueType all_value_types[] =
165
+ {CPU_TIME_VALUE, CPU_SAMPLES_VALUE, WALL_TIME_VALUE, ALLOC_SAMPLES_VALUE, ALLOC_SAMPLES_UNSCALED_VALUE, HEAP_SAMPLES_VALUE, HEAP_SIZE_VALUE, TIMELINE_VALUE};
166
+
167
+ // This array MUST be kept in sync with all_value_types above and is intended to act as a "hashmap" between VALUE_ID and the position it
168
+ // occupies on the all_value_types array.
169
+ // E.g. all_value_types_positions[CPU_TIME_VALUE_ID] => 0, means that CPU_TIME_VALUE was declared at position 0 of all_value_types.
170
+ static const uint8_t all_value_types_positions[] =
171
+ {CPU_TIME_VALUE_ID, CPU_SAMPLES_VALUE_ID, WALL_TIME_VALUE_ID, ALLOC_SAMPLES_VALUE_ID, ALLOC_SAMPLES_UNSCALED_VALUE_ID, HEAP_SAMPLES_VALUE_ID, HEAP_SIZE_VALUE_ID, TIMELINE_VALUE_ID};
172
+
173
+ #define ALL_VALUE_TYPES_COUNT (sizeof(all_value_types) / sizeof(ddog_prof_ValueType))
174
+
175
+ // Struct for storing stats related to a profile in a particular slot.
176
+ // These stats will share the same lifetime as the data in that profile slot.
177
+ typedef struct {
178
+ // How many individual samples were recorded into this slot (un-weighted)
179
+ uint64_t recorded_samples;
180
+ } stats_slot;
181
+
182
+ typedef struct {
183
+ ddog_prof_Profile profile;
184
+ stats_slot stats;
185
+ ddog_Timespec start_timestamp;
186
+ } profile_slot;
187
+
188
+ // Contains native state for each instance
189
+ typedef struct {
190
+ // Heap recorder instance
191
+ heap_recorder *heap_recorder;
192
+ bool heap_clean_after_gc_enabled;
193
+
194
+ pthread_mutex_t mutex_slot_one;
195
+ profile_slot profile_slot_one;
196
+ pthread_mutex_t mutex_slot_two;
197
+ profile_slot profile_slot_two;
198
+
199
+ ddog_prof_ManagedStringStorage string_storage;
200
+ ddog_prof_ManagedStringId label_key_allocation_class;
201
+ ddog_prof_ManagedStringId label_key_gc_gen_age;
202
+
203
+ short active_slot; // MUST NEVER BE ACCESSED FROM record_sample; this is NOT for the sampler thread to use.
204
+
205
+ uint8_t position_for[ALL_VALUE_TYPES_COUNT];
206
+ uint8_t enabled_values_count;
207
+
208
+ // Struct for storing stats related to behaviour of a stack recorder instance during its entire lifetime.
209
+ struct lifetime_stats {
210
+ // How many profiles have we serialized successfully so far
211
+ uint64_t serialization_successes;
212
+ // How many profiles have we serialized unsuccessfully so far
213
+ uint64_t serialization_failures;
214
+ // Stats on profile serialization time
215
+ long serialization_time_ns_min;
216
+ long serialization_time_ns_max;
217
+ uint64_t serialization_time_ns_total;
218
+ } stats_lifetime;
219
+ } stack_recorder_state;
220
+
221
+ // Used to group mutex and the corresponding profile slot for easy unlocking after work is done.
222
+ typedef struct {
223
+ pthread_mutex_t *mutex;
224
+ profile_slot *data;
225
+ } locked_profile_slot;
226
+
227
+ typedef struct {
228
+ // Set by caller
229
+ stack_recorder_state *state;
230
+ ddog_Timespec finish_timestamp;
231
+
232
+ // Set by callee
233
+ profile_slot *slot;
234
+ ddog_prof_Profile_SerializeResult result;
235
+ long heap_profile_build_time_ns;
236
+ long serialize_no_gvl_time_ns;
237
+ ddog_prof_MaybeError advance_gen_result;
238
+
239
+ // Set by both
240
+ bool serialize_ran;
241
+ } call_serialize_without_gvl_arguments;
242
+
243
+ static VALUE _native_new(VALUE klass);
244
+ static void initialize_slot_concurrency_control(stack_recorder_state *state);
245
+ static void initialize_profiles(stack_recorder_state *state, ddog_prof_Slice_ValueType sample_types);
246
+ static void stack_recorder_typed_data_free(void *data);
247
+ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self);
248
+ static VALUE _native_serialize(VALUE self, VALUE recorder_instance);
249
+ static VALUE ruby_time_from(ddog_Timespec ddprof_time);
250
+ static void *call_serialize_without_gvl(void *call_args);
251
+ static locked_profile_slot sampler_lock_active_profile(stack_recorder_state *state);
252
+ static void sampler_unlock_active_profile(locked_profile_slot active_slot);
253
+ static profile_slot* serializer_flip_active_and_inactive_slots(stack_recorder_state *state);
254
+ static VALUE _native_active_slot(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
255
+ static VALUE _native_is_slot_one_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
256
+ static VALUE _native_is_slot_two_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
257
+ static VALUE test_slot_mutex_state(VALUE recorder_instance, int slot);
258
+ static ddog_Timespec system_epoch_now_timespec(void);
259
+ static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE recorder_instance);
260
+ static void serializer_set_start_timestamp_for_next_profile(stack_recorder_state *state, ddog_Timespec start_time);
261
+ static VALUE _native_record_endpoint(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE local_root_span_id, VALUE endpoint);
262
+ static void reset_profile_slot(profile_slot *slot, ddog_Timespec start_timestamp);
263
+ static VALUE _native_track_object(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE new_obj, VALUE weight, VALUE alloc_class);
264
+ static VALUE _native_start_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
265
+ static VALUE _native_end_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
266
+ static VALUE _native_debug_heap_recorder(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
267
+ static VALUE _native_stats(DDTRACE_UNUSED VALUE self, VALUE instance);
268
+ static VALUE build_profile_stats(profile_slot *slot, long serialization_time_ns, long heap_iteration_prep_time_ns, long heap_profile_build_time_ns);
269
+ static VALUE _native_is_object_recorded(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE object_id);
270
+ static VALUE _native_heap_recorder_reset_last_update(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
271
+ static VALUE _native_recorder_after_gc_step(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
272
+ static VALUE _native_benchmark_intern(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE string, VALUE times, VALUE use_all);
273
+ static VALUE _native_test_managed_string_storage_produces_valid_profiles(DDTRACE_UNUSED VALUE _self);
274
+
275
+ void stack_recorder_init(VALUE profiling_module) {
276
+ VALUE stack_recorder_class = rb_define_class_under(profiling_module, "StackRecorder", rb_cObject);
277
+ // Hosts methods used for testing the native code using RSpec
278
+ VALUE testing_module = rb_define_module_under(stack_recorder_class, "Testing");
279
+
280
+ // Instances of the StackRecorder class are "TypedData" objects.
281
+ // "TypedData" objects are special objects in the Ruby VM that can wrap C structs.
282
+ // In this case, it wraps the stack_recorder_state.
283
+ //
284
+ // Because Ruby doesn't know how to initialize native-level structs, we MUST override the allocation function for objects
285
+ // of this class so that we can manage this part. Not overriding or disabling the allocation function is a common
286
+ // gotcha for "TypedData" objects that can very easily lead to VM crashes, see for instance
287
+ // https://bugs.ruby-lang.org/issues/18007 for a discussion around this.
288
+ rb_define_alloc_func(stack_recorder_class, _native_new);
289
+
290
+ rb_define_singleton_method(stack_recorder_class, "_native_initialize", _native_initialize, -1);
291
+ rb_define_singleton_method(stack_recorder_class, "_native_serialize", _native_serialize, 1);
292
+ rb_define_singleton_method(stack_recorder_class, "_native_reset_after_fork", _native_reset_after_fork, 1);
293
+ rb_define_singleton_method(stack_recorder_class, "_native_stats", _native_stats, 1);
294
+ rb_define_singleton_method(testing_module, "_native_active_slot", _native_active_slot, 1);
295
+ rb_define_singleton_method(testing_module, "_native_slot_one_mutex_locked?", _native_is_slot_one_mutex_locked, 1);
296
+ rb_define_singleton_method(testing_module, "_native_slot_two_mutex_locked?", _native_is_slot_two_mutex_locked, 1);
297
+ rb_define_singleton_method(testing_module, "_native_record_endpoint", _native_record_endpoint, 3);
298
+ rb_define_singleton_method(testing_module, "_native_track_object", _native_track_object, 4);
299
+ rb_define_singleton_method(testing_module, "_native_start_fake_slow_heap_serialization",
300
+ _native_start_fake_slow_heap_serialization, 1);
301
+ rb_define_singleton_method(testing_module, "_native_end_fake_slow_heap_serialization",
302
+ _native_end_fake_slow_heap_serialization, 1);
303
+ rb_define_singleton_method(testing_module, "_native_debug_heap_recorder",
304
+ _native_debug_heap_recorder, 1);
305
+ rb_define_singleton_method(testing_module, "_native_is_object_recorded?", _native_is_object_recorded, 2);
306
+ rb_define_singleton_method(testing_module, "_native_heap_recorder_reset_last_update", _native_heap_recorder_reset_last_update, 1);
307
+ rb_define_singleton_method(testing_module, "_native_recorder_after_gc_step", _native_recorder_after_gc_step, 1);
308
+ rb_define_singleton_method(testing_module, "_native_benchmark_intern", _native_benchmark_intern, 4);
309
+ rb_define_singleton_method(testing_module, "_native_test_managed_string_storage_produces_valid_profiles", _native_test_managed_string_storage_produces_valid_profiles, 0);
310
+
311
+ ok_symbol = ID2SYM(rb_intern_const("ok"));
312
+ error_symbol = ID2SYM(rb_intern_const("error"));
313
+ }
314
+
315
+ // This structure is used to define a Ruby object that stores a pointer to a ddog_prof_Profile instance
316
+ // See also https://github.com/ruby/ruby/blob/master/doc/extension.rdoc for how this works
317
+ static const rb_data_type_t stack_recorder_typed_data = {
318
+ .wrap_struct_name = "Datadog::Profiling::StackRecorder",
319
+ .function = {
320
+ .dfree = stack_recorder_typed_data_free,
321
+ .dsize = NULL, // We don't track profile memory usage (although it'd be cool if we did!)
322
+ // No need to provide dmark nor dcompact because we don't directly reference Ruby VALUEs from inside this object
323
+ },
324
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
325
+ };
326
+
327
+ static VALUE _native_new(VALUE klass) {
328
+ stack_recorder_state *state = ruby_xcalloc(1, sizeof(stack_recorder_state));
329
+
330
+ // Note: Any exceptions raised from this note until the TypedData_Wrap_Struct call will lead to the state memory
331
+ // being leaked.
332
+
333
+ state->heap_clean_after_gc_enabled = false;
334
+
335
+ ddog_prof_Slice_ValueType sample_types = {.ptr = all_value_types, .len = ALL_VALUE_TYPES_COUNT};
336
+
337
+ initialize_slot_concurrency_control(state);
338
+ for (uint8_t i = 0; i < ALL_VALUE_TYPES_COUNT; i++) { state->position_for[i] = all_value_types_positions[i]; }
339
+ state->enabled_values_count = ALL_VALUE_TYPES_COUNT;
340
+ state->stats_lifetime = (struct lifetime_stats) {
341
+ .serialization_time_ns_min = INT64_MAX,
342
+ };
343
+
344
+ // Note: At this point, slot_one_profile/slot_two_profile/string_storage contain null pointers. Libdatadog validates pointers
345
+ // before using them so it's ok for us to go ahead and create the StackRecorder object.
346
+
347
+ VALUE stack_recorder = TypedData_Wrap_Struct(klass, &stack_recorder_typed_data, state);
348
+
349
+ ddog_prof_ManagedStringStorageNewResult string_storage = ddog_prof_ManagedStringStorage_new();
350
+
351
+ if (string_storage.tag == DDOG_PROF_MANAGED_STRING_STORAGE_NEW_RESULT_ERR) {
352
+ rb_raise(rb_eRuntimeError, "Failed to initialize string storage: %"PRIsVALUE, get_error_details_and_drop(&string_storage.err));
353
+ }
354
+
355
+ state->string_storage = string_storage.ok;
356
+ state->label_key_allocation_class = intern_or_raise(state->string_storage, DDOG_CHARSLICE_C("allocation class"));
357
+ state->label_key_gc_gen_age = intern_or_raise(state->string_storage, DDOG_CHARSLICE_C("gc gen age"));
358
+
359
+ initialize_profiles(state, sample_types);
360
+
361
+ // NOTE: We initialize this because we want a new recorder to be operational even before #initialize runs and our
362
+ // default is everything enabled. However, if during recording initialization it turns out we don't want
363
+ // heap samples, we will free and reset heap_recorder back to NULL.
364
+ state->heap_recorder = heap_recorder_new(state->string_storage);
365
+
366
+ return stack_recorder;
367
+ }
368
+
369
+ static void initialize_slot_concurrency_control(stack_recorder_state *state) {
370
+ state->mutex_slot_one = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
371
+ state->mutex_slot_two = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
372
+
373
+ // A newly-created StackRecorder starts with slot one being active for samples, so let's lock slot two
374
+ ENFORCE_SUCCESS_GVL(pthread_mutex_lock(&state->mutex_slot_two));
375
+
376
+ state->active_slot = 1;
377
+ }
378
+
379
+ static void initialize_profiles(stack_recorder_state *state, ddog_prof_Slice_ValueType sample_types) {
380
+ ddog_Timespec start_timestamp = system_epoch_now_timespec();
381
+
382
+ ddog_prof_Profile_NewResult slot_one_profile_result =
383
+ ddog_prof_Profile_with_string_storage(sample_types, NULL /* period is optional */, state->string_storage);
384
+
385
+ if (slot_one_profile_result.tag == DDOG_PROF_PROFILE_NEW_RESULT_ERR) {
386
+ rb_raise(rb_eRuntimeError, "Failed to initialize slot one profile: %"PRIsVALUE, get_error_details_and_drop(&slot_one_profile_result.err));
387
+ }
388
+
389
+ state->profile_slot_one = (profile_slot) { .profile = slot_one_profile_result.ok, .start_timestamp = start_timestamp };
390
+
391
+ ddog_prof_Profile_NewResult slot_two_profile_result =
392
+ ddog_prof_Profile_with_string_storage(sample_types, NULL /* period is optional */, state->string_storage);
393
+
394
+ if (slot_two_profile_result.tag == DDOG_PROF_PROFILE_NEW_RESULT_ERR) {
395
+ // Note: No need to take any special care of slot one, it'll get cleaned up by stack_recorder_typed_data_free
396
+ rb_raise(rb_eRuntimeError, "Failed to initialize slot two profile: %"PRIsVALUE, get_error_details_and_drop(&slot_two_profile_result.err));
397
+ }
398
+
399
+ state->profile_slot_two = (profile_slot) { .profile = slot_two_profile_result.ok, .start_timestamp = start_timestamp };
400
+ }
401
+
402
+ static void stack_recorder_typed_data_free(void *state_ptr) {
403
+ stack_recorder_state *state = (stack_recorder_state *) state_ptr;
404
+
405
+ pthread_mutex_destroy(&state->mutex_slot_one);
406
+ ddog_prof_Profile_drop(&state->profile_slot_one.profile);
407
+
408
+ pthread_mutex_destroy(&state->mutex_slot_two);
409
+ ddog_prof_Profile_drop(&state->profile_slot_two.profile);
410
+
411
+ heap_recorder_free(state->heap_recorder);
412
+
413
+ ddog_prof_ManagedStringStorage_drop(state->string_storage);
414
+
415
+ ruby_xfree(state);
416
+ }
417
+
418
+ static VALUE _native_initialize(int argc, VALUE *argv, DDTRACE_UNUSED VALUE _self) {
419
+ VALUE options;
420
+ rb_scan_args(argc, argv, "0:", &options);
421
+ if (options == Qnil) options = rb_hash_new();
422
+
423
+ VALUE recorder_instance = rb_hash_fetch(options, ID2SYM(rb_intern("self_instance")));
424
+ VALUE cpu_time_enabled = rb_hash_fetch(options, ID2SYM(rb_intern("cpu_time_enabled")));
425
+ VALUE alloc_samples_enabled = rb_hash_fetch(options, ID2SYM(rb_intern("alloc_samples_enabled")));
426
+ VALUE heap_samples_enabled = rb_hash_fetch(options, ID2SYM(rb_intern("heap_samples_enabled")));
427
+ VALUE heap_size_enabled = rb_hash_fetch(options, ID2SYM(rb_intern("heap_size_enabled")));
428
+ VALUE heap_sample_every = rb_hash_fetch(options, ID2SYM(rb_intern("heap_sample_every")));
429
+ VALUE timeline_enabled = rb_hash_fetch(options, ID2SYM(rb_intern("timeline_enabled")));
430
+ VALUE heap_clean_after_gc_enabled = rb_hash_fetch(options, ID2SYM(rb_intern("heap_clean_after_gc_enabled")));
431
+
432
+ ENFORCE_BOOLEAN(cpu_time_enabled);
433
+ ENFORCE_BOOLEAN(alloc_samples_enabled);
434
+ ENFORCE_BOOLEAN(heap_samples_enabled);
435
+ ENFORCE_BOOLEAN(heap_size_enabled);
436
+ ENFORCE_TYPE(heap_sample_every, T_FIXNUM);
437
+ ENFORCE_BOOLEAN(timeline_enabled);
438
+ ENFORCE_BOOLEAN(heap_clean_after_gc_enabled);
439
+
440
+ stack_recorder_state *state;
441
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
442
+
443
+ state->heap_clean_after_gc_enabled = (heap_clean_after_gc_enabled == Qtrue);
444
+
445
+ heap_recorder_set_sample_rate(state->heap_recorder, NUM2INT(heap_sample_every));
446
+
447
+ uint8_t requested_values_count = ALL_VALUE_TYPES_COUNT -
448
+ (cpu_time_enabled == Qtrue ? 0 : 1) -
449
+ (alloc_samples_enabled == Qtrue? 0 : 2) -
450
+ (heap_samples_enabled == Qtrue ? 0 : 1) -
451
+ (heap_size_enabled == Qtrue ? 0 : 1) -
452
+ (timeline_enabled == Qtrue ? 0 : 1);
453
+
454
+ if (requested_values_count == ALL_VALUE_TYPES_COUNT) return Qtrue; // Nothing to do, this is the default
455
+
456
+ // When some sample types are disabled, we need to reconfigure libdatadog to record less types,
457
+ // as well as reconfigure the position_for array to push the disabled types to the end so they don't get recorded.
458
+ // See record_sample for details on the use of position_for.
459
+
460
+ state->enabled_values_count = requested_values_count;
461
+
462
+ ddog_prof_ValueType enabled_value_types[ALL_VALUE_TYPES_COUNT];
463
+ uint8_t next_enabled_pos = 0;
464
+ uint8_t next_disabled_pos = requested_values_count;
465
+
466
+ // CPU_SAMPLES_VALUE is always enabled
467
+ enabled_value_types[next_enabled_pos] = (ddog_prof_ValueType) CPU_SAMPLES_VALUE;
468
+ state->position_for[CPU_SAMPLES_VALUE_ID] = next_enabled_pos++;
469
+
470
+ // WALL_TIME_VALUE is always enabled
471
+ enabled_value_types[next_enabled_pos] = (ddog_prof_ValueType) WALL_TIME_VALUE;
472
+ state->position_for[WALL_TIME_VALUE_ID] = next_enabled_pos++;
473
+
474
+ if (cpu_time_enabled == Qtrue) {
475
+ enabled_value_types[next_enabled_pos] = (ddog_prof_ValueType) CPU_TIME_VALUE;
476
+ state->position_for[CPU_TIME_VALUE_ID] = next_enabled_pos++;
477
+ } else {
478
+ state->position_for[CPU_TIME_VALUE_ID] = next_disabled_pos++;
479
+ }
480
+
481
+ if (alloc_samples_enabled == Qtrue) {
482
+ enabled_value_types[next_enabled_pos] = (ddog_prof_ValueType) ALLOC_SAMPLES_VALUE;
483
+ state->position_for[ALLOC_SAMPLES_VALUE_ID] = next_enabled_pos++;
484
+
485
+ enabled_value_types[next_enabled_pos] = (ddog_prof_ValueType) ALLOC_SAMPLES_UNSCALED_VALUE;
486
+ state->position_for[ALLOC_SAMPLES_UNSCALED_VALUE_ID] = next_enabled_pos++;
487
+ } else {
488
+ state->position_for[ALLOC_SAMPLES_VALUE_ID] = next_disabled_pos++;
489
+ state->position_for[ALLOC_SAMPLES_UNSCALED_VALUE_ID] = next_disabled_pos++;
490
+ }
491
+
492
+ if (heap_samples_enabled == Qtrue) {
493
+ enabled_value_types[next_enabled_pos] = (ddog_prof_ValueType) HEAP_SAMPLES_VALUE;
494
+ state->position_for[HEAP_SAMPLES_VALUE_ID] = next_enabled_pos++;
495
+ } else {
496
+ state->position_for[HEAP_SAMPLES_VALUE_ID] = next_disabled_pos++;
497
+ }
498
+
499
+ if (heap_size_enabled == Qtrue) {
500
+ enabled_value_types[next_enabled_pos] = (ddog_prof_ValueType) HEAP_SIZE_VALUE;
501
+ state->position_for[HEAP_SIZE_VALUE_ID] = next_enabled_pos++;
502
+ } else {
503
+ state->position_for[HEAP_SIZE_VALUE_ID] = next_disabled_pos++;
504
+ }
505
+ heap_recorder_set_size_enabled(state->heap_recorder, heap_size_enabled);
506
+
507
+ if (heap_samples_enabled == Qfalse && heap_size_enabled == Qfalse) {
508
+ // Turns out heap sampling is disabled but we initialized everything in _native_new
509
+ // assuming all samples were enabled. We need to deinitialize the heap recorder.
510
+ heap_recorder_free(state->heap_recorder);
511
+ state->heap_recorder = NULL;
512
+ }
513
+
514
+ if (timeline_enabled == Qtrue) {
515
+ enabled_value_types[next_enabled_pos] = (ddog_prof_ValueType) TIMELINE_VALUE;
516
+ state->position_for[TIMELINE_VALUE_ID] = next_enabled_pos++;
517
+ } else {
518
+ state->position_for[TIMELINE_VALUE_ID] = next_disabled_pos++;
519
+ }
520
+
521
+ ddog_prof_Profile_drop(&state->profile_slot_one.profile);
522
+ ddog_prof_Profile_drop(&state->profile_slot_two.profile);
523
+
524
+ ddog_prof_Slice_ValueType sample_types = {.ptr = enabled_value_types, .len = state->enabled_values_count};
525
+ initialize_profiles(state, sample_types);
526
+
527
+ return Qtrue;
528
+ }
529
+
530
+ static VALUE _native_serialize(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
531
+ stack_recorder_state *state;
532
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
533
+
534
+ ddog_Timespec finish_timestamp = system_epoch_now_timespec();
535
+ // Need to do this while still holding on to the Global VM Lock; see comments on method for why
536
+ serializer_set_start_timestamp_for_next_profile(state, finish_timestamp);
537
+
538
+ long heap_iteration_prep_start_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE);
539
+ // Prepare the iteration on heap recorder we'll be doing outside the GVL. The preparation needs to
540
+ // happen while holding on to the GVL.
541
+ // NOTE: While rare, it's possible for the GVL to be released inside this function (see comments on `heap_recorder_update`)
542
+ // and thus don't assume this is an "atomic" step -- other threads may get some running time in the meanwhile.
543
+ heap_recorder_prepare_iteration(state->heap_recorder);
544
+ long heap_iteration_prep_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - heap_iteration_prep_start_time_ns;
545
+
546
+ // We'll release the Global VM Lock while we're calling serialize, so that the Ruby VM can continue to work while this
547
+ // is pending
548
+ call_serialize_without_gvl_arguments args = {
549
+ .state = state,
550
+ .finish_timestamp = finish_timestamp,
551
+ .serialize_ran = false,
552
+ };
553
+
554
+ while (!args.serialize_ran) {
555
+ // Give the Ruby VM an opportunity to process any pending interruptions (including raising exceptions).
556
+ // Note that it's OK to do this BEFORE call_serialize_without_gvl runs BUT NOT AFTER because afterwards
557
+ // there's heap-allocated memory that MUST be cleaned before raising any exception.
558
+ //
559
+ // Note that we run this in a loop because `rb_thread_call_without_gvl2` may return multiple times due to
560
+ // pending interrupts until it actually runs our code.
561
+ process_pending_interruptions(Qnil);
562
+
563
+ // We use rb_thread_call_without_gvl2 here because unlike the regular _gvl variant, gvl2 does not process
564
+ // interruptions and thus does not raise exceptions after running our code.
565
+ rb_thread_call_without_gvl2(call_serialize_without_gvl, &args, NULL /* No interruption function needed in this case */, NULL /* Not needed */);
566
+ }
567
+
568
+ // Cleanup after heap recorder iteration. This needs to happen while holding on to the GVL.
569
+ heap_recorder_finish_iteration(state->heap_recorder);
570
+
571
+ // NOTE: We are focusing on the serialization time outside of the GVL in this stat here. This doesn't
572
+ // really cover the full serialization process but it gives a more useful number since it bypasses
573
+ // the noise of acquiring GVLs and dealing with interruptions which is highly specific to runtime
574
+ // conditions and over which we really have no control about.
575
+ state->stats_lifetime.serialization_time_ns_max = long_max_of(state->stats_lifetime.serialization_time_ns_max, args.serialize_no_gvl_time_ns);
576
+ state->stats_lifetime.serialization_time_ns_min = long_min_of(state->stats_lifetime.serialization_time_ns_min, args.serialize_no_gvl_time_ns);
577
+ state->stats_lifetime.serialization_time_ns_total += args.serialize_no_gvl_time_ns;
578
+
579
+ ddog_prof_Profile_SerializeResult serialized_profile = args.result;
580
+
581
+ if (serialized_profile.tag == DDOG_PROF_PROFILE_SERIALIZE_RESULT_ERR) {
582
+ state->stats_lifetime.serialization_failures++;
583
+ return rb_ary_new_from_args(2, error_symbol, get_error_details_and_drop(&serialized_profile.err));
584
+ }
585
+
586
+ // Note: If we got here, the profile serialized correctly.
587
+ // Once we wrap this into a Ruby object, our `EncodedProfile` class will automatically manage memory for it and we
588
+ // can raise exceptions without worrying about leaking the profile.
589
+ state->stats_lifetime.serialization_successes++;
590
+ VALUE encoded_profile = from_ddog_prof_EncodedProfile(serialized_profile.ok);
591
+
592
+ ddog_prof_MaybeError result = args.advance_gen_result;
593
+ if (result.tag == DDOG_PROF_OPTION_ERROR_SOME_ERROR) {
594
+ rb_raise(rb_eRuntimeError, "Failed to advance string storage gen: %"PRIsVALUE, get_error_details_and_drop(&result.some));
595
+ }
596
+
597
+ VALUE start = ruby_time_from(args.slot->start_timestamp);
598
+ VALUE finish = ruby_time_from(finish_timestamp);
599
+ VALUE profile_stats = build_profile_stats(args.slot, args.serialize_no_gvl_time_ns, heap_iteration_prep_time_ns, args.heap_profile_build_time_ns);
600
+
601
+ return rb_ary_new_from_args(2, ok_symbol, rb_ary_new_from_args(4, start, finish, encoded_profile, profile_stats));
602
+ }
603
+
604
+ static VALUE ruby_time_from(ddog_Timespec ddprof_time) {
605
+ const int utc = INT_MAX - 1; // From Ruby sources
606
+ struct timespec time = {.tv_sec = ddprof_time.seconds, .tv_nsec = ddprof_time.nanoseconds};
607
+ return rb_time_timespec_new(&time, utc);
608
+ }
609
+
610
+ void record_sample(VALUE recorder_instance, ddog_prof_Slice_Location locations, sample_values values, sample_labels labels) {
611
+ stack_recorder_state *state;
612
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
613
+
614
+ locked_profile_slot active_slot = sampler_lock_active_profile(state);
615
+
616
+ // Note: We initialize this array to have ALL_VALUE_TYPES_COUNT but only tell libdatadog to use the first
617
+ // state->enabled_values_count values. This simplifies handling disabled value types -- we still put them on the
618
+ // array, but in _native_initialize we arrange so their position starts from state->enabled_values_count and thus
619
+ // libdatadog doesn't touch them.
620
+ int64_t metric_values[ALL_VALUE_TYPES_COUNT] = {0};
621
+ uint8_t *position_for = state->position_for;
622
+
623
+ metric_values[position_for[CPU_TIME_VALUE_ID]] = values.cpu_time_ns;
624
+ metric_values[position_for[CPU_SAMPLES_VALUE_ID]] = values.cpu_or_wall_samples;
625
+ metric_values[position_for[WALL_TIME_VALUE_ID]] = values.wall_time_ns;
626
+ metric_values[position_for[ALLOC_SAMPLES_VALUE_ID]] = values.alloc_samples;
627
+ metric_values[position_for[ALLOC_SAMPLES_UNSCALED_VALUE_ID]] = values.alloc_samples_unscaled;
628
+ metric_values[position_for[TIMELINE_VALUE_ID]] = values.timeline_wall_time_ns;
629
+
630
+ if (values.heap_sample) {
631
+ // If we got an allocation sample end the heap allocation recording to commit the heap sample.
632
+ // FIXME: Heap sampling currently has to be done in 2 parts because the construction of locations is happening
633
+ // very late in the allocation-sampling path (which is shared with the cpu sampling path). This can
634
+ // be fixed with some refactoring but for now this leads to a less impactful change.
635
+ //
636
+ // NOTE: The heap recorder is allowed to raise exceptions if something's wrong. But we also need to handle it
637
+ // on this side to make sure we properly unlock the active slot mutex on our way out. Otherwise, this would
638
+ // later lead to deadlocks (since the active slot mutex is not expected to be locked forever).
639
+ int exception_state = end_heap_allocation_recording_with_rb_protect(state->heap_recorder, locations);
640
+ if (exception_state) {
641
+ sampler_unlock_active_profile(active_slot);
642
+ rb_jump_tag(exception_state);
643
+ }
644
+ }
645
+
646
+ ddog_prof_Profile_Result result = ddog_prof_Profile_add(
647
+ &active_slot.data->profile,
648
+ (ddog_prof_Sample) {
649
+ .locations = locations,
650
+ .values = (ddog_Slice_I64) {.ptr = metric_values, .len = state->enabled_values_count},
651
+ .labels = labels.labels
652
+ },
653
+ labels.end_timestamp_ns
654
+ );
655
+
656
+ active_slot.data->stats.recorded_samples++;
657
+
658
+ sampler_unlock_active_profile(active_slot);
659
+
660
+ if (result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
661
+ rb_raise(rb_eArgError, "Failed to record sample: %"PRIsVALUE, get_error_details_and_drop(&result.err));
662
+ }
663
+ }
664
+
665
+ void track_object(VALUE recorder_instance, VALUE new_object, unsigned int sample_weight, ddog_CharSlice alloc_class) {
666
+ stack_recorder_state *state;
667
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
668
+ // FIXME: Heap sampling currently has to be done in 2 parts because the construction of locations is happening
669
+ // very late in the allocation-sampling path (which is shared with the cpu sampling path). This can
670
+ // be fixed with some refactoring but for now this leads to a less impactful change.
671
+ start_heap_allocation_recording(state->heap_recorder, new_object, sample_weight, alloc_class);
672
+ }
673
+
674
+ void record_endpoint(VALUE recorder_instance, uint64_t local_root_span_id, ddog_CharSlice endpoint) {
675
+ stack_recorder_state *state;
676
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
677
+
678
+ locked_profile_slot active_slot = sampler_lock_active_profile(state);
679
+
680
+ ddog_prof_Profile_Result result = ddog_prof_Profile_set_endpoint(&active_slot.data->profile, local_root_span_id, endpoint);
681
+
682
+ sampler_unlock_active_profile(active_slot);
683
+
684
+ if (result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
685
+ rb_raise(rb_eArgError, "Failed to record endpoint: %"PRIsVALUE, get_error_details_and_drop(&result.err));
686
+ }
687
+ }
688
+
689
+ void recorder_after_gc_step(VALUE recorder_instance) {
690
+ stack_recorder_state *state;
691
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
692
+
693
+ if (state->heap_clean_after_gc_enabled) heap_recorder_update_young_objects(state->heap_recorder);
694
+ }
695
+
696
+ #define MAX_LEN_HEAP_ITERATION_ERROR_MSG 256
697
+
698
+ // Heap recorder iteration context allows us access to stack recorder state and profile being serialized
699
+ // during iteration of heap recorder live objects.
700
+ typedef struct heap_recorder_iteration_context {
701
+ stack_recorder_state *state;
702
+ profile_slot *slot;
703
+
704
+ bool error;
705
+ char error_msg[MAX_LEN_HEAP_ITERATION_ERROR_MSG];
706
+ } heap_recorder_iteration_context;
707
+
708
+ static bool add_heap_sample_to_active_profile_without_gvl(heap_recorder_iteration_data iteration_data, void *extra_arg) {
709
+ heap_recorder_iteration_context *context = (heap_recorder_iteration_context*) extra_arg;
710
+
711
+ live_object_data *object_data = &iteration_data.object_data;
712
+
713
+ int64_t metric_values[ALL_VALUE_TYPES_COUNT] = {0};
714
+ uint8_t *position_for = context->state->position_for;
715
+
716
+ metric_values[position_for[HEAP_SAMPLES_VALUE_ID]] = object_data->weight;
717
+ metric_values[position_for[HEAP_SIZE_VALUE_ID]] = object_data->size * object_data->weight;
718
+
719
+ ddog_prof_Label labels[2];
720
+ size_t label_offset = 0;
721
+
722
+ if (object_data->class.value > 0) {
723
+ labels[label_offset++] = (ddog_prof_Label) {
724
+ .key_id = context->state->label_key_allocation_class,
725
+ .str_id = object_data->class,
726
+ .num = 0, // This shouldn't be needed but the tracer-2.7 docker image ships a buggy gcc that complains about this
727
+ };
728
+ }
729
+ labels[label_offset++] = (ddog_prof_Label) {
730
+ .key_id = context->state->label_key_gc_gen_age,
731
+ .num = object_data->gen_age,
732
+ };
733
+
734
+ ddog_prof_Profile_Result result = ddog_prof_Profile_add(
735
+ &context->slot->profile,
736
+ (ddog_prof_Sample) {
737
+ .locations = iteration_data.locations,
738
+ .values = (ddog_Slice_I64) {.ptr = metric_values, .len = context->state->enabled_values_count},
739
+ .labels = (ddog_prof_Slice_Label) {
740
+ .ptr = labels,
741
+ .len = label_offset,
742
+ }
743
+ },
744
+ 0
745
+ );
746
+
747
+ context->slot->stats.recorded_samples++;
748
+
749
+ if (result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
750
+ read_ddogerr_string_and_drop(&result.err, context->error_msg, MAX_LEN_HEAP_ITERATION_ERROR_MSG);
751
+ context->error = true;
752
+ // By returning false we cancel the iteration
753
+ return false;
754
+ }
755
+
756
+ // Keep on iterating to next item!
757
+ return true;
758
+ }
759
+
760
+ static void build_heap_profile_without_gvl(stack_recorder_state *state, profile_slot *slot) {
761
+ heap_recorder_iteration_context iteration_context = {
762
+ .state = state,
763
+ .slot = slot,
764
+ .error = false,
765
+ .error_msg = {0},
766
+ };
767
+ bool iterated = heap_recorder_for_each_live_object(state->heap_recorder, add_heap_sample_to_active_profile_without_gvl, (void*) &iteration_context);
768
+ // We wait until we're out of the iteration to grab the gvl and raise. This is important because during
769
+ // iteration we may potentially acquire locks in the heap recorder and we could reach a deadlock if the
770
+ // same locks are acquired by the heap recorder while holding the gvl (since we'd be operating on the
771
+ // same locks but acquiring them in different order).
772
+ if (!iterated) {
773
+ grab_gvl_and_raise(rb_eRuntimeError, "Failure during heap profile building: iteration cancelled");
774
+ }
775
+ else if (iteration_context.error) {
776
+ grab_gvl_and_raise(rb_eRuntimeError, "Failure during heap profile building: %s", iteration_context.error_msg);
777
+ }
778
+ }
779
+
780
+ static void *call_serialize_without_gvl(void *call_args) {
781
+ call_serialize_without_gvl_arguments *args = (call_serialize_without_gvl_arguments *) call_args;
782
+
783
+ long serialize_no_gvl_start_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE);
784
+
785
+ profile_slot *slot_now_inactive = serializer_flip_active_and_inactive_slots(args->state);
786
+ args->slot = slot_now_inactive;
787
+
788
+ // Now that we have the inactive profile with all but heap samples, lets fill it with heap data
789
+ // without needing to race with the active sampler
790
+ build_heap_profile_without_gvl(args->state, args->slot);
791
+ args->heap_profile_build_time_ns = monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - serialize_no_gvl_start_time_ns;
792
+
793
+ // Note: The profile gets reset by the serialize call
794
+ args->result = ddog_prof_Profile_serialize(&args->slot->profile, &args->slot->start_timestamp, &args->finish_timestamp);
795
+ args->advance_gen_result = ddog_prof_ManagedStringStorage_advance_gen(args->state->string_storage);
796
+ args->serialize_ran = true;
797
+ args->serialize_no_gvl_time_ns = long_max_of(0, monotonic_wall_time_now_ns(DO_NOT_RAISE_ON_FAILURE) - serialize_no_gvl_start_time_ns);
798
+
799
+ return NULL; // Unused
800
+ }
801
+
802
+ VALUE enforce_recorder_instance(VALUE object) {
803
+ ENFORCE_TYPED_DATA(object, &stack_recorder_typed_data);
804
+ return object;
805
+ }
806
+
807
+ static locked_profile_slot sampler_lock_active_profile(stack_recorder_state *state) {
808
+ int error;
809
+
810
+ for (int attempts = 0; attempts < 2; attempts++) {
811
+ error = pthread_mutex_trylock(&state->mutex_slot_one);
812
+ if (error && error != EBUSY) ENFORCE_SUCCESS_GVL(error);
813
+
814
+ // Slot one is active
815
+ if (!error) return (locked_profile_slot) {.mutex = &state->mutex_slot_one, .data = &state->profile_slot_one};
816
+
817
+ // If we got here, slot one was not active, let's try slot two
818
+
819
+ error = pthread_mutex_trylock(&state->mutex_slot_two);
820
+ if (error && error != EBUSY) ENFORCE_SUCCESS_GVL(error);
821
+
822
+ // Slot two is active
823
+ if (!error) return (locked_profile_slot) {.mutex = &state->mutex_slot_two, .data = &state->profile_slot_two};
824
+ }
825
+
826
+ // We already tried both multiple times, and we did not succeed. This is not expected to happen. Let's stop sampling.
827
+ rb_raise(rb_eRuntimeError, "Failed to grab either mutex in sampler_lock_active_profile");
828
+ }
829
+
830
+ static void sampler_unlock_active_profile(locked_profile_slot active_slot) {
831
+ ENFORCE_SUCCESS_GVL(pthread_mutex_unlock(active_slot.mutex));
832
+ }
833
+
834
+ static profile_slot* serializer_flip_active_and_inactive_slots(stack_recorder_state *state) {
835
+ int previously_active_slot = state->active_slot;
836
+
837
+ if (previously_active_slot != 1 && previously_active_slot != 2) {
838
+ grab_gvl_and_raise(rb_eRuntimeError, "Unexpected active_slot state %d in serializer_flip_active_and_inactive_slots", previously_active_slot);
839
+ }
840
+
841
+ pthread_mutex_t *previously_active = (previously_active_slot == 1) ? &state->mutex_slot_one : &state->mutex_slot_two;
842
+ pthread_mutex_t *previously_inactive = (previously_active_slot == 1) ? &state->mutex_slot_two : &state->mutex_slot_one;
843
+
844
+ // Release the lock, thus making this slot active
845
+ ENFORCE_SUCCESS_NO_GVL(pthread_mutex_unlock(previously_inactive));
846
+
847
+ // Grab the lock, thus making this slot inactive
848
+ ENFORCE_SUCCESS_NO_GVL(pthread_mutex_lock(previously_active));
849
+
850
+ // Update active_slot
851
+ state->active_slot = (previously_active_slot == 1) ? 2 : 1;
852
+
853
+ // Return pointer to previously active slot (now inactive)
854
+ return (previously_active_slot == 1) ? &state->profile_slot_one : &state->profile_slot_two;
855
+ }
856
+
857
+ // This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
858
+ // It SHOULD NOT be used for other purposes.
859
+ static VALUE _native_active_slot(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
860
+ stack_recorder_state *state;
861
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
862
+
863
+ return INT2NUM(state->active_slot);
864
+ }
865
+
866
+ // This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
867
+ // It SHOULD NOT be used for other purposes.
868
+ static VALUE _native_is_slot_one_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) { return test_slot_mutex_state(recorder_instance, 1); }
869
+
870
+ // This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
871
+ // It SHOULD NOT be used for other purposes.
872
+ static VALUE _native_is_slot_two_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) { return test_slot_mutex_state(recorder_instance, 2); }
873
+
874
+ static VALUE test_slot_mutex_state(VALUE recorder_instance, int slot) {
875
+ stack_recorder_state *state;
876
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
877
+
878
+ pthread_mutex_t *slot_mutex = (slot == 1) ? &state->mutex_slot_one : &state->mutex_slot_two;
879
+
880
+ // Like Heisenberg's uncertainty principle, we can't observe without affecting...
881
+ int error = pthread_mutex_trylock(slot_mutex);
882
+
883
+ if (error == 0) {
884
+ // Mutex was unlocked
885
+ ENFORCE_SUCCESS_GVL(pthread_mutex_unlock(slot_mutex));
886
+ return Qfalse;
887
+ } else if (error == EBUSY) {
888
+ // Mutex was locked
889
+ return Qtrue;
890
+ } else {
891
+ ENFORCE_SUCCESS_GVL(error);
892
+ rb_raise(rb_eRuntimeError, "Failed to raise exception in test_slot_mutex_state; this should never happen");
893
+ }
894
+ }
895
+
896
+ static ddog_Timespec system_epoch_now_timespec(void) {
897
+ long now_ns = system_epoch_time_now_ns(RAISE_ON_FAILURE);
898
+ return (ddog_Timespec) {.seconds = now_ns / SECONDS_AS_NS(1), .nanoseconds = now_ns % SECONDS_AS_NS(1)};
899
+ }
900
+
901
+ // After the Ruby VM forks, this method gets called in the child process to clean up any leftover state from the parent.
902
+ //
903
+ // Assumption: This method gets called BEFORE restarting profiling -- e.g. there are no components attempting to
904
+ // trigger samples at the same time.
905
+ static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE recorder_instance) {
906
+ stack_recorder_state *state;
907
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
908
+
909
+ // In case the fork happened halfway through `serializer_flip_active_and_inactive_slots` execution and the
910
+ // resulting state is inconsistent, we make sure to reset it back to the initial state.
911
+ initialize_slot_concurrency_control(state);
912
+ ddog_Timespec start_timestamp = system_epoch_now_timespec();
913
+ reset_profile_slot(&state->profile_slot_one, start_timestamp);
914
+ reset_profile_slot(&state->profile_slot_two, start_timestamp);
915
+
916
+ heap_recorder_after_fork(state->heap_recorder);
917
+
918
+ return Qtrue;
919
+ }
920
+
921
+ // Assumption 1: This method is called with the GVL being held, because `ddog_prof_Profile_reset` mutates the profile and must
922
+ // not be interrupted part-way through by a VM fork.
923
+ static void serializer_set_start_timestamp_for_next_profile(stack_recorder_state *state, ddog_Timespec start_time) {
924
+ // Before making this profile active, we reset it so that it uses the correct start_time for its start
925
+ profile_slot *next_profile_slot = (state->active_slot == 1) ? &state->profile_slot_two : &state->profile_slot_one;
926
+ reset_profile_slot(next_profile_slot, start_time);
927
+ }
928
+
929
+ static VALUE _native_record_endpoint(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE local_root_span_id, VALUE endpoint) {
930
+ ENFORCE_TYPE(local_root_span_id, T_FIXNUM);
931
+ record_endpoint(recorder_instance, NUM2ULL(local_root_span_id), char_slice_from_ruby_string(endpoint));
932
+ return Qtrue;
933
+ }
934
+
935
+ static VALUE _native_track_object(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE new_obj, VALUE weight, VALUE alloc_class) {
936
+ ENFORCE_TYPE(weight, T_FIXNUM);
937
+ track_object(recorder_instance, new_obj, NUM2UINT(weight), char_slice_from_ruby_string(alloc_class));
938
+ return Qtrue;
939
+ }
940
+
941
+ static void reset_profile_slot(profile_slot *slot, ddog_Timespec start_timestamp) {
942
+ ddog_prof_Profile_Result reset_result = ddog_prof_Profile_reset(&slot->profile);
943
+ if (reset_result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
944
+ rb_raise(rb_eRuntimeError, "Failed to reset profile: %"PRIsVALUE, get_error_details_and_drop(&reset_result.err));
945
+ }
946
+ slot->start_timestamp = start_timestamp;
947
+ slot->stats = (stats_slot) {};
948
+ }
949
+
950
+ // This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
951
+ // It SHOULD NOT be used for other purposes.
952
+ static VALUE _native_start_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
953
+ stack_recorder_state *state;
954
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
955
+
956
+ heap_recorder_prepare_iteration(state->heap_recorder);
957
+
958
+ return Qnil;
959
+ }
960
+
961
+ // This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
962
+ // It SHOULD NOT be used for other purposes.
963
+ static VALUE _native_end_fake_slow_heap_serialization(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
964
+ stack_recorder_state *state;
965
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
966
+
967
+ heap_recorder_finish_iteration(state->heap_recorder);
968
+
969
+ return Qnil;
970
+ }
971
+
972
+ // This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
973
+ // It SHOULD NOT be used for other purposes.
974
+ static VALUE _native_debug_heap_recorder(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
975
+ stack_recorder_state *state;
976
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
977
+
978
+ return heap_recorder_testonly_debug(state->heap_recorder);
979
+ }
980
+
981
+ static VALUE _native_stats(DDTRACE_UNUSED VALUE self, VALUE recorder_instance) {
982
+ stack_recorder_state *state;
983
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
984
+
985
+ uint64_t total_serializations = state->stats_lifetime.serialization_successes + state->stats_lifetime.serialization_failures;
986
+
987
+ VALUE heap_recorder_snapshot = state->heap_recorder ?
988
+ heap_recorder_state_snapshot(state->heap_recorder) : Qnil;
989
+
990
+ VALUE stats_as_hash = rb_hash_new();
991
+ VALUE arguments[] = {
992
+ ID2SYM(rb_intern("serialization_successes")), /* => */ ULL2NUM(state->stats_lifetime.serialization_successes),
993
+ ID2SYM(rb_intern("serialization_failures")), /* => */ ULL2NUM(state->stats_lifetime.serialization_failures),
994
+
995
+ ID2SYM(rb_intern("serialization_time_ns_min")), /* => */ RUBY_NUM_OR_NIL(state->stats_lifetime.serialization_time_ns_min, != INT64_MAX, LONG2NUM),
996
+ ID2SYM(rb_intern("serialization_time_ns_max")), /* => */ RUBY_NUM_OR_NIL(state->stats_lifetime.serialization_time_ns_max, > 0, LONG2NUM),
997
+ ID2SYM(rb_intern("serialization_time_ns_total")), /* => */ RUBY_NUM_OR_NIL(state->stats_lifetime.serialization_time_ns_total, > 0, LONG2NUM),
998
+ ID2SYM(rb_intern("serialization_time_ns_avg")), /* => */ RUBY_AVG_OR_NIL(state->stats_lifetime.serialization_time_ns_total, total_serializations),
999
+
1000
+ ID2SYM(rb_intern("heap_recorder_snapshot")), /* => */ heap_recorder_snapshot,
1001
+ };
1002
+ for (long unsigned int i = 0; i < VALUE_COUNT(arguments); i += 2) rb_hash_aset(stats_as_hash, arguments[i], arguments[i+1]);
1003
+ return stats_as_hash;
1004
+ }
1005
+
1006
+ static VALUE build_profile_stats(profile_slot *slot, long serialization_time_ns, long heap_iteration_prep_time_ns, long heap_profile_build_time_ns) {
1007
+ VALUE stats_as_hash = rb_hash_new();
1008
+ VALUE arguments[] = {
1009
+ ID2SYM(rb_intern("recorded_samples")), /* => */ ULL2NUM(slot->stats.recorded_samples),
1010
+ ID2SYM(rb_intern("serialization_time_ns")), /* => */ LONG2NUM(serialization_time_ns),
1011
+ ID2SYM(rb_intern("heap_iteration_prep_time_ns")), /* => */ LONG2NUM(heap_iteration_prep_time_ns),
1012
+ ID2SYM(rb_intern("heap_profile_build_time_ns")), /* => */ LONG2NUM(heap_profile_build_time_ns),
1013
+ };
1014
+ for (long unsigned int i = 0; i < VALUE_COUNT(arguments); i += 2) rb_hash_aset(stats_as_hash, arguments[i], arguments[i+1]);
1015
+ return stats_as_hash;
1016
+ }
1017
+
1018
+ static VALUE _native_is_object_recorded(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE obj_id) {
1019
+ ENFORCE_TYPE(obj_id, T_FIXNUM);
1020
+
1021
+ stack_recorder_state *state;
1022
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
1023
+
1024
+ return heap_recorder_testonly_is_object_recorded(state->heap_recorder, obj_id);
1025
+ }
1026
+
1027
+ static VALUE _native_heap_recorder_reset_last_update(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
1028
+ stack_recorder_state *state;
1029
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
1030
+
1031
+ heap_recorder_testonly_reset_last_update(state->heap_recorder);
1032
+
1033
+ return Qtrue;
1034
+ }
1035
+
1036
+ static VALUE _native_recorder_after_gc_step(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
1037
+ recorder_after_gc_step(recorder_instance);
1038
+ return Qtrue;
1039
+ }
1040
+
1041
+ static VALUE _native_benchmark_intern(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE string, VALUE times, VALUE use_all) {
1042
+ ENFORCE_TYPE(string, T_STRING);
1043
+ ENFORCE_TYPE(times, T_FIXNUM);
1044
+ ENFORCE_BOOLEAN(use_all);
1045
+
1046
+ stack_recorder_state *state;
1047
+ TypedData_Get_Struct(recorder_instance, stack_recorder_state, &stack_recorder_typed_data, state);
1048
+
1049
+ heap_recorder_testonly_benchmark_intern(state->heap_recorder, char_slice_from_ruby_string(string), FIX2INT(times), use_all == Qtrue);
1050
+
1051
+ return Qtrue;
1052
+ }
1053
+
1054
+ // See comments in rspec test for details on what we're testing here.
1055
+ static VALUE _native_test_managed_string_storage_produces_valid_profiles(DDTRACE_UNUSED VALUE _self) {
1056
+ ddog_prof_ManagedStringStorageNewResult string_storage = ddog_prof_ManagedStringStorage_new();
1057
+
1058
+ if (string_storage.tag == DDOG_PROF_MANAGED_STRING_STORAGE_NEW_RESULT_ERR) {
1059
+ rb_raise(rb_eRuntimeError, "Failed to initialize string storage: %"PRIsVALUE, get_error_details_and_drop(&string_storage.err));
1060
+ }
1061
+
1062
+ ddog_prof_Slice_ValueType sample_types = {.ptr = all_value_types, .len = ALL_VALUE_TYPES_COUNT};
1063
+ ddog_prof_Profile_NewResult profile = ddog_prof_Profile_with_string_storage(sample_types, NULL, string_storage.ok);
1064
+
1065
+ if (profile.tag == DDOG_PROF_PROFILE_NEW_RESULT_ERR) {
1066
+ rb_raise(rb_eRuntimeError, "Failed to initialize profile: %"PRIsVALUE, get_error_details_and_drop(&profile.err));
1067
+ }
1068
+
1069
+ ddog_prof_ManagedStringId hello = intern_or_raise(string_storage.ok, DDOG_CHARSLICE_C("hello"));
1070
+ ddog_prof_ManagedStringId world = intern_or_raise(string_storage.ok, DDOG_CHARSLICE_C("world"));
1071
+ ddog_prof_ManagedStringId key = intern_or_raise(string_storage.ok, DDOG_CHARSLICE_C("key"));
1072
+
1073
+ int64_t metric_values[] = {1, 2, 3, 4, 5, 6, 7, 8};
1074
+ ddog_prof_Label labels[] = {{.key_id = key, .str_id = key}};
1075
+
1076
+ ddog_prof_Location locations[] = {
1077
+ (ddog_prof_Location) {
1078
+ .mapping = {.filename = DDOG_CHARSLICE_C(""), .build_id = DDOG_CHARSLICE_C(""), .build_id_id = {}},
1079
+ .function = {
1080
+ .name = DDOG_CHARSLICE_C(""),
1081
+ .name_id = hello,
1082
+ .filename = DDOG_CHARSLICE_C(""),
1083
+ .filename_id = world,
1084
+ },
1085
+ .line = 1,
1086
+ }
1087
+ };
1088
+
1089
+ ddog_prof_Profile_Result result = ddog_prof_Profile_add(
1090
+ &profile.ok,
1091
+ (ddog_prof_Sample) {
1092
+ .locations = (ddog_prof_Slice_Location) { .ptr = locations, .len = 1},
1093
+ .values = (ddog_Slice_I64) {.ptr = metric_values, .len = 8},
1094
+ .labels = (ddog_prof_Slice_Label) { .ptr = labels, .len = 1 }
1095
+ },
1096
+ 0
1097
+ );
1098
+
1099
+ if (result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
1100
+ rb_raise(rb_eArgError, "Failed to record sample: %"PRIsVALUE, get_error_details_and_drop(&result.err));
1101
+ }
1102
+
1103
+ ddog_Timespec finish_timestamp = system_epoch_now_timespec();
1104
+ ddog_Timespec start_timestamp = {.seconds = finish_timestamp.seconds - 60};
1105
+ ddog_prof_Profile_SerializeResult serialize_result = ddog_prof_Profile_serialize(&profile.ok, &start_timestamp, &finish_timestamp);
1106
+
1107
+ if (serialize_result.tag == DDOG_PROF_PROFILE_SERIALIZE_RESULT_ERR) {
1108
+ rb_raise(rb_eRuntimeError, "Failed to serialize: %"PRIsVALUE, get_error_details_and_drop(&serialize_result.err));
1109
+ }
1110
+
1111
+ ddog_prof_MaybeError advance_gen_result = ddog_prof_ManagedStringStorage_advance_gen(string_storage.ok);
1112
+
1113
+ if (advance_gen_result.tag == DDOG_PROF_OPTION_ERROR_SOME_ERROR) {
1114
+ rb_raise(rb_eRuntimeError, "Failed to advance string storage gen: %"PRIsVALUE, get_error_details_and_drop(&advance_gen_result.some));
1115
+ }
1116
+
1117
+ VALUE encoded_pprof_1 = from_ddog_prof_EncodedProfile(serialize_result.ok);
1118
+
1119
+ result = ddog_prof_Profile_add(
1120
+ &profile.ok,
1121
+ (ddog_prof_Sample) {
1122
+ .locations = (ddog_prof_Slice_Location) { .ptr = locations, .len = 1},
1123
+ .values = (ddog_Slice_I64) {.ptr = metric_values, .len = 8},
1124
+ .labels = (ddog_prof_Slice_Label) { .ptr = labels, .len = 1 }
1125
+ },
1126
+ 0
1127
+ );
1128
+
1129
+ if (result.tag == DDOG_PROF_PROFILE_RESULT_ERR) {
1130
+ rb_raise(rb_eArgError, "Failed to record sample: %"PRIsVALUE, get_error_details_and_drop(&result.err));
1131
+ }
1132
+
1133
+ serialize_result = ddog_prof_Profile_serialize(&profile.ok, &start_timestamp, &finish_timestamp);
1134
+
1135
+ if (serialize_result.tag == DDOG_PROF_PROFILE_SERIALIZE_RESULT_ERR) {
1136
+ rb_raise(rb_eArgError, "Failed to serialize: %"PRIsVALUE, get_error_details_and_drop(&serialize_result.err));
1137
+ }
1138
+
1139
+ VALUE encoded_pprof_2 = from_ddog_prof_EncodedProfile(serialize_result.ok);
1140
+
1141
+ ddog_prof_Profile_drop(&profile.ok);
1142
+ ddog_prof_ManagedStringStorage_drop(string_storage.ok);
1143
+
1144
+ return rb_ary_new_from_args(2, encoded_pprof_1, encoded_pprof_2);
1145
+ }