ddtrace 1.18.0 → 1.23.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (229) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +228 -2
  3. data/LICENSE-3rdparty.csv +1 -1
  4. data/bin/ddprofrb +15 -0
  5. data/bin/ddtracerb +3 -1
  6. data/ext/{ddtrace_profiling_loader/ddtrace_profiling_loader.c → datadog_profiling_loader/datadog_profiling_loader.c} +2 -2
  7. data/ext/{ddtrace_profiling_loader → datadog_profiling_loader}/extconf.rb +3 -3
  8. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_cpu_and_wall_time_worker.c +312 -117
  9. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +422 -0
  10. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +101 -0
  11. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_dynamic_sampling_rate.c +22 -14
  12. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_dynamic_sampling_rate.h +4 -0
  13. data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.c +156 -0
  14. data/ext/datadog_profiling_native_extension/collectors_gc_profiling_helper.h +5 -0
  15. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_stack.c +43 -102
  16. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_stack.h +10 -3
  17. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_thread_context.c +272 -136
  18. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_thread_context.h +2 -1
  19. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/extconf.rb +28 -7
  20. data/ext/datadog_profiling_native_extension/heap_recorder.c +1047 -0
  21. data/ext/datadog_profiling_native_extension/heap_recorder.h +166 -0
  22. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/helpers.h +6 -0
  23. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/http_transport.c +15 -19
  24. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/libdatadog_helpers.c +20 -0
  25. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/libdatadog_helpers.h +11 -0
  26. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/native_extension_helpers.rb +50 -4
  27. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/private_vm_api_access.c +19 -0
  28. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/private_vm_api_access.h +4 -0
  29. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/profiling.c +18 -1
  30. data/ext/datadog_profiling_native_extension/ruby_helpers.c +267 -0
  31. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/ruby_helpers.h +33 -0
  32. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/stack_recorder.c +476 -58
  33. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/stack_recorder.h +3 -0
  34. data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/time_helpers.h +2 -0
  35. data/lib/datadog/appsec/contrib/devise/tracking.rb +8 -0
  36. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +45 -14
  37. data/lib/datadog/appsec/event.rb +1 -1
  38. data/lib/datadog/auto_instrument.rb +3 -0
  39. data/lib/datadog/core/configuration/components.rb +7 -6
  40. data/lib/datadog/core/configuration/option.rb +8 -6
  41. data/lib/datadog/core/configuration/settings.rb +259 -60
  42. data/lib/datadog/core/configuration.rb +20 -4
  43. data/lib/datadog/core/diagnostics/environment_logger.rb +4 -3
  44. data/lib/datadog/core/environment/class_count.rb +6 -6
  45. data/lib/datadog/core/environment/git.rb +25 -0
  46. data/lib/datadog/core/environment/identity.rb +18 -48
  47. data/lib/datadog/core/environment/platform.rb +7 -1
  48. data/lib/datadog/core/git/ext.rb +2 -23
  49. data/lib/datadog/core/remote/client/capabilities.rb +1 -1
  50. data/lib/datadog/core/remote/component.rb +25 -12
  51. data/lib/datadog/core/remote/ext.rb +1 -0
  52. data/lib/datadog/core/remote/negotiation.rb +2 -2
  53. data/lib/datadog/core/remote/tie/tracing.rb +39 -0
  54. data/lib/datadog/core/remote/tie.rb +27 -0
  55. data/lib/datadog/core/remote/transport/http/config.rb +1 -1
  56. data/lib/datadog/core/remote/worker.rb +7 -4
  57. data/lib/datadog/core/telemetry/client.rb +18 -10
  58. data/lib/datadog/core/telemetry/emitter.rb +9 -13
  59. data/lib/datadog/core/telemetry/event.rb +247 -56
  60. data/lib/datadog/core/telemetry/ext.rb +4 -0
  61. data/lib/datadog/core/telemetry/heartbeat.rb +1 -3
  62. data/lib/datadog/core/telemetry/http/ext.rb +4 -1
  63. data/lib/datadog/core/telemetry/http/response.rb +4 -0
  64. data/lib/datadog/core/telemetry/http/transport.rb +9 -4
  65. data/lib/datadog/core/telemetry/request.rb +59 -0
  66. data/lib/datadog/core/transport/ext.rb +2 -0
  67. data/lib/datadog/core/utils/url.rb +25 -0
  68. data/lib/datadog/opentelemetry/sdk/propagator.rb +3 -2
  69. data/lib/datadog/opentelemetry.rb +3 -0
  70. data/lib/datadog/profiling/collectors/code_provenance.rb +10 -4
  71. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +36 -12
  72. data/lib/datadog/profiling/collectors/info.rb +101 -0
  73. data/lib/datadog/profiling/component.rb +210 -34
  74. data/lib/datadog/profiling/exporter.rb +23 -6
  75. data/lib/datadog/profiling/ext.rb +2 -0
  76. data/lib/datadog/profiling/flush.rb +6 -3
  77. data/lib/datadog/profiling/http_transport.rb +5 -1
  78. data/lib/datadog/profiling/load_native_extension.rb +19 -6
  79. data/lib/datadog/profiling/native_extension.rb +1 -1
  80. data/lib/datadog/profiling/scheduler.rb +4 -6
  81. data/lib/datadog/profiling/stack_recorder.rb +19 -4
  82. data/lib/datadog/profiling/tag_builder.rb +5 -0
  83. data/lib/datadog/profiling/tasks/exec.rb +3 -3
  84. data/lib/datadog/profiling/tasks/help.rb +3 -3
  85. data/lib/datadog/profiling.rb +13 -2
  86. data/lib/datadog/tracing/configuration/ext.rb +0 -1
  87. data/lib/datadog/tracing/configuration/settings.rb +2 -1
  88. data/lib/datadog/tracing/contrib/action_cable/configuration/settings.rb +1 -0
  89. data/lib/datadog/tracing/contrib/action_cable/ext.rb +1 -0
  90. data/lib/datadog/tracing/contrib/action_mailer/configuration/settings.rb +1 -0
  91. data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +1 -1
  92. data/lib/datadog/tracing/contrib/action_mailer/ext.rb +1 -0
  93. data/lib/datadog/tracing/contrib/action_pack/configuration/settings.rb +1 -0
  94. data/lib/datadog/tracing/contrib/action_pack/ext.rb +1 -0
  95. data/lib/datadog/tracing/contrib/action_view/configuration/settings.rb +1 -0
  96. data/lib/datadog/tracing/contrib/action_view/ext.rb +1 -0
  97. data/lib/datadog/tracing/contrib/active_job/configuration/settings.rb +1 -0
  98. data/lib/datadog/tracing/contrib/active_job/ext.rb +1 -0
  99. data/lib/datadog/tracing/contrib/active_model_serializers/configuration/settings.rb +1 -0
  100. data/lib/datadog/tracing/contrib/active_model_serializers/ext.rb +1 -0
  101. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +11 -4
  102. data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +1 -0
  103. data/lib/datadog/tracing/contrib/active_record/ext.rb +1 -0
  104. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +1 -0
  105. data/lib/datadog/tracing/contrib/active_support/ext.rb +1 -0
  106. data/lib/datadog/tracing/contrib/analytics.rb +0 -1
  107. data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +1 -0
  108. data/lib/datadog/tracing/contrib/aws/ext.rb +1 -0
  109. data/lib/datadog/tracing/contrib/concurrent_ruby/async_patch.rb +20 -0
  110. data/lib/datadog/tracing/contrib/concurrent_ruby/patcher.rb +11 -1
  111. data/lib/datadog/tracing/contrib/configurable.rb +1 -1
  112. data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +1 -0
  113. data/lib/datadog/tracing/contrib/dalli/ext.rb +1 -0
  114. data/lib/datadog/tracing/contrib/delayed_job/configuration/settings.rb +1 -0
  115. data/lib/datadog/tracing/contrib/delayed_job/ext.rb +1 -0
  116. data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +1 -0
  117. data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +1 -0
  118. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +1 -0
  119. data/lib/datadog/tracing/contrib/ethon/ext.rb +1 -0
  120. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +1 -0
  121. data/lib/datadog/tracing/contrib/excon/ext.rb +1 -0
  122. data/lib/datadog/tracing/contrib/extensions.rb +6 -2
  123. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +7 -0
  124. data/lib/datadog/tracing/contrib/faraday/ext.rb +1 -0
  125. data/lib/datadog/tracing/contrib/faraday/middleware.rb +1 -1
  126. data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +1 -0
  127. data/lib/datadog/tracing/contrib/grape/ext.rb +1 -0
  128. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +1 -0
  129. data/lib/datadog/tracing/contrib/graphql/ext.rb +1 -0
  130. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +1 -0
  131. data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
  132. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +1 -0
  133. data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +2 -2
  134. data/lib/datadog/tracing/contrib/http/ext.rb +1 -0
  135. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +1 -0
  136. data/lib/datadog/tracing/contrib/httpclient/ext.rb +1 -0
  137. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +1 -0
  138. data/lib/datadog/tracing/contrib/httprb/ext.rb +1 -0
  139. data/lib/datadog/tracing/contrib/kafka/configuration/settings.rb +1 -0
  140. data/lib/datadog/tracing/contrib/kafka/ext.rb +1 -0
  141. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +1 -0
  142. data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -0
  143. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +5 -0
  144. data/lib/datadog/tracing/contrib/mysql2/ext.rb +1 -0
  145. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +2 -1
  146. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +1 -0
  147. data/lib/datadog/tracing/contrib/opensearch/ext.rb +1 -0
  148. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +1 -0
  149. data/lib/datadog/tracing/contrib/pg/ext.rb +1 -0
  150. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +11 -4
  151. data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +1 -0
  152. data/lib/datadog/tracing/contrib/presto/ext.rb +1 -0
  153. data/lib/datadog/tracing/contrib/qless/configuration/settings.rb +1 -0
  154. data/lib/datadog/tracing/contrib/qless/ext.rb +1 -0
  155. data/lib/datadog/tracing/contrib/que/configuration/settings.rb +1 -0
  156. data/lib/datadog/tracing/contrib/que/ext.rb +1 -0
  157. data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +1 -0
  158. data/lib/datadog/tracing/contrib/racecar/ext.rb +1 -0
  159. data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +1 -0
  160. data/lib/datadog/tracing/contrib/rack/ext.rb +1 -0
  161. data/lib/datadog/tracing/contrib/rack/middlewares.rb +9 -2
  162. data/lib/datadog/tracing/contrib/rails/auto_instrument_railtie.rb +0 -2
  163. data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +1 -0
  164. data/lib/datadog/tracing/contrib/rails/ext.rb +1 -0
  165. data/lib/datadog/tracing/contrib/rake/configuration/settings.rb +1 -0
  166. data/lib/datadog/tracing/contrib/rake/ext.rb +1 -0
  167. data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +1 -0
  168. data/lib/datadog/tracing/contrib/redis/ext.rb +1 -0
  169. data/lib/datadog/tracing/contrib/redis/instrumentation.rb +2 -2
  170. data/lib/datadog/tracing/contrib/redis/patcher.rb +34 -21
  171. data/lib/datadog/tracing/contrib/resque/configuration/settings.rb +1 -0
  172. data/lib/datadog/tracing/contrib/resque/ext.rb +1 -0
  173. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +1 -0
  174. data/lib/datadog/tracing/contrib/rest_client/ext.rb +1 -0
  175. data/lib/datadog/tracing/contrib/roda/configuration/settings.rb +1 -0
  176. data/lib/datadog/tracing/contrib/roda/ext.rb +1 -0
  177. data/lib/datadog/tracing/contrib/sequel/configuration/settings.rb +1 -0
  178. data/lib/datadog/tracing/contrib/sequel/ext.rb +1 -0
  179. data/lib/datadog/tracing/contrib/shoryuken/configuration/settings.rb +1 -0
  180. data/lib/datadog/tracing/contrib/shoryuken/ext.rb +1 -0
  181. data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +1 -0
  182. data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
  183. data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +1 -0
  184. data/lib/datadog/tracing/contrib/sinatra/ext.rb +1 -0
  185. data/lib/datadog/tracing/contrib/sneakers/configuration/settings.rb +1 -0
  186. data/lib/datadog/tracing/contrib/sneakers/ext.rb +1 -0
  187. data/lib/datadog/tracing/contrib/stripe/configuration/settings.rb +1 -0
  188. data/lib/datadog/tracing/contrib/stripe/ext.rb +1 -0
  189. data/lib/datadog/tracing/contrib/sucker_punch/configuration/settings.rb +1 -0
  190. data/lib/datadog/tracing/contrib/sucker_punch/ext.rb +1 -0
  191. data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +58 -0
  192. data/lib/datadog/tracing/contrib/trilogy/ext.rb +27 -0
  193. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +94 -0
  194. data/lib/datadog/tracing/contrib/trilogy/integration.rb +43 -0
  195. data/lib/datadog/tracing/contrib/trilogy/patcher.rb +31 -0
  196. data/lib/datadog/tracing/contrib.rb +1 -0
  197. data/lib/datadog/tracing/sampling/matcher.rb +23 -3
  198. data/lib/datadog/tracing/sampling/rule.rb +7 -2
  199. data/lib/datadog/tracing/sampling/rule_sampler.rb +2 -0
  200. data/lib/datadog/tracing/trace_operation.rb +1 -2
  201. data/lib/datadog/tracing/transport/http.rb +1 -0
  202. data/lib/datadog/tracing/transport/trace_formatter.rb +31 -0
  203. data/lib/datadog/tracing.rb +8 -2
  204. data/lib/ddtrace/version.rb +2 -2
  205. metadata +71 -61
  206. data/ext/ddtrace_profiling_native_extension/pid_controller.c +0 -57
  207. data/ext/ddtrace_profiling_native_extension/pid_controller.h +0 -45
  208. data/ext/ddtrace_profiling_native_extension/ruby_helpers.c +0 -110
  209. data/lib/datadog/core/telemetry/collector.rb +0 -240
  210. data/lib/datadog/core/telemetry/v1/app_event.rb +0 -52
  211. data/lib/datadog/core/telemetry/v1/application.rb +0 -92
  212. data/lib/datadog/core/telemetry/v1/configuration.rb +0 -25
  213. data/lib/datadog/core/telemetry/v1/dependency.rb +0 -43
  214. data/lib/datadog/core/telemetry/v1/host.rb +0 -59
  215. data/lib/datadog/core/telemetry/v1/integration.rb +0 -64
  216. data/lib/datadog/core/telemetry/v1/product.rb +0 -36
  217. data/lib/datadog/core/telemetry/v1/telemetry_request.rb +0 -106
  218. data/lib/datadog/core/telemetry/v2/app_client_configuration_change.rb +0 -41
  219. data/lib/datadog/core/telemetry/v2/request.rb +0 -29
  220. data/lib/datadog/profiling/diagnostics/environment_logger.rb +0 -39
  221. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/NativeExtensionDesign.md +0 -0
  222. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/clock_id.h +0 -0
  223. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/clock_id_from_pthread.c +0 -0
  224. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/clock_id_noop.c +0 -0
  225. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_idle_sampling_helper.c +0 -0
  226. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/collectors_idle_sampling_helper.h +0 -0
  227. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/setup_signal_handler.c +0 -0
  228. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/setup_signal_handler.h +0 -0
  229. /data/ext/{ddtrace_profiling_native_extension → datadog_profiling_native_extension}/time_helpers.c +0 -0
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'set'
4
+ require 'time'
5
+
6
+ module Datadog
7
+ module Profiling
8
+ module Collectors
9
+ # Collects information of relevance for profiler. This will get sent alongside
10
+ # the profile and show up in the UI or potentially influence processing in some way.
11
+ #
12
+ # Information is currently collected and frozen at construction time. A full collector
13
+ # could be seen as overkill for this case but it allows us to centralize information
14
+ # gathering and easily support more flexible/dynamic info collection in the future.
15
+ class Info
16
+ def initialize(settings)
17
+ @profiler_info = nil
18
+ @info = {
19
+ platform: collect_platform_info,
20
+ runtime: collect_runtime_info,
21
+ application: collect_application_info(settings),
22
+ profiler: collect_profiler_info(settings),
23
+ }.freeze
24
+ end
25
+
26
+ attr_reader :info
27
+
28
+ private
29
+
30
+ # Instead of trying to figure out real process start time by checking
31
+ # /proc or some other complex/non-portable way, approximate start time
32
+ # by time of requirement of this file.
33
+ START_TIME = Time.now.utc.freeze
34
+
35
+ def collect_platform_info
36
+ @platform_info ||= {
37
+ container_id: Datadog::Core::Environment::Container.container_id,
38
+ hostname: Datadog::Core::Environment::Platform.hostname,
39
+ kernel_name: Datadog::Core::Environment::Platform.kernel_name,
40
+ kernel_release: Datadog::Core::Environment::Platform.kernel_release,
41
+ kernel_version: Datadog::Core::Environment::Platform.kernel_version
42
+ }.freeze
43
+ end
44
+
45
+ def collect_runtime_info
46
+ @runtime_info ||= {
47
+ engine: Datadog::Core::Environment::Identity.lang_engine,
48
+ version: Datadog::Core::Environment::Identity.lang_version,
49
+ platform: Datadog::Core::Environment::Identity.lang_platform,
50
+ }.freeze
51
+ end
52
+
53
+ def collect_application_info(settings)
54
+ @application_info ||= {
55
+ start_time: START_TIME.iso8601,
56
+ env: settings.env,
57
+ service: settings.service,
58
+ version: settings.version,
59
+ }.freeze
60
+ end
61
+
62
+ def collect_profiler_info(settings)
63
+ unless @profiler_info
64
+ lib_datadog_gem = ::Gem.loaded_specs['libdatadog']
65
+ @profiler_info = {
66
+ version: Datadog::Core::Environment::Identity.tracer_version,
67
+ libdatadog: "#{lib_datadog_gem.version}-#{lib_datadog_gem.platform}",
68
+ settings: collect_settings_recursively(settings.profiling),
69
+ }.freeze
70
+ end
71
+ @profiler_info
72
+ end
73
+
74
+ # The settings/option model isn't directly serializable because
75
+ # of subsettings and options that link to full blown custom object
76
+ # instances without proper serialization.
77
+ # This method navigates a settings object recursively, converting
78
+ # it into more basic types that are trivially convertible to JSON.
79
+ def collect_settings_recursively(v)
80
+ v = v.options_hash if v.respond_to?(:options_hash)
81
+
82
+ if v.nil? || v.is_a?(Symbol) || v.is_a?(Numeric) || v.is_a?(String) || v.equal?(true) || v.equal?(false)
83
+ Core::Utils::SafeDup.frozen_or_dup(v)
84
+ elsif v.is_a?(Hash)
85
+ collected_hash = v.each_with_object({}) do |(key, value), hash|
86
+ collected_value = collect_settings_recursively(value)
87
+ hash[key] = collected_value
88
+ end
89
+ collected_hash.freeze
90
+ elsif v.is_a?(Enumerable)
91
+ collected_list = v
92
+ .map { |value| collect_settings_recursively(value) }
93
+ collected_list.freeze
94
+ else
95
+ v.inspect
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -7,12 +7,8 @@ module Datadog
7
7
  # Passing in a `nil` tracer is supported and will disable the following profiling features:
