datadog 2.2.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +51 -2
  3. data/ext/datadog_profiling_loader/extconf.rb +15 -15
  4. data/ext/datadog_profiling_native_extension/clock_id.h +1 -0
  5. data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +1 -2
  6. data/ext/datadog_profiling_native_extension/clock_id_noop.c +1 -2
  7. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +113 -43
  8. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +49 -26
  9. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +34 -4
  10. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +4 -0
  11. data/ext/datadog_profiling_native_extension/collectors_stack.c +49 -37
  12. data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
  13. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +81 -19
  14. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +1 -0
  15. data/ext/datadog_profiling_native_extension/datadog_ruby_common.c +110 -0
  16. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +57 -0
  17. data/ext/datadog_profiling_native_extension/extconf.rb +65 -60
  18. data/ext/datadog_profiling_native_extension/heap_recorder.c +34 -6
  19. data/ext/datadog_profiling_native_extension/heap_recorder.h +3 -1
  20. data/ext/datadog_profiling_native_extension/helpers.h +6 -17
  21. data/ext/datadog_profiling_native_extension/http_transport.c +3 -3
  22. data/ext/datadog_profiling_native_extension/libdatadog_helpers.c +0 -86
  23. data/ext/datadog_profiling_native_extension/libdatadog_helpers.h +2 -23
  24. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +61 -172
  25. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +64 -138
  26. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +17 -11
  27. data/ext/datadog_profiling_native_extension/profiling.c +0 -2
  28. data/ext/datadog_profiling_native_extension/ruby_helpers.c +0 -33
  29. data/ext/datadog_profiling_native_extension/ruby_helpers.h +1 -26
  30. data/ext/datadog_profiling_native_extension/setup_signal_handler.h +1 -0
  31. data/ext/datadog_profiling_native_extension/stack_recorder.c +14 -2
  32. data/ext/datadog_profiling_native_extension/stack_recorder.h +1 -0
  33. data/ext/datadog_profiling_native_extension/time_helpers.c +0 -15
  34. data/ext/datadog_profiling_native_extension/time_helpers.h +36 -6
  35. data/ext/{datadog_profiling_native_extension → libdatadog_api}/crashtracker.c +19 -6
  36. data/ext/libdatadog_api/datadog_ruby_common.c +110 -0
  37. data/ext/libdatadog_api/datadog_ruby_common.h +57 -0
  38. data/ext/libdatadog_api/extconf.rb +108 -0
  39. data/ext/libdatadog_api/macos_development.md +26 -0
  40. data/ext/libdatadog_extconf_helpers.rb +130 -0
  41. data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +49 -0
  42. data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +73 -0
  43. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +68 -0
  44. data/lib/datadog/appsec/contrib/graphql/integration.rb +41 -0
  45. data/lib/datadog/appsec/contrib/graphql/patcher.rb +37 -0
  46. data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +59 -0
  47. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +1 -1
  48. data/lib/datadog/appsec/processor/actions.rb +1 -1
  49. data/lib/datadog/appsec/response.rb +15 -1
  50. data/lib/datadog/appsec.rb +1 -0
  51. data/lib/datadog/core/configuration/components.rb +14 -12
  52. data/lib/datadog/core/configuration/settings.rb +54 -7
  53. data/lib/datadog/core/crashtracking/agent_base_url.rb +21 -0
  54. data/lib/datadog/core/crashtracking/component.rb +111 -0
  55. data/lib/datadog/core/crashtracking/tag_builder.rb +39 -0
  56. data/lib/datadog/core/diagnostics/environment_logger.rb +8 -11
  57. data/lib/datadog/core/telemetry/component.rb +49 -2
  58. data/lib/datadog/core/telemetry/emitter.rb +9 -11
  59. data/lib/datadog/core/telemetry/event.rb +32 -1
  60. data/lib/datadog/core/telemetry/ext.rb +1 -0
  61. data/lib/datadog/core/telemetry/http/adapters/net.rb +10 -12
  62. data/lib/datadog/core/telemetry/http/ext.rb +3 -0
  63. data/lib/datadog/core/telemetry/http/transport.rb +38 -9
  64. data/lib/datadog/core/telemetry/logging.rb +35 -0
  65. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +102 -0
  66. data/lib/datadog/kit/appsec/events.rb +2 -4
  67. data/lib/datadog/opentelemetry/sdk/span_processor.rb +10 -0
  68. data/lib/datadog/opentelemetry/sdk/trace/span.rb +23 -0
  69. data/lib/datadog/profiling/collectors/code_provenance.rb +7 -7
  70. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +17 -17
  71. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +11 -13
  72. data/lib/datadog/profiling/collectors/info.rb +3 -3
  73. data/lib/datadog/profiling/collectors/thread_context.rb +4 -2
  74. data/lib/datadog/profiling/component.rb +69 -91
  75. data/lib/datadog/profiling/exporter.rb +3 -3
  76. data/lib/datadog/profiling/ext/dir_monkey_patches.rb +3 -3
  77. data/lib/datadog/profiling/ext.rb +21 -21
  78. data/lib/datadog/profiling/flush.rb +1 -1
  79. data/lib/datadog/profiling/http_transport.rb +8 -6
  80. data/lib/datadog/profiling/load_native_extension.rb +5 -5
  81. data/lib/datadog/profiling/preload.rb +1 -1
  82. data/lib/datadog/profiling/profiler.rb +5 -8
  83. data/lib/datadog/profiling/scheduler.rb +31 -25
  84. data/lib/datadog/profiling/tag_builder.rb +2 -2
  85. data/lib/datadog/profiling/tasks/exec.rb +5 -5
  86. data/lib/datadog/profiling/tasks/setup.rb +16 -35
  87. data/lib/datadog/profiling.rb +4 -5
  88. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +1 -0
  89. data/lib/datadog/tracing/contrib/ext.rb +14 -0
  90. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +1 -1
  91. data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +4 -1
  92. data/lib/datadog/tracing/contrib/lograge/patcher.rb +16 -0
  93. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +5 -0
  94. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +17 -13
  95. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +5 -0
  96. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +4 -1
  97. data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +28 -0
  98. data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +5 -1
  99. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +22 -10
  100. data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +5 -0
  101. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +4 -1
  102. data/lib/datadog/tracing/diagnostics/environment_logger.rb +14 -16
  103. data/lib/datadog/tracing/metadata/errors.rb +9 -1
  104. data/lib/datadog/tracing/metadata/ext.rb +4 -0
  105. data/lib/datadog/tracing/pipeline/span_filter.rb +2 -2
  106. data/lib/datadog/tracing/span.rb +9 -2
  107. data/lib/datadog/tracing/span_event.rb +41 -0
  108. data/lib/datadog/tracing/span_operation.rb +6 -2
  109. data/lib/datadog/tracing/transport/serializable_trace.rb +3 -0
  110. data/lib/datadog/version.rb +1 -1
  111. metadata +28 -10
  112. data/lib/datadog/profiling/crashtracker.rb +0 -91
  113. data/lib/datadog/profiling/ext/forking.rb +0 -98
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'trace/span'
4
4
  require_relative '../../tracing/span_link'
