datadog 2.22.0 → 2.24.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 (212) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +100 -1
  3. data/ext/LIBDATADOG_DEVELOPMENT.md +1 -58
  4. data/ext/datadog_profiling_native_extension/collectors_stack.c +21 -5
  5. data/ext/datadog_profiling_native_extension/crashtracking_runtime_stacks.c +239 -0
  6. data/ext/datadog_profiling_native_extension/datadog_ruby_common.h +1 -1
  7. data/ext/datadog_profiling_native_extension/extconf.rb +9 -4
  8. data/ext/datadog_profiling_native_extension/heap_recorder.c +1 -1
  9. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +12 -0
  10. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +4 -0
  11. data/ext/datadog_profiling_native_extension/profiling.c +2 -0
  12. data/ext/libdatadog_api/datadog_ruby_common.h +1 -1
  13. data/ext/libdatadog_api/feature_flags.c +554 -0
  14. data/ext/libdatadog_api/feature_flags.h +5 -0
  15. data/ext/libdatadog_api/init.c +2 -0
  16. data/ext/libdatadog_api/library_config.c +12 -11
  17. data/ext/libdatadog_extconf_helpers.rb +1 -1
  18. data/lib/datadog/appsec/api_security/route_extractor.rb +23 -6
  19. data/lib/datadog/appsec/api_security/sampler.rb +7 -4
  20. data/lib/datadog/appsec/assets/blocked.html +8 -0
  21. data/lib/datadog/appsec/assets/blocked.json +1 -1
  22. data/lib/datadog/appsec/assets/blocked.text +3 -1
  23. data/lib/datadog/appsec/assets.rb +1 -1
  24. data/lib/datadog/appsec/context.rb +2 -1
  25. data/lib/datadog/appsec/remote.rb +5 -9
  26. data/lib/datadog/appsec/response.rb +18 -4
  27. data/lib/datadog/appsec/security_engine/result.rb +2 -1
  28. data/lib/datadog/core/configuration/components.rb +30 -3
  29. data/lib/datadog/core/configuration/config_helper.rb +2 -2
  30. data/lib/datadog/core/configuration/deprecations.rb +2 -2
  31. data/lib/datadog/core/configuration/option_definition.rb +4 -2
  32. data/lib/datadog/core/configuration/options.rb +8 -5
  33. data/lib/datadog/core/configuration/settings.rb +28 -3
  34. data/lib/datadog/core/configuration/supported_configurations.rb +332 -302
  35. data/lib/datadog/core/ddsketch.rb +0 -2
  36. data/lib/datadog/core/environment/cgroup.rb +52 -25
  37. data/lib/datadog/core/environment/container.rb +140 -46
  38. data/lib/datadog/core/environment/ext.rb +7 -0
  39. data/lib/datadog/core/environment/process.rb +87 -0
  40. data/lib/datadog/core/feature_flags.rb +61 -0
  41. data/lib/datadog/core/rate_limiter.rb +9 -1
  42. data/lib/datadog/core/remote/client/capabilities.rb +7 -0
  43. data/lib/datadog/core/remote/client.rb +14 -6
  44. data/lib/datadog/core/remote/component.rb +6 -4
  45. data/lib/datadog/core/remote/configuration/content.rb +15 -2
  46. data/lib/datadog/core/remote/configuration/digest.rb +14 -7
  47. data/lib/datadog/core/remote/configuration/repository.rb +1 -1
  48. data/lib/datadog/core/remote/configuration/target.rb +13 -6
  49. data/lib/datadog/core/remote/transport/config.rb +4 -25
  50. data/lib/datadog/core/remote/transport/http/config.rb +10 -50
  51. data/lib/datadog/core/remote/transport/http/negotiation.rb +14 -44
  52. data/lib/datadog/core/remote/transport/http.rb +15 -24
  53. data/lib/datadog/core/remote/transport/negotiation.rb +8 -33
  54. data/lib/datadog/core/remote/worker.rb +25 -37
  55. data/lib/datadog/core/tag_builder.rb +0 -4
  56. data/lib/datadog/core/tag_normalizer.rb +84 -0
  57. data/lib/datadog/core/telemetry/component.rb +59 -16
  58. data/lib/datadog/core/telemetry/event/app_started.rb +86 -49
  59. data/lib/datadog/core/telemetry/event/synth_app_client_configuration_change.rb +27 -4
  60. data/lib/datadog/core/telemetry/logger.rb +2 -2
  61. data/lib/datadog/core/telemetry/logging.rb +2 -8
  62. data/lib/datadog/core/telemetry/metrics_manager.rb +9 -0
  63. data/lib/datadog/core/telemetry/request.rb +17 -3
  64. data/lib/datadog/core/telemetry/transport/http/telemetry.rb +3 -34
  65. data/lib/datadog/core/telemetry/transport/http.rb +21 -16
  66. data/lib/datadog/core/telemetry/transport/telemetry.rb +3 -11
  67. data/lib/datadog/core/telemetry/worker.rb +88 -32
  68. data/lib/datadog/core/transport/ext.rb +2 -0
  69. data/lib/datadog/core/transport/http/api/endpoint.rb +9 -4
  70. data/lib/datadog/core/transport/http/api/instance.rb +4 -21
  71. data/lib/datadog/core/transport/http/builder.rb +9 -5
  72. data/lib/datadog/core/transport/http/client.rb +80 -0
  73. data/lib/datadog/core/transport/http.rb +22 -19
  74. data/lib/datadog/core/transport/response.rb +9 -0
  75. data/lib/datadog/core/transport/transport.rb +90 -0
  76. data/lib/datadog/core/utils/array.rb +29 -0
  77. data/lib/datadog/{appsec/api_security → core/utils}/lru_cache.rb +10 -21
  78. data/lib/datadog/core/utils/network.rb +3 -1
  79. data/lib/datadog/core/utils/only_once_successful.rb +8 -2
  80. data/lib/datadog/core/utils/time.rb +1 -1
  81. data/lib/datadog/core/utils.rb +2 -0
  82. data/lib/datadog/core/workers/async.rb +10 -1
  83. data/lib/datadog/core/workers/interval_loop.rb +44 -3
  84. data/lib/datadog/core/workers/polling.rb +2 -0
  85. data/lib/datadog/core/workers/queue.rb +100 -1
  86. data/lib/datadog/data_streams/configuration/settings.rb +49 -0
  87. data/lib/datadog/data_streams/configuration.rb +11 -0
  88. data/lib/datadog/data_streams/ext.rb +11 -0
  89. data/lib/datadog/data_streams/extensions.rb +16 -0
  90. data/lib/datadog/data_streams/pathway_context.rb +169 -0
  91. data/lib/datadog/data_streams/processor.rb +509 -0
  92. data/lib/datadog/data_streams/transport/http/stats.rb +52 -0
  93. data/lib/datadog/data_streams/transport/http.rb +40 -0
  94. data/lib/datadog/data_streams/transport/stats.rb +46 -0
  95. data/lib/datadog/data_streams.rb +100 -0
  96. data/lib/datadog/di/component.rb +0 -16
  97. data/lib/datadog/di/contrib/active_record.rb +31 -5
  98. data/lib/datadog/di/el/compiler.rb +8 -4
  99. data/lib/datadog/di/el/evaluator.rb +1 -1
  100. data/lib/datadog/di/error.rb +9 -0
  101. data/lib/datadog/di/instrumenter.rb +93 -34
  102. data/lib/datadog/di/probe.rb +20 -0
  103. data/lib/datadog/di/probe_builder.rb +2 -1
  104. data/lib/datadog/di/probe_manager.rb +47 -33
  105. data/lib/datadog/di/probe_notification_builder.rb +77 -25
  106. data/lib/datadog/di/proc_responder.rb +32 -0
  107. data/lib/datadog/di/remote.rb +89 -84
  108. data/lib/datadog/di/transport/diagnostics.rb +8 -36
  109. data/lib/datadog/di/transport/http/diagnostics.rb +1 -33
  110. data/lib/datadog/di/transport/http/input.rb +1 -33
  111. data/lib/datadog/di/transport/http.rb +32 -17
  112. data/lib/datadog/di/transport/input.rb +67 -34
  113. data/lib/datadog/di.rb +61 -5
  114. data/lib/datadog/open_feature/component.rb +60 -0
  115. data/lib/datadog/open_feature/configuration.rb +27 -0
  116. data/lib/datadog/open_feature/evaluation_engine.rb +70 -0
  117. data/lib/datadog/open_feature/exposures/batch_builder.rb +32 -0
  118. data/lib/datadog/open_feature/exposures/buffer.rb +43 -0
  119. data/lib/datadog/open_feature/exposures/deduplicator.rb +30 -0
  120. data/lib/datadog/open_feature/exposures/event.rb +60 -0
  121. data/lib/datadog/open_feature/exposures/reporter.rb +40 -0
  122. data/lib/datadog/open_feature/exposures/worker.rb +116 -0
  123. data/lib/datadog/open_feature/ext.rb +14 -0
  124. data/lib/datadog/open_feature/native_evaluator.rb +38 -0
  125. data/lib/datadog/open_feature/noop_evaluator.rb +26 -0
  126. data/lib/datadog/open_feature/provider.rb +141 -0
  127. data/lib/datadog/open_feature/remote.rb +67 -0
  128. data/lib/datadog/open_feature/resolution_details.rb +35 -0
  129. data/lib/datadog/open_feature/transport.rb +70 -0
  130. data/lib/datadog/open_feature.rb +19 -0
  131. data/lib/datadog/opentelemetry/api/baggage.rb +1 -1
  132. data/lib/datadog/opentelemetry/configuration/settings.rb +159 -0
  133. data/lib/datadog/opentelemetry/metrics.rb +117 -0
  134. data/lib/datadog/opentelemetry/sdk/configurator.rb +25 -1
  135. data/lib/datadog/opentelemetry/sdk/metrics_exporter.rb +35 -0
  136. data/lib/datadog/opentelemetry.rb +3 -0
  137. data/lib/datadog/profiling/collectors/code_provenance.rb +41 -7
  138. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +1 -1
  139. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -1
  140. data/lib/datadog/profiling/collectors/info.rb +2 -1
  141. data/lib/datadog/profiling/component.rb +12 -11
  142. data/lib/datadog/profiling/http_transport.rb +4 -1
  143. data/lib/datadog/profiling/profiler.rb +4 -0
  144. data/lib/datadog/profiling/tag_builder.rb +36 -3
  145. data/lib/datadog/profiling.rb +1 -2
  146. data/lib/datadog/single_step_instrument.rb +1 -1
  147. data/lib/datadog/tracing/configuration/ext.rb +9 -0
  148. data/lib/datadog/tracing/configuration/settings.rb +74 -0
  149. data/lib/datadog/tracing/contrib/action_pack/action_controller/instrumentation.rb +4 -4
  150. data/lib/datadog/tracing/contrib/action_pack/utils.rb +1 -2
  151. data/lib/datadog/tracing/contrib/active_job/log_injection.rb +21 -7
  152. data/lib/datadog/tracing/contrib/active_job/patcher.rb +5 -1
  153. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +4 -2
  154. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +4 -1
  155. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +11 -3
  156. data/lib/datadog/tracing/contrib/extensions.rb +10 -2
  157. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +11 -7
  158. data/lib/datadog/tracing/contrib/grape/configuration/settings.rb +7 -3
  159. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +22 -17
  160. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +11 -3
  161. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +11 -3
  162. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +11 -3
  163. data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +66 -0
  164. data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +66 -0
  165. data/lib/datadog/tracing/contrib/kafka/patcher.rb +14 -0
  166. data/lib/datadog/tracing/contrib/karafka/framework.rb +30 -0
  167. data/lib/datadog/tracing/contrib/karafka/monitor.rb +11 -0
  168. data/lib/datadog/tracing/contrib/karafka/patcher.rb +35 -4
  169. data/lib/datadog/tracing/contrib/rack/middlewares.rb +59 -27
  170. data/lib/datadog/tracing/contrib/rack/route_inference.rb +53 -0
  171. data/lib/datadog/tracing/contrib/rails/middlewares.rb +2 -2
  172. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +4 -1
  173. data/lib/datadog/tracing/contrib/roda/instrumentation.rb +3 -1
  174. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +3 -1
  175. data/lib/datadog/tracing/contrib/status_range_matcher.rb +9 -1
  176. data/lib/datadog/tracing/contrib/utils/quantization/hash.rb +3 -1
  177. data/lib/datadog/tracing/contrib/waterdrop/configuration/settings.rb +27 -0
  178. data/lib/datadog/tracing/contrib/waterdrop/distributed/propagation.rb +48 -0
  179. data/lib/datadog/tracing/contrib/waterdrop/ext.rb +17 -0
  180. data/lib/datadog/tracing/contrib/waterdrop/integration.rb +43 -0
  181. data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +46 -0
  182. data/lib/datadog/tracing/contrib/waterdrop/patcher.rb +49 -0
  183. data/lib/datadog/tracing/contrib/waterdrop/producer.rb +50 -0
  184. data/lib/datadog/tracing/contrib/waterdrop.rb +37 -0
  185. data/lib/datadog/tracing/contrib.rb +1 -0
  186. data/lib/datadog/tracing/diagnostics/environment_logger.rb +1 -1
  187. data/lib/datadog/tracing/metadata/ext.rb +1 -1
  188. data/lib/datadog/tracing/remote.rb +1 -9
  189. data/lib/datadog/tracing/span_event.rb +2 -2
  190. data/lib/datadog/tracing/span_operation.rb +9 -4
  191. data/lib/datadog/tracing/trace_operation.rb +44 -6
  192. data/lib/datadog/tracing/tracer.rb +42 -16
  193. data/lib/datadog/tracing/transport/http/client.rb +12 -26
  194. data/lib/datadog/tracing/transport/http/traces.rb +2 -50
  195. data/lib/datadog/tracing/transport/http.rb +15 -9
  196. data/lib/datadog/tracing/transport/io/client.rb +1 -1
  197. data/lib/datadog/tracing/transport/trace_formatter.rb +11 -0
  198. data/lib/datadog/tracing/transport/traces.rb +9 -71
  199. data/lib/datadog/tracing/workers/trace_writer.rb +5 -0
  200. data/lib/datadog/tracing/writer.rb +1 -0
  201. data/lib/datadog/version.rb +2 -2
  202. data/lib/datadog.rb +2 -0
  203. metadata +78 -21
  204. data/lib/datadog/core/remote/transport/http/api.rb +0 -53
  205. data/lib/datadog/core/remote/transport/http/client.rb +0 -49
  206. data/lib/datadog/core/telemetry/transport/http/api.rb +0 -43
  207. data/lib/datadog/core/telemetry/transport/http/client.rb +0 -49
  208. data/lib/datadog/core/transport/http/api/spec.rb +0 -36
  209. data/lib/datadog/di/transport/http/api.rb +0 -42
  210. data/lib/datadog/di/transport/http/client.rb +0 -47
  211. data/lib/datadog/opentelemetry/api/baggage.rbs +0 -26
  212. data/lib/datadog/tracing/transport/http/api.rb +0 -44
