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
@@ -4,6 +4,7 @@
4
4
 
5
5
  require_relative "evaluation_failure"
6
6
  require_relative "fatal_exceptions"
7
+ require_relative "guardrails_telemetry"
7
8
 
8
9
  module Datadog
9
10
  module DI
@@ -17,12 +18,17 @@ module Datadog
17
18
  # @param serializer [Serializer] serializer for captured values
18
19
  # @param logger [DI::Logger] logger for builder diagnostics
19
20
  # @param capture_expression_evaluator [CaptureExpressionEvaluator] evaluator for the probe's capture expressions
21
+ # @param guardrails_telemetry [GuardrailsTelemetry] emitter for the canonical evaluation-timeout skip metric
22
+ # @param telemetry [Datadog::Core::Telemetry::Component, nil] component evaluation timeouts are counted through
20
23
  # @return [void]
21
- def initialize(settings, serializer, logger, capture_expression_evaluator:)
24
+ def initialize(settings, serializer, logger, capture_expression_evaluator:, guardrails_telemetry:,
25
+ telemetry:)
22
26
  @settings = settings
23
27
  @serializer = serializer
24
28
  @logger = logger
25
29
  @capture_expression_evaluator = capture_expression_evaluator
30
+ @guardrails_telemetry = guardrails_telemetry
31
+ @telemetry = telemetry
26
32
  end
27
33
 
28
34
  attr_reader :settings
@@ -33,35 +39,43 @@ module Datadog
33
39
 
34
40
  attr_reader :capture_expression_evaluator
35
41
 
42
+ # The guardrails metric emitter.
43
+ # @return [GuardrailsTelemetry]
44
+ attr_reader :guardrails_telemetry
45
+
46
+ # The telemetry component evaluation timeouts are counted through.
47
+ # @return [Datadog::Core::Telemetry::Component, nil]
48
+ attr_reader :telemetry
49
+
36
50
  def build_received(probe)
37
51
  build_status(probe,
38
52
  message: "Probe #{probe.id} has been received correctly",
39
- status: "RECEIVED",)
53
+ status: "RECEIVED")
40
54
  end
41
55
 
42
56
  def build_installed(probe)
43
57
  build_status(probe,
44
58
  message: "Probe #{probe.id} has been instrumented correctly",
45
- status: "INSTALLED",)
59
+ status: "INSTALLED")
46
60
  end
47
61
 
48
62
  def build_emitting(probe)
49
63
  build_status(probe,
50
64
  message: "Probe #{probe.id} is emitting",
51
- status: "EMITTING",)
65
+ status: "EMITTING")
52
66
  end
53
67
 
54
68
  def build_errored(probe, exc)
55
69
  build_status(probe,
56
70
  message: "Instrumentation for probe #{probe.id} failed: #{exc}",
57
71
  status: "ERROR",
58
- exception: exc,)
72
+ exception: exc)
59
73
  end
60
74
 
61
75
  def build_disabled(probe, duration)
62
76
  build_status(probe,
63
77
  message: "Probe #{probe.id} was disabled because it consumed #{duration} seconds of CPU time in DI processing",
64
- status: "ERROR",)
78
+ status: "ERROR")
65
79
  end
66
80
 
67
81
  # Duration is in seconds.
@@ -144,12 +158,13 @@ module Datadog
144
158
  message = nil
145
159
  evaluation_errors = []
146
160
  if segments = probe.template_segments
147
- message, evaluation_errors = evaluate_template(segments, context)
161
+ message, evaluation_errors = evaluate_template(segments, context,
162
+ evaluation_deadline: serializer.evaluation_deadline)
148
163
  end
149
164
  evaluation_errors.concat(capture_expression_evaluation_errors)
150
165
  build_snapshot_base(context,
151
166
  evaluation_errors: evaluation_errors, message: message,
152
- captures: captures,)
167
+ captures: captures)
153
168
  end
154
169
 
155
170
  def build_condition_evaluation_failed(context, expression, exception)
@@ -401,23 +416,56 @@ module Datadog
401
416
  end
402
417
  end
403
418
 