8
8
  # * Code Hotspots panel in the trace viewer, as well as scoping a profile down to a span
9
9
  # * Endpoint aggregation in the profiler UX, including normalization (resource per endpoint call)
10
- def self.build_profiler_component(settings:, agent_settings:, optional_tracer:)
11
- require_relative '../profiling/diagnostics/environment_logger'
12
-
13
- Profiling::Diagnostics::EnvironmentLogger.collect_and_log!
14
-
15
- return unless settings.profiling.enabled
10
+ def self.build_profiler_component(settings:, agent_settings:, optional_tracer:) # rubocop:disable Metrics/MethodLength
11
+ return [nil, { profiling_enabled: false }] unless settings.profiling.enabled
16
12
 
17
13
  # Workaround for weird dependency direction: the Core::Configuration::Components class currently has a
18
14
  # dependency on individual products, in this case the Profiler.
@@ -32,7 +28,8 @@ module Datadog
32
28
  # done, then profiling may not be loaded, and thus to avoid this issue we do a require here (which is a
33
29
  # no-op if profiling is already loaded).
34
30
  require_relative '../profiling'
35
- return unless Profiling.supported?
31
+
32
+ return [nil, { profiling_enabled: false }] unless Profiling.supported?
36
33
 
37
34
  # Activate forking extensions