@@ -14,14 +14,26 @@ require_relative '../utils/forking'
14
14
  module Datadog
15
15
  module Core
16
16
  module Telemetry
17
- # Telemetry entrypoint, coordinates sending telemetry events at various points in app lifecycle.
18
- # Note: Telemetry does not spawn its worker thread in fork processes, thus no telemetry is sent in forked processes.
17
+ # Telemetry entry point, coordinates sending telemetry events at
18
+ # various points in application lifecycle.
19
19
  #
20
20
  # @api private
21
21
  class Component
22
22
  ENDPOINT_COLLECTION_MESSAGE_LIMIT = 300
23
23
 
24
- attr_reader :enabled, :logger, :transport, :worker
24
+ ONLY_ONCE = Utils::OnlyOnce.new
25
+
26
+ attr_reader :enabled
27
+ attr_reader :logger
28
+ attr_reader :transport
29
+ attr_reader :worker
30
+ attr_reader :settings
31
+ attr_reader :agent_settings
32
+ attr_reader :metrics_manager
33
+
34
+ # Alias for consistency with other components.
35
+ # TODO Remove +enabled+ method
36
+ alias_method :enabled?, :enabled
25
37
 
26
38
  include Core::Utils::Forking
27
39
  include Telemetry::Logging
@@ -50,6 +62,17 @@ module Datadog
50
62
  logger:,