404
- def evaluate_template(template_segments, context)
419
+ # Renders the probe's message template against +context+.
420
+ #
421
+ # @param template_segments [Array<String, EL::Expression>] compiled
422
+ # template segments to render.
423
+ # @param context [Context] evaluation context for expression segments.
424
+ # @param evaluation_deadline [Float] cooperative evaluation deadline, as
425
+ # CLOCK_THREAD_CPUTIME_ID float seconds.
426
+ # @return [Array(String, Array<EvaluationFailure>)] the rendered message
427
+ # and the evaluation errors.
428
+ def evaluate_template(template_segments, context, evaluation_deadline:)
405
429
  evaluation_errors = []
430
+ timed_out = false
406
431
  message = template_segments.map do |segment|
432
+ if segment.is_a?(EL::Expression) && !timed_out &&
433
+ EL::Evaluator.evaluation_deadline_exceeded?(evaluation_deadline)
434
+ raise DI::Error::EvaluationTimeout
435
+ end
407
436
  case segment
408
437
  when String
409
438
  segment
410
439
  when EL::Expression
411
- serializer.serialize_value_for_message(segment.evaluate(context), name: segment.redaction_identifier)
440
+ if timed_out
441
+ # The shared deadline already crossed and reported its
442
+ # timeout, so the remaining segments render as the
443
+ # placeholder rather than raising and re-reporting per
444
+ # segment.
445
+ "[evaluation error]"
446
+ else
447
+ serializer.serialize_value_for_message(segment.evaluate(context, evaluation_deadline: evaluation_deadline), name: segment.redaction_identifier)
448
+ end
412
449
  else
413
450
  raise ArgumentError, "Invalid template segment type: #{segment}"
414
451
  end
415
452
  rescue Exception => exc # standard:disable Lint/RescueException
416
453
  Datadog::DI.reraise_if_fatal(exc)
454
+ DI.report_evaluation_timeout(
455
+ telemetry: telemetry, guardrails_telemetry: guardrails_telemetry, logger: logger,
456
+ probe: context.probe, kind: "template", exc: exc,
457
+ )
417
458
  evaluation_errors << EvaluationFailure.new(
418
459
  expr: segment.dsl_expr, # steep:ignore NoMethod
419
460
  message: "#{exc.class}: #{exc.message}",
420
461
  )
462
+ # The matches wall-time bound also raises EvaluationTimeout
463
+ # without crossing the shared deadline, and it stops only one
464
+ # segment, so it must not suppress the remaining ones.
465
+ if exc.is_a?(DI::Error::EvaluationTimeout) &&
466
+ EL::Evaluator.evaluation_deadline_exceeded?(evaluation_deadline)
467
+ timed_out = true
468
+ end
421
469
  "[evaluation error]"
422
470
  end.join
423
471
  [message, evaluation_errors]
@@ -220,7 +220,7 @@ module Datadog
220
220
  # @return [DI::Transport::Input::Transport]
221
221
  def snapshot_transport
222
222
  @snapshot_transport ||= DI::Transport::HTTP.input(agent_settings: agent_settings, logger: logger,
223
- telemetry: telemetry, guardrails_telemetry: guardrails_telemetry,)
223
+ telemetry: telemetry, guardrails_telemetry: guardrails_telemetry)
224
224
  end
225
225
 
226
226
  # Sends a batch of snapshot payloads to the agent.
@@ -131,6 +131,10 @@ module Datadog
131
131
  @logger = logger
132
132
  @guardrails_telemetry = guardrails_telemetry
133
133
  @telemetry = telemetry
134
+ # Evaluation budget for one expression evaluation, as thread CPU
135
+ # seconds, converted from max_time_to_evaluate_ms here so that
136
+ # deadline resolution per probe firing traverses no settings.
137
+ @evaluation_budget_seconds = settings.dynamic_instrumentation.max_time_to_evaluate_ms / 1000.0
134
138
  end
135
139
 
136
140
  attr_reader :settings
@@ -186,7 +190,7 @@ module Datadog
186
190
  collection_size: nil)
187
191
  combined = combine_args(args, kwargs, target_self)
188
192
  serialize_vars(combined, depth: depth, attribute_count: attribute_count,
189
- length: length, collection_size: collection_size, deadline: deadline,)
193
+ length: length, collection_size: collection_size, deadline: deadline)
190
194
  end
191
195
 
192
196
  # Serializes variables captured by a line probe.
@@ -205,7 +209,7 @@ module Datadog
205
209
  collection_size: nil)
