ddtrace 1.18.0 → 1.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +82 -1
  3. data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +96 -66
  4. data/ext/ddtrace_profiling_native_extension/collectors_discrete_dynamic_sampler.c +349 -0
  5. data/ext/ddtrace_profiling_native_extension/collectors_discrete_dynamic_sampler.h +89 -0
  6. data/ext/ddtrace_profiling_native_extension/collectors_dynamic_sampling_rate.c +22 -14
  7. data/ext/ddtrace_profiling_native_extension/collectors_dynamic_sampling_rate.h +4 -0
  8. data/ext/ddtrace_profiling_native_extension/collectors_gc_profiling_helper.c +156 -0
  9. data/ext/ddtrace_profiling_native_extension/collectors_gc_profiling_helper.h +5 -0
  10. data/ext/ddtrace_profiling_native_extension/collectors_stack.c +43 -102
  11. data/ext/ddtrace_profiling_native_extension/collectors_stack.h +10 -3
  12. data/ext/ddtrace_profiling_native_extension/collectors_thread_context.c +159 -124
  13. data/ext/ddtrace_profiling_native_extension/collectors_thread_context.h +2 -1
  14. data/ext/ddtrace_profiling_native_extension/extconf.rb +19 -0
  15. data/ext/ddtrace_profiling_native_extension/heap_recorder.c +970 -0
  16. data/ext/ddtrace_profiling_native_extension/heap_recorder.h +155 -0
  17. data/ext/ddtrace_profiling_native_extension/helpers.h +6 -0
  18. data/ext/ddtrace_profiling_native_extension/libdatadog_helpers.c +20 -0
  19. data/ext/ddtrace_profiling_native_extension/libdatadog_helpers.h +11 -0
  20. data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +5 -0
  21. data/ext/ddtrace_profiling_native_extension/profiling.c +17 -0
  22. data/ext/ddtrace_profiling_native_extension/ruby_helpers.c +147 -0
  23. data/ext/ddtrace_profiling_native_extension/ruby_helpers.h +28 -0
  24. data/ext/ddtrace_profiling_native_extension/stack_recorder.c +329 -10
  25. data/ext/ddtrace_profiling_native_extension/stack_recorder.h +3 -0
  26. data/ext/ddtrace_profiling_native_extension/time_helpers.h +2 -0
  27. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +2 -1
  28. data/lib/datadog/core/configuration/settings.rb +153 -21
  29. data/lib/datadog/core/environment/class_count.rb +6 -6
  30. data/lib/datadog/core/remote/component.rb +25 -12
  31. data/lib/datadog/core/remote/ext.rb +1 -0
  32. data/lib/datadog/core/remote/tie/tracing.rb +39 -0
  33. data/lib/datadog/core/remote/tie.rb +27 -0
  34. data/lib/datadog/core/telemetry/collector.rb +10 -0
  35. data/lib/datadog/core/telemetry/event.rb +2 -1
  36. data/lib/datadog/core/telemetry/ext.rb +3 -0
  37. data/lib/datadog/core/telemetry/v1/app_event.rb +8 -1
  38. data/lib/datadog/core/telemetry/v1/install_signature.rb +38 -0
  39. data/lib/datadog/opentelemetry/sdk/propagator.rb +3 -2
  40. data/lib/datadog/opentelemetry.rb +3 -0
  41. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +5 -12
  42. data/lib/datadog/profiling/component.rb +183 -13
  43. data/lib/datadog/profiling/scheduler.rb +4 -6
  44. data/lib/datadog/profiling/stack_recorder.rb +13 -2
  45. data/lib/datadog/tracing/configuration/ext.rb +0 -1
  46. data/lib/datadog/tracing/configuration/settings.rb +2 -1
  47. data/lib/datadog/tracing/contrib/action_cable/configuration/settings.rb +1 -0
  48. data/lib/datadog/tracing/contrib/action_cable/ext.rb +1 -0
  49. data/lib/datadog/tracing/contrib/action_mailer/configuration/settings.rb +1 -0
  50. data/lib/datadog/tracing/contrib/action_mailer/ext.rb +1 -0
  51. data/lib/datadog/tracing/contrib/action_pack/configuration/settings.rb +1 -0
  52. data/lib/datadog/tracing/contrib/action_pack/ext.rb +1 -0
  53. data/lib/datadog/tracing/contrib/action_view/configuration/settings.rb +1 -0
  54. data/lib/datadog/tracing/contrib/action_view/ext.rb +1 -0
  55. data/lib/datadog/tracing/contrib/active_job/configuration/settings.rb +1 -0
  56. data/lib/datadog/tracing/contrib/active_job/ext.rb +1 -0
  57. data/lib/datadog/tracing/contrib/active_model_serializers/configuration/settings.rb +1 -0
  58. data/lib/datadog/tracing/contrib/active_model_serializers/ext.rb +1 -0
  59. data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +1 -0
  60. data/lib/datadog/tracing/contrib/active_record/ext.rb +1 -0
  61. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +1 -0
  62. data/lib/datadog/tracing/contrib/active_support/ext.rb +1 -0
  63. data/lib/datadog/tracing/contrib/analytics.rb +0 -1
  64. data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +1 -0
  65. data/lib/datadog/tracing/contrib/aws/ext.rb +1 -0
  66. data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +1 -0
  67. data/lib/datadog/tracing/contrib/dalli/ext.rb +1 -0
  68. data/lib/datadog/tracing/contrib/delayed_job/configuration/settings.rb +1 -0
  69. data/lib/datadog/tracing/contrib/delayed_job/ext.rb +1 -0
  70. data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +1 -0
  71. data/lib/datadog/tracing/contrib/elasticsearch/ext.rb +1 -0
  72. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +1 -0
  73. data/lib/datadog/tracing/contrib/ethon/ext.rb +1 -0
  74. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +1 -0
  75. data/lib/datadog/tracing/contrib/excon/ext.rb +1 -0
  76. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +7 -0
  77. data/lib/datadog/tracing/contrib/faraday/ext.rb +1 -0
  78. data/lib/datadog/tracing/contrib/faraday/middleware.rb +1 -1
  79. data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +1 -0
  80. data/lib/datadog/tracing/contrib/grape/ext.rb +1 -0
  81. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +1 -0
  82. data/lib/datadog/tracing/contrib/graphql/ext.rb +1 -0
  83. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +1 -0
  84. data/lib/datadog/tracing/contrib/grpc/ext.rb +1 -0
  85. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +1 -0
  86. data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +2 -2
  87. data/lib/datadog/tracing/contrib/http/ext.rb +1 -0
  88. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +1 -0
  89. data/lib/datadog/tracing/contrib/httpclient/ext.rb +1 -0
  90. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +1 -0
  91. data/lib/datadog/tracing/contrib/httprb/ext.rb +1 -0
  92. data/lib/datadog/tracing/contrib/kafka/configuration/settings.rb +1 -0
  93. data/lib/datadog/tracing/contrib/kafka/ext.rb +1 -0
  94. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +1 -0
  95. data/lib/datadog/tracing/contrib/mongodb/ext.rb +1 -0
  96. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +5 -0
  97. data/lib/datadog/tracing/contrib/mysql2/ext.rb +1 -0
  98. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +2 -1
  99. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +1 -0
  100. data/lib/datadog/tracing/contrib/opensearch/ext.rb +1 -0
  101. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +1 -0
  102. data/lib/datadog/tracing/contrib/pg/ext.rb +1 -0
  103. data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +1 -0
  104. data/lib/datadog/tracing/contrib/presto/ext.rb +1 -0
  105. data/lib/datadog/tracing/contrib/qless/configuration/settings.rb +1 -0
  106. data/lib/datadog/tracing/contrib/qless/ext.rb +1 -0
  107. data/lib/datadog/tracing/contrib/que/configuration/settings.rb +1 -0
  108. data/lib/datadog/tracing/contrib/que/ext.rb +1 -0
  109. data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +1 -0
  110. data/lib/datadog/tracing/contrib/racecar/ext.rb +1 -0
  111. data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +1 -0
  112. data/lib/datadog/tracing/contrib/rack/ext.rb +1 -0
  113. data/lib/datadog/tracing/contrib/rack/middlewares.rb +9 -2
  114. data/lib/datadog/tracing/contrib/rails/auto_instrument_railtie.rb +0 -2
  115. data/lib/datadog/tracing/contrib/rails/configuration/settings.rb +1 -0
  116. data/lib/datadog/tracing/contrib/rails/ext.rb +1 -0
  117. data/lib/datadog/tracing/contrib/rake/configuration/settings.rb +1 -0
  118. data/lib/datadog/tracing/contrib/rake/ext.rb +1 -0
  119. data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +1 -0
  120. data/lib/datadog/tracing/contrib/redis/ext.rb +1 -0
  121. data/lib/datadog/tracing/contrib/redis/instrumentation.rb +2 -2
  122. data/lib/datadog/tracing/contrib/redis/patcher.rb +34 -21
  123. data/lib/datadog/tracing/contrib/resque/configuration/settings.rb +1 -0
  124. data/lib/datadog/tracing/contrib/resque/ext.rb +1 -0
  125. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +1 -0
  126. data/lib/datadog/tracing/contrib/rest_client/ext.rb +1 -0
  127. data/lib/datadog/tracing/contrib/roda/configuration/settings.rb +1 -0
  128. data/lib/datadog/tracing/contrib/roda/ext.rb +1 -0
  129. data/lib/datadog/tracing/contrib/sequel/configuration/settings.rb +1 -0
  130. data/lib/datadog/tracing/contrib/sequel/ext.rb +1 -0
  131. data/lib/datadog/tracing/contrib/shoryuken/configuration/settings.rb +1 -0
  132. data/lib/datadog/tracing/contrib/shoryuken/ext.rb +1 -0
  133. data/lib/datadog/tracing/contrib/sidekiq/configuration/settings.rb +1 -0
  134. data/lib/datadog/tracing/contrib/sidekiq/ext.rb +1 -0
  135. data/lib/datadog/tracing/contrib/sinatra/configuration/settings.rb +1 -0
  136. data/lib/datadog/tracing/contrib/sinatra/ext.rb +1 -0
  137. data/lib/datadog/tracing/contrib/sneakers/configuration/settings.rb +1 -0
  138. data/lib/datadog/tracing/contrib/sneakers/ext.rb +1 -0
  139. data/lib/datadog/tracing/contrib/stripe/configuration/settings.rb +1 -0
  140. data/lib/datadog/tracing/contrib/stripe/ext.rb +1 -0
  141. data/lib/datadog/tracing/contrib/sucker_punch/configuration/settings.rb +1 -0
  142. data/lib/datadog/tracing/contrib/sucker_punch/ext.rb +1 -0
  143. data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +58 -0
  144. data/lib/datadog/tracing/contrib/trilogy/ext.rb +27 -0
  145. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +94 -0
  146. data/lib/datadog/tracing/contrib/trilogy/integration.rb +43 -0
  147. data/lib/datadog/tracing/contrib/trilogy/patcher.rb +31 -0
  148. data/lib/datadog/tracing/contrib.rb +1 -0
  149. data/lib/datadog/tracing.rb +8 -2
  150. data/lib/ddtrace/version.rb +1 -1
  151. metadata +20 -6
