datadog 2.1.0 → 2.3.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 (183) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +101 -1
  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 +132 -44
  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 +90 -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 +69 -62
  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 -126
  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.c +1 -1
  31. data/ext/datadog_profiling_native_extension/setup_signal_handler.h +1 -0
  32. data/ext/datadog_profiling_native_extension/stack_recorder.c +27 -8
  33. data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -0
  34. data/ext/datadog_profiling_native_extension/time_helpers.c +0 -15
  35. data/ext/datadog_profiling_native_extension/time_helpers.h +36 -6
  36. data/ext/{datadog_profiling_native_extension → libdatadog_api}/crashtracker.c +20 -7
  37. data/ext/libdatadog_api/datadog_ruby_common.c +110 -0
  38. data/ext/libdatadog_api/datadog_ruby_common.h +57 -0
  39. data/ext/libdatadog_api/extconf.rb +108 -0
  40. data/ext/libdatadog_api/macos_development.md +26 -0
  41. data/ext/libdatadog_extconf_helpers.rb +130 -0
  42. data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +49 -0
  43. data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +73 -0
  44. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +68 -0
  45. data/lib/datadog/appsec/contrib/graphql/integration.rb +41 -0
  46. data/lib/datadog/appsec/contrib/graphql/patcher.rb +37 -0
  47. data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +59 -0
  48. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +1 -1
  49. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +1 -1
  50. data/lib/datadog/appsec/extensions.rb +1 -0
  51. data/lib/datadog/appsec/processor/actions.rb +1 -1
  52. data/lib/datadog/appsec/response.rb +15 -1
  53. data/lib/datadog/appsec.rb +1 -0
  54. data/lib/datadog/core/configuration/components.rb +17 -12
  55. data/lib/datadog/core/configuration/settings.rb +93 -7
  56. data/lib/datadog/core/configuration.rb +3 -17
  57. data/lib/datadog/core/crashtracking/agent_base_url.rb +21 -0
  58. data/lib/datadog/core/crashtracking/component.rb +111 -0
  59. data/lib/datadog/core/crashtracking/tag_builder.rb +39 -0
  60. data/lib/datadog/core/deprecations.rb +58 -0
  61. data/lib/datadog/core/diagnostics/environment_logger.rb +8 -11
  62. data/lib/datadog/core/environment/yjit.rb +5 -0
  63. data/lib/datadog/core/runtime/ext.rb +1 -0
  64. data/lib/datadog/core/runtime/metrics.rb +6 -0
  65. data/lib/datadog/core/telemetry/component.rb +154 -0
  66. data/lib/datadog/core/telemetry/emitter.rb +9 -11
  67. data/lib/datadog/core/telemetry/event.rb +132 -26
  68. data/lib/datadog/core/telemetry/ext.rb +3 -0
  69. data/lib/datadog/core/telemetry/http/adapters/net.rb +11 -13
  70. data/lib/datadog/core/telemetry/http/ext.rb +3 -0
  71. data/lib/datadog/core/telemetry/http/transport.rb +38 -9
  72. data/lib/datadog/core/telemetry/logging.rb +35 -0
  73. data/lib/datadog/core/telemetry/metric.rb +167 -0
  74. data/lib/datadog/core/telemetry/metrics_collection.rb +81 -0
  75. data/lib/datadog/core/telemetry/metrics_manager.rb +81 -0
  76. data/lib/datadog/core/telemetry/request.rb +1 -1
  77. data/lib/datadog/core/telemetry/worker.rb +173 -0
  78. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +102 -0
  79. data/lib/datadog/core/utils/only_once_successful.rb +76 -0
  80. data/lib/datadog/core.rb +2 -19
  81. data/lib/datadog/kit/appsec/events.rb +2 -4
  82. data/lib/datadog/opentelemetry/sdk/propagator.rb +5 -10
  83. data/lib/datadog/opentelemetry/sdk/span_processor.rb +15 -2
  84. data/lib/datadog/opentelemetry/sdk/trace/span.rb +23 -0
  85. data/lib/datadog/profiling/collectors/code_provenance.rb +24 -11
  86. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +17 -17
  87. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +11 -13
  88. data/lib/datadog/profiling/collectors/info.rb +3 -3
  89. data/lib/datadog/profiling/collectors/thread_context.rb +4 -2
  90. data/lib/datadog/profiling/component.rb +85 -90
  91. data/lib/datadog/profiling/exporter.rb +3 -3
  92. data/lib/datadog/profiling/ext/dir_monkey_patches.rb +410 -0
  93. data/lib/datadog/profiling/ext.rb +21 -21
  94. data/lib/datadog/profiling/flush.rb +1 -1
  95. data/lib/datadog/profiling/http_transport.rb +8 -6
  96. data/lib/datadog/profiling/load_native_extension.rb +5 -5
  97. data/lib/datadog/profiling/preload.rb +1 -1
  98. data/lib/datadog/profiling/profiler.rb +5 -8
  99. data/lib/datadog/profiling/scheduler.rb +31 -25
  100. data/lib/datadog/profiling/tag_builder.rb +2 -2
  101. data/lib/datadog/profiling/tasks/exec.rb +5 -5
  102. data/lib/datadog/profiling/tasks/setup.rb +16 -35
  103. data/lib/datadog/profiling.rb +5 -5
  104. data/lib/datadog/tracing/contrib/action_cable/event.rb +1 -1
  105. data/lib/datadog/tracing/contrib/action_cable/events/broadcast.rb +1 -1
  106. data/lib/datadog/tracing/contrib/action_cable/events/perform_action.rb +1 -1
  107. data/lib/datadog/tracing/contrib/action_cable/events/transmit.rb +1 -1
  108. data/lib/datadog/tracing/contrib/action_mailer/event.rb +4 -6
  109. data/lib/datadog/tracing/contrib/action_mailer/events/deliver.rb +9 -4
  110. data/lib/datadog/tracing/contrib/action_mailer/events/process.rb +3 -2
  111. data/lib/datadog/tracing/contrib/action_view/events/render_partial.rb +1 -5
  112. data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +1 -1
  113. data/lib/datadog/tracing/contrib/active_job/events/discard.rb +1 -1
  114. data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +1 -1
  115. data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +1 -1
  116. data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +1 -1
  117. data/lib/datadog/tracing/contrib/active_job/events/perform.rb +1 -1
  118. data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +1 -1
  119. data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +1 -1
  120. data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +1 -1
  121. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +1 -1
  122. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +2 -1
  123. data/lib/datadog/tracing/contrib/active_support/cache/event.rb +32 -0
  124. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +156 -0
  125. data/lib/datadog/tracing/contrib/active_support/cache/events.rb +34 -0
  126. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +45 -41
  127. data/lib/datadog/tracing/contrib/active_support/cache/patcher.rb +17 -40
  128. data/lib/datadog/tracing/contrib/active_support/cache/redis.rb +4 -1
  129. data/lib/datadog/tracing/contrib/active_support/notifications/event.rb +29 -6
  130. data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +16 -4
  131. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +33 -29
  132. data/lib/datadog/tracing/contrib/analytics.rb +5 -0
  133. data/lib/datadog/tracing/contrib/ext.rb +14 -0
  134. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +5 -0
  135. data/lib/datadog/tracing/contrib/graphql/patcher.rb +8 -2
  136. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +166 -0
  137. data/lib/datadog/tracing/contrib/graphql/unified_trace_patcher.rb +28 -0
  138. data/lib/datadog/tracing/contrib/kafka/consumer_event.rb +1 -1
  139. data/lib/datadog/tracing/contrib/kafka/consumer_group_event.rb +1 -1
  140. data/lib/datadog/tracing/contrib/kafka/event.rb +1 -1
  141. data/lib/datadog/tracing/contrib/kafka/events/connection/request.rb +3 -3
  142. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_batch.rb +3 -3
  143. data/lib/datadog/tracing/contrib/kafka/events/consumer/process_message.rb +3 -3
  144. data/lib/datadog/tracing/contrib/kafka/events/consumer_group/heartbeat.rb +3 -3
  145. data/lib/datadog/tracing/contrib/kafka/events/produce_operation/send_messages.rb +3 -3
  146. data/lib/datadog/tracing/contrib/kafka/events/producer/deliver_messages.rb +3 -3
  147. data/lib/datadog/tracing/contrib/lograge/patcher.rb +16 -0
  148. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +5 -0
  149. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +17 -13
  150. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +5 -0
  151. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +4 -1
  152. data/lib/datadog/tracing/contrib/propagation/sql_comment/ext.rb +28 -0
  153. data/lib/datadog/tracing/contrib/propagation/sql_comment/mode.rb +5 -1
  154. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +22 -10
  155. data/lib/datadog/tracing/contrib/racecar/event.rb +2 -2
  156. data/lib/datadog/tracing/contrib/rails/ext.rb +9 -0
  157. data/lib/datadog/tracing/contrib/rails/patcher.rb +7 -0
  158. data/lib/datadog/tracing/contrib/rails/runner.rb +95 -0
  159. data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +5 -0
  160. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +4 -1
  161. data/lib/datadog/tracing/diagnostics/environment_logger.rb +14 -16
  162. data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
  163. data/lib/datadog/tracing/distributed/b3_single.rb +3 -1
  164. data/lib/datadog/tracing/distributed/datadog.rb +2 -2
  165. data/lib/datadog/tracing/distributed/propagation.rb +9 -2
  166. data/lib/datadog/tracing/distributed/trace_context.rb +3 -2
  167. data/lib/datadog/tracing/metadata/errors.rb +9 -1
  168. data/lib/datadog/tracing/metadata/ext.rb +4 -0
  169. data/lib/datadog/tracing/pipeline/span_filter.rb +2 -2
  170. data/lib/datadog/tracing/span.rb +9 -2
  171. data/lib/datadog/tracing/span_event.rb +41 -0
  172. data/lib/datadog/tracing/span_operation.rb +9 -4
  173. data/lib/datadog/tracing/trace_operation.rb +7 -3
  174. data/lib/datadog/tracing/trace_segment.rb +4 -1
  175. data/lib/datadog/tracing/tracer.rb +9 -2
  176. data/lib/datadog/tracing/transport/serializable_trace.rb +3 -0
  177. data/lib/datadog/tracing.rb +5 -1
  178. data/lib/datadog/version.rb +2 -2
  179. metadata +43 -12
  180. data/lib/datadog/core/telemetry/client.rb +0 -95
  181. data/lib/datadog/core/telemetry/heartbeat.rb +0 -33
  182. data/lib/datadog/profiling/crashtracker.rb +0 -91
  183. data/lib/datadog/profiling/ext/forking.rb +0 -98
