ddtrace 1.1.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (641) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +423 -1
  3. data/LICENSE-3rdparty.csv +3 -0
  4. data/README.md +9 -4
  5. data/ext/ddtrace_profiling_loader/ddtrace_profiling_loader.c +21 -5
  6. data/ext/ddtrace_profiling_loader/extconf.rb +22 -1
  7. data/ext/ddtrace_profiling_native_extension/NativeExtensionDesign.md +52 -8
  8. data/ext/ddtrace_profiling_native_extension/clock_id.h +22 -1
  9. data/ext/ddtrace_profiling_native_extension/clock_id_from_pthread.c +34 -3
  10. data/ext/ddtrace_profiling_native_extension/clock_id_noop.c +11 -2
  11. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.c +899 -0
  12. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.h +9 -0
  13. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +776 -0
  14. data/ext/ddtrace_profiling_native_extension/collectors_dynamic_sampling_rate.c +142 -0
  15. data/ext/ddtrace_profiling_native_extension/collectors_dynamic_sampling_rate.h +14 -0
  16. data/ext/ddtrace_profiling_native_extension/collectors_idle_sampling_helper.c +241 -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 +175 -63
  19. data/ext/ddtrace_profiling_native_extension/collectors_stack.h +18 -0
  20. data/ext/ddtrace_profiling_native_extension/extconf.rb +90 -18
  21. data/ext/ddtrace_profiling_native_extension/helpers.h +17 -0
  22. data/ext/ddtrace_profiling_native_extension/http_transport.c +354 -0
  23. data/ext/ddtrace_profiling_native_extension/libdatadog_helpers.h +18 -0
  24. data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +154 -21
  25. data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +256 -17
  26. data/ext/ddtrace_profiling_native_extension/private_vm_api_access.h +17 -5
  27. data/ext/ddtrace_profiling_native_extension/profiling.c +223 -3
  28. data/ext/ddtrace_profiling_native_extension/ruby_helpers.c +110 -0
  29. data/ext/ddtrace_profiling_native_extension/ruby_helpers.h +89 -0
  30. data/ext/ddtrace_profiling_native_extension/setup_signal_handler.c +115 -0
  31. data/ext/ddtrace_profiling_native_extension/setup_signal_handler.h +11 -0
  32. data/ext/ddtrace_profiling_native_extension/stack_recorder.c +392 -44
  33. data/ext/ddtrace_profiling_native_extension/stack_recorder.h +25 -14
  34. data/ext/ddtrace_profiling_native_extension/time_helpers.c +17 -0
  35. data/ext/ddtrace_profiling_native_extension/time_helpers.h +10 -0
  36. data/lib/datadog/appsec/assets/blocked.html +98 -3
  37. data/lib/datadog/appsec/assets/blocked.json +1 -0
  38. data/lib/datadog/appsec/assets/blocked.text +5 -0
  39. data/lib/datadog/appsec/assets/waf_rules/recommended.json +1250 -300
  40. data/lib/datadog/appsec/assets/waf_rules/risky.json +78 -78
  41. data/lib/datadog/appsec/assets/waf_rules/strict.json +308 -73
  42. data/lib/datadog/appsec/assets.rb +3 -3
  43. data/lib/datadog/appsec/autoload.rb +4 -2
  44. data/lib/datadog/appsec/configuration/settings.rb +40 -23
  45. data/lib/datadog/appsec/configuration.rb +9 -3
  46. data/lib/datadog/appsec/contrib/auto_instrument.rb +1 -3
  47. data/lib/datadog/appsec/contrib/configuration/settings.rb +2 -2
  48. data/lib/datadog/appsec/contrib/integration.rb +1 -1
  49. data/lib/datadog/appsec/contrib/patcher.rb +1 -1
  50. data/lib/datadog/appsec/contrib/rack/configuration/settings.rb +3 -3
  51. data/lib/datadog/appsec/contrib/rack/ext.rb +1 -1
  52. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +32 -27
  53. data/lib/datadog/appsec/contrib/rack/integration.rb +5 -5
  54. data/lib/datadog/appsec/contrib/rack/patcher.rb +2 -2
  55. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +17 -21
  56. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +13 -13
  57. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +13 -13
  58. data/lib/datadog/appsec/contrib/rack/request.rb +21 -1
  59. data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +3 -3
  60. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +50 -23
  61. data/lib/datadog/appsec/contrib/rack/response.rb +1 -1
  62. data/lib/datadog/appsec/contrib/rails/configuration/settings.rb +3 -3
  63. data/lib/datadog/appsec/contrib/rails/ext.rb +1 -1
  64. data/lib/datadog/appsec/contrib/rails/framework.rb +1 -1
  65. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +12 -11
  66. data/lib/datadog/appsec/contrib/rails/integration.rb +5 -5
  67. data/lib/datadog/appsec/contrib/rails/patcher.rb +14 -13
  68. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +13 -13
  69. data/lib/datadog/appsec/contrib/rails/request.rb +4 -1
  70. data/lib/datadog/appsec/contrib/rails/request_middleware.rb +1 -1
  71. data/lib/datadog/appsec/contrib/sinatra/configuration/settings.rb +3 -3
  72. data/lib/datadog/appsec/contrib/sinatra/ext.rb +2 -1
  73. data/lib/datadog/appsec/contrib/sinatra/framework.rb +1 -1
  74. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +21 -19
  75. data/lib/datadog/appsec/contrib/sinatra/integration.rb +4 -4
  76. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +22 -15
  77. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +12 -12
  78. data/lib/datadog/appsec/contrib/sinatra/request_middleware.rb +1 -1
  79. data/lib/datadog/appsec/event.rb +10 -14
  80. data/lib/datadog/appsec/extensions.rb +43 -23
  81. data/lib/datadog/appsec/instrumentation/gateway.rb +17 -3
  82. data/lib/datadog/appsec/processor.rb +51 -21
  83. data/lib/datadog/appsec/rate_limiter.rb +1 -1
  84. data/lib/datadog/appsec/reactive/address_hash.rb +1 -1
  85. data/lib/datadog/appsec/reactive/engine.rb +3 -3
  86. data/lib/datadog/appsec/reactive/operation.rb +5 -5
  87. data/lib/datadog/appsec/reactive/subscriber.rb +1 -1
  88. data/lib/datadog/appsec/response.rb +63 -0
  89. data/lib/datadog/appsec/utils/http/media_range.rb +201 -0
  90. data/lib/datadog/appsec/utils/http/media_type.rb +87 -0
  91. data/lib/datadog/appsec/utils/http.rb +9 -0
  92. data/lib/datadog/appsec/utils.rb +7 -0
  93. data/lib/datadog/appsec.rb +6 -6
  94. data/lib/datadog/ci/configuration/components.rb +1 -1
  95. data/lib/datadog/ci/configuration/settings.rb +1 -1
  96. data/lib/datadog/ci/contrib/cucumber/configuration/settings.rb +2 -2
  97. data/lib/datadog/ci/contrib/cucumber/formatter.rb +5 -5
  98. data/lib/datadog/ci/contrib/cucumber/instrumentation.rb +1 -1
  99. data/lib/datadog/ci/contrib/cucumber/integration.rb +4 -4
  100. data/lib/datadog/ci/contrib/cucumber/patcher.rb +2 -2
  101. data/lib/datadog/ci/contrib/rspec/configuration/settings.rb +2 -2
  102. data/lib/datadog/ci/contrib/rspec/example.rb +5 -5
  103. data/lib/datadog/ci/contrib/rspec/integration.rb +4 -4
  104. data/lib/datadog/ci/contrib/rspec/patcher.rb +2 -2
  105. data/lib/datadog/ci/ext/environment.rb +78 -20
  106. data/lib/datadog/ci/extensions.rb +4 -4
  107. data/lib/datadog/ci/flush.rb +2 -2
  108. data/lib/datadog/ci/test.rb +3 -3
  109. data/lib/datadog/ci.rb +6 -6
  110. data/lib/datadog/core/buffer/cruby.rb +1 -1
  111. data/lib/datadog/core/buffer/thread_safe.rb +1 -1
  112. data/lib/datadog/core/configuration/agent_settings_resolver.rb +8 -11
  113. data/lib/datadog/core/configuration/base.rb +14 -2
  114. data/lib/datadog/core/configuration/components.rb +103 -52
  115. data/lib/datadog/core/configuration/ext.rb +26 -0
  116. data/lib/datadog/core/configuration/option_definition.rb +12 -3
  117. data/lib/datadog/core/configuration/option_definition_set.rb +1 -1
  118. data/lib/datadog/core/configuration/options.rb +3 -3
  119. data/lib/datadog/core/configuration/settings.rb +78 -250
  120. data/lib/datadog/core/configuration.rb +9 -6
  121. data/lib/datadog/core/diagnostics/environment_logger.rb +10 -5
  122. data/lib/datadog/core/diagnostics/health.rb +5 -23
  123. data/lib/datadog/core/environment/cgroup.rb +1 -1
  124. data/lib/datadog/core/environment/container.rb +1 -1
  125. data/lib/datadog/core/environment/ext.rb +1 -1
  126. data/lib/datadog/core/environment/identity.rb +2 -2
  127. data/lib/datadog/core/environment/platform.rb +40 -0
  128. data/lib/datadog/core/environment/socket.rb +1 -1
  129. data/lib/datadog/core/environment/variable_helpers.rb +58 -10
  130. data/lib/datadog/core/error.rb +1 -1
  131. data/lib/datadog/core/extensions.rb +1 -1
  132. data/lib/datadog/core/header_collection.rb +41 -0
  133. data/lib/datadog/core/metrics/client.rb +10 -9
  134. data/lib/datadog/core/metrics/ext.rb +0 -2
  135. data/lib/datadog/core/metrics/options.rb +3 -3
  136. data/lib/datadog/core/runtime/ext.rb +1 -1
  137. data/lib/datadog/core/runtime/metrics.rb +6 -6
  138. data/lib/datadog/core/telemetry/client.rb +79 -0
  139. data/lib/datadog/core/telemetry/collector.rb +233 -0
  140. data/lib/datadog/core/telemetry/emitter.rb +48 -0
  141. data/lib/datadog/core/telemetry/event.rb +71 -0
  142. data/lib/datadog/core/telemetry/ext.rb +11 -0
  143. data/lib/datadog/core/telemetry/heartbeat.rb +37 -0
  144. data/lib/datadog/core/telemetry/http/adapters/net.rb +113 -0
  145. data/lib/datadog/core/telemetry/http/env.rb +20 -0
  146. data/lib/datadog/core/telemetry/http/ext.rb +20 -0
  147. data/lib/datadog/core/telemetry/http/response.rb +68 -0
  148. data/lib/datadog/core/telemetry/http/transport.rb +53 -0
  149. data/lib/datadog/core/telemetry/v1/app_event.rb +52 -0
  150. data/lib/datadog/core/telemetry/v1/application.rb +86 -0
  151. data/lib/datadog/core/telemetry/v1/configuration.rb +25 -0
  152. data/lib/datadog/core/telemetry/v1/dependency.rb +36 -0
  153. data/lib/datadog/core/telemetry/v1/host.rb +51 -0
  154. data/lib/datadog/core/telemetry/v1/integration.rb +58 -0
  155. data/lib/datadog/core/telemetry/v1/product.rb +28 -0
  156. data/lib/datadog/core/telemetry/v1/telemetry_request.rb +100 -0
  157. data/lib/datadog/core/utils/compression.rb +5 -1
  158. data/lib/datadog/core/utils/object_set.rb +1 -1
  159. data/lib/datadog/core/utils/sequence.rb +5 -0
  160. data/lib/datadog/core/utils/string_table.rb +1 -1
  161. data/lib/datadog/core/utils/time.rb +3 -3
  162. data/lib/datadog/core/utils.rb +1 -22
  163. data/lib/datadog/core/vendor/multipart-post/multipart/post/multipartable.rb +2 -2
  164. data/lib/datadog/core/vendor/multipart-post/net/http/post/multipart.rb +3 -3
  165. data/lib/datadog/core/workers/async.rb +1 -3
  166. data/lib/datadog/core/workers/polling.rb +2 -2
  167. data/lib/datadog/core/workers/runtime_metrics.rb +4 -4
  168. data/lib/datadog/core.rb +22 -56
  169. data/lib/datadog/kit/appsec/events.rb +75 -0
  170. data/lib/datadog/kit/enable_core_dumps.rb +1 -0
  171. data/lib/datadog/kit/identity.rb +8 -7
  172. data/lib/datadog/kit.rb +1 -1
  173. data/lib/datadog/opentelemetry/api/context.rb +187 -0
  174. data/lib/datadog/opentelemetry/api/trace/span.rb +15 -0
  175. data/lib/datadog/opentelemetry/sdk/configurator.rb +38 -0
  176. data/lib/datadog/opentelemetry/sdk/id_generator.rb +27 -0
  177. data/lib/datadog/opentelemetry/sdk/propagator.rb +91 -0
  178. data/lib/datadog/opentelemetry/sdk/span_processor.rb +92 -0
  179. data/lib/datadog/opentelemetry.rb +48 -0
  180. data/lib/datadog/opentracer/distributed_headers.rb +7 -9
  181. data/lib/datadog/opentracer/rack_propagator.rb +10 -9
  182. data/lib/datadog/opentracer/span.rb +1 -1
  183. data/lib/datadog/opentracer/text_map_propagator.rb +13 -12
  184. data/lib/datadog/opentracer/thread_local_scope_manager.rb +26 -3
  185. data/lib/datadog/opentracer/tracer.rb +23 -21
  186. data/lib/datadog/opentracer.rb +16 -16
  187. data/lib/datadog/profiling/buffer.rb +3 -3
  188. data/lib/datadog/profiling/collectors/code_provenance.rb +1 -0
  189. data/lib/datadog/profiling/collectors/cpu_and_wall_time.rb +43 -0
  190. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +91 -0
  191. data/lib/datadog/profiling/collectors/dynamic_sampling_rate.rb +14 -0
  192. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +68 -0
  193. data/lib/datadog/profiling/collectors/old_stack.rb +15 -8
  194. data/lib/datadog/profiling/collectors/stack.rb +3 -6
  195. data/lib/datadog/profiling/encoding/profile.rb +8 -12
  196. data/lib/datadog/profiling/events/stack.rb +1 -1
  197. data/lib/datadog/profiling/exporter.rb +69 -9
  198. data/lib/datadog/profiling/ext/forking.rb +41 -42
  199. data/lib/datadog/profiling/ext.rb +3 -15
  200. data/lib/datadog/profiling/flush.rb +25 -56
  201. data/lib/datadog/profiling/http_transport.rb +132 -0
  202. data/lib/datadog/profiling/old_recorder.rb +109 -0
  203. data/lib/datadog/profiling/pprof/builder.rb +4 -4
  204. data/lib/datadog/profiling/pprof/converter.rb +1 -1
  205. data/lib/datadog/profiling/pprof/message_set.rb +1 -1
  206. data/lib/datadog/profiling/pprof/stack_sample.rb +4 -4
  207. data/lib/datadog/profiling/pprof/string_table.rb +1 -1
  208. data/lib/datadog/profiling/pprof/template.rb +5 -5
  209. data/lib/datadog/profiling/preload.rb +1 -1
  210. data/lib/datadog/profiling/profiler.rb +7 -0
  211. data/lib/datadog/profiling/scheduler.rb +28 -49
  212. data/lib/datadog/profiling/stack_recorder.rb +50 -4
  213. data/lib/datadog/profiling/tag_builder.rb +6 -1
  214. data/lib/datadog/profiling/tasks/setup.rb +2 -9
  215. data/lib/datadog/profiling/trace_identifiers/ddtrace.rb +2 -2
  216. data/lib/datadog/profiling/trace_identifiers/helper.rb +1 -1
  217. data/lib/datadog/profiling.rb +24 -21
  218. data/lib/datadog/tracing/analytics.rb +1 -1
  219. data/lib/datadog/tracing/buffer.rb +5 -5
  220. data/lib/datadog/tracing/client_ip.rb +164 -0
  221. data/lib/datadog/tracing/configuration/ext.rb +47 -4
  222. data/lib/datadog/tracing/configuration/settings.rb +433 -0
  223. data/lib/datadog/tracing/context.rb +1 -1
  224. data/lib/datadog/tracing/context_provider.rb +18 -2
  225. data/lib/datadog/tracing/contrib/action_cable/configuration/settings.rb +2 -2
  226. data/lib/datadog/tracing/contrib/action_cable/event.rb +4 -5
  227. data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +4 -4
  228. data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +3 -3
  229. data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +4 -4
  230. data/lib/datadog/tracing/contrib/action_cable/events.rb +4 -4
  231. data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +3 -4
  232. data/lib/datadog/tracing/contrib/action_cable/integration.rb +4 -4
  233. data/lib/datadog/tracing/contrib/action_cable/patcher.rb +4 -4
  234. data/lib/datadog/tracing/contrib/action_mailer/configuration/settings.rb +2 -2
  235. data/lib/datadog/tracing/contrib/action_mailer/event.rb +3 -3
  236. data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +3 -3
  237. data/lib/datadog/tracing/contrib/action_mailer/events/process.rb +3 -3
  238. data/lib/datadog/tracing/contrib/action_mailer/events.rb +2 -2
  239. data/lib/datadog/tracing/contrib/action_mailer/integration.rb +4 -4
  240. data/lib/datadog/tracing/contrib/action_mailer/patcher.rb +3 -3
  241. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +10 -6
  242. data/lib/datadog/tracing/contrib/action_pack/action_controller/patcher.rb +2 -2
  243. data/lib/datadog/tracing/contrib/action_pack/configuration/settings.rb +2 -2
  244. data/lib/datadog/tracing/contrib/action_pack/integration.rb +4 -4
  245. data/lib/datadog/tracing/contrib/action_pack/patcher.rb +2 -2
  246. data/lib/datadog/tracing/contrib/action_pack/utils.rb +1 -1
  247. data/lib/datadog/tracing/contrib/action_view/configuration/settings.rb +2 -2
  248. data/lib/datadog/tracing/contrib/action_view/event.rb +1 -1
  249. data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +5 -5
  250. data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +5 -5
  251. data/lib/datadog/tracing/contrib/action_view/events.rb +2 -2
  252. data/lib/datadog/tracing/contrib/action_view/instrumentation/partial_renderer.rb +2 -2
  253. data/lib/datadog/tracing/contrib/action_view/instrumentation/template_renderer.rb +2 -2
  254. data/lib/datadog/tracing/contrib/action_view/integration.rb +4 -4
  255. data/lib/datadog/tracing/contrib/action_view/patcher.rb +7 -7
  256. data/lib/datadog/tracing/contrib/action_view/utils.rb +1 -1
  257. data/lib/datadog/tracing/contrib/active_job/configuration/settings.rb +3 -3
  258. data/lib/datadog/tracing/contrib/active_job/event.rb +3 -3
  259. data/lib/datadog/tracing/contrib/active_job/events/discard.rb +4 -4
  260. data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +4 -4
  261. data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +4 -4
  262. data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +4 -4
  263. data/lib/datadog/tracing/contrib/active_job/events/perform.rb +4 -4
  264. data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +4 -4
  265. data/lib/datadog/tracing/contrib/active_job/events.rb +6 -6
  266. data/lib/datadog/tracing/contrib/active_job/integration.rb +4 -4
  267. data/lib/datadog/tracing/contrib/active_job/log_injection.rb +0 -2
  268. data/lib/datadog/tracing/contrib/active_job/patcher.rb +4 -4
  269. data/lib/datadog/tracing/contrib/active_model_serializers/configuration/settings.rb +2 -2
  270. data/lib/datadog/tracing/contrib/active_model_serializers/event.rb +4 -5
  271. data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +3 -3
  272. data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +2 -2
  273. data/lib/datadog/tracing/contrib/active_model_serializers/events.rb +2 -2
  274. data/lib/datadog/tracing/contrib/active_model_serializers/integration.rb +3 -3
  275. data/lib/datadog/tracing/contrib/active_model_serializers/patcher.rb +3 -4
  276. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +2 -2
  277. data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +3 -3
  278. data/lib/datadog/tracing/contrib/active_record/event.rb +1 -1
  279. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +4 -4
  280. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +6 -6
  281. data/lib/datadog/tracing/contrib/active_record/events.rb +2 -2
  282. data/lib/datadog/tracing/contrib/active_record/integration.rb +6 -6
  283. data/lib/datadog/tracing/contrib/active_record/patcher.rb +2 -2
  284. data/lib/datadog/tracing/contrib/active_record/utils.rb +2 -2
  285. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +19 -9
  286. data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +2 -2
  287. data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +1 -1
  288. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +2 -2
  289. data/lib/datadog/tracing/contrib/active_support/integration.rb +5 -5
  290. data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +1 -1
  291. data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +1 -1
  292. data/lib/datadog/tracing/contrib/active_support/patcher.rb +2 -2
  293. data/lib/datadog/tracing/contrib/analytics.rb +1 -1
  294. data/lib/datadog/tracing/contrib/auto_instrument.rb +4 -4
  295. data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +6 -3
  296. data/lib/datadog/tracing/contrib/aws/ext.rb +1 -0
  297. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +5 -4
  298. data/lib/datadog/tracing/contrib/aws/integration.rb +3 -3
  299. data/lib/datadog/tracing/contrib/aws/patcher.rb +5 -5
  300. data/lib/datadog/tracing/contrib/aws/services.rb +0 -2
  301. data/lib/datadog/tracing/contrib/concurrent_ruby/configuration/settings.rb +2 -2
  302. data/lib/datadog/tracing/contrib/concurrent_ruby/future_patch.rb +1 -1
  303. data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +3 -3
  304. data/lib/datadog/tracing/contrib/concurrent_ruby/patcher.rb +2 -2
  305. data/lib/datadog/tracing/contrib/configurable.rb +2 -2
  306. data/lib/datadog/tracing/contrib/configuration/resolvers/pattern_resolver.rb +1 -1
  307. data/lib/datadog/tracing/contrib/configuration/settings.rb +2 -2
  308. data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +6 -3
  309. data/lib/datadog/tracing/contrib/dalli/ext.rb +2 -0
  310. data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +8 -5
  311. data/lib/datadog/tracing/contrib/dalli/integration.rb +3 -3
  312. data/lib/datadog/tracing/contrib/dalli/patcher.rb +3 -3
  313. data/lib/datadog/tracing/contrib/dalli/quantize.rb +1 -1
  314. data/lib/datadog/tracing/contrib/delayed_job/configuration/settings.rb +3 -3
  315. data/lib/datadog/tracing/contrib/delayed_job/ext.rb +2 -0
  316. data/lib/datadog/tracing/contrib/delayed_job/integration.rb +3 -3
  317. data/lib/datadog/tracing/contrib/delayed_job/patcher.rb +8 -2
  318. data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +7 -4
  319. data/lib/datadog/tracing/contrib/delayed_job/server_internal_tracer/worker.rb +32 -0
  320. data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +7 -3
  321. data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +3 -0
  322. data/lib/datadog/tracing/contrib/elasticsearch/integration.rb +3 -3
  323. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +9 -7
  324. data/lib/datadog/tracing/contrib/elasticsearch/quantize.rb +1 -1
  325. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +8 -3
  326. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +6 -7
  327. data/lib/datadog/tracing/contrib/ethon/ext.rb +1 -0
  328. data/lib/datadog/tracing/contrib/ethon/integration.rb +4 -4
  329. data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +5 -4
  330. data/lib/datadog/tracing/contrib/ethon/patcher.rb +3 -3
  331. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +7 -3
  332. data/lib/datadog/tracing/contrib/excon/ext.rb +1 -0
  333. data/lib/datadog/tracing/contrib/excon/integration.rb +4 -4
  334. data/lib/datadog/tracing/contrib/excon/middleware.rb +8 -7
  335. data/lib/datadog/tracing/contrib/excon/patcher.rb +2 -2
  336. data/lib/datadog/tracing/contrib/ext.rb +25 -0
  337. data/lib/datadog/tracing/contrib/extensions.rb +5 -3
  338. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +7 -3
  339. data/lib/datadog/tracing/contrib/faraday/ext.rb +1 -0
  340. data/lib/datadog/tracing/contrib/faraday/integration.rb +4 -4
  341. data/lib/datadog/tracing/contrib/faraday/middleware.rb +8 -8
  342. data/lib/datadog/tracing/contrib/faraday/patcher.rb +5 -5
  343. data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +3 -3
  344. data/lib/datadog/tracing/contrib/grape/endpoint.rb +4 -7
  345. data/lib/datadog/tracing/contrib/grape/integration.rb +3 -3
  346. data/lib/datadog/tracing/contrib/grape/patcher.rb +4 -4
  347. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +3 -3
  348. data/lib/datadog/tracing/contrib/graphql/integration.rb +3 -3
  349. data/lib/datadog/tracing/contrib/graphql/patcher.rb +2 -3
  350. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +10 -4
  351. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +20 -5
  352. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +17 -17
  353. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor.rb +7 -4
  354. data/lib/datadog/tracing/contrib/grpc/distributed/fetcher.rb +27 -0
  355. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +43 -0
  356. data/lib/datadog/tracing/contrib/grpc/ext.rb +4 -0
  357. data/lib/datadog/tracing/contrib/grpc/integration.rb +3 -3
  358. data/lib/datadog/tracing/contrib/grpc/patcher.rb +3 -5
  359. data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +47 -0
  360. data/lib/datadog/tracing/contrib/hanami/configuration/settings.rb +22 -0
  361. data/lib/datadog/tracing/contrib/hanami/ext.rb +24 -0
  362. data/lib/datadog/tracing/contrib/hanami/integration.rb +44 -0
  363. data/lib/datadog/tracing/contrib/hanami/patcher.rb +33 -0
  364. data/lib/datadog/tracing/contrib/hanami/plugin.rb +23 -0
  365. data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +41 -0
  366. data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +44 -0
  367. data/lib/datadog/tracing/contrib/http/circuit_breaker.rb +1 -2
  368. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +13 -3
  369. data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +39 -0
  370. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +38 -0
  371. data/lib/datadog/tracing/contrib/http/ext.rb +2 -0
  372. data/lib/datadog/tracing/contrib/http/instrumentation.rb +8 -10
  373. data/lib/datadog/tracing/contrib/http/integration.rb +6 -6
  374. data/lib/datadog/tracing/contrib/http/patcher.rb +3 -3
  375. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +13 -3
  376. data/lib/datadog/tracing/contrib/httpclient/ext.rb +2 -0
  377. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +9 -9
  378. data/lib/datadog/tracing/contrib/httpclient/integration.rb +4 -4
  379. data/lib/datadog/tracing/contrib/httpclient/patcher.rb +3 -3
  380. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +13 -3
  381. data/lib/datadog/tracing/contrib/httprb/ext.rb +2 -0
  382. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +9 -9
  383. data/lib/datadog/tracing/contrib/httprb/integration.rb +4 -4
  384. data/lib/datadog/tracing/contrib/httprb/patcher.rb +3 -3
  385. data/lib/datadog/tracing/contrib/integration.rb +3 -3
  386. data/lib/datadog/tracing/contrib/kafka/configuration/settings.rb +2 -2
  387. data/lib/datadog/tracing/contrib/kafka/consumer_event.rb +1 -0
  388. data/lib/datadog/tracing/contrib/kafka/event.rb +3 -3
  389. data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +2 -2
  390. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +3 -3
  391. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +3 -3
  392. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +4 -4
  393. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/join_group.rb +4 -4
  394. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/leave_group.rb +4 -4
  395. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/sync_group.rb +4 -4
  396. data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +3 -2
  397. data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +3 -2
  398. data/lib/datadog/tracing/contrib/kafka/events.rb +9 -9
  399. data/lib/datadog/tracing/contrib/kafka/integration.rb +3 -3
  400. data/lib/datadog/tracing/contrib/kafka/patcher.rb +3 -3
  401. data/lib/datadog/tracing/contrib/lograge/configuration/settings.rb +2 -2
  402. data/lib/datadog/tracing/contrib/lograge/instrumentation.rb +1 -2
  403. data/lib/datadog/tracing/contrib/lograge/integration.rb +3 -3
  404. data/lib/datadog/tracing/contrib/lograge/patcher.rb +2 -2
  405. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +7 -3
  406. data/lib/datadog/tracing/contrib/mongodb/ext.rb +8 -0
  407. data/lib/datadog/tracing/contrib/mongodb/instrumentation.rb +3 -3
  408. data/lib/datadog/tracing/contrib/mongodb/integration.rb +4 -4
  409. data/lib/datadog/tracing/contrib/mongodb/parsers.rb +1 -1
  410. data/lib/datadog/tracing/contrib/mongodb/patcher.rb +3 -3
  411. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +10 -4
  412. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +18 -3
  413. data/lib/datadog/tracing/contrib/mysql2/ext.rb +2 -0
  414. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +20 -5
  415. data/lib/datadog/tracing/contrib/mysql2/integration.rb +3 -3
  416. data/lib/datadog/tracing/contrib/mysql2/patcher.rb +2 -2
  417. data/lib/datadog/tracing/contrib/patcher.rb +16 -4
  418. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +50 -0
  419. data/lib/datadog/tracing/contrib/pg/ext.rb +33 -0
  420. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +168 -0
  421. data/lib/datadog/tracing/contrib/pg/integration.rb +43 -0
  422. data/lib/datadog/tracing/contrib/pg/patcher.rb +31 -0
  423. data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +6 -3
  424. data/lib/datadog/tracing/contrib/presto/ext.rb +1 -0
  425. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +2 -3
  426. data/lib/datadog/tracing/contrib/presto/integration.rb +3 -3
  427. data/lib/datadog/tracing/contrib/presto/patcher.rb +4 -4
  428. data/lib/datadog/tracing/contrib/propagation/sql_comment/comment.rb +43 -0
  429. data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +33 -0
  430. data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +28 -0
  431. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +47 -0
  432. data/lib/datadog/tracing/contrib/qless/configuration/settings.rb +2 -2
  433. data/lib/datadog/tracing/contrib/qless/integration.rb +3 -3
  434. data/lib/datadog/tracing/contrib/qless/patcher.rb +1 -2
  435. data/lib/datadog/tracing/contrib/qless/qless_job.rb +2 -3
  436. data/lib/datadog/tracing/contrib/qless/tracer_cleaner.rb +0 -2
  437. data/lib/datadog/tracing/contrib/que/configuration/settings.rb +3 -3
  438. data/lib/datadog/tracing/contrib/que/integration.rb +4 -4
  439. data/lib/datadog/tracing/contrib/que/patcher.rb +1 -1
  440. data/lib/datadog/tracing/contrib/que/tracer.rb +3 -1
  441. data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +2 -2
  442. data/lib/datadog/tracing/contrib/racecar/event.rb +4 -5
  443. data/lib/datadog/tracing/contrib/racecar/events/batch.rb +6 -3
  444. data/lib/datadog/tracing/contrib/racecar/events/consume.rb +2 -2
  445. data/lib/datadog/tracing/contrib/racecar/events/message.rb +6 -3
  446. data/lib/datadog/tracing/contrib/racecar/events.rb +3 -3
  447. data/lib/datadog/tracing/contrib/racecar/integration.rb +3 -3
  448. data/lib/datadog/tracing/contrib/racecar/patcher.rb +3 -3
  449. data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +2 -2
  450. data/lib/datadog/tracing/contrib/rack/header_collection.rb +35 -0
  451. data/lib/datadog/tracing/contrib/rack/integration.rb +4 -4
  452. data/lib/datadog/tracing/contrib/rack/middlewares.rb +129 -61
  453. data/lib/datadog/tracing/contrib/rack/patcher.rb +12 -2
  454. data/lib/datadog/tracing/contrib/rails/auto_instrument_railtie.rb +1 -1
  455. data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +4 -1
  456. data/lib/datadog/tracing/contrib/rails/framework.rb +18 -22
  457. data/lib/datadog/tracing/contrib/rails/integration.rb +4 -4
  458. data/lib/datadog/tracing/contrib/rails/log_injection.rb +0 -2
  459. data/lib/datadog/tracing/contrib/rails/middlewares.rb +1 -2
  460. data/lib/datadog/tracing/contrib/rails/patcher.rb +7 -8
  461. data/lib/datadog/tracing/contrib/rails/railtie.rb +3 -3
  462. data/lib/datadog/tracing/contrib/rails/utils.rb +1 -1
  463. data/lib/datadog/tracing/contrib/rake/configuration/settings.rb +17 -2
  464. data/lib/datadog/tracing/contrib/rake/instrumentation.rb +12 -7
  465. data/lib/datadog/tracing/contrib/rake/integration.rb +3 -3
  466. data/lib/datadog/tracing/contrib/rake/patcher.rb +3 -4
  467. data/lib/datadog/tracing/contrib/redis/configuration/resolver.rb +1 -1
  468. data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +6 -3
  469. data/lib/datadog/tracing/contrib/redis/ext.rb +3 -0
  470. data/lib/datadog/tracing/contrib/redis/instrumentation.rb +36 -26
  471. data/lib/datadog/tracing/contrib/redis/integration.rb +37 -4
  472. data/lib/datadog/tracing/contrib/redis/patcher.rb +57 -13
  473. data/lib/datadog/tracing/contrib/redis/quantize.rb +12 -9
  474. data/lib/datadog/tracing/contrib/redis/tags.rb +12 -10
  475. data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +72 -0
  476. data/lib/datadog/tracing/contrib/resque/configuration/settings.rb +3 -3
  477. data/lib/datadog/tracing/contrib/resque/integration.rb +3 -3
  478. data/lib/datadog/tracing/contrib/resque/patcher.rb +2 -2
  479. data/lib/datadog/tracing/contrib/resque/resque_job.rb +5 -4
  480. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +9 -3
  481. data/lib/datadog/tracing/contrib/rest_client/ext.rb +1 -0
  482. data/lib/datadog/tracing/contrib/rest_client/integration.rb +3 -3
  483. data/lib/datadog/tracing/contrib/rest_client/patcher.rb +2 -2
  484. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +7 -6
  485. data/lib/datadog/tracing/contrib/semantic_logger/configuration/settings.rb +2 -2
  486. data/lib/datadog/tracing/contrib/semantic_logger/instrumentation.rb +1 -2
  487. data/lib/datadog/tracing/contrib/semantic_logger/integration.rb +3 -3
  488. data/lib/datadog/tracing/contrib/semantic_logger/patcher.rb +2 -2
  489. data/lib/datadog/tracing/contrib/sequel/configuration/settings.rb +2 -2
  490. data/lib/datadog/tracing/contrib/sequel/database.rb +4 -5
  491. data/lib/datadog/tracing/contrib/sequel/dataset.rb +4 -5
  492. data/lib/datadog/tracing/contrib/sequel/integration.rb +3 -3
  493. data/lib/datadog/tracing/contrib/sequel/patcher.rb +3 -3
  494. data/lib/datadog/tracing/contrib/sequel/utils.rb +2 -2
  495. data/lib/datadog/tracing/contrib/shoryuken/configuration/settings.rb +3 -3
  496. data/lib/datadog/tracing/contrib/shoryuken/integration.rb +4 -4
  497. data/lib/datadog/tracing/contrib/shoryuken/patcher.rb +1 -1
  498. data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +3 -1
  499. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +9 -5
  500. data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +3 -3
  501. data/lib/datadog/tracing/contrib/sidekiq/ext.rb +6 -0
  502. data/lib/datadog/tracing/contrib/sidekiq/integration.rb +3 -3
  503. data/lib/datadog/tracing/contrib/sidekiq/patcher.rb +14 -7
  504. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/heartbeat.rb +19 -1
  505. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/{scheduled_push.rb → redis_info.rb} +5 -6
  506. data/lib/datadog/tracing/contrib/sidekiq/server_internal_tracer/scheduled_poller.rb +53 -0
  507. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +10 -6
  508. data/lib/datadog/tracing/contrib/sidekiq/tracing.rb +2 -2
  509. data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +2 -2
  510. data/lib/datadog/tracing/contrib/sinatra/env.rb +14 -25
  511. data/lib/datadog/tracing/contrib/sinatra/ext.rb +7 -3
  512. data/lib/datadog/tracing/contrib/sinatra/framework.rb +0 -2
  513. data/lib/datadog/tracing/contrib/sinatra/headers.rb +1 -1
  514. data/lib/datadog/tracing/contrib/sinatra/integration.rb +3 -3
  515. data/lib/datadog/tracing/contrib/sinatra/patcher.rb +7 -7
  516. data/lib/datadog/tracing/contrib/sinatra/tracer.rb +15 -88
  517. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +20 -16
  518. data/lib/datadog/tracing/contrib/sneakers/configuration/settings.rb +2 -2
  519. data/lib/datadog/tracing/contrib/sneakers/integration.rb +4 -4
  520. data/lib/datadog/tracing/contrib/sneakers/patcher.rb +2 -2
  521. data/lib/datadog/tracing/contrib/sneakers/tracer.rb +4 -3
  522. data/lib/datadog/tracing/contrib/status_code_matcher.rb +2 -2
  523. data/lib/datadog/tracing/contrib/stripe/configuration/settings.rb +33 -0
  524. data/lib/datadog/tracing/contrib/stripe/ext.rb +26 -0
  525. data/lib/datadog/tracing/contrib/stripe/integration.rb +43 -0
  526. data/lib/datadog/tracing/contrib/stripe/patcher.rb +29 -0
  527. data/lib/datadog/tracing/contrib/stripe/request.rb +67 -0
  528. data/lib/datadog/tracing/contrib/sucker_punch/configuration/settings.rb +2 -2
  529. data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +3 -4
  530. data/lib/datadog/tracing/contrib/sucker_punch/integration.rb +3 -3
  531. data/lib/datadog/tracing/contrib/sucker_punch/patcher.rb +4 -5
  532. data/lib/datadog/tracing/contrib/utils/quantization/http.rb +92 -10
  533. data/lib/datadog/tracing/contrib.rb +50 -47
  534. data/lib/datadog/tracing/correlation.rb +1 -1
  535. data/lib/datadog/{core → tracing}/diagnostics/ext.rb +1 -6
  536. data/lib/datadog/tracing/diagnostics/health.rb +40 -0
  537. data/lib/datadog/tracing/distributed/b3_multi.rb +66 -0
  538. data/lib/datadog/tracing/distributed/b3_single.rb +66 -0
  539. data/lib/datadog/tracing/distributed/datadog.rb +153 -0
  540. data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +85 -0
  541. data/lib/datadog/tracing/distributed/fetcher.rb +30 -0
  542. data/lib/datadog/tracing/distributed/headers/ext.rb +19 -15
  543. data/lib/datadog/tracing/distributed/helpers.rb +40 -4
  544. data/lib/datadog/tracing/distributed/none.rb +19 -0
  545. data/lib/datadog/tracing/distributed/propagation.rb +127 -0
  546. data/lib/datadog/tracing/distributed/trace_context.rb +378 -0
  547. data/lib/datadog/tracing/event.rb +1 -1
  548. data/lib/datadog/tracing/flush.rb +57 -35
  549. data/lib/datadog/tracing/metadata/analytics.rb +2 -2
  550. data/lib/datadog/tracing/metadata/errors.rb +2 -2
  551. data/lib/datadog/tracing/metadata/ext.rb +28 -1
  552. data/lib/datadog/tracing/metadata/tagging.rb +23 -2
  553. data/lib/datadog/tracing/metadata.rb +3 -3
  554. data/lib/datadog/tracing/pipeline/span_filter.rb +10 -6
  555. data/lib/datadog/tracing/pipeline.rb +3 -3
  556. data/lib/datadog/tracing/propagation/http.rb +3 -98
  557. data/lib/datadog/tracing/runtime/metrics.rb +1 -1
  558. data/lib/datadog/tracing/sampling/all_sampler.rb +1 -1
  559. data/lib/datadog/tracing/sampling/ext.rb +31 -0
  560. data/lib/datadog/tracing/sampling/priority_sampler.rb +62 -9
  561. data/lib/datadog/tracing/sampling/rate_by_key_sampler.rb +10 -11
  562. data/lib/datadog/tracing/sampling/rate_by_service_sampler.rb +32 -8
  563. data/lib/datadog/tracing/sampling/rate_limiter.rb +4 -1
  564. data/lib/datadog/tracing/sampling/rate_sampler.rb +27 -10
  565. data/lib/datadog/tracing/sampling/rule.rb +3 -3
  566. data/lib/datadog/tracing/sampling/rule_sampler.rb +8 -7
  567. data/lib/datadog/tracing/sampling/span/ext.rb +25 -0
  568. data/lib/datadog/tracing/sampling/span/matcher.rb +89 -0
  569. data/lib/datadog/tracing/sampling/span/rule.rb +82 -0
  570. data/lib/datadog/tracing/sampling/span/rule_parser.rb +104 -0
  571. data/lib/datadog/tracing/sampling/span/sampler.rb +75 -0
  572. data/lib/datadog/tracing/span.rb +24 -20
  573. data/lib/datadog/tracing/span_operation.rb +13 -13
  574. data/lib/datadog/tracing/sync_writer.rb +5 -5
  575. data/lib/datadog/tracing/trace_digest.rb +88 -2
  576. data/lib/datadog/tracing/trace_operation.rb +60 -15
  577. data/lib/datadog/tracing/trace_segment.rb +13 -8
  578. data/lib/datadog/tracing/tracer.rb +49 -21
  579. data/lib/datadog/tracing/utils.rb +50 -0
  580. data/lib/datadog/tracing/workers/trace_writer.rb +9 -9
  581. data/lib/datadog/tracing/workers.rb +3 -3
  582. data/lib/datadog/tracing/writer.rb +12 -5
  583. data/lib/datadog/tracing.rb +8 -8
  584. data/lib/ddtrace/auto_instrument.rb +9 -2
  585. data/lib/ddtrace/transport/ext.rb +7 -1
  586. data/lib/ddtrace/transport/http/adapters/net.rb +3 -2
  587. data/lib/ddtrace/transport/http/adapters/test.rb +1 -1
  588. data/lib/ddtrace/transport/http/adapters/unix_socket.rb +2 -2
  589. data/lib/ddtrace/transport/http/api/map.rb +1 -1
  590. data/lib/ddtrace/transport/http/api.rb +4 -4
  591. data/lib/ddtrace/transport/http/builder.rb +5 -5
  592. data/lib/ddtrace/transport/http/client.rb +2 -2
  593. data/lib/ddtrace/transport/http/response.rb +1 -1
  594. data/lib/ddtrace/transport/http/statistics.rb +1 -1
  595. data/lib/ddtrace/transport/http/traces.rb +5 -5
  596. data/lib/ddtrace/transport/http.rb +12 -9
  597. data/lib/ddtrace/transport/io/client.rb +2 -2
  598. data/lib/ddtrace/transport/io/response.rb +1 -1
  599. data/lib/ddtrace/transport/io/traces.rb +3 -3
  600. data/lib/ddtrace/transport/io.rb +3 -3
  601. data/lib/ddtrace/transport/statistics.rb +2 -2
  602. data/lib/ddtrace/transport/trace_formatter.rb +14 -10
  603. data/lib/ddtrace/transport/traces.rb +8 -6
  604. data/lib/ddtrace/version.rb +1 -1
  605. data/lib/ddtrace.rb +6 -6
  606. metadata +127 -48
  607. data/.editorconfig +0 -22
  608. data/.gitignore +0 -58
  609. data/CONTRIBUTING.md +0 -81
  610. data/ddtrace.gemspec +0 -68
  611. data/docs/0.x-trace.png +0 -0
  612. data/docs/1.0-trace.png +0 -0
  613. data/docs/AutoInstrumentation.md +0 -36
  614. data/docs/Deprecation.md +0 -8
  615. data/docs/DevelopmentGuide.md +0 -259
  616. data/docs/GettingStarted.md +0 -2688
  617. data/docs/ProfilingDevelopment.md +0 -110
  618. data/docs/PublicApi.md +0 -14
  619. data/docs/UpgradeGuide.md +0 -736
  620. data/ext/ddtrace_profiling_native_extension/libddprof_helpers.h +0 -13
  621. data/lib/datadog/profiling/recorder.rb +0 -117
  622. data/lib/datadog/profiling/transport/client.rb +0 -16
  623. data/lib/datadog/profiling/transport/http/api/endpoint.rb +0 -107
  624. data/lib/datadog/profiling/transport/http/api/instance.rb +0 -38
  625. data/lib/datadog/profiling/transport/http/api/spec.rb +0 -42
  626. data/lib/datadog/profiling/transport/http/api.rb +0 -45
  627. data/lib/datadog/profiling/transport/http/builder.rb +0 -30
  628. data/lib/datadog/profiling/transport/http/client.rb +0 -35
  629. data/lib/datadog/profiling/transport/http/response.rb +0 -23
  630. data/lib/datadog/profiling/transport/http.rb +0 -112
  631. data/lib/datadog/profiling/transport/io/client.rb +0 -29
  632. data/lib/datadog/profiling/transport/io/response.rb +0 -18
  633. data/lib/datadog/profiling/transport/io.rb +0 -32
  634. data/lib/datadog/profiling/transport/parcel.rb +0 -19
  635. data/lib/datadog/profiling/transport/request.rb +0 -17
  636. data/lib/datadog/profiling/transport/response.rb +0 -10
  637. data/lib/datadog/tracing/distributed/headers/b3.rb +0 -55
  638. data/lib/datadog/tracing/distributed/headers/b3_single.rb +0 -67
  639. data/lib/datadog/tracing/distributed/headers/datadog.rb +0 -52
  640. data/lib/datadog/tracing/distributed/parser.rb +0 -70
  641. data/lib/datadog/tracing/propagation/grpc.rb +0 -88
