datadog 2.31.0 → 2.33.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 (202) hide show
  1. checksums.yaml +4 -4
  2. data/ext/datadog_profiling_native_extension/clock_id.h +9 -1
  3. data/ext/datadog_profiling_native_extension/clock_id_from_mach.c +73 -0
  4. data/ext/datadog_profiling_native_extension/clock_id_from_pthread.c +1 -1
  5. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +17 -7
  6. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +16 -5
  7. data/ext/datadog_profiling_native_extension/collectors_thread_context.h +6 -0
  8. data/ext/datadog_profiling_native_extension/extconf.rb +8 -4
  9. data/ext/datadog_profiling_native_extension/http_transport.c +10 -5
  10. data/ext/datadog_profiling_native_extension/stack_recorder.c +3 -9
  11. data/ext/datadog_profiling_native_extension/time_helpers.h +1 -0
  12. data/ext/libdatadog_api/crashtracker.c +2 -0
  13. data/ext/libdatadog_api/di.c +48 -0
  14. data/ext/libdatadog_api/extconf.rb +7 -4
  15. data/ext/libdatadog_extconf_helpers.rb +38 -1
  16. data/lib/datadog/ai_guard/autoload.rb +10 -0
  17. data/lib/datadog/ai_guard/component.rb +1 -1
  18. data/lib/datadog/ai_guard/configuration.rb +105 -2
  19. data/lib/datadog/ai_guard/contrib/auto_instrument.rb +24 -0
  20. data/lib/datadog/ai_guard/contrib/rack/integration.rb +42 -0
  21. data/lib/datadog/ai_guard/contrib/rack/patcher.rb +26 -0
  22. data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +83 -0
  23. data/lib/datadog/ai_guard/contrib/rails/integration.rb +41 -0
  24. data/lib/datadog/ai_guard/contrib/rails/patcher.rb +97 -0
  25. data/lib/datadog/ai_guard/evaluation.rb +2 -0
  26. data/lib/datadog/ai_guard/ext.rb +2 -0
  27. data/lib/datadog/ai_guard.rb +8 -0
  28. data/lib/datadog/appsec/autoload.rb +1 -1
  29. data/lib/datadog/appsec/component.rb +1 -1
  30. data/lib/datadog/appsec/configuration.rb +414 -1
  31. data/lib/datadog/appsec/contrib/aws_lambda/gateway/watcher.rb +75 -0
  32. data/lib/datadog/appsec/contrib/aws_lambda/integration.rb +39 -0
  33. data/lib/datadog/appsec/contrib/aws_lambda/patcher.rb +30 -0
  34. data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +111 -0
  35. data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +2 -1
  36. data/lib/datadog/appsec/contrib/rack/gateway/request.rb +1 -1
  37. data/lib/datadog/appsec/contrib/rails/patcher.rb +2 -2
  38. data/lib/datadog/appsec/metrics/telemetry.rb +13 -1
  39. data/lib/datadog/appsec/security_engine/runner.rb +1 -1
  40. data/lib/datadog/appsec/trace_keeper.rb +18 -6
  41. data/lib/datadog/appsec/utils/http/url_encoded.rb +2 -2
  42. data/lib/datadog/appsec.rb +1 -0
  43. data/lib/datadog/core/configuration/components.rb +1 -1
  44. data/lib/datadog/core/configuration/settings.rb +13 -0
  45. data/lib/datadog/core/configuration/supported_configurations.rb +4 -0
  46. data/lib/datadog/core/configuration.rb +1 -1
  47. data/lib/datadog/core/contrib/rails/utils.rb +1 -1
  48. data/lib/datadog/core/crashtracking/component.rb +3 -3
  49. data/lib/datadog/core/diagnostics/environment_logger.rb +3 -1
  50. data/lib/datadog/core/environment/container.rb +2 -2
  51. data/lib/datadog/core/environment/ext.rb +1 -0
  52. data/lib/datadog/core/environment/socket.rb +13 -0
  53. data/lib/datadog/core/feature_flags.rb +1 -1
  54. data/lib/datadog/core/metrics/client.rb +5 -5
  55. data/lib/datadog/core/remote/client.rb +1 -1
  56. data/lib/datadog/core/remote/component.rb +2 -2
  57. data/lib/datadog/core/runtime/metrics.rb +1 -1
  58. data/lib/datadog/core/telemetry/emitter.rb +1 -1
  59. data/lib/datadog/core/telemetry/event/app_started.rb +2 -2
  60. data/lib/datadog/core/transport/http.rb +2 -0
  61. data/lib/datadog/core/utils.rb +1 -1
  62. data/lib/datadog/core/workers/async.rb +1 -1
  63. data/lib/datadog/core.rb +1 -1
  64. data/lib/datadog/data_streams/configuration.rb +40 -1
  65. data/lib/datadog/data_streams/pathway_context.rb +1 -1
  66. data/lib/datadog/data_streams/processor.rb +1 -1
  67. data/lib/datadog/data_streams.rb +1 -1
  68. data/lib/datadog/di/base.rb +8 -5
  69. data/lib/datadog/di/code_tracker.rb +179 -1
  70. data/lib/datadog/di/component.rb +1 -1
  71. data/lib/datadog/di/configuration.rb +235 -2
  72. data/lib/datadog/di/instrumenter.rb +46 -26
  73. data/lib/datadog/di/probe_builder.rb +1 -1
  74. data/lib/datadog/di/probe_file_loader.rb +2 -2
  75. data/lib/datadog/di/probe_manager.rb +6 -6
  76. data/lib/datadog/di/probe_notification_builder.rb +1 -1
  77. data/lib/datadog/di/probe_notifier_worker.rb +2 -2
  78. data/lib/datadog/di/remote.rb +6 -6
  79. data/lib/datadog/di/serializer.rb +1 -1
  80. data/lib/datadog/di/transport/input.rb +3 -3
  81. data/lib/datadog/error_tracking/configuration.rb +55 -2
  82. data/lib/datadog/kit/enable_core_dumps.rb +1 -1
  83. data/lib/datadog/open_feature/component.rb +18 -1
  84. data/lib/datadog/open_feature/evaluation_engine.rb +3 -3
  85. data/lib/datadog/open_feature/exposures/reporter.rb +1 -1
  86. data/lib/datadog/open_feature/exposures/worker.rb +1 -1
  87. data/lib/datadog/open_feature/hooks/flag_eval_hook.rb +49 -0
  88. data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +149 -0
  89. data/lib/datadog/open_feature/provider.rb +19 -1
  90. data/lib/datadog/open_feature/remote.rb +1 -1
  91. data/lib/datadog/open_feature/transport.rb +1 -1
  92. data/lib/datadog/opentelemetry/metrics.rb +13 -4
  93. data/lib/datadog/opentelemetry/sdk/configurator.rb +1 -1
  94. data/lib/datadog/opentelemetry/sdk/id_generator.rb +16 -10
  95. data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +1 -1
  96. data/lib/datadog/profiling/collectors/code_provenance.rb +35 -9
  97. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +31 -2
  98. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +8 -2
  99. data/lib/datadog/profiling/collectors/info.rb +16 -3
  100. data/lib/datadog/profiling/component.rb +3 -6
  101. data/lib/datadog/profiling/exporter.rb +37 -12
  102. data/lib/datadog/profiling/ext.rb +0 -2
  103. data/lib/datadog/profiling/flush.rb +21 -12
  104. data/lib/datadog/profiling/http_transport.rb +12 -1
  105. data/lib/datadog/profiling/load_native_extension.rb +1 -1
  106. data/lib/datadog/profiling/profiler.rb +13 -1
  107. data/lib/datadog/profiling/scheduler.rb +2 -2
  108. data/lib/datadog/profiling/stack_recorder.rb +0 -4
  109. data/lib/datadog/profiling/tasks/exec.rb +8 -3
  110. data/lib/datadog/profiling/tasks/help.rb +1 -0
  111. data/lib/datadog/profiling/tasks/setup.rb +2 -2
  112. data/lib/datadog/single_step_instrument.rb +1 -1
  113. data/lib/datadog/symbol_database/configuration.rb +65 -0
  114. data/lib/datadog/symbol_database/extractor.rb +906 -0
  115. data/lib/datadog/symbol_database/file_hash.rb +46 -0
  116. data/lib/datadog/symbol_database/logger.rb +43 -0
  117. data/lib/datadog/symbol_database/scope.rb +102 -0
  118. data/lib/datadog/symbol_database/scope_batcher.rb +280 -0
  119. data/lib/datadog/symbol_database/service_version.rb +57 -0
  120. data/lib/datadog/symbol_database/symbol.rb +66 -0
  121. data/lib/datadog/symbol_database/transport/http/endpoint.rb +28 -0
  122. data/lib/datadog/symbol_database/transport/http.rb +45 -0
  123. data/lib/datadog/symbol_database/transport.rb +54 -0
  124. data/lib/datadog/symbol_database/uploader.rb +169 -0
  125. data/lib/datadog/symbol_database.rb +49 -0
  126. data/lib/datadog/tracing/buffer.rb +3 -3
  127. data/lib/datadog/tracing/configuration/settings.rb +1 -1
  128. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +5 -3
  129. data/lib/datadog/tracing/contrib/action_view/events/render_template.rb +1 -1
  130. data/lib/datadog/tracing/contrib/active_job/events/discard.rb +1 -1
  131. data/lib/datadog/tracing/contrib/active_job/events/enqueue.rb +1 -1
  132. data/lib/datadog/tracing/contrib/active_job/events/enqueue_at.rb +1 -1
  133. data/lib/datadog/tracing/contrib/active_job/events/enqueue_retry.rb +1 -1
  134. data/lib/datadog/tracing/contrib/active_job/events/perform.rb +1 -1
  135. data/lib/datadog/tracing/contrib/active_job/events/retry_stopped.rb +1 -1
  136. data/lib/datadog/tracing/contrib/active_model_serializers/events/render.rb +1 -1
  137. data/lib/datadog/tracing/contrib/active_model_serializers/events/serialize.rb +1 -1
  138. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +2 -2
  139. data/lib/datadog/tracing/contrib/active_record/events/instantiation.rb +1 -1
  140. data/lib/datadog/tracing/contrib/active_record/events/sql.rb +1 -1
  141. data/lib/datadog/tracing/contrib/active_record/utils.rb +1 -1
  142. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +1 -1
  143. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +2 -2
  144. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +1 -1
  145. data/lib/datadog/tracing/contrib/component.rb +1 -1
  146. data/lib/datadog/tracing/contrib/configuration/resolver.rb +7 -4
  147. data/lib/datadog/tracing/contrib/dalli/quantize.rb +1 -1
  148. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +1 -1
  149. data/lib/datadog/tracing/contrib/excon/middleware.rb +2 -2
  150. data/lib/datadog/tracing/contrib/extensions.rb +9 -0
  151. data/lib/datadog/tracing/contrib/faraday/middleware.rb +2 -2
  152. data/lib/datadog/tracing/contrib/grape/endpoint.rb +5 -5
  153. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +2 -2
  154. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +2 -2
  155. data/lib/datadog/tracing/contrib/http/instrumentation.rb +2 -2
  156. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +6 -2
  157. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +2 -2
  158. data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +2 -2
  159. data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +2 -2
  160. data/lib/datadog/tracing/contrib/karafka/patcher.rb +1 -1
  161. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +3 -3
  162. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +1 -1
  163. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +3 -3
  164. data/lib/datadog/tracing/contrib/rack/configuration/settings.rb +6 -0
  165. data/lib/datadog/tracing/contrib/rack/ext.rb +27 -0
  166. data/lib/datadog/tracing/contrib/rack/patcher.rb +1 -1
  167. data/lib/datadog/tracing/contrib/rack/request_queue.rb +1 -1
  168. data/lib/datadog/tracing/contrib/rack/trace_proxy_middleware.rb +117 -1
  169. data/lib/datadog/tracing/contrib/rails/log_injection.rb +1 -1
  170. data/lib/datadog/tracing/contrib/rails/runner.rb +1 -1
  171. data/lib/datadog/tracing/contrib/rake/instrumentation.rb +2 -2
  172. data/lib/datadog/tracing/contrib/redis/quantize.rb +1 -1
  173. data/lib/datadog/tracing/contrib/redis/tags.rb +1 -1
  174. data/lib/datadog/tracing/contrib/sidekiq/utils.rb +1 -1
  175. data/lib/datadog/tracing/contrib/stripe/request.rb +1 -1
  176. data/lib/datadog/tracing/contrib.rb +8 -0
  177. data/lib/datadog/tracing/diagnostics/environment_logger.rb +3 -1
  178. data/lib/datadog/tracing/distributed/baggage.rb +59 -5
  179. data/lib/datadog/tracing/distributed/datadog.rb +11 -11
  180. data/lib/datadog/tracing/distributed/datadog_tags_codec.rb +1 -1
  181. data/lib/datadog/tracing/distributed/propagation.rb +2 -2
  182. data/lib/datadog/tracing/distributed/trace_context.rb +74 -32
  183. data/lib/datadog/tracing/event.rb +1 -1
  184. data/lib/datadog/tracing/metadata/tagging.rb +2 -2
  185. data/lib/datadog/tracing/pipeline.rb +1 -1
  186. data/lib/datadog/tracing/remote.rb +1 -1
  187. data/lib/datadog/tracing/sampling/rule.rb +1 -1
  188. data/lib/datadog/tracing/sampling/rule_sampler.rb +2 -2
  189. data/lib/datadog/tracing/sampling/span/rule_parser.rb +2 -2
  190. data/lib/datadog/tracing/span_operation.rb +3 -3
  191. data/lib/datadog/tracing/trace_operation.rb +4 -4
  192. data/lib/datadog/tracing/tracer.rb +6 -8
  193. data/lib/datadog/tracing/transport/io/client.rb +1 -1
  194. data/lib/datadog/tracing/workers.rb +2 -1
  195. data/lib/datadog/version.rb +1 -1
  196. metadata +33 -12
  197. data/ext/datadog_profiling_native_extension/clock_id_noop.c +0 -21
  198. data/lib/datadog/ai_guard/configuration/settings.rb +0 -113
  199. data/lib/datadog/appsec/configuration/settings.rb +0 -423
  200. data/lib/datadog/data_streams/configuration/settings.rb +0 -49
  201. data/lib/datadog/di/configuration/settings.rb +0 -243
  202. data/lib/datadog/error_tracking/configuration/settings.rb +0 -63
