ddtrace 1.6.1 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +89 -2
  3. data/README.md +2 -2
  4. data/ext/ddtrace_profiling_loader/extconf.rb +5 -2
  5. data/ext/ddtrace_profiling_native_extension/NativeExtensionDesign.md +1 -1
  6. data/ext/ddtrace_profiling_native_extension/clock_id_from_pthread.c +3 -2
  7. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.c +81 -47
  8. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.h +1 -1
  9. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +332 -125
  10. data/ext/ddtrace_profiling_native_extension/collectors_dynamic_sampling_rate.c +142 -0
  11. data/ext/ddtrace_profiling_native_extension/collectors_dynamic_sampling_rate.h +14 -0
  12. data/ext/ddtrace_profiling_native_extension/collectors_idle_sampling_helper.c +241 -0
  13. data/ext/ddtrace_profiling_native_extension/collectors_idle_sampling_helper.h +3 -0
  14. data/ext/ddtrace_profiling_native_extension/collectors_stack.c +11 -13
  15. data/ext/ddtrace_profiling_native_extension/extconf.rb +22 -8
  16. data/ext/ddtrace_profiling_native_extension/helpers.h +5 -0
  17. data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +8 -0
  18. data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +111 -26
  19. data/ext/ddtrace_profiling_native_extension/private_vm_api_access.h +9 -0
  20. data/ext/ddtrace_profiling_native_extension/profiling.c +205 -0
  21. data/ext/ddtrace_profiling_native_extension/ruby_helpers.c +86 -0
  22. data/ext/ddtrace_profiling_native_extension/ruby_helpers.h +28 -6
  23. data/ext/ddtrace_profiling_native_extension/setup_signal_handler.c +115 -0
  24. data/ext/ddtrace_profiling_native_extension/setup_signal_handler.h +11 -0
  25. data/ext/ddtrace_profiling_native_extension/stack_recorder.c +84 -35
  26. data/ext/ddtrace_profiling_native_extension/stack_recorder.h +1 -0
  27. data/ext/ddtrace_profiling_native_extension/time_helpers.c +17 -0
  28. data/ext/ddtrace_profiling_native_extension/time_helpers.h +10 -0
  29. data/lib/datadog/appsec/assets/blocked.html +98 -3
  30. data/lib/datadog/appsec/assets/blocked.json +1 -0
  31. data/lib/datadog/appsec/assets/blocked.text +5 -0
  32. data/lib/datadog/appsec/assets/waf_rules/recommended.json +35 -46
  33. data/lib/datadog/appsec/assets/waf_rules/risky.json +1 -1
  34. data/lib/datadog/appsec/assets/waf_rules/strict.json +46 -1
  35. data/lib/datadog/appsec/assets.rb +2 -2
  36. data/lib/datadog/appsec/configuration/settings.rb +6 -0
  37. data/lib/datadog/appsec/configuration.rb +4 -0
  38. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +4 -8
  39. data/lib/datadog/appsec/contrib/rack/request.rb +17 -0
  40. data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +2 -2
  41. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +2 -2
  42. data/lib/datadog/appsec/contrib/rails/patcher.rb +3 -6
  43. data/lib/datadog/appsec/contrib/sinatra/ext.rb +1 -0
  44. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +1 -1
  45. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +11 -8
  46. data/lib/datadog/appsec/extensions.rb +10 -0
  47. data/lib/datadog/appsec/processor.rb +18 -0
  48. data/lib/datadog/appsec/response.rb +54 -0
  49. data/lib/datadog/core/configuration/components.rb +27 -6
  50. data/lib/datadog/core/configuration/ext.rb +18 -0
  51. data/lib/datadog/core/configuration/settings.rb +14 -341
  52. data/lib/datadog/core/diagnostics/health.rb +4 -22
  53. data/lib/datadog/core/environment/variable_helpers.rb +58 -10
  54. data/lib/datadog/core/runtime/ext.rb +1 -1
  55. data/lib/datadog/core/utils.rb +0 -21
  56. data/lib/datadog/core.rb +21 -1
  57. data/lib/datadog/opentracer/distributed_headers.rb +7 -9
  58. data/lib/datadog/opentracer/rack_propagator.rb +0 -3
  59. data/lib/datadog/opentracer/text_map_propagator.rb +5 -7
  60. data/lib/datadog/profiling/collectors/cpu_and_wall_time.rb +10 -4
  61. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +20 -5
  62. data/lib/datadog/profiling/collectors/dynamic_sampling_rate.rb +14 -0
  63. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +68 -0
  64. data/lib/datadog/profiling/collectors/old_stack.rb +7 -0
  65. data/lib/datadog/profiling/exporter.rb +5 -0
  66. data/lib/datadog/profiling/old_recorder.rb +8 -0
  67. data/lib/datadog/profiling/profiler.rb +7 -0
  68. data/lib/datadog/profiling/scheduler.rb +4 -7
  69. data/lib/datadog/profiling/stack_recorder.rb +36 -0
  70. data/lib/datadog/profiling/tasks/setup.rb +0 -7
  71. data/lib/datadog/profiling.rb +2 -0
  72. data/lib/datadog/tracing/configuration/ext.rb +33 -3
  73. data/lib/datadog/tracing/configuration/settings.rb +433 -0
  74. data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +4 -1
  75. data/lib/datadog/tracing/contrib/aws/ext.rb +1 -0
  76. data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +4 -1
  77. data/lib/datadog/tracing/contrib/dalli/ext.rb +1 -0
  78. data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +4 -0
  79. data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +5 -1
  80. data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +1 -0
  81. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +6 -1
  82. data/lib/datadog/tracing/contrib/ethon/ext.rb +1 -0
  83. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +5 -1
  84. data/lib/datadog/tracing/contrib/excon/ext.rb +1 -0
  85. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +5 -1
  86. data/lib/datadog/tracing/contrib/faraday/ext.rb +1 -0
  87. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +6 -1
  88. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +2 -1
  89. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +6 -12
  90. data/lib/datadog/tracing/contrib/grpc/distributed/fetcher.rb +27 -0
  91. data/lib/datadog/tracing/contrib/grpc/distributed/propagation.rb +43 -0
  92. data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
  93. data/lib/datadog/tracing/contrib/grpc/patcher.rb +0 -2
  94. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +6 -1
  95. data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +32 -0
  96. data/lib/datadog/tracing/contrib/http/distributed/propagation.rb +38 -0
  97. data/lib/datadog/tracing/contrib/http/ext.rb +1 -0
  98. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +6 -1
  99. data/lib/datadog/tracing/contrib/httpclient/ext.rb +1 -0
  100. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +6 -1
  101. data/lib/datadog/tracing/contrib/httprb/ext.rb +1 -0
  102. data/lib/datadog/tracing/contrib/kafka/consumer_event.rb +1 -0
  103. data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +1 -0
  104. data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +1 -0
  105. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +5 -1
  106. data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -0
  107. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +2 -0
  108. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +4 -1
  109. data/lib/datadog/tracing/contrib/mysql2/ext.rb +1 -0
  110. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +2 -2
  111. data/lib/datadog/tracing/contrib/patcher.rb +3 -2
  112. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +4 -1
  113. data/lib/datadog/tracing/contrib/pg/ext.rb +1 -0
  114. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +12 -2
  115. data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +4 -1
  116. data/lib/datadog/tracing/contrib/presto/ext.rb +1 -0
  117. data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +1 -0
  118. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +10 -12
  119. data/lib/datadog/tracing/contrib/que/tracer.rb +2 -0
  120. data/lib/datadog/tracing/contrib/racecar/events/batch.rb +4 -1
  121. data/lib/datadog/tracing/contrib/racecar/events/message.rb +4 -1
  122. data/lib/datadog/tracing/contrib/rack/middlewares.rb +2 -0
  123. data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +4 -1
  124. data/lib/datadog/tracing/contrib/redis/ext.rb +1 -0
  125. data/lib/datadog/tracing/contrib/redis/instrumentation.rb +30 -21
  126. data/lib/datadog/tracing/contrib/redis/integration.rb +34 -2
  127. data/lib/datadog/tracing/contrib/redis/patcher.rb +18 -14
  128. data/lib/datadog/tracing/contrib/redis/quantize.rb +12 -9
  129. data/lib/datadog/tracing/contrib/redis/tags.rb +4 -6
  130. data/lib/datadog/tracing/contrib/redis/trace_middleware.rb +72 -0
  131. data/lib/datadog/tracing/contrib/resque/resque_job.rb +2 -0
  132. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +6 -1
  133. data/lib/datadog/tracing/contrib/rest_client/ext.rb +1 -0
  134. data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +2 -0
  135. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +5 -0
  136. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +5 -0
  137. data/lib/datadog/tracing/contrib/sneakers/tracer.rb +2 -0
  138. data/lib/datadog/{core → tracing}/diagnostics/ext.rb +1 -6
  139. data/lib/datadog/tracing/diagnostics/health.rb +40 -0
  140. data/lib/datadog/tracing/distributed/b3_multi.rb +66 -0
  141. data/lib/datadog/tracing/distributed/b3_single.rb +66 -0
  142. data/lib/datadog/tracing/distributed/datadog.rb +153 -0
  143. data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +1 -0
  144. data/lib/datadog/tracing/distributed/fetcher.rb +30 -0
  145. data/lib/datadog/tracing/distributed/headers/ext.rb +18 -16
  146. data/lib/datadog/tracing/distributed/helpers.rb +9 -7
  147. data/lib/datadog/tracing/distributed/none.rb +19 -0
  148. data/lib/datadog/tracing/distributed/propagation.rb +127 -0
  149. data/lib/datadog/tracing/distributed/trace_context.rb +369 -0
  150. data/lib/datadog/tracing/metadata/ext.rb +1 -1
  151. data/lib/datadog/tracing/propagation/http.rb +3 -106
  152. data/lib/datadog/tracing/sampling/priority_sampler.rb +11 -0
  153. data/lib/datadog/tracing/sampling/rate_sampler.rb +3 -3
  154. data/lib/datadog/tracing/span.rb +3 -19
  155. data/lib/datadog/tracing/span_operation.rb +5 -4
  156. data/lib/datadog/tracing/trace_digest.rb +75 -2
  157. data/lib/datadog/tracing/trace_operation.rb +5 -4
  158. data/lib/datadog/tracing/trace_segment.rb +1 -1
  159. data/lib/datadog/tracing/utils.rb +50 -0
  160. data/lib/ddtrace/transport/trace_formatter.rb +2 -5
  161. data/lib/ddtrace/version.rb +2 -2
  162. metadata +35 -15
  163. data/lib/datadog/tracing/distributed/headers/b3.rb +0 -55
  164. data/lib/datadog/tracing/distributed/headers/b3_single.rb +0 -67
  165. data/lib/datadog/tracing/distributed/headers/datadog.rb +0 -144
  166. data/lib/datadog/tracing/distributed/headers/parser.rb +0 -37
  167. data/lib/datadog/tracing/distributed/metadata/b3.rb +0 -55
  168. data/lib/datadog/tracing/distributed/metadata/b3_single.rb +0 -66
  169. data/lib/datadog/tracing/distributed/metadata/datadog.rb +0 -73
  170. data/lib/datadog/tracing/distributed/metadata/parser.rb +0 -34
  171. data/lib/datadog/tracing/propagation/grpc.rb +0 -98
