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
@@ -44,7 +44,7 @@ module Datadog
44
44
 
45
45
  Datadog.logger.warn(
46
46
  "DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED is deprecated; use " \
47
- "DD_FEATURE_FLAGS_ENABLED and DD_FEATURE_FLAGS_CONFIGURATION_SOURCE instead"
47
+ "DD_FEATURE_FLAGS_ENABLED and DD_FEATURE_FLAGS_CONFIGURATION_SOURCE instead",
48
48
  )
49
49
  end
50
50
  end
@@ -118,7 +118,7 @@ module Datadog
118
118
  value
119
119
  else
120
120
  Datadog.logger.warn(
121
- "Feature Flags agentless poll interval must be positive; using the default"
121
+ "Feature Flags agentless poll interval must be positive; using the default",
122
122
  )
123
123
  Settings::DEFAULT_POLL_INTERVAL_SECONDS
124
124
  end
@@ -138,7 +138,7 @@ module Datadog
138
138
  else
139
139
  Datadog.logger.warn(
140
140
  "Feature Flags agentless request timeout must be within (0, " \
141
- "#{Settings::MAX_REQUEST_TIMEOUT_SECONDS}]; using the default"
141
+ "#{Settings::MAX_REQUEST_TIMEOUT_SECONDS}]; using the default",
142
142
  )
143
143
  Settings::DEFAULT_REQUEST_TIMEOUT_SECONDS
144
144
  end
@@ -159,7 +159,7 @@ module Datadog
159
159
  else
160
160
  Datadog.logger.warn(
161
161
  "Feature Flags provider initialization timeout must be within (0, " \
162
- "#{Settings::MAX_INITIALIZATION_TIMEOUT_MS}]; using the default"
162
+ "#{Settings::MAX_INITIALIZATION_TIMEOUT_MS}]; using the default",
163
163
  )
164
164
  Settings::DEFAULT_INITIALIZATION_TIMEOUT_MS
165
165
  end
@@ -1,9 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "json"
4
+
3
5
  require_relative "ext"
4
6
  require_relative "noop_evaluator"
5
7
  require_relative "native_evaluator"
6
8
  require_relative "resolution_details"
9
+ require_relative "../core/utils/only_once"
7
10
 
8
11
  module Datadog
9
12
  module OpenFeature
@@ -14,10 +17,15 @@ module Datadog
14
17
 
15
18
  ALLOWED_TYPES = %i[boolean string number float integer object].freeze
16
19
 
20
+ RAW_DATA_WARNING = "Feature Flags: debug logging is enabled, so feature flag logs include raw evaluation data " \
21
+ "(targeting keys, evaluation context attributes, flag values, and default values) that may contain " \
22
+ "personal or sensitive information. Unset DD_TRACE_DEBUG when you no longer need it."
23
+
17
24
  def initialize(reporter, telemetry:, logger:)
18
25
  @reporter = reporter
19
26
  @telemetry = telemetry
20
27
  @logger = logger
28
+ @raw_data_warning = Core::Utils::OnlyOnce.new
21
29
 
22
30
  @evaluator = NoopEvaluator.new(nil)
23
31
  end
@@ -34,7 +42,7 @@ module Datadog
34
42
  unless ALLOWED_TYPES.include?(expected_type)
35
43
  message = "unknown type #{expected_type.inspect}, allowed types #{ALLOWED_TYPES.join(", ")}"
36
44
  result = ResolutionDetails.build_error(
37
- value: default_value, error_code: Ext::UNKNOWN_TYPE, error_message: message
45
+ value: default_value, error_code: Ext::UNKNOWN_TYPE, error_message: message,
38
46
  )
39
47
 
40
48
  return with_observe_full_evaluation_data(result, observe_full_evaluation_data)
@@ -42,19 +50,21 @@ module Datadog
42
50
 
43
51
  context = evaluation_context&.fields.to_h
44
52
  result = evaluator.get_assignment(
45
- flag_key, default_value: default_value, context: context, expected_type: expected_type
53
+ flag_key, default_value: default_value, context: context, expected_type: expected_type,
46
54
  )
47
55
 
48
56
  result = with_observe_full_evaluation_data(result, observe_full_evaluation_data)
57
+ log_resolution(flag_key, expected_type, result)
49
58
 
50
59
  @reporter.report(result, flag_key: flag_key, context: evaluation_context)