@@ -1,11 +1,130 @@
1
1
  #include <ruby.h>
2
2
  #include <ruby/thread.h>
3
+ #include <pthread.h>
4
+ #include <errno.h>
5
+ #include "helpers.h"
3
6
  #include "stack_recorder.h"
4
- #include "libddprof_helpers.h"
7
+ #include "libdatadog_helpers.h"
8
+ #include "ruby_helpers.h"
5
9
 
6
- // Used to wrap a ddprof_ffi_Profile in a Ruby object and expose Ruby-level serialization APIs
10
+ // Used to wrap a ddog_prof_Profile in a Ruby object and expose Ruby-level serialization APIs
7
11
  // This file implements the native bits of the Datadog::Profiling::StackRecorder class
8
12
 
13
+ // ---
14
+ // ## Synchronization mechanism for safe parallel access design notes
15
+ //
16
+ // The state of the StackRecorder is managed using a set of locks to avoid concurrency issues.
17
+ //
18
+ // This is needed because the state is expected to be accessed, in parallel, by two different threads.
19
+ //
20
+ // 1. The thread that is taking a stack sample and that called `record_sample`, let's call it the **sampler thread**.
21
+ // In the current implementation of the profiler, there can only exist one **sampler thread** at a time; if this
22
+ // constraint changes, we should revise the design of the StackRecorder.
23
+ //
24
+ // 2. The thread that serializes and reports profiles, let's call it the **serializer thread**. We enforce that there
25
+ // cannot be more than one thread attempting to serialize profiles at a time.
26
+ //
27
+ // If both the sampler and serializer threads are trying to access the same `ddog_prof_Profile` in parallel, we will
28
+ // have a concurrency issue. Thus, the StackRecorder has an added mechanism to avoid this.
29
+ //
30
+ // As an additional constraint, the **sampler thread** has absolute priority and must never block while
31
+ // recording a sample.
32
+ //
33
+ // ### The solution: Keep two profiles at the same time
34
+ //
35
+ // To solve for the constraints above, the StackRecorder keeps two `ddog_prof_Profile` profile instances inside itself.
36
+ // They are called the `slot_one_profile` and `slot_two_profile`.
37
+ //
38
+ // Each profile is paired with its own mutex. `slot_one_profile` is protected by `slot_one_mutex` and `slot_two_profile`
39
+ // is protected by `slot_two_mutex`.
40
+ //
41
+ // We additionally introduce the concept of **active** and **inactive** profile slots. At any point, the sampler thread
42
+ // can probe the mutexes to discover which of the profiles corresponds to the active slot, and then records samples in it.
43
+ // When the serializer thread is ready to serialize data, it flips the active and inactive slots; it reports the data
44
+ // on the previously-active profile slot, and the sampler thread can continue to record in the previously-inactive
45
+ // profile slot.
46
+ //
47
+ // Thus, the sampler and serializer threads never cross paths, avoiding concurrency issues. The sampler thread writes to
48
+ // the active profile slot, and the serializer thread reads from the inactive profile slot.
49
+ //
50
+ // ### Locking protocol, high-level
51
+ //
52
+ // The active profile slot is the slot for which its corresponding mutex **is unlocked**. That is, if the sampler
53
+ // thread can grab a lock for a profile slot, then that slot is the active one. (Here you see where the constraint
54
+ // stated above that only one sampler thread can exist kicks in -- this part would need to be more complex if multiple
55
+ // sampler threads were in play.)
56
+ //
57
+ // As a counterpart, the inactive profile slot mutex is **kept locked** until such time the serializer
58
+ // thread is ready to work and decides to flip the slots.
59
+ //
60
+ // When a new StackRecorder is initialized, the `slot_one_mutex` is unlocked, and the `slot_two_mutex` is kept locked,
61
+ // that is, a new instance always starts with slot one active.
62
+ //
63
+ // Additionally, an `active_slot` field is kept, containing a `1` or `2`; this is only kept for the serializer thread
64
+ // to use as a simplification, as well as for testing and debugging; the **sampler thread must never use the `active_slot`
65
+ // field**.
66
+ //
67
+ // ### Locking protocol, from the sampler thread side
68
+ //
69
+ // When the sampler thread wants to record a sample, it goes through the following steps to discover which is the
70
+ // active profile slot:
71
+ //
72
+ // 1. `pthread_mutex_trylock(slot_one_mutex)`. If it succeeds to grab the lock, this means the active profile slot is
73
+ // slot one. If it fails, we move to the next step.
74
+ //
75
+ // 2. `pthread_mutex_trylock(slot_two_mutex)`. If it succeeds to grab the lock, this means the active profile slot is
76
+ // slot two. If it fails, we move to the next step.
77
+ //
78
+ // 3. What does it mean for the sampler thread to have observed both `slot_one_mutex` as well as `slot_two_mutex` as
79
+ // being locked? There are two options:
80
+ // a. The sampler thread got really unlucky. When it tried to grab the `slot_one_mutex`, the active profile slot was
81
+ // the second one BUT then the serializer thread flipped the slots, and by the time the sampler thread probed the
82
+ // `slot_two_mutex`, that one was taken. Since the serializer thread is expected only to work once a minute,
83
+ // we retry steps 1. and 2. and should be able to find an active slot.
84
+ // b. Something is incorrect in the StackRecorder state. In this situation, the sampler thread should give up on
85
+ // sampling and enter an error state.
86
+ //
87
+ // Note that in the steps above, and because the sampler thread uses `trylock` to probe the mutexes, that the
88
+ // sampler thread never blocks. It either is able to find an active profile slot in a bounded amount of steps or it
89
+ // enters an error state.
90
+ //
91
+ // This guarantees that sampler performance is never constrained by serializer performance.
92
+ //
93
+ // ### Locking protocol, from the serializer thread side
94
+ //
95
+ // When the serializer thread wants to serialize a profile, it first flips the active and inactive profile slots.
96
+ //
97
+ // The flipping action is described below. Consider previously-inactive and previously-active as the state of the slots
98
+ // before the flipping happens.
99
+ //
100
+ // The flipping steps are the following:
101
+ //
102
+ // 1. Release the mutex for the previously-inactive profile slot. That slot, as seen by the sampler thread, is now
103
+ // active.
104
+ //
105
+ // 2. Grab the mutex for the previously-active profile slot. Note that this can lead to the serializer thread blocking,
106
+ // if the sampler thread is holding this mutex. After the mutex is grabbed, the previously-active slot becomes inactive,
107
+ // as seen by the sampler thread.
108
+ //
109
+ // 3. Update `active_slot`.
110
+ //
111
+ // After flipping the profile slots, the serializer thread is now free to serialize the inactive profile slot. The slot
112
+ // is kept inactive until the next time the serializer thread wants to serialize data.
113
+ //
114
+ // Note there can be a brief period between steps 1 and 2 where the serializer thread holds no lock, which means that
115
+ // the sampler thread can pick either slot. This is OK: if the sampler thread picks the previously-inactive slot, the
116
+ // samples will be reported on the next serialization; if the sampler thread picks the previously-active slot, the
117
+ // samples are still included in the current serialization. Either option is correct.
118
+ //
119
+ // ### Additional notes
120
+ //
121
+ // Q: Can the sampler thread and the serializer thread ever be the same thread? (E.g. sampling in interrupt handler)
122
+ // A: No; the current profiler design requires that sampling happens only on the thread that is holding the Global VM
123
+ // Lock (GVL). The serializer thread flipping occurs after the serializer thread releases the GVL, and thus the
124
+ // serializer thread will not be able to host the sampling process.
125
+ //
126
+ // ---
127
+
9
128
  static VALUE ok_symbol = Qnil; // :ok in Ruby