5
+ require_relative '../../tracing/span_event'
5
6
  require_relative '../../tracing/trace_digest'
6
7
 
7
8
  module Datadog
@@ -31,6 +32,15 @@ module Datadog
31
32
  #
32
33
  # @param [Span] span the {Span} that just ended.
33
34
  def on_finish(span)
35
+ unless span.events.nil?
36
+ span.datadog_span.span_events = span.events.map do |event|
37
+ Datadog::Tracing::SpanEvent.new(
38
+ event.name,
39
+ attributes: event.attributes,
40
+ time_unix_nano: event.timestamp
41
+ )
42
+ end
43
+ end
34
44
  span.datadog_span.finish(ns_to_time(span.end_timestamp))
35
45
  end
36
46
 
@@ -15,6 +15,29 @@ module Datadog
15
15
  res
16
16
  end
17
17
 
18
+ # Record an exception during the execution of this span. Multiple exceptions
19
+ # can be recorded on a span.
20
+ #
21
+ # @param [Exception] exception The exception to recorded
22
+ # @param [optional Hash{String => String, Numeric, Boolean, Array<String, Numeric, Boolean>}]
23
+ # attributes One or more key:value pairs, where the keys must be
24
+ # strings and the values may be (array of) string, boolean or numeric
25
+ # type.
26
+ #
27
+ # @return [void]
28
+ def record_exception(exception, attributes: nil)
29
+ res = super
30
+ if (span = datadog_span)
31
+ # Sets the exception attributes as span error tags. The values in the attribute hash MUST
32
+ # take precedence over the type, message and stacktrace inferred from the exception object
33
+ type = attributes&.[]('exception.type') || exception.class.to_s
34
+ message = attributes&.[]('exception.message') || exception.message
35
+ stacktrace = attributes&.[]('exception.stacktrace') || exception.full_message(highlight: false, order: :top)
36
+ span.set_error_tags([type, message, stacktrace])
37
+ end
38
+ res
39
+ end
40
+
18
41
  # `alias` performed to match {OpenTelemetry::SDK::Trace::Span} aliasing upstream
19
42
  alias []= set_attribute
20
43
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'set'
4
- require 'json'
3
+ require "set"
4
+ require "json"
5
5
 
6
6
  module Datadog
7
7
  module Profiling
@@ -14,7 +14,7 @@ module Datadog
14
14
  #
15
15
  # This class acts both as a collector (collecting data) as well as a recorder (records/serializes it)
16
16
  class CodeProvenance
17
- def initialize(standard_library_path: RbConfig::CONFIG.fetch('rubylibdir'))
17
+ def initialize(standard_library_path: RbConfig::CONFIG.fetch("rubylibdir"))
18
18
  @libraries_by_name = {}
19
19
  @libraries_by_path = {}
20
20
  @seen_files = Set.new
@@ -22,8 +22,8 @@ module Datadog
22
22
 