51
60
 
52
61
  result
53
62
  rescue => e
54
63
  @telemetry.report(e, description: "OpenFeature: Failed to fetch flag value")
64
+ log_resolution_failure(flag_key, e)
55
65
 
56
66
  result = ResolutionDetails.build_error(
57
- value: default_value, error_code: Ext::GENERAL, error_message: "#{e.class}: #{e.message}"
67
+ value: default_value, error_code: Ext::GENERAL, error_message: "#{e.class}: #{e.message}",
58
68
  )
59
69
  # `== true` is load-bearing: Steep types this local as `(nil | bool)` in a rescue
60
70
  # body, and coercing at the use site is what narrows it to `bool`.
@@ -66,12 +76,13 @@ module Datadog
66
76
  # in the format expected by `libdatadog` without any modifications
67
77
  def reconfigure!(configuration)
68
78
  if configuration.nil?
69
- @logger.debug("OpenFeature: Removing configuration")
79
+ @logger.debug("Feature Flags: configuration removed")
70
80
 
71
81
  return @evaluator = NoopEvaluator.new(configuration)
72
82
  end
73
83
 
74
84
  @evaluator = NativeEvaluator.new(configuration)
85
+ @logger.debug { "Feature Flags: configuration applied; #{configuration_summary(configuration)}" }
75
86
  rescue => e
76
87
  message = "OpenFeature: Failed to reconfigure, reverting to the previous configuration"
77
88
 
@@ -81,8 +92,55 @@ module Datadog
81
92
  raise ReconfigurationError, "#{e.class}: #{e.message}"
82
93
  end
83
94
 
95
+ # Public so Component can warn before handing out DebugLoggingHook, which logs raw data.
96
+ def warn_raw_data_logging
97
+ return unless @logger.debug?
98
+
99
+ @raw_data_warning.run { @logger.warn(RAW_DATA_WARNING) }
100
+ end
101
+
84
102
  private
85
103
 
104
+ # The SDK can still replace this result, for example on a type mismatch; DebugLoggingHook logs the final one.
105
+ def log_resolution(flag_key, expected_type, result)
106
+ @logger.debug do
107
+ warn_raw_data_logging
108
+ "Feature Flags: provider resolved #{flag_key.inspect}: type=#{expected_type}, " \
109
+ "value=#{result.value.inspect}, variant=#{result.variant.inspect}, reason=#{result.reason.inspect}, " \
110
+ "allocation=#{result.allocation_key.inspect}, serial_id=#{result.serial_id.inspect}, " \
111
+ "error_code=#{result.error_code.inspect}, error_message=#{result.error_message.inspect}"
112
+ end
113
+ end
114
+
115
+ def log_resolution_failure(flag_key, error)
116
+ @logger.debug do
117
+ warn_raw_data_logging
118
+ "Feature Flags: provider failed to resolve #{flag_key.inspect}: #{error.class}: #{error.message}; " \
119
+ "returning the default value"
120
+ end
121
+ end
122
+
123
+ def configuration_summary(configuration)
124
+ payload = begin
125
+ JSON.parse(configuration)
126
+ rescue JSON::NestingError
127
+ # Native parsing accepts deeper JSON than Ruby's default nesting limit.
128
+ return "received payload metadata unavailable: JSON nesting exceeds the diagnostic parser limit"
129
+ end
130
+ return "received payload metadata unavailable: expected a JSON object" unless payload.is_a?(Hash)
131
+
132
+ flags = payload["flags"]
133
+ environment = payload["environment"]
134
+ environment_name = environment["name"] if environment.is_a?(Hash)
135
+ flag_count = flags.is_a?(Hash) ? "flag_count=#{flags.size}" : "flag_count is not specified"
136
+ environment_summary = environment_name ? "environment=#{environment_name.inspect}" : "environment is not specified"
137
+ created_at = payload["createdAt"]
138
+ creation_summary = created_at ? "created_at=#{created_at.inspect}" : "created_at is not specified"
139
+
140
+ "received payload: #{flag_count}, #{environment_summary}, #{creation_summary}; " \
141
+ "individual flags may still fail evaluation"
142
+ end
143
+
86
144
  # Stamps observe_full_evaluation_data onto the result metadata so the hook
87
145
  # reads it from the event, not live config.
88
146
  def with_observe_full_evaluation_data(result, observe_full_evaluation_data)