206
210
  vars.each_with_object({}) do |(k, v), agg|
207
211
  agg[k] = serialize_value(v, name: k, depth: depth, attribute_count: attribute_count,
208
- length: length, collection_size: collection_size, deadline: deadline,)
212
+ length: length, collection_size: collection_size, deadline: deadline)
209
213
  end
210
214
  end
211
215
 
@@ -568,8 +572,22 @@ module Datadog
568
572
  settings.dynamic_instrumentation.max_time_to_serialize_ms / 1000.0
569
573
  end
570
574
 
575
+ # Computes the absolute thread CPU time deadline (in seconds) for an
576
+ # expression evaluation by adding the evaluation budget, converted
577
+ # from max_time_to_evaluate_ms once at construction, to the current
578
+ # thread CPU clock reading.
579
+ #
580
+ # @return [Float] absolute thread CPU clock reading, in seconds, at
581
+ # which the evaluation budget is exhausted
582
+ def evaluation_deadline
583
+ Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID, :float_second) +
584
+ evaluation_budget_seconds
585
+ end
586
+
571
587
  private
572
588
 
589
+ attr_reader :evaluation_budget_seconds
590
+
573
591
  def deadline_exceeded?(deadline)
574
592
  Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID, :float_second) >= deadline
575
593
  end
data/lib/datadog/di.rb CHANGED
@@ -173,6 +173,33 @@ module Datadog
173
173
  Datadog.send(:components).dynamic_instrumentation
174
174
  end
175
175
 
176
+ # Reports an evaluation timeout: increments the evaluation_timeouts
177
+ # telemetry counter, emits the canonical guardrail skip metric for the
178
+ # timeout, and logs at debug with the probe id, the evaluation kind and
179
+ # the exception. Returns whether +exc+ was an evaluation timeout, so
180
+ # callers can run timeout-specific follow-up.
181
+ #
182
+ # @param telemetry [Datadog::Core::Telemetry::Component, nil] component
183
+ # the counter increments through.
184
+ # @param guardrails_telemetry [GuardrailsTelemetry] emitter for the
185
+ # canonical evaluation-timeout skip metric.
186
+ # @param logger [DI::Logger] logger the timeout log writes through.
187
+ # @param probe [Probe] the probe whose evaluation timed out.
188
+ # @param kind [String] the evaluation kind, e.g. "condition",
189
+ # "capture expression" or "template".
190
+ # @param exc [Exception] the exception raised by the evaluation.
191
+ # @return [Boolean] whether the exception was an evaluation timeout.
192
+ def report_evaluation_timeout(telemetry:, guardrails_telemetry:, logger:, probe:, kind:, exc:)
193
+ return false unless exc.is_a?(DI::Error::EvaluationTimeout)
194
+ telemetry&.inc(TELEMETRY_NAMESPACE, "evaluation_timeouts", 1)
195
+ guardrails_telemetry.skipped(
196
+ reason: GuardrailsTelemetry::Reason::EVALUATION_TIMEOUT,
197
+ probe: probe,
198
+ )
199
+ logger.debug { "di: probe #{probe.id}: #{kind} evaluation timed out: #{exc.class}: #{exc.message}" }
200
+ true
201
+ end
202
+
176
203
  # Track how many outstanding instrumentations are in DI.
177
204
  #
178
205
  # It is hard to find the actual instrumentations - there is no
@@ -36,7 +36,7 @@ module Datadog
36
36
  elsif RubyVersion.is?("< 2.7")
37
37
  logger.warn(
38
38
  "error tracking: cannot enable error tracking: Ruby 2.7+ is required, but running
39
- on #{RUBY_VERSION}"
39
+ on #{RUBY_VERSION}",
40
40
  )
41
41
  false
42
42
  else
@@ -35,7 +35,7 @@ module Datadog
35
35
  Datadog.logger.warn(
36
36
  "Invalid handled errors scope: #{value}. " \
37
37
  "Supported values are: #{Ext::VALID_HANDLED_ERRORS.join(" | ")}. " \
38
- "Deactivating the feature."
38
+ "Deactivating the feature.",
39
39
  )
40
40
  end
41
41
 
@@ -50,7 +50,7 @@ module Datadog
50
50
 
51
51
  if trace.nil? || span.nil?