@@ -1,15 +1,13 @@
1
1
  # typed: true
2
2
 
3
- require_relative '../tracing/span'
4
- require_relative '../tracing/distributed/headers/ext'
3
+ require_relative '../tracing/distributed/datadog'
4
+ require_relative '../tracing/utils'
5
5
 
6
6
  module Datadog
7
7
  module OpenTracer
8
8
  # DistributedHeaders provides easy access and validation to headers
9
9
  # @public_api
10
10
  class DistributedHeaders
11
- include Tracing::Distributed::Headers::Ext
12
-
13
11
  def initialize(carrier)
14
12
  @carrier = carrier
15
13
  end
@@ -20,15 +18,15 @@ module Datadog
20
18
  end
21
19
 
22
20
  def trace_id
23
- id HTTP_HEADER_TRACE_ID
21
+ id Tracing::Distributed::Datadog::TRACE_ID_KEY
24
22
  end
25
23
 
26
24
  def parent_id
27
- id HTTP_HEADER_PARENT_ID
25
+ id Tracing::Distributed::Datadog::PARENT_ID_KEY
28
26
  end
29
27
 
30
28
  def sampling_priority
31
- hdr = @carrier[HTTP_HEADER_SAMPLING_PRIORITY]
29
+ hdr = @carrier[Tracing::Distributed::Datadog::SAMPLING_PRIORITY_KEY]
32
30
  # It's important to make a difference between no header,