@@ -1,23 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../../tracing/utils'
4
+
3
5
  module Datadog
4
6
  module OpenTelemetry
5
7
  module SDK
6
- # Generates Datadog-compatible IDs for OpenTelemetry traces.
7
- # OpenTelemetry traces already produce Datadog-compatible IDs.
8
+ # Generates Datadog-compatible trace IDs for OpenTelemetry spans.
9
+ #
10
+ # Reuses the same 128-bit ID format as non-OTel Datadog tracing:
11
+ # [32-bit seconds since Epoch | 32 zero bits | 64 random bits]
12
+ #
13
+ # When DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED is false the high 64
14
+ # bits are zero, preserving the OTel 16-byte wire format while keeping
15
+ # backward compatibility with 64-bit Datadog trace IDs.
8
16
  class IdGenerator
9
17
  class << self
10
18
  include ::OpenTelemetry::Trace
11
19
 
12
- # Generates a valid trace identifier, a 16-byte string with at least one
13
- # non-zero byte.
14
- #
15
- # @return [String] a valid trace ID.
20
+ # @return [String] a valid 16-byte trace ID.
16
21
  def generate_trace_id
17
- loop do
18
- id = Random.bytes(8) # DEV: Change to 16 (16*8-byte) when 128-bit trace_id is supported.
19
- return id unless id == ::OpenTelemetry::Trace::INVALID_SPAN_ID
20
- end
22
+ trace_id = Tracing::Utils::TraceId.next_id
23
+ [
24
+ Tracing::Utils::TraceId.to_high_order(trace_id),
25
+ Tracing::Utils::TraceId.to_low_order(trace_id),
26
+ ].pack('Q>Q>')
21
27
  end