@@ -21,6 +21,10 @@ module Datadog
21
21
  super
22
22
  end
23
23
 
24
+ def pending_dropped_count
25
+ @dropped
26
+ end
27
+
24
28
  protected
25
29
 
26
30
  def drain!
@@ -19,21 +19,34 @@ module Datadog
19
19
  # might be missing depending on the customer way of using flags evaluation API.
20
20
  # In addition to that the evaluation result must be marked for reporting.
21
21
  def report(result, flag_key:, context:)
22
- return false if context.nil?
23
- return false unless result.log?
22
+ return skip(flag_key, "no evaluation context") if context.nil?
23
+ return skip(flag_key, "the evaluation result is not marked for exposure logging") unless result.log?
24
24
 
25
25
  key = Event.cache_key(result, flag_key: flag_key, context: context)
26
26
  value = Event.cache_value(result, flag_key: flag_key, context: context)
27
- return false if @deduplicator.duplicate?(key, value)
27
+ return skip(flag_key, "duplicate of the last exposure for this subject") if @deduplicator.duplicate?(key, value)
28
28
 
29
29
  event = Event.build(result, flag_key: flag_key, context: context)
30
- @worker.enqueue(event)
30
+ return false unless @worker.enqueue(event)
31
+
32
+ @logger.debug do
33
+ "Feature Flags: queued exposure for #{flag_key.inspect} (allocation=#{result.allocation_key.inspect}, " \
34
+ "variant=#{result.variant.inspect}, targeting_key=#{context.targeting_key.inspect})"
35
+ end
36
+ true
31
37
  rescue => e
32
38
  @logger.debug { "OpenFeature: Failed to report resolution details: #{e.class}: #{e.message}" }
33
39
  @telemetry.report(e, description: "OpenFeature: Failed to report resolution details")
34
40
 
35
41
  false
36
42
  end
43
+
44
+ private
45
+
46
+ def skip(flag_key, reason)
47
+ @logger.debug { "Feature Flags: exposure for #{flag_key.inspect} not recorded: #{reason}" }
48
+ false
49
+ end
37
50
  end
38
51
  end
39
52
  end
@@ -54,7 +54,11 @@ module Datadog
54
54
  end
55
55
 
56
56
  def enqueue(event)
57
- buffer.push(event)
57
+ unless buffer.push(event)
58
+ @logger.debug { "Feature Flags: exposure not queued: buffer closed" }
59
+ return false
60
+ end
61
+
58
62
  start unless running?
59
63
 
60
64
  true
@@ -84,7 +88,10 @@ module Datadog
84
88
  break if Core::Utils::Time.get_time - started > wait_time
85
89
  end
86
90
 
87
- stop(true)
91
+ log_shutdown_outcome(wait_time)
92
+ stopped = stop(true)
93
+ @logger.debug("Feature Flags: exposure worker stopped") unless running?
94
+ stopped
88
95
  end
89
96
 
90
97
  private
@@ -93,23 +100,47 @@ module Datadog
93
100
  return if events.empty?
94
101
 
95
102
  if dropped.positive?
96
- @logger.debug { "OpenFeature: Resolution details worker dropped #{dropped} event(s) due to full buffer" }
103
+ @logger.debug do
104
+ "Feature Flags: dropped #{dropped} older queued exposure event(s) because the exposure buffer was full"
105
+ end
97
106
  end
98
107
 
99
108
  payload = @batch_builder.payload_for(events)
109
+ @logger.debug { "Feature Flags: flushing #{events.size} exposure event(s) to the Datadog Agent" }
100
110
  response = @transport.send_exposures(payload)
101
111
 
102
- unless response&.ok?
103
- @logger.debug { "OpenFeature: Resolution details upload response was not OK: #{response.inspect}" }
112
+ if response&.ok?
113
+ @logger.debug { "Feature Flags: sent #{events.size} exposure event(s) to the Datadog Agent" }
114
+ else
115
+ @logger.debug do
116
+ "Feature Flags: exposure upload response was not OK; dropping #{events.size} exposure event(s) " \
117
+ "without retry: #{response.inspect}"
118
+ end
104
119
  end
105
120
 
106
121
  response
107
122
  rescue => e