33
31
  # and a header defined to zero.
34
32
  return unless hdr
@@ -40,7 +38,7 @@ module Datadog
40
38
  end
41
39
 
42
40
  def origin
43
- hdr = @carrier[HTTP_HEADER_ORIGIN]
41
+ hdr = @carrier[Tracing::Distributed::Datadog::ORIGIN_KEY]
44
42
  # Only return the value if it is not an empty string
45
43
  hdr if hdr != ''
46
44
  end
@@ -49,7 +47,7 @@ module Datadog
49
47
 
50
48
  def id(header)
51
49
  value = @carrier[header].to_i
52
- return if value.zero? || value >= Datadog::Tracing::Span::EXTERNAL_MAX_ID
50
+ return if value.zero? || value >= Datadog::Tracing::Utils::EXTERNAL_MAX_ID
53
51
 
54
52
  value < 0 ? value + 0x1_0000_0000_0000_0000 : value
55
53
  end
@@ -1,7 +1,6 @@
1
1
  # typed: true
2
2
 
3
3
  require_relative '../tracing/context'
4
- require_relative '../tracing/distributed/headers/ext'
5
4
  require_relative '../tracing/propagation/http'
6
5
  require_relative '../tracing/trace_operation'
7
6
  require_relative 'propagator'
@@ -11,8 +10,6 @@ module Datadog
11
10
  # OpenTracing propagator for Datadog::OpenTracer::Tracer