22
28
  end
23
29
  end
@@ -19,7 +19,7 @@ module Datadog
19
19
  telemetry&.inc(TELEMETRY_NAMESPACE, metric_name, 1, tags: TELEMETRY_TAGS)
20
20
  result
21
21
  rescue => e
22
- Datadog.logger.error("Failed to export OpenTelemetry Metrics: #{e.class}: #{e}")
22
+ Datadog.logger.error("Failed to export OpenTelemetry Metrics: #{e.class}: #{e.message}")
23
23
  telemetry&.inc(TELEMETRY_NAMESPACE, METRIC_EXPORT_FAILURES, 1, tags: TELEMETRY_TAGS)
24
24
  raise
25
25
  end
@@ -14,6 +14,9 @@ module Datadog
14
14
  #
15
15
  # This class acts both as a collector (collecting data) as well as a recorder (records/serializes it)
16
16
  class CodeProvenance
17
+ # @rbs standard_library_path: ::String
18
+ # @rbs ruby_native_filename: ::String?
19
+ # @rbs return: void
17
20
  def initialize(
18
21
  standard_library_path: RbConfig::CONFIG.fetch("rubylibdir"),
19
22
  ruby_native_filename: Datadog::Profiling::Collectors::Stack._native_ruby_native_filename
@@ -35,6 +38,9 @@ module Datadog
35
38
  )