10
129
  static VALUE error_symbol = Qnil; // :error in Ruby
11
130
 
@@ -13,39 +132,82 @@ static ID ruby_time_from_id; // id of :ruby_time_from in Ruby
13
132
 
14
133
  static VALUE stack_recorder_class = Qnil;
15
134
 
135
+ // Contains native state for each instance
136
+ struct stack_recorder_state {
137
+ pthread_mutex_t slot_one_mutex;
138
+ ddog_prof_Profile *slot_one_profile;
139
+
140
+ pthread_mutex_t slot_two_mutex;
141
+ ddog_prof_Profile *slot_two_profile;
142
+
143
+ short active_slot; // MUST NEVER BE ACCESSED FROM record_sample; this is NOT for the sampler thread to use.
144
+ };
145
+
146
+ // Used to return a pair of values from sampler_lock_active_profile()
147
+ struct active_slot_pair {
148
+ pthread_mutex_t *mutex;
149
+ ddog_prof_Profile *profile;
150
+ };
151
+
16
152
  struct call_serialize_without_gvl_arguments {
17
- ddprof_ffi_Profile *profile;
18
- ddprof_ffi_SerializeResult result;
153
+ // Set by caller
154
+ struct stack_recorder_state *state;
155
+ ddog_Timespec finish_timestamp;
156
+
157
+ // Set by callee
158
+ ddog_prof_Profile *profile;
159
+ ddog_prof_Profile_SerializeResult result;
160
+
161
+ // Set by both
19
162
  bool serialize_ran;
20
163
  };