108
- @logger.debug { "OpenFeature: Failed to flush resolution details events: #{e.class}: #{e.message}" }
123
+ @logger.debug do
124
+ "Feature Flags: failed to flush exposure events; dropping #{events.size} exposure event(s) " \
125
+ "without retry: #{e.class}: #{e.message}"
126
+ end
109
127
  @telemetry.report(e, description: "OpenFeature: Failed to flush resolution details events")
110
128
 
111
129
  nil
112
130
  end
131
+
132
+ def log_shutdown_outcome(wait_time)
133
+ @logger.debug do
134
+ queued = buffer.length
135
+ evicted = buffer.pending_dropped_count
136
+ uploading = !!in_iteration?
137
+ remaining = queued.positive? ? "; #{queued} queued exposure event(s) will not be sent" : "; no queued exposure events remain"
138
+ remaining += "; #{evicted} exposure event(s) evicted from the full buffer were not sent" if evicted.positive?
139
+ outcome = uploading ? "; the in-flight upload may still report sent or dropping during shutdown; if forcibly terminated, its outcome will not be reported" : ""
140
+ "Feature Flags: exposure shutdown wait finished; queued=#{queued}, " \
141
+ "upload_in_progress=#{uploading}, wait_budget=#{wait_time}s#{remaining}#{outcome}"
142
+ end
143
+ end
113
144
  end
114
145
  end
115
146
  end
@@ -124,7 +124,7 @@ module Datadog
124
124
  if per_flag_count >= @per_flag_cap
125
125
  add_to_degraded(
126
126
  flag_key, variant, allocation_key, runtime_default, error_message, evaluation_time_ms,
127
- observe_full_evaluation_data
127
+ observe_full_evaluation_data,
128
128
  )
129
129
  return
130
130
  end
@@ -140,7 +140,7 @@ module Datadog
140
140
  error_message: error_message,
141
141
  targeting_key: targeting_key,
142
142
  context_attrs: observe_full_evaluation_data ? attrs : nil,
143
- observe_full_evaluation_data: observe_full_evaluation_data
143
+ observe_full_evaluation_data: observe_full_evaluation_data,
144
144
  )
145
145
  @full[full_key] = entry
146
146
  @global_count += 1
@@ -148,7 +148,7 @@ module Datadog
148
148
  # Route to degraded tier
149
149
  add_to_degraded(
150
150
  flag_key, variant, allocation_key, runtime_default, error_message, evaluation_time_ms,
151
- observe_full_evaluation_data
151
+ observe_full_evaluation_data,
152
152
  )
153
153
  end
154
154
  end
@@ -328,7 +328,7 @@ module Datadog
328
328
  end
329
329
 
330
330
  output[prefix] = string_value.encode(
331
- Encoding::UTF_8, invalid: :replace, undef: :replace
331
+ Encoding::UTF_8, invalid: :replace, undef: :replace,
332
332
  ).freeze
333
333
  rescue
334
334
  # Unsupported caller values must not break flag evaluation.
@@ -433,7 +433,7 @@ module Datadog
433
433
  evaluation_time_ms,
434
434
  runtime_default: runtime_default,
435
435
  error_message: error_message,
436
- observe_full_evaluation_data: observe_full_evaluation_data
436
+ observe_full_evaluation_data: observe_full_evaluation_data,
437
437
  )
438
438
  end
439
439
  end
@@ -489,7 +489,7 @@ module Datadog
489
489
  {
490
490
  "context" => @service_context,
491
491
  "flagEvaluations" => events,
492
- }
492
+ },
493
493
  )
494
494
  if response.respond_to?(:ok?) && !response.ok?
