datadog 2.47.0 → 2.48.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 (273) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -1
  3. data/LICENSE-3rdparty.csv +1 -0
  4. data/ext/datadog_profiling_native_extension/collectors_stack.c +141 -101
  5. data/ext/datadog_profiling_native_extension/collectors_stack.h +9 -1
  6. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +6 -1
  7. data/ext/datadog_profiling_native_extension/extconf.rb +7 -13
  8. data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +3 -3
  9. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +66 -13
  10. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +5 -1
  11. data/ext/datadog_profiling_native_extension/profiling.c +1 -1
  12. data/ext/libdatadog_api/extconf.rb +9 -7
  13. data/ext/libdatadog_api/trace_exporter.c +34 -7
  14. data/ext/libdatadog_extconf_helpers.rb +1 -1
  15. data/lib/datadog/ai_guard/component.rb +1 -1
  16. data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +1 -9
  17. data/lib/datadog/ai_guard/contrib/rails/patcher.rb +1 -1
  18. data/lib/datadog/ai_guard/contrib/ruby_llm/message_adapter.rb +1 -1
  19. data/lib/datadog/ai_guard/contrib/ruby_llm/redaction_change_set.rb +3 -3
  20. data/lib/datadog/ai_guard/evaluation/client.rb +3 -3
  21. data/lib/datadog/ai_guard/evaluation.rb +2 -2
  22. data/lib/datadog/ai_guard/http_client.rb +3 -2
  23. data/lib/datadog/ai_guard/redaction.rb +1 -1
  24. data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +1 -1
  25. data/lib/datadog/appsec/assets/waf_rules/README.md +3 -3
  26. data/lib/datadog/appsec/assets/waf_rules/recommended.json +5366 -1517
  27. data/lib/datadog/appsec/assets/waf_rules/strict.json +2 -2
  28. data/lib/datadog/appsec/autoload.rb +1 -1
  29. data/lib/datadog/appsec/component.rb +1 -1
  30. data/lib/datadog/appsec/compressed_json.rb +1 -1
  31. data/lib/datadog/appsec/configuration.rb +3 -3
  32. data/lib/datadog/appsec/context.rb +1 -1
  33. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +11 -1
  34. data/lib/datadog/appsec/contrib/active_record/patcher.rb +12 -4
  35. data/lib/datadog/appsec/contrib/aws_lambda/gateway/watcher.rb +2 -2
  36. data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +1 -1
  37. data/lib/datadog/appsec/contrib/devise/configuration.rb +1 -1
  38. data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +1 -1
  39. data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +1 -1
  40. data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +1 -1
  41. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +1 -1
  42. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +1 -1
  43. data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +7 -7
  44. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +1 -1
  45. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +3 -3
  46. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +5 -5
  47. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +2 -2
  48. data/lib/datadog/appsec/contrib/rails/patcher.rb +2 -2
  49. data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +1 -1
  50. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +3 -3
  51. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +1 -1
  52. data/lib/datadog/appsec/metrics/collector.rb +5 -5
  53. data/lib/datadog/appsec/metrics/telemetry_exporter.rb +3 -3
  54. data/lib/datadog/appsec/monitor/gateway/watcher.rb +2 -2
  55. data/lib/datadog/appsec/processor/rule_loader.rb +1 -1
  56. data/lib/datadog/appsec/response.rb +1 -1
  57. data/lib/datadog/appsec/security_engine/engine.rb +6 -6
  58. data/lib/datadog/appsec/security_engine/runner.rb +2 -2
  59. data/lib/datadog/appsec/trace_keeper.rb +1 -1
  60. data/lib/datadog/appsec.rb +1 -1
  61. data/lib/datadog/core/configuration/agent_settings_resolver.rb +14 -13
  62. data/lib/datadog/core/configuration/agentless_settings_resolver.rb +2 -2
  63. data/lib/datadog/core/configuration/components.rb +1 -1
  64. data/lib/datadog/core/configuration/settings.rb +5 -2
  65. data/lib/datadog/core/configuration/supported_configurations.rb +1 -0
  66. data/lib/datadog/core/configuration.rb +2 -2
  67. data/lib/datadog/core/crashtracking/component.rb +1 -1
  68. data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
  69. data/lib/datadog/core/environment/cgroup.rb +2 -2
  70. data/lib/datadog/core/environment/container.rb +3 -3
  71. data/lib/datadog/core/metrics/client.rb +6 -6
  72. data/lib/datadog/core/process_discovery.rb +1 -1
  73. data/lib/datadog/core/remote/tie/tracing.rb +4 -3
  74. data/lib/datadog/core/remote/transport/http.rb +2 -2
  75. data/lib/datadog/core/runtime/metrics.rb +14 -14
  76. data/lib/datadog/core/semaphore.rb +3 -1
  77. data/lib/datadog/core/telemetry/event/app_started.rb +9 -9
  78. data/lib/datadog/core/telemetry/logger.rb +1 -1
  79. data/lib/datadog/core/telemetry/logging.rb +1 -1
  80. data/lib/datadog/core/telemetry/request.rb +9 -3
  81. data/lib/datadog/core/telemetry/transport/http.rb +2 -2
  82. data/lib/datadog/core/telemetry/worker.rb +1 -1
  83. data/lib/datadog/core/transport/http/adapters/net.rb +1 -1
  84. data/lib/datadog/core/transport/http/adapters/unix_socket.rb +1 -1
  85. data/lib/datadog/core/transport/http/builder.rb +1 -1
  86. data/lib/datadog/core/transport/http.rb +3 -3
  87. data/lib/datadog/core/utils/at_fork_monkey_patch.rb +2 -2
  88. data/lib/datadog/core/workers/async.rb +1 -1
  89. data/lib/datadog/core/workers/runtime_metrics.rb +1 -1
  90. data/lib/datadog/data_streams/pathway_context.rb +1 -1
  91. data/lib/datadog/data_streams/processor.rb +48 -27
  92. data/lib/datadog/data_streams/transport/http.rb +1 -1
  93. data/lib/datadog/data_streams.rb +16 -0
  94. data/lib/datadog/di/capture_expression_evaluator.rb +48 -11
  95. data/lib/datadog/di/component.rb +3 -2
  96. data/lib/datadog/di/configuration.rb +19 -0
  97. data/lib/datadog/di/contrib/active_record.rb +1 -1
  98. data/lib/datadog/di/el/compiler.rb +4 -4
  99. data/lib/datadog/di/el/evaluator.rb +247 -43
  100. data/lib/datadog/di/el/expression.rb +36 -6
  101. data/lib/datadog/di/error.rb +16 -0
  102. data/lib/datadog/di/guardrails_telemetry/reason.rb +3 -2
  103. data/lib/datadog/di/instrumenter.rb +39 -10
  104. data/lib/datadog/di/probe_notification_builder.rb +58 -10
  105. data/lib/datadog/di/probe_notifier_worker.rb +1 -1
  106. data/lib/datadog/di/serializer.rb +20 -2
  107. data/lib/datadog/di.rb +27 -0
  108. data/lib/datadog/error_tracking/component.rb +1 -1
  109. data/lib/datadog/error_tracking/configuration.rb +1 -1
  110. data/lib/datadog/kit/appsec/events/v2.rb +6 -6
  111. data/lib/datadog/kit/appsec/events.rb +1 -1
  112. data/lib/datadog/kit/enable_core_dumps.rb +1 -1
  113. data/lib/datadog/kit/identity.rb +1 -1
  114. data/lib/datadog/open_feature/activation.rb +26 -1
  115. data/lib/datadog/open_feature/agentless/configuration_source.rb +94 -15
  116. data/lib/datadog/open_feature/component.rb +22 -2
  117. data/lib/datadog/open_feature/configuration/agentless_endpoint.rb +6 -0
  118. data/lib/datadog/open_feature/configuration.rb +4 -4
  119. data/lib/datadog/open_feature/evaluation_engine.rb +62 -4
  120. data/lib/datadog/open_feature/exposures/buffer.rb +4 -0
  121. data/lib/datadog/open_feature/exposures/reporter.rb +17 -4
  122. data/lib/datadog/open_feature/exposures/worker.rb +37 -6
  123. data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +5 -5
  124. data/lib/datadog/open_feature/flag_evaluation/writer.rb +1 -1
  125. data/lib/datadog/open_feature/hooks/debug_logging_hook.rb +56 -0
  126. data/lib/datadog/open_feature/hooks/span_enrichment_hook.rb +2 -2
  127. data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +1 -1
  128. data/lib/datadog/open_feature/native_evaluator.rb +1 -1
  129. data/lib/datadog/open_feature/noop_evaluator.rb +1 -1
  130. data/lib/datadog/open_feature/provider.rb +50 -12
  131. data/lib/datadog/open_feature/remote.rb +8 -1
  132. data/lib/datadog/open_feature/resolution_details.rb +2 -2
  133. data/lib/datadog/open_feature/transport.rb +6 -6
  134. data/lib/datadog/opentelemetry/api/context.rb +3 -3
  135. data/lib/datadog/opentelemetry/logs.rb +5 -5
  136. data/lib/datadog/opentelemetry/metrics.rb +3 -3
  137. data/lib/datadog/opentelemetry/sdk/propagator.rb +3 -3
  138. data/lib/datadog/opentelemetry/sdk/span_processor.rb +2 -2
  139. data/lib/datadog/opentelemetry/sdk/trace/span.rb +1 -1
  140. data/lib/datadog/profiling/collectors/code_provenance.rb +3 -3
  141. data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +4 -4
  142. data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -1
  143. data/lib/datadog/profiling/collectors/thread_context.rb +1 -1
  144. data/lib/datadog/profiling/component.rb +19 -19
  145. data/lib/datadog/profiling/exporter.rb +1 -1
  146. data/lib/datadog/profiling/http_transport.rb +3 -3
  147. data/lib/datadog/profiling/profiler.rb +2 -2
  148. data/lib/datadog/profiling/scheduler.rb +2 -2
  149. data/lib/datadog/profiling/tag_builder.rb +1 -1
  150. data/lib/datadog/symbol_database/extractor.rb +8 -8
  151. data/lib/datadog/symbol_database/uploader.rb +1 -1
  152. data/lib/datadog/tracing/buffer.rb +3 -3
  153. data/lib/datadog/tracing/client_ip.rb +1 -1
  154. data/lib/datadog/tracing/component.rb +8 -8
  155. data/lib/datadog/tracing/configuration/dynamic/option.rb +2 -2
  156. data/lib/datadog/tracing/configuration/settings.rb +3 -3
  157. data/lib/datadog/tracing/context.rb +1 -1
  158. data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +2 -2
  159. data/lib/datadog/tracing/contrib/active_job/data_streams.rb +27 -2
  160. data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +2 -2
  161. data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +1 -1
  162. data/lib/datadog/tracing/contrib/active_record/utils.rb +1 -1
  163. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +1 -1
  164. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +1 -1
  165. data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +2 -2
  166. data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +2 -2
  167. data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +1 -1
  168. data/lib/datadog/tracing/contrib/aws/instrumentation.rb +1 -1
  169. data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +1 -1
  170. data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +1 -1
  171. data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +2 -2
  172. data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +1 -1
  173. data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +3 -3
  174. data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +1 -1
  175. data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +8 -8
  176. data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +1 -1
  177. data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +1 -1
  178. data/lib/datadog/tracing/contrib/excon/middleware.rb +7 -7
  179. data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +1 -1
  180. data/lib/datadog/tracing/contrib/faraday/middleware.rb +5 -5
  181. data/lib/datadog/tracing/contrib/grape/endpoint.rb +4 -4
  182. data/lib/datadog/tracing/contrib/graphql/patcher.rb +1 -1
  183. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +3 -3
  184. data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +1 -1
  185. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +2 -2
  186. data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +1 -1
  187. data/lib/datadog/tracing/contrib/grpc.rb +1 -1
  188. data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +1 -1
  189. data/lib/datadog/tracing/contrib/hanami/plugin.rb +1 -1
  190. data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +1 -1
  191. data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +1 -1
  192. data/lib/datadog/tracing/contrib/http/configuration/settings.rb +1 -1
  193. data/lib/datadog/tracing/contrib/http/instrumentation.rb +6 -6
  194. data/lib/datadog/tracing/contrib/http.rb +1 -1
  195. data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +1 -1
  196. data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +7 -7
  197. data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +1 -1
  198. data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +5 -5
  199. data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +2 -2
  200. data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +2 -2
  201. data/lib/datadog/tracing/contrib/karafka/monitor.rb +1 -1
  202. data/lib/datadog/tracing/contrib/karafka/patcher.rb +1 -1
  203. data/lib/datadog/tracing/contrib/karafka.rb +1 -1
  204. data/lib/datadog/tracing/contrib/lograge/patcher.rb +1 -1
  205. data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +1 -1
  206. data/lib/datadog/tracing/contrib/mongodb/parsers.rb +1 -1
  207. data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +1 -1
  208. data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +1 -1
  209. data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +3 -3
  210. data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +2 -2
  211. data/lib/datadog/tracing/contrib/opensearch/patcher.rb +3 -3
  212. data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +1 -1
  213. data/lib/datadog/tracing/contrib/pg/instrumentation.rb +4 -4
  214. data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +1 -1
  215. data/lib/datadog/tracing/contrib/presto/instrumentation.rb +4 -4
  216. data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +1 -1
  217. data/lib/datadog/tracing/contrib/que/tracer.rb +1 -1
  218. data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +1 -1
  219. data/lib/datadog/tracing/contrib/racecar/events/batch.rb +1 -1
  220. data/lib/datadog/tracing/contrib/racecar/events/message.rb +1 -1
  221. data/lib/datadog/tracing/contrib/rack/middlewares.rb +3 -3
  222. data/lib/datadog/tracing/contrib/rack/patcher.rb +1 -1
  223. data/lib/datadog/tracing/contrib/rails/framework.rb +7 -7
  224. data/lib/datadog/tracing/contrib/rails/log_injection.rb +1 -1
  225. data/lib/datadog/tracing/contrib/rails/runner.rb +4 -4
  226. data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +1 -1
  227. data/lib/datadog/tracing/contrib/redis/quantize.rb +1 -1
  228. data/lib/datadog/tracing/contrib/redis/tags.rb +1 -1
  229. data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +1 -1
  230. data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +8 -8
  231. data/lib/datadog/tracing/contrib/sequel/database.rb +1 -1
  232. data/lib/datadog/tracing/contrib/sequel/dataset.rb +1 -1
  233. data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +1 -1
  234. data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +2 -2
  235. data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +2 -2
  236. data/lib/datadog/tracing/contrib/sidekiq.rb +1 -1
  237. data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +1 -1
  238. data/lib/datadog/tracing/contrib/status_range_env_parser.rb +1 -1
  239. data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +1 -1
  240. data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +1 -1
  241. data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +3 -3
  242. data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +2 -2
  243. data/lib/datadog/tracing/contrib/waterdrop.rb +1 -1
  244. data/lib/datadog/tracing/diagnostics/environment_logger.rb +1 -1
  245. data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
  246. data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
  247. data/lib/datadog/tracing/distributed/baggage.rb +3 -3
  248. data/lib/datadog/tracing/distributed/datadog.rb +3 -3
  249. data/lib/datadog/tracing/distributed/propagation.rb +7 -7
  250. data/lib/datadog/tracing/distributed/trace_context.rb +1 -1
  251. data/lib/datadog/tracing/distributed/trace_state/open_telemetry.rb +1 -1
  252. data/lib/datadog/tracing/otel_thread_context.rb +3 -3
  253. data/lib/datadog/tracing/pipeline.rb +1 -1
  254. data/lib/datadog/tracing/sampling/priority_sampler.rb +1 -1
  255. data/lib/datadog/tracing/sampling/rule.rb +1 -1
  256. data/lib/datadog/tracing/sampling/rule_sampler.rb +1 -1
  257. data/lib/datadog/tracing/sampling/span/rule_parser.rb +2 -2
  258. data/lib/datadog/tracing/span_operation.rb +1 -1
  259. data/lib/datadog/tracing/trace_digest.rb +1 -1
  260. data/lib/datadog/tracing/trace_operation.rb +6 -6
  261. data/lib/datadog/tracing/tracer.rb +6 -6
  262. data/lib/datadog/tracing/transport/http/telemetry.rb +1 -1
  263. data/lib/datadog/tracing/transport/http.rb +2 -2
  264. data/lib/datadog/tracing/transport/io.rb +1 -1
  265. data/lib/datadog/tracing/transport/native.rb +3 -3
  266. data/lib/datadog/tracing/transport/statistics.rb +2 -2
  267. data/lib/datadog/tracing/transport/telemetry.rb +3 -1
  268. data/lib/datadog/tracing/transport/trace_formatter.rb +12 -12
  269. data/lib/datadog/tracing/transport/traces.rb +1 -1
  270. data/lib/datadog/tracing/utils.rb +1 -1
  271. data/lib/datadog/tracing/workers.rb +1 -1
  272. data/lib/datadog/version.rb +1 -1
  273. metadata +4 -3