51
63
  enabled:
52
64
  )
65
+ ONLY_ONCE.run do
66
+ Utils::AtForkMonkeyPatch.apply!
67
+
68
+ # All of the other at fork monkey patch callbacks reference
69
+ # globals, follow that pattern here to avoid having the component
70
+ # referenced via the at fork callbacks.
71
+ Datadog::Core::Utils::AtForkMonkeyPatch.at_fork(:child) do
72
+ Datadog.send(:components, allow_initialization: false)&.telemetry&.after_fork
73
+ end
74
+ end
75
+
53
76
  @enabled = enabled
54
77
  @log_collection_enabled = settings.telemetry.log_collection_enabled
55
78
  @logger = logger
@@ -109,13 +132,17 @@ module Datadog
109
132
  @worker&.enabled = false
110
133
  end
111
134
 
112
- def start(initial_event_is_change = false)
113
- return if !@enabled
135
+ def start(initial_event_is_change = false, components:)
136
+ return unless enabled?
114
137
 
115
138
  initial_event = if initial_event_is_change
116
- Event::SynthAppClientConfigurationChange.new(agent_settings: @agent_settings)
139
+ Event::SynthAppClientConfigurationChange.new(
140
+ components: components,
141
+ )
117
142
  else
118
- Event::AppStarted.new(agent_settings: @agent_settings)
143
+ Event::AppStarted.new(
144
+ components: components,
145
+ )
119
146
  end