36
39
  end
37
40
 
41
+ # @rbs loaded_files: ::Array[::String]
42
+ # @rbs loaded_specs: ::Array[::Gem::BasicSpecification]
43
+ # @rbs return: self
38
44
  def refresh(loaded_files: $LOADED_FEATURES, loaded_specs: Gem.loaded_specs.values)
39
45
  record_loaded_specs(loaded_specs)
40
46
  record_loaded_files(loaded_files)
@@ -42,19 +48,20 @@ module Datadog
42
48
  self
43
49
  end
44
50
 
51
+ #: () -> ::String
45
52
  def generate_json
46
53
  JSON.generate(v1: seen_libraries.to_a)
47
54
  end
48
55
 
49
56
  private
50
57
 
51
- attr_reader \
52
- :libraries_by_name,
53
- :libraries_by_path,
54
- :seen_files,
55
- :seen_libraries,
56
- :executable_paths
58
+ attr_reader :libraries_by_name #: ::Hash[::String, Library]
59
+ attr_reader :libraries_by_path #: ::Hash[::String, Library]
60
+ attr_reader :seen_files #: ::Set[::String]
61
+ attr_reader :seen_libraries #: ::Set[Library]
62
+ attr_reader :executable_paths #: ::Array[::String]
57
63
 
64
+ #: (Library) -> void
58
65
  def record_library(library)
59
66
  libraries_by_name[library.name] = library
60
67
  libraries_by_path[library.path] = library
@@ -71,10 +78,12 @@ module Datadog
71
78
  #
72
79
  # Alternatively/in the future we could instead use a trie to match paths, but I doubt for the data sizes we're
73
80
  # looking at that a trie is that much faster than using Ruby's built-in native collections.
81
+ #: () -> void
74
82
  def sort_libraries_by_longest_path_first
75
83
  @libraries_by_path = @libraries_by_path.sort.reverse!.to_h
76
84
  end
77
85
 
86
+ #: (::Array[::Gem::BasicSpecification]) -> void
78
87
  def record_loaded_specs(loaded_specs)
79
88
  recorded_library = false
80
89
 
@@ -103,6 +112,7 @@ module Datadog
103
112
  sort_libraries_by_longest_path_first if recorded_library
104
113
  end
105
114
 
115
+ #: (::Array[::String]) -> void
106
116
  def record_loaded_files(loaded_files)
107
117
  loaded_files.each do |file_path|
108
118
  next if seen_files.include?(file_path)
@@ -125,6 +135,7 @@ module Datadog
125
135
  # bundler complaints here impacting the application. (Bundler tends to go "something is wrong, raise!" which
126
136
  # I think makes a lot of sense given how bundler is intended to be used, but for this our kind of "ask a few
127
137
  # questions usage" it's not what we want.)
138
+ #: () -> ::String?
128
139
  def bundler_bin_path
129
140
  return unless defined?(Bundler)
130
141
 
@@ -135,7 +146,7 @@ module Datadog
135
146
  rescue Exception => e # rubocop:disable Lint/RescueException
136
147
  Datadog.logger.debug(
137
148
  "CodeProvenance#bundler_bin_path failed. " \
138
- "Cause: #{e.class}: #{e} Location: #{Array(e.backtrace).first}"
149
+ "Cause: #{e.class}: #{e.message} Location: #{Array(e.backtrace).first}"
139
150
  )
140
151
  nil
141
152
  end
@@ -149,8 +160,21 @@ module Datadog
149
160
  # Thus, this class was setup to match the JSON output. Take this into consideration if you are adding new
150
161
  # fields. (Also, we have a spec for this)
151
162
  class Library
152
- attr_reader :kind, :name, :version
153
-
163
+ # @rbs @kind: ::String
164
+ # @rbs @name: ::String
165
+ # @rbs @version: ::String
166
+ # @rbs @paths: ::Array[::String]
167
+
168
+ attr_reader :kind #: ::String
169
+ attr_reader :name #: ::String
170
+ attr_reader :version #: ::String
171
+
172
+ # @rbs kind: ::String
173
+ # @rbs name: ::String
174
+ # @rbs version: ::String | ::Gem::Version
175
+ # @rbs path: ::String
176
+ # @rbs extra_paths: ::Array[::String?]
177
+ # @rbs return: void
154
178
  def initialize(kind:, name:, version:, path:, extra_paths:)
155
179
  extra_paths = Array(extra_paths).compact.reject(&:empty?).map { |p| p.dup.freeze }
156
180
  @kind = kind.freeze
@@ -160,10 +184,12 @@ module Datadog
160
184
  freeze
161
185
  end
162
186
 
187
+ #: (?::JSON::State?) -> ::String
163
188
  def to_json(arg = nil)
164
189
  {kind: @kind, name: @name, version: @version, paths: @paths}.to_json(arg)
165
190
  end
166
191
 
192
+ #: () -> ::String
167
193
  def path
168
194
  @paths.first
169
195
  end
@@ -9,12 +9,32 @@ module Datadog
9
9
  #