@@ -314,34 +314,89 @@ module Datadog
314
314
 
315
315
  # Can be used to enable/disable the Datadog::Profiling.allocation_count feature.
316
316
  #
317
- # This feature is safe and enabled by default on Ruby 2.x, but has a few caveats on Ruby 3.x.
317
+ # This feature is now controlled via {:experimental_allocation_enabled}
318
+ option :allocation_counting_enabled do |o|
319
+ o.after_set do
320
+ Datadog.logger.warn(
321
+ 'The profiling.advanced.allocation_counting_enabled setting has been deprecated for removal and no ' \
322
+ 'longer does anything. Please remove it from your Datadog.configure block. ' \
323
+ 'Allocation counting is now controlled by the `experimental_allocation_enabled` setting instead.'
324
+ )
325
+ end
326
+ end
327
+
328
+ # Can be used to enable/disable collection of allocation profiles.
318
329
  #
319
- # Caveat 1 (severe):
320
- # On Ruby versions 3.0 (all), 3.1.0 to 3.1.3, and 3.2.0 to 3.2.2 this is disabled by default because it
321
- # can trigger a VM bug that causes a segmentation fault during garbage collection of Ractors
322
- # (https://bugs.ruby-lang.org/issues/18464). We don't recommend using this feature on such Rubies.
323
- # This bug is fixed on Ruby versions 3.1.4, 3.2.3 and 3.3.0.
330
+ # This feature is alpha and disabled by default
324
331
  #