23
23
  record_library(
24
24
  Library.new(
25
- kind: 'standard library',
26
- name: 'stdlib',
25
+ kind: "standard library",
26
+ name: "stdlib",
27
27
  version: RUBY_VERSION,
28
28
  path: standard_library_path,
29
29
  )
@@ -79,7 +79,7 @@ module Datadog
79
79
  loaded_specs.each do |spec|
80
80
  next if libraries_by_name.key?(spec.name)
81
81
 
82
- record_library(Library.new(kind: 'library', name: spec.name, version: spec.version, path: spec.gem_dir))
82
+ record_library(Library.new(kind: "library", name: spec.name, version: spec.version, path: spec.gem_dir))
83
83
  recorded_library = true
84
84
  end
85
85
 
@@ -119,7 +119,7 @@ module Datadog
119
119
  end
120
120
 
121
121
  def to_json(arg = nil)
122
- { kind: @kind, name: @name, version: @version, paths: @paths }.to_json(arg)
122
+ {kind: @kind, name: @name, version: @version, paths: @paths}.to_json(arg)
123
123
  end
124
124
 
125
125
  def path
@@ -21,6 +21,7 @@ module Datadog
21
21
  thread_context_collector:,
22
22
  dynamic_sampling_rate_overhead_target_percentage:,
23
23
  allocation_profiling_enabled:,
24
+ allocation_counting_enabled:,
24
25
  # **NOTE**: This should only be used for testing; disabling the dynamic sampling rate will increase the
25
26
  # profiler overhead!
26
27
  dynamic_sampling_rate_enabled: true,
@@ -29,7 +30,7 @@ module Datadog
29
30
  )
30
31
  unless dynamic_sampling_rate_enabled
31
32
  Datadog.logger.warn(
32
- 'Profiling dynamic sampling rate disabled. This should only be used for testing, and will increase overhead!'
33
+ "Profiling dynamic sampling rate disabled. This should only be used for testing, and will increase overhead!"
33
34
  )
34
35
  end
35
36
 
@@ -42,6 +43,7 @@ module Datadog
42
43
  dynamic_sampling_rate_enabled,
43
44
  dynamic_sampling_rate_overhead_target_percentage,
44
45
  allocation_profiling_enabled,
46
+ allocation_counting_enabled,
45
47
  skip_idle_samples_for_testing,
46
48
  )
47
49
  @worker_thread = nil
@@ -54,27 +56,25 @@ module Datadog
54
56
 
55
57
  def start(on_failure_proc: nil)
56
58
  @start_stop_mutex.synchronize do
57
- return if @worker_thread && @worker_thread.alive?
59
+ return if @worker_thread&.alive?
58
60
 
59
61
  Datadog.logger.debug { "Starting thread for: #{self}" }
60
62
 
61
63
  @idle_sampling_helper.start
62
64
 
63
65
  @worker_thread = Thread.new do
64
- begin
65
- Thread.current.name = self.class.name
66
-
67
- self.class._native_sampling_loop(self)
68
-
69
- Datadog.logger.debug('CpuAndWallTimeWorker thread stopping cleanly')
70
- rescue Exception => e # rubocop:disable Lint/RescueException
71
- @failure_exception = e
72
- Datadog.logger.warn(
73
- 'CpuAndWallTimeWorker thread error. ' \
74
- "Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
75
- )
76
- on_failure_proc&.call
77
- end
66
+ Thread.current.name = self.class.name
67
+
68
+ self.class._native_sampling_loop(self)
69
+
70
+ Datadog.logger.debug("CpuAndWallTimeWorker thread stopping cleanly")
71
+ rescue Exception => e # rubocop:disable Lint/RescueException
72
+ @failure_exception = e
73
+ Datadog.logger.warn(
74
+ "CpuAndWallTimeWorker thread error. " \
75
+ "Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
76
+ )
77
+ on_failure_proc&.call
78
78
  end
79
79
  @worker_thread.name = self.class.name # Repeated from above to make sure thread gets named asap
80
80
  @worker_thread.thread_variable_set(:fork_safe, true)
@@ -85,7 +85,7 @@ module Datadog
85
85
 
86
86
  def stop
87
87
  @start_stop_mutex.synchronize do
88
- Datadog.logger.debug('Requesting CpuAndWallTimeWorker thread shut down')
88
+ Datadog.logger.debug("Requesting CpuAndWallTimeWorker thread shut down")
89
89
 
90
90
  @idle_sampling_helper.stop
91
91
 
@@ -21,7 +21,7 @@ module Datadog
21
21
 
22
22
  def start
23
23
  @start_stop_mutex.synchronize do
24
- return if @worker_thread && @worker_thread.alive?
24
+ return if @worker_thread&.alive?
25
25
 
26
26
  Datadog.logger.debug { "Starting thread for: #{self}" }
27
27
 
@@ -30,19 +30,17 @@ module Datadog
30
30
  self.class._native_reset(self)
31
31
 
32
32
  @worker_thread = Thread.new do
33
- begin
34
- Thread.current.name = self.class.name
33
+ Thread.current.name = self.class.name
35
34
 
36
- self.class._native_idle_sampling_loop(self)
35
+ self.class._native_idle_sampling_loop(self)
37
36
 