@@ -97,7 +97,7 @@ module Datadog
97
97
  AT_FORK_REGISTRY_MUTEX.synchronize do
98
98
  current = @at_fork_blocks
99
99
  @at_fork_blocks = current.merge(
100
- stage => (blocks_for(current, stage) + [Callback.new(block)]).freeze
100
+ stage => (blocks_for(current, stage) + [Callback.new(block)]).freeze,
101
101
  ).freeze
102
102
  end
103
103
 
@@ -129,7 +129,7 @@ module Datadog
129
129
  current = @at_fork_blocks
130
130
  callbacks = blocks_for(current, stage)
131
131
  @at_fork_blocks = current.merge(
132
- stage => callbacks.reject { |callback| callback.block.equal?(block) }.freeze
132
+ stage => callbacks.reject { |callback| callback.block.equal?(block) }.freeze,
133
133
  ).freeze
134
134
  end
135
135
 
@@ -168,7 +168,7 @@ module Datadog
168
168
  rescue Exception => e
169
169
  @error = e
170
170
  Datadog.logger.debug(
171
- "Worker thread error. Cause: #{e.class}: #{e.message} Location: #{Array(e.backtrace).first}"
171
+ "Worker thread error. Cause: #{e.class}: #{e.message} Location: #{Array(e.backtrace).first}",
172
172
  )