325
- # Caveat 2 (annoyance):
326
- # On all known versions of Ruby 3.x, due to https://bugs.ruby-lang.org/issues/19112, when a ractor gets
327
- # garbage collected, Ruby will disable all active tracepoints, which this feature internally relies on.
328
- # Thus this feature is only usable if you're not using Ractors.
332
+ # @warn This feature is not supported/safe in all Rubies. Details in {Datadog::Profiling::Component} but
333
+ # in summary, this should be supported on Ruby 2.x, 3.1.4+, 3.2.3+ and 3.3.0+. Enabling it on
334
+ # unsupported Rubies may result in unexpected behaviour, including crashes.
329
335
  #
330
- # Caveat 3 (severe):
331
- # Ruby 3.2.0 to 3.2.2 have a bug in the newobj tracepoint (https://bugs.ruby-lang.org/issues/19482,
332
- # https://github.com/ruby/ruby/pull/7464) so that's an extra reason why it's not safe on those Rubies.
333
- # This bug is fixed on Ruby versions 3.2.3 and 3.3.0.
336
+ # @default `DD_PROFILING_EXPERIMENTAL_ALLOCATION_ENABLED` environment variable as a boolean, otherwise `false`
337
+ option :experimental_allocation_enabled do |o|
338
+ o.type :bool
339
+ o.env 'DD_PROFILING_EXPERIMENTAL_ALLOCATION_ENABLED'
340
+ o.default false
341
+ end
342
+
343
+ # Can be used to enable/disable the collection of heap profiles.
334
344
  #