38
35
  Profiling::Tasks::Setup.new.run
@@ -40,45 +37,64 @@ module Datadog
40
37
  # NOTE: Please update the Initialization section of ProfilingDevelopment.md with any changes to this method
41
38
 
42
39
  no_signals_workaround_enabled = no_signals_workaround_enabled?(settings)
43
- timeline_enabled = settings.profiling.advanced.experimental_timeline_enabled
40
+ timeline_enabled = settings.profiling.advanced.timeline_enabled
41
+ allocation_profiling_enabled = enable_allocation_profiling?(settings)
42
+ heap_sample_every = get_heap_sample_every(settings)
43
+ heap_profiling_enabled = enable_heap_profiling?(settings, allocation_profiling_enabled, heap_sample_every)
44
+ heap_size_profiling_enabled = enable_heap_size_profiling?(settings, heap_profiling_enabled)
45
+
46
+ overhead_target_percentage = valid_overhead_target(settings.profiling.advanced.overhead_target_percentage)
47
+ upload_period_seconds = [60, settings.profiling.advanced.upload_period_seconds].max
44
48
 
45
49
  recorder = Datadog::Profiling::StackRecorder.new(
46
50
  cpu_time_enabled: RUBY_PLATFORM.include?('linux'), # Only supported on Linux currently
47
- alloc_samples_enabled: false, # Always disabled for now -- work in progress
48
- )
49
- thread_context_collector = Datadog::Profiling::Collectors::ThreadContext.new(
50
- recorder: recorder,
51
- max_frames: settings.profiling.advanced.max_frames,
52
- tracer: optional_tracer,
53
- endpoint_collection_enabled: settings.profiling.advanced.endpoint.collection.enabled,
51
+ alloc_samples_enabled: allocation_profiling_enabled,
52
+ heap_samples_enabled: heap_profiling_enabled,
53
+ heap_size_enabled: heap_size_profiling_enabled,
54
+ heap_sample_every: heap_sample_every,
54
55
  timeline_enabled: timeline_enabled,
55
56
  )