173
173
  raise
174
174
 
@@ -27,7 +27,7 @@ module Datadog
27
27
  telemetry: telemetry,
28
28
  experimental_propagate_process_tags_enabled: options.fetch(:propagate_process_tags_enabled) do
29
29
  options.fetch(:experimental_propagate_process_tags_enabled)
30
- end
30
+ end,
31
31
  )
32
32
  end
33
33
 
@@ -90,7 +90,7 @@ module Datadog
90
90
  new(
91
91
  hash_value: hash_value,
92
92
  pathway_start: pathway_start,
93
- current_edge_start: current_edge_start
93
+ current_edge_start: current_edge_start,
94
94
  )
95
95
  rescue EOFError
96
96
  # Not enough data in binary stream
@@ -10,6 +10,7 @@ require_relative "../core/ddsketch"
10
10
  require_relative "../core/buffer/cruby"
11
11
  require_relative "../core/utils/time"
12
12
  require_relative "../core/utils/fnv"
13
+ require_relative "../core/utils/sequence"
13
14
 
14
15
  module Datadog
15
16
  module DataStreams
@@ -28,7 +29,17 @@ module Datadog
28
29
  # Set to handle high-throughput scenarios (e.g., 10k events/sec for 10s interval)
29
30
  DEFAULT_BUFFER_SIZE = 100_000