335
- # @default `true` on Ruby 2.x and 3.1.4+, 3.2.3+ and 3.3.0+; `false` for Ruby 3.0 and unpatched Rubies.
336
- option :allocation_counting_enabled do |o|
337
- o.default do
338
- RUBY_VERSION.start_with?('2.') ||
339
- (RUBY_VERSION.start_with?('3.1.') && RUBY_VERSION >= '3.1.4') ||
340
- (RUBY_VERSION.start_with?('3.2.') && RUBY_VERSION >= '3.2.3') ||
341
- RUBY_VERSION >= '3.3.'
345
+ # This feature is alpha and disabled by default
346
+ #
347
+ # @warn To enable heap profiling you are required to also enable allocation profiling.
348
+ #
349
+ # @default `DD_PROFILING_EXPERIMENTAL_HEAP_ENABLED` environment variable as a boolean, otherwise `false`
350
+ option :experimental_heap_enabled do |o|
351
+ o.type :bool
352
+ o.env 'DD_PROFILING_EXPERIMENTAL_HEAP_ENABLED'
353
+ o.default false
354
+ end
355
+
356
+ # Can be used to enable/disable the collection of heap size profiles.
357
+ #
358
+ # This feature is alpha and enabled by default when heap profiling is enabled.
359
+ #
360
+ # @warn To enable heap size profiling you are required to also enable allocation and heap profiling.
361
+ #
362
+ # @default `DD_PROFILING_EXPERIMENTAL_HEAP_SIZE_ENABLED` environment variable as a boolean, otherwise
363
+ # whatever the value of DD_PROFILING_EXPERIMENTAL_HEAP_ENABLED is.
364
+ option :experimental_heap_size_enabled do |o|
365
+ o.type :bool
366
+ o.env 'DD_PROFILING_EXPERIMENTAL_HEAP_SIZE_ENABLED'
367
+ o.default true # This gets ANDed with experimental_heap_enabled in the profiler component.
368
+ end
369
+
370
+ # Can be used to configure the allocation sampling rate: a sample will be collected every x allocations.
371
+ #
372
+ # This feature is now controlled via {:overhead_target_percentage}
373
+ option :experimental_allocation_sample_rate do |o|
374
+ o.after_set do
375
+ Datadog.logger.warn(
376
+ 'The profiling.advanced.experimental_allocation_sample_rate setting has been deprecated for removal ' \
377
+ 'and no longer does anything. Please remove it from your Datadog.configure block. ' \
378
+ 'Allocation sample rate is now handled by a dynamic sampler which will adjust the sampling rate to ' \
379
+ 'keep to the configured `profiling.advanced.overhead_target_percentage`.'
380
+ )
342
381
  end
343
382
  end
344
383
 
384
+ # Can be used to configure the heap sampling rate: a heap sample will be collected for every x allocation
385
+ # samples.
386
+ #
387
+ # The lower the value, the more accuracy in heap tracking but the bigger the overhead. In particular, a
388
+ # value of 1 will track ALL allocations samples for heap profiles.
389
+ #
390
+ # The effective heap sampling rate in terms of allocations (not allocation samples) can be calculated via
391
+ # effective_heap_sample_rate = allocation_sample_rate * heap_sample_rate.
392
+ #
393
+ # @default `DD_PROFILING_EXPERIMENTAL_HEAP_SAMPLE_RATE` environment variable, otherwise `10`.
394
+ option :experimental_heap_sample_rate do |o|
395
+ o.type :int
396
+ o.env 'DD_PROFILING_EXPERIMENTAL_HEAP_SAMPLE_RATE'
397
+ o.default 10
398
+ end
399
+
345
400
  # Can be used to disable checking which version of `libmysqlclient` is being used by the `mysql2` gem.
346
401
  #
347
402
  # This setting is only used when the `mysql2` gem is installed.
@@ -391,6 +446,34 @@ module Datadog
391
446
  end
392
447
  end
393
448
  end