120
147
 
121
148
  @worker.start(initial_event)
@@ -132,44 +159,44 @@ module Datadog
132
159
  end
133
160
 
134
161
  def emit_closing!
135
- return if !@enabled || forked?
162
+ return unless enabled?
136
163
 
137
164
  @worker.enqueue(Event::AppClosing.new)
138
165
  end
139
166
 
140
167
  def integrations_change!
141
- return if !@enabled || forked?
168
+ return unless enabled?
142
169
 
143
170
  @worker.enqueue(Event::AppIntegrationsChange.new)
144
171
  end
145
172
 
146
173
  def log!(event)
147
- return if !@enabled || forked? || !@log_collection_enabled
174
+ return unless enabled? && @log_collection_enabled
148
175
 
149
176
  @worker.enqueue(event)
150
177
  end
151
178
 
152
179
  # Wait for the worker to send out all events that have already
153
180
  # been queued, up to 15 seconds. Returns whether all events have
154
- # been flushed.
181
+ # been flushed, or nil if telemetry is disabled.
155
182
  #
156
183
  # @api private
157
- def flush
158
- return if !@enabled || forked?
184
+ def flush(timeout: nil)
185
+ return unless enabled?
159
186
 
160
- @worker.flush
187
+ @worker.flush(timeout: timeout)
161
188
  end
162
189
 
163
190
  # Report configuration changes caused by Remote Configuration.
164
191
  def client_configuration_change!(changes)
165
- return if !@enabled || forked?
192
+ return unless enabled?
166
193
 
167
194
  @worker.enqueue(Event::AppClientConfigurationChange.new(changes, 'remote_config'))
168
195
  end
169
196
 
170
197
  # Report application endpoints
171
198
  def app_endpoints_loaded(endpoints, page_size: ENDPOINT_COLLECTION_MESSAGE_LIMIT)
172
- return if !@enabled || forked?
199
+ return unless enabled?
173
200
 
174
201
  endpoints.each_slice(page_size).with_index do |endpoints_slice, i|
175
202
  @worker.enqueue(Event::AppEndpointsLoaded.new(endpoints_slice, is_first: i.zero?))
@@ -200,6 +227,22 @@ module Datadog
200
227
  def distribution(namespace, metric_name, value, tags: {}, common: true)
201
228
  @metrics_manager.distribution(namespace, metric_name, value, tags: tags, common: common)
202
229
  end
230
+
231
+ # When a fork happens, we generally need to do two things inside the
232
+ # child proess:
233
+ # 1. Restart the worker.
234
+ # 2. Discard any events and metrics that were submitted in the
235
+ # parent process (because they will be sent out in the parent
236
+ # process, sending them in the child would cause duplicate
237
+ # submission).
238
+ def after_fork
239
+ # We cannot simply create a new instance of metrics manager because
240
+ # it is referenced from other objects (e.g. the worker).
241
+ # We must reset the existing instance.
242
+ @metrics_manager.clear
243
+
244
+ worker&.send(:after_fork_monkey_patched)
245
+ end
203
246
  end
204
247
  end
205
248
  end
@@ -8,8 +8,18 @@ module Datadog
8
8
  module Event
9
9
  # Telemetry class for the 'app-started' event
10
10
  class AppStarted < Base
11
- def initialize(agent_settings:)
12
- @agent_settings = agent_settings
11
+ def initialize(components:)
12
+ # To not hold a reference to the component tree, generate
13
+ # the event payload here in the constructor.
14
+ #
15
+ # Important: do not store data that contains (or is derived from)
16
+ # the runtime_id or sequence numbers.
17
+ # This event is reused when a process forks, but in the
18
+ # child process the runtime_id would be different and sequence
19
+ # number is reset.
20
+ @configuration = configuration(components.settings, components.agent_settings)
21
+ @install_signature = install_signature(components.settings)
22
+ @products = products(components)
13
23
  end