30
31
 
31
- attr_reader :pathway_context, :buckets, :bucket_size_ns
32
+ attr_reader :buckets, :bucket_size_ns
33
+
34
+ UNIQUE_INSTANCE_MUTEX = Mutex.new
35
+ UNIQUE_INSTANCE_GENERATOR = Core::Utils::Sequence.new
36
+
37
+ private_constant :UNIQUE_INSTANCE_MUTEX, :UNIQUE_INSTANCE_GENERATOR
38
+
39
+ # Not object_id: the VM may reuse it, letting a new processor read a stale context.
40
+ def self.next_instance_id
41
+ UNIQUE_INSTANCE_MUTEX.synchronize { UNIQUE_INSTANCE_GENERATOR.next }
42
+ end
32
43
 
33
44
  # Initialize the Data Streams Monitoring processor
34
45
  #
@@ -48,12 +59,9 @@ module Datadog
48
59
  @agent_info = agent_info
49
60
  @logger = logger
50
61
 
51
- now = Core::Utils::Time.now
52
- @pathway_context = PathwayContext.new(
53
- hash_value: 0,
54
- pathway_start: now,
55
- current_edge_start: now
56
- )
62
+ # Fiber-local (Thread#[] is fiber-local), so a consume on one thread never rewrites the
63
+ # pathway of produces on another.
64
+ @pathway_context_key = :"datadog_data_streams_pathway_context_#{Processor.next_instance_id}"
57
65
  @bucket_size_ns = (interval * 1e9).to_i