495
495
  @logger.debug { "OpenFeature EVP: transport response was not OK: #{response.inspect}" }
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../ext"
4
+
5
+ module Datadog
6
+ module OpenFeature
7
+ module Hooks
8
+ # Logs each SDK-final evaluation outcome for onboarding diagnostics.
9
+ #
10
+ # Logs raw flag values, default values, targeting keys, context attributes, and
11
+ # error messages, so it is only registered while debug logging is enabled.
12
+ class DebugLoggingHook
13
+ include ::OpenFeature::SDK::Hooks::Hook if defined?(::OpenFeature::SDK::Hooks::Hook)
14
+
15
+ def self.available?
16
+ !!defined?(::OpenFeature::SDK::Hooks::Hook)
17
+ end
18
+
19
+ def initialize(logger)
20
+ @logger = logger
21
+ end
22
+
23
+ def finally(hook_context:, evaluation_details:, **_opts)
24
+ @logger.debug do
25
+ evaluation_context = hook_context.evaluation_context
26
+ "Feature Flags: evaluated #{hook_context.flag_key.inspect} (" \
27
+ "type=#{hook_context.flag_value_type}, " \
28
+ "default=#{hook_context.default_value.inspect}, " \
29
+ "value=#{evaluation_details.value.inspect}, " \
30
+ "variant=#{evaluation_details.variant.inspect}, " \
31
+ "reason=#{evaluation_details.reason.inspect}, " \
32
+ "allocation=#{extract_allocation_key(evaluation_details).inspect}, " \
33
+ "error_code=#{evaluation_details.error_code.inspect}, " \
34
+ "error_message=#{evaluation_details.error_message.inspect}, " \
35
+ "targeting_key=#{evaluation_context&.targeting_key.inspect}, " \
36
+ "attributes=#{attributes(evaluation_context).inspect}, " \
37
+ "flag_metadata=#{evaluation_details.flag_metadata.inspect})"
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def extract_allocation_key(evaluation_details)
44
+ metadata = evaluation_details.flag_metadata
45
+ metadata&.[](Ext::METADATA_ALLOCATION_KEY)
46
+ end
47
+
48
+ def attributes(evaluation_context)
49
+ return {} unless evaluation_context
50
+
51
+ evaluation_context.fields.reject { |key, _value| key == ::OpenFeature::SDK::EvaluationContext::TARGETING_KEY }
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -94,7 +94,7 @@ module Datadog
94
94
  end
95
95
  end
96
96
  rescue => e
97
- @logger.debug { "Error capturing span enrichment: #{e.class}: #{e.message}" }
97
+ @logger.debug { "OpenFeature: Error capturing span enrichment: #{e.class}: #{e.message}" }
98
98
  end
99
99
 
100
100
  # Provider-close cleanup: mark the hook inactive and drop all accumulated
@@ -153,7 +153,7 @@ module Datadog
153
153
 
154
154
  write_tags_on_root(span_op, finishing_trace_op, state)
155
155
  rescue => e
156
- @logger.debug { "Error writing span enrichment tags: #{e.class}: #{e.message}" }
156
+ @logger.debug { "OpenFeature: Error writing span enrichment tags: #{e.class}: #{e.message}" }
157
157
  end
158
158
  end
159
159
 
@@ -78,7 +78,7 @@ module Datadog
78
78
  @counter = meter.create_counter(
79
79
  METRIC_NAME,
80
80
  unit: METRIC_UNIT,
81
- description: METRIC_DESCRIPTION
81
+ description: METRIC_DESCRIPTION,
82
82
  )
83
83
  end
84
84
  rescue => e
@@ -66,7 +66,7 @@ module Datadog
66
66
  ResolutionDetails.build_error(
67
67
  value: default_value,
68
68
  error_code: Ext::PARSE_ERROR,
69
- error_message: INVALID_FLAG_CONFIGURATION_ERROR_MESSAGE
69
+ error_message: INVALID_FLAG_CONFIGURATION_ERROR_MESSAGE,
70
70
  )
71
71
  end
72
72
  end
@@ -23,7 +23,7 @@ module Datadog
23
23
  error?: true,
24
24
  error_code: Ext::PROVIDER_NOT_READY,
25
25
  error_message: "Waiting for flags configuration",
26
- reason: Ext::ERROR
26
+ reason: Ext::ERROR,
27
27
  )
28
28
  end
29
29
  end
@@ -108,6 +108,7 @@ module Datadog
108
108
  @stale_emitted = false
109
109
  @stale_pending = false
110
110
  end
111
+ Datadog.logger.debug { "Feature Flags: provider initialization started" }
111
112
  ready_handler_installed = install_initialization_ready_handler
112
113
 
113
114
  component, failure = OpenFeature.activate_provider(self)
@@ -126,6 +127,7 @@ module Datadog
126
127
  case wait_result
127
128
  when Component::CONFIGURATION_READY
128
129
  @initialization_mutex.synchronize { @initializing = false } unless ready_handler_installed
130
+ Datadog.logger.debug { "Feature Flags: provider initialized successfully" }
129
131
  when Component::CONFIGURATION_TIMEOUT