57
+ thread_context_collector = build_thread_context_collector(settings, recorder, optional_tracer, timeline_enabled)
56
58
  worker = Datadog::Profiling::Collectors::CpuAndWallTimeWorker.new(
57
59
  gc_profiling_enabled: enable_gc_profiling?(settings),
58
- allocation_counting_enabled: settings.profiling.advanced.allocation_counting_enabled,
59
60
  no_signals_workaround_enabled: no_signals_workaround_enabled,
60
61
  thread_context_collector: thread_context_collector,
61
- allocation_sample_every: 0,
62
+ dynamic_sampling_rate_overhead_target_percentage: overhead_target_percentage,
63
+ allocation_profiling_enabled: allocation_profiling_enabled,
62
64
  )
63
65
 
64
66
  internal_metadata = {
65
67
  no_signals_workaround_enabled: no_signals_workaround_enabled,
66
68
  timeline_enabled: timeline_enabled,
69
+ heap_sample_every: heap_sample_every,
67
70
  }.freeze
68
71
 
69
- exporter = build_profiler_exporter(settings, recorder, internal_metadata: internal_metadata)
72
+ exporter = build_profiler_exporter(settings, recorder, worker, internal_metadata: internal_metadata)
70
73
  transport = build_profiler_transport(settings, agent_settings)
71
- scheduler = Profiling::Scheduler.new(exporter: exporter, transport: transport)
74
+ scheduler = Profiling::Scheduler.new(exporter: exporter, transport: transport, interval: upload_period_seconds)
72
75
 