58
66
  @buckets = {}
59
67
  @consumer_stats = []
@@ -83,6 +91,14 @@ module Datadog
83
91
  perform
84
92
  end
85
93
 
94
+ def pathway_context
95
+ Thread.current[@pathway_context_key]
96
+ end
97
+
98
+ def pathway_context=(context)
99
+ Thread.current[@pathway_context_key] = context
100
+ end
101
+
86
102
  # Track Kafka produce offset for lag monitoring
87
103
  # @param topic [String] The Kafka topic name
88
104
  # @param partition [Integer] The partition number
@@ -97,7 +113,7 @@ module Datadog
97
113
  partition: partition,
98
114
  offset: offset,
99
115
  timestamp_ns: (now.to_f * 1e9).to_i,
100
- }
116
+ },
101
117
  )
102
118
  true
103
119
  end
@@ -116,7 +132,7 @@ module Datadog
116
132
  partition: partition,
117
133
  offset: offset,
118
134
  timestamp: now,
119
- }
135
+ },
120
136
  )
121
137
  true
122
138
  end
@@ -253,7 +269,7 @@ module Datadog
253
269
  end
254
270
 
255
271
  def encode_pathway_context
256
- @pathway_context.encode_b64
272
+ get_current_context.encode_b64
257
273
  end
258
274
 
259
275
  def set_checkpoint(tags:, now: nil, payload_size: 0, span: nil)
@@ -301,7 +317,7 @@ module Datadog
301
317
  full_pathway_latency_sec: full_pathway_latency_sec,
302
318
  payload_size: payload_size,
303
319
  tags: tags,
304
- timestamp_sec: now.to_f
320
+ timestamp_sec: now.to_f,
305
321
  )