130
132
  message = "Feature Flags provider initialization timed out while waiting for configuration"
131
133
  Datadog.logger.error(message)
@@ -173,17 +175,20 @@ module Datadog
173
175
  )
174
176
  end
175
177
  OpenFeature.deactivate_provider(self)
178
+ Datadog.logger.debug { "Feature Flags: provider shut down" }
176
179
  end
177
180
 
178
181
  def hooks
179
182
  component = Datadog.send(:components).open_feature
180
- hooks = [
183
+ telemetry_hooks = [
181
184
  component&.flag_eval_metrics_hook,
182
185
  component&.flag_eval_evp_hook,
183
186
  ].compact
184
- return hooks unless @enable_evaluation_telemetry_opt_out_parameter
187
+ if @enable_evaluation_telemetry_opt_out_parameter
188
+ telemetry_hooks = telemetry_hooks.map { |hook| Hooks::EvaluationTelemetryOptOutHook.new(hook) }
189
+ end
185
190
 
186
- hooks.map { |hook| Hooks::EvaluationTelemetryOptOutHook.new(hook) }
191
+ [*telemetry_hooks, component&.debug_logging_hook].compact
187
192
  end
188
193
 
189
194
  def fetch_boolean_value(flag_key:, default_value:, evaluation_context: nil)
@@ -234,6 +239,8 @@ module Datadog
234
239
  def fail_initialization(component, message)
235
240
  prepare_initialization_failure(component)
236
241
  cancel_initialization_if_shutdown!
242
+ # Non-blocking set_provider surfaces this only as a PROVIDER_ERROR event.
243
+ Datadog.logger.debug { "Feature Flags: provider failed to initialize: #{message}" }
237
244
  raise message.to_s
238
245
  end
239
246
 
@@ -326,7 +333,7 @@ module Datadog
326
333
  end
327
334
  end
328
335
  end
329
- emit_event(::OpenFeature::SDK::ProviderEvent::PROVIDER_READY) if emit_ready
336
+ emit_state_event(::OpenFeature::SDK::ProviderEvent::PROVIDER_READY) if emit_ready
330
337
  end
331
338
 
332
339
  def provider_ready(_details)
@@ -348,7 +355,7 @@ module Datadog
348
355
  end
349
356
  end
350
357
  configuration.remove_handler(::OpenFeature::SDK::ProviderEvent::PROVIDER_READY, handler) if handler
351
- emit_event(::OpenFeature::SDK::ProviderEvent::PROVIDER_STALE) if emit_stale
358
+ emit_state_event(::OpenFeature::SDK::ProviderEvent::PROVIDER_STALE) if emit_stale
352
359
  end
353
360
 
354
361
  def configuration_changed(event)
@@ -394,7 +401,25 @@ module Datadog
394
401
  end
395
402
  end
396
403
 
397
- emit_event(event_type) if event_type
404
+ emit_state_event(event_type) if event_type
405
+ end
406
+
407
+ def emit_state_event(event_type)
408
+ log_state_event(event_type)
409
+ emit_event(event_type)
410
+ end
411
+
412
+ def log_state_event(event_type)
413
+ logger = Datadog.logger
414
+ logger.debug do
415
+ availability = case event_type
416
+ when ::OpenFeature::SDK::ProviderEvent::PROVIDER_READY
417
+ "; configuration is available"
418
+ when ::OpenFeature::SDK::ProviderEvent::PROVIDER_STALE
419
+ "; configuration is no longer available"
420
+ end
421
+ "Feature Flags: provider emitted #{event_type}#{availability}"
422
+ end
398
423
  end
399
424
 
400
425
  def evaluate(flag_key, default_value:, expected_type:, evaluation_context:)
@@ -404,7 +429,10 @@ module Datadog
404
429
  flag_meta = nil
405
430
 
406
431
  engine = OpenFeature.engine
407
- return component_not_configured_default(default_value, eval_time_ms) if engine.nil?
432
+ if engine.nil?
433
+ log_component_not_configured(flag_key, expected_type)
434
+ return component_not_configured_default(default_value, eval_time_ms)
435
+ end
408
436
 
409
437
  result = fetch_engine_value(engine, flag_key, default_value, expected_type, evaluation_context)
410
438
 
@@ -428,11 +456,11 @@ module Datadog
428
456
  error_result = Datadog::OpenFeature::ResolutionDetails.build_error(
429
457
  value: default_value,
430
458
  error_code: Ext::GENERAL,
431
- error_message: error_message
459
+ error_message: error_message,
432
460
  )
433
461
  error_flag_meta = flag_meta
434
462
  error_flag_meta ||= build_flag_metadata(
435
- error_result, eval_time_ms || (Core::Utils::Time.now.to_f * 1000).to_i
463
+ error_result, eval_time_ms || (Core::Utils::Time.now.to_f * 1000).to_i,
436
464
  )
437
465
 
438
466
  sdk_error_details(default_value, Ext::GENERAL, error_message, Ext::ERROR, error_flag_meta)
@@ -443,7 +471,7 @@ module Datadog
443
471
  flag_key,
444
472
  default_value: default_value,
445
473
  expected_type: expected_type,
446
- evaluation_context: evaluation_context
474
+ evaluation_context: evaluation_context,
447
475
  )
