ddtrace 1.4.2 → 1.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (870) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +986 -2
  3. data/LICENSE-3rdparty.csv +2 -0
  4. data/README.md +10 -12
  5. data/ext/ddtrace_profiling_loader/ddtrace_profiling_loader.c +9 -2
  6. data/ext/ddtrace_profiling_loader/extconf.rb +21 -3
  7. data/ext/ddtrace_profiling_native_extension/NativeExtensionDesign.md +48 -12
  8. data/ext/ddtrace_profiling_native_extension/clock_id.h +1 -3
  9. data/ext/ddtrace_profiling_native_extension/clock_id_from_pthread.c +6 -23
  10. data/ext/ddtrace_profiling_native_extension/clock_id_noop.c +0 -1
  11. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +719 -129
  12. data/ext/ddtrace_profiling_native_extension/collectors_dynamic_sampling_rate.c +150 -0
  13. data/ext/ddtrace_profiling_native_extension/collectors_dynamic_sampling_rate.h +18 -0
  14. data/ext/ddtrace_profiling_native_extension/collectors_gc_profiling_helper.c +156 -0
  15. data/ext/ddtrace_profiling_native_extension/collectors_gc_profiling_helper.h +5 -0
  16. data/ext/ddtrace_profiling_native_extension/collectors_idle_sampling_helper.c +244 -0
  17. data/ext/ddtrace_profiling_native_extension/collectors_idle_sampling_helper.h +3 -0
  18. data/ext/ddtrace_profiling_native_extension/collectors_stack.c +184 -94
  19. data/ext/ddtrace_profiling_native_extension/collectors_stack.h +20 -2
  20. data/ext/ddtrace_profiling_native_extension/collectors_thread_context.c +1301 -0
  21. data/ext/ddtrace_profiling_native_extension/collectors_thread_context.h +15 -0
  22. data/ext/ddtrace_profiling_native_extension/extconf.rb +103 -28
  23. data/ext/ddtrace_profiling_native_extension/heap_recorder.c +970 -0
  24. data/ext/ddtrace_profiling_native_extension/heap_recorder.h +155 -0
  25. data/ext/ddtrace_profiling_native_extension/helpers.h +7 -0
  26. data/ext/ddtrace_profiling_native_extension/http_transport.c +133 -88
  27. data/ext/ddtrace_profiling_native_extension/libdatadog_helpers.c +62 -0
  28. data/ext/ddtrace_profiling_native_extension/libdatadog_helpers.h +32 -4
  29. data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +55 -26
  30. data/ext/ddtrace_profiling_native_extension/pid_controller.c +57 -0
  31. data/ext/ddtrace_profiling_native_extension/pid_controller.h +45 -0
  32. data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +317 -131
  33. data/ext/ddtrace_profiling_native_extension/private_vm_api_access.h +25 -1
  34. data/ext/ddtrace_profiling_native_extension/profiling.c +219 -4
  35. data/ext/ddtrace_profiling_native_extension/ruby_helpers.c +233 -1
  36. data/ext/ddtrace_profiling_native_extension/ruby_helpers.h +60 -8
  37. data/ext/ddtrace_profiling_native_extension/setup_signal_handler.c +115 -0
  38. data/ext/ddtrace_profiling_native_extension/setup_signal_handler.h +11 -0
  39. data/ext/ddtrace_profiling_native_extension/stack_recorder.c +585 -66
  40. data/ext/ddtrace_profiling_native_extension/stack_recorder.h +19 -30
  41. data/ext/ddtrace_profiling_native_extension/time_helpers.c +53 -0
  42. data/ext/ddtrace_profiling_native_extension/time_helpers.h +24 -0
  43. data/lib/datadog/appsec/assets/blocked.html +98 -3
  44. data/lib/datadog/appsec/assets/blocked.json +1 -0
  45. data/lib/datadog/appsec/assets/blocked.text +5 -0
  46. data/lib/datadog/appsec/assets/waf_rules/processors.json +92 -0
  47. data/lib/datadog/appsec/assets/waf_rules/recommended.json +2861 -796
  48. data/lib/datadog/appsec/assets/waf_rules/scanners.json +114 -0
  49. data/lib/datadog/appsec/assets/waf_rules/strict.json +459 -122
  50. data/lib/datadog/appsec/assets.rb +10 -4
  51. data/lib/datadog/appsec/autoload.rb +4 -11
  52. data/lib/datadog/appsec/component.rb +94 -0
  53. data/lib/datadog/appsec/configuration/settings.rb +170 -162
  54. data/lib/datadog/appsec/configuration.rb +1 -70
  55. data/lib/datadog/appsec/contrib/auto_instrument.rb +3 -5
  56. data/lib/datadog/appsec/contrib/devise/event.rb +57 -0
  57. data/lib/datadog/appsec/contrib/devise/ext.rb +13 -0
  58. data/lib/datadog/appsec/contrib/devise/integration.rb +42 -0
  59. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +76 -0
  60. data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +54 -0
  61. data/lib/datadog/appsec/contrib/devise/patcher.rb +45 -0
  62. data/lib/datadog/appsec/contrib/devise/resource.rb +35 -0
  63. data/lib/datadog/appsec/contrib/devise/tracking.rb +49 -0
  64. data/lib/datadog/appsec/contrib/integration.rb +1 -1
  65. data/lib/datadog/appsec/contrib/patcher.rb +1 -1
  66. data/lib/datadog/appsec/contrib/rack/ext.rb +1 -3
  67. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +104 -0
  68. data/lib/datadog/appsec/contrib/rack/gateway/response.rb +30 -0
  69. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +112 -121
  70. data/lib/datadog/appsec/contrib/rack/integration.rb +0 -7
  71. data/lib/datadog/appsec/contrib/rack/patcher.rb +3 -1
  72. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +33 -39
  73. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +19 -23
  74. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +25 -23
  75. data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +11 -8
  76. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +122 -41
  77. data/lib/datadog/appsec/contrib/rails/ext.rb +2 -4
  78. data/lib/datadog/appsec/contrib/rails/framework.rb +2 -16
  79. data/lib/datadog/appsec/contrib/rails/gateway/request.rb +67 -0
  80. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +40 -52
  81. data/lib/datadog/appsec/contrib/rails/integration.rb +1 -8
  82. data/lib/datadog/appsec/contrib/rails/patcher.rb +23 -20
  83. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +21 -23
  84. data/lib/datadog/appsec/contrib/rails/request.rb +4 -1
  85. data/lib/datadog/appsec/contrib/rails/request_middleware.rb +1 -1
  86. data/lib/datadog/appsec/contrib/sinatra/ext.rb +2 -3
  87. data/lib/datadog/appsec/contrib/sinatra/framework.rb +2 -16
  88. data/lib/datadog/appsec/contrib/sinatra/gateway/request.rb +17 -0
  89. data/lib/datadog/appsec/contrib/sinatra/gateway/route_params.rb +23 -0
  90. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +78 -87
  91. data/lib/datadog/appsec/contrib/sinatra/integration.rb +0 -7
  92. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +33 -15
  93. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +19 -21
  94. data/lib/datadog/appsec/contrib/sinatra/request_middleware.rb +1 -1
  95. data/lib/datadog/appsec/event.rb +98 -50
  96. data/lib/datadog/appsec/ext.rb +10 -0
  97. data/lib/datadog/appsec/extensions.rb +2 -105
  98. data/lib/datadog/appsec/instrumentation/gateway/argument.rb +22 -0
  99. data/lib/datadog/appsec/instrumentation/gateway.rb +26 -6
  100. data/lib/datadog/appsec/instrumentation.rb +9 -0
  101. data/lib/datadog/appsec/monitor/gateway/watcher.rb +67 -0
  102. data/lib/datadog/appsec/monitor/reactive/set_user.rb +58 -0
  103. data/lib/datadog/appsec/monitor.rb +11 -0
  104. data/lib/datadog/appsec/processor/actions.rb +49 -0
  105. data/lib/datadog/appsec/processor/rule_loader.rb +123 -0
  106. data/lib/datadog/appsec/processor/rule_merger.rb +152 -0
  107. data/lib/datadog/appsec/processor.rb +68 -61
  108. data/lib/datadog/appsec/rate_limiter.rb +1 -3
  109. data/lib/datadog/appsec/reactive/address_hash.rb +6 -2
  110. data/lib/datadog/appsec/reactive/engine.rb +10 -7
  111. data/lib/datadog/appsec/reactive/operation.rb +19 -2
  112. data/lib/datadog/appsec/reactive/subscriber.rb +2 -1
  113. data/lib/datadog/appsec/remote.rb +129 -0
  114. data/lib/datadog/appsec/response.rb +151 -0
  115. data/lib/datadog/appsec/sample_rate.rb +21 -0
  116. data/lib/datadog/appsec/scope.rb +61 -0
  117. data/lib/datadog/appsec/utils/http/media_range.rb +199 -0
  118. data/lib/datadog/appsec/utils/http/media_type.rb +85 -0
  119. data/lib/datadog/appsec/utils/http.rb +11 -0
  120. data/lib/datadog/appsec/utils.rb +9 -0
  121. data/lib/datadog/appsec.rb +41 -4
  122. data/lib/datadog/core/backport.rb +51 -0
  123. data/lib/datadog/core/buffer/cruby.rb +1 -1
  124. data/lib/datadog/core/buffer/random.rb +1 -1
  125. data/lib/datadog/core/buffer/thread_safe.rb +1 -1
  126. data/lib/datadog/core/chunker.rb +1 -1
  127. data/lib/datadog/core/configuration/agent_settings_resolver.rb +96 -56
  128. data/lib/datadog/core/configuration/base.rb +7 -16
  129. data/lib/datadog/core/configuration/components.rb +40 -296
  130. data/lib/datadog/core/configuration/ext.rb +47 -0
  131. data/lib/datadog/core/configuration/option.rb +270 -22
  132. data/lib/datadog/core/configuration/option_definition.rb +81 -31
  133. data/lib/datadog/core/configuration/options.rb +26 -16
  134. data/lib/datadog/core/configuration/settings.rb +419 -305
  135. data/lib/datadog/core/configuration.rb +10 -6
  136. data/lib/datadog/core/diagnostics/environment_logger.rb +129 -230
  137. data/lib/datadog/core/diagnostics/health.rb +4 -22
  138. data/lib/datadog/core/encoding.rb +0 -4
  139. data/lib/datadog/core/environment/cgroup.rb +0 -4
  140. data/lib/datadog/core/environment/class_count.rb +1 -1
  141. data/lib/datadog/core/environment/container.rb +0 -4
  142. data/lib/datadog/core/environment/execution.rb +103 -0
  143. data/lib/datadog/core/environment/ext.rb +12 -12
  144. data/lib/datadog/core/environment/gc.rb +1 -1
  145. data/lib/datadog/core/environment/identity.rb +57 -1
  146. data/lib/datadog/core/environment/platform.rb +0 -2
  147. data/lib/datadog/core/environment/socket.rb +1 -1
  148. data/lib/datadog/core/environment/thread_count.rb +1 -1
  149. data/lib/datadog/core/environment/variable_helpers.rb +29 -44
  150. data/lib/datadog/core/environment/vm_cache.rb +18 -1
  151. data/lib/datadog/core/environment/yjit.rb +58 -0
  152. data/lib/datadog/core/error.rb +1 -2
  153. data/lib/datadog/core/extensions.rb +1 -1
  154. data/lib/datadog/core/git/ext.rb +25 -23
  155. data/lib/datadog/core/header_collection.rb +43 -0
  156. data/lib/datadog/core/logger.rb +0 -2
  157. data/lib/datadog/core/logging/ext.rb +3 -1
  158. data/lib/datadog/core/metrics/client.rb +3 -4
  159. data/lib/datadog/core/metrics/ext.rb +6 -8
  160. data/lib/datadog/core/metrics/helpers.rb +1 -1
  161. data/lib/datadog/core/metrics/logging.rb +0 -2
  162. data/lib/datadog/core/metrics/metric.rb +1 -1
  163. data/lib/datadog/core/metrics/options.rb +0 -2
  164. data/lib/datadog/core/pin.rb +0 -2
  165. data/lib/datadog/core/remote/client/capabilities.rb +62 -0
  166. data/lib/datadog/core/remote/client.rb +232 -0
  167. data/lib/datadog/core/remote/component.rb +149 -0
  168. data/lib/datadog/core/remote/configuration/content.rb +111 -0
  169. data/lib/datadog/core/remote/configuration/digest.rb +62 -0
  170. data/lib/datadog/core/remote/configuration/path.rb +90 -0
  171. data/lib/datadog/core/remote/configuration/repository.rb +294 -0
  172. data/lib/datadog/core/remote/configuration/target.rb +74 -0
  173. data/lib/datadog/core/remote/configuration.rb +18 -0
  174. data/lib/datadog/core/remote/dispatcher.rb +59 -0
  175. data/lib/datadog/core/remote/ext.rb +12 -0
  176. data/lib/datadog/core/remote/negotiation.rb +70 -0
  177. data/lib/datadog/core/remote/transport/config.rb +60 -0
  178. data/lib/datadog/core/remote/transport/http/api/instance.rb +39 -0
  179. data/lib/datadog/core/remote/transport/http/api/spec.rb +21 -0
  180. data/lib/datadog/core/remote/transport/http/api.rb +58 -0
  181. data/lib/datadog/core/remote/transport/http/builder.rb +219 -0
  182. data/lib/datadog/core/remote/transport/http/client.rb +48 -0
  183. data/lib/datadog/core/remote/transport/http/config.rb +280 -0
  184. data/lib/datadog/core/remote/transport/http/negotiation.rb +146 -0
  185. data/lib/datadog/core/remote/transport/http.rb +179 -0
  186. data/lib/datadog/core/remote/transport/negotiation.rb +62 -0
  187. data/lib/datadog/core/remote/worker.rb +99 -0
  188. data/lib/datadog/core/remote.rb +24 -0
  189. data/lib/datadog/core/runtime/ext.rb +21 -11
  190. data/lib/datadog/core/runtime/metrics.rb +64 -7
  191. data/lib/datadog/core/telemetry/client.rb +12 -4
  192. data/lib/datadog/core/telemetry/collector.rb +34 -18
  193. data/lib/datadog/core/telemetry/emitter.rb +4 -4
  194. data/lib/datadog/core/telemetry/event.rb +20 -8
  195. data/lib/datadog/core/telemetry/ext.rb +6 -2
  196. data/lib/datadog/core/telemetry/heartbeat.rb +3 -5
  197. data/lib/datadog/core/telemetry/http/adapters/net.rb +0 -2
  198. data/lib/datadog/core/telemetry/http/env.rb +1 -1
  199. data/lib/datadog/core/telemetry/http/ext.rb +10 -8
  200. data/lib/datadog/core/telemetry/http/response.rb +0 -4
  201. data/lib/datadog/core/telemetry/http/transport.rb +4 -1
  202. data/lib/datadog/core/telemetry/v1/app_event.rb +10 -3
  203. data/lib/datadog/core/telemetry/v1/application.rb +7 -1
  204. data/lib/datadog/core/telemetry/v1/dependency.rb +9 -2
  205. data/lib/datadog/core/telemetry/v1/host.rb +9 -1
  206. data/lib/datadog/core/telemetry/v1/install_signature.rb +38 -0
  207. data/lib/datadog/core/telemetry/v1/integration.rb +7 -1
  208. data/lib/datadog/core/telemetry/v1/product.rb +9 -1
  209. data/lib/datadog/core/telemetry/v1/telemetry_request.rb +7 -1
  210. data/lib/datadog/core/telemetry/v2/app_client_configuration_change.rb +41 -0
  211. data/lib/datadog/core/telemetry/v2/request.rb +29 -0
  212. data/lib/datadog/core/transport/ext.rb +47 -0
  213. data/lib/datadog/core/transport/http/adapters/net.rb +168 -0
  214. data/lib/datadog/core/transport/http/adapters/registry.rb +29 -0
  215. data/lib/datadog/core/transport/http/adapters/test.rb +89 -0
  216. data/lib/datadog/core/transport/http/adapters/unix_socket.rb +83 -0
  217. data/lib/datadog/core/transport/http/api/endpoint.rb +31 -0
  218. data/lib/datadog/core/transport/http/api/fallbacks.rb +26 -0
  219. data/lib/datadog/core/transport/http/api/map.rb +18 -0
  220. data/lib/datadog/core/transport/http/env.rb +62 -0
  221. data/lib/datadog/core/transport/http/response.rb +60 -0
  222. data/lib/datadog/core/transport/parcel.rb +22 -0
  223. data/lib/datadog/core/transport/request.rb +17 -0
  224. data/lib/datadog/core/transport/response.rb +64 -0
  225. data/lib/datadog/core/utils/compression.rb +6 -2
  226. data/lib/datadog/core/utils/duration.rb +52 -0
  227. data/lib/datadog/core/utils/forking.rb +0 -2
  228. data/lib/datadog/core/utils/hash.rb +79 -0
  229. data/lib/datadog/core/utils/network.rb +140 -0
  230. data/lib/datadog/core/utils/only_once.rb +0 -2
  231. data/lib/datadog/core/utils/safe_dup.rb +35 -12
  232. data/lib/datadog/core/utils/sequence.rb +1 -1
  233. data/lib/datadog/core/utils/time.rb +1 -3
  234. data/lib/datadog/core/utils.rb +1 -24
  235. data/lib/datadog/core/vendor/ipaddr.rb +78 -0
  236. data/lib/datadog/core/vendor/multipart-post/multipart/post/composite_read_io.rb +0 -2
  237. data/lib/datadog/core/vendor/multipart-post/multipart/post/multipartable.rb +0 -2
  238. data/lib/datadog/core/vendor/multipart-post/multipart/post/parts.rb +0 -2
  239. data/lib/datadog/core/vendor/multipart-post/multipart/post/version.rb +0 -2
  240. data/lib/datadog/core/vendor/multipart-post/multipart/post.rb +0 -2
  241. data/lib/datadog/core/vendor/multipart-post/multipart.rb +0 -2
  242. data/lib/datadog/core/vendor/multipart-post/net/http/post/multipart.rb +0 -2
  243. data/lib/datadog/core/worker.rb +1 -1
  244. data/lib/datadog/core/workers/async.rb +7 -6
  245. data/lib/datadog/core/workers/interval_loop.rb +6 -2
  246. data/lib/datadog/core/workers/polling.rb +2 -4
  247. data/lib/datadog/core/workers/queue.rb +1 -1
  248. data/lib/datadog/core/workers/runtime_metrics.rb +1 -1
  249. data/lib/datadog/core.rb +20 -55
  250. data/lib/datadog/kit/appsec/events.rb +169 -0
  251. data/lib/datadog/kit/enable_core_dumps.rb +8 -9
  252. data/lib/datadog/kit/identity.rb +90 -49
  253. data/lib/datadog/kit.rb +1 -1
  254. data/lib/datadog/opentelemetry/api/context.rb +193 -0
  255. data/lib/datadog/opentelemetry/api/trace/span.rb +14 -0
  256. data/lib/datadog/opentelemetry/sdk/configurator.rb +37 -0
  257. data/lib/datadog/opentelemetry/sdk/id_generator.rb +26 -0
  258. data/lib/datadog/opentelemetry/sdk/propagator.rb +91 -0
  259. data/lib/datadog/opentelemetry/sdk/span_processor.rb +134 -0
  260. data/lib/datadog/opentelemetry/sdk/trace/span.rb +167 -0
  261. data/lib/datadog/opentelemetry/trace.rb +58 -0
  262. data/lib/datadog/opentelemetry.rb +48 -0
  263. data/lib/datadog/opentracer/binary_propagator.rb +1 -1
  264. data/lib/datadog/opentracer/carrier.rb +1 -1
  265. data/lib/datadog/opentracer/distributed_headers.rb +7 -11
  266. data/lib/datadog/opentracer/global_tracer.rb +1 -1
  267. data/lib/datadog/opentracer/propagator.rb +1 -1
  268. data/lib/datadog/opentracer/rack_propagator.rb +0 -5
  269. data/lib/datadog/opentracer/scope.rb +1 -1
  270. data/lib/datadog/opentracer/scope_manager.rb +1 -1
  271. data/lib/datadog/opentracer/span.rb +0 -2
  272. data/lib/datadog/opentracer/span_context.rb +1 -1
  273. data/lib/datadog/opentracer/span_context_factory.rb +1 -1
  274. data/lib/datadog/opentracer/text_map_propagator.rb +6 -9
  275. data/lib/datadog/opentracer/thread_local_scope.rb +1 -1
  276. data/lib/datadog/opentracer/thread_local_scope_manager.rb +0 -2
  277. data/lib/datadog/opentracer/tracer.rb +0 -2
  278. data/lib/datadog/opentracer.rb +10 -1
  279. data/lib/datadog/profiling/collectors/code_provenance.rb +0 -2
  280. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +53 -19
  281. data/lib/datadog/profiling/collectors/dynamic_sampling_rate.rb +14 -0
  282. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +68 -0
  283. data/lib/datadog/profiling/collectors/stack.rb +1 -1
  284. data/lib/datadog/profiling/collectors/thread_context.rb +61 -0
  285. data/lib/datadog/profiling/component.rb +434 -0
  286. data/lib/datadog/profiling/diagnostics/environment_logger.rb +39 -0
  287. data/lib/datadog/profiling/exporter.rb +12 -7
  288. data/lib/datadog/profiling/ext/forking.rb +0 -2
  289. data/lib/datadog/profiling/ext.rb +20 -32
  290. data/lib/datadog/profiling/flush.rb +8 -6
  291. data/lib/datadog/profiling/http_transport.rb +19 -8
  292. data/lib/datadog/profiling/load_native_extension.rb +7 -3
  293. data/lib/datadog/profiling/native_extension.rb +1 -22
  294. data/lib/datadog/profiling/preload.rb +1 -1
  295. data/lib/datadog/profiling/profiler.rb +42 -14
  296. data/lib/datadog/profiling/scheduler.rb +27 -25
  297. data/lib/datadog/profiling/stack_recorder.rb +30 -6
  298. data/lib/datadog/profiling/tag_builder.rb +1 -1
  299. data/lib/datadog/profiling/tasks/exec.rb +0 -2
  300. data/lib/datadog/profiling/tasks/help.rb +0 -2
  301. data/lib/datadog/profiling/tasks/setup.rb +0 -35
  302. data/lib/datadog/profiling.rb +53 -74
  303. data/lib/datadog/tracing/analytics.rb +1 -1
  304. data/lib/datadog/tracing/buffer.rb +0 -5
  305. data/lib/datadog/tracing/client_ip.rb +61 -0
  306. data/lib/datadog/tracing/component.rb +235 -0
  307. data/lib/datadog/tracing/configuration/agent_settings_resolver.rb +13 -0
  308. data/lib/datadog/tracing/configuration/dynamic/option.rb +71 -0
  309. data/lib/datadog/tracing/configuration/dynamic.rb +64 -0
  310. data/lib/datadog/tracing/configuration/ext.rb +73 -15
  311. data/lib/datadog/tracing/configuration/http.rb +74 -0
  312. data/lib/datadog/tracing/configuration/settings.rb +501 -0
  313. data/lib/datadog/tracing/context.rb +1 -1
  314. data/lib/datadog/tracing/context_provider.rb +0 -2
  315. data/lib/datadog/tracing/contrib/action_cable/configuration/settings.rb +10 -7
  316. data/lib/datadog/tracing/contrib/action_cable/event.rb +1 -1
  317. data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +0 -2
  318. data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +0 -2
  319. data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +0 -2
  320. data/lib/datadog/tracing/contrib/action_cable/events.rb +1 -1
  321. data/lib/datadog/tracing/contrib/action_cable/ext.rb +19 -19
  322. data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +0 -2
  323. data/lib/datadog/tracing/contrib/action_cable/integration.rb +0 -2
  324. data/lib/datadog/tracing/contrib/action_cable/patcher.rb +1 -1
  325. data/lib/datadog/tracing/contrib/action_mailer/configuration/settings.rb +10 -7
  326. data/lib/datadog/tracing/contrib/action_mailer/event.rb +1 -1
  327. data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +0 -2
  328. data/lib/datadog/tracing/contrib/action_mailer/events/process.rb +0 -2
  329. data/lib/datadog/tracing/contrib/action_mailer/events.rb +1 -1
  330. data/lib/datadog/tracing/contrib/action_mailer/ext.rb +19 -19
  331. data/lib/datadog/tracing/contrib/action_mailer/integration.rb +0 -2
  332. data/lib/datadog/tracing/contrib/action_mailer/patcher.rb +1 -1
  333. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +2 -26
  334. data/lib/datadog/tracing/contrib/action_pack/action_controller/patcher.rb +1 -1
  335. data/lib/datadog/tracing/contrib/action_pack/configuration/settings.rb +22 -9
  336. data/lib/datadog/tracing/contrib/action_pack/ext.rb +9 -9
  337. data/lib/datadog/tracing/contrib/action_pack/integration.rb +0 -2
  338. data/lib/datadog/tracing/contrib/action_pack/patcher.rb +1 -1
  339. data/lib/datadog/tracing/contrib/action_pack/utils.rb +0 -2
  340. data/lib/datadog/tracing/contrib/action_view/configuration/settings.rb +9 -8
  341. data/lib/datadog/tracing/contrib/action_view/event.rb +1 -1
  342. data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +0 -2
  343. data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +0 -2
  344. data/lib/datadog/tracing/contrib/action_view/events.rb +1 -1
  345. data/lib/datadog/tracing/contrib/action_view/ext.rb +11 -11
  346. data/lib/datadog/tracing/contrib/action_view/instrumentation/partial_renderer.rb +0 -2
  347. data/lib/datadog/tracing/contrib/action_view/instrumentation/template_renderer.rb +0 -2
  348. data/lib/datadog/tracing/contrib/action_view/integration.rb +0 -2
  349. data/lib/datadog/tracing/contrib/action_view/patcher.rb +0 -2
  350. data/lib/datadog/tracing/contrib/action_view/utils.rb +0 -2
  351. data/lib/datadog/tracing/contrib/active_job/configuration/settings.rb +14 -8
  352. data/lib/datadog/tracing/contrib/active_job/event.rb +1 -1
  353. data/lib/datadog/tracing/contrib/active_job/events/discard.rb +0 -2
  354. data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +0 -2
  355. data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +0 -2
  356. data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +0 -2
  357. data/lib/datadog/tracing/contrib/active_job/events/perform.rb +0 -2
  358. data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +0 -2
  359. data/lib/datadog/tracing/contrib/active_job/events.rb +1 -1
  360. data/lib/datadog/tracing/contrib/active_job/ext.rb +24 -24
  361. data/lib/datadog/tracing/contrib/active_job/integration.rb +0 -2
  362. data/lib/datadog/tracing/contrib/active_job/log_injection.rb +2 -2
  363. data/lib/datadog/tracing/contrib/active_job/patcher.rb +2 -2
  364. data/lib/datadog/tracing/contrib/active_model_serializers/configuration/settings.rb +10 -7
  365. data/lib/datadog/tracing/contrib/active_model_serializers/event.rb +1 -1
  366. data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +0 -2
  367. data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +0 -2
  368. data/lib/datadog/tracing/contrib/active_model_serializers/events.rb +1 -1
  369. data/lib/datadog/tracing/contrib/active_model_serializers/ext.rb +11 -11
  370. data/lib/datadog/tracing/contrib/active_model_serializers/integration.rb +0 -2
  371. data/lib/datadog/tracing/contrib/active_model_serializers/patcher.rb +1 -1
  372. data/lib/datadog/tracing/contrib/active_record/configuration/makara_resolver.rb +0 -2
  373. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +18 -13
  374. data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +16 -9
  375. data/lib/datadog/tracing/contrib/active_record/event.rb +1 -1
  376. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +0 -2
  377. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +3 -6
  378. data/lib/datadog/tracing/contrib/active_record/events.rb +1 -1
  379. data/lib/datadog/tracing/contrib/active_record/ext.rb +16 -16
  380. data/lib/datadog/tracing/contrib/active_record/integration.rb +0 -2
  381. data/lib/datadog/tracing/contrib/active_record/patcher.rb +1 -1
  382. data/lib/datadog/tracing/contrib/active_record/utils.rb +1 -3
  383. data/lib/datadog/tracing/contrib/active_record/vendor/connection_specification.rb +0 -2
  384. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +107 -201
  385. data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +4 -1
  386. data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +1 -1
  387. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +18 -8
  388. data/lib/datadog/tracing/contrib/active_support/ext.rb +17 -17
  389. data/lib/datadog/tracing/contrib/active_support/integration.rb +0 -2
  390. data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +1 -1
  391. data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +1 -1
  392. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +0 -2
  393. data/lib/datadog/tracing/contrib/active_support/patcher.rb +1 -1
  394. data/lib/datadog/tracing/contrib/analytics.rb +1 -1
  395. data/lib/datadog/tracing/contrib/auto_instrument.rb +1 -1
  396. data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +24 -8
  397. data/lib/datadog/tracing/contrib/aws/ext.rb +36 -14
  398. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +28 -3
  399. data/lib/datadog/tracing/contrib/aws/integration.rb +0 -2
  400. data/lib/datadog/tracing/contrib/aws/parsed_context.rb +4 -2
  401. data/lib/datadog/tracing/contrib/aws/patcher.rb +1 -1
  402. data/lib/datadog/tracing/contrib/aws/service/base.rb +16 -0
  403. data/lib/datadog/tracing/contrib/aws/service/dynamodb.rb +22 -0
  404. data/lib/datadog/tracing/contrib/aws/service/eventbridge.rb +22 -0
  405. data/lib/datadog/tracing/contrib/aws/service/kinesis.rb +32 -0
  406. data/lib/datadog/tracing/contrib/aws/service/s3.rb +22 -0
  407. data/lib/datadog/tracing/contrib/aws/service/sns.rb +30 -0
  408. data/lib/datadog/tracing/contrib/aws/service/sqs.rb +27 -0
  409. data/lib/datadog/tracing/contrib/aws/service/states.rb +40 -0
  410. data/lib/datadog/tracing/contrib/aws/services.rb +17 -3
  411. data/lib/datadog/tracing/contrib/concurrent_ruby/configuration/settings.rb +4 -3
  412. data/lib/datadog/tracing/contrib/concurrent_ruby/context_composite_executor_service.rb +15 -15
  413. data/lib/datadog/tracing/contrib/concurrent_ruby/ext.rb +3 -3
  414. data/lib/datadog/tracing/contrib/concurrent_ruby/future_patch.rb +4 -11
  415. data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +2 -3
  416. data/lib/datadog/tracing/contrib/concurrent_ruby/patcher.rb +9 -3
  417. data/lib/datadog/tracing/contrib/concurrent_ruby/promises_future_patch.rb +22 -0
  418. data/lib/datadog/tracing/contrib/configurable.rb +1 -1
  419. data/lib/datadog/tracing/contrib/configuration/resolver.rb +1 -1
  420. data/lib/datadog/tracing/contrib/configuration/resolvers/pattern_resolver.rb +1 -1
  421. data/lib/datadog/tracing/contrib/configuration/settings.rb +1 -5
  422. data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +29 -8
  423. data/lib/datadog/tracing/contrib/dalli/ext.rb +25 -10
  424. data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +23 -7
  425. data/lib/datadog/tracing/contrib/dalli/integration.rb +0 -2
  426. data/lib/datadog/tracing/contrib/dalli/patcher.rb +1 -1
  427. data/lib/datadog/tracing/contrib/dalli/quantize.rb +0 -2
  428. data/lib/datadog/tracing/contrib/delayed_job/configuration/settings.rb +14 -8
  429. data/lib/datadog/tracing/contrib/delayed_job/ext.rb +15 -15
  430. data/lib/datadog/tracing/contrib/delayed_job/integration.rb +0 -2
  431. data/lib/datadog/tracing/contrib/delayed_job/patcher.rb +1 -1
  432. data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +9 -1
  433. data/lib/datadog/tracing/contrib/delayed_job/server_internal_tracer/worker.rb +3 -1
  434. data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +24 -8
  435. data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +20 -13
  436. data/lib/datadog/tracing/contrib/elasticsearch/integration.rb +0 -2
  437. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +105 -95
  438. data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +0 -4
  439. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +27 -10
  440. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +52 -7
  441. data/lib/datadog/tracing/contrib/ethon/ext.rb +18 -11
  442. data/lib/datadog/tracing/contrib/ethon/integration.rb +0 -2
  443. data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +10 -3
  444. data/lib/datadog/tracing/contrib/ethon/patcher.rb +1 -2
  445. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +29 -11
  446. data/lib/datadog/tracing/contrib/excon/ext.rb +15 -8
  447. data/lib/datadog/tracing/contrib/excon/integration.rb +0 -2
  448. data/lib/datadog/tracing/contrib/excon/middleware.rb +27 -4
  449. data/lib/datadog/tracing/contrib/excon/patcher.rb +1 -1
  450. data/lib/datadog/tracing/contrib/ext.rb +55 -0
  451. data/lib/datadog/tracing/contrib/extensions.rb +32 -2
  452. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +30 -11
  453. data/lib/datadog/tracing/contrib/faraday/connection.rb +1 -1
  454. data/lib/datadog/tracing/contrib/faraday/ext.rb +15 -8
  455. data/lib/datadog/tracing/contrib/faraday/integration.rb +0 -2
  456. data/lib/datadog/tracing/contrib/faraday/middleware.rb +24 -6
  457. data/lib/datadog/tracing/contrib/faraday/patcher.rb +0 -2
  458. data/lib/datadog/tracing/contrib/faraday/rack_builder.rb +1 -1
  459. data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +9 -7
  460. data/lib/datadog/tracing/contrib/grape/endpoint.rb +0 -4
  461. data/lib/datadog/tracing/contrib/grape/ext.rb +15 -15
  462. data/lib/datadog/tracing/contrib/grape/instrumentation.rb +0 -2
  463. data/lib/datadog/tracing/contrib/grape/integration.rb +0 -2
  464. data/lib/datadog/tracing/contrib/grape/patcher.rb +1 -1
  465. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +10 -8
  466. data/lib/datadog/tracing/contrib/graphql/ext.rb +6 -6
  467. data/lib/datadog/tracing/contrib/graphql/integration.rb +0 -2
  468. data/lib/datadog/tracing/contrib/graphql/patcher.rb +0 -2
  469. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +50 -10
  470. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +45 -19
  471. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +43 -26
  472. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor.rb +0 -6
  473. data/lib/datadog/tracing/contrib/grpc/distributed/fetcher.rb +26 -0
  474. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +42 -0
  475. data/lib/datadog/tracing/contrib/grpc/ext.rb +15 -11
  476. data/lib/datadog/tracing/contrib/grpc/formatting.rb +127 -0
  477. data/lib/datadog/tracing/contrib/grpc/integration.rb +8 -3
  478. data/lib/datadog/tracing/contrib/grpc/intercept_with_datadog.rb +1 -1
  479. data/lib/datadog/tracing/contrib/grpc/patcher.rb +1 -4
  480. data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +47 -0
  481. data/lib/datadog/tracing/contrib/hanami/configuration/settings.rb +23 -0
  482. data/lib/datadog/tracing/contrib/hanami/ext.rb +24 -0
  483. data/lib/datadog/tracing/contrib/hanami/integration.rb +42 -0
  484. data/lib/datadog/tracing/contrib/hanami/patcher.rb +33 -0
  485. data/lib/datadog/tracing/contrib/hanami/plugin.rb +23 -0
  486. data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +41 -0
  487. data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +44 -0
  488. data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +6 -9
  489. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +47 -10
  490. data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +38 -0
  491. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +37 -0
  492. data/lib/datadog/tracing/contrib/http/ext.rb +15 -8
  493. data/lib/datadog/tracing/contrib/http/instrumentation.rb +32 -12
  494. data/lib/datadog/tracing/contrib/http/integration.rb +1 -1
  495. data/lib/datadog/tracing/contrib/http/patcher.rb +1 -1
  496. data/lib/datadog/tracing/contrib/http_annotation_helper.rb +1 -1
  497. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +47 -10
  498. data/lib/datadog/tracing/contrib/httpclient/ext.rb +16 -8
  499. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +27 -8
  500. data/lib/datadog/tracing/contrib/httpclient/integration.rb +0 -2
  501. data/lib/datadog/tracing/contrib/httpclient/patcher.rb +0 -2
  502. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +47 -10
  503. data/lib/datadog/tracing/contrib/httprb/ext.rb +15 -8
  504. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +27 -9
  505. data/lib/datadog/tracing/contrib/httprb/integration.rb +0 -2
  506. data/lib/datadog/tracing/contrib/httprb/patcher.rb +0 -2
  507. data/lib/datadog/tracing/contrib/integration.rb +1 -1
  508. data/lib/datadog/tracing/contrib/kafka/configuration/settings.rb +10 -7
  509. data/lib/datadog/tracing/contrib/kafka/consumer_event.rb +2 -1
  510. data/lib/datadog/tracing/contrib/kafka/consumer_group_event.rb +1 -1
  511. data/lib/datadog/tracing/contrib/kafka/event.rb +2 -1
  512. data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +0 -2
  513. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +0 -2
  514. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +0 -2
  515. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +0 -2
  516. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/join_group.rb +0 -2
  517. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/leave_group.rb +0 -2
  518. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/sync_group.rb +0 -2
  519. data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +1 -2
  520. data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +1 -2
  521. data/lib/datadog/tracing/contrib/kafka/events.rb +1 -1
  522. data/lib/datadog/tracing/contrib/kafka/ext.rb +41 -39
  523. data/lib/datadog/tracing/contrib/kafka/integration.rb +0 -2
  524. data/lib/datadog/tracing/contrib/kafka/patcher.rb +1 -1
  525. data/lib/datadog/tracing/contrib/lograge/configuration/settings.rb +4 -3
  526. data/lib/datadog/tracing/contrib/lograge/ext.rb +2 -2
  527. data/lib/datadog/tracing/contrib/lograge/instrumentation.rb +3 -18
  528. data/lib/datadog/tracing/contrib/lograge/integration.rb +0 -2
  529. data/lib/datadog/tracing/contrib/lograge/patcher.rb +1 -1
  530. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +24 -8
  531. data/lib/datadog/tracing/contrib/mongodb/ext.rb +24 -14
  532. data/lib/datadog/tracing/contrib/mongodb/instrumentation.rb +1 -1
  533. data/lib/datadog/tracing/contrib/mongodb/integration.rb +0 -2
  534. data/lib/datadog/tracing/contrib/mongodb/parsers.rb +0 -2
  535. data/lib/datadog/tracing/contrib/mongodb/patcher.rb +1 -1
  536. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +22 -4
  537. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +35 -8
  538. data/lib/datadog/tracing/contrib/mysql2/ext.rb +14 -9
  539. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +38 -4
  540. data/lib/datadog/tracing/contrib/mysql2/integration.rb +0 -2
  541. data/lib/datadog/tracing/contrib/mysql2/patcher.rb +1 -1
  542. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +52 -0
  543. data/lib/datadog/tracing/contrib/opensearch/ext.rb +37 -0
  544. data/lib/datadog/tracing/contrib/opensearch/integration.rb +44 -0
  545. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +135 -0
  546. data/lib/datadog/tracing/contrib/opensearch/quantize.rb +81 -0
  547. data/lib/datadog/tracing/contrib/patchable.rb +1 -1
  548. data/lib/datadog/tracing/contrib/patcher.rb +3 -5
  549. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +36 -8
  550. data/lib/datadog/tracing/contrib/pg/ext.rb +21 -18
  551. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +115 -39
  552. data/lib/datadog/tracing/contrib/pg/integration.rb +0 -2
  553. data/lib/datadog/tracing/contrib/pg/patcher.rb +1 -1
  554. data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +23 -8
  555. data/lib/datadog/tracing/contrib/presto/ext.rb +24 -19
  556. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +17 -5
  557. data/lib/datadog/tracing/contrib/presto/integration.rb +0 -2
  558. data/lib/datadog/tracing/contrib/presto/patcher.rb +0 -2
  559. data/lib/datadog/tracing/contrib/propagation/sql_comment/comment.rb +41 -0
  560. data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +33 -0
  561. data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +28 -0
  562. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +53 -0
  563. data/lib/datadog/tracing/contrib/qless/configuration/settings.rb +13 -9
  564. data/lib/datadog/tracing/contrib/qless/ext.rb +13 -13
  565. data/lib/datadog/tracing/contrib/qless/integration.rb +0 -2
  566. data/lib/datadog/tracing/contrib/qless/patcher.rb +1 -2
  567. data/lib/datadog/tracing/contrib/qless/qless_job.rb +3 -2
  568. data/lib/datadog/tracing/contrib/qless/tracer_cleaner.rb +1 -1
  569. data/lib/datadog/tracing/contrib/que/configuration/settings.rb +21 -14
  570. data/lib/datadog/tracing/contrib/que/ext.rb +0 -2
  571. data/lib/datadog/tracing/contrib/que/integration.rb +0 -2
  572. data/lib/datadog/tracing/contrib/que/patcher.rb +0 -2
  573. data/lib/datadog/tracing/contrib/que/tracer.rb +4 -2
  574. data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +18 -8
  575. data/lib/datadog/tracing/contrib/racecar/event.rb +7 -4
  576. data/lib/datadog/tracing/contrib/racecar/events/batch.rb +4 -3
  577. data/lib/datadog/tracing/contrib/racecar/events/consume.rb +0 -2
  578. data/lib/datadog/tracing/contrib/racecar/events/message.rb +4 -3
  579. data/lib/datadog/tracing/contrib/racecar/events.rb +1 -1
  580. data/lib/datadog/tracing/contrib/racecar/ext.rb +19 -18
  581. data/lib/datadog/tracing/contrib/racecar/integration.rb +0 -2
  582. data/lib/datadog/tracing/contrib/racecar/patcher.rb +1 -1
  583. data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +16 -14
  584. data/lib/datadog/tracing/contrib/rack/ext.rb +17 -12
  585. data/lib/datadog/tracing/contrib/rack/header_collection.rb +38 -0
  586. data/lib/datadog/tracing/contrib/rack/header_tagging.rb +63 -0
  587. data/lib/datadog/tracing/contrib/rack/integration.rb +0 -2
  588. data/lib/datadog/tracing/contrib/rack/middlewares.rb +130 -81
  589. data/lib/datadog/tracing/contrib/rack/patcher.rb +0 -2
  590. data/lib/datadog/tracing/contrib/rack/request_queue.rb +0 -2
  591. data/lib/datadog/tracing/contrib/rails/auto_instrument_railtie.rb +0 -4
  592. data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +28 -19
  593. data/lib/datadog/tracing/contrib/rails/ext.rb +6 -6
  594. data/lib/datadog/tracing/contrib/rails/framework.rb +1 -1
  595. data/lib/datadog/tracing/contrib/rails/integration.rb +0 -2
  596. data/lib/datadog/tracing/contrib/rails/log_injection.rb +7 -12
  597. data/lib/datadog/tracing/contrib/rails/middlewares.rb +1 -1
  598. data/lib/datadog/tracing/contrib/rails/patcher.rb +10 -43
  599. data/lib/datadog/tracing/contrib/rails/railtie.rb +3 -5
  600. data/lib/datadog/tracing/contrib/rails/utils.rb +2 -2
  601. data/lib/datadog/tracing/contrib/rake/configuration/settings.rb +14 -11
  602. data/lib/datadog/tracing/contrib/rake/ext.rb +13 -13
  603. data/lib/datadog/tracing/contrib/rake/instrumentation.rb +0 -2
  604. data/lib/datadog/tracing/contrib/rake/integration.rb +0 -2
  605. data/lib/datadog/tracing/contrib/rake/patcher.rb +1 -1
  606. data/lib/datadog/tracing/contrib/redis/configuration/resolver.rb +0 -2
  607. data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +26 -10
  608. data/lib/datadog/tracing/contrib/redis/ext.rb +21 -13
  609. data/lib/datadog/tracing/contrib/redis/instrumentation.rb +13 -39
  610. data/lib/datadog/tracing/contrib/redis/integration.rb +34 -3
  611. data/lib/datadog/tracing/contrib/redis/patcher.rb +53 -11
  612. data/lib/datadog/tracing/contrib/redis/quantize.rb +11 -10
  613. data/lib/datadog/tracing/contrib/redis/tags.rb +24 -9
  614. data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +83 -0
  615. data/lib/datadog/tracing/contrib/redis/vendor/resolver.rb +0 -2
  616. data/lib/datadog/tracing/contrib/registerable.rb +1 -1
  617. data/lib/datadog/tracing/contrib/registry.rb +1 -1
  618. data/lib/datadog/tracing/contrib/resque/configuration/settings.rb +14 -8
  619. data/lib/datadog/tracing/contrib/resque/ext.rb +8 -8
  620. data/lib/datadog/tracing/contrib/resque/integration.rb +0 -2
  621. data/lib/datadog/tracing/contrib/resque/patcher.rb +1 -1
  622. data/lib/datadog/tracing/contrib/resque/resque_job.rb +5 -1
  623. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +27 -10
  624. data/lib/datadog/tracing/contrib/rest_client/ext.rb +14 -8
  625. data/lib/datadog/tracing/contrib/rest_client/integration.rb +0 -2
  626. data/lib/datadog/tracing/contrib/rest_client/patcher.rb +1 -2
  627. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +28 -3
  628. data/lib/datadog/tracing/contrib/roda/configuration/settings.rb +37 -0
  629. data/lib/datadog/tracing/contrib/roda/ext.rb +18 -0
  630. data/lib/datadog/tracing/contrib/roda/instrumentation.rb +76 -0
  631. data/lib/datadog/tracing/contrib/roda/integration.rb +45 -0
  632. data/lib/datadog/{ci/contrib/cucumber → tracing/contrib/roda}/patcher.rb +10 -7
  633. data/lib/datadog/tracing/contrib/semantic_logger/configuration/settings.rb +4 -3
  634. data/lib/datadog/tracing/contrib/semantic_logger/ext.rb +2 -2
  635. data/lib/datadog/tracing/contrib/semantic_logger/instrumentation.rb +6 -21
  636. data/lib/datadog/tracing/contrib/semantic_logger/integration.rb +0 -2
  637. data/lib/datadog/tracing/contrib/semantic_logger/patcher.rb +1 -1
  638. data/lib/datadog/tracing/contrib/sequel/configuration/settings.rb +10 -7
  639. data/lib/datadog/tracing/contrib/sequel/database.rb +4 -3
  640. data/lib/datadog/tracing/contrib/sequel/dataset.rb +5 -2
  641. data/lib/datadog/tracing/contrib/sequel/ext.rb +9 -9
  642. data/lib/datadog/tracing/contrib/sequel/integration.rb +0 -2
  643. data/lib/datadog/tracing/contrib/sequel/patcher.rb +1 -1
  644. data/lib/datadog/tracing/contrib/sequel/utils.rb +7 -6
  645. data/lib/datadog/tracing/contrib/shoryuken/configuration/settings.rb +15 -9
  646. data/lib/datadog/tracing/contrib/shoryuken/ext.rb +13 -12
  647. data/lib/datadog/tracing/contrib/shoryuken/integration.rb +0 -2
  648. data/lib/datadog/tracing/contrib/shoryuken/patcher.rb +1 -1
  649. data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +5 -1
  650. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +18 -4
  651. data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +19 -11
  652. data/lib/datadog/tracing/contrib/sidekiq/distributed/propagation.rb +38 -0
  653. data/lib/datadog/tracing/contrib/sidekiq/ext.rb +31 -31
  654. data/lib/datadog/tracing/contrib/sidekiq/integration.rb +8 -2
  655. data/lib/datadog/tracing/contrib/sidekiq/patcher.rb +15 -3
  656. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/heartbeat.rb +14 -5
  657. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/job_fetch.rb +3 -1
  658. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/redis_info.rb +3 -1
  659. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/scheduled_poller.rb +5 -1
  660. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/stop.rb +34 -0
  661. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +24 -3
  662. data/lib/datadog/tracing/contrib/sidekiq/{tracing.rb → utils.rb} +2 -2
  663. data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +11 -11
  664. data/lib/datadog/tracing/contrib/sinatra/env.rb +11 -41
  665. data/lib/datadog/tracing/contrib/sinatra/ext.rb +23 -19
  666. data/lib/datadog/tracing/contrib/sinatra/framework.rb +0 -2
  667. data/lib/datadog/tracing/contrib/sinatra/integration.rb +0 -2
  668. data/lib/datadog/tracing/contrib/sinatra/patcher.rb +2 -3
  669. data/lib/datadog/tracing/contrib/sinatra/tracer.rb +8 -82
  670. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +14 -20
  671. data/lib/datadog/tracing/contrib/sneakers/configuration/settings.rb +14 -10
  672. data/lib/datadog/tracing/contrib/sneakers/ext.rb +2 -2
  673. data/lib/datadog/tracing/contrib/sneakers/integration.rb +0 -2
  674. data/lib/datadog/tracing/contrib/sneakers/patcher.rb +0 -2
  675. data/lib/datadog/tracing/contrib/sneakers/tracer.rb +5 -2
  676. data/lib/datadog/tracing/contrib/span_attribute_schema.rb +92 -0
  677. data/lib/datadog/tracing/contrib/status_code_matcher.rb +0 -3
  678. data/lib/datadog/tracing/contrib/stripe/configuration/settings.rb +36 -0
  679. data/lib/datadog/tracing/contrib/stripe/ext.rb +26 -0
  680. data/lib/datadog/tracing/contrib/stripe/integration.rb +43 -0
  681. data/lib/datadog/tracing/contrib/stripe/patcher.rb +28 -0
  682. data/lib/datadog/tracing/contrib/stripe/request.rb +67 -0
  683. data/lib/datadog/tracing/contrib/sucker_punch/configuration/settings.rb +10 -7
  684. data/lib/datadog/tracing/contrib/sucker_punch/exception_handler.rb +1 -1
  685. data/lib/datadog/tracing/contrib/sucker_punch/ext.rb +14 -14
  686. data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +0 -2
  687. data/lib/datadog/tracing/contrib/sucker_punch/integration.rb +0 -2
  688. data/lib/datadog/tracing/contrib/sucker_punch/patcher.rb +1 -2
  689. data/lib/datadog/tracing/contrib/utils/database.rb +4 -4
  690. data/lib/datadog/tracing/contrib/utils/quantization/hash.rb +0 -2
  691. data/lib/datadog/tracing/contrib/utils/quantization/http.rb +92 -14
  692. data/lib/datadog/tracing/contrib.rb +5 -1
  693. data/lib/datadog/tracing/correlation.rb +42 -14
  694. data/lib/datadog/tracing/diagnostics/environment_logger.rb +165 -0
  695. data/lib/datadog/{core → tracing}/diagnostics/ext.rb +21 -26
  696. data/lib/datadog/tracing/diagnostics/health.rb +40 -0
  697. data/lib/datadog/tracing/distributed/b3_multi.rb +72 -0
  698. data/lib/datadog/tracing/distributed/b3_single.rb +68 -0
  699. data/lib/datadog/tracing/distributed/datadog.rb +199 -0
  700. data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +84 -0
  701. data/lib/datadog/tracing/distributed/fetcher.rb +21 -0
  702. data/lib/datadog/tracing/distributed/headers/ext.rb +19 -16
  703. data/lib/datadog/tracing/distributed/helpers.rb +26 -39
  704. data/lib/datadog/tracing/distributed/none.rb +18 -0
  705. data/lib/datadog/tracing/distributed/propagation.rb +127 -0
  706. data/lib/datadog/tracing/distributed/trace_context.rb +415 -0
  707. data/lib/datadog/tracing/event.rb +0 -4
  708. data/lib/datadog/tracing/flush.rb +58 -36
  709. data/lib/datadog/tracing/metadata/analytics.rb +1 -1
  710. data/lib/datadog/tracing/metadata/errors.rb +1 -1
  711. data/lib/datadog/tracing/metadata/ext.rb +29 -14
  712. data/lib/datadog/tracing/metadata/tagging.rb +17 -4
  713. data/lib/datadog/tracing/metadata.rb +1 -1
  714. data/lib/datadog/tracing/pipeline/span_filter.rb +1 -1
  715. data/lib/datadog/tracing/pipeline/span_processor.rb +1 -1
  716. data/lib/datadog/tracing/pipeline.rb +0 -4
  717. data/lib/datadog/tracing/propagation/http.rb +4 -99
  718. data/lib/datadog/tracing/remote.rb +78 -0
  719. data/lib/datadog/tracing/runtime/metrics.rb +1 -3
  720. data/lib/datadog/tracing/sampling/all_sampler.rb +1 -1
  721. data/lib/datadog/tracing/sampling/ext.rb +30 -1
  722. data/lib/datadog/tracing/sampling/matcher.rb +1 -1
  723. data/lib/datadog/tracing/sampling/priority_sampler.rb +58 -5
  724. data/lib/datadog/tracing/sampling/rate_by_key_sampler.rb +8 -11
  725. data/lib/datadog/tracing/sampling/rate_by_service_sampler.rb +29 -8
  726. data/lib/datadog/tracing/sampling/rate_limiter.rb +3 -2
  727. data/lib/datadog/tracing/sampling/rate_sampler.rb +23 -10
  728. data/lib/datadog/tracing/sampling/rule.rb +0 -4
  729. data/lib/datadog/tracing/sampling/rule_sampler.rb +33 -7
  730. data/lib/datadog/tracing/sampling/sampler.rb +0 -2
  731. data/lib/datadog/tracing/sampling/span/ext.rb +25 -0
  732. data/lib/datadog/tracing/sampling/span/matcher.rb +9 -0
  733. data/lib/datadog/tracing/sampling/span/rule.rb +82 -0
  734. data/lib/datadog/tracing/sampling/span/rule_parser.rb +104 -0
  735. data/lib/datadog/tracing/sampling/span/sampler.rb +77 -0
  736. data/lib/datadog/tracing/span.rb +3 -21
  737. data/lib/datadog/tracing/span_operation.rb +8 -24
  738. data/lib/datadog/tracing/sync_writer.rb +4 -6
  739. data/lib/datadog/tracing/trace_digest.rb +120 -3
  740. data/lib/datadog/tracing/trace_operation.rb +61 -13
  741. data/lib/datadog/tracing/trace_segment.rb +20 -7
  742. data/lib/datadog/tracing/tracer.rb +46 -10
  743. data/lib/datadog/tracing/transport/http/api/instance.rb +37 -0
  744. data/lib/datadog/tracing/transport/http/api/spec.rb +19 -0
  745. data/lib/datadog/tracing/transport/http/api.rb +43 -0
  746. data/lib/datadog/tracing/transport/http/builder.rb +162 -0
  747. data/lib/datadog/tracing/transport/http/client.rb +57 -0
  748. data/lib/datadog/tracing/transport/http/statistics.rb +47 -0
  749. data/lib/datadog/tracing/transport/http/traces.rb +152 -0
  750. data/lib/datadog/tracing/transport/http.rb +124 -0
  751. data/lib/datadog/tracing/transport/io/client.rb +89 -0
  752. data/lib/datadog/tracing/transport/io/response.rb +27 -0
  753. data/lib/datadog/tracing/transport/io/traces.rb +101 -0
  754. data/lib/datadog/tracing/transport/io.rb +30 -0
  755. data/lib/datadog/tracing/transport/serializable_trace.rb +126 -0
  756. data/lib/datadog/tracing/transport/statistics.rb +77 -0
  757. data/lib/datadog/tracing/transport/trace_formatter.rb +209 -0
  758. data/lib/datadog/tracing/transport/traces.rb +224 -0
  759. data/lib/datadog/tracing/utils.rb +83 -0
  760. data/lib/datadog/tracing/workers/trace_writer.rb +6 -7
  761. data/lib/datadog/tracing/workers.rb +4 -6
  762. data/lib/datadog/tracing/writer.rb +12 -6
  763. data/lib/datadog/tracing.rb +1 -1
  764. data/lib/ddtrace/auto_instrument.rb +1 -1
  765. data/lib/ddtrace/auto_instrument_base.rb +1 -1
  766. data/lib/ddtrace/profiling/preload.rb +0 -2
  767. data/lib/ddtrace/transport/ext.rb +21 -15
  768. data/lib/ddtrace/version.rb +14 -15
  769. data/lib/ddtrace.rb +3 -5
  770. metadata +230 -113
  771. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.c +0 -390
  772. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.h +0 -6
  773. data/lib/datadog/appsec/assets/waf_rules/risky.json +0 -1499
  774. data/lib/datadog/appsec/contrib/configuration/settings.rb +0 -20
  775. data/lib/datadog/appsec/contrib/rack/configuration/settings.rb +0 -22
  776. data/lib/datadog/appsec/contrib/rack/request.rb +0 -58
  777. data/lib/datadog/appsec/contrib/rack/response.rb +0 -24
  778. data/lib/datadog/appsec/contrib/rails/configuration/settings.rb +0 -22
  779. data/lib/datadog/appsec/contrib/sinatra/configuration/settings.rb +0 -22
  780. data/lib/datadog/ci/configuration/components.rb +0 -32
  781. data/lib/datadog/ci/configuration/settings.rb +0 -53
  782. data/lib/datadog/ci/contrib/cucumber/configuration/settings.rb +0 -33
  783. data/lib/datadog/ci/contrib/cucumber/ext.rb +0 -22
  784. data/lib/datadog/ci/contrib/cucumber/formatter.rb +0 -94
  785. data/lib/datadog/ci/contrib/cucumber/instrumentation.rb +0 -28
  786. data/lib/datadog/ci/contrib/cucumber/integration.rb +0 -49
  787. data/lib/datadog/ci/contrib/rspec/configuration/settings.rb +0 -33
  788. data/lib/datadog/ci/contrib/rspec/example.rb +0 -70
  789. data/lib/datadog/ci/contrib/rspec/ext.rb +0 -21
  790. data/lib/datadog/ci/contrib/rspec/integration.rb +0 -50
  791. data/lib/datadog/ci/contrib/rspec/patcher.rb +0 -27
  792. data/lib/datadog/ci/ext/app_types.rb +0 -11
  793. data/lib/datadog/ci/ext/environment.rb +0 -505
  794. data/lib/datadog/ci/ext/settings.rb +0 -12
  795. data/lib/datadog/ci/ext/test.rb +0 -37
  796. data/lib/datadog/ci/extensions.rb +0 -19
  797. data/lib/datadog/ci/flush.rb +0 -38
  798. data/lib/datadog/ci/test.rb +0 -83
  799. data/lib/datadog/ci.rb +0 -20
  800. data/lib/datadog/core/configuration/dependency_resolver.rb +0 -28
  801. data/lib/datadog/core/configuration/option_definition_set.rb +0 -22
  802. data/lib/datadog/core/configuration/option_set.rb +0 -10
  803. data/lib/datadog/core/utils/object_set.rb +0 -43
  804. data/lib/datadog/core/utils/string_table.rb +0 -49
  805. data/lib/datadog/profiling/backtrace_location.rb +0 -34
  806. data/lib/datadog/profiling/buffer.rb +0 -43
  807. data/lib/datadog/profiling/collectors/cpu_and_wall_time.rb +0 -27
  808. data/lib/datadog/profiling/collectors/old_stack.rb +0 -298
  809. data/lib/datadog/profiling/encoding/profile.rb +0 -43
  810. data/lib/datadog/profiling/event.rb +0 -15
  811. data/lib/datadog/profiling/events/stack.rb +0 -82
  812. data/lib/datadog/profiling/old_ext.rb +0 -42
  813. data/lib/datadog/profiling/old_recorder.rb +0 -101
  814. data/lib/datadog/profiling/pprof/builder.rb +0 -127
  815. data/lib/datadog/profiling/pprof/converter.rb +0 -104
  816. data/lib/datadog/profiling/pprof/message_set.rb +0 -16
  817. data/lib/datadog/profiling/pprof/payload.rb +0 -20
  818. data/lib/datadog/profiling/pprof/pprof.proto +0 -212
  819. data/lib/datadog/profiling/pprof/pprof_pb.rb +0 -83
  820. data/lib/datadog/profiling/pprof/stack_sample.rb +0 -141
  821. data/lib/datadog/profiling/pprof/string_table.rb +0 -12
  822. data/lib/datadog/profiling/pprof/template.rb +0 -120
  823. data/lib/datadog/profiling/trace_identifiers/ddtrace.rb +0 -45
  824. data/lib/datadog/profiling/trace_identifiers/helper.rb +0 -47
  825. data/lib/datadog/profiling/transport/http/api/endpoint.rb +0 -85
  826. data/lib/datadog/profiling/transport/http/api/instance.rb +0 -38
  827. data/lib/datadog/profiling/transport/http/api/spec.rb +0 -42
  828. data/lib/datadog/profiling/transport/http/api.rb +0 -45
  829. data/lib/datadog/profiling/transport/http/builder.rb +0 -30
  830. data/lib/datadog/profiling/transport/http/client.rb +0 -37
  831. data/lib/datadog/profiling/transport/http/response.rb +0 -21
  832. data/lib/datadog/profiling/transport/http.rb +0 -118
  833. data/lib/datadog/tracing/contrib/sinatra/headers.rb +0 -35
  834. data/lib/datadog/tracing/distributed/headers/b3.rb +0 -55
  835. data/lib/datadog/tracing/distributed/headers/b3_single.rb +0 -67
  836. data/lib/datadog/tracing/distributed/headers/datadog.rb +0 -52
  837. data/lib/datadog/tracing/distributed/headers/parser.rb +0 -37
  838. data/lib/datadog/tracing/distributed/metadata/b3.rb +0 -55
  839. data/lib/datadog/tracing/distributed/metadata/b3_single.rb +0 -66
  840. data/lib/datadog/tracing/distributed/metadata/datadog.rb +0 -73
  841. data/lib/datadog/tracing/distributed/metadata/parser.rb +0 -34
  842. data/lib/datadog/tracing/propagation/grpc.rb +0 -98
  843. data/lib/ddtrace/transport/http/adapters/net.rb +0 -158
  844. data/lib/ddtrace/transport/http/adapters/registry.rb +0 -27
  845. data/lib/ddtrace/transport/http/adapters/test.rb +0 -87
  846. data/lib/ddtrace/transport/http/adapters/unix_socket.rb +0 -79
  847. data/lib/ddtrace/transport/http/api/endpoint.rb +0 -29
  848. data/lib/ddtrace/transport/http/api/fallbacks.rb +0 -24
  849. data/lib/ddtrace/transport/http/api/instance.rb +0 -35
  850. data/lib/ddtrace/transport/http/api/map.rb +0 -16
  851. data/lib/ddtrace/transport/http/api/spec.rb +0 -17
  852. data/lib/ddtrace/transport/http/api.rb +0 -41
  853. data/lib/ddtrace/transport/http/builder.rb +0 -178
  854. data/lib/ddtrace/transport/http/client.rb +0 -54
  855. data/lib/ddtrace/transport/http/env.rb +0 -58
  856. data/lib/ddtrace/transport/http/response.rb +0 -58
  857. data/lib/ddtrace/transport/http/statistics.rb +0 -45
  858. data/lib/ddtrace/transport/http/traces.rb +0 -146
  859. data/lib/ddtrace/transport/http.rb +0 -121
  860. data/lib/ddtrace/transport/io/client.rb +0 -87
  861. data/lib/ddtrace/transport/io/response.rb +0 -25
  862. data/lib/ddtrace/transport/io/traces.rb +0 -101
  863. data/lib/ddtrace/transport/io.rb +0 -28
  864. data/lib/ddtrace/transport/parcel.rb +0 -22
  865. data/lib/ddtrace/transport/request.rb +0 -15
  866. data/lib/ddtrace/transport/response.rb +0 -62
  867. data/lib/ddtrace/transport/serializable_trace.rb +0 -118
  868. data/lib/ddtrace/transport/statistics.rb +0 -75
  869. data/lib/ddtrace/transport/trace_formatter.rb +0 -187
  870. data/lib/ddtrace/transport/traces.rb +0 -216
@@ -0,0 +1,970 @@
1
+ #include "heap_recorder.h"
2
+ #include <pthread.h>
3
+ #include "ruby/st.h"
4
+ #include "ruby_helpers.h"
5
+ #include <errno.h>
6
+ #include "collectors_stack.h"
7
+ #include "libdatadog_helpers.h"
8
+
9
+ #if (defined(HAVE_WORKING_RB_GC_FORCE_RECYCLE) && ! defined(NO_SEEN_OBJ_ID_FLAG))
10
+ #define CAN_APPLY_GC_FORCE_RECYCLE_BUG_WORKAROUND
11
+ #endif
12
+
13
+ // A compact representation of a stacktrace frame for a heap allocation.
14
+ typedef struct {
15
+ char *name;
16
+ char *filename;
17
+ int32_t line;
18
+ } heap_frame;
19
+ static st_index_t heap_frame_hash(heap_frame*, st_index_t seed);
20
+
21
+ // A compact representation of a stacktrace for a heap allocation.
22
+ //
23
+ // We could use a ddog_prof_Slice_Location instead but it has a lot of
24
+ // unused fields. Because we have to keep these stacks around for at
25
+ // least the lifetime of the objects allocated therein, we would be
26
+ // incurring a non-negligible memory overhead for little purpose.
27
+ typedef struct {
28
+ uint16_t frames_len;
29
+ heap_frame frames[];
30
+ } heap_stack;
31
+ static heap_stack* heap_stack_new(ddog_prof_Slice_Location);
32
+ static void heap_stack_free(heap_stack*);
33
+ static st_index_t heap_stack_hash(heap_stack*, st_index_t);
34
+
35
+ #if MAX_FRAMES_LIMIT > UINT16_MAX
36
+ #error Frames len type not compatible with MAX_FRAMES_LIMIT
37
+ #endif
38
+
39
+ enum heap_record_key_type {
40
+ HEAP_STACK,
41
+ LOCATION_SLICE
42
+ };
43
+ // This struct allows us to use two different types of stacks when
44
+ // interacting with a heap_record hash.
45
+ //
46
+ // The idea is that we'll always want to use heap_stack-keys when
47
+ // adding new entries to the hash since that's the compact stack
48
+ // representation we rely on internally.
49
+ //
50
+ // However, when querying for an existing heap record, we'd save a
51
+ // lot of allocations if we could query with the
52
+ // ddog_prof_Slice_Location we receive in our external API.
53
+ //
54
+ // To allow this interchange, we need a union and need to ensure
55
+ // that whatever shape of the union, the heap_record_key_cmp_st
56
+ // and heap_record_hash_st functions return the same results for
57
+ // equivalent stacktraces.
58
+ typedef struct {
59
+ enum heap_record_key_type type;
60
+ union {
61
+ // key never owns this if set
62
+ heap_stack *heap_stack;
63
+ // key never owns this if set
64
+ ddog_prof_Slice_Location *location_slice;
65
+ };
66
+ } heap_record_key;
67
+ static heap_record_key* heap_record_key_new(heap_stack*);
68
+ static void heap_record_key_free(heap_record_key*);
69
+ static int heap_record_key_cmp_st(st_data_t, st_data_t);
70
+ static st_index_t heap_record_key_hash_st(st_data_t);
71
+ static const struct st_hash_type st_hash_type_heap_record_key = {
72
+ heap_record_key_cmp_st,
73
+ heap_record_key_hash_st,
74
+ };
75
+
76
+ // Need to implement these functions to support the location-slice based keys
77
+ static st_index_t ddog_location_hash(ddog_prof_Location, st_index_t seed);
78
+ static st_index_t ddog_location_slice_hash(ddog_prof_Slice_Location, st_index_t seed);
79
+
80
+ // A heap record is used for deduping heap allocation stacktraces across multiple
81
+ // objects sharing the same allocation location.
82
+ typedef struct {
83
+ // How many objects are currently tracked by the heap recorder for this heap record.
84
+ uint32_t num_tracked_objects;
85
+ // stack is owned by the associated record and gets cleaned up alongside it
86
+ heap_stack *stack;
87
+ } heap_record;
88
+ static heap_record* heap_record_new(heap_stack*);
89
+ static void heap_record_free(heap_record*);
90
+
91
+ // An object record is used for storing data about currently tracked live objects
92
+ typedef struct {
93
+ long obj_id;
94
+ heap_record *heap_record;
95
+ live_object_data object_data;
96
+ } object_record;
97
+ static object_record* object_record_new(long, heap_record*, live_object_data);
98
+ static void object_record_free(object_record*);
99
+ static VALUE object_record_inspect(object_record*);
100
+ static object_record SKIPPED_RECORD = {0};
101
+
102
+ // A wrapper around an object record that is in the process of being recorded and was not
103
+ // yet committed.
104
+ typedef struct {
105
+ // Pointer to the (potentially partial) object_record containing metadata about an ongoing recording.
106
+ // When NULL, this symbolizes an unstarted/invalid recording.
107
+ object_record *object_record;
108
+ // A flag to track whether we had to force set the RUBY_FL_SEEN_OBJ_ID flag on this object
109
+ // as part of our workaround around rb_gc_force_recycle issues.
110
+ bool did_recycle_workaround;
111
+ } recording;
112
+
113
+ struct heap_recorder {
114
+ // Config
115
+ // Whether the recorder should try to determine approximate sizes for tracked objects.
116
+ bool size_enabled;
117
+ uint sample_rate;
118
+
119
+ // Map[key: heap_record_key*, record: heap_record*]
120
+ // NOTE: We always use heap_record_key.type == HEAP_STACK for storage but support lookups
121
+ // via heap_record_key.type == LOCATION_SLICE to allow for allocation-free fast-paths.
122
+ // NOTE: This table is currently only protected by the GVL since we never interact with it
123
+ // outside the GVL.
124
+ // NOTE: This table has ownership of both its heap_record_keys and heap_records.
125
+ st_table *heap_records;
126
+
127
+ // Map[obj_id: long, record: object_record*]
128
+ // NOTE: This table is currently only protected by the GVL since we never interact with it
129
+ // outside the GVL.
130
+ // NOTE: This table has ownership of its object_records. The keys are longs and so are
131
+ // passed as values.
132
+ st_table *object_records;
133
+
134
+ // Map[obj_id: long, record: object_record*]
135
+ // NOTE: This is a snapshot of object_records built ahead of a iteration. Outside of an
136
+ // iteration context, this table will be NULL. During an iteration, there will be no
137
+ // mutation of the data so iteration can occur without acquiring a lock.
138
+ // NOTE: Contrary to object_records, this table has no ownership of its data.
139
+ st_table *object_records_snapshot;
140
+
141
+ // Data for a heap recording that was started but not yet ended
142
+ recording active_recording;
143
+
144
+ // Reusable location array, implementing a flyweight pattern for things like iteration.
145
+ ddog_prof_Location *reusable_locations;
146
+
147
+ // Sampling state
148
+ uint num_recordings_skipped;
149
+ };
150
+ static heap_record* get_or_create_heap_record(heap_recorder*, ddog_prof_Slice_Location);
151
+ static void cleanup_heap_record_if_unused(heap_recorder*, heap_record*);
152
+ static void on_committed_object_record_cleanup(heap_recorder *heap_recorder, object_record *record);
153
+ static int st_heap_record_entry_free(st_data_t, st_data_t, st_data_t);
154
+ static int st_object_record_entry_free(st_data_t, st_data_t, st_data_t);
155
+ static int st_object_record_update(st_data_t, st_data_t, st_data_t);
156
+ static int st_object_records_iterate(st_data_t, st_data_t, st_data_t);
157
+ static int st_object_records_debug(st_data_t key, st_data_t value, st_data_t extra);
158
+ static int update_object_record_entry(st_data_t*, st_data_t*, st_data_t, int);
159
+ static void commit_recording(heap_recorder*, heap_record*, recording);
160
+
161
+ // ==========================
162
+ // Heap Recorder External API
163
+ //
164
+ // WARN: All these APIs should support receiving a NULL heap_recorder, resulting in a noop.
165
+ //
166
+ // WARN: Except for ::heap_recorder_for_each_live_object, we always assume interaction with these APIs
167
+ // happens under the GVL.
168
+ //
169
+ // ==========================
170
+ heap_recorder* heap_recorder_new(void) {
171
+ heap_recorder *recorder = ruby_xcalloc(1, sizeof(heap_recorder));
172
+
173
+ recorder->heap_records = st_init_table(&st_hash_type_heap_record_key);
174
+ recorder->object_records = st_init_numtable();
175
+ recorder->object_records_snapshot = NULL;
176
+ recorder->reusable_locations = ruby_xcalloc(MAX_FRAMES_LIMIT, sizeof(ddog_prof_Location));
177
+ recorder->active_recording = (recording) {0};
178
+ recorder->size_enabled = true;
179
+ recorder->sample_rate = 1; // By default do no sampling on top of what allocation profiling already does
180
+
181
+ return recorder;
182
+ }
183
+
184
+ void heap_recorder_free(heap_recorder *heap_recorder) {
185
+ if (heap_recorder == NULL) {
186
+ return;
187
+ }
188
+
189
+ if (heap_recorder->object_records_snapshot != NULL) {
190
+ // if there's an unfinished iteration, clean it up now
191
+ // before we clean up any other state it might depend on
192
+ heap_recorder_finish_iteration(heap_recorder);
193
+ }
194
+
195
+ // Clean-up all object records
196
+ st_foreach(heap_recorder->object_records, st_object_record_entry_free, 0);
197
+ st_free_table(heap_recorder->object_records);
198
+
199
+ // Clean-up all heap records (this includes those only referred to by queued_samples)
200
+ st_foreach(heap_recorder->heap_records, st_heap_record_entry_free, 0);
201
+ st_free_table(heap_recorder->heap_records);
202
+
203
+ if (heap_recorder->active_recording.object_record != NULL) {
204
+ // If there's a partial object record, clean it up as well
205
+ object_record_free(heap_recorder->active_recording.object_record);
206
+ }
207
+
208
+ ruby_xfree(heap_recorder->reusable_locations);
209
+
210
+ ruby_xfree(heap_recorder);
211
+ }
212
+
213
+ void heap_recorder_set_size_enabled(heap_recorder *heap_recorder, bool size_enabled) {
214
+ if (heap_recorder == NULL) {
215
+ return;
216
+ }
217
+
218
+ heap_recorder->size_enabled = size_enabled;
219
+ }
220
+
221
+ void heap_recorder_set_sample_rate(heap_recorder *heap_recorder, int sample_rate) {
222
+ if (heap_recorder == NULL) {
223
+ return;
224
+ }
225
+
226
+ if (sample_rate <= 0) {
227
+ rb_raise(rb_eArgError, "Heap sample rate must be a positive integer value but was %d", sample_rate);
228
+ }
229
+
230
+ heap_recorder->sample_rate = sample_rate;
231
+ heap_recorder->num_recordings_skipped = 0;
232
+ }
233
+
234
+ // WARN: Assumes this gets called before profiler is reinitialized on the fork
235
+ void heap_recorder_after_fork(heap_recorder *heap_recorder) {
236
+ if (heap_recorder == NULL) {
237
+ return;
238
+ }
239
+
240
+ // When forking, the child process gets a copy of the entire state of the parent process, minus
241
+ // threads.
242
+ //
243
+ // This means anything the heap recorder is tracking will still be alive after the fork and
244
+ // should thus be kept. Because this heap recorder implementation does not rely on free
245
+ // tracepoints to track liveness, any frees that happen until we fully reinitialize, will
246
+ // simply be noticed on next heap_recorder_prepare_iteration.
247
+ //
248
+ // There is one small caveat though: fork only preserves one thread and in a Ruby app, that
249
+ // will be the thread holding on to the GVL. Since we support iteration on the heap recorder
250
+ // outside of the GVL, any state specific to that interaction may be incosistent after fork
251
+ // (e.g. an acquired lock for thread safety). Iteration operates on object_records_snapshot
252
+ // though and that one will be updated on next heap_recorder_prepare_iteration so we really
253
+ // only need to finish any iteration that might have been left unfinished.
254
+ if (heap_recorder->object_records_snapshot != NULL) {
255
+ heap_recorder_finish_iteration(heap_recorder);
256
+ }
257
+ }
258
+
259
+ void start_heap_allocation_recording(heap_recorder *heap_recorder, VALUE new_obj, unsigned int weight, ddog_CharSlice *alloc_class) {
260
+ if (heap_recorder == NULL) {
261
+ return;
262
+ }
263
+
264
+ if (heap_recorder->active_recording.object_record != NULL) {
265
+ rb_raise(rb_eRuntimeError, "Detected consecutive heap allocation recording starts without end.");
266
+ }
267
+
268
+ if (heap_recorder->num_recordings_skipped + 1 < heap_recorder->sample_rate) {
269
+ heap_recorder->active_recording.object_record = &SKIPPED_RECORD;
270
+ heap_recorder->num_recordings_skipped++;
271
+ return;
272
+ }
273
+
274
+ heap_recorder->num_recordings_skipped = 0;
275
+
276
+ VALUE ruby_obj_id = rb_obj_id(new_obj);
277
+ if (!FIXNUM_P(ruby_obj_id)) {
278
+ rb_raise(rb_eRuntimeError, "Detected a bignum object id. These are not supported by heap profiling.");
279
+ }
280
+
281
+ bool did_recycle_workaround = false;
282
+
283
+ #ifdef CAN_APPLY_GC_FORCE_RECYCLE_BUG_WORKAROUND
284
+ // If we are in a ruby version that has a working rb_gc_force_recycle implementation,
285
+ // its usage may lead to an object being re-used outside of the typical GC cycle.
286
+ //
287
+ // This re-use is in theory invisible to us unless we're lucky enough to sample both
288
+ // the original object and the replacement that uses the recycled slot.
289
+ //
290
+ // In practice, we've observed (https://github.com/DataDog/dd-trace-rb/pull/3366)
291
+ // that non-noop implementations of rb_gc_force_recycle have an implementation bug
292
+ // which results in the object that re-used the recycled slot inheriting the same
293
+ // object id without setting the FL_SEEN_OBJ_ID flag. We rely on this knowledge to
294
+ // "observe" implicit frees when an object we are tracking is force-recycled.
295
+ //
296
+ // However, it may happen that we start tracking a new object and that object was
297
+ // allocated on a recycled slot. Due to the bug, this object would be missing the
298
+ // FL_SEEN_OBJ_ID flag even though it was not recycled itself. If we left it be,
299
+ // when we're doing our liveness check, the absence of the flag would trigger our
300
+ // implicit free workaround and the object would be inferred as recycled even though
301
+ // it might still be alive.
302
+ //
303
+ // Thus, if we detect that this new allocation is already missing the flag at the start
304
+ // of the heap allocation recording, we force-set it. This should be safe since we
305
+ // just called rb_obj_id on it above and the expectation is that any flaggable object
306
+ // that goes through it ends up with the flag set (as evidenced by the GC_ASSERT
307
+ // lines in https://github.com/ruby/ruby/blob/4a8d7246d15b2054eacb20f8ab3d29d39a3e7856/gc.c#L4050C14-L4050C14).
308
+ if (RB_FL_ABLE(new_obj) && !RB_FL_TEST(new_obj, RUBY_FL_SEEN_OBJ_ID)) {
309
+ RB_FL_SET(new_obj, RUBY_FL_SEEN_OBJ_ID);
310
+ did_recycle_workaround = true;
311
+ }
312
+ #endif
313
+
314
+ heap_recorder->active_recording = (recording) {
315
+ .object_record = object_record_new(FIX2LONG(ruby_obj_id), NULL, (live_object_data) {
316
+ .weight = weight * heap_recorder->sample_rate,
317
+ .class = alloc_class != NULL ? string_from_char_slice(*alloc_class) : NULL,
318
+ .alloc_gen = rb_gc_count(),
319
+ }),
320
+ .did_recycle_workaround = did_recycle_workaround,
321
+ };
322
+ }
323
+
324
+ void end_heap_allocation_recording(struct heap_recorder *heap_recorder, ddog_prof_Slice_Location locations) {
325
+ if (heap_recorder == NULL) {
326
+ return;
327
+ }
328
+
329
+ recording active_recording = heap_recorder->active_recording;
330
+
331
+ if (active_recording.object_record == NULL) {
332
+ // Recording ended without having been started?
333
+ rb_raise(rb_eRuntimeError, "Ended a heap recording that was not started");
334
+ }
335
+ // From now on, mark the global active recording as invalid so we can short-circuit at any point
336
+ // and not end up with a still active recording. the local active_recording still holds the
337
+ // data required for committing though.
338
+ heap_recorder->active_recording = (recording) {0};
339
+
340
+ if (active_recording.object_record == &SKIPPED_RECORD) {
341
+ // special marker when we decided to skip due to sampling
342
+ return;
343
+ }
344
+
345
+ heap_record *heap_record = get_or_create_heap_record(heap_recorder, locations);
346
+
347
+ // And then commit the new allocation.
348
+ commit_recording(heap_recorder, heap_record, active_recording);
349
+ }
350
+
351
+ void heap_recorder_prepare_iteration(heap_recorder *heap_recorder) {
352
+ if (heap_recorder == NULL) {
353
+ return;
354
+ }
355
+
356
+ if (heap_recorder->object_records_snapshot != NULL) {
357
+ // we could trivially handle this but we raise to highlight and catch unexpected usages.
358
+ rb_raise(rb_eRuntimeError, "New heap recorder iteration prepared without the previous one having been finished.");
359
+ }
360
+
361
+ st_foreach(heap_recorder->object_records, st_object_record_update, (st_data_t) heap_recorder);
362
+
363
+ heap_recorder->object_records_snapshot = st_copy(heap_recorder->object_records);
364
+ if (heap_recorder->object_records_snapshot == NULL) {
365
+ rb_raise(rb_eRuntimeError, "Failed to create heap snapshot.");
366
+ }
367
+ }
368
+
369
+ void heap_recorder_finish_iteration(heap_recorder *heap_recorder) {
370
+ if (heap_recorder == NULL) {
371
+ return;
372
+ }
373
+
374
+ if (heap_recorder->object_records_snapshot == NULL) {
375
+ // we could trivially handle this but we raise to highlight and catch unexpected usages.
376
+ rb_raise(rb_eRuntimeError, "Heap recorder iteration finished without having been prepared.");
377
+ }
378
+
379
+ st_free_table(heap_recorder->object_records_snapshot);
380
+ heap_recorder->object_records_snapshot = NULL;
381
+ }
382
+
383
+ // Internal data we need while performing iteration over live objects.
384
+ typedef struct {
385
+ // The callback we need to call for each object.
386
+ bool (*for_each_callback)(heap_recorder_iteration_data stack_data, void *extra_arg);
387
+ // The extra arg to pass as the second parameter to the callback.
388
+ void *for_each_callback_extra_arg;
389
+ // A reference to the heap recorder so we can access extra stuff like reusable_locations.
390
+ heap_recorder *heap_recorder;
391
+ } iteration_context;
392
+
393
+ // WARN: Assume iterations can run without the GVL for performance reasons. Do not raise, allocate or
394
+ // do NoGVL-unsafe interactions with the Ruby runtime. Any such interactions should be done during
395
+ // heap_recorder_prepare_iteration or heap_recorder_finish_iteration.
396
+ bool heap_recorder_for_each_live_object(
397
+ heap_recorder *heap_recorder,
398
+ bool (*for_each_callback)(heap_recorder_iteration_data stack_data, void *extra_arg),
399
+ void *for_each_callback_extra_arg) {
400
+ if (heap_recorder == NULL) {
401
+ return true;
402
+ }
403
+
404
+ if (heap_recorder->object_records_snapshot == NULL) {
405
+ return false;
406
+ }
407
+
408
+ iteration_context context;
409
+ context.for_each_callback = for_each_callback;
410
+ context.for_each_callback_extra_arg = for_each_callback_extra_arg;
411
+ context.heap_recorder = heap_recorder;
412
+ st_foreach(heap_recorder->object_records_snapshot, st_object_records_iterate, (st_data_t) &context);
413
+ return true;
414
+ }
415
+
416
+ void heap_recorder_testonly_assert_hash_matches(ddog_prof_Slice_Location locations) {
417
+ heap_stack *stack = heap_stack_new(locations);
418
+ heap_record_key stack_based_key = (heap_record_key) {
419
+ .type = HEAP_STACK,
420
+ .heap_stack = stack,
421
+ };
422
+ heap_record_key location_based_key = (heap_record_key) {
423
+ .type = LOCATION_SLICE,
424
+ .location_slice = &locations,
425
+ };
426
+
427
+ st_index_t stack_hash = heap_record_key_hash_st((st_data_t) &stack_based_key);
428
+ st_index_t location_hash = heap_record_key_hash_st((st_data_t) &location_based_key);
429
+
430
+ heap_stack_free(stack);
431
+
432
+ if (stack_hash != location_hash) {
433
+ rb_raise(rb_eRuntimeError, "Heap record key hashes built from the same locations differ. stack_based_hash=%"PRI_VALUE_PREFIX"u location_based_hash=%"PRI_VALUE_PREFIX"u", stack_hash, location_hash);
434
+ }
435
+ }
436
+
437
+ VALUE heap_recorder_testonly_debug(heap_recorder *heap_recorder) {
438
+ if (heap_recorder == NULL) {
439
+ return rb_str_new2("NULL heap_recorder");
440
+ }
441
+
442
+ VALUE debug_str = rb_str_new2("object records:\n");
443
+ st_foreach(heap_recorder->object_records, st_object_records_debug, (st_data_t) debug_str);
444
+ return debug_str;
445
+ }
446
+
447
+ // ==========================
448
+ // Heap Recorder Internal API
449
+ // ==========================
450
+ static int st_heap_record_entry_free(st_data_t key, st_data_t value, DDTRACE_UNUSED st_data_t extra_arg) {
451
+ heap_record_key *record_key = (heap_record_key*) key;
452
+ heap_record_key_free(record_key);
453
+ heap_record_free((heap_record *) value);
454
+ return ST_DELETE;
455
+ }
456
+
457
+ static int st_object_record_entry_free(DDTRACE_UNUSED st_data_t key, st_data_t value, DDTRACE_UNUSED st_data_t extra_arg) {
458
+ object_record_free((object_record *) value);
459
+ return ST_DELETE;
460
+ }
461
+
462
+ static int st_object_record_update(st_data_t key, st_data_t value, st_data_t extra_arg) {
463
+ long obj_id = (long) key;
464
+ object_record *record = (object_record*) value;
465
+ heap_recorder *recorder = (heap_recorder*) extra_arg;
466
+
467
+ VALUE ref;
468
+
469
+ if (!ruby_ref_from_id(LONG2NUM(obj_id), &ref)) {
470
+ // Id no longer associated with a valid ref. Need to delete this object record!
471
+ on_committed_object_record_cleanup(recorder, record);
472
+ return ST_DELETE;
473
+ }
474
+
475
+ // If we got this far, then we found a valid live object for the tracked id.
476
+
477
+ #ifdef CAN_APPLY_GC_FORCE_RECYCLE_BUG_WORKAROUND
478
+ // If we are in a ruby version that has a working rb_gc_force_recycle implementation,
479
+ // its usage may lead to an object being re-used outside of the typical GC cycle.
480
+ //
481
+ // This re-use is in theory invisible to us and would mean that the ref from which we
482
+ // collected the object_record metadata may not be the same as the current ref and
483
+ // thus any further reporting would be innacurately attributed to stale metadata.
484
+ //
485
+ // In practice, there is a way for us to notice that this happened because of a bug
486
+ // in the implementation of rb_gc_force_recycle. Our heap profiler relies on object
487
+ // ids and id2ref to detect whether objects are still alive. Turns out that when an
488
+ // object with an id is re-used via rb_gc_force_recycle, it will "inherit" the ID
489
+ // of the old object but it will NOT have the FL_SEEN_OBJ_ID as per the experiment
490
+ // in https://github.com/DataDog/dd-trace-rb/pull/3360#discussion_r1442823517
491
+ //
492
+ // Thus, if we detect that the ref we just resolved above is missing this flag, we can
493
+ // safely say re-use happened and thus treat it as an implicit free of the object
494
+ // we were tracking (the original one which got recycled).
495
+ if (RB_FL_ABLE(ref) && !RB_FL_TEST(ref, RUBY_FL_SEEN_OBJ_ID)) {
496
+
497
+ // NOTE: We don't really need to set this flag for heap recorder to work correctly
498
+ // but doing so partially mitigates a bug in runtimes with working rb_gc_force_recycle
499
+ // which leads to broken invariants and leaking of entries in obj_to_id and id_to_obj
500
+ // tables in objspace. We already do the same thing when we sample a recycled object,
501
+ // here we apply it as well to objects that replace recycled objects that were being
502
+ // tracked. More details in https://github.com/DataDog/dd-trace-rb/pull/3366
503
+ RB_FL_SET(ref, RUBY_FL_SEEN_OBJ_ID);
504
+
505
+ on_committed_object_record_cleanup(recorder, record);
506
+ return ST_DELETE;
507
+ }
508
+
509
+ #endif
510
+
511
+ if (recorder->size_enabled && !record->object_data.is_frozen) {
512
+ // if we were asked to update sizes and this object was not already seen as being frozen,
513
+ // update size again.
514
+ record->object_data.size = ruby_obj_memsize_of(ref);
515
+ // Check if it's now frozen so we skip a size update next time
516
+ record->object_data.is_frozen = RB_OBJ_FROZEN(ref);
517
+ }
518
+
519
+ return ST_CONTINUE;
520
+ }
521
+
522
+ // WARN: This can get called outside the GVL. NO HEAP ALLOCATIONS OR EXCEPTIONS ARE ALLOWED.
523
+ static int st_object_records_iterate(DDTRACE_UNUSED st_data_t key, st_data_t value, st_data_t extra) {
524
+ object_record *record = (object_record*) value;
525
+ const heap_stack *stack = record->heap_record->stack;
526
+ iteration_context *context = (iteration_context*) extra;
527
+
528
+ ddog_prof_Location *locations = context->heap_recorder->reusable_locations;
529
+
530
+ for (uint16_t i = 0; i < stack->frames_len; i++) {
531
+ const heap_frame *frame = &stack->frames[i];
532
+ ddog_prof_Location *location = &locations[i];
533
+ location->function.name.ptr = frame->name;
534
+ location->function.name.len = strlen(frame->name);
535
+ location->function.filename.ptr = frame->filename;
536
+ location->function.filename.len = strlen(frame->filename);
537
+ location->line = frame->line;
538
+ }
539
+
540
+ heap_recorder_iteration_data iteration_data;
541
+ iteration_data.object_data = record->object_data;
542
+ iteration_data.locations = (ddog_prof_Slice_Location) {.ptr = locations, .len = stack->frames_len};
543
+
544
+ if (!context->for_each_callback(iteration_data, context->for_each_callback_extra_arg)) {
545
+ return ST_STOP;
546
+ }
547
+
548
+ return ST_CONTINUE;
549
+ }
550
+
551
+ static int st_object_records_debug(DDTRACE_UNUSED st_data_t key, st_data_t value, st_data_t extra) {
552
+ VALUE debug_str = (VALUE) extra;
553
+
554
+ object_record *record = (object_record*) value;
555
+
556
+ rb_str_catf(debug_str, "%"PRIsVALUE"\n", object_record_inspect(record));
557
+
558
+ return ST_CONTINUE;
559
+ }
560
+
561
+ // Struct holding data required for an update operation on heap_records
562
+ typedef struct {
563
+ // [in] The recording containing the new object record we want to add.
564
+ // NOTE: Transfer of ownership of the contained object record is assumed, do not re-use it after call to ::update_object_record_entry
565
+ recording recording;
566
+
567
+ // [in] The heap recorder where the update is happening.
568
+ heap_recorder *heap_recorder;
569
+ } object_record_update_data;
570
+
571
+ static int update_object_record_entry(DDTRACE_UNUSED st_data_t *key, st_data_t *value, st_data_t data, int existing) {
572
+ object_record_update_data *update_data = (object_record_update_data*) data;
573
+ recording recording = update_data->recording;
574
+ object_record *new_object_record = recording.object_record;
575
+ if (existing) {
576
+ object_record *existing_record = (object_record*) (*value);
577
+ if (recording.did_recycle_workaround) {
578
+ // In this case, it's possible for an object id to be re-used and we were lucky enough to have
579
+ // sampled both the original object and the replacement so cleanup the old one and replace it with
580
+ // the new object_record (i.e. treat this as a combined free+allocation).
581
+ on_committed_object_record_cleanup(update_data->heap_recorder, existing_record);
582
+ } else {
583
+ // This is not supposed to happen, raising...
584
+ VALUE existing_inspect = object_record_inspect(existing_record);
585
+ VALUE new_inspect = object_record_inspect(new_object_record);
586
+ rb_raise(rb_eRuntimeError, "Object ids are supposed to be unique. We got 2 allocation recordings with "
587
+ "the same id. previous=%"PRIsVALUE" new=%"PRIsVALUE, existing_inspect, new_inspect);
588
+ }
589
+ }
590
+ // Always carry on with the update, we want the new record to be there at the end
591
+ (*value) = (st_data_t) new_object_record;
592
+ return ST_CONTINUE;
593
+ }
594
+
595
+ static void commit_recording(heap_recorder *heap_recorder, heap_record *heap_record, recording recording) {
596
+ // Link the object record with the corresponding heap record. This was the last remaining thing we
597
+ // needed to fully build the object_record.
598
+ recording.object_record->heap_record = heap_record;
599
+ if (heap_record->num_tracked_objects == UINT32_MAX) {
600
+ rb_raise(rb_eRuntimeError, "Reached maximum number of tracked objects for heap record");
601
+ }
602
+ heap_record->num_tracked_objects++;
603
+
604
+ // Update object_records with the data for this new recording
605
+ object_record_update_data update_data = (object_record_update_data) {
606
+ .heap_recorder = heap_recorder,
607
+ .recording = recording,
608
+ };
609
+ st_update(heap_recorder->object_records, recording.object_record->obj_id, update_object_record_entry, (st_data_t) &update_data);
610
+ }
611
+
612
+ // Struct holding data required for an update operation on heap_records
613
+ typedef struct {
614
+ // [in] The locations we did this update with
615
+ ddog_prof_Slice_Location locations;
616
+ // [out] Pointer that will be updated to the updated heap record to prevent having to do
617
+ // another lookup to access the updated heap record.
618
+ heap_record **record;
619
+ } heap_record_update_data;
620
+
621
+ // This function assumes ownership of stack_data is passed on to it so it'll either transfer ownership or clean-up.
622
+ static int update_heap_record_entry_with_new_allocation(st_data_t *key, st_data_t *value, st_data_t data, int existing) {
623
+ heap_record_update_data *update_data = (heap_record_update_data*) data;
624
+
625
+ if (!existing) {
626
+ // there was no matching heap record so lets create a new one...
627
+ // we need to initialize a heap_record_key with a new stack and use that for the key storage. We can't use the
628
+ // locations-based key we used for the update call because we don't own its lifecycle. So we create a new
629
+ // heap stack and will pass ownership of it to the heap_record.
630
+ heap_stack *stack = heap_stack_new(update_data->locations);
631
+ (*key) = (st_data_t) heap_record_key_new(stack);
632
+ (*value) = (st_data_t) heap_record_new(stack);
633
+ }
634
+
635
+ heap_record *record = (heap_record*) (*value);
636
+ (*update_data->record) = record;
637
+
638
+ return ST_CONTINUE;
639
+ }
640
+
641
+ static heap_record* get_or_create_heap_record(heap_recorder *heap_recorder, ddog_prof_Slice_Location locations) {
642
+ // For performance reasons we use a stack-allocated location-slice based key. This allows us
643
+ // to do allocation-free lookups and reuse of a matching existing heap record.
644
+ // NOTE: If we end up creating a new record, we'll create a heap-allocated key we own and use that for storage
645
+ // instead of this one.
646
+ heap_record_key lookup_key = (heap_record_key) {
647
+ .type = LOCATION_SLICE,
648
+ .location_slice = &locations,
649
+ };
650
+
651
+ heap_record *heap_record = NULL;
652
+ heap_record_update_data update_data = (heap_record_update_data) {
653
+ .locations = locations,
654
+ .record = &heap_record,
655
+ };
656
+ st_update(heap_recorder->heap_records, (st_data_t) &lookup_key, update_heap_record_entry_with_new_allocation, (st_data_t) &update_data);
657
+
658
+ return heap_record;
659
+ }
660
+
661
+ static void cleanup_heap_record_if_unused(heap_recorder *heap_recorder, heap_record *heap_record) {
662
+ if (heap_record->num_tracked_objects > 0) {
663
+ // still being used! do nothing...
664
+ return;
665
+ }
666
+
667
+ heap_record_key heap_key = (heap_record_key) {
668
+ .type = HEAP_STACK,
669
+ .heap_stack = heap_record->stack,
670
+ };
671
+ // We need to access the deleted key to free it since we gave ownership of the keys to the hash.
672
+ // st_delete will change this pointer to point to the removed key if one is found.
673
+ heap_record_key *deleted_key = &heap_key;
674
+ if (!st_delete(heap_recorder->heap_records, (st_data_t*) &deleted_key, NULL)) {
675
+ rb_raise(rb_eRuntimeError, "Attempted to cleanup an untracked heap_record");
676
+ };
677
+ heap_record_key_free(deleted_key);
678
+ heap_record_free(heap_record);
679
+ }
680
+
681
+ static void on_committed_object_record_cleanup(heap_recorder *heap_recorder, object_record *record) {
682
+ // Starting with the associated heap record. There will now be one less tracked object pointing to it
683
+ heap_record *heap_record = record->heap_record;
684
+ heap_record->num_tracked_objects--;
685
+
686
+ // One less object using this heap record, it may have become unused...
687
+ cleanup_heap_record_if_unused(heap_recorder, heap_record);
688
+
689
+ object_record_free(record);
690
+ }
691
+
692
+ // ===============
693
+ // Heap Record API
694
+ // ===============
695
+ heap_record* heap_record_new(heap_stack *stack) {
696
+ heap_record *record = ruby_xcalloc(1, sizeof(heap_record));
697
+ record->num_tracked_objects = 0;
698
+ record->stack = stack;
699
+ return record;
700
+ }
701
+
702
+ void heap_record_free(heap_record *record) {
703
+ heap_stack_free(record->stack);
704
+ ruby_xfree(record);
705
+ }
706
+
707
+
708
+ // =================
709
+ // Object Record API
710
+ // =================
711
+ object_record* object_record_new(long obj_id, heap_record *heap_record, live_object_data object_data) {
712
+ object_record *record = ruby_xcalloc(1, sizeof(object_record));
713
+ record->obj_id = obj_id;
714
+ record->heap_record = heap_record;
715
+ record->object_data = object_data;
716
+ return record;
717
+ }
718
+
719
+ void object_record_free(object_record *record) {
720
+ if (record->object_data.class != NULL) {
721
+ ruby_xfree(record->object_data.class);
722
+ }
723
+ ruby_xfree(record);
724
+ }
725
+
726
+ VALUE object_record_inspect(object_record *record) {
727
+ heap_frame top_frame = record->heap_record->stack->frames[0];
728
+ VALUE inspect = rb_sprintf("obj_id=%ld weight=%d size=%zu location=%s:%d alloc_gen=%zu ",
729
+ record->obj_id, record->object_data.weight, record->object_data.size, top_frame.filename,
730
+ (int) top_frame.line, record->object_data.alloc_gen);
731
+
732
+ const char *class = record->object_data.class;
733
+ if (class != NULL) {
734
+ rb_str_catf(inspect, "class=%s ", class);
735
+ }
736
+ VALUE ref;
737
+
738
+ if (!ruby_ref_from_id(LONG2NUM(record->obj_id), &ref)) {
739
+ rb_str_catf(inspect, "object=<invalid>");
740
+ } else {
741
+ VALUE ruby_inspect = ruby_safe_inspect(ref);
742
+ if (ruby_inspect != Qnil) {
743
+ rb_str_catf(inspect, "object=%"PRIsVALUE, ruby_inspect);
744
+ } else {
745
+ rb_str_catf(inspect, "object=%s", ruby_value_type_to_string(rb_type(ref)));
746
+ }
747
+ }
748
+
749
+ return inspect;
750
+ }
751
+
752
+ // ==============
753
+ // Heap Frame API
754
+ // ==============
755
+ int heap_frame_cmp(heap_frame *f1, heap_frame *f2) {
756
+ int line_diff = (int) (f1->line - f2->line);
757
+ if (line_diff != 0) {
758
+ return line_diff;
759
+ }
760
+ int cmp = strcmp(f1->name, f2->name);
761
+ if (cmp != 0) {
762
+ return cmp;
763
+ }
764
+ return strcmp(f1->filename, f2->filename);
765
+ }
766
+
767
+ // TODO: Research potential performance improvements around hashing stuff here
768
+ // once we have a benchmarking suite.
769
+ // Example: Each call to st_hash is calling murmur_finish and we may want
770
+ // to only finish once per structure, not per field?
771
+ // Example: There may be a more efficient hashing for line that is not the
772
+ // generic st_hash algorithm?
773
+
774
+ // WARN: Must be kept in-sync with ::char_slice_hash
775
+ st_index_t string_hash(char *str, st_index_t seed) {
776
+ return st_hash(str, strlen(str), seed);
777
+ }
778
+
779
+ // WARN: Must be kept in-sync with ::string_hash
780
+ st_index_t char_slice_hash(ddog_CharSlice char_slice, st_index_t seed) {
781
+ return st_hash(char_slice.ptr, char_slice.len, seed);
782
+ }
783
+
784
+ // WARN: Must be kept in-sync with ::ddog_location_hash
785
+ st_index_t heap_frame_hash(heap_frame *frame, st_index_t seed) {
786
+ st_index_t hash = string_hash(frame->name, seed);
787
+ hash = string_hash(frame->filename, hash);
788
+ hash = st_hash(&frame->line, sizeof(frame->line), hash);
789
+ return hash;
790
+ }
791
+
792
+ // WARN: Must be kept in-sync with ::heap_frame_hash
793
+ st_index_t ddog_location_hash(ddog_prof_Location location, st_index_t seed) {
794
+ st_index_t hash = char_slice_hash(location.function.name, seed);
795
+ hash = char_slice_hash(location.function.filename, hash);
796
+ // Convert ddog_prof line type to the same type we use for our heap_frames to
797
+ // ensure we have compatible hashes
798
+ int32_t line_as_int32 = (int32_t) location.line;
799
+ hash = st_hash(&line_as_int32, sizeof(line_as_int32), hash);
800
+ return hash;
801
+ }
802
+
803
+ // ==============
804
+ // Heap Stack API
805
+ // ==============
806
+ heap_stack* heap_stack_new(ddog_prof_Slice_Location locations) {
807
+ uint16_t frames_len = locations.len;
808
+ if (frames_len > MAX_FRAMES_LIMIT) {
809
+ // This should not be happening anyway since MAX_FRAMES_LIMIT should be shared with
810
+ // the stacktrace construction mechanism. If it happens, lets just raise. This should
811
+ // be safe since only allocate with the GVL anyway.
812
+ rb_raise(rb_eRuntimeError, "Found stack with more than %d frames (%d)", MAX_FRAMES_LIMIT, frames_len);
813
+ }
814
+ heap_stack *stack = ruby_xcalloc(1, sizeof(heap_stack) + frames_len * sizeof(heap_frame));
815
+ stack->frames_len = frames_len;
816
+ for (uint16_t i = 0; i < stack->frames_len; i++) {
817
+ const ddog_prof_Location *location = &locations.ptr[i];
818
+ stack->frames[i] = (heap_frame) {
819
+ .name = string_from_char_slice(location->function.name),
820
+ .filename = string_from_char_slice(location->function.filename),
821
+ // ddog_prof_Location is a int64_t. We don't expect to have to profile files with more than
822
+ // 2M lines so this cast should be fairly safe?
823
+ .line = (int32_t) location->line,
824
+ };
825
+ }
826
+ return stack;
827
+ }
828
+
829
+ void heap_stack_free(heap_stack *stack) {
830
+ for (uint64_t i = 0; i < stack->frames_len; i++) {
831
+ heap_frame *frame = &stack->frames[i];
832
+ ruby_xfree(frame->name);
833
+ ruby_xfree(frame->filename);
834
+ }
835
+ ruby_xfree(stack);
836
+ }
837
+
838
+ // WARN: Must be kept in-sync with ::ddog_location_slice_hash
839
+ st_index_t heap_stack_hash(heap_stack *stack, st_index_t seed) {
840
+ st_index_t hash = seed;
841
+ for (uint64_t i = 0; i < stack->frames_len; i++) {
842
+ hash = heap_frame_hash(&stack->frames[i], hash);
843
+ }
844
+ return hash;
845
+ }
846
+
847
+ // WARN: Must be kept in-sync with ::heap_stack_hash
848
+ st_index_t ddog_location_slice_hash(ddog_prof_Slice_Location locations, st_index_t seed) {
849
+ st_index_t hash = seed;
850
+ for (uint64_t i = 0; i < locations.len; i++) {
851
+ hash = ddog_location_hash(locations.ptr[i], hash);
852
+ }
853
+ return hash;
854
+ }
855
+
856
+ // ===================
857
+ // Heap Record Key API
858
+ // ===================
859
+ heap_record_key* heap_record_key_new(heap_stack *stack) {
860
+ heap_record_key *key = ruby_xmalloc(sizeof(heap_record_key));
861
+ key->type = HEAP_STACK;
862
+ key->heap_stack = stack;
863
+ return key;
864
+ }
865
+
866
+ void heap_record_key_free(heap_record_key *key) {
867
+ ruby_xfree(key);
868
+ }
869
+
870
+ static inline size_t heap_record_key_len(heap_record_key *key) {
871
+ if (key->type == HEAP_STACK) {
872
+ return key->heap_stack->frames_len;
873
+ } else {
874
+ return key->location_slice->len;
875
+ }
876
+ }
877
+
878
+ static inline int64_t heap_record_key_entry_line(heap_record_key *key, size_t entry_i) {
879
+ if (key->type == HEAP_STACK) {
880
+ return key->heap_stack->frames[entry_i].line;
881
+ } else {
882
+ return key->location_slice->ptr[entry_i].line;
883
+ }
884
+ }
885
+
886
+ static inline size_t heap_record_key_entry_name(heap_record_key *key, size_t entry_i, const char **name_ptr) {
887
+ if (key->type == HEAP_STACK) {
888
+ char *name = key->heap_stack->frames[entry_i].name;
889
+ (*name_ptr) = name;
890
+ return strlen(name);
891
+ } else {
892
+ ddog_CharSlice name = key->location_slice->ptr[entry_i].function.name;
893
+ (*name_ptr) = name.ptr;
894
+ return name.len;
895
+ }
896
+ }
897
+
898
+ static inline size_t heap_record_key_entry_filename(heap_record_key *key, size_t entry_i, const char **filename_ptr) {
899
+ if (key->type == HEAP_STACK) {
900
+ char *filename = key->heap_stack->frames[entry_i].filename;
901
+ (*filename_ptr) = filename;
902
+ return strlen(filename);
903
+ } else {
904
+ ddog_CharSlice filename = key->location_slice->ptr[entry_i].function.filename;
905
+ (*filename_ptr) = filename.ptr;
906
+ return filename.len;
907
+ }
908
+ }
909
+
910
+ int heap_record_key_cmp_st(st_data_t key1, st_data_t key2) {
911
+ heap_record_key *key_record1 = (heap_record_key*) key1;
912
+ heap_record_key *key_record2 = (heap_record_key*) key2;
913
+
914
+ // Fast path, check if lengths differ
915
+ size_t key_record1_len = heap_record_key_len(key_record1);
916
+ size_t key_record2_len = heap_record_key_len(key_record2);
917
+
918
+ if (key_record1_len != key_record2_len) {
919
+ return ((int) key_record1_len) - ((int) key_record2_len);
920
+ }
921
+
922
+ // If we got this far, we have same lengths so need to check item-by-item
923
+ for (size_t i = 0; i < key_record1_len; i++) {
924
+ // Lines are faster to compare, lets do that first
925
+ size_t line1 = heap_record_key_entry_line(key_record1, i);
926
+ size_t line2 = heap_record_key_entry_line(key_record2, i);
927
+ if (line1 != line2) {
928
+ return ((int) line1) - ((int)line2);
929
+ }
930
+
931
+ // Then come names, they are usually smaller than filenames
932
+ const char *name1, *name2;
933
+ size_t name1_len = heap_record_key_entry_name(key_record1, i, &name1);
934
+ size_t name2_len = heap_record_key_entry_name(key_record2, i, &name2);
935
+ if (name1_len != name2_len) {
936
+ return ((int) name1_len) - ((int) name2_len);
937
+ }
938
+ int name_cmp_result = strncmp(name1, name2, name1_len);
939
+ if (name_cmp_result != 0) {
940
+ return name_cmp_result;
941
+ }
942
+
943
+ // Then come filenames
944
+ const char *filename1, *filename2;
945
+ int64_t filename1_len = heap_record_key_entry_filename(key_record1, i, &filename1);
946
+ int64_t filename2_len = heap_record_key_entry_filename(key_record2, i, &filename2);
947
+ if (filename1_len != filename2_len) {
948
+ return ((int) filename1_len) - ((int) filename2_len);
949
+ }
950
+ int filename_cmp_result = strncmp(filename1, filename2, filename1_len);
951
+ if (filename_cmp_result != 0) {
952
+ return filename_cmp_result;
953
+ }
954
+ }
955
+
956
+ // If we survived the above for, then everything matched
957
+ return 0;
958
+ }
959
+
960
+ // Initial seed for hash functions
961
+ #define FNV1_32A_INIT 0x811c9dc5
962
+
963
+ st_index_t heap_record_key_hash_st(st_data_t key) {
964
+ heap_record_key *record_key = (heap_record_key*) key;
965
+ if (record_key->type == HEAP_STACK) {
966
+ return heap_stack_hash(record_key->heap_stack, FNV1_32A_INIT);
967
+ } else {
968
+ return ddog_location_slice_hash(*record_key->location_slice, FNV1_32A_INIT);
969
+ }
970
+ }