73
- Profiling::Profiler.new(worker: worker, scheduler: scheduler)
76
+ [Profiling::Profiler.new(worker: worker, scheduler: scheduler), { profiling_enabled: true }]
74
77
  end
75
78
 
76
- private_class_method def self.build_profiler_exporter(settings, recorder, internal_metadata:)
79
+ private_class_method def self.build_thread_context_collector(settings, recorder, optional_tracer, timeline_enabled)
80
+ Datadog::Profiling::Collectors::ThreadContext.new(
81
+ recorder: recorder,
82
+ max_frames: settings.profiling.advanced.max_frames,
83
+ tracer: optional_tracer,
84
+ endpoint_collection_enabled: settings.profiling.advanced.endpoint.collection.enabled,
85
+ timeline_enabled: timeline_enabled,
86
+ )
87
+ end
88
+
89
+ private_class_method def self.build_profiler_exporter(settings, recorder, worker, internal_metadata:)
90
+ info_collector = Profiling::Collectors::Info.new(settings)
77
91
  code_provenance_collector =
78
92
  (Profiling::Collectors::CodeProvenance.new if settings.profiling.advanced.code_provenance_enabled)
79
93
 
80
94
  Profiling::Exporter.new(
81
95
  pprof_recorder: recorder,
96
+ worker: worker,
97
+ info_collector: info_collector,
82
98
  code_provenance_collector: code_provenance_collector,
83
99
  internal_metadata: internal_metadata,
84
100
  )
@@ -95,19 +111,134 @@ module Datadog
95
111
  end
96
112
 
97
113
  private_class_method def self.enable_gc_profiling?(settings)
98
- # See comments on the setting definition for more context on why it exists.
99
- if settings.profiling.advanced.force_enable_gc_profiling
100
- if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3')
101
- Datadog.logger.debug(
102
- 'Profiling time/resources spent in Garbage Collection force enabled. Do not use Ractors in combination ' \
103
- 'with this option as profiles will be incomplete.'
104
- )
105
- end
114
+ return false unless settings.profiling.advanced.gc_enabled
115
+
116
+ # SEVERE - Only with Ractors
117
+ # On Ruby versions 3.0 (all), 3.1.0 to 3.1.3, and 3.2.0 to 3.2.2 gc profiling can trigger a VM bug
118
+ # that causes a segmentation fault during garbage collection of Ractors
119
+ # (https://bugs.ruby-lang.org/issues/18464). We don't allow enabling gc profiling on such Rubies.
120
+ # This bug is fixed on Ruby versions 3.1.4, 3.2.3 and 3.3.0.
121
+ if RUBY_VERSION.start_with?('3.0.') ||
122
+ (RUBY_VERSION.start_with?('3.1.') && RUBY_VERSION < '3.1.4') ||
123
+ (RUBY_VERSION.start_with?('3.2.') && RUBY_VERSION < '3.2.3')
124
+ Datadog.logger.warn(
125
+ "Current Ruby version (#{RUBY_VERSION}) has a VM bug where enabling GC profiling would cause "\
126
+ 'crashes (https://bugs.ruby-lang.org/issues/18464). GC profiling has been disabled.'
127
+ )
128
+ return false
129
+ elsif RUBY_VERSION.start_with?('3.')
130
+ Datadog.logger.debug(
131
+ 'In all known versions of Ruby 3.x, using Ractors may result in GC profiling unexpectedly ' \
132
+ 'stopping (https://bugs.ruby-lang.org/issues/19112). Note that this stop has no impact in your ' \
133
+ 'application stability or performance. This does not happen if Ractors are not used.'
134
+ )
135
+ end
106
136
 
107
- true
108
- else
109
- false
137
+ true
138
+ end
139
+
140
+ private_class_method def self.get_heap_sample_every(settings)
141
+ heap_sample_rate = settings.profiling.advanced.experimental_heap_sample_rate
142
+
143
+ raise ArgumentError, "Heap sample rate must be a positive integer. Was #{heap_sample_rate}" if heap_sample_rate <= 0
144
+
145
+ heap_sample_rate
146
+ end
147
+
148
+ private_class_method def self.enable_allocation_profiling?(settings)
149
+ return false unless settings.profiling.allocation_enabled
150
+
151
+ # Allocation sampling is safe and supported on Ruby 2.x, but has a few caveats on Ruby 3.x.
152
+
153
+ # SEVERE - All configurations
154
+ # Ruby 3.2.0 to 3.2.2 have a bug in the newobj tracepoint (https://bugs.ruby-lang.org/issues/19482,
155
+ # https://github.com/ruby/ruby/pull/7464) that makes this crash in any configuration. This bug is
156
+ # fixed on Ruby versions 3.2.3 and 3.3.0.
157
+ if RUBY_VERSION.start_with?('3.2.') && RUBY_VERSION < '3.2.3'
158
+ Datadog.logger.warn(
159
+ 'Allocation profiling is not supported in Ruby versions 3.2.0, 3.2.1 and 3.2.2 and will be forcibly '\
160
+ 'disabled. This is due to a VM bug that can lead to crashes (https://bugs.ruby-lang.org/issues/19482). '\
161
+ 'Other Ruby versions do not suffer from this issue.'
162
+ )
163
+ return false
110
164
  end