449
+
450
+ # Configures how much wall-time overhead the profiler targets. The profiler will dynamically adjust the
451
+ # interval between samples it takes so as to try and maintain the property that it spends no longer than
452
+ # this amount of wall-clock time profiling. For example, with the default value of 2%, the profiler will
453
+ # try and cause no more than 1.2 seconds per minute of overhead. Decreasing this value will reduce the
454
+ # accuracy of the data collected. Increasing will impact the application.
455
+ #
456
+ # We do not recommend tweaking this value.
457
+ #
458
+ # This value should be a percentage i.e. a number between 0 and 100, not 0 and 1.
459
+ #
460
+ # @default `DD_PROFILING_OVERHEAD_TARGET_PERCENTAGE` as a float, otherwise 2.0
461
+ option :overhead_target_percentage do |o|
462
+ o.type :float
463
+ o.env 'DD_PROFILING_OVERHEAD_TARGET_PERCENTAGE'
464
+ o.default 2.0
465
+ end
466
+
467
+ # Controls how often the profiler reports data, in seconds. Cannot be lower than 60 seconds.
468
+ #
469
+ # We do not recommend tweaking this value.
470
+ #
471
+ # @default `DD_PROFILING_UPLOAD_PERIOD` environment variable, otherwise 60
472
+ option :upload_period_seconds do |o|
473
+ o.type :int
474
+ o.env 'DD_PROFILING_UPLOAD_PERIOD'
475
+ o.default 60
476
+ end
394
477
  end
395
478
 
396
479
  # @public_api
@@ -592,6 +675,42 @@ module Datadog
592
675
  o.env Core::Telemetry::Ext::ENV_HEARTBEAT_INTERVAL
593
676
  o.default 60.0
594
677
  end
678
+
679
+ # The install id of the application.
680
+ #
681
+ # This method is used internally, by library injection.
682
+ #
683
+ # @default `DD_INSTRUMENTATION_INSTALL_ID` environment variable, otherwise `nil`.
684
+ # @return [String,nil]
685
+ # @!visibility private
686
+ option :install_id do |o|
687
+ o.type :string, nilable: true
688
+ o.env Core::Telemetry::Ext::ENV_INSTALL_ID
689
+ end
690
+
691
+ # The install type of the application.
692
+ #
693
+ # This method is used internally, by library injection.
694
+ #
695
+ # @default `DD_INSTRUMENTATION_INSTALL_TYPE` environment variable, otherwise `nil`.
696
+ # @return [String,nil]
697
+ # @!visibility private
698
+ option :install_type do |o|
699
+ o.type :string, nilable: true
700
+ o.env Core::Telemetry::Ext::ENV_INSTALL_TYPE
701
+ end
702
+
703
+ # The install time of the application.
704
+ #
705
+ # This method is used internally, by library injection.
706
+ #
707
+ # @default `DD_INSTRUMENTATION_INSTALL_TIME` environment variable, otherwise `nil`.
708
+ # @return [String,nil]
709
+ # @!visibility private
710
+ option :install_time do |o|
711
+ o.type :string, nilable: true
712
+ o.env Core::Telemetry::Ext::ENV_INSTALL_TIME
713
+ end
595
714
  end
596
715
 
597
716
  # Remote configuration
@@ -630,6 +749,19 @@ module Datadog
630
749
  o.default 5.0
631
750
  end
632
751
 
752
+ # Tune remote configuration boot timeout.
753
+ # Early operations such as requests are blocked until RC is ready. In
754
+ # order to not block the application indefinitely a timeout is
755
+ # enforced allowing requests to proceed with the local configuration.
756
+ #
757
+ # @default `DD_REMOTE_CONFIG_BOOT_TIMEOUT` environment variable, otherwise `1.0` seconds.
758
+ # @return [Float]
759
+ option :boot_timeout_seconds do |o|
760
+ o.env Core::Remote::Ext::ENV_BOOT_TIMEOUT_SECONDS
761
+ o.type :float
762
+ o.default 1.0
763
+ end
764
+
633
765
  # Declare service name to bind to remote configuration. Use when
634
766
  # DD_SERVICE does not match the correct integration for which remote
635
767
  # configuration applies.
@@ -5,15 +5,15 @@ module Datadog
5
5
  module Environment
6
6
  # Retrieves number of classes from runtime
7
7
  module ClassCount
8
- module_function
9
-
10
- def value
8
+ def self.value
11
9
  ::ObjectSpace.count_objects[:T_CLASS]
12
10
  end
13
11
 
14
- def available?
15
- ::ObjectSpace.respond_to?(:count_objects) \
16
- && ::ObjectSpace.count_objects.key?(:T_CLASS)
12
+ def self.available?
13
+ return @class_count_available if defined?(@class_count_available)
14
+
15
+ @class_count_available =
16
+ ::ObjectSpace.respond_to?(:count_objects) && ::ObjectSpace.count_objects.key?(:T_CLASS)
17
17
  end