52
52
  return Datadog.logger.warn(
53
- "Kit::AppSec: Tracing is not enabled. Please enable tracing if you want to track events"
53
+ "Kit::AppSec: Tracing is not enabled. Please enable tracing if you want to track events",
54
54
  )
55
55
  end
56
56
 
@@ -69,7 +69,7 @@ module Datadog
69
69
  record_event_telemetry_metric(LOGIN_SUCCESS_EVENT)
70
70
  ::Datadog::AppSec::Instrumentation.gateway.push("appsec.events.user_lifecycle", LOGIN_SUCCESS_EVENT)
71
71
 
72
- return Kit::Identity.set_user(trace, span, **user_attributes) if user_attributes.key?(:id)
72
+ return Kit::Identity.set_user(trace, span, **user_attributes) if user_attributes.key?(:id) # steep:ignore InsufficientKeywordArguments
73
73
 
74
74
  # NOTE: This is a fallback for the case when we don't have an ID,
75
75
  # but need to trigger WAF.
@@ -102,7 +102,7 @@ module Datadog
102
102
 
103
103
  if trace.nil? || span.nil?
104
104
  return Datadog.logger.warn(
105
- "Kit::AppSec: Tracing is not enabled. Please enable tracing if you want to track events"
105
+ "Kit::AppSec: Tracing is not enabled. Please enable tracing if you want to track events",
106
106
  )
107
107
  end
108
108
 
@@ -155,7 +155,7 @@ module Datadog
155
155
 
156
156
  if trace.nil? || span.nil?
157
157
  return Datadog.logger.warn(
158
- "Kit::AppSec: Tracing is not enabled. Please enable tracing if you want to track events"
158
+ "Kit::AppSec: Tracing is not enabled. Please enable tracing if you want to track events",
159
159
  )
160
160
  end
161
161
 
@@ -174,7 +174,7 @@ module Datadog
174
174
  record_event_telemetry_metric(SIGNUP_EVENT)
175
175
 
176
176
  if user_attributes.key?(:id)
177
- Kit::Identity.set_user(trace, span, **user_attributes)
177
+ Kit::Identity.set_user(trace, span, **user_attributes) # steep:ignore InsufficientKeywordArguments
178
178
  else
179
179
  # NOTE: {Datadog::Kit::Identity.set_user} requires an ID,
180
180
  # but WAF can evaluate login alone
@@ -235,7 +235,7 @@ module Datadog
235
235
 
236
236
  if telemetry.nil?
237
237
  return Datadog.logger.debug(
238
- "Kit::AppSec: Telemetry component is unavailable. Skip recording SDK metrics"
238
+ "Kit::AppSec: Telemetry component is unavailable. Skip recording SDK metrics",
239
239
  )
240
240
  end
241
241
 
@@ -160,7 +160,7 @@ module Datadog
160
160
  unless trace && span
161
161
  Datadog.logger.debug(
162
162
  "Tracing not enabled. Method ##{method} is a no-op. Please enable tracing if you want ##{method}" \
163
- " to track this events"
163
+ " to track this events",
164
164
  )
165
165
  return
166
166
  end
@@ -31,7 +31,7 @@ module Datadog
31
31
  rescue => e
32
32
  Kernel.warn(
33
33
  "[datadog] Failed to enable core dumps. Cause: #{e.class}: #{e.message} " \
34
- "Location: #{Array(e.backtrace).first}"
34
+ "Location: #{Array(e.backtrace).first}",
35
35
  )
36
36
  return
37
37
  end
@@ -96,7 +96,7 @@ module Datadog
96
96
  unless trace && span
97
97
  Datadog.logger.debug(
98
98
  "Tracing not enabled. Method ##{method} is a no-op. Please enable tracing if you want ##{method}" \
99
- " to track this events"
99
+ " to track this events",
100
100
  )
101
101
  return
102
102
  end
@@ -100,6 +100,7 @@ module Datadog
100
100
  return unless @providers.empty?
101
101
  if @delivery_source == Configuration::Source::REMOTE_CONFIG && @delivery_started
102
102
  # Remote Configuration is process-scoped and may already hold configuration needed by the next provider.
103
+ @logger.debug { "Feature Flags: provider detached; process-scoped Remote Configuration remains active" }
103
104
  [nil, nil]
104
105
  else