165
+
166
+ # SEVERE - Only with Ractors
167
+ # On Ruby versions 3.0 (all), 3.1.0 to 3.1.3, and 3.2.0 to 3.2.2 allocation profiling can trigger a VM bug
168
+ # that causes a segmentation fault during garbage collection of Ractors
169
+ # (https://bugs.ruby-lang.org/issues/18464). We don't recommend using this feature on such Rubies.
170
+ # This bug is fixed on Ruby versions 3.1.4, 3.2.3 and 3.3.0.
171
+ if RUBY_VERSION.start_with?('3.0.') ||
172
+ (RUBY_VERSION.start_with?('3.1.') && RUBY_VERSION < '3.1.4') ||
173
+ (RUBY_VERSION.start_with?('3.2.') && RUBY_VERSION < '3.2.3')
174
+ Datadog.logger.warn(
175
+ "Current Ruby version (#{RUBY_VERSION}) has a VM bug where enabling allocation profiling while using "\
176
+ 'Ractors may cause unexpected issues, including crashes (https://bugs.ruby-lang.org/issues/18464). '\
177
+ 'This does not happen if Ractors are not used.'
178
+ )
179
+ # ANNOYANCE - Only with Ractors
180
+ # On all known versions of Ruby 3.x, due to https://bugs.ruby-lang.org/issues/19112, when a ractor gets
181
+ # garbage collected, Ruby will disable all active tracepoints, which this feature internally relies on.
182
+ elsif RUBY_VERSION.start_with?('3.')
183
+ Datadog.logger.warn(
184
+ 'In all known versions of Ruby 3.x, using Ractors may result in allocation profiling unexpectedly ' \
185
+ 'stopping (https://bugs.ruby-lang.org/issues/19112). Note that this stop has no impact in your ' \
186
+ 'application stability or performance. This does not happen if Ractors are not used.'
187
+ )
188
+ end
189
+
190
+ Datadog.logger.debug('Enabled allocation profiling')
191
+
192
+ true
193
+ end
194
+
195
+ private_class_method def self.enable_heap_profiling?(settings, allocation_profiling_enabled, heap_sample_rate)
196
+ heap_profiling_enabled = settings.profiling.advanced.experimental_heap_enabled
197
+
198
+ return false unless heap_profiling_enabled
199
+
200
+ if RUBY_VERSION.start_with?('2.') && RUBY_VERSION < '2.7'
201
+ Datadog.logger.warn(
202
+ 'Heap profiling currently relies on features introduced in Ruby 2.7 and will be forcibly disabled. '\
203
+ 'Please upgrade to Ruby >= 2.7 in order to use this feature.'
204
+ )
205
+ return false
206
+ end
207
+
208
+ if RUBY_VERSION < '3.1'
209
+ Datadog.logger.debug(
210
+ "Current Ruby version (#{RUBY_VERSION}) supports forced object recycling which has a bug that the " \
211
+ 'heap profiler is forced to work around to remain accurate. This workaround requires force-setting '\
212
+ "the SEEN_OBJ_ID flag on objects that should have it but don't. Full details can be found in " \
213
+ 'https://github.com/DataDog/dd-trace-rb/pull/3360. This workaround should be safe but can be ' \
214
+ 'bypassed by disabling the heap profiler or upgrading to Ruby >= 3.1 where forced object recycling ' \
215
+ 'was completely removed (https://bugs.ruby-lang.org/issues/18290).'
216
+ )
217
+ end
218
+
219
+ unless allocation_profiling_enabled
220
+ raise ArgumentError,
221
+ 'Heap profiling requires allocation profiling to be enabled'
222
+ end
223
+
224
+ Datadog.logger.warn(
225
+ "Enabled experimental heap profiling: heap_sample_rate=#{heap_sample_rate}. This is experimental, not " \
226
+ 'recommended, and will increase overhead!'
227
+ )
228
+
229
+ true
230
+ end
231
+
232
+ private_class_method def self.enable_heap_size_profiling?(settings, heap_profiling_enabled)
233
+ heap_size_profiling_enabled = settings.profiling.advanced.experimental_heap_size_enabled
234
+
235
+ return false unless heap_profiling_enabled && heap_size_profiling_enabled
236
+
237
+ Datadog.logger.warn(
238
+ 'Enabled experimental heap size profiling. This is experimental, not recommended, and will increase overhead!'
239
+ )
240
+
241
+ true
111
242
  end
112
243
 
113
244
  private_class_method def self.no_signals_workaround_enabled?(settings) # rubocop:disable Metrics/MethodLength
@@ -217,9 +348,12 @@ module Datadog
217
348
 
218
349
  return true unless mysql2_client_class && mysql2_client_class.respond_to?(:info)
219
350
 
220
- libmysqlclient_version = Gem::Version.new(mysql2_client_class.info[:version])
351
+ info = mysql2_client_class.info
352
+ libmysqlclient_version = Gem::Version.new(info[:version])
221
353
 
222
- compatible = libmysqlclient_version >= Gem::Version.new('8.0.0')
354
+ compatible =
355
+ libmysqlclient_version >= Gem::Version.new('8.0.0') ||
356
+ looks_like_mariadb?(info, libmysqlclient_version)
223
357
 