@@ -301,6 +301,16 @@ module Datadog
301
301
  o.default true
302
302
  end
303
303
 
304
+ # Can be used to enable/disable the Datadog::Profiling.allocation_count feature.
305
+ #
306
+ # Requires allocation profiling to be enabled.
307
+ #
308
+ # @default false
309
+ option :allocation_counting_enabled do |o|
310
+ o.type :bool
311
+ o.default false
312
+ end
313
+
304
314
  # Can be used to enable/disable the collection of heap profiles.
305
315
  #
306
316
  # This feature is alpha and disabled by default
@@ -397,6 +407,22 @@ module Datadog
397
407
  end
398
408
  end
399
409
 
410
+ # The profiler gathers data by sending `SIGPROF` unix signals to Ruby application threads.
411
+ #
412
+ # We've discovered that this can trigger a bug in a number of Ruby APIs in the `Dir` class, as
413
+ # described in https://github.com/DataDog/dd-trace-rb/issues/3450 . This workaround prevents the issue
414
+ # from happening by monkey patching the affected APIs.
415
+ #
416
+ # (In the future, once a fix lands upstream, we'll disable this workaround for Rubies that don't need it)
417
+ #
418
+ # @default `DD_PROFILING_DIR_INTERRUPTION_WORKAROUND_ENABLED` environment variable as a boolean,
419
+ # otherwise `true`
420
+ option :dir_interruption_workaround_enabled do |o|
421
+ o.env 'DD_PROFILING_DIR_INTERRUPTION_WORKAROUND_ENABLED'
422
+ o.type :bool
423
+ o.default true
424
+ end
425
+
400
426
  # Configures how much wall-time overhead the profiler targets. The profiler will dynamically adjust the