14
24
 
15
25
  def type
@@ -18,27 +28,37 @@ module Datadog
18
28
 
19
29
  def payload
20
30
  {
21
- products: products,
22
- configuration: configuration,
23
- install_signature: install_signature,
31
+ products: @products,
32
+ configuration: @configuration,
33
+ install_signature: @install_signature,
24
34
  # DEV: Not implemented yet
25
35
  # error: error, # Start-up errors
26
36
  }
27
37
  end
28
38
 
39
+ # Whether the event is actually the app-started event.
40
+ # For the app-started event we follow up by sending
41
+ # app-dependencies-loaded, if the event is
42
+ # app-client-configuration-change we don't send
43
+ # app-dependencies-loaded.
44
+ def app_started?
45
+ true
46
+ end
47
+
29
48
  private
30
49
 
31
- def products
50
+ def products(components)
32
51
  # @type var products: Hash[Symbol, Hash[Symbol, Hash[Symbol, String | Integer] | bool | nil]]
33
52
  products = {
34
53
  appsec: {
35
- enabled: Datadog::AppSec.enabled?,
54
+ # TODO take appsec status out of component tree?
55
+ enabled: components.settings.appsec.enabled,
36
56
  },
37
57
  profiler: {
38
- enabled: Datadog::Profiling.enabled?,
58
+ enabled: !!components.profiler&.enabled?,
39
59
  },
40
60
  dynamic_instrumentation: {
41
- enabled: defined?(Datadog::DI) && Datadog::DI.respond_to?(:enabled?) && Datadog::DI.enabled?,
61
+ enabled: !!components.dynamic_instrumentation,
42
62
  }
43
63
  }
44
64
 
@@ -73,12 +93,11 @@ module Datadog
73
93
 
74
94
  # standard:disable Metrics/AbcSize
75
95
  # standard:disable Metrics/MethodLength
76
- def configuration
77
- config = Datadog.configuration
96
+ def configuration(settings, agent_settings)
78
97
  seq_id = Event.configuration_sequence.next
79
98
 
80
99
  # tracing.writer_options.buffer_size and tracing.writer_options.flush_interval have the same origin.
81
- writer_option_origin = get_telemetry_origin(config, 'tracing.writer_options')
100
+ writer_option_origin = get_telemetry_origin(settings, 'tracing.writer_options')
82
101
 
83
102
  list = [
84
103
  # Only set using env var as of June 2025
@@ -100,59 +119,78 @@ module Datadog
100
119
  ),
101
120
 
102
121
  # Mix of env var, programmatic and default config, so we use unknown
103
- conf_value('DD_AGENT_TRANSPORT', agent_transport, seq_id, 'unknown'), # rubocop:disable CustomCops/EnvStringValidationCop
122
+ conf_value('DD_AGENT_TRANSPORT', agent_transport(agent_settings), seq_id, 'unknown'), # rubocop:disable CustomCops/EnvStringValidationCop
104
123
 
105
124
  # writer_options is defined as an option that has a Hash value.
106
125
  conf_value(
107
126
  'tracing.writer_options.buffer_size',
108
- to_value(config.tracing.writer_options[:buffer_size]),
127
+ to_value(settings.tracing.writer_options[:buffer_size]),
109
128
  seq_id,
110
129
  writer_option_origin
111
130
  ),
112
131
  conf_value(
113
132
  'tracing.writer_options.flush_interval',
114
- to_value(config.tracing.writer_options[:flush_interval]),
133
+ to_value(settings.tracing.writer_options[:flush_interval]),
115
134
  seq_id,
116
135
  writer_option_origin
117
136
  ),
118
137
 
119
- conf_value('DD_AGENT_HOST', config.agent.host, seq_id, get_telemetry_origin(config, 'agent.host')),
138
+ conf_value('DD_AGENT_HOST', settings.agent.host, seq_id, get_telemetry_origin(settings, 'agent.host')),
120
139
  conf_value(
121
140
  'DD_TRACE_SAMPLE_RATE',
122
- to_value(config.tracing.sampling.default_rate),
141
+ to_value(settings.tracing.sampling.default_rate),
123
142
  seq_id,
124
- get_telemetry_origin(config, 'tracing.sampling.default_rate')
143
+ get_telemetry_origin(settings, 'tracing.sampling.default_rate')
125
144
  ),
126
145
  conf_value(
127
146
  'DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED',
128
- config.tracing.contrib.global_default_service_name.enabled,
147
+ settings.tracing.contrib.global_default_service_name.enabled,
129
148
  seq_id,
130
- get_telemetry_origin(config, 'tracing.contrib.global_default_service_name.enabled')
149
+ get_telemetry_origin(settings, 'tracing.contrib.global_default_service_name.enabled')
131
150
  ),
132
151
  conf_value(
133
152
  'DD_TRACE_PEER_SERVICE_DEFAULTS_ENABLED',
134
- config.tracing.contrib.peer_service_defaults,
153
+ settings.tracing.contrib.peer_service_defaults,
135
154
  seq_id,
136
- get_telemetry_origin(config, 'tracing.contrib.peer_service_defaults')
155
+ get_telemetry_origin(settings, 'tracing.contrib.peer_service_defaults')
137
156
  ),