18
18
  end
19
19
  end
@@ -13,9 +13,7 @@ module Datadog
13
13
  # Configures the HTTP transport to communicate with the agent
14
14
  # to fetch and sync the remote configuration
15
15
  class Component
16
- BARRIER_TIMEOUT = 1.0 # second
17
-
18
- attr_reader :client
16
+ attr_reader :client, :healthy
19
17
 
20
18
  def initialize(settings, capabilities, agent_settings)
21
19
  transport_options = {}
@@ -24,14 +22,14 @@ module Datadog
24
22
  negotiation = Negotiation.new(settings, agent_settings)
25
23
  transport_v7 = Datadog::Core::Remote::Transport::HTTP.v7(**transport_options.dup)
26
24
 
27
- @barrier = Barrier.new(BARRIER_TIMEOUT)
25
+ @barrier = Barrier.new(settings.remote.boot_timeout_seconds)
28
26
 
29
27
  @client = Client.new(transport_v7, capabilities)
30
- healthy = false
28
+ @healthy = false
31
29
  Datadog.logger.debug { "new remote configuration client: #{@client.id}" }
32
30
 
33
31
  @worker = Worker.new(interval: settings.remote.poll_interval_seconds) do
34
- unless healthy || negotiation.endpoint?('/v0.7/config')
32
+ unless @healthy || negotiation.endpoint?('/v0.7/config')
35
33
  @barrier.lift
36
34
 
37
35
  next
@@ -39,7 +37,7 @@ module Datadog
39
37
 
40
38
  begin
41
39
  @client.sync
42
- healthy ||= true
40
+ @healthy ||= true
43
41
  rescue Client::SyncError => e
44
42
  Datadog.logger.error do
45
43
  "remote worker client sync error: #{e.message} location: #{Array(e.backtrace).first}. skipping sync"
@@ -57,7 +55,7 @@ module Datadog
57
55
 
58
56
  # client state is unknown, state might be corrupted
59
57
  @client = Client.new(transport_v7, capabilities)
60
- healthy = false
58
+ @healthy = false
61
59
  Datadog.logger.debug { "new remote configuration client: #{@client.id}" }
62
60
 
63
61
  # TODO: bail out if too many errors?
@@ -103,17 +101,32 @@ module Datadog
103
101
  def wait_once(timeout = nil)
104
102
  # TTAS (Test and Test-And-Set) optimisation
105
103
  # Since @once only ever goes from false to true, this is semantically valid
106
- return if @once
104
+ return :pass if @once
107
105
 
108
106
  begin
109
107
  @mutex.lock
110
108
 
111
- return if @once
109
+ return :pass if @once
112
110
 
113
111
  timeout ||= @timeout
114
112
 
115
- # rbs/core has a bug, timeout type is incorrectly ?Integer
116
- @condition.wait(@mutex, _ = timeout)
113
+ # - starting with Ruby 3.2, ConditionVariable#wait returns nil on
114
+ # timeout and an integer otherwise
115
+ # - before Ruby 3.2, ConditionVariable returns itself
116
+ # so we have to rely on @once having been set
117
+ if RUBY_VERSION >= '3.2'
118
+ lifted = @condition.wait(@mutex, timeout)
119
+ else
120
+ @condition.wait(@mutex, timeout)
121
+ lifted = @once
122
+ end
123
+
124
+ if lifted
125
+ :lift
126
+ else
127
+ @once = true
128
+ :timeout
129
+ end
117
130
  ensure
118
131
  @mutex.unlock
119
132
  end
@@ -6,6 +6,7 @@ module Datadog
6
6
  module Ext
7
7
  ENV_ENABLED = 'DD_REMOTE_CONFIGURATION_ENABLED'
8
8
  ENV_POLL_INTERVAL_SECONDS = 'DD_REMOTE_CONFIG_POLL_INTERVAL_SECONDS'
9
+ ENV_BOOT_TIMEOUT_SECONDS = 'DD_REMOTE_CONFIG_BOOT_TIMEOUT_SECONDS'
9
10
  end
10
11
  end