401
427
  # interval between samples it takes so as to try and maintain the property that it spends no longer than
402
428
  # this amount of wall-clock time profiling. For example, with the default value of 2%, the profiler will
@@ -425,14 +451,16 @@ module Datadog
425
451
  o.default 60
426
452
  end
427
453
 
428
- # Enables reporting of information when the Ruby VM crashes.
429
- #
430
- # @default `DD_PROFILING_EXPERIMENTAL_CRASH_TRACKING_ENABLED` environment variable as a boolean,
431
- # otherwise `false`
454
+ # DEV-3.0: Remove `experimental_crash_tracking_enabled` option
432
455
  option :experimental_crash_tracking_enabled do |o|
433
- o.type :bool
434
- o.env 'DD_PROFILING_EXPERIMENTAL_CRASH_TRACKING_ENABLED'
435
- o.default false
456
+ o.after_set do |_, _, precedence|
457
+ unless precedence == Datadog::Core::Configuration::Option::Precedence::DEFAULT
458
+ Core.log_deprecation(key: :experimental_crash_tracking_enabled) do
459
+ 'The profiling.advanced.experimental_crash_tracking_enabled setting has been deprecated for removal '\
460
+ 'and no longer does anything. Please remove it from your Datadog.configure block.'
461
+ end
462
+ end
463
+ end
436
464
  end
437
465
  end
438
466
 
@@ -647,6 +675,34 @@ module Datadog
647
675
  o.type :bool