12
11
  module RackPropagator
13
12
  extend Propagator
14
- extend Tracing::Distributed::Headers::Ext
15
- include Tracing::Distributed::Headers::Ext
16
13
 
17
14
  BAGGAGE_PREFIX = 'ot-baggage-'.freeze
18
15
  BAGGAGE_PREFIX_FORMATTED = 'HTTP_OT_BAGGAGE_'.freeze
@@ -1,7 +1,7 @@
1
1
  # typed: true
2
2
 
3
3
  require_relative '../tracing/context'
4
- require_relative '../tracing/distributed/headers/ext'
4
+ require_relative '../tracing/distributed/datadog'
5
5
  require_relative '../tracing/trace_operation'
6
6
  require_relative 'propagator'
7
7
 
@@ -10,8 +10,6 @@ module Datadog
10
10
  # OpenTracing propagator for Datadog::OpenTracer::Tracer
11
11
  module TextMapPropagator
12
12
  extend Propagator
13
- extend Tracing::Distributed::Headers::Ext
14
- include Tracing::Distributed::Headers::Ext
15
13
 
16
14
  BAGGAGE_PREFIX = 'ot-baggage-'.freeze
17
15
 
@@ -34,10 +32,10 @@ module Datadog
34
32
  end
35
33
  return unless digest
36
34
 