306
322
 
307
323
  current_context.parent_hash = current_context.hash
@@ -326,6 +342,8 @@ module Datadog
326
342
  # agent. Discard it instead: losing a few seconds of pre-fork stats is preferable to
327
343
  # corrupting pipeline throughput/lag numbers with duplicates.
328
344
  def discard_inherited_state_after_fork!
345
+ # Runs on the forking thread, the only one that survives into the child.
346
+ self.pathway_context = nil
329
347
  @event_buffer.pop
330
348
  @stats_mutex.synchronize do
331
349
  @buckets.clear
@@ -367,24 +385,27 @@ module Datadog
367
385
  get_current_context
368
386
  end
369
387
 
388
+ # Created at the fiber's first checkpoint rather than at processor start, so a producer
389
+ # that starts a pathway reports ~0 latency however long the process sat idle.
370
390
  def get_current_context
371
- @pathway_context ||= begin
372
- now = Core::Utils::Time.now
373
- PathwayContext.new(
374
- hash_value: 0,
375
- pathway_start: now,
376
- current_edge_start: now
377
- )
378
- end
391
+ current = pathway_context
392
+ return current if current
393
+
394
+ now = Core::Utils::Time.now
395
+ self.pathway_context = PathwayContext.new(
396
+ hash_value: 0,
397
+ pathway_start: now,
398
+ current_edge_start: now,
399
+ )
379
400
  end
380
401
 
381
402
  def set_pathway_context(ctx)
382
- if ctx
383
- @pathway_context = ctx
384
- @pathway_context.previous_direction = nil
385
- @pathway_context.closest_opposite_direction_hash = 0
386
- @pathway_context.closest_opposite_direction_edge_start = @pathway_context.current_edge_start
387
- end
403
+ return unless ctx
404
+
405
+ ctx.previous_direction = nil
406
+ ctx.closest_opposite_direction_hash = 0
407
+ ctx.closest_opposite_direction_edge_start = ctx.current_edge_start
408
+ self.pathway_context = ctx
388
409
  end
389
410
 
390
411
  def decode_and_set_pathway_context(headers)
@@ -432,7 +453,7 @@ module Datadog
432
453
  payload_size: payload_size,
433
454
  tags: tags,
434
455
  timestamp_sec: timestamp_sec,
435
- }
456
+ },
436
457
  )
437
458
  true
438
459
  end
@@ -450,7 +471,7 @@ module Datadog
450
471
  def transport
451
472
  @transport ||= Transport::HTTP.default(
452
473
  agent_settings: @agent_settings,
453
- logger: @logger
474
+ logger: @logger,
454
475
  )
455
476
  end
456
477
 
@@ -10,7 +10,7 @@ module Datadog
10
10
  # HTTP transport for Data Streams Monitoring
11
11
  module HTTP
12
12
  V01 = Stats::API::Endpoint.new(
13
- "/v0.1/pipeline_stats"
13
+ "/v0.1/pipeline_stats",
14
14
  )
15
15
 
16
16
  module_function
@@ -75,6 +75,22 @@ module Datadog
75
75
  processor&.track_kafka_consume(topic, partition, offset, Core::Utils::Time.now)
76
76
  end
77
77
 
78
+ # The calling fiber's pathway context, without creating one.
79
+ #
80
+ # @return [PathwayContext, nil]
81
+ # @!visibility private
82
+ def pathway_context
83
+ processor&.pathway_context
84
+ end
85
+
86
+ # Restores a context returned by {.pathway_context}; nil clears it.
87
+ #
88
+ # @param context [PathwayContext, nil]
89
+ # @!visibility private
90
+ def pathway_context=(context)
91
+ processor&.pathway_context = context
92
+ end
93
+
78
94
  # Check if Data Streams Monitoring is enabled and available
79
95
  #
80
96
  # @return [Boolean] true if the processor is available
@@ -7,6 +7,7 @@ require_relative "evaluation_failure"
7
7
  require_relative "fatal_exceptions"
8
8
  require_relative "guardrails_telemetry"
9
9
  require_relative "../core/utils/time"
10
+ require_relative "el"
10
11
 
11
12
  module Datadog
12
13
  module DI
@@ -16,7 +17,7 @@ module Datadog
16
17
  # @param settings [Datadog::Core::Configuration::Settings] tracer settings
17
18
  # @param serializer [Serializer] serializer for captured expression values
18
19
  # @param logger [DI::Logger] logger for evaluation failure diagnostics
19
- # @param guardrails_telemetry [GuardrailsTelemetry] emitter for the canonical capture-timeout skip metric
20
+ # @param guardrails_telemetry [GuardrailsTelemetry] emitter for the canonical evaluation-timeout skip metric
20
21
  # @param telemetry [Datadog::Core::Telemetry::Component, nil] component evaluation failures are reported through