648
676
  end
649
677
 
678
+ # Enable agentless mode for telemetry: submit telemetry events directly to the intake without Datadog Agent.
679
+ #
680
+ # @return [Boolean]
681
+ # @!visibility private
682
+ option :agentless_enabled do |o|
683
+ o.type :bool
684
+ o.default false
685
+ end
686
+
687
+ # Overrides agentless telemetry URL. To be used internally for testing purposes only.
688
+ #
689
+ # @return [String]
690
+ # @!visibility private
691
+ option :agentless_url_override do |o|
692
+ o.type :string, nilable: true
693
+ o.env Core::Telemetry::Ext::ENV_AGENTLESS_URL_OVERRIDE
694
+ end
695
+
696
+ # Enable metrics collection for telemetry. Metrics collection only works when telemetry is enabled and
697
+ # metrics are enabled.
698
+ # @default `DD_TELEMETRY_METRICS_ENABLED` environment variable, otherwise `true`.
699
+ # @return [Boolean]
700
+ option :metrics_enabled do |o|
701
+ o.type :bool
702
+ o.env Core::Telemetry::Ext::ENV_METRICS_ENABLED
703
+ o.default true
704
+ end
705
+
650
706
  # The interval in seconds when telemetry must be sent.
651
707
  #
652
708
  # This method is used internally, for testing purposes only.
@@ -660,6 +716,19 @@ module Datadog
660
716
  o.default 60.0
661
717
  end
662
718
 
719
+ # The interval in seconds when telemetry metrics are aggregated.
720
+ # Should be a denominator of `heartbeat_interval_seconds`.
721
+ #
722
+ # This method is used internally, for testing purposes only.
723
+ # @default `DD_TELEMETRY_METRICS_AGGREGATION_INTERVAL` environment variable, otherwise `10`.
724
+ # @return [Float]
725
+ # @!visibility private
726
+ option :metrics_aggregation_interval_seconds do |o|
727
+ o.type :float
728
+ o.env Core::Telemetry::Ext::ENV_METRICS_AGGREGATION_INTERVAL
729
+ o.default 10.0
730
+ end
731
+
663
732
  # The install id of the application.
664
733
  #
665
734
  # This method is used internally, by library injection.
@@ -695,6 +764,14 @@ module Datadog
695
764
  o.type :string, nilable: true
696
765
  o.env Core::Telemetry::Ext::ENV_INSTALL_TIME
697
766
  end
767
+
768
+ # Telemetry shutdown timeout in seconds
769
+ #
770
+ # @!visibility private
771
+ option :shutdown_timeout_seconds do |o|
772
+ o.type :float
773
+ o.default 1.0
774
+ end
698
775
  end
699
776
 
700
777
  # Remote configuration
@@ -755,6 +832,15 @@ module Datadog
755
832
  option :service
756
833
  end
757
834
 
835
+ settings :crashtracking do
836
+ # Enables reporting of information when Ruby VM crashes.
837
+ option :enabled do |o|
838
+ o.type :bool
839
+ o.default true
840
+ o.env 'DD_CRASHTRACKING_ENABLED'
841
+ end
842
+ end
843
+
758
844
  # TODO: Tracing should manage its own settings.
759
845
  # Keep this extension here for now to keep things working.
760
846
  extend Datadog::Tracing::Configuration::Settings
@@ -84,23 +84,16 @@ module Datadog
84
84
  configuration = self.configuration
85
85
  yield(configuration)
86
86
 
87
- built_components = false
88
-
89
- components = safely_synchronize do |write_components|
87
+ safely_synchronize do |write_components|
90
88
  write_components.call(
91
89
  if components?
92
90
  replace_components!(configuration, @components)
93
91
  else
94
- components = build_components(configuration)
95
- built_components = true
96
- components
92
+ build_components(configuration)
97
93
  end
98
94
  )
99
95
  end
100
96
 
101
- # Should only be called the first time components are built
102
- components.telemetry.started! if built_components
103
-
104
97
  configuration
105
98
  end
106
99
 
@@ -200,20 +193,13 @@ module Datadog
200
193
  current_components = COMPONENTS_READ_LOCK.synchronize { defined?(@components) && @components }
201
194
  return current_components if current_components || !allow_initialization
202
195
 
203
- built_components = false
204
-
205
- components = safely_synchronize do |write_components|
196
+ safely_synchronize do |write_components|
206
197
  if defined?(@components) && @components
207
198
  @components
208
199
  else
209
- built_components = true
210
200
  write_components.call(build_components(configuration))
211
201
  end
212
202
  end
213
-
214
- # Should only be called the first time components are built
215
- components&.telemetry&.started! if built_components
216
- components
217
203
  end