37
- carrier[HTTP_HEADER_ORIGIN] = digest.trace_origin
38
- carrier[HTTP_HEADER_PARENT_ID] = digest.span_id
39
- carrier[HTTP_HEADER_SAMPLING_PRIORITY] = digest.trace_sampling_priority
40
- carrier[HTTP_HEADER_TRACE_ID] = digest.trace_id
35
+ carrier[Tracing::Distributed::Datadog::ORIGIN_KEY] = digest.trace_origin
36
+ carrier[Tracing::Distributed::Datadog::PARENT_ID_KEY] = digest.span_id
37
+ carrier[Tracing::Distributed::Datadog::SAMPLING_PRIORITY_KEY] = digest.trace_sampling_priority
38
+ carrier[Tracing::Distributed::Datadog::TRACE_ID_KEY] = digest.trace_id
41
39
 
42
40
  nil
43
41
  end
@@ -23,13 +23,19 @@ module Datadog
23
23
  result
24
24
  end
25
25
 
26
+ def reset_after_fork
27
+ self.class._native_reset_after_fork(self)
28
+ end
29
+
26
30
  private
27
31
 
28
32
  def safely_extract_context_key_from(tracer)
29
- tracer &&
30
- tracer.respond_to?(:provider) &&
31
- # NOTE: instance_variable_get always works, even on nil -- it just returns nil if the variable doesn't exist
32
- tracer.provider.instance_variable_get(:@context).instance_variable_get(:@key)
33
+ provider = tracer && tracer.respond_to?(:provider) && tracer.provider
34
+
35
+ return unless provider
36
+
37
+ context = provider.instance_variable_get(:@context)
38
+ context && context.instance_variable_get(:@key)
33
39
  end
34
40
  end
35
41
  end
@@ -20,12 +20,14 @@ module Datadog
20
20
  max_frames:,
21
21
  tracer:,
22
22
  gc_profiling_enabled:,
23
- cpu_and_wall_time_collector: CpuAndWallTime.new(recorder: recorder, max_frames: max_frames, tracer: tracer)
23
+ cpu_and_wall_time_collector: CpuAndWallTime.new(recorder: recorder, max_frames: max_frames, tracer: tracer),
24
+ idle_sampling_helper: IdleSamplingHelper.new
24
25
  )
25
- self.class._native_initialize(self, cpu_and_wall_time_collector, gc_profiling_enabled)
26
+ self.class._native_initialize(self, cpu_and_wall_time_collector, gc_profiling_enabled, idle_sampling_helper)
26
27
  @worker_thread = nil
27
28
  @failure_exception = nil
28
29
  @start_stop_mutex = Mutex.new
30
+ @idle_sampling_helper = idle_sampling_helper
29
31
  end
30
32
 
31
33
  def start
@@ -33,6 +35,9 @@ module Datadog
33
35
  return if @worker_thread && @worker_thread.alive?
34
36
 
35
37
  Datadog.logger.debug { "Starting thread for: #{self}" }
38
+
39
+ @idle_sampling_helper.start
40
+
36
41
  @worker_thread = Thread.new do
37
42
  begin
38
43
  Thread.current.name = self.class.name unless Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.3')
@@ -43,7 +48,8 @@ module Datadog
43
48
  rescue Exception => e # rubocop:disable Lint/RescueException
44
49
  @failure_exception = e
45
50
  Datadog.logger.warn(
46
- "Worker thread error. Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
51
+ 'CpuAndWallTimeWorker thread error. ' \
52
+ "Cause: #{e.class.name} #{e.message} Location: #{Array(e.backtrace).first}"
47
53
  )
48
54
  end
49
55
  end
@@ -60,16 +66,25 @@ module Datadog
60
66
  @start_stop_mutex.synchronize do
61
67
  Datadog.logger.debug('Requesting CpuAndWallTimeWorker thread shut down')
62
68
 
69
+ @idle_sampling_helper.stop
70
+
63
71
  return unless @worker_thread
64
72
 
65
- @worker_thread.kill
66
- self.class._native_stop(self)
73
+ self.class._native_stop(self, @worker_thread)
67
74
 
68
75
  @worker_thread.join
69
76
  @worker_thread = nil
70
77
  @failure_exception = nil