38
- Datadog.logger.debug('IdleSamplingHelper thread stopping cleanly')
39
- rescue Exception => e # rubocop:disable Lint/RescueException
40
- @failure_exception = e
41
- Datadog.logger.warn(
42
- 'IdleSamplingHelper thread error. ' \
43
- "Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
44
- )
45
- end
37
+ Datadog.logger.debug("IdleSamplingHelper thread stopping cleanly")
38
+ rescue Exception => e # rubocop:disable Lint/RescueException
39
+ @failure_exception = e
40
+ Datadog.logger.warn(
41
+ "IdleSamplingHelper thread error. " \
42
+ "Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
43
+ )
46
44
  end
47
45
  @worker_thread.name = self.class.name # Repeated from above to make sure thread gets named asap
48
46
  @worker_thread.thread_variable_set(:fork_safe, true)
@@ -53,7 +51,7 @@ module Datadog
53
51
 
54
52
  def stop
55
53
  @start_stop_mutex.synchronize do
56
- Datadog.logger.debug('Requesting IdleSamplingHelper thread shut down')
54
+ Datadog.logger.debug("Requesting IdleSamplingHelper thread shut down")
57
55
 
58
56
  return unless @worker_thread
59
57
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'set'
4
- require 'time'
3
+ require "set"
4
+ require "time"
5
5
 
6
6
  module Datadog
7
7
  module Profiling
@@ -61,7 +61,7 @@ module Datadog
61
61
 
62
62
  def collect_profiler_info(settings)
63
63
  unless @profiler_info