218
204
 
219
205
  private
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../configuration/ext'
4
+
5
+ module Datadog
6
+ module Core
7
+ module Crashtracking
8
+ # This module provides a method to resolve the base URL of the agent
9
+ module AgentBaseUrl
10
+ def self.resolve(agent_settings)
11
+ case agent_settings.adapter
12
+ when Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
13
+ "#{agent_settings.ssl ? 'https' : 'http'}://#{agent_settings.hostname}:#{agent_settings.port}/"
14
+ when Datadog::Core::Configuration::Ext::Agent::UnixSocket::ADAPTER
15
+ "unix://#{agent_settings.uds_path}"
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'libdatadog'
4
+
5
+ require_relative 'tag_builder'
6
+ require_relative 'agent_base_url'
7
+ require_relative '../utils/only_once'
8
+ require_relative '../utils/at_fork_monkey_patch'
9
+
10
+ module Datadog
11
+ module Core
12
+ module Crashtracking
13
+ # Used to report Ruby VM crashes.
14
+ #
15
+ # NOTE: The crashtracker native state is a singleton;
16
+ # so even if you create multiple instances of `Crashtracking::Component` and start them,
17
+ # it only works as "last writer wins". Same for stop -- there's only one state, so calling stop
18
+ # on it will stop the crash tracker, regardless of which instance started it.
19
+ #
20
+ # Methods prefixed with _native_ are implemented in `crashtracker.c`
21
+ class Component
22
+ LIBDATADOG_API_FAILURE =
23
+ begin
24
+ require "libdatadog_api.#{RUBY_VERSION[/\d+.\d+/]}_#{RUBY_PLATFORM}"
25
+ nil
26
+ rescue LoadError => e
27
+ e.message
28
+ end
29
+
30
+ ONLY_ONCE = Core::Utils::OnlyOnce.new
31
+
32
+ def self.build(settings, agent_settings, logger:)
33
+ tags = TagBuilder.call(settings)
34
+ agent_base_url = AgentBaseUrl.resolve(agent_settings)
35
+ logger.warn('Missing agent base URL; cannot enable crash tracking') unless agent_base_url
36
+
37
+ ld_library_path = ::Libdatadog.ld_library_path
38
+ logger.warn('Missing ld_library_path; cannot enable crash tracking') unless ld_library_path
39
+
40
+ path_to_crashtracking_receiver_binary = ::Libdatadog.path_to_crashtracking_receiver_binary
41
+ unless path_to_crashtracking_receiver_binary
42
+ logger.warn('Missing path_to_crashtracking_receiver_binary; cannot enable crash tracking')
43
+ end
44
+
45
+ return unless agent_base_url
46
+ return unless ld_library_path
47
+ return unless path_to_crashtracking_receiver_binary
48
+
49
+ new(
50
+ tags: tags,
51
+ agent_base_url: agent_base_url,
52
+ ld_library_path: ld_library_path,
53
+ path_to_crashtracking_receiver_binary: path_to_crashtracking_receiver_binary,
54
+ logger: logger
55
+ ).tap(&:start)
56
+ end
57
+
58
+ def initialize(tags:, agent_base_url:, ld_library_path:, path_to_crashtracking_receiver_binary:, logger:)
59
+ @tags = tags
60
+ @agent_base_url = agent_base_url
61
+ @ld_library_path = ld_library_path
62
+ @path_to_crashtracking_receiver_binary = path_to_crashtracking_receiver_binary
63
+ @logger = logger
64
+ end
65
+
66
+ def start
67
+ Utils::AtForkMonkeyPatch.apply!
68
+
69
+ start_or_update_on_fork(action: :start)
70
+ ONLY_ONCE.run do
71
+ Utils::AtForkMonkeyPatch.at_fork(:child) do
72
+ # Must NOT reference `self` here, as only the first instance will
73
+ # be captured by the ONLY_ONCE and we want to pick the latest active one
74
+ # (which may have different tags or agent config)
75
+ Datadog.send(:components).crashtracker&.update_on_fork
76
+ end
77
+ end
78
+ end
79
+
80
+ def update_on_fork
81
+ start_or_update_on_fork(action: :update_on_fork)
82
+ end
83
+
84
+ def stop
85
+ self.class._native_stop
86
+ logger.debug('Crash tracking stopped successfully')
87
+ rescue => e
88
+ logger.error("Failed to stop crash tracking: #{e.message}")
89
+ end
90
+
91
+ private
92
+
93
+ attr_reader :tags, :agent_base_url, :ld_library_path, :path_to_crashtracking_receiver_binary, :logger
94
+
95
+ def start_or_update_on_fork(action:)
96
+ self.class._native_start_or_update_on_fork(
97
+ action: action,
98
+ exporter_configuration: [:agent, agent_base_url],
99
+ path_to_crashtracking_receiver_binary: path_to_crashtracking_receiver_binary,
100
+ ld_library_path: ld_library_path,
101
+ tags_as_array: tags.to_a,
102
+ upload_timeout_seconds: 1
103
+ )
104
+ logger.debug("Crash tracking #{action} successfully")
105
+ rescue => e
106
+ logger.error("Failed to #{action} crash tracking: #{e.message}")
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../utils'
4
+ require_relative '../environment/socket'
5
+ require_relative '../environment/identity'
6
+ require_relative '../environment/git'
7
+
8
+ module Datadog
9
+ module Core
10
+ module Crashtracking
11
+ # This module builds a hash of tags
12
+ module TagBuilder
13
+ def self.call(settings)
14
+ hash = {
15
+ 'host' => Environment::Socket.hostname,
16
+ 'process_id' => Process.pid.to_s,
17
+ 'runtime_engine' => Environment::Identity.lang_engine,
18
+ 'runtime-id' => Environment::Identity.id,
19
+ 'runtime_platform' => Environment::Identity.lang_platform,
20
+ 'runtime_version' => Environment::Identity.lang_version,
21
+ 'env' => settings.env,
22
+ 'service' => settings.service,
23
+ 'version' => settings.version,
24
+ 'git.repository_url' => Environment::Git.git_repository_url,
25
+ 'git.commit.sha' => Environment::Git.git_commit_sha,
26
+ 'is_crash' => 'true',
27
+ 'language' => 'ruby',
28
+ 'library_version' => Core::Environment::Identity.gem_datadog_version,
29
+ }.compact
30
+
31
+ # Make sure everything is an utf-8 string, to avoid encoding issues in downstream
32
+ settings.tags.merge(hash).each_with_object({}) do |(key, value), h|
33
+ h[Utils.utf8_encode(key)] = Utils.utf8_encode(value)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module Core
5
+ # Contains behavior for handling deprecated functions in the codebase.
6
+ module Deprecations
7
+ # Records the occurrence of a deprecated operation in this library.
8
+ #
9
+ # Currently, these operations are logged to `Datadog.logger` at `warn` level.
10
+ #
11
+ # `disallowed_next_major` adds a message informing that the deprecated operation
12
+ # won't be allowed in the next major release.
13
+ #
14
+ # @yieldreturn [String] a String with the lazily evaluated deprecation message.
15
+ # @param [Boolean] disallowed_next_major whether this deprecation will be enforced in the next major release.
16
+ # @param [Object] key A unique key for the deprecation. Only the first message with the same key will be logged.
17
+ def log_deprecation(disallowed_next_major: true, key: nil)
18
+ return unless log_deprecation?(key)
19
+
20
+ Datadog.logger.warn do
21
+ message = yield
22
+ message += ' This will be enforced in the next major release.' if disallowed_next_major
23
+ message
24
+ end
25
+
26
+ # Track the deprecation being logged.
27
+ deprecation_logged!(key)
28
+
29
+ nil
30
+ end
31
+
32
+ private
33
+
34
+ # Determines whether a deprecation message should be logged.
35
+ #
36
+ # Internal use only.
37
+ def log_deprecation?(key)
38
+ return true if key.nil?
39
+
40
+ # Only allow a deprecation to be logged once.
41
+ !logged_deprecations.key?(key)
42
+ end
43
+
44
+ def deprecation_logged!(key)
45
+ return if key.nil?
46
+
47
+ logged_deprecations[key] += 1
48
+ end
49
+
50
+ # Tracks what deprecation warnings have already been logged
51
+ #
52
+ # Internal use only.
53
+ def logged_deprecations
54
+ @logged_deprecations ||= Hash.new(0)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -8,11 +8,17 @@ module Datadog
8
8
  module Core