71
78
  end
72
79
  end
80
+
81
+ def reset_after_fork
82
+ self.class._native_reset_after_fork(self)
83
+ end
84
+
85
+ def stats
86
+ self.class._native_stats(self)
87
+ end
73
88
  end
74
89
  end
75
90
  end
@@ -0,0 +1,14 @@
1
+ # typed: false
2
+
3
+ module Datadog
4
+ module Profiling
5
+ module Collectors
6
+ # Used to pace the rate of profiling samples based on the last observed time for a sample.
7
+ # All of this module is implemented as native code.
8
+ #
9
+ # Methods prefixed with _native_ are implemented in `collectors_dynamic_sampling_rate.c`
10
+ module DynamicSamplingRate
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,68 @@
1
+ # typed: false
2
+
3
+ module Datadog
4
+ module Profiling
5
+ module Collectors
6
+ # Used by the Collectors::CpuAndWallTimeWorker to gather samples when the Ruby process is idle.
7
+ # Almost all of this class is implemented as native code.
8
+ #
9
+ # Methods prefixed with _native_ are implemented in `collectors_idle_sampling_helper.c`
10
+ class IdleSamplingHelper
11
+ private
12
+
13
+ attr_accessor :failure_exception
14
+
15
+ public
16
+
17
+ def initialize
18
+ @worker_thread = nil
19
+ @start_stop_mutex = Mutex.new
20
+ end
21
+
22
+ def start
23
+ @start_stop_mutex.synchronize do
24
+ return if @worker_thread && @worker_thread.alive?
25
+
26
+ Datadog.logger.debug { "Starting thread for: #{self}" }
27
+
28
+ # The same instance of the IdleSamplingHelper can be reused multiple times, and this resets it back to
29
+ # a pristine state before recreating the worker thread
30
+ self.class._native_reset(self)
31
+
32
+ @worker_thread = Thread.new do
33
+ begin
34
+ Thread.current.name = self.class.name unless Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.3')
35
+
36
+ self.class._native_idle_sampling_loop(self)
37
+
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
46
+ end
47
+ end
48
+
49
+ true
50
+ end
51
+
52
+ def stop(*_)
53
+ @start_stop_mutex.synchronize do
54
+ Datadog.logger.debug('Requesting IdleSamplingHelper thread shut down')
55
+
56
+ return unless @worker_thread
57
+
58
+ self.class._native_stop(self)
59
+
60
+ @worker_thread.join
61
+ @worker_thread = nil
62
+ @failure_exception = nil
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -218,6 +218,13 @@ module Datadog
218
218
  )
219
219
  end
220
220
 
221
+ def reset_after_fork
222
+ recorder.reset_after_fork
223
+
224
+ # NOTE: We could perhaps also call #reset_cpu_time_tracking here, although it's not needed because we always
225
+ # call in in #start.
226
+ end
227
+
221
228
  private
222
229
 
223
230
  # If the profiler is started for a while, stopped and then restarted OR whenever the process forks, we need to
@@ -70,6 +70,11 @@ module Datadog
70
70
  !duration_below_threshold?(last_flush_finish_at || created_at, time_provider.now.utc)
71
71
  end
72
72
 
73
+ def reset_after_fork
74
+ @last_flush_finish_at = time_provider.now.utc
75
+ nil
76
+ end
77
+
73
78
  private
74
79
 
75
80
  def duration_below_threshold?(start, finish)
@@ -73,6 +73,14 @@ module Datadog
73
73
  [start, finish, encoded_pprof]
74
74
  end
75
75
 
76
+ def reset_after_fork
77
+ Datadog.logger.debug('Resetting OldRecorder in child process after fork')
78
+
79
+ # NOTE: A bit of a heavy-handed approach, but it doesn't happen often and this class will be removed soon anyway
80
+ serialize
81
+ nil
82
+ end
83
+
76
84
  # Error when event of an unknown type is used with the OldRecorder
77
85
  class UnknownEventError < StandardError
78
86
  attr_reader :event_class