448
476
  end
449
477
 
@@ -462,7 +490,7 @@ module Datadog
462
490
  error_code: error_code,
463
491
  error_message: error_message,
464
492
  reason: reason,
465
- flag_metadata: flag_meta
493
+ flag_metadata: flag_meta,
466
494
  )
467
495
  end
468
496
 
@@ -509,6 +537,16 @@ module Datadog
509
537
  Datadog.send(:components).open_feature&.span_enrichment_hook
510
538
  end
511
539
 
540
+ # No component means no DebugLoggingHook and no raw-data warning, so only non-raw fields are logged.
541
+ def log_component_not_configured(flag_key, expected_type)
542
+ logger = Datadog.logger
543
+ logger.debug do
544
+ "Feature Flags: provider returned the default value for #{flag_key.inspect} (type=#{expected_type}): " \
545
+ "the Feature Flags component is not active; see the provider initialization logs " \
546
+ "(error_code=#{Ext::PROVIDER_FATAL})"
547
+ end
548
+ end
549
+
512
550
  def evaluation_telemetry_opted_out?(evaluation_context)
513
551
  @enable_evaluation_telemetry_opt_out_parameter &&
514
552
  Hooks::EvaluationTelemetryOptOutHook.opted_out?(evaluation_context)
@@ -523,7 +561,7 @@ module Datadog
523
561
  flag_metadata: {
524
562
  "dd.eval.timestamp_ms" => eval_time_ms,
525
563
  Ext::METADATA_OBSERVE_FULL_EVALUATION_DATA => false,
526
- }
564
+ },
527
565
  )
528
566
  end
529
567
  end
@@ -19,7 +19,7 @@ module Datadog
19
19
  FFE_PRODUCTS
20
20
  end
21
21
 
22
- def receivers(telemetry, component_provider:)
22
+ def receivers(telemetry, component_provider:, logger: Datadog.logger)
23
23
  matcher = Core::Remote::Dispatcher::Matcher::Product.new(FFE_PRODUCTS)
24
24
  receiver = Core::Remote::Dispatcher::Receiver.new(matcher) do |repository, changes|
25
25
  component = component_provider.call
@@ -27,8 +27,15 @@ module Datadog
27
27
 
28
28
  changes.each do |change|
29
29
  content = repository[change.path]
30
+ logger.debug do
31
+ version = content ? " (version #{content.version})" : ""
32
+ "Feature Flags: received Remote Configuration #{change.type} for #{change.path}#{version}"
33
+ end
30
34
 
31
35
  unless content || change.type == :delete
36
+ logger.debug do
37
+ "Feature Flags: ignored Remote Configuration #{change.type} for #{change.path}: content is missing"
38
+ end
32
39
  next telemetry.error("OpenFeature: Remote Configuration change is not present on #{change.type}")
33
40
  end
34
41
 
@@ -19,7 +19,7 @@ module Datadog
19
19
  :extra_logging,
20
20
  :log?,
21
21
  :error?,
22
- keyword_init: true
22
+ keyword_init: true,
23
23
  )
24
24
  def self.build_error(value:, error_code:, error_message:, reason: Ext::ERROR)
25
25
  new(
@@ -29,7 +29,7 @@ module Datadog
29
29
  reason: reason,
30
30
  error?: true,
31
31
  log?: false,
32
- serial_id: nil
32
+ serial_id: nil,
33
33
  ).freeze
34
34
  end
35
35
  end