9
9
  module Diagnostics
10
10
  # Base class for EnvironmentLoggers - should allow for easy reporting by users to Datadog support.
11
+ #
12
+ # The EnvironmentLogger should not pollute the logs in a development environment.
11
13
  module EnvironmentLogging
12
14
  def log_configuration!(prefix, data)
13
15
  logger.info("DATADOG CONFIGURATION - #{prefix} - #{data}")
14
16
  end
15
17
 
18
+ def log_debug!(prefix, data)
19
+ logger.debug("DATADOG CONFIGURATION - #{prefix} - #{data}")
20
+ end
21
+
16
22
  def log_error!(prefix, type, error)
17
23
  logger.warn("DATADOG ERROR - #{prefix} - #{type}: #{error}")
18
24
  end
@@ -27,21 +33,12 @@ module Datadog
27
33
  def log?
28
34
  startup_logs_enabled = Datadog.configuration.diagnostics.startup_logs.enabled
29
35
  if startup_logs_enabled.nil?
30
- !repl? && !rspec? # Suppress logs if we are running in a REPL or rspec
36
+ # Do not pollute the logs in a development environment.
37
+ !Datadog::Core::Environment::Execution.development?
31
38
  else
32
39
  startup_logs_enabled
33
40
  end
34
41
  end