@@ -4,6 +4,8 @@ module Datadog
4
4
  module Profiling
5
5
  # Profiling entry point, which coordinates collectors and a scheduler
6
6
  class Profiler
7
+ include Datadog::Core::Utils::Forking
8
+
7
9
  attr_reader \
8
10
  :collectors,
9
11
  :scheduler
@@ -14,6 +16,11 @@ module Datadog
14
16
  end
15
17
 
16
18
  def start
19
+ after_fork! do
20
+ collectors.each(&:reset_after_fork)
21
+ scheduler.reset_after_fork
22
+ end
23
+
17
24
  collectors.each(&:start)
18
25
  scheduler.start
19
26
  end
@@ -66,13 +66,6 @@ module Datadog
66
66
  end
67
67
  end
68
68
 
69
- def after_fork
70
- # Clear any existing profiling state.
71
- # We don't want the child process to report profiling data from its parent.
72
- Datadog.logger.debug('Flushing exporter in child process #after_fork and discarding data')
73
- exporter.flush
74
- end
75
-
76
69
  # Configure Workers::IntervalLoop to not report immediately when scheduler starts
77
70
  #
78
71
  # When a scheduler gets created (or reset), we don't want it to immediately try to flush; we want it to wait for
@@ -86,6 +79,10 @@ module Datadog
86
79
  exporter.can_flush?
87
80
  end
88
81
 
82
+ def reset_after_fork
83
+ exporter.reset_after_fork
84
+ end
85
+
89
86
  private
90
87
 
91
88
  def flush_and_wait
@@ -34,10 +34,46 @@ module Datadog
34
34
  end
35
35
  end
36
36
 
37
+ def serialize!
38
+ status, result = @no_concurrent_synchronize_mutex.synchronize { self.class._native_serialize(self) }
39
+
40
+ if status == :ok
41
+ _start, _finish, encoded_pprof = result
42
+
43
+ encoded_pprof
44
+ else
45
+ error_message = result
46
+
47
+ raise("Failed to serialize profiling data: #{error_message}")
48
+ end
49
+ end
50
+
51
+ def clear
52
+ status, result = @no_concurrent_synchronize_mutex.synchronize { self.class._native_clear(self) }
53
+
54
+ if status == :ok
55
+ finish_timestamp = result
56
+
57
+ Datadog.logger.debug { "Cleared profile at #{finish_timestamp}" }
58
+
59
+ finish_timestamp
60
+ else
61
+ error_message = result
62
+
63
+ Datadog.logger.error("Failed to clear profiling data: #{error_message}")
64
+
65
+ nil
66
+ end
67
+ end
68
+
37
69
  # Used only for Ruby 2.2 which doesn't have the native `rb_time_timespec_new` API; called from native code
38
70
  def self.ruby_time_from(timespec_seconds, timespec_nanoseconds)
39
71
  Time.at(0).utc + timespec_seconds + (timespec_nanoseconds.to_r / 1_000_000_000)
40
72
  end
73
+
74
+ def reset_after_fork
75
+ self.class._native_reset_after_fork(self)
76
+ end
41
77
  end
42
78
  end
43
79
  end
@@ -55,13 +55,6 @@ module Datadog
55
55
  if Process.respond_to?(:at_fork)
56
56
  Process.at_fork(:child) do
57
57
  begin
58
- # When Ruby forks, clock IDs for each of the threads
59
- # will change. We can only update these IDs from the
60
- # execution context of the thread that owns it.
61
- # This hook will update the IDs for the main thread
62
- # after a fork occurs.
63
- Thread.current.send(:update_native_ids) if Thread.current.respond_to?(:update_native_ids, true)
64
-
65
58
  # Restart profiler, if enabled
66
59
  Profiling.start_if_enabled
67
60
  rescue StandardError => e
@@ -149,6 +149,8 @@ module Datadog
149
149
  require_relative 'profiling/collectors/code_provenance'
150
150
  require_relative 'profiling/collectors/cpu_and_wall_time'