224
358
  Datadog.logger.debug(
225
359
  "The `mysql2` gem is using #{compatible ? 'a compatible' : 'an incompatible'} version of " \
@@ -245,6 +379,48 @@ module Datadog
245
379
  true
246
380
  end
247
381
  end
382
+
383
+ private_class_method def self.valid_overhead_target(overhead_target_percentage)
384
+ if overhead_target_percentage > 0 && overhead_target_percentage <= 20
385
+ overhead_target_percentage
386
+ else
387
+ Datadog.logger.error(
388
+ 'Ignoring invalid value for profiling overhead_target_percentage setting: ' \
389
+ "#{overhead_target_percentage.inspect}. Falling back to default value."
390
+ )
391
+
392
+ 2.0
393
+ end
394
+ end
395
+
396
+ # To add just a bit more complexity to our detection code, in https://github.com/DataDog/dd-trace-rb/issues/3334
397
+ # a user reported that our code was incorrectly flagging the mariadb variant of libmysqlclient as being
398
+ # incompatible. In fact we have no reports of the mariadb variant needing the "no signals" workaround,
399
+ # so we flag it as compatible when it's in use.
400
+ #
401
+ # A problem is that there doesn't seem to be an obvious way to query the mysql2 gem on which kind of
402
+ # libmysqlclient it's using, so we detect it by looking at the version.
403
+ #
404
+ # The info method for mysql2 with mariadb looks something like this:
405
+ # `{:id=>30308, :version=>"3.3.8", :header_version=>"11.2.2"}`
406
+ #
407
+ # * The version seems to come from https://github.com/mariadb-corporation/mariadb-connector-c and the latest
408
+ # one is 3.x.
409
+ # * The header_version is what people usually see as the "mariadb version"
410
+ #
411
+ # As a comparison, for libmysql the info looks like:
412
+ # * `{:id=>80035, :version=>"8.0.35", :header_version=>"8.0.35"}`
413
+ #
414
+ # Thus our detection is version 4 or older, because libmysqlclient 4 is almost 20 years old so it's most probably
415
+ # not that one + header_version being 10 or newer, since according to https://endoflife.date/mariadb that's a
416
+ # sane range for modern mariadb releases.
417
+ private_class_method def self.looks_like_mariadb?(info, libmysqlclient_version)
418
+ header_version = Gem::Version.new(info[:header_version]) if info[:header_version]
419
+
420
+ !!(header_version &&
421
+ libmysqlclient_version < Gem::Version.new('5.0.0') &&
422
+ header_version >= Gem::Version.new('10.0.0'))
423
+ end
248
424
  end
249
425
  end
250
426
  end
@@ -23,31 +23,40 @@ module Datadog
23
23
  :time_provider,
24
24
  :last_flush_finish_at,
25
25
  :created_at,
26
- :internal_metadata
26
+ :internal_metadata,
27
+ :info_json
27
28
 
28
29
  public
29
30
 
30
31
  def initialize(
31
32
  pprof_recorder:,
33
+ worker:,
34
+ info_collector:,
32
35
  code_provenance_collector:,
33
36
  internal_metadata:,
34
37
  minimum_duration_seconds: PROFILE_DURATION_THRESHOLD_SECONDS,
35
38
  time_provider: Time
36
39
  )
37
40
  @pprof_recorder = pprof_recorder
41
+ @worker = worker
38
42
  @code_provenance_collector = code_provenance_collector
39
43
  @minimum_duration_seconds = minimum_duration_seconds
40
44
  @time_provider = time_provider
41
45
  @last_flush_finish_at = nil
42
46
  @created_at = time_provider.now.utc
43
47
  @internal_metadata = internal_metadata
48
+ # NOTE: At the time of this comment collected info does not change over time so we'll hardcode
49
+ # it on startup to prevent serializing the same info on every flush.
50
+ @info_json = JSON.fast_generate(info_collector.info).freeze
44
51
  end
45
52
 
46
53
  def flush
47
- start, finish, uncompressed_pprof = pprof_recorder.serialize
48
- @last_flush_finish_at = finish
54
+ worker_stats = @worker.stats_and_reset_not_thread_safe
55
+ serialization_result = pprof_recorder.serialize
56
+ return if serialization_result.nil?
49
57
 
50
- return if uncompressed_pprof.nil? # We don't want to report empty profiles
58
+ start, finish, compressed_pprof, profile_stats = serialization_result
59
+ @last_flush_finish_at = finish
51
60
 
52
61
  if duration_below_threshold?(start, finish)
53
62
  Datadog.logger.debug('Skipped exporting profiling events as profile duration is below minimum')
@@ -60,11 +69,19 @@ module Datadog
60
69
  start: start,
61
70
  finish: finish,
62
71
  pprof_file_name: Datadog::Profiling::Ext::Transport::HTTP::PPROF_DEFAULT_FILENAME,
63
- pprof_data: uncompressed_pprof.to_s,
72
+ pprof_data: compressed_pprof.to_s,
64
73
  code_provenance_file_name: Datadog::Profiling::Ext::Transport::HTTP::CODE_PROVENANCE_FILENAME,
65
74
  code_provenance_data: uncompressed_code_provenance,
66
75
  tags_as_array: Datadog::Profiling::TagBuilder.call(settings: Datadog.configuration).to_a,
67
- internal_metadata: internal_metadata,
76
+ internal_metadata: internal_metadata.merge(
77
+ {
78
+ worker_stats: worker_stats,
79
+ profile_stats: profile_stats,
80
+ recorder_stats: pprof_recorder.stats,
81
+ gc: GC.stat,
82
+ }
83
+ ),
84
+ info_json: info_json,
68
85
  )
69
86
  end
70
87
 
@@ -23,6 +23,8 @@ module Datadog
23
23
  FORM_FIELD_TAG_RUNTIME_VERSION = 'runtime_version'
24
24
  FORM_FIELD_TAG_SERVICE = 'service'
25
25
  FORM_FIELD_TAG_VERSION = 'version'
26
+ TAG_GIT_REPOSITORY_URL = 'git.repository_url'
27
+ TAG_GIT_COMMIT_SHA = 'git.commit.sha'
26
28
 
27
29
  PPROF_DEFAULT_FILENAME = 'rubyprofile.pprof'
28
30
  CODE_PROVENANCE_FILENAME = 'code-provenance.json'
@@ -14,7 +14,8 @@ module Datadog
14
14
  :code_provenance_file_name,
15
15
  :code_provenance_data, # gzipped json bytes
16
16
  :tags_as_array,
17
- :internal_metadata_json
17
+ :internal_metadata_json,
18
+ :info_json
18
19
 
19
20
  def initialize(
20
21
  start:,
@@ -24,7 +25,8 @@ module Datadog
24
25
  code_provenance_file_name:,
25
26
  code_provenance_data:,
26
27
  tags_as_array:,
27
- internal_metadata:
28
+ internal_metadata:,
29
+ info_json:
28
30
  )
29
31
  @start = start
30
32
  @finish = finish
@@ -33,7 +35,8 @@ module Datadog
33
35
  @code_provenance_file_name = code_provenance_file_name
34
36
  @code_provenance_data = code_provenance_data
35
37
  @tags_as_array = tags_as_array
36
- @internal_metadata_json = JSON.fast_generate(internal_metadata.map { |k, v| [k, v.to_s] }.to_h)
38
+ @internal_metadata_json = JSON.fast_generate(internal_metadata)
39
+ @info_json = info_json
37
40
  end
38
41
  end
39
42
  end
@@ -43,6 +43,8 @@ module Datadog
43
43
 
44
44
  tags_as_array: flush.tags_as_array,
45
45
  internal_metadata_json: flush.internal_metadata_json,
46
+
47
+ info_json: flush.info_json
46
48
  )
47
49
 
48
50
  if status == :ok