35
-
36
- REPL_PROGRAM_NAMES = %w[irb pry].freeze
37
-
38
- def repl?
39
- REPL_PROGRAM_NAMES.include?($PROGRAM_NAME)
40
- end
41
-
42
- def rspec?
43
- $PROGRAM_NAME.end_with?('rspec')
44
- end
45
42
  end
46
43
 
47
44
  # Collects and logs Core diagnostic information
@@ -47,6 +47,11 @@ module Datadog
47
47
  ::RubyVM::YJIT.runtime_stats[:object_shape_count]
48
48
  end
49
49
 
50
+ # Size of memory Rust allocated for metadata
51
+ def yjit_alloc_size
52
+ ::RubyVM::YJIT.runtime_stats[:yjit_alloc_size]
53
+ end
54
+
50
55
  def available?
51
56
  defined?(::RubyVM::YJIT) \
52
57
  && ::RubyVM::YJIT.enabled? \
@@ -30,6 +30,7 @@ module Datadog
30
30
  METRIC_YJIT_LIVE_PAGE_COUNT = 'runtime.ruby.yjit.live_page_count'
31
31
  METRIC_YJIT_OBJECT_SHAPE_COUNT = 'runtime.ruby.yjit.object_shape_count'
32
32
  METRIC_YJIT_OUTLINED_CODE_SIZE = 'runtime.ruby.yjit.outlined_code_size'
33
+ METRIC_YJIT_YJIT_ALLOC_SIZE = 'runtime.ruby.yjit.yjit_alloc_size'
33
34
 
34
35
  TAG_SERVICE = 'service'
35
36
  end
@@ -140,6 +140,7 @@ module Datadog
140
140
  gauge(metric_name, metric_value) if metric_value
141
141
  end
142
142
 
143
+ # rubocop:disable Metrics/MethodLength
143
144
  def flush_yjit_stats
144
145
  # Only on Ruby >= 3.2
145
146
  try_flush do
@@ -176,9 +177,14 @@ module Datadog
176
177
  Core::Runtime::Ext::Metrics::METRIC_YJIT_OUTLINED_CODE_SIZE,
177
178
  Core::Environment::YJIT.outlined_code_size
178
179
  )
180
+ gauge_if_not_nil(
181
+ Core::Runtime::Ext::Metrics::METRIC_YJIT_YJIT_ALLOC_SIZE,
182
+ Core::Environment::YJIT.yjit_alloc_size
183
+ )
179
184
  end
180
185
  end
181
186
  end
187
+ # rubocop:enable Metrics/MethodLength
182
188
  end
183
189
  end
184
190
  end
