ddtrace 1.18.0 → 1.23.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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)