64
- lib_datadog_gem = ::Gem.loaded_specs['libdatadog']
64
+ lib_datadog_gem = ::Gem.loaded_specs["libdatadog"]
65
65
  @profiler_info = {
66
66
  # TODO: If profiling is extracted and its version diverges from the datadog gem, this is inaccurate.
67
67
  # Update if this ever occurs.
@@ -48,12 +48,14 @@ module Datadog
48
48
  private
49
49
 
50
50
  def safely_extract_context_key_from(tracer)
51
- provider = tracer && tracer.respond_to?(:provider) && tracer.provider
51
+ return unless tracer
52
+
53
+ provider = tracer.respond_to?(:provider) && tracer.provider
52
54
 
53
55
  return unless provider
54
56
 
55
57
  context = provider.instance_variable_get(:@context)
56
- context && context.instance_variable_get(:@key)
58
+ context&.instance_variable_get(:@key)
57
59
  end
58
60
  end
59
61
  end
@@ -8,7 +8,7 @@ module Datadog
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
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
11
+ return [nil, {profiling_enabled: false}] unless settings.profiling.enabled
12
12
 
13
13
  # Workaround for weird dependency direction: the Core::Configuration::Components class currently has a
14
14
  # dependency on individual products, in this case the Profiler.
@@ -27,9 +27,9 @@ module Datadog
27
27
  # On the other hand, if datadog/core is loaded by a different product and no general `require 'datadog'` is
28
28
  # done, then profiling may not be loaded, and thus to avoid this issue we do a require here (which is a
29
29
  # no-op if profiling is already loaded).
30
- require_relative '../profiling'
30
+ require_relative "../profiling"
31
31
 
32
- return [nil, { profiling_enabled: false }] unless Profiling.supported?
32
+ return [nil, {profiling_enabled: false}] unless Profiling.supported?
33
33
 
34
34
  # Activate forking extensions
35
35
  Profiling::Tasks::Setup.new.run
@@ -47,7 +47,7 @@ module Datadog
47
47
  upload_period_seconds = [60, settings.profiling.advanced.upload_period_seconds].max
48
48
 
49
49
  recorder = Datadog::Profiling::StackRecorder.new(
50
- cpu_time_enabled: RUBY_PLATFORM.include?('linux'), # Only supported on Linux currently
50
+ cpu_time_enabled: RUBY_PLATFORM.include?("linux"), # Only supported on Linux currently
51
51
  alloc_samples_enabled: allocation_profiling_enabled,
52
52
  heap_samples_enabled: heap_profiling_enabled,
53
53
  heap_size_enabled: heap_size_profiling_enabled,
@@ -61,6 +61,7 @@ module Datadog
61
61
  thread_context_collector: thread_context_collector,
62
62
  dynamic_sampling_rate_overhead_target_percentage: overhead_target_percentage,
63
63
  allocation_profiling_enabled: allocation_profiling_enabled,
64
+ allocation_counting_enabled: settings.profiling.advanced.allocation_counting_enabled,
64
65
  )
65
66
 
66
67
  internal_metadata = {
@@ -72,14 +73,13 @@ module Datadog
72
73
  exporter = build_profiler_exporter(settings, recorder, worker, internal_metadata: internal_metadata)
73
74
  transport = build_profiler_transport(settings, agent_settings)
74
75
  scheduler = Profiling::Scheduler.new(exporter: exporter, transport: transport, interval: upload_period_seconds)
75
- crashtracker = build_crashtracker(settings, transport)
76
- profiler = Profiling::Profiler.new(worker: worker, scheduler: scheduler, optional_crashtracker: crashtracker)
76
+ profiler = Profiling::Profiler.new(worker: worker, scheduler: scheduler)
77
77
 
78
78
  if dir_interruption_workaround_enabled?(settings, no_signals_workaround_enabled)
79
79
  Datadog::Profiling::Ext::DirMonkeyPatches.apply!
80
80
  end
81
81
 
82
- [profiler, { profiling_enabled: true }]
82
+ [profiler, {profiling_enabled: true}]
83
83
  end
84
84
 
85
85
  private_class_method def self.build_thread_context_collector(settings, recorder, optional_tracer, timeline_enabled)
@@ -116,28 +116,6 @@ module Datadog
116
116
  )
117
117
  end
118
118
 
119
- private_class_method def self.build_crashtracker(settings, transport)
120
- return unless settings.profiling.advanced.experimental_crash_tracking_enabled
121
-
122
- # By default, the transport is an instance of HttpTransport, which validates the configuration and makes
123
- # it available for us to use here.
124
- # But we support overriding the transport with a user-specific one, which may e.g. write stuff to a file,
125
- # and thus can't really provide a valid configuration to talk to a Datadog agent. Thus, in this situation,
126
- # we can't use the crashtracker, even if enabled.
127
- unless transport.respond_to?(:exporter_configuration)
128
- Datadog.logger.warn(
129
- 'Cannot enable profiling crash tracking as a custom settings.profiling.exporter.transport is configured'
130
- )
131
- return
132
- end
133
-
134
- Datadog::Profiling::Crashtracker.new(
135
- exporter_configuration: transport.exporter_configuration,
136
- tags: Datadog::Profiling::TagBuilder.call(settings: settings),
137
- upload_timeout_seconds: settings.profiling.upload.timeout_seconds,
138
- )
139
- end
140
-
141
119
  private_class_method def self.enable_gc_profiling?(settings)
142
120
  return false unless settings.profiling.advanced.gc_enabled
143
121
 
@@ -146,19 +124,19 @@ module Datadog
146
124
  # that causes a segmentation fault during garbage collection of Ractors
147
125
  # (https://bugs.ruby-lang.org/issues/18464). We don't allow enabling gc profiling on such Rubies.
148
126
  # This bug is fixed on Ruby versions 3.1.4, 3.2.3 and 3.3.0.
149
- if RUBY_VERSION.start_with?('3.0.') ||
150
- (RUBY_VERSION.start_with?('3.1.') && RUBY_VERSION < '3.1.4') ||
151
- (RUBY_VERSION.start_with?('3.2.') && RUBY_VERSION < '3.2.3')
127
+ if RUBY_VERSION.start_with?("3.0.") ||
128
+ (RUBY_VERSION.start_with?("3.1.") && RUBY_VERSION < "3.1.4") ||
129
+ (RUBY_VERSION.start_with?("3.2.") && RUBY_VERSION < "3.2.3")
152
130
  Datadog.logger.warn(
153
- "Current Ruby version (#{RUBY_VERSION}) has a VM bug where enabling GC profiling would cause "\
154
- 'crashes (https://bugs.ruby-lang.org/issues/18464). GC profiling has been disabled.'
131
+ "Current Ruby version (#{RUBY_VERSION}) has a VM bug where enabling GC profiling would cause " \
132
+ "crashes (https://bugs.ruby-lang.org/issues/18464). GC profiling has been disabled."
155
133
  )
156
134
  return false
157
- elsif RUBY_VERSION.start_with?('3.')
135
+ elsif RUBY_VERSION.start_with?("3.")
158
136
  Datadog.logger.debug(
159
- 'In all known versions of Ruby 3.x, using Ractors may result in GC profiling unexpectedly ' \
160
- 'stopping (https://bugs.ruby-lang.org/issues/19112). Note that this stop has no impact in your ' \
161
- 'application stability or performance. This does not happen if Ractors are not used.'
137
+ "In all known versions of Ruby 3.x, using Ractors may result in GC profiling unexpectedly " \
138
+ "stopping (https://bugs.ruby-lang.org/issues/19112). Note that this stop has no impact in your " \
139
+ "application stability or performance. This does not happen if Ractors are not used."
162
140
  )
163
141
  end
164
142
 
@@ -182,11 +160,11 @@ module Datadog
182
160
  # Ruby 3.2.0 to 3.2.2 have a bug in the newobj tracepoint (https://bugs.ruby-lang.org/issues/19482,
183
161
  # https://github.com/ruby/ruby/pull/7464) that makes this crash in any configuration. This bug is
184
162
  # fixed on Ruby versions 3.2.3 and 3.3.0.
185
- if RUBY_VERSION.start_with?('3.2.') && RUBY_VERSION < '3.2.3'
163
+ if RUBY_VERSION.start_with?("3.2.") && RUBY_VERSION < "3.2.3"
186
164
  Datadog.logger.warn(
187
- 'Allocation profiling is not supported in Ruby versions 3.2.0, 3.2.1 and 3.2.2 and will be forcibly '\
188
- 'disabled. This is due to a VM bug that can lead to crashes (https://bugs.ruby-lang.org/issues/19482). '\
189
- 'Other Ruby versions do not suffer from this issue.'
165
+ "Allocation profiling is not supported in Ruby versions 3.2.0, 3.2.1 and 3.2.2 and will be forcibly " \
166
+ "disabled. This is due to a VM bug that can lead to crashes (https://bugs.ruby-lang.org/issues/19482). " \
167
+ "Other Ruby versions do not suffer from this issue."
190
168
  )
191
169
  return false
192
170
  end
@@ -196,26 +174,26 @@ module Datadog
196
174
  # that causes a segmentation fault during garbage collection of Ractors
197
175
  # (https://bugs.ruby-lang.org/issues/18464). We don't recommend using this feature on such Rubies.
198
176
  # This bug is fixed on Ruby versions 3.1.4, 3.2.3 and 3.3.0.
199
- if RUBY_VERSION.start_with?('3.0.') ||
200
- (RUBY_VERSION.start_with?('3.1.') && RUBY_VERSION < '3.1.4') ||
201
- (RUBY_VERSION.start_with?('3.2.') && RUBY_VERSION < '3.2.3')
177
+ if RUBY_VERSION.start_with?("3.0.") ||
178
+ (RUBY_VERSION.start_with?("3.1.") && RUBY_VERSION < "3.1.4") ||
179
+ (RUBY_VERSION.start_with?("3.2.") && RUBY_VERSION < "3.2.3")
202
180
  Datadog.logger.warn(
203
- "Current Ruby version (#{RUBY_VERSION}) has a VM bug where enabling allocation profiling while using "\
204
- 'Ractors may cause unexpected issues, including crashes (https://bugs.ruby-lang.org/issues/18464). '\
205
- 'This does not happen if Ractors are not used.'
181
+ "Current Ruby version (#{RUBY_VERSION}) has a VM bug where enabling allocation profiling while using " \
182
+ "Ractors may cause unexpected issues, including crashes (https://bugs.ruby-lang.org/issues/18464). " \
183
+ "This does not happen if Ractors are not used."
206
184
  )
207
185
  # ANNOYANCE - Only with Ractors
208
186
  # On all known versions of Ruby 3.x, due to https://bugs.ruby-lang.org/issues/19112, when a ractor gets
209
187
  # garbage collected, Ruby will disable all active tracepoints, which this feature internally relies on.
210
- elsif RUBY_VERSION.start_with?('3.')
188
+ elsif RUBY_VERSION.start_with?("3.")
211
189
  Datadog.logger.warn(
212
- 'In all known versions of Ruby 3.x, using Ractors may result in allocation profiling unexpectedly ' \
213
- 'stopping (https://bugs.ruby-lang.org/issues/19112). Note that this stop has no impact in your ' \
214
- 'application stability or performance. This does not happen if Ractors are not used.'
190
+ "In all known versions of Ruby 3.x, using Ractors may result in allocation profiling unexpectedly " \
191
+ "stopping (https://bugs.ruby-lang.org/issues/19112). Note that this stop has no impact in your " \
192
+ "application stability or performance. This does not happen if Ractors are not used."
215
193
  )
216
194
  end
217
195
 
218
- Datadog.logger.debug('Enabled allocation profiling')
196
+ Datadog.logger.debug("Enabled allocation profiling")
219
197
 
220
198
  true
221
199
  end
@@ -225,33 +203,33 @@ module Datadog
225
203
 
226
204
  return false unless heap_profiling_enabled
227
205
 
228
- if RUBY_VERSION.start_with?('2.') && RUBY_VERSION < '2.7'
206
+ if RUBY_VERSION.start_with?("2.") && RUBY_VERSION < "2.7"
229
207
  Datadog.logger.warn(
230
- 'Heap profiling currently relies on features introduced in Ruby 2.7 and will be forcibly disabled. '\
231
- 'Please upgrade to Ruby >= 2.7 in order to use this feature.'
208
+ "Heap profiling currently relies on features introduced in Ruby 2.7 and will be forcibly disabled. " \
209
+ "Please upgrade to Ruby >= 2.7 in order to use this feature."
232
210
  )
233
211
  return false
234
212
  end
235
213
 
236
- if RUBY_VERSION < '3.1'
214
+ if RUBY_VERSION < "3.1"
237
215
  Datadog.logger.debug(
238
216
  "Current Ruby version (#{RUBY_VERSION}) supports forced object recycling which has a bug that the " \
239
- 'heap profiler is forced to work around to remain accurate. This workaround requires force-setting '\
217
+ "heap profiler is forced to work around to remain accurate. This workaround requires force-setting " \
240
218
  "the SEEN_OBJ_ID flag on objects that should have it but don't. Full details can be found in " \
241
- 'https://github.com/DataDog/dd-trace-rb/pull/3360. This workaround should be safe but can be ' \
242
- 'bypassed by disabling the heap profiler or upgrading to Ruby >= 3.1 where forced object recycling ' \
243
- 'was completely removed (https://bugs.ruby-lang.org/issues/18290).'
219
+ "https://github.com/DataDog/dd-trace-rb/pull/3360. This workaround should be safe but can be " \
220
+ "bypassed by disabling the heap profiler or upgrading to Ruby >= 3.1 where forced object recycling " \
221
+ "was completely removed (https://bugs.ruby-lang.org/issues/18290)."
244
222
  )
245
223
  end
246
224
 
247
225
  unless allocation_profiling_enabled
248
226
  raise ArgumentError,
249
- 'Heap profiling requires allocation profiling to be enabled'
227
+ "Heap profiling requires allocation profiling to be enabled"
250
228
  end
251
229
 
252
230
  Datadog.logger.warn(
253
231
  "Enabled experimental heap profiling: heap_sample_rate=#{heap_sample_rate}. This is experimental, not " \
254
- 'recommended, and will increase overhead!'
232
+ "recommended, and will increase overhead!"
255
233
  )
256
234
 
257
235
  true
@@ -263,7 +241,7 @@ module Datadog
263
241
  return false unless heap_profiling_enabled && heap_size_profiling_enabled
264
242
 
265
243
  Datadog.logger.warn(
266
- 'Enabled experimental heap size profiling. This is experimental, not recommended, and will increase overhead!'
244
+ "Enabled experimental heap size profiling. This is experimental, not recommended, and will increase overhead!"
267
245
  )
268
246
 
269
247
  true
@@ -271,12 +249,12 @@ module Datadog
271
249
 
272
250
  private_class_method def self.no_signals_workaround_enabled?(settings) # rubocop:disable Metrics/MethodLength
273
251
  setting_value = settings.profiling.advanced.no_signals_workaround_enabled
274
- legacy_ruby_that_should_use_workaround = RUBY_VERSION.start_with?('2.5.')
252
+ legacy_ruby_that_should_use_workaround = RUBY_VERSION.start_with?("2.5.")
275
253
 
276
254
  unless [true, false, :auto].include?(setting_value)
277
255
  Datadog.logger.error(
278
256
  "Ignoring invalid value for profiling no_signals_workaround_enabled setting: #{setting_value.inspect}. " \
279
- 'Valid options are `true`, `false` or (default) `:auto`.'
257
+ "Valid options are `true`, `false` or (default) `:auto`."
280
258
  )
281
259
 
282
260
  setting_value = :auto
@@ -286,10 +264,10 @@ module Datadog
286
264
  if legacy_ruby_that_should_use_workaround
287
265
  Datadog.logger.warn(
288
266
  'The profiling "no signals" workaround has been disabled via configuration on a legacy Ruby version ' \
289
- '(< 2.6). This is not recommended ' \
290
- 'in production environments, as due to limitations in Ruby APIs, we suspect it may lead to crashes ' \
291
- 'in very rare situations. Please report any issues you run into to Datadog support or ' \
292
- 'via <https://github.com/datadog/dd-trace-rb/issues/new>!'
267
+ "(< 2.6). This is not recommended " \
268
+ "in production environments, as due to limitations in Ruby APIs, we suspect it may lead to crashes " \
269
+ "in very rare situations. Please report any issues you run into to Datadog support or " \
270
+ "via <https://github.com/datadog/dd-trace-rb/issues/new>!"
293
271
  )
294
272
  else
295
273
  Datadog.logger.warn('Profiling "no signals" workaround disabled via configuration')
@@ -311,30 +289,30 @@ module Datadog
311
289
  # We don't warn users in this situation because "upgrade your Ruby" is not a great warning
312
290
  return true if legacy_ruby_that_should_use_workaround
313
291
 
314
- if Gem.loaded_specs['mysql2'] && incompatible_libmysqlclient_version?(settings)
292
+ if Gem.loaded_specs["mysql2"] && incompatible_libmysqlclient_version?(settings)
315
293
  Datadog.logger.warn(
316
294
  'Enabling the profiling "no signals" workaround because an incompatible version of the mysql2 gem is ' \
317
- 'installed. Profiling data will have lower quality. ' \
318
- 'To fix this, upgrade the libmysqlclient in your OS image to version 8.0.0 or above.'
295
+ "installed. Profiling data will have lower quality. " \
296
+ "To fix this, upgrade the libmysqlclient in your OS image to version 8.0.0 or above."
319
297
  )
320
298
  return true
321
299
  end
322
300
 
323
- if Gem.loaded_specs['rugged']
301
+ if Gem.loaded_specs["rugged"]
324
302
  Datadog.logger.warn(
325
303
  'Enabling the profiling "no signals" workaround because the rugged gem is installed. ' \
326
- 'This is needed because some operations on this gem are currently incompatible with the normal working mode ' \
327
- 'of the profiler, as detailed in <https://github.com/datadog/dd-trace-rb/issues/2721>. ' \
328
- 'Profiling data will have lower quality.'
304
+ "This is needed because some operations on this gem are currently incompatible with the normal working mode " \
305
+ "of the profiler, as detailed in <https://github.com/datadog/dd-trace-rb/issues/2721>. " \
306
+ "Profiling data will have lower quality."
329
307
  )
330
308
  return true
331
309
  end
332
310
 
333
- if (defined?(::PhusionPassenger) || Gem.loaded_specs['passenger']) && incompatible_passenger_version?
311
+ if (defined?(::PhusionPassenger) || Gem.loaded_specs["passenger"]) && incompatible_passenger_version?
334
312
  Datadog.logger.warn(
335
313
  'Enabling the profiling "no signals" workaround because an incompatible version of the passenger gem is ' \
336
- 'installed. Profiling data will have lower quality.' \
337
- 'To fix this, upgrade the passenger gem to version 6.0.19 or above.'
314
+ "installed. Profiling data will have lower quality." \
315
+ "To fix this, upgrade the passenger gem to version 6.0.19 or above."
338
316
  )
339
317
  return true
340
318
  end
@@ -355,11 +333,11 @@ module Datadog
355
333
  return true if settings.profiling.advanced.skip_mysql2_check
356
334
 
357
335
  Datadog.logger.debug(
358
- 'Requiring `mysql2` to check if the `libmysqlclient` version it uses is compatible with profiling'
336
+ "Requiring `mysql2` to check if the `libmysqlclient` version it uses is compatible with profiling"
359
337
  )
360
338
 
361
339
  begin
362
- require 'mysql2'
340
+ require "mysql2"
363
341
 
364
342
  # The mysql2-aurora gem likes to monkey patch itself in replacement of Mysql2::Client, and uses
365
343
  # `method_missing` to delegate to the original BUT unfortunately does not implement `respond_to_missing?` and
@@ -380,18 +358,18 @@ module Datadog
380
358
  libmysqlclient_version = Gem::Version.new(info[:version])
381
359
 
382
360
  compatible =
383
- libmysqlclient_version >= Gem::Version.new('8.0.0') ||
361
+ libmysqlclient_version >= Gem::Version.new("8.0.0") ||
384
362
  looks_like_mariadb?(info, libmysqlclient_version)
385
363
 
386
364
  Datadog.logger.debug(
387
- "The `mysql2` gem is using #{compatible ? 'a compatible' : 'an incompatible'} version of " \
365
+ "The `mysql2` gem is using #{compatible ? "a compatible" : "an incompatible"} version of " \
388
366
  "the `libmysqlclient` library (#{libmysqlclient_version})"
389
367
  )
390
368
 
391
369
  !compatible
392
370
  rescue StandardError, LoadError => e
393
371
  Datadog.logger.warn(
394
- 'Failed to probe `mysql2` gem information. ' \
372
+ "Failed to probe `mysql2` gem information. " \
395
373
  "Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
396
374
  )
397
375
 
@@ -401,10 +379,10 @@ module Datadog
401
379
 
402
380
  # See https://github.com/datadog/dd-trace-rb/issues/2976 for details.
403
381
  private_class_method def self.incompatible_passenger_version?
404
- first_compatible_version = Gem::Version.new('6.0.19')
382
+ first_compatible_version = Gem::Version.new("6.0.19")
405
383
 
406
- if Gem.loaded_specs['passenger']
407
- Gem.loaded_specs['passenger'].version < first_compatible_version
384
+ if Gem.loaded_specs["passenger"]
385
+ Gem.loaded_specs["passenger"].version < first_compatible_version
408
386
  elsif defined?(PhusionPassenger::VERSION_STRING)
409
387
  Gem::Version.new(PhusionPassenger::VERSION_STRING) < first_compatible_version
410
388
  else
@@ -417,7 +395,7 @@ module Datadog
417
395
  overhead_target_percentage
418
396
  else
419
397
  Datadog.logger.error(
420
- 'Ignoring invalid value for profiling overhead_target_percentage setting: ' \
398
+ "Ignoring invalid value for profiling overhead_target_percentage setting: " \
421
399
  "#{overhead_target_percentage.inspect}. Falling back to default value."
422
400
  )
423
401
 
@@ -450,8 +428,8 @@ module Datadog
450
428
  header_version = Gem::Version.new(info[:header_version]) if info[:header_version]
451
429
 
452
430
  !!(header_version &&
453
- libmysqlclient_version < Gem::Version.new('5.0.0') &&
454
- header_version >= Gem::Version.new('10.0.0'))
431
+ libmysqlclient_version < Gem::Version.new("5.0.0") &&
432
+ header_version >= Gem::Version.new("10.0.0"))
455
433
  end
456
434
 
457
435
  private_class_method def self.dir_interruption_workaround_enabled?(settings, no_signals_workaround_enabled)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'ext'
4
- require_relative 'tag_builder'
3
+ require_relative "ext"
4
+ require_relative "tag_builder"
5
5
 
6
6
  module Datadog
7
7
  module Profiling
@@ -61,7 +61,7 @@ module Datadog
61
61
  @last_flush_finish_at = finish
62
62
 
63
63
  if duration_below_threshold?(start, finish)
64
- Datadog.logger.debug('Skipped exporting profiling events as profile duration is below minimum')
64
+ Datadog.logger.debug("Skipped exporting profiling events as profile duration is below minimum")
65
65
  return
66
66
  end
67
67