@@ -0,0 +1,154 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'emitter'
4
+ require_relative 'event'
5
+ require_relative 'http/transport'
6
+ require_relative 'metrics_manager'
7
+ require_relative 'worker'
8
+
9
+ require_relative '../configuration/ext'
10
+ require_relative '../utils/forking'
11
+
12
+ module Datadog
13
+ module Core
14
+ module Telemetry
15
+ # Telemetry entrypoint, coordinates sending telemetry events at various points in app lifecycle.
16
+ class Component
17
+ attr_reader :enabled
18
+
19
+ include Core::Utils::Forking
20
+
21
+ def self.build(settings, agent_settings, logger)
22
+ enabled = settings.telemetry.enabled
23
+ agentless_enabled = settings.telemetry.agentless_enabled
24
+
25
+ if !agentless_enabled && agent_settings.adapter != Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER
26
+ enabled = false
27
+ logger.debug { "Telemetry disabled. Agent network adapter not supported: #{agent_settings.adapter}" }
28
+ end
29
+
30
+ if agentless_enabled && settings.api_key.nil?
31
+ enabled = false
32
+ logger.debug { 'Telemetry disabled. Agentless telemetry requires an DD_API_KEY variable to be set.' }
33
+ end
34
+
35
+ transport = if agentless_enabled
36
+ Datadog::Core::Telemetry::Http::Transport.build_agentless_transport(
37
+ api_key: settings.api_key,
38
+ dd_site: settings.site,
39
+ url_override: settings.telemetry.agentless_url_override
40
+ )
41
+ else
42
+ Datadog::Core::Telemetry::Http::Transport.build_agent_transport(agent_settings)
43
+ end
44
+
45
+ Telemetry::Component.new(
46
+ http_transport: transport,
47
+ enabled: enabled,
48
+ metrics_enabled: enabled && settings.telemetry.metrics_enabled,
49
+ heartbeat_interval_seconds: settings.telemetry.heartbeat_interval_seconds,
50
+ metrics_aggregation_interval_seconds: settings.telemetry.metrics_aggregation_interval_seconds,
51
+ dependency_collection: settings.telemetry.dependency_collection,
52
+ shutdown_timeout_seconds: settings.telemetry.shutdown_timeout_seconds,
53
+ )
54
+ end
55
+
56
+ # @param enabled [Boolean] Determines whether telemetry events should be sent to the API
57
+ # @param metrics_enabled [Boolean] Determines whether telemetry metrics should be sent to the API
58
+ # @param heartbeat_interval_seconds [Float] How frequently heartbeats will be reported, in seconds.
59
+ # @param metrics_aggregation_interval_seconds [Float] How frequently metrics will be aggregated, in seconds.
60
+ # @param [Boolean] dependency_collection Whether to send the `app-dependencies-loaded` event
61
+ def initialize(
62
+ heartbeat_interval_seconds:,
63
+ metrics_aggregation_interval_seconds:,
64
+ dependency_collection:,
65
+ http_transport:,
66
+ shutdown_timeout_seconds:,
67
+ enabled: true,
68
+ metrics_enabled: true
69
+ )
70
+ @enabled = enabled
71
+ @stopped = false
72
+
73
+ @metrics_manager = MetricsManager.new(
74
+ enabled: enabled && metrics_enabled,
75
+ aggregation_interval: metrics_aggregation_interval_seconds
76
+ )
77
+
78
+ @worker = Telemetry::Worker.new(
79
+ enabled: @enabled,
80
+ heartbeat_interval_seconds: heartbeat_interval_seconds,
81
+ metrics_aggregation_interval_seconds: metrics_aggregation_interval_seconds,
82
+ emitter: Emitter.new(http_transport: http_transport),
83
+ metrics_manager: @metrics_manager,
84
+ dependency_collection: dependency_collection,
85
+ shutdown_timeout: shutdown_timeout_seconds
86
+ )
87
+ @worker.start
88
+ end
89
+
90
+ def disable!
91
+ @enabled = false
92
+ @worker.enabled = false
93
+ end
94
+
95
+ def stop!
96
+ return if @stopped
97
+
98
+ @worker.stop(true)
99
+ @stopped = true
100
+ end
101
+
102
+ def emit_closing!
103
+ return if !@enabled || forked?
104
+
105
+ @worker.enqueue(Event::AppClosing.new)
106
+ end
107
+
108
+ def integrations_change!
109
+ return if !@enabled || forked?
110
+
111
+ @worker.enqueue(Event::AppIntegrationsChange.new)
112
+ end
113
+
114
+ def log!(event)
115
+ return unless @enabled || forked?
116
+
117
+ @worker.enqueue(event)
118
+ end
119
+
120
+ # Report configuration changes caused by Remote Configuration.
121
+ def client_configuration_change!(changes)
122
+ return if !@enabled || forked?
123
+
124
+ @worker.enqueue(Event::AppClientConfigurationChange.new(changes, 'remote_config'))
125
+ end
126
+
127
+ # Increments a count metric.
128
+ def inc(namespace, metric_name, value, tags: {}, common: true)
129
+ @metrics_manager.inc(namespace, metric_name, value, tags: tags, common: common)
130
+ end
131
+
132
+ # Decremenets a count metric.
133
+ def dec(namespace, metric_name, value, tags: {}, common: true)
134
+ @metrics_manager.dec(namespace, metric_name, value, tags: tags, common: common)
135
+ end
136
+
137
+ # Tracks gauge metric.
138
+ def gauge(namespace, metric_name, value, tags: {}, common: true)
139
+ @metrics_manager.gauge(namespace, metric_name, value, tags: tags, common: common)
140
+ end
141
+
142
+ # Tracks rate metric.
143
+ def rate(namespace, metric_name, value, tags: {}, common: true)
144
+ @metrics_manager.rate(namespace, metric_name, value, tags: tags, common: common)
145
+ end
146
+
147
+ # Tracks distribution metric.
148
+ def distribution(namespace, metric_name, value, tags: {}, common: true)
149
+ @metrics_manager.distribution(namespace, metric_name, value, tags: tags, common: common)
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end