21
22
  # @return [void]
22
23
  def initialize(settings:, serializer:, logger:, guardrails_telemetry:, telemetry: nil)
@@ -42,8 +43,13 @@ module Datadog
42
43
  # Evaluates each of the probe's capture expressions against the given
43
44
  # context, serializing the captured values under one capture deadline
44
45
  # resolved through the serializer and shared across all expressions.
45
- # An expression that fails to evaluate or serialize contributes an entry
46
- # to the returned errors.
46
+ # Each expression resolves its own evaluation deadline immediately
47
+ # before its evaluation and is evaluated under the earlier of that
48
+ # deadline and the capture deadline, so the capture expressions
49
+ # together stay within the capture budget. An expression the capture
50
+ # budget stops is reported as not captured; an expression that fails
51
+ # to evaluate or serialize otherwise contributes an entry to the
52
+ # returned errors.
47
53
  #
48
54
  # @param probe [Probe] the probe whose capture expressions are evaluated
49
55
  # @param context [Context] evaluation context the expressions are evaluated against
@@ -59,18 +65,14 @@ module Datadog
59
65
  probe.capture_expressions.each do |capture_expression|
60
66
  name = capture_expression.name
61
67
 
62
- if Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID, :float_second) >= deadline
63
- output[name] = {notCapturedReason: "timeout"}
64
- telemetry&.inc(DI::TELEMETRY_NAMESPACE, "capture_expressions_skipped_by_timeout", 1)
65
- guardrails_telemetry.skipped(
66
- reason: GuardrailsTelemetry::Reason::EVALUATION_TIMEOUT,
67
- probe: probe,
68
- )
68
+ if capture_deadline_passed?(deadline)
69
+ record_capture_timeout(output, name, probe)
69
70
  next
70
71
  end
71
72
 
72
73
  begin
73
- value = capture_expression.expr.evaluate(context)
74
+ evaluation_deadline = [serializer.evaluation_deadline, deadline].min
75
+ value = capture_expression.expr.evaluate(context, evaluation_deadline: evaluation_deadline)
74
76
  limits = CaptureLimits.resolve(
75
77
  expr_limits: capture_expression.limits,
76
78
  probe: probe,
@@ -86,6 +88,14 @@ module Datadog
86
88
  )
87
89
  rescue Exception => exc # standard:disable Lint/RescueException
88
90
  Datadog::DI.reraise_if_fatal(exc)
91
+ if exc.is_a?(DI::Error::EvaluationTimeout) && capture_deadline_passed?(deadline)
92
+ record_capture_timeout(output, name, probe)
93
+ next
94
+ end
95
+ DI.report_evaluation_timeout(
96
+ telemetry: telemetry, guardrails_telemetry: guardrails_telemetry, logger: logger,
97
+ probe: probe, kind: "capture expression", exc: exc,
98
+ )
89
99
  evaluation_errors << EvaluationFailure.new(expr: name, message: "#{exc.class}: #{exc.message}")
90
100
  logger.debug do
91
101
  "di: probe #{probe.id}: capture expression #{name}: evaluation failed: #{exc.class}: #{exc.message}"
@@ -96,6 +106,33 @@ module Datadog
96
106
 
97
107
  Result.new(serialized_values: output, errors: evaluation_errors)
98
108
  end
109
+
110
+ private
111
+
112
+ # Returns whether the thread CPU clock has reached +capture_deadline+.
113
+ #
114
+ # @param capture_deadline [Float] the capture deadline, as
115
+ # CLOCK_THREAD_CPUTIME_ID float seconds.
116
+ # @return [Boolean]
117
+ def capture_deadline_passed?(capture_deadline)
118
+ Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID, :float_second) >= capture_deadline
119
+ end
120
+
121
+ # Reports capture expression +name+ as not captured because the
122
+ # capture budget ran out.
123
+ #
124
+ # @param output [Hash{String => Object}] serialized values by name.
125
+ # @param name [String] the capture expression's name.
126
+ # @param probe [Probe] the probe whose capture expression is stopped.
127
+ # @return [void]
128
+ def record_capture_timeout(output, name, probe)
129
+ output[name] = {notCapturedReason: "timeout"}
130
+ telemetry&.inc(DI::TELEMETRY_NAMESPACE, "capture_expressions_skipped_by_timeout", 1)
131
+ guardrails_telemetry.skipped(
132
+ reason: GuardrailsTelemetry::Reason::EVALUATION_TIMEOUT,
133
+ probe: probe,
134
+ )
135
+ end
99
136
  end