138
157
  conf_value(
139
158
  'DD_TRACE_DEBUG',
140
- config.diagnostics.debug,
159
+ settings.diagnostics.debug,
141
160
  seq_id,
142
- get_telemetry_origin(config, 'diagnostics.debug')
161
+ get_telemetry_origin(settings, 'diagnostics.debug')
143
162
  )
144
163
  ]
145
164
 
146
165
  peer_service_mapping_str = ''
147
- unless config.tracing.contrib.peer_service_mapping.empty?
148
- peer_service_mapping = config.tracing.contrib.peer_service_mapping
166
+ unless settings.tracing.contrib.peer_service_mapping.empty?
167
+ peer_service_mapping = settings.tracing.contrib.peer_service_mapping
149
168
  peer_service_mapping_str = peer_service_mapping.map { |key, value| "#{key}:#{value}" }.join(',')
150
169
  end
151
170
  list << conf_value(
152
171
  'DD_TRACE_PEER_SERVICE_MAPPING',
153
172
  peer_service_mapping_str,
154
173
  seq_id,
155
- get_telemetry_origin(config, 'tracing.contrib.peer_service_mapping')
174
+ get_telemetry_origin(settings, 'tracing.contrib.peer_service_mapping')
175
+ )
176
+
177
+ # OpenTelemetry configuration options (using environment variable names)
178
+ otel_exporter_headers_string = settings.opentelemetry.exporter.headers&.map { |key, value| "#{key}=#{value}" }&.join(',')
179
+ otel_exporter_metrics_headers_string = settings.opentelemetry.metrics.headers&.map { |key, value| "#{key}=#{value}" }&.join(',')
180
+ list.push(
181
+ conf_value('OTEL_EXPORTER_OTLP_ENDPOINT', settings.opentelemetry.exporter.endpoint, seq_id, get_telemetry_origin(settings, 'opentelemetry.exporter.endpoint')),
182
+ conf_value('OTEL_EXPORTER_OTLP_HEADERS', otel_exporter_headers_string, seq_id, get_telemetry_origin(settings, 'opentelemetry.exporter.headers')),
183
+ conf_value('OTEL_EXPORTER_OTLP_PROTOCOL', settings.opentelemetry.exporter.protocol, seq_id, get_telemetry_origin(settings, 'opentelemetry.exporter.protocol')),
184
+ conf_value('OTEL_EXPORTER_OTLP_TIMEOUT', settings.opentelemetry.exporter.timeout_millis, seq_id, get_telemetry_origin(settings, 'opentelemetry.exporter.timeout_millis')),
185
+ conf_value('DD_METRICS_OTEL_ENABLED', settings.opentelemetry.metrics.enabled, seq_id, get_telemetry_origin(settings, 'opentelemetry.metrics.enabled')),
186
+ conf_value('OTEL_METRICS_EXPORTER', settings.opentelemetry.metrics.exporter, seq_id, get_telemetry_origin(settings, 'opentelemetry.metrics.exporter')),
187
+ conf_value('OTEL_EXPORTER_OTLP_METRICS_ENDPOINT', settings.opentelemetry.metrics.endpoint, seq_id, get_telemetry_origin(settings, 'opentelemetry.metrics.endpoint')),
188
+ conf_value('OTEL_EXPORTER_OTLP_METRICS_HEADERS', otel_exporter_metrics_headers_string, seq_id, get_telemetry_origin(settings, 'opentelemetry.metrics.headers')),
189
+ conf_value('OTEL_EXPORTER_OTLP_METRICS_PROTOCOL', settings.opentelemetry.metrics.protocol, seq_id, get_telemetry_origin(settings, 'opentelemetry.metrics.protocol')),
190
+ conf_value('OTEL_EXPORTER_OTLP_METRICS_TIMEOUT', settings.opentelemetry.metrics.timeout_millis, seq_id, get_telemetry_origin(settings, 'opentelemetry.metrics.timeout_millis')),
191
+ conf_value('OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE', settings.opentelemetry.metrics.temporality_preference, seq_id, get_telemetry_origin(settings, 'opentelemetry.metrics.temporality_preference')),
192
+ conf_value('OTEL_METRIC_EXPORT_INTERVAL', settings.opentelemetry.metrics.export_interval_millis, seq_id, get_telemetry_origin(settings, 'opentelemetry.metrics.export_interval_millis')),
193
+ conf_value('OTEL_METRIC_EXPORT_TIMEOUT', settings.opentelemetry.metrics.export_timeout_millis, seq_id, get_telemetry_origin(settings, 'opentelemetry.metrics.export_timeout_millis')),
156
194
  )
157
195
 
158
196
  # Whitelist of configuration options to send in additional payload object
@@ -160,9 +198,9 @@ module Datadog
160
198
  split_option = option_path.split('.')
161
199
  list << conf_value(
162
200
  option_path,
163
- to_value(config.dig(*split_option)),
201
+ to_value(settings.dig(*split_option)),
164
202
  seq_id,
165
- get_telemetry_origin(config, option_path)
203
+ get_telemetry_origin(settings, option_path)
166
204
  )
167
205
  end
168
206
 
@@ -181,34 +219,34 @@ module Datadog
181
219
  )
182
220
 
183
221
  # Add some more custom additional payload values here
184
- if config.logger.instance
222
+ if settings.logger.instance
185
223
  list << conf_value(
186
224
  'logger.instance',
187
- config.logger.instance.class.to_s,
225
+ settings.logger.instance.class.to_s,
188
226
  seq_id,
189
- get_telemetry_origin(config, 'logger.instance')
227
+ get_telemetry_origin(settings, 'logger.instance')
190
228
  )