21
164
 
22
165
  static VALUE _native_new(VALUE klass);
166
+ static void initialize_slot_concurrency_control(struct stack_recorder_state *state);
23
167
  static void stack_recorder_typed_data_free(void *data);
24
168
  static VALUE _native_serialize(VALUE self, VALUE recorder_instance);
25
- static VALUE ruby_time_from(ddprof_ffi_Timespec ddprof_time);
169
+ static VALUE ruby_time_from(ddog_Timespec ddprof_time);
26
170
  static void *call_serialize_without_gvl(void *call_args);
171
+ static struct active_slot_pair sampler_lock_active_profile();
172
+ static void sampler_unlock_active_profile(struct active_slot_pair active_slot);
173
+ static ddog_prof_Profile *serializer_flip_active_and_inactive_slots(struct stack_recorder_state *state);
174
+ static VALUE _native_active_slot(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
175
+ static VALUE _native_is_slot_one_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
176
+ static VALUE _native_is_slot_two_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance);
177
+ static VALUE test_slot_mutex_state(VALUE recorder_instance, int slot);
178
+ static ddog_Timespec time_now(void);
179
+ static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE recorder_instance);
180
+ static void serializer_set_start_timestamp_for_next_profile(struct stack_recorder_state *state, ddog_Timespec timestamp);
181
+ static VALUE _native_record_endpoint(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE local_root_span_id, VALUE endpoint);
27
182
 