100
137
  end
101
138
  end
@@ -100,10 +100,11 @@ module Datadog
100
100
  )
101
101
  @instrumenter = Instrumenter.new(settings, serializer, logger, code_tracker: code_tracker, telemetry: telemetry,
102
102
  guardrails_telemetry: guardrails_telemetry,
103
- capture_expression_evaluator: capture_expression_evaluator,)
103
+ capture_expression_evaluator: capture_expression_evaluator)
104
104
  @probe_repository = ProbeRepository.new
105
105
  @probe_notification_builder = ProbeNotificationBuilder.new(settings, serializer, logger,
106
- capture_expression_evaluator: capture_expression_evaluator,)
106
+ capture_expression_evaluator: capture_expression_evaluator, guardrails_telemetry: guardrails_telemetry,
107
+ telemetry: telemetry)
107
108
  @probe_notifier_worker = ProbeNotifierWorker.new(
108
109
  settings, logger,
109
110
  agent_settings: agent_settings,
@@ -169,6 +169,25 @@ module Datadog
169
169
  end
170
170
  end
171
171
 
172
+ # Maximum thread CPU time, in milliseconds, allowed for
173
+ # evaluating expressions. The env var key is shared with
174
+ # other tracers, which measure wall time for it.
175
+ #
176
+ # @return [Integer]
177
+ option :max_time_to_evaluate_ms do |o|
178
+ o.type :int
179
+ o.default 50
180
+ o.env "DD_DYNAMIC_INSTRUMENTATION_EVALUATION_TIMEOUT_MS"
181
+ o.setter do |value, _old|
182
+ if value < 0
183
+ raise ArgumentError,
184
+ "The setting `dynamic_instrumentation.max_time_to_evaluate_ms` must not be negative, " \
185
+ "but `#{value.inspect}` was provided."
186
+ end
187
+ value
188
+ end
189
+ end
190
+
172
191
  # Settings in the 'internal' group are for internal Datadog
173
192
  # use only, and are needed to test dynamic instrumentation or
174
193
  # experiment with features not released to customers.
@@ -9,7 +9,7 @@ Datadog::DI::Serializer.register(
9
9
  # An alternative could have been to make DI specifically provide lookup
10
10
  # logic for "instances of classes derived from X", but a condition Proc
11
11
  # is more universal.
12
- condition: lambda { |value| ActiveRecord::Base === value }
12
+ condition: lambda { |value| ActiveRecord::Base === value },
13
13
  ) do |serializer, value, name:, depth:, deadline:|
14
14
  # +serializer+ is an instance of DI::Serializer.
15
15
  # Use it to perform the serialization to primitive values.
@@ -133,7 +133,7 @@ module Datadog
133
133
  raise DI::Error::BadVariableName, "Bad variable name: #{target}"
134
134
  end
135
135
  method_name = (($1 == "@") ? "iref" : "ref")
136
- "#{method_name}('#{target}')"
136
+ "#{method_name}(context, '#{target}')"
137
137
  end
138
138
  when *SINGLE_ARG_METHODS
139
139
  method_name = op.gsub(/[A-Z]/) { |m| "_#{m.downcase}" }
@@ -146,10 +146,10 @@ module Datadog
146
146
  if String === second
147
147
  # Match against a literal regular expression (string).
148
148
  index = precompile_regexp(second, regexps)
149
- "matches_compiled(#{compile_partial(first, regexps)}, #{index})"
149
+ "matches_compiled(#{compile_partial(first, regexps)}, #{index}, evaluation_deadline)"
150
150
  else
151
151
  # Match against a (complex) expression.
152
- "matches(#{compile_partial(first, regexps)}, (#{compile_partial(second, regexps)}))"
152
+ "matches(#{compile_partial(first, regexps)}, (#{compile_partial(second, regexps)}), evaluation_deadline)"
153
153
  end
154
154
  when *TWO_ARG_METHODS
155
155
  method_name = op.gsub(/[A-Z]/) { |m| "_#{m.downcase}" }
@@ -185,7 +185,7 @@ module Datadog
185
185
  unless Array === target && target.length == 2
186
186
  raise DI::Error::InvalidExpression, "Improper #{op} syntax"
187
187
  end
188
- "#{op}(#{compile_partial(target.first, regexps)}) { |current_item, current_key, current_value| #{compile_partial(target.last, regexps)} }"
188
+ "#{op}(#{compile_partial(target.first, regexps)}, evaluation_deadline) { |current_item, current_key, current_value| #{compile_partial(target.last, regexps)} }"
189
189
  else
190
190
  raise DI::Error::InvalidExpression, "Unknown operation: #{op}"
191
191
  end