191
229
  end
192
- if config.respond_to?('appsec')
230
+ if settings.respond_to?('appsec')
193
231
  list << conf_value(
194
232
  'appsec.enabled',
195
- config.dig('appsec', 'enabled'),
233
+ settings.dig('appsec', 'enabled'),
196
234
  seq_id,
197
- get_telemetry_origin(config, 'appsec.enabled')
235
+ get_telemetry_origin(settings, 'appsec.enabled')
198
236
  )
199
237
  list << conf_value(
200
238
  'appsec.sca_enabled',
201
- config.dig('appsec', 'sca_enabled'),
239
+ settings.dig('appsec', 'sca_enabled'),
202
240
  seq_id,
203
- get_telemetry_origin(config, 'appsec.sca_enabled')
241
+ get_telemetry_origin(settings, 'appsec.sca_enabled')
204
242
  )
205
243
  end
206
- if config.respond_to?('ci')
244
+ if settings.respond_to?('ci')
207
245
  list << conf_value(
208
246
  'ci.enabled',
209
- config.dig('ci', 'enabled'),
247
+ settings.dig('ci', 'enabled'),
210
248
  seq_id,
211
- get_telemetry_origin(config, 'ci.enabled')
249
+ get_telemetry_origin(settings, 'ci.enabled')
212
250
  )
213
251
  end
214
252
 
@@ -218,8 +256,8 @@ module Datadog
218
256
  # standard:enable Metrics/AbcSize
219
257
  # standard:enable Metrics/MethodLength
220
258
 
221
- def agent_transport
222
- adapter = @agent_settings.adapter
259
+ def agent_transport(agent_settings)
260
+ adapter = agent_settings.adapter
223
261
  if adapter == Datadog::Core::Transport::Ext::UnixSocket::ADAPTER
224
262
  'UDS'
225
263
  else
@@ -260,23 +298,22 @@ module Datadog
260
298
  end
261
299
  end
262
300
 
263
- def install_signature
264
- config = Datadog.configuration
301
+ def install_signature(settings)
265
302
  {
266
- install_id: config.dig('telemetry', 'install_id'),
267
- install_type: config.dig('telemetry', 'install_type'),
268
- install_time: config.dig('telemetry', 'install_time'),
303
+ install_id: settings.dig('telemetry', 'install_id'),
304
+ install_type: settings.dig('telemetry', 'install_type'),
305
+ install_time: settings.dig('telemetry', 'install_time'),
269
306
  }
270
307
  end
271
308
 
272
- def get_telemetry_origin(config, config_path)
309
+ def get_telemetry_origin(settings, config_path)
273
310
  split_option = config_path.split('.')
274
311
  option_name = split_option.pop
275
312
  return 'unknown' if option_name.nil?
276
313
 
277
314
  # @type var parent_setting: Core::Configuration::Options
278
315
  # @type var option: Core::Configuration::Option
279
- parent_setting = config.dig(*split_option)
316
+ parent_setting = settings.dig(*split_option)
280
317
  option = parent_setting.send(:resolve_option, option_name.to_sym)
281
318
  option.precedence_set&.origin || 'unknown'
282
319
  end
@@ -28,13 +28,36 @@ module Datadog
28
28
  # and app-closing events.
29
29
  class SynthAppClientConfigurationChange < AppStarted
30
30
  def type
31
- 'app-client-configuration-change'
31
+ if reset?
32
+ super
33
+ else
34
+ 'app-client-configuration-change'
35
+ end
32
36
  end
33
37
 
34
38
  def payload
35
- {
36
- configuration: configuration,
37
- }
39
+ if reset?
40
+ super
41
+ else
42
+ {
43
+ configuration: @configuration,
44
+ }
45
+ end
46
+ end
47
+
48
+ def app_started?
49
+ reset?
50
+ end
51
+
52
+ # Revert this event to a "regular" AppStarted event.
53
+ #
54
+ # Used in after_fork to send the AppStarted event in child processes.
55
+ def reset!
56
+ @reset = true
57
+ end
58
+
59
+ def reset?
60
+ defined?(@reset) && !!@reset
38
61
  end
39
62
  end
40
63
  end
@@ -14,8 +14,8 @@ module Datadog
14
14
  # read: lib/datadog/core/telemetry/logging.rb
15
15
  module Logger
16
16
  class << self
17
- def report(exception, level: :error, description: nil, pii_safe: false)
18
- instance&.report(exception, level: level, description: description, pii_safe: pii_safe)
17
+ def report(exception, level: :error, description: nil)
18
+ instance&.report(exception, level: level, description: description)
19
19
  end
20
20
 
21
21
  def error(description)
@@ -45,17 +45,11 @@ module Datadog
45
45
  end
46
46
  end
47
47
 
48
- def report(exception, level: :error, description: nil, pii_safe: false)
48
+ def report(exception, level: :error, description: nil)
49
49
  # Anonymous exceptions to be logged as <Class:0x00007f8b1c0b3b40>
50
50
  message = +"#{exception.class.name || exception.class.inspect}" # standard:disable Style/RedundantInterpolation
51
51
 
52
- exception_message = pii_safe ? exception.message : nil
53
-
54
- if description || exception_message
55
- message << ':'
56
- message << " #{description}" if description
57
- message << " (#{exception.message})" if exception_message
58
- end
52
+ message << ": #{description}" if description
59
53
 