11
12
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../tie'
4
+
5
+ module Datadog
6
+ module Core
7
+ module Remote
8
+ module Tie
9
+ # Extend Remote Configuration abilities with Tracing
10
+ module Tracing
11
+ # Tag per-request Remote Configuration metadata using Tracing
12
+ def self.tag(boot, span)
13
+ return if boot.nil?
14
+ return if span.nil?
15
+
16
+ return if Datadog::Core::Remote.active_remote.nil?
17
+
18
+ # TODO: this is not thread-consistent
19
+ ready = Datadog::Core::Remote.active_remote.healthy
20
+ status = ready ? 'ready' : 'disconnected'
21
+
22
+ span.set_tag('_dd.rc.client_id', Datadog::Core::Remote.active_remote.client.id)
23
+ span.set_tag('_dd.rc.status', status)
24
+
25
+ if boot.barrier != :pass
26
+ span.set_tag('_dd.rc.boot.time', boot.time)
27
+
28
+ if boot.barrier == :timeout
29
+ span.set_tag('_dd.rc.boot.timeout', true)
30
+ else
31
+ span.set_tag('_dd.rc.boot.ready', ready)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Core
5
+ module Remote
6
+ # Provide Remote Configuration extensions to other components
7
+ module Tie
8
+ Boot = Struct.new(
9
+ :barrier,
10
+ :time,
11
+ )
12
+
13
+ def self.boot
14
+ return if Datadog::Core::Remote.active_remote.nil?
15
+
16
+ barrier = nil
17
+
18
+ t = Datadog::Core::Utils::Time.measure do
19
+ barrier = Datadog::Core::Remote.active_remote.barrier(:once)
20
+ end
21
+
22
+ Boot.new(barrier, t)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -9,6 +9,7 @@ require_relative '../utils/hash'
9
9
  require_relative 'v1/application'
10
10
  require_relative 'v1/dependency'
11
11
  require_relative 'v1/host'
12
+ require_relative 'v1/install_signature'
12
13
  require_relative 'v1/integration'
13
14
  require_relative 'v1/product'
14
15
  require_relative '../transport/ext'
@@ -81,6 +82,15 @@ module Datadog
81
82
  )
82
83
  end
83
84
 
85
+ # Forms a telemetry app-started install_signature object
86
+ def install_signature
87
+ Telemetry::V1::InstallSignature.new(
88
+ install_id: Datadog.configuration.dig('telemetry', 'install_id'),
89
+ install_type: Datadog.configuration.dig('telemetry', 'install_type'),
90
+ install_time: Datadog.configuration.dig('telemetry', 'install_time'),
91
+ )
92
+ end
93
+
84
94
  # Forms a telemetry app-started integrations object
85
95
  def integrations
86
96
  Datadog.registry.map do |integration|
@@ -60,7 +60,8 @@ module Datadog
60
60
  dependencies: dependencies,
61
61
  integrations: integrations,
62
62
  configuration: configurations,
63
- additional_payload: additional_payload
63
+ additional_payload: additional_payload,
64
+ install_signature: install_signature
64
65
  )
65
66
  end
66
67
 
@@ -6,6 +6,9 @@ module Datadog
6
6
  module Ext
7
7
  ENV_ENABLED = 'DD_INSTRUMENTATION_TELEMETRY_ENABLED'
8
8
  ENV_HEARTBEAT_INTERVAL = 'DD_TELEMETRY_HEARTBEAT_INTERVAL'
9
+ ENV_INSTALL_ID = 'DD_INSTRUMENTATION_INSTALL_ID'
10
+ ENV_INSTALL_TYPE = 'DD_INSTRUMENTATION_INSTALL_TYPE'
11
+ ENV_INSTALL_TIME = 'DD_INSTRUMENTATION_INSTALL_TIME'
9
12
  end
10
13
  end
11
14
  end
@@ -10,18 +10,24 @@ module Datadog
10
10
  :additional_payload,
11
11
  :configuration,
12
12
  :dependencies,
13
+ :install_signature,
13
14
  :integrations
14
15
 
15
16
  # @param additional_payload [Array<Telemetry::V1::Configuration>] List of Additional payload to track (any key
16
17
  # value not mentioned and doesn't fit under a metric)
17
18
  # @param configuration [Array<Telemetry::V1::Configuration>] List of Tracer related configuration data
18
19
  # @param dependencies [Array<Telemetry::V1::Dependency>] List of all loaded modules requested by the app
20
+ # @param install_signature [Telemetry::V1::InstallSignature] Install signature data
19
21
  # @param integrations [Array<Telemetry::V1::Integration>] List of integrations that are available within the app
20
22
  # and applicable to be traced
21
- def initialize(additional_payload: nil, configuration: nil, dependencies: nil, integrations: nil)
23
+ def initialize(
24
+ additional_payload: nil, configuration: nil, dependencies: nil, install_signature: nil,
25
+ integrations: nil
26
+ )
22
27
  @additional_payload = additional_payload
23
28
  @configuration = configuration
24
29
  @dependencies = dependencies
30
+ @install_signature = install_signature
25
31
  @integrations = integrations
26
32
  end