151
151
  require_relative 'profiling/collectors/cpu_and_wall_time_worker'
152
+ require_relative 'profiling/collectors/dynamic_sampling_rate'
153
+ require_relative 'profiling/collectors/idle_sampling_helper'
152
154
  require_relative 'profiling/collectors/old_stack'
153
155
  require_relative 'profiling/collectors/stack'
154
156
  require_relative 'profiling/stack_recorder'
@@ -3,7 +3,11 @@
3
3
  module Datadog
4
4
  module Tracing
5
5
  module Configuration
6
+ # Constants for configuration settings
7
+ # e.g. Env vars, default values, enums, etc...
6
8
  module Ext
9
+ ENV_ENABLED = 'DD_TRACE_ENABLED'.freeze
10
+
7
11
  # @public_api
8
12
  module Analytics
9
13
  ENV_TRACE_ANALYTICS_ENABLED = 'DD_TRACE_ANALYTICS_ENABLED'.freeze
@@ -16,11 +20,37 @@ module Datadog
16
20
 
17
21
  # @public_api
18
22
  module Distributed
23
+ # Custom Datadog format
19
24
  PROPAGATION_STYLE_DATADOG = 'Datadog'.freeze
25
+
26
+ PROPAGATION_STYLE_B3_MULTI_HEADER = 'b3multi'.freeze
27
+ # @deprecated Use `b3multi` instead.
20
28
  PROPAGATION_STYLE_B3 = 'B3'.freeze
21
- PROPAGATION_STYLE_B3_SINGLE_HEADER = 'B3 single header'.freeze
22
- ENV_PROPAGATION_STYLE_INJECT = 'DD_PROPAGATION_STYLE_INJECT'.freeze
23
- ENV_PROPAGATION_STYLE_EXTRACT = 'DD_PROPAGATION_STYLE_EXTRACT'.freeze
29
+
30
+ PROPAGATION_STYLE_B3_SINGLE_HEADER = 'b3'.freeze
31
+ # @deprecated Use `b3` instead.
32
+ PROPAGATION_STYLE_B3_SINGLE_HEADER_OLD = 'B3 single header'.freeze
33
+
34
+ # W3C Trace Context
35
+ PROPAGATION_STYLE_TRACE_CONTEXT = 'tracecontext'.freeze
36
+
37
+ # Sets both extract and inject propagation style tho the provided value.
38
+ # Has lower precedence than `DD_TRACE_PROPAGATION_STYLE_INJECT` or
39
+ # `DD_TRACE_PROPAGATION_STYLE_EXTRACT`.
40
+ ENV_PROPAGATION_STYLE = 'DD_TRACE_PROPAGATION_STYLE'.freeze
41
+
42
+ ENV_PROPAGATION_STYLE_INJECT = 'DD_TRACE_PROPAGATION_STYLE_INJECT'.freeze
43
+ # @deprecated Use `DD_TRACE_PROPAGATION_STYLE_INJECT` instead.
44
+ ENV_PROPAGATION_STYLE_INJECT_OLD = 'DD_PROPAGATION_STYLE_INJECT'.freeze
45
+
46
+ ENV_PROPAGATION_STYLE_EXTRACT = 'DD_TRACE_PROPAGATION_STYLE_EXTRACT'.freeze
47
+ # @deprecated Use `DD_TRACE_PROPAGATION_STYLE_EXTRACT` instead.
48
+ ENV_PROPAGATION_STYLE_EXTRACT_OLD = 'DD_PROPAGATION_STYLE_EXTRACT'.freeze
49
+
50
+ # A no-op propagator. Compatible with OpenTelemetry's `none` propagator.
51
+ # @see https://opentelemetry.io/docs/concepts/sdk-configuration/general-sdk-configuration/#otel_propagators
52
+ PROPAGATION_STYLE_NONE = 'none'.freeze
53
+
24
54
  ENV_X_DATADOG_TAGS_MAX_LENGTH = 'DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH'.freeze
25
55
  end
26
56