60
54
  event = Event::Log.new(
61
55
  message: message,
@@ -6,8 +6,11 @@ module Datadog
6
6
  module Core
7
7
  module Telemetry
8
8
  # MetricsManager aggregates and flushes metrics and distributions
9
+ #
10
+ # @api private
9
11
  class MetricsManager
10
12
  attr_reader :enabled
13
+ attr_reader :collections
11
14
 
12
15
  def initialize(aggregation_interval:, enabled:)
13
16
  @interval = aggregation_interval
@@ -68,6 +71,12 @@ module Datadog
68
71
  @enabled = false
69
72
  end
70
73
 
74
+ def clear
75
+ @mutex.synchronize do
76
+ @collections = {}
77
+ end
78
+ end
79
+
71
80
  private
72
81
 
73
82
  def fetch_or_create_collection(namespace)
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../environment/platform'
4
+ require_relative '../environment/process'
4
5
  require_relative '../utils/hash'
5
6
 
6
7
  module Datadog
@@ -11,9 +12,9 @@ module Datadog
11
12
  class << self
12
13
  using Core::Utils::Hash::Refinement
13
14
 
14
- def build_payload(event, seq_id, api_version: 'v2', debug: false)
15
+ def build_payload(event, seq_id, debug: false)
15
16
  hash = {
16
- api_version: api_version,
17
+ api_version: 'v2',
17
18
  application: application,
18
19
  debug: debug,
19
20
  host: host,
@@ -43,7 +44,7 @@ module Datadog
43
44
  tracer_version = "#{tracer_version}-ci-#{::Datadog::CI::VERSION::STRING}"
44
45
  end
45
46
 
46
- {
47
+ app = {
47
48
  env: config.env,
48
49
  language_name: Core::Environment::Ext::LANG,
49
50
  language_version: Core::Environment::Ext::LANG_VERSION,
@@ -53,6 +54,10 @@ module Datadog
53
54
  service_version: config.version,
54
55
  tracer_version: tracer_version
55
56
  }
57
+
58
+ tag_process_tags!(app, config)
59
+
60
+ app
56
61
  end
57
62
 
58
63
  def host
@@ -64,6 +69,15 @@ module Datadog
64
69
  kernel_version: Core::Environment::Platform.kernel_version
65
70
  }
66
71
  end
72
+
73
+ def tag_process_tags!(app, config)
74
+ return unless config.experimental_propagate_process_tags_enabled
75
+
76
+ process_tags = Core::Environment::Process.serialized
77
+ return if process_tags.empty?
78
+
79
+ app[:process_tags] = process_tags
80
+ end
67
81
  end
68
82
  end
69
83
  end
@@ -2,9 +2,8 @@
2
2
 
3
3
  require_relative '../../../transport/http/api/endpoint'
4
4
  require_relative '../../../transport/http/api/instance'
5
- require_relative '../../../transport/http/api/spec'
5
+ require_relative '../../../transport/http/client'
6
6
  require_relative '../../../transport/request'
7
- require_relative 'client'
8
7
 
9
8
  module Datadog
10
9
  module Core
@@ -12,35 +11,7 @@ module Datadog
12
11
  module Transport
13
12
  module HTTP
14
13
  module Telemetry
15
- module Client
16
- def send_telemetry_payload(request)
17
- send_request(request) do |api, env| # steep:ignore
18
- api.send_telemetry(env)
19
- end
20
- end
21
- end
22
-
23
14
  module API
24
- class Instance < Core::Transport::HTTP::API::Instance
25
- def send_telemetry(env)
26
- raise Core::Transport::HTTP::API::Instance::EndpointNotSupportedError.new('telemetry', self) unless spec.is_a?(Telemetry::API::Spec)
27
-
28
- spec.send_telemetry(env) do |request_env|
29
- call(request_env)
30
- end
31
- end
32
- end
33
-
34
- class Spec < Core::Transport::HTTP::API::Spec
35
- attr_accessor :telemetry
36
-
37
- def send_telemetry(env, &block)
38
- raise Core::Transport::HTTP::API::Spec::EndpointNotDefinedError.new('telemetry', self) if telemetry.nil?
39
-
40
- telemetry.call(env, &block)
41
- end
42
- end
43
-
44
15
  class Endpoint < Datadog::Core::Transport::HTTP::API::Endpoint
45
16
  HEADER_CONTENT_TYPE = 'Content-Type'
46
17
 
@@ -64,12 +35,12 @@ module Datadog
64
35
  super
65
36
  end
66
37
 
67
- def headers(request_type:, api_key:, api_version: 'v2')
38
+ def headers(request_type:, api_key:)
68
39
  {
69
40
  Core::Transport::Ext::HTTP::HEADER_DD_INTERNAL_UNTRACED_REQUEST => '1',
70
41
  # Provided by encoder
71
42
  # 'Content-Type' => 'application/json',
72
- 'DD-Telemetry-API-Version' => api_version,
43
+ 'DD-Telemetry-API-Version' => 'v2',
73
44
  'DD-Telemetry-Request-Type' => request_type,
74
45
  'DD-Client-Library-Language' => Core::Environment::Ext::LANG,
75
46
  'DD-Client-Library-Version' => Core::Environment::Identity.gem_datadog_version_semver2,
@@ -83,8 +54,6 @@ module Datadog
83
54
  end
84
55
  end
85
56
  end
86
-
87
- HTTP::Client.include(Telemetry::Client)
88
57
  end
89
58
  end
90
59
  end