27
33
 
@@ -30,6 +36,7 @@ module Datadog
30
36
  hash[:additional_payload] = map_hash(@additional_payload) if @additional_payload
31
37
  hash[:configuration] = map_hash(@configuration) if @configuration
32
38
  hash[:dependencies] = map_array(@dependencies) if @dependencies
39
+ hash[:install_signature] = @install_signature.to_h if @install_signature
33
40
  hash[:integrations] = map_array(@integrations) if @integrations
34
41
  end
35
42
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Core
5
+ module Telemetry
6
+ module V1
7
+ # Describes attributes for install signature
8
+ class InstallSignature
9
+ using Core::Utils::Hash::Refinement
10
+
11
+ attr_reader \
12
+ :install_id,
13
+ :install_type,
14
+ :install_time
15
+
16
+ # @param id [String,nil] Install ID
17
+ # @param type [String,nil] Install type
18
+ # @param type [String,nil] Install time
19
+ def initialize(install_id:, install_type:, install_time:)
20
+ @install_id = install_id
21
+ @install_type = install_type
22
+ @install_time = install_time
23
+ end
24
+
25
+ def to_h
26
+ hash = {
27
+ install_id: @install_id,
28
+ install_type: @install_type,
29
+ install_time: @install_time
30
+ }
31
+ hash.compact!
32
+ hash
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -29,9 +29,10 @@ module Datadog
29
29
  carrier, context: ::OpenTelemetry::Context.current,
30
30
  getter: ::OpenTelemetry::Context::Propagation.text_map_getter
31
31
  )
32
- unless getter == ::OpenTelemetry::Context::Propagation.text_map_getter
32
+ if getter != ::OpenTelemetry::Context::Propagation.text_map_getter &&
33
+ getter != ::OpenTelemetry::Common::Propagation.rack_env_getter
33
34
  Datadog.logger.error(
34
- 'Custom getter is not supported. Please inform the `ddtrace` team at ' \
35
+ "Custom getter #{getter} is not supported. Please inform the `ddtrace` team at " \
35
36
  ' https://github.com/DataDog/dd-trace-rb of your use case so we can best support you. Using the default ' \
36
37
  'OpenTelemetry::Context::Propagation.text_map_getter as a fallback getter.'
37
38
  )
@@ -8,7 +8,10 @@
8
8
  # This file activates the integrations of all OpenTelemetry
9
9
  # components supported by Datadog.
10
10
 
11
+ # Load Tracing
11
12
  require_relative 'tracing'
13
+ require_relative 'tracing/contrib'
14
+
12
15
  require_relative 'opentelemetry/api/context'
13
16
 
14
17
  # DEV: Should this be a Contrib integration, that depends on the `opentelemetry-sdk`
@@ -15,14 +15,14 @@ module Datadog
15
15
 
16
16
  def initialize(
17
17
  gc_profiling_enabled:,
18
- allocation_counting_enabled:,
19
18
  no_signals_workaround_enabled:,
20
19
  thread_context_collector:,
21
- idle_sampling_helper: IdleSamplingHelper.new,
20
+ dynamic_sampling_rate_overhead_target_percentage:,
21
+ allocation_profiling_enabled:,
22
22
  # **NOTE**: This should only be used for testing; disabling the dynamic sampling rate will increase the
23
23
  # profiler overhead!
24
24
  dynamic_sampling_rate_enabled: true,
25
- allocation_sample_every: 0 # Currently only for testing; Setting this to > 0 can add a lot of overhead!
25
+ idle_sampling_helper: IdleSamplingHelper.new
26
26
  )
27
27
  unless dynamic_sampling_rate_enabled
28
28
  Datadog.logger.warn(
@@ -30,22 +30,15 @@ module Datadog
30
30
  )
31
31
  end
32
32
 
33
- if allocation_counting_enabled && allocation_sample_every > 0
34
- Datadog.logger.warn(
35
- "Enabled experimental allocation profiling: allocation_sample_every=#{allocation_sample_every}. This is " \
36
- 'experimental, not recommended, and will increase overhead!'
37
- )
38
- end
39
-
40
33
  self.class._native_initialize(
41
34
  self,
42
35
  thread_context_collector,
43
36
  gc_profiling_enabled,
44
37
  idle_sampling_helper,
45
- allocation_counting_enabled,
46
38
  no_signals_workaround_enabled,
47
39
  dynamic_sampling_rate_enabled,
48
- allocation_sample_every,
40
+ dynamic_sampling_rate_overhead_target_percentage,
41
+ allocation_profiling_enabled,
49
42
  )
50
43
  @worker_thread = nil
51
44
  @failure_exception = nil