@@ -117,7 +119,8 @@ module Datadog
117
119
  code_provenance_file_name:,
118
120
  code_provenance_data:,
119
121
  tags_as_array:,
120
- internal_metadata_json:
122
+ internal_metadata_json:,
123
+ info_json:
121
124
  )
122
125
  self.class._native_do_export(
123
126
  exporter_configuration,
@@ -132,6 +135,7 @@ module Datadog
132
135
  code_provenance_data,
133
136
  tags_as_array,
134
137
  internal_metadata_json,
138
+ info_json,
135
139
  )
136
140
  end
137
141
 
@@ -1,24 +1,37 @@
1
1
  # This file is used to load the profiling native extension. It works in two steps:
2
2
  #
3
- # 1. Load the ddtrace_profiling_loader extension. This extension will be used to load the actual extension, but in
4
- # a special way that avoids exposing native-level code symbols. See `ddtrace_profiling_loader.c` for more details.
3
+ # 1. Load the datadog_profiling_loader extension. This extension will be used to load the actual extension, but in
4
+ # a special way that avoids exposing native-level code symbols. See `datadog_profiling_loader.c` for more details.
5
5
  #
6
- # 2. Use the Datadog::Profiling::Loader exposed by the ddtrace_profiling_loader extension to load the actual
6
+ # 2. Use the Datadog::Profiling::Loader exposed by the datadog_profiling_loader extension to load the actual
7
7
  # profiling native extension.
8
8
  #
9
9
  # All code on this file is on-purpose at the top-level; this makes it so this file is executed only once,
10
10
  # the first time it gets required, to avoid any issues with the native extension being initialized more than once.
11
11
 
12
12
  begin
13
- require "ddtrace_profiling_loader.#{RUBY_VERSION}_#{RUBY_PLATFORM}"
13
+ require "datadog_profiling_loader.#{RUBY_VERSION}_#{RUBY_PLATFORM}"
14
14
  rescue LoadError => e
15
15
  raise LoadError,
16
16
  'Failed to load the profiling loader extension. To fix this, please remove and then reinstall ddtrace ' \
17
17
  "(Details: #{e.message})"
18
18
  end
19
19
 
20
- extension_name = "ddtrace_profiling_native_extension.#{RUBY_VERSION}_#{RUBY_PLATFORM}"
21
- full_file_path = "#{__dir__}/../../#{extension_name}.#{RbConfig::CONFIG['DLEXT']}"
20
+ extension_name = "datadog_profiling_native_extension.#{RUBY_VERSION}_#{RUBY_PLATFORM}"
21
+ file_name = "#{extension_name}.#{RbConfig::CONFIG['DLEXT']}"
22
+ full_file_path = "#{__dir__}/../../#{file_name}"
23
+
24
+ unless File.exist?(full_file_path)
25
+ extension_dir = Gem.loaded_specs['ddtrace'].extension_dir
26
+ candidate_path = "#{extension_dir}/#{file_name}"
27
+ if File.exist?(candidate_path)
28
+ full_file_path = candidate_path
29
+ else # rubocop:disable Style/EmptyElse
30
+ # We found none of the files. This is unexpected. Let's go ahead anyway, the error is going to be reported further
31
+ # down anyway.
32
+ end
33
+ end
34
+
22
35
  init_function_name = "Init_#{extension_name.split('.').first}"
23
36
 
24
37
  status, result = Datadog::Profiling::Loader._native_load(full_file_path, init_function_name)
@@ -3,7 +3,7 @@
3
3
  module Datadog
4
4
  module Profiling
5
5
  # This module contains classes and methods which are implemented using native code in the
6
- # ext/ddtrace_profiling_native_extension folder, as well as some Ruby-level utilities that don't make sense to
6
+ # ext/datadog_profiling_native_extension folder, as well as some Ruby-level utilities that don't make sense to
7
7
  # write using C
8
8
  module NativeExtension
9
9
  private_class_method def self.working?
@@ -5,12 +5,11 @@ require_relative '../core/workers/polling'
5
5
 
6
6
  module Datadog
7
7
  module Profiling
8
- # Periodically (every DEFAULT_INTERVAL_SECONDS) takes a profile from the `Exporter` and reports it using the
8
+ # Periodically (every interval, 60 seconds by default) takes a profile from the `Exporter` and reports it using the
9
9
  # configured transport. Runs on its own background thread.
10
10
  class Scheduler < Core::Worker
11
11
  include Core::Workers::Polling
12
12
 
13
- DEFAULT_INTERVAL_SECONDS = 60
14
13
  MINIMUM_INTERVAL_SECONDS = 0
15
14
 
16
15
  # We sleep for at most this duration seconds before reporting data to avoid multi-process applications all
@@ -28,8 +27,7 @@ module Datadog
28
27
  def initialize(
29
28
  exporter:,
30
29
  transport:,
31
- fork_policy: Core::Workers::Async::Thread::FORK_POLICY_RESTART, # Restart in forks by default
32
- interval: DEFAULT_INTERVAL_SECONDS,
30
+ interval:, fork_policy: Core::Workers::Async::Thread::FORK_POLICY_RESTART, # Restart in forks by default, # seconds
33
31
  enabled: true
34
32
  )
35
33
  @exporter = exporter
@@ -115,8 +113,8 @@ module Datadog
115
113
  #
116
114
  # During PR review (https://github.com/DataDog/dd-trace-rb/pull/1807) we discussed the possible alternative of
117
115
  # just sleeping before starting the scheduler loop. We ended up not going with that option to avoid the first
118
- # profile containing up to DEFAULT_INTERVAL_SECONDS + DEFAULT_FLUSH_JITTER_MAXIMUM_SECONDS instead of the
119
- # usual DEFAULT_INTERVAL_SECONDS size.
116
+ # profile containing up to interval + DEFAULT_FLUSH_JITTER_MAXIMUM_SECONDS instead of the
117
+ # usual interval seconds.
120
118
  if run_loop?
121
119
  jitter_seconds = rand * DEFAULT_FLUSH_JITTER_MAXIMUM_SECONDS # floating point number between (0.0...maximum)
122
120
  sleep(jitter_seconds)