ddtrace 1.6.1 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
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