105
106
  previous_source = @configuration_source
@@ -149,9 +150,14 @@ module Datadog
149
150
  @activated = true
150
151
  unless resolution.enabled?
151
152
  @failure = "Feature Flags are disabled"
153
+ @logger.debug do
154
+ reason = @settings.feature_flags.enabled ? "the resolved configuration source is offline" : "feature_flags.enabled is false"
155
+ "Feature Flags: disabled because #{reason}"
156
+ end
152
157
  return
153
158
  end
154
159
 
160
+ @logger.debug { "Feature Flags: configuration source is #{resolution.source}" }
155
161
  component = Component.build(
156
162
  @settings,
157
163
  @agent_settings,
@@ -230,6 +236,20 @@ module Datadog
230
236
  end
231
237
 
232
238
  @configuration_source = configuration_source
239
+
240
+ @logger.debug do
241
+ agentless = @settings.feature_flags.agentless
242
+ sdk_env = @settings.env ? "sdk_env=#{@settings.env.inspect}" : "sdk_env is unset"
243
+ requested_env = if endpoint.managed?
244
+ @settings.env ? "requested_env=#{@settings.env.inspect}" : "requested_env is unset"
245
+ else
246
+ "requested_env is not sent (custom endpoint)"
247
+ end
248
+ "Feature Flags: starting agentless configuration source at #{endpoint.origin} " \
249
+ "(#{sdk_env}, #{requested_env}, " \
250
+ "poll interval #{agentless.poll_interval_seconds}s, request timeout #{agentless.request_timeout_seconds}s)"
251
+ end
252
+
233
253
  started = configuration_source.start
234
254
  @failure = "Feature Flags agentless delivery could not start" unless started
235
255
  started
@@ -241,7 +261,7 @@ module Datadog
241
261
  @failure = "Feature Flags Remote Configuration is unavailable"
242
262
  @logger.warn(
243
263
  "#{@failure}. To enable Remote Configuration, " \
244
- "see https://docs.datadoghq.com/remote_configuration/."
264
+ "see https://docs.datadoghq.com/remote_configuration/.",
245
265
  )
246
266
  return false
247
267
  end
@@ -249,6 +269,7 @@ module Datadog
249
269
  receivers = @remote_receivers ||= Remote.receivers(
250
270
  @telemetry,
251
271
  component_provider: -> { @mutex.synchronize { @component } },
272
+ logger: @logger,
252
273
  )
253
274
  remote.register(
254
275
  capabilities: Remote.capabilities,
@@ -256,6 +277,10 @@ module Datadog
256
277
  receivers: receivers,
257
278
  )
258
279
  remote.start
280
+ @logger.debug do
281
+ sdk_env = @settings.env ? "sdk_env=#{@settings.env.inspect}" : "sdk_env is unset"
282
+ "Feature Flags: started Remote Configuration source (#{sdk_env}) using Datadog Agent"
283
+ end
259
284
  true
260
285
  end
261
286
 
@@ -61,6 +61,7 @@ module Datadog
61
61
  @retry_wait = retry_wait || ->(delay) { wait_for_retry(delay) }
62
62
  @etag = nil
63
63
  @warned = {}
64
+ @failed_polls = 0
64
65
  @lifecycle_mutex = Mutex.new
65
66
  @started = false
66
67
  @stopped = false
@@ -91,6 +92,7 @@ module Datadog
91
92
  end
92
93
 
93
94
  super
95
+ @logger.debug { "Feature Flags: stopped agentless configuration polling" }
94
96
  true
95
97
  end
96
98
 
@@ -110,6 +112,7 @@ module Datadog
110
112
  return if stopped?
111
113
 
112
114
  response = @transport.get(@etag)
115
+ log_poll_attempt(response, attempt)
113
116
  unless retryable?(response)
114
117
  apply_response(response)
115
118
  return
@@ -120,7 +123,9 @@ module Datadog
120
123
  return
121
124
  end
122
125
 
123
- return if wait_before_retry(retry_delay(attempt))
126
+ delay = retry_delay(attempt)
127
+ @logger.debug { "Feature Flags: retrying agentless configuration poll in #{delay.round(1)}s" }
128
+ return if wait_before_retry(delay)
124
129
 
125
130
  attempt += 1
126
131
  end
@@ -131,6 +136,7 @@ module Datadog
131
136
  def after_fork
132
137
  # The child must report its own failures, while the inherited ETag still matches its configuration.
133
138
  @warned = {}
139
+ @failed_polls = 0
134
140
  nil
135
141
  end
136
142
 
@@ -140,6 +146,53 @@ module Datadog
140
146
  @lifecycle_mutex.synchronize { @stopped }
141
147
  end
142
148
 
149
+ def log_poll_attempt(response, attempt)
150
+ @logger.debug do
151
+ status = response.status
152
+ outcome = case status
153
+ when nil
154
+ "failed: #{request_error_class(response)}"
155
+ when 304
156
+ "configuration unchanged (HTTP 304)"
157
+ when 200
158
+ etag = response.etag.to_s.strip
159
+ etag.empty? ? "configuration received (HTTP 200)" : "configuration received (ETag #{etag}; HTTP 200)"
160
+ else
161
+ "#{http_failure_reason(status)} (HTTP #{status})"
162
+ end
163
+ "Feature Flags: agentless configuration poll attempt #{attempt}/#{MAX_ATTEMPTS}: #{outcome}"
164
+ end
165
+ end
166
+
167
+ def http_failure_reason(status)
168
+ case status
169
+ when 400
170
+ "configuration request rejected as invalid"
171
+ when 401
172
+ "configuration request lacks valid authentication credentials"
173
+ when 403
174
+ "access to the configuration endpoint is forbidden"
175
+ when 404
176
+ "configuration endpoint not found"
177
+ when 408
178
+ "configuration request timed out"
179
+ when 429
180
+ "configuration request rate limited"
181
+ when 500
182
+ "configuration endpoint encountered an internal error"
183
+ when 502
184
+ "configuration endpoint received an invalid upstream response"
185
+ when 503
186
+ "configuration endpoint is temporarily unavailable"
187
+ when 504
188
+ "configuration endpoint timed out waiting for an upstream response"
189
+ when 500..599
190
+ "configuration endpoint reported a server error"
191
+ else
192
+ "unexpected response from the configuration endpoint"
193
+ end
194
+ end
195
+
143
196
  def retryable?(response)
144
197
  status = response.status
145
198
  return true unless status
@@ -181,17 +234,18 @@ module Datadog
181
234
  end
182
235
 
183
236
  def apply_response(response)
184
- case response.status
237
+ status = response.status
238
+ case status
185
239
  when 200
240
+ log_recovery
186
241
  apply_configuration(response)
187
242
  when 304
188
- nil
243
+ log_recovery
189
244
  when 401, 403
190
- warn_once(:authentication) do
191
- @logger.warn(
192
- "Feature Flags agentless endpoint returned HTTP #{response.status}; verify endpoint authentication"
193
- )
194
- end
245
+ report_poll_failure(
246
+ :authentication,
247
+ "Feature Flags agentless #{http_failure_reason(status)}; verify endpoint authentication (HTTP #{status})",
248
+ )
195
249
  else
196
250
  warn_failure(response, 1)
197
251
  end
@@ -203,6 +257,9 @@ module Datadog
203
257
  warn_once(:malformed) do
204
258
  @logger.error("Feature Flags agentless endpoint returned malformed UFC payload")
205
259
  end
260
+ @logger.debug do
261
+ "Feature Flags: ignoring malformed agentless configuration payload"
262
+ end
206
263
  return
207
264
  end
208
265
 
@@ -224,16 +281,38 @@ module Datadog
224
281
  else
225
282
  :http_unexpected
226
283
  end
227
- warn_once(category) do
228
- if status
229
- @logger.warn("Feature Flags agentless endpoint returned HTTP #{status} after #{attempts} attempt(s)")
230
- else
231
- error_class = response.error ? response.error.class : StandardError
232
- @logger.warn("Feature Flags agentless request failed after #{attempts} attempt(s): #{error_class}")
233
- end
284
+ refresh = (attempts == MAX_ATTEMPTS) ? "; next poll in #{@poll_interval_seconds}s" : ""
285
+ message = if status
286
+ "Feature Flags agentless #{http_failure_reason(status)} after #{attempts} attempt(s) (HTTP #{status})#{refresh}"
287
+ else
288
+ "Feature Flags agentless request failed after #{attempts} attempt(s): #{request_error_class(response)}#{refresh}"
289
+ end
290
+ report_poll_failure(category, message)
291
+ end
292
+
293
+ # Repeats are debug-only so a persistent outage does not flood warnings.
294
+ def report_poll_failure(category, message)
295
+ @failed_polls += 1
296
+ if @warned[category]
297
+ @logger.debug { message }
298
+ else
299
+ warn_once(category) { @logger.warn(message) }
234
300
  end
235
301
  end
236
302
 
303
+ def log_recovery
304
+ return if @failed_polls.zero?
305
+
306
+ failed_polls = @failed_polls
307
+ @failed_polls = 0
308
+ @logger.debug { "Feature Flags: agentless configuration delivery recovered after #{failed_polls} failed poll(s)" }
309
+ end
310
+
311
+ # Class only: transport error messages can embed endpoint details.
312
+ def request_error_class(response)
313
+ response.error ? response.error.class : StandardError
314
+ end
315
+
237
316
  def warn_once(category)
238
317
  return if @warned[category]
239
318
 
@@ -13,6 +13,7 @@ require_relative "flag_evaluation/writer"
13
13
  require_relative "hooks/flag_eval_metrics_hook"
14
14
  require_relative "hooks/flag_eval_evp_hook"
15
15
  require_relative "hooks/span_enrichment_hook"
16
+ require_relative "hooks/debug_logging_hook"
16
17
 
17
18
  module Datadog
18
19
  module OpenFeature
@@ -70,12 +71,15 @@ module Datadog
70
71
  @flag_eval_metrics_hook = create_flag_eval_metrics_hook
71
72
  @flag_eval_evp_hook = create_flag_eval_evp_hook
72
73
  @span_enrichment_hook = create_span_enrichment_hook
74
+ @debug_logging_hook = nil
73
75
 
74
76
  @configuration_mutex = Mutex.new
75
77
  @reconfiguration_mutex = Mutex.new
76
78
  @configuration_condition = ConditionVariable.new
77
79
  @configuration_received = false
78
80
  @configuration_shutdown = false
81
+
82
+ @engine.warn_raw_data_logging
79
83
  end
80
84
 
81
85
  def reconfigure!(configuration)
@@ -102,9 +106,19 @@ module Datadog
102
106
  @on_configuration_change&.call(event) if event
103
107
  end
104
108
 
109
+ # Checked per evaluation so the SDK skips hook dispatch unless debug logging is on. Built lazily
110
+ # because Remote Configuration can build this component before the OpenFeature SDK loads.
111
+ def debug_logging_hook
112
+ return unless @logger.debug?
113
+
114
+ @engine.warn_raw_data_logging
115
+ @debug_logging_hook ||= create_debug_logging_hook
116
+ end
117
+
105
118
  def wait_for_configuration(&cancelled)
106
- timeout_seconds = @settings.feature_flags.initialization_timeout_ms / 1000.0
107
- deadline = Core::Utils::Time.get_time + timeout_seconds
119
+ timeout_ms = @settings.feature_flags.initialization_timeout_ms
120
+ @logger.debug { "Feature Flags: waiting up to #{timeout_ms}ms for configuration" }
121
+ deadline = Core::Utils::Time.get_time + timeout_ms / 1000.0
108
122
 
109
123
  @configuration_mutex.synchronize do
110
124
  loop do
@@ -176,6 +190,12 @@ module Datadog
176
190
  store = Hooks::SpanEnrichmentHook::SpanEnrichmentStateStore.new
177
191
  Hooks::SpanEnrichmentHook.new(store, logger: @logger)
178
192
  end
193
+
194
+ def create_debug_logging_hook
195
+ return unless Hooks::DebugLoggingHook.available?
196
+
197
+ Hooks::DebugLoggingHook.new(@logger)
198
+ end
179
199
  end
180
200
  end
181
201
  end
@@ -84,6 +84,12 @@ module Datadog
84
84
  def managed?
85
85
  @managed
86
86
  end
87
+
88
+ # Excludes userinfo, path, and query, which may carry credentials.
89
+ def origin
90
+ origin = "#{uri.scheme}://#{uri.host}"
91
+ (uri.port == uri.default_port) ? origin : "#{origin}:#{uri.port}"
92
+ end
87
93
  end
88
94
  end
89
95
  end