10
10
  # Methods prefixed with _native_ are implemented in `collectors_cpu_and_wall_time_worker.c`
11
11
  class CpuAndWallTimeWorker
12
+ # @rbs @worker_thread: untyped
13
+ # @rbs @start_stop_mutex: ::Thread::Mutex
14
+ # @rbs @failure_exception: ::Exception?
15
+ # @rbs @idle_sampling_helper: IdleSamplingHelper
16
+ # @rbs @wait_until_running_mutex: ::Thread::Mutex
17
+ # @rbs @wait_until_running_condition: ::Thread::ConditionVariable
18
+
12
19
  private
13
20
 
14
- attr_accessor :failure_exception
21
+ attr_accessor :failure_exception #: ::Exception?
15
22
 
16
23
  public
17
24
 
25
+ # @rbs gc_profiling_enabled: bool
26
+ # @rbs no_signals_workaround_enabled: bool
27
+ # @rbs thread_context_collector: Datadog::Profiling::Collectors::ThreadContext
28
+ # @rbs dynamic_sampling_rate_overhead_target_percentage: Float
29
+ # @rbs cpu_sampling_interval_ms: ::Integer
30
+ # @rbs idle_sampling_helper: Datadog::Profiling::Collectors::IdleSamplingHelper
31
+ # @rbs dynamic_sampling_rate_enabled: bool
32
+ # @rbs allocation_profiling_enabled: bool
33
+ # @rbs allocation_counting_enabled: bool
34
+ # @rbs gvl_profiling_enabled: bool
35
+ # @rbs sighandler_sampling_enabled: bool
36
+ # @rbs skip_idle_samples_for_testing: false
37
+ # @rbs return: void
18
38
  def initialize(
19
39
  gc_profiling_enabled:,
20
40
  no_signals_workaround_enabled:,
@@ -67,6 +87,8 @@ module Datadog
67
87
  @wait_until_running_condition = ConditionVariable.new
68
88
  end
69
89
 
90
+ # @rbs on_failure_proc: (^(?log_failure: bool) -> void)?
91
+ # @rbs return: bool?
70
92
  def start(on_failure_proc: nil)
71
93
  @start_stop_mutex.synchronize do
72
94
  return if @worker_thread&.alive?
@@ -93,7 +115,7 @@ module Datadog
93
115
  operation_name = self.class._native_failure_exception_during_operation(self).inspect
94
116
  Datadog.logger.warn(
95
117
  "CpuAndWallTimeWorker thread error. " \
96
- "Operation: #{operation_name} Cause: #{e.class}: #{e} Location: #{Array(e.backtrace).first}"
118
+ "Operation: #{operation_name} Cause: #{e.class}: #{e.message} Location: #{Array(e.backtrace).first}"
97
119
  )
98
120
  on_failure_proc&.call
99
121
  Datadog::Core::Telemetry::Logger.report(e, description: "CpuAndWallTimeWorker thread error: #{operation_name}")
@@ -105,6 +127,7 @@ module Datadog
105
127
  true
106
128
  end
107
129
 
130
+ #: () -> void
108
131
  def stop
109
132
  @start_stop_mutex.synchronize do
110
133
  Datadog.logger.debug("Requesting CpuAndWallTimeWorker thread shut down")
@@ -121,14 +144,17 @@ module Datadog
121
144
  end
122
145
  end
123
146
 
147
+ #: () -> true
124
148
  def reset_after_fork
125
149
  self.class._native_reset_after_fork(self)
126
150
  end
127
151
 
152
+ #: () -> ::Hash[::Symbol, untyped]
128
153
  def stats
129
154
  self.class._native_stats(self)
130
155
  end
131
156
 
157
+ #: () -> ::Hash[::Symbol, untyped]
132
158
  def stats_and_reset_not_thread_safe
133
159
  stats = self.stats
134
160
  self.class._native_stats_reset_not_thread_safe(self)
@@ -136,6 +162,8 @@ module Datadog
136
162
  end
137
163
 
138
164
  # Useful for testing, to e.g. make sure the profiler is running before we start running some code we want to observe
165
+ # @rbs timeout_seconds: ::Integer?
166
+ # @rbs return: true
139
167
  def wait_until_running(timeout_seconds: 5)
140
168
  @wait_until_running_mutex.synchronize do
141
169
  return true if self.class._native_is_running?(self)
@@ -152,6 +180,7 @@ module Datadog
152
180
 
153
181
  private
154
182
 
183
+ #: () -> void
155
184
  def signal_running
156
185
  @wait_until_running_mutex.synchronize { @wait_until_running_condition.broadcast }
157
186
  end
@@ -8,17 +8,22 @@ module Datadog
8
8
  #
9
9
  # Methods prefixed with _native_ are implemented in `collectors_idle_sampling_helper.c`
10
10
  class IdleSamplingHelper
11
+ # @rbs @worker_thread: untyped
12
+ # @rbs @start_stop_mutex: ::Thread::Mutex
13
+
11
14
  private
12
15
 
13
- attr_accessor :failure_exception
16
+ attr_accessor :failure_exception #: ::Exception?
14
17
 
15
18
  public
16
19
 
20
+ #: () -> void
17
21
  def initialize
18
22
  @worker_thread = nil
19
23
  @start_stop_mutex = Mutex.new
20
24
  end
21
25
 
26
+ #: () -> (nil | true)
22
27
  def start
23
28
  @start_stop_mutex.synchronize do
24
29
  return if @worker_thread&.alive?
@@ -39,7 +44,7 @@ module Datadog
39
44
  @failure_exception = e
40
45
  Datadog.logger.warn(
41
46
  "IdleSamplingHelper thread error. " \
42
- "Cause: #{e.class}: #{e} Location: #{Array(e.backtrace).first}"
47
+ "Cause: #{e.class}: #{e.message} Location: #{Array(e.backtrace).first}"
43
48
  )
44
49
  Datadog::Core::Telemetry::Logger.report(e, description: "IdleSamplingHelper thread error")
45
50
  end
@@ -50,6 +55,7 @@ module Datadog
50
55
  true
51
56
  end
52
57
 
58
+ #: () -> void
53
59
  def stop
54
60
  @start_stop_mutex.synchronize do
55
61
  Datadog.logger.debug("Requesting IdleSamplingHelper thread shut down")
@@ -14,11 +14,18 @@ module Datadog
14
14
  # could be seen as overkill for this case but it allows us to centralize information
15
15
  # gathering and easily support more flexible/dynamic info collection in the future.
16
16
  class Info
17
+ # @rbs @info: ::Hash[::Symbol, ::Hash[::Symbol, untyped]]
18
+ # @rbs @platform_info: ::Hash[::Symbol, untyped]
19
+ # @rbs @runtime_info: ::Hash[::Symbol, untyped]
20
+ # @rbs @application_info: ::Hash[::Symbol, untyped]
21
+ # @rbs @profiler_info: ::Hash[::Symbol, untyped]?
22
+ # @rbs @gc_tuning_info: ::Hash[::Symbol, ::String]
23
+
24
+ #: (untyped) -> void
17
25
  def initialize(settings)
18
26
  @profiler_info = nil
19
27
 
20
- # Steep: https://github.com/soutaro/steep/issues/363
21
- @info = { # steep:ignore IncompatibleAssignment
28
+ @info = {
22
29
  platform: collect_platform_info,
23
30
  runtime: collect_runtime_info,
24
31
  application: collect_application_info(settings),
@@ -26,7 +33,7 @@ module Datadog
26
33
  }.freeze
27
34
  end
28
35
 
29
- attr_reader :info
36
+ attr_reader :info #: ::Hash[::Symbol, ::Hash[::Symbol, untyped]]
30
37
 
31
38
  private
32
39
 
@@ -69,6 +76,7 @@ module Datadog
69
76
  # gets initialized before a user has a chance to configure the library.
70
77
  START_TIME = Time.now.utc.freeze
71
78
 
79
+ #: () -> ::Hash[::Symbol, untyped]
72
80
  def collect_platform_info
73
81
  @platform_info ||= {
74
82
  container_id: Datadog::Core::Environment::Container.container_id,
@@ -79,6 +87,7 @@ module Datadog
79
87
  }.freeze
80
88
  end
81
89
 
90
+ #: () -> ::Hash[::Symbol, untyped]
82
91
  def collect_runtime_info
83
92
  @runtime_info ||= {
84
93
  engine: Datadog::Core::Environment::Identity.lang_engine,
@@ -88,6 +97,7 @@ module Datadog
88
97
  }.freeze
89
98
  end
90
99
 
100
+ #: (untyped) -> ::Hash[::Symbol, untyped]
91
101
  def collect_application_info(settings)
92
102
  @application_info ||= {
93
103
  start_time: START_TIME.iso8601,
@@ -97,6 +107,7 @@ module Datadog
97
107
  }.freeze
98
108
  end
99
109
 
110
+ #: (untyped) -> ::Hash[::Symbol, untyped]
100
111
  def collect_profiler_info(settings)
101
112
  @profiler_info ||= begin
102
113
  lib_datadog_gem = ::Gem.loaded_specs["libdatadog"]
@@ -123,6 +134,7 @@ module Datadog
123
134
  # instances without proper serialization.
124
135
  # This method navigates a settings object recursively, converting
125
136
  # it into more basic types that are trivially convertible to JSON.
137
+ #: (untyped) -> untyped
126
138
  def collect_settings_recursively(v)
127
139
  v = v.options_hash if v.respond_to?(:options_hash)
128
140
 
@@ -143,6 +155,7 @@ module Datadog
143
155
  end
144
156
  end
145
157
 
158
+ #: () -> ::Hash[::Symbol, ::String]
146
159
  def collect_gc_tuning_info
147
160
  return @gc_tuning_info if defined?(@gc_tuning_info)
148
161
 
@@ -10,8 +10,6 @@ module Datadog
10
10
  # * Profiling in the trace viewer, as well as scoping a profile down to a span
11
11
  # * Endpoint aggregation in the profiler UX, including normalization (resource per endpoint call)
12
12
  def self.build_profiler_component(settings:, agent_settings:, optional_tracer:, logger:) # rubocop:disable Metrics/MethodLength
13
- return [nil, {profiling_enabled: false}] unless settings.profiling.enabled
14
-
15
13
  # Workaround for weird dependency direction: the Core::Configuration::Components class currently has a
16
14
  # dependency on individual products, in this case the Profiler.
17
15
  # (Note "currently": in the future we want to change this so core classes don't depend on specific products)
@@ -31,7 +29,7 @@ module Datadog
31
29
  # no-op if profiling is already loaded).
32
30
  require_relative "../profiling"
33
31
 
34
- return [nil, {profiling_enabled: false}] unless Profiling.supported?
32
+ return [nil, {profiling_enabled: false}] unless settings.profiling.enabled && Profiling.supported?
35
33
 
36
34
  # Activate forking extensions
37
35
  Profiling::Tasks::Setup.new.run
@@ -51,7 +49,6 @@ module Datadog
51
49
  valid_cpu_sampling_interval(settings.profiling.advanced.experimental_cpu_sampling_interval_ms, logger)
52
50
 
53
51
  recorder = Datadog::Profiling::StackRecorder.new(
54
- cpu_time_enabled: RUBY_PLATFORM.include?("linux"), # Only supported on Linux currently
55
52
  alloc_samples_enabled: allocation_profiling_enabled,
56
53
  heap_samples_enabled: heap_profiling_enabled,
57
54
  heap_size_enabled: heap_size_profiling_enabled,
@@ -94,7 +91,7 @@ module Datadog
94
91
  [profiler, {profiling_enabled: true}]
95
92
  rescue Exception => e # rubocop:disable Lint/RescueException
96
93
  logger.warn do
97
- "Failed to initialize profiling: #{e.class}: #{e} " \
94
+ "Failed to initialize profiling: #{e.class}: #{e.message} " \
98
95
  "Location: #{Array(e.backtrace).first}"
99
96
  end
100
97
  Datadog::Core::Telemetry::Logger.report(e, description: "Failed to initialize profiling")
@@ -378,7 +375,7 @@ module Datadog
378
375
  rescue StandardError, LoadError => e
379
376
  logger.warn(
380
377
  "Failed to probe `mysql2` gem information. " \
381
- "Cause: #{e.class}: #{e} Location: #{Array(e.backtrace).first}"
378
+ "Cause: #{e.class}: #{e.message} Location: #{Array(e.backtrace).first}"
382
379
  )
383
380
 
384
381
  true
@@ -13,24 +13,35 @@ module Datadog
13
13
  # recorders, so I've decided to make it specific until we actually need to support more recorders.
14
14
  #
15
15
  class Exporter
16
+ # @rbs @worker: Datadog::Profiling::Collectors::CpuAndWallTimeWorker
17
+
16
18
  # Profiles with duration less than this will not be reported
17
19
  PROFILE_DURATION_THRESHOLD_SECONDS = 1
18
20
 
19
21
  private
20
22
 
21
- attr_reader \
22
- :pprof_recorder,
23
- :code_provenance_collector, # The code provenance collector acts both as collector and as a recorder
24
- :minimum_duration_seconds,
25
- :time_provider,
26
- :last_flush_finish_at,
27
- :created_at,
28
- :internal_metadata,
29
- :info_json,
30
- :sequence_tracker
23
+ attr_reader :pprof_recorder #: Datadog::Profiling::StackRecorder
24
+ # The code provenance collector acts both as collector and as a recorder
25
+ attr_reader :code_provenance_collector #: Datadog::Profiling::Collectors::CodeProvenance?
26
+ attr_reader :minimum_duration_seconds #: ::Integer
27
+ attr_reader :time_provider #: singleton(::Time)
28
+ attr_reader :last_flush_finish_at #: ::Time?
29
+ attr_reader :created_at #: ::Time
30
+ attr_reader :internal_metadata #: ::Hash[::Symbol, untyped]
31
+ attr_reader :info_json #: ::String
32
+ attr_reader :sequence_tracker #: singleton(Datadog::Profiling::SequenceTracker)
31
33
 
32
34
  public
33
35
 
36
+ # @rbs pprof_recorder: Datadog::Profiling::StackRecorder
37
+ # @rbs worker: Datadog::Profiling::Collectors::CpuAndWallTimeWorker
38
+ # @rbs info_collector: Datadog::Profiling::Collectors::Info
39
+ # @rbs code_provenance_collector: Datadog::Profiling::Collectors::CodeProvenance?
40
+ # @rbs internal_metadata: ::Hash[::Symbol, untyped]
41
+ # @rbs minimum_duration_seconds: ::Integer
42
+ # @rbs time_provider: singleton(::Time)
43
+ # @rbs sequence_tracker: singleton(Datadog::Profiling::SequenceTracker)
44
+ # @rbs return: void
34
45
  def initialize(
35
46
  pprof_recorder:,
36
47
  worker:,
@@ -55,6 +66,7 @@ module Datadog
55
66
  @sequence_tracker = sequence_tracker
56
67
  end
57
68
 
69
+ #: () -> Datadog::Profiling::Flush?
58
70
  def flush
59
71
  worker_stats = @worker.stats_and_reset_not_thread_safe
60
72
  serialization_result = pprof_recorder.serialize
@@ -68,7 +80,17 @@ module Datadog
68
80
  return
69
81
  end
70
82
 
71
- uncompressed_code_provenance = code_provenance_collector.refresh.generate_json if code_provenance_collector
83
+ uncompressed_code_provenance =
84
+ if (collector = code_provenance_collector)
85
+ collector.refresh.generate_json
86
+ end
87
+
88
+ metrics = [] #: Array[[::String, ::Numeric]]
89
+
90
+ # The key is always there, but the value might be nil if GVL profiling is disabled.
91
+ # We delete it to avoid reporting the same data point twice.
92
+ gvl_waiting_time_ns_total = worker_stats.delete(:gvl_waiting_time_ns_total)
93
+ metrics << ["ruby_global_lock_wait_time_total", gvl_waiting_time_ns_total] if gvl_waiting_time_ns_total
72
94
 
73
95
  process_tags = Datadog.configuration.experimental_propagate_process_tags_enabled ?
74
96
  Core::Environment::Process.serialized : ''
@@ -77,8 +99,8 @@ module Datadog
77
99
  start: start,
78
100
  finish: finish,
79
101
  encoded_profile: encoded_profile,
80
- code_provenance_file_name: Datadog::Profiling::Ext::Transport::HTTP::CODE_PROVENANCE_FILENAME,
81
102
  code_provenance_data: uncompressed_code_provenance,
103
+ metrics: metrics,
82
104
  tags_as_array: Datadog::Profiling::TagBuilder.call(
83
105
  settings: Datadog.configuration,
84
106
  profile_seq: sequence_tracker.get_next,
@@ -96,10 +118,12 @@ module Datadog
96
118
  )
97
119
  end
98
120
 
121
+ #: () -> bool
99
122
  def can_flush?
100
123
  !duration_below_threshold?(last_flush_finish_at || created_at, time_provider.now.utc)
101
124
  end
102
125
 
126
+ #: () -> void
103
127
  def reset_after_fork
104
128
  @last_flush_finish_at = time_provider.now.utc
105
129
  nil
@@ -107,6 +131,7 @@ module Datadog
107
131
 
108
132
  private
109
133
 
134
+ #: (::Time, ::Time) -> bool
110
135
  def duration_below_threshold?(start, finish)
111
136
  (finish - start) < minimum_duration_seconds
112
137
  end
@@ -13,8 +13,6 @@ module Datadog
13
13
  module Transport
14
14
  module HTTP
15
15
  FORM_FIELD_TAG_PROFILER_VERSION = "profiler_version"
16
-
17
- CODE_PROVENANCE_FILENAME = "code-provenance.json"
18
16
  end
19
17
  end
20
18
  end
@@ -6,23 +6,32 @@ module Datadog
6
6
  module Profiling
7
7
  # Entity class used to represent metadata for a given profile
8
8
  class Flush
9
- attr_reader \
10
- :start,
11
- :finish,
12
- :encoded_profile,
13
- :code_provenance_file_name,
14
- :code_provenance_data,
15
- :tags_as_array,
16
- :process_tags,
17
- :internal_metadata_json,
18
- :info_json
9
+ attr_reader :start #: ::Time
10
+ attr_reader :finish #: ::Time
11
+ attr_reader :encoded_profile #: Datadog::Profiling::EncodedProfile
12
+ attr_reader :code_provenance_data #: ::String?
13
+ attr_reader :metrics #: ::String
14
+ attr_reader :tags_as_array #: Array[[::String, ::String]]
15
+ attr_reader :process_tags #: ::String
16
+ attr_reader :internal_metadata_json #: ::String
17
+ attr_reader :info_json #: ::String
19
18
 
19
+ # @rbs start: ::Time
20
+ # @rbs finish: ::Time
21
+ # @rbs encoded_profile: Datadog::Profiling::EncodedProfile
22
+ # @rbs code_provenance_data: ::String?
23
+ # @rbs metrics: Array[[::String, ::Numeric]]
24
+ # @rbs tags_as_array: Array[[::String, ::String]]
25
+ # @rbs process_tags: ::String
26
+ # @rbs internal_metadata: ::Hash[::Symbol, ::String | bool | ::Numeric]
27
+ # @rbs info_json: ::String
28
+ # @rbs return: void
20
29
  def initialize(
21
30
  start:,
22
31
  finish:,
23
32
  encoded_profile:,
24
- code_provenance_file_name:,
25
33
  code_provenance_data:,
34
+ metrics:,
26
35
  tags_as_array:,
27
36
  process_tags:,
28
37
  internal_metadata:,
@@ -31,8 +40,8 @@ module Datadog
31
40
  @start = start
32
41
  @finish = finish
33
42
  @encoded_profile = encoded_profile
34
- @code_provenance_file_name = code_provenance_file_name
35
43
  @code_provenance_data = code_provenance_data
44
+ @metrics = JSON.generate(metrics)
36
45
  @tags_as_array = tags_as_array
37
46
  @process_tags = process_tags
38
47
  @internal_metadata_json = JSON.generate(internal_metadata)
@@ -8,8 +8,16 @@ module Datadog
8
8
  # Used to report profiling data to Datadog.
9
9
  # Methods prefixed with _native_ are implemented in `http_transport.c`
10
10
  class HttpTransport
11
- attr_reader :exporter_configuration
11
+ # @rbs @exporter_configuration: exporter_configuration_array
12
12
 
13
+ attr_reader :exporter_configuration #: exporter_configuration_array
14
+
15
+ # @rbs agent_settings: Datadog::Core::Configuration::AgentSettings
16
+ # @rbs site: ::String?
17
+ # @rbs api_key: ::String?
18
+ # @rbs upload_timeout_seconds: ::Integer
19
+ # @rbs use_system_dns: bool
20
+ # @rbs return: void
13
21
  def initialize(agent_settings:, site:, api_key:, upload_timeout_seconds:, use_system_dns:)
14
22
  timeout_milliseconds = (upload_timeout_seconds * 1_000).to_i
15
23
 
@@ -28,6 +36,7 @@ module Datadog
28
36
  raise(ArgumentError, "Failed to initialize transport: #{result}") if status == :error
29
37
  end
30
38
 
39
+ #: (Datadog::Profiling::Flush) -> bool
31
40
  def export(flush)
32
41
  status, result = self.class._native_do_export(
33
42
  exporter_configuration,
@@ -57,10 +66,12 @@ module Datadog
57
66
 
58
67
  private
59
68
 
69
+ #: (::String?, ::String?) -> bool?
60
70
  def agentless?(site, api_key)
61
71
  site && api_key && %w[1 true].include?(ENV[Profiling::Ext::ENV_AGENTLESS] || '') # rubocop:disable CustomCops/EnvUsageCop
62
72
  end
63
73
 
74
+ #: () -> ::String
64
75
  def config_without_api_key
65
76
  "#{exporter_configuration[0]}: #{exporter_configuration[3]}"
66
77
  end
@@ -5,5 +5,5 @@ begin
5
5
  rescue LoadError => e
6
6
  raise LoadError,
7
7
  "Failed to load the profiling native extension. To fix this, please remove and then reinstall datadog " \
8
- "(Details: #{e.message})"
8
+ "(Details: #{e.class}: #{e.message})"
9
9
  end