28
183
  void stack_recorder_init(VALUE profiling_module) {
29
184
  stack_recorder_class = rb_define_class_under(profiling_module, "StackRecorder", rb_cObject);
185
+ // Hosts methods used for testing the native code using RSpec
186
+ VALUE testing_module = rb_define_module_under(stack_recorder_class, "Testing");
30
187
 
31
- // Instances of the StackRecorder class are going to be "TypedData" objects.
188
+ // Instances of the StackRecorder class are "TypedData" objects.
32
189
  // "TypedData" objects are special objects in the Ruby VM that can wrap C structs.
33
- // In our case, we're going to keep a libddprof profile reference inside our object.
190
+ // In this case, it wraps the stack_recorder_state.
34
191
  //
35
- // Because Ruby doesn't know how to initialize libddprof profiles, we MUST override the allocation function for objects
192
+ // Because Ruby doesn't know how to initialize native-level structs, we MUST override the allocation function for objects
36
193
  // of this class so that we can manage this part. Not overriding or disabling the allocation function is a common
37
194
  // gotcha for "TypedData" objects that can very easily lead to VM crashes, see for instance
38
195
  // https://bugs.ruby-lang.org/issues/18007 for a discussion around this.
39
196
  rb_define_alloc_func(stack_recorder_class, _native_new);
40
197
 
41
198
  rb_define_singleton_method(stack_recorder_class, "_native_serialize", _native_serialize, 1);
199
+ rb_define_singleton_method(stack_recorder_class, "_native_reset_after_fork", _native_reset_after_fork, 1);
200
+ rb_define_singleton_method(testing_module, "_native_active_slot", _native_active_slot, 1);
201
+ rb_define_singleton_method(testing_module, "_native_slot_one_mutex_locked?", _native_is_slot_one_mutex_locked, 1);
202
+ rb_define_singleton_method(testing_module, "_native_slot_two_mutex_locked?", _native_is_slot_two_mutex_locked, 1);
203
+ rb_define_singleton_method(testing_module, "_native_record_endpoint", _native_record_endpoint, 3);
42
204
 
43
205
  ok_symbol = ID2SYM(rb_intern_const("ok"));
44
206
  error_symbol = ID2SYM(rb_intern_const("error"));
45
207
  ruby_time_from_id = rb_intern_const("ruby_time_from");
46
208
  }
47
209
 
48
- // This structure is used to define a Ruby object that stores a pointer to a ddprof_ffi_Profile instance
210
+ // This structure is used to define a Ruby object that stores a pointer to a ddog_prof_Profile instance
49
211
  // See also https://github.com/ruby/ruby/blob/master/doc/extension.rdoc for how this works
50
212
  static const rb_data_type_t stack_recorder_typed_data = {
51
213
  .wrap_struct_name = "Datadog::Profiling::StackRecorder",
@@ -58,61 +220,95 @@ static const rb_data_type_t stack_recorder_typed_data = {
58
220
  };
59
221
 
60
222
  static VALUE _native_new(VALUE klass) {
61
- ddprof_ffi_Slice_value_type sample_types = {.ptr = enabled_value_types, .len = ENABLED_VALUE_TYPES_COUNT};
223
+ struct stack_recorder_state *state = ruby_xcalloc(1, sizeof(struct stack_recorder_state));
62
224
 
63
- ddprof_ffi_Profile *profile = ddprof_ffi_Profile_new(sample_types, NULL /* Period is optional */);
225
+ ddog_prof_Slice_ValueType sample_types = {.ptr = enabled_value_types, .len = ENABLED_VALUE_TYPES_COUNT};
64
226
 
65
- return TypedData_Wrap_Struct(klass, &stack_recorder_typed_data, profile);
227
+ initialize_slot_concurrency_control(state);
228
+
229
+ // Note: Don't raise exceptions after this point, since it'll lead to libdatadog memory leaking!
230
+
231
+ state->slot_one_profile = ddog_prof_Profile_new(sample_types, NULL /* period is optional */, NULL /* start_time is optional */);
232
+ state->slot_two_profile = ddog_prof_Profile_new(sample_types, NULL /* period is optional */, NULL /* start_time is optional */);
233
+
234
+ return TypedData_Wrap_Struct(klass, &stack_recorder_typed_data, state);
66
235
  }
67
236
 
68
- static void stack_recorder_typed_data_free(void *data) {
69
- ddprof_ffi_Profile_free((ddprof_ffi_Profile *) data);
237
+ static void initialize_slot_concurrency_control(struct stack_recorder_state *state) {
238
+ state->slot_one_mutex = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
239
+ state->slot_two_mutex = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER;
240
+
241
+ // A newly-created StackRecorder starts with slot one being active for samples, so let's lock slot two
242
+ ENFORCE_SUCCESS_GVL(pthread_mutex_lock(&state->slot_two_mutex));
243
+
244
+ state->active_slot = 1;
70
245
  }
71
246
 
72
- static VALUE _native_serialize(VALUE self, VALUE recorder_instance) {
73
- ddprof_ffi_Profile *profile;
74
- TypedData_Get_Struct(recorder_instance, ddprof_ffi_Profile, &stack_recorder_typed_data, profile);
247
+ static void stack_recorder_typed_data_free(void *state_ptr) {
248
+ struct stack_recorder_state *state = (struct stack_recorder_state *) state_ptr;
75
249
 
76
- // We'll release the Global VM Lock while we're calling serialize, so that the Ruby VM can continue to work while this
77
- // is pending
78
- struct call_serialize_without_gvl_arguments args = {.profile = profile, .serialize_ran = false};
250
+ pthread_mutex_destroy(&state->slot_one_mutex);
251
+ ddog_prof_Profile_drop(state->slot_one_profile);
252
+
253
+ pthread_mutex_destroy(&state->slot_two_mutex);
254
+ ddog_prof_Profile_drop(state->slot_two_profile);
255
+
256
+ ruby_xfree(state);
257
+ }
258
+
259
+ static VALUE _native_serialize(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
260
+ struct stack_recorder_state *state;
261
+ TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
79
262
 
80
- // We use rb_thread_call_without_gvl2 for similar reasons as in http_transport.c: we don't want pending interrupts
81
- // that cause exceptions to be raised to be processed as otherwise we can leak the serialized profile.
82
- rb_thread_call_without_gvl2(call_serialize_without_gvl, &args, /* No interruption supported */ NULL, NULL);
263
+ ddog_Timespec finish_timestamp = time_now();
264
+ // Need to do this while still holding on to the Global VM Lock; see comments on method for why
265
+ serializer_set_start_timestamp_for_next_profile(state, finish_timestamp);
83
266
 
84
- // This weird corner case can happen if rb_thread_call_without_gvl2 returns immediately due to an interrupt
85
- // without ever calling call_serialize_without_gvl. In this situation, we don't have anything to clean up, we can
86
- // just return.
87
- if (!args.serialize_ran) {
88
- return rb_ary_new_from_args(2, error_symbol, rb_str_new_cstr("Interrupted before call_serialize_without_gvl ran"));
267
+ // We'll release the Global VM Lock while we're calling serialize, so that the Ruby VM can continue to work while this
268
+ // is pending
269
+ struct call_serialize_without_gvl_arguments args = {.state = state, .finish_timestamp = finish_timestamp, .serialize_ran = false};
270
+
271
+ while (!args.serialize_ran) {
272
+ // Give the Ruby VM an opportunity to process any pending interruptions (including raising exceptions).
273
+ // Note that it's OK to do this BEFORE call_serialize_without_gvl runs BUT NOT AFTER because afterwards
274
+ // there's heap-allocated memory that MUST be cleaned before raising any exception.
275
+ //
276
+ // Note that we run this in a loop because `rb_thread_call_without_gvl2` may return multiple times due to
277
+ // pending interrupts until it actually runs our code.
278
+ process_pending_interruptions(Qnil);
279
+
280
+ // We use rb_thread_call_without_gvl2 here because unlike the regular _gvl variant, gvl2 does not process
281
+ // interruptions and thus does not raise exceptions after running our code.
282
+ rb_thread_call_without_gvl2(call_serialize_without_gvl, &args, NULL /* No interruption function needed in this case */, NULL /* Not needed */);
89
283
  }
90
284
 
91
- ddprof_ffi_SerializeResult serialized_profile = args.result;
285
+ ddog_prof_Profile_SerializeResult serialized_profile = args.result;
92
286
 
93
- if (serialized_profile.tag == DDPROF_FFI_SERIALIZE_RESULT_ERR) {
94
- VALUE err_details = ruby_string_from_vec_u8(serialized_profile.err);
95
- ddprof_ffi_SerializeResult_drop(serialized_profile);
287
+ if (serialized_profile.tag == DDOG_PROF_PROFILE_SERIALIZE_RESULT_ERR) {
288
+ VALUE err_details = ruby_string_from_prof_vec_u8(serialized_profile.err);
289
+ ddog_prof_Profile_SerializeResult_drop(serialized_profile);
96
290
  return rb_ary_new_from_args(2, error_symbol, err_details);
97
291
  }
98
292
 
99
- VALUE encoded_pprof = ruby_string_from_vec_u8(serialized_profile.ok.buffer);
293
+ VALUE encoded_pprof = ruby_string_from_prof_vec_u8(serialized_profile.ok.buffer);
100
294
 
101
- ddprof_ffi_Timespec ddprof_start = serialized_profile.ok.start;
102
- ddprof_ffi_Timespec ddprof_finish = serialized_profile.ok.end;
295
+ ddog_Timespec ddprof_start = serialized_profile.ok.start;
296
+ ddog_Timespec ddprof_finish = serialized_profile.ok.end;
103
297
 
104
- // Clean up libddprof object to avoid leaking in case ruby_time_from raises an exception
105
- ddprof_ffi_SerializeResult_drop(serialized_profile);
298
+ // Clean up libdatadog object to avoid leaking in case ruby_time_from raises an exception
299
+ ddog_prof_Profile_SerializeResult_drop(serialized_profile);
106
300
 
107
301
  VALUE start = ruby_time_from(ddprof_start);
108
302
  VALUE finish = ruby_time_from(ddprof_finish);
109
303
 
110
- if (!ddprof_ffi_Profile_reset(profile)) return rb_ary_new_from_args(2, error_symbol, rb_str_new_cstr("Failed to reset profile"));
304
+ if (!ddog_prof_Profile_reset(args.profile, NULL /* start_time is optional */ )) {
305
+ return rb_ary_new_from_args(2, error_symbol, rb_str_new_cstr("Failed to reset profile"));
306
+ }
111
307
 
112
308
  return rb_ary_new_from_args(2, ok_symbol, rb_ary_new_from_args(3, start, finish, encoded_pprof));
113
309
  }
114
310
 
115
- static VALUE ruby_time_from(ddprof_ffi_Timespec ddprof_time) {
311
+ static VALUE ruby_time_from(ddog_Timespec ddprof_time) {
116
312
  #ifndef NO_RB_TIME_TIMESPEC_NEW // Modern Rubies
117
313
  const int utc = INT_MAX - 1; // From Ruby sources
118
314
  struct timespec time = {.tv_sec = ddprof_time.seconds, .tv_nsec = ddprof_time.nanoseconds};
@@ -122,18 +318,170 @@ static VALUE ruby_time_from(ddprof_ffi_Timespec ddprof_time) {
122
318
  #endif
123
319
  }
124
320
 
125
- void record_sample(VALUE recorder_instance, ddprof_ffi_Sample sample) {
126
- ddprof_ffi_Profile *profile;
127
- TypedData_Get_Struct(recorder_instance, ddprof_ffi_Profile, &stack_recorder_typed_data, profile);
321
+ void record_sample(VALUE recorder_instance, ddog_prof_Sample sample) {
322
+ struct stack_recorder_state *state;
323
+ TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
324
+
325
+ struct active_slot_pair active_slot = sampler_lock_active_profile(state);
326
+
327
+ ddog_prof_Profile_add(active_slot.profile, sample);
328
+
329
+ sampler_unlock_active_profile(active_slot);
330
+ }
331
+
332
+ void record_endpoint(VALUE recorder_instance, ddog_CharSlice local_root_span_id, ddog_CharSlice endpoint) {
333
+ struct stack_recorder_state *state;
334
+ TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
335
+
336
+ struct active_slot_pair active_slot = sampler_lock_active_profile(state);
337
+
338
+ ddog_prof_Profile_set_endpoint(active_slot.profile, local_root_span_id, endpoint);
128
339
 
129
- ddprof_ffi_Profile_add(profile, sample);
340
+ sampler_unlock_active_profile(active_slot);
130
341
  }
131
342
 
132
343
  static void *call_serialize_without_gvl(void *call_args) {
133
344
  struct call_serialize_without_gvl_arguments *args = (struct call_serialize_without_gvl_arguments *) call_args;
134
345
 
135
- args->result = ddprof_ffi_Profile_serialize(args->profile);
346
+ args->profile = serializer_flip_active_and_inactive_slots(args->state);
347
+ args->result = ddog_prof_Profile_serialize(args->profile, &args->finish_timestamp, NULL /* duration_nanos is optional */);
136
348
  args->serialize_ran = true;
137
349
 
138
350
  return NULL; // Unused
139
351
  }
352
+
353
+ VALUE enforce_recorder_instance(VALUE object) {
354
+ Check_TypedStruct(object, &stack_recorder_typed_data);
355
+ return object;
356
+ }
357
+
358
+ static struct active_slot_pair sampler_lock_active_profile(struct stack_recorder_state *state) {
359
+ int error;
360
+
361
+ for (int attempts = 0; attempts < 2; attempts++) {
362
+ error = pthread_mutex_trylock(&state->slot_one_mutex);
363
+ if (error && error != EBUSY) ENFORCE_SUCCESS_GVL(error);
364
+
365
+ // Slot one is active
366
+ if (!error) return (struct active_slot_pair) {.mutex = &state->slot_one_mutex, .profile = state->slot_one_profile};
367
+
368
+ // If we got here, slot one was not active, let's try slot two
369
+
370
+ error = pthread_mutex_trylock(&state->slot_two_mutex);
371
+ if (error && error != EBUSY) ENFORCE_SUCCESS_GVL(error);
372
+
373
+ // Slot two is active
374
+ if (!error) return (struct active_slot_pair) {.mutex = &state->slot_two_mutex, .profile = state->slot_two_profile};
375
+ }
376
+
377
+ // We already tried both multiple times, and we did not succeed. This is not expected to happen. Let's stop sampling.
378
+ rb_raise(rb_eRuntimeError, "Failed to grab either mutex in sampler_lock_active_profile");
379
+ }
380
+
381
+ static void sampler_unlock_active_profile(struct active_slot_pair active_slot) {
382
+ ENFORCE_SUCCESS_GVL(pthread_mutex_unlock(active_slot.mutex));
383
+ }
384
+
385
+ static ddog_prof_Profile *serializer_flip_active_and_inactive_slots(struct stack_recorder_state *state) {
386
+ int previously_active_slot = state->active_slot;
387
+
388
+ if (previously_active_slot != 1 && previously_active_slot != 2) {
389
+ grab_gvl_and_raise(rb_eRuntimeError, "Unexpected active_slot state %d in serializer_flip_active_and_inactive_slots", previously_active_slot);
390
+ }
391
+
392
+ pthread_mutex_t *previously_active = (previously_active_slot == 1) ? &state->slot_one_mutex : &state->slot_two_mutex;
393
+ pthread_mutex_t *previously_inactive = (previously_active_slot == 1) ? &state->slot_two_mutex : &state->slot_one_mutex;
394
+
395
+ // Release the lock, thus making this slot active
396
+ ENFORCE_SUCCESS_NO_GVL(pthread_mutex_unlock(previously_inactive));
397
+
398
+ // Grab the lock, thus making this slot inactive
399
+ ENFORCE_SUCCESS_NO_GVL(pthread_mutex_lock(previously_active));
400
+
401
+ // Update active_slot
402
+ state->active_slot = (previously_active_slot == 1) ? 2 : 1;
403
+
404
+ // Return profile for previously active slot (now inactive)
405
+ return (previously_active_slot == 1) ? state->slot_one_profile : state->slot_two_profile;
406
+ }
407
+
408
+ // This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
409
+ // It SHOULD NOT be used for other purposes.
410
+ static VALUE _native_active_slot(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) {
411
+ struct stack_recorder_state *state;
412
+ TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
413
+
414
+ return INT2NUM(state->active_slot);
415
+ }
416
+
417
+ // This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
418
+ // It SHOULD NOT be used for other purposes.
419
+ static VALUE _native_is_slot_one_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) { return test_slot_mutex_state(recorder_instance, 1); }
420
+
421
+ // This method exists only to enable testing Datadog::Profiling::StackRecorder behavior using RSpec.
422
+ // It SHOULD NOT be used for other purposes.
423
+ static VALUE _native_is_slot_two_mutex_locked(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance) { return test_slot_mutex_state(recorder_instance, 2); }
424
+
425
+ static VALUE test_slot_mutex_state(VALUE recorder_instance, int slot) {
426
+ struct stack_recorder_state *state;
427
+ TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
428
+
429
+ pthread_mutex_t *slot_mutex = (slot == 1) ? &state->slot_one_mutex : &state->slot_two_mutex;
430
+
431
+ // Like Heisenberg's uncertainty principle, we can't observe without affecting...
432
+ int error = pthread_mutex_trylock(slot_mutex);
433
+
434
+ if (error == 0) {
435
+ // Mutex was unlocked
436
+ ENFORCE_SUCCESS_GVL(pthread_mutex_unlock(slot_mutex));
437
+ return Qfalse;
438
+ } else if (error == EBUSY) {
439
+ // Mutex was locked
440
+ return Qtrue;
441
+ } else {
442
+ ENFORCE_SUCCESS_GVL(error);
443
+ rb_raise(rb_eRuntimeError, "Failed to raise exception in test_slot_mutex_state; this should never happen");
444
+ }
445
+ }
446
+
447
+ // Note that this is using CLOCK_REALTIME (e.g. actual time since unix epoch) and not the CLOCK_MONOTONIC as we use in
448
+ // monotonic_wall_time_now_ns (used in other parts of the codebase)
449
+ static ddog_Timespec time_now(void) {
450
+ struct timespec current_time;
451
+
452
+ if (clock_gettime(CLOCK_REALTIME, &current_time) != 0) ENFORCE_SUCCESS_GVL(errno);
453
+
454
+ return (ddog_Timespec) {.seconds = current_time.tv_sec, .nanoseconds = (uint32_t) current_time.tv_nsec};
455
+ }
456
+
457
+ // After the Ruby VM forks, this method gets called in the child process to clean up any leftover state from the parent.
458
+ //
459
+ // Assumption: This method gets called BEFORE restarting profiling -- e.g. there are no components attempting to
460
+ // trigger samples at the same time.
461
+ static VALUE _native_reset_after_fork(DDTRACE_UNUSED VALUE self, VALUE recorder_instance) {
462
+ struct stack_recorder_state *state;
463
+ TypedData_Get_Struct(recorder_instance, struct stack_recorder_state, &stack_recorder_typed_data, state);
464
+
465
+ // In case the fork happened halfway through `serializer_flip_active_and_inactive_slots` execution and the
466
+ // resulting state is inconsistent, we make sure to reset it back to the initial state.
467
+ initialize_slot_concurrency_control(state);
468
+
469
+ ddog_prof_Profile_reset(state->slot_one_profile, /* start_time: */ NULL);
470
+ ddog_prof_Profile_reset(state->slot_two_profile, /* start_time: */ NULL);
471
+
472
+ return Qtrue;
473
+ }
474
+
475
+ // Assumption 1: This method is called with the GVL being held, because `ddog_prof_Profile_reset` mutates the profile and should
476
+ // not be interrupted part-way through by a VM fork.
477
+ static void serializer_set_start_timestamp_for_next_profile(struct stack_recorder_state *state, ddog_Timespec timestamp) {
478
+ // Before making this profile active, we reset it so that it uses the correct timestamp for its start
479
+ ddog_prof_Profile *next_profile = (state->active_slot == 1) ? state->slot_two_profile : state->slot_one_profile;
480
+
481
+ if (!ddog_prof_Profile_reset(next_profile, &timestamp)) rb_raise(rb_eRuntimeError, "Failed to reset profile");
482
+ }
483
+
484
+ static VALUE _native_record_endpoint(DDTRACE_UNUSED VALUE _self, VALUE recorder_instance, VALUE local_root_span_id, VALUE endpoint) {
485
+ record_endpoint(recorder_instance, char_slice_from_ruby_string(local_root_span_id), char_slice_from_ruby_string(endpoint));
486
+ return Qtrue;
487
+ }
@@ -1,28 +1,39 @@
1
1
  #pragma once
2
2
 
3
- #include <ddprof/ffi.h>
3
+ #include <datadog/profiling.h>
4
4
 
5
- // Note: Please DO NOT use `VALUE_STRING` anywhere else, instead use `DDPROF_FFI_CHARSLICE_C`.
6
- // `VALUE_STRING` is only needed because older versions of gcc (4.9.2, used in our Ruby 2.1 and 2.2 CI test images)
5
+ // Note: Please DO NOT use `VALUE_STRING` anywhere else, instead use `DDOG_CHARSLICE_C`.
6
+ // `VALUE_STRING` is only needed because older versions of gcc (4.9.2, used in our Ruby 2.2 CI test images)
7
7
  // tripped when compiling `enabled_value_types` using `-std=gnu99` due to the extra cast that is included in
8
- // `DDPROF_FFI_CHARSLICE_C` with the following error:
8
+ // `DDOG_CHARSLICE_C` with the following error:
9
9
  //
10
10
  // ```
11
11
  // compiling ../../../../ext/ddtrace_profiling_native_extension/stack_recorder.c
12
12
  // ../../../../ext/ddtrace_profiling_native_extension/stack_recorder.c:23:1: error: initializer element is not constant
13
- // static const ddprof_ffi_ValueType enabled_value_types[] = {CPU_TIME_VALUE, CPU_SAMPLES_VALUE, WALL_TIME_VALUE};
13
+ // static const ddog_prof_ValueType enabled_value_types[] = {CPU_TIME_VALUE, CPU_SAMPLES_VALUE, WALL_TIME_VALUE};
14
14
  // ^
15
15
  // ```
16
16
  #define VALUE_STRING(string) {.ptr = "" string, .len = sizeof(string) - 1}
17
17
 
18
- #define CPU_TIME_VALUE {.type_ = VALUE_STRING("cpu-time"), .unit = VALUE_STRING("nanoseconds")}
19
- #define CPU_SAMPLES_VALUE {.type_ = VALUE_STRING("cpu-samples"), .unit = VALUE_STRING("count")}
20
- #define WALL_TIME_VALUE {.type_ = VALUE_STRING("wall-time"), .unit = VALUE_STRING("nanoseconds")}
21
- #define ALLOC_SAMPLES_VALUE {.type_ = VALUE_STRING("alloc-samples"), .unit = VALUE_STRING("count")}
22
- #define ALLOC_SPACE_VALUE {.type_ = VALUE_STRING("alloc-space"), .unit = VALUE_STRING("bytes")}
23
- #define HEAP_SPACE_VALUE {.type_ = VALUE_STRING("heap-space"), .unit = VALUE_STRING("bytes")}
18
+ #define CPU_TIME_VALUE {.type_ = VALUE_STRING("cpu-time"), .unit = VALUE_STRING("nanoseconds")}
19
+ #define CPU_SAMPLES_VALUE {.type_ = VALUE_STRING("cpu-samples"), .unit = VALUE_STRING("count")}
20
+ #define WALL_TIME_VALUE {.type_ = VALUE_STRING("wall-time"), .unit = VALUE_STRING("nanoseconds")}
21
+ #define ALLOC_SIZE_VALUE {.type_ = VALUE_STRING("alloc-size"), .unit = VALUE_STRING("bytes")}
22
+ #define ALLOC_SAMPLES_VALUE {.type_ = VALUE_STRING("alloc-samples"), .unit = VALUE_STRING("count")}
23
+ #define HEAP_LIVE_SIZE_VALUE {.type_ = VALUE_STRING("heap-live-size"), .unit = VALUE_STRING("bytes")}
24
+ #define HEAP_LIVE_SAMPLES_VALUE {.type_ = VALUE_STRING("heap-live-samples"), .unit = VALUE_STRING("count")}
24
25
 
25
- static const ddprof_ffi_ValueType enabled_value_types[] = {CPU_TIME_VALUE, CPU_SAMPLES_VALUE, WALL_TIME_VALUE};
26
- #define ENABLED_VALUE_TYPES_COUNT (sizeof(enabled_value_types) / sizeof(ddprof_ffi_ValueType))
26
+ static const ddog_prof_ValueType enabled_value_types[] = {
27
+ #define CPU_TIME_VALUE_POS 0
28
+ CPU_TIME_VALUE,
29
+ #define CPU_SAMPLES_VALUE_POS 1
30
+ CPU_SAMPLES_VALUE,
31
+ #define WALL_TIME_VALUE_POS 2
32
+ WALL_TIME_VALUE
33
+ };
27
34
 
28
- void record_sample(VALUE recorder_instance, ddprof_ffi_Sample sample);
35
+ #define ENABLED_VALUE_TYPES_COUNT (sizeof(enabled_value_types) / sizeof(ddog_prof_ValueType))
36
+
37
+ void record_sample(VALUE recorder_instance, ddog_prof_Sample sample);
38
+ void record_endpoint(VALUE recorder_instance, ddog_CharSlice local_root_span_id, ddog_CharSlice endpoint);
39
+ VALUE enforce_recorder_instance(VALUE object);
@@ -0,0 +1,17 @@
1
+ #include <errno.h>
2
+ #include <time.h>
3
+
4
+ #include "ruby_helpers.h"
5
+ #include "time_helpers.h"
6
+
7
+ // Safety: This function is assumed never to raise exceptions by callers when raise_on_failure == false
8
+ long monotonic_wall_time_now_ns(bool raise_on_failure) {
9
+ struct timespec current_monotonic;
10
+
11
+ if (clock_gettime(CLOCK_MONOTONIC, &current_monotonic) != 0) {
12
+ if (raise_on_failure) ENFORCE_SUCCESS_GVL(errno);
13
+ return 0;
14
+ }
15
+
16
+ return current_monotonic.tv_nsec + SECONDS_AS_NS(current_monotonic.tv_sec);
17
+ }
@@ -0,0 +1,10 @@
1
+ #pragma once
2
+
3
+ #define SECONDS_AS_NS(value) (value * 1000 * 1000 * 1000L)
4
+ #define MILLIS_AS_NS(value) (value * 1000 * 1000L)
5
+
6
+ #define RAISE_ON_FAILURE true
7
+ #define DO_NOT_RAISE_ON_FAILURE false
8
+
9
+ // Safety: This function is assumed never to raise exceptions by callers when raise_on_failure == false
10
+ long monotonic_wall_time_now_ns(bool raise_on_failure);