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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -1
- data/LICENSE-3rdparty.csv +1 -0
- data/ext/datadog_profiling_native_extension/collectors_stack.c +141 -101
- data/ext/datadog_profiling_native_extension/collectors_stack.h +9 -1
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +6 -1
- data/ext/datadog_profiling_native_extension/extconf.rb +7 -13
- data/ext/datadog_profiling_native_extension/native_extension_helpers.rb +3 -3
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +66 -13
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +5 -1
- data/ext/datadog_profiling_native_extension/profiling.c +1 -1
- data/ext/libdatadog_api/extconf.rb +9 -7
- data/ext/libdatadog_api/trace_exporter.c +34 -7
- data/ext/libdatadog_extconf_helpers.rb +1 -1
- data/lib/datadog/ai_guard/component.rb +1 -1
- data/lib/datadog/ai_guard/contrib/rack/request_middleware.rb +1 -9
- data/lib/datadog/ai_guard/contrib/rails/patcher.rb +1 -1
- data/lib/datadog/ai_guard/contrib/ruby_llm/message_adapter.rb +1 -1
- data/lib/datadog/ai_guard/contrib/ruby_llm/redaction_change_set.rb +3 -3
- data/lib/datadog/ai_guard/evaluation/client.rb +3 -3
- data/lib/datadog/ai_guard/evaluation.rb +2 -2
- data/lib/datadog/ai_guard/http_client.rb +3 -2
- data/lib/datadog/ai_guard/redaction.rb +1 -1
- data/lib/datadog/appsec/api_security/endpoint_collection/rails_collector.rb +1 -1
- data/lib/datadog/appsec/assets/waf_rules/README.md +3 -3
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +5366 -1517
- data/lib/datadog/appsec/assets/waf_rules/strict.json +2 -2
- data/lib/datadog/appsec/autoload.rb +1 -1
- data/lib/datadog/appsec/component.rb +1 -1
- data/lib/datadog/appsec/compressed_json.rb +1 -1
- data/lib/datadog/appsec/configuration.rb +3 -3
- data/lib/datadog/appsec/context.rb +1 -1
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +11 -1
- data/lib/datadog/appsec/contrib/active_record/patcher.rb +12 -4
- data/lib/datadog/appsec/contrib/aws_lambda/gateway/watcher.rb +2 -2
- data/lib/datadog/appsec/contrib/aws_lambda/waf_addresses.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/configuration.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/patches/signin_tracking_patch.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/patches/signup_tracking_patch.rb +1 -1
- data/lib/datadog/appsec/contrib/devise/tracking_middleware.rb +1 -1
- data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +1 -1
- data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +1 -1
- data/lib/datadog/appsec/contrib/graphql/gateway/multiplex.rb +7 -7
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +3 -3
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +5 -5
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +2 -2
- data/lib/datadog/appsec/contrib/rails/patcher.rb +2 -2
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +3 -3
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +1 -1
- data/lib/datadog/appsec/metrics/collector.rb +5 -5
- data/lib/datadog/appsec/metrics/telemetry_exporter.rb +3 -3
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +2 -2
- data/lib/datadog/appsec/processor/rule_loader.rb +1 -1
- data/lib/datadog/appsec/response.rb +1 -1
- data/lib/datadog/appsec/security_engine/engine.rb +6 -6
- data/lib/datadog/appsec/security_engine/runner.rb +2 -2
- data/lib/datadog/appsec/trace_keeper.rb +1 -1
- data/lib/datadog/appsec.rb +1 -1
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +14 -13
- data/lib/datadog/core/configuration/agentless_settings_resolver.rb +2 -2
- data/lib/datadog/core/configuration/components.rb +1 -1
- data/lib/datadog/core/configuration/settings.rb +5 -2
- data/lib/datadog/core/configuration/supported_configurations.rb +1 -0
- data/lib/datadog/core/configuration.rb +2 -2
- data/lib/datadog/core/crashtracking/component.rb +1 -1
- data/lib/datadog/core/diagnostics/environment_logger.rb +1 -1
- data/lib/datadog/core/environment/cgroup.rb +2 -2
- data/lib/datadog/core/environment/container.rb +3 -3
- data/lib/datadog/core/metrics/client.rb +6 -6
- data/lib/datadog/core/process_discovery.rb +1 -1
- data/lib/datadog/core/remote/tie/tracing.rb +4 -3
- data/lib/datadog/core/remote/transport/http.rb +2 -2
- data/lib/datadog/core/runtime/metrics.rb +14 -14
- data/lib/datadog/core/semaphore.rb +3 -1
- data/lib/datadog/core/telemetry/event/app_started.rb +9 -9
- data/lib/datadog/core/telemetry/logger.rb +1 -1
- data/lib/datadog/core/telemetry/logging.rb +1 -1
- data/lib/datadog/core/telemetry/request.rb +9 -3
- data/lib/datadog/core/telemetry/transport/http.rb +2 -2
- data/lib/datadog/core/telemetry/worker.rb +1 -1
- data/lib/datadog/core/transport/http/adapters/net.rb +1 -1
- data/lib/datadog/core/transport/http/adapters/unix_socket.rb +1 -1
- data/lib/datadog/core/transport/http/builder.rb +1 -1
- data/lib/datadog/core/transport/http.rb +3 -3
- data/lib/datadog/core/utils/at_fork_monkey_patch.rb +2 -2
- data/lib/datadog/core/workers/async.rb +1 -1
- data/lib/datadog/core/workers/runtime_metrics.rb +1 -1
- data/lib/datadog/data_streams/pathway_context.rb +1 -1
- data/lib/datadog/data_streams/processor.rb +48 -27
- data/lib/datadog/data_streams/transport/http.rb +1 -1
- data/lib/datadog/data_streams.rb +16 -0
- data/lib/datadog/di/capture_expression_evaluator.rb +48 -11
- data/lib/datadog/di/component.rb +3 -2
- data/lib/datadog/di/configuration.rb +19 -0
- data/lib/datadog/di/contrib/active_record.rb +1 -1
- data/lib/datadog/di/el/compiler.rb +4 -4
- data/lib/datadog/di/el/evaluator.rb +247 -43
- data/lib/datadog/di/el/expression.rb +36 -6
- data/lib/datadog/di/error.rb +16 -0
- data/lib/datadog/di/guardrails_telemetry/reason.rb +3 -2
- data/lib/datadog/di/instrumenter.rb +39 -10
- data/lib/datadog/di/probe_notification_builder.rb +58 -10
- data/lib/datadog/di/probe_notifier_worker.rb +1 -1
- data/lib/datadog/di/serializer.rb +20 -2
- data/lib/datadog/di.rb +27 -0
- data/lib/datadog/error_tracking/component.rb +1 -1
- data/lib/datadog/error_tracking/configuration.rb +1 -1
- data/lib/datadog/kit/appsec/events/v2.rb +6 -6
- data/lib/datadog/kit/appsec/events.rb +1 -1
- data/lib/datadog/kit/enable_core_dumps.rb +1 -1
- data/lib/datadog/kit/identity.rb +1 -1
- data/lib/datadog/open_feature/activation.rb +26 -1
- data/lib/datadog/open_feature/agentless/configuration_source.rb +94 -15
- data/lib/datadog/open_feature/component.rb +22 -2
- data/lib/datadog/open_feature/configuration/agentless_endpoint.rb +6 -0
- data/lib/datadog/open_feature/configuration.rb +4 -4
- data/lib/datadog/open_feature/evaluation_engine.rb +62 -4
- data/lib/datadog/open_feature/exposures/buffer.rb +4 -0
- data/lib/datadog/open_feature/exposures/reporter.rb +17 -4
- data/lib/datadog/open_feature/exposures/worker.rb +37 -6
- data/lib/datadog/open_feature/flag_evaluation/aggregator.rb +5 -5
- data/lib/datadog/open_feature/flag_evaluation/writer.rb +1 -1
- data/lib/datadog/open_feature/hooks/debug_logging_hook.rb +56 -0
- data/lib/datadog/open_feature/hooks/span_enrichment_hook.rb +2 -2
- data/lib/datadog/open_feature/metrics/flag_eval_metrics.rb +1 -1
- data/lib/datadog/open_feature/native_evaluator.rb +1 -1
- data/lib/datadog/open_feature/noop_evaluator.rb +1 -1
- data/lib/datadog/open_feature/provider.rb +50 -12
- data/lib/datadog/open_feature/remote.rb +8 -1
- data/lib/datadog/open_feature/resolution_details.rb +2 -2
- data/lib/datadog/open_feature/transport.rb +6 -6
- data/lib/datadog/opentelemetry/api/context.rb +3 -3
- data/lib/datadog/opentelemetry/logs.rb +5 -5
- data/lib/datadog/opentelemetry/metrics.rb +3 -3
- data/lib/datadog/opentelemetry/sdk/propagator.rb +3 -3
- data/lib/datadog/opentelemetry/sdk/span_processor.rb +2 -2
- data/lib/datadog/opentelemetry/sdk/trace/span.rb +1 -1
- data/lib/datadog/profiling/collectors/code_provenance.rb +3 -3
- data/lib/datadog/profiling/collectors/cpu_and_wall_time_worker.rb +4 -4
- data/lib/datadog/profiling/collectors/idle_sampling_helper.rb +1 -1
- data/lib/datadog/profiling/collectors/thread_context.rb +1 -1
- data/lib/datadog/profiling/component.rb +19 -19
- data/lib/datadog/profiling/exporter.rb +1 -1
- data/lib/datadog/profiling/http_transport.rb +3 -3
- data/lib/datadog/profiling/profiler.rb +2 -2
- data/lib/datadog/profiling/scheduler.rb +2 -2
- data/lib/datadog/profiling/tag_builder.rb +1 -1
- data/lib/datadog/symbol_database/extractor.rb +8 -8
- data/lib/datadog/symbol_database/uploader.rb +1 -1
- data/lib/datadog/tracing/buffer.rb +3 -3
- data/lib/datadog/tracing/client_ip.rb +1 -1
- data/lib/datadog/tracing/component.rb +8 -8
- data/lib/datadog/tracing/configuration/dynamic/option.rb +2 -2
- data/lib/datadog/tracing/configuration/settings.rb +3 -3
- data/lib/datadog/tracing/context.rb +1 -1
- data/lib/datadog/tracing/contrib/action_cable/instrumentation.rb +2 -2
- data/lib/datadog/tracing/contrib/active_job/data_streams.rb +27 -2
- data/lib/datadog/tracing/contrib/active_record/configuration/resolver.rb +2 -2
- data/lib/datadog/tracing/contrib/active_record/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/active_record/utils.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/active_support/notifications/subscriber.rb +2 -2
- data/lib/datadog/tracing/contrib/active_support/notifications/subscription.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/aws/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/dalli/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/dalli/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/delayed_job/plugin.rb +2 -2
- data/lib/datadog/tracing/contrib/elasticsearch/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/elasticsearch/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/ethon/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/ethon/easy_patch.rb +8 -8
- data/lib/datadog/tracing/contrib/ethon/multi_patch.rb +1 -1
- data/lib/datadog/tracing/contrib/excon/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/excon/middleware.rb +7 -7
- data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +5 -5
- data/lib/datadog/tracing/contrib/grape/endpoint.rb +4 -4
- data/lib/datadog/tracing/contrib/graphql/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +3 -3
- data/lib/datadog/tracing/contrib/grpc/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/client.rb +2 -2
- data/lib/datadog/tracing/contrib/grpc/datadog_interceptor/server.rb +1 -1
- data/lib/datadog/tracing/contrib/grpc.rb +1 -1
- data/lib/datadog/tracing/contrib/hanami/action_tracer.rb +1 -1
- data/lib/datadog/tracing/contrib/hanami/plugin.rb +1 -1
- data/lib/datadog/tracing/contrib/hanami/renderer_policy_tracing.rb +1 -1
- data/lib/datadog/tracing/contrib/hanami/router_tracing.rb +1 -1
- data/lib/datadog/tracing/contrib/http/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +6 -6
- data/lib/datadog/tracing/contrib/http.rb +1 -1
- data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +7 -7
- data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +5 -5
- data/lib/datadog/tracing/contrib/kafka/instrumentation/consumer.rb +2 -2
- data/lib/datadog/tracing/contrib/kafka/instrumentation/producer.rb +2 -2
- data/lib/datadog/tracing/contrib/karafka/monitor.rb +1 -1
- data/lib/datadog/tracing/contrib/karafka/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/karafka.rb +1 -1
- data/lib/datadog/tracing/contrib/lograge/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/mongodb/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/mongodb/parsers.rb +1 -1
- data/lib/datadog/tracing/contrib/mongodb/subscribers.rb +1 -1
- data/lib/datadog/tracing/contrib/mysql2/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/mysql2/instrumentation.rb +3 -3
- data/lib/datadog/tracing/contrib/opensearch/configuration/settings.rb +2 -2
- data/lib/datadog/tracing/contrib/opensearch/patcher.rb +3 -3
- data/lib/datadog/tracing/contrib/pg/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +4 -4
- data/lib/datadog/tracing/contrib/presto/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/presto/instrumentation.rb +4 -4
- data/lib/datadog/tracing/contrib/propagation/sql_comment.rb +1 -1
- data/lib/datadog/tracing/contrib/que/tracer.rb +1 -1
- data/lib/datadog/tracing/contrib/racecar/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/racecar/events/batch.rb +1 -1
- data/lib/datadog/tracing/contrib/racecar/events/message.rb +1 -1
- data/lib/datadog/tracing/contrib/rack/middlewares.rb +3 -3
- data/lib/datadog/tracing/contrib/rack/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/framework.rb +7 -7
- data/lib/datadog/tracing/contrib/rails/log_injection.rb +1 -1
- data/lib/datadog/tracing/contrib/rails/runner.rb +4 -4
- data/lib/datadog/tracing/contrib/redis/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/redis/quantize.rb +1 -1
- data/lib/datadog/tracing/contrib/redis/tags.rb +1 -1
- data/lib/datadog/tracing/contrib/rest_client/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/rest_client/request_patch.rb +8 -8
- data/lib/datadog/tracing/contrib/sequel/database.rb +1 -1
- data/lib/datadog/tracing/contrib/sequel/dataset.rb +1 -1
- data/lib/datadog/tracing/contrib/shoryuken/tracer.rb +1 -1
- data/lib/datadog/tracing/contrib/sidekiq/client_tracer.rb +2 -2
- data/lib/datadog/tracing/contrib/sidekiq/server_tracer.rb +2 -2
- data/lib/datadog/tracing/contrib/sidekiq.rb +1 -1
- data/lib/datadog/tracing/contrib/sinatra/tracer_middleware.rb +1 -1
- data/lib/datadog/tracing/contrib/status_range_env_parser.rb +1 -1
- data/lib/datadog/tracing/contrib/sucker_punch/instrumentation.rb +1 -1
- data/lib/datadog/tracing/contrib/trilogy/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/trilogy/instrumentation.rb +3 -3
- data/lib/datadog/tracing/contrib/waterdrop/middleware.rb +2 -2
- data/lib/datadog/tracing/contrib/waterdrop.rb +1 -1
- data/lib/datadog/tracing/diagnostics/environment_logger.rb +1 -1
- data/lib/datadog/tracing/distributed/b3_multi.rb +1 -1
- data/lib/datadog/tracing/distributed/b3_single.rb +1 -1
- data/lib/datadog/tracing/distributed/baggage.rb +3 -3
- data/lib/datadog/tracing/distributed/datadog.rb +3 -3
- data/lib/datadog/tracing/distributed/propagation.rb +7 -7
- data/lib/datadog/tracing/distributed/trace_context.rb +1 -1
- data/lib/datadog/tracing/distributed/trace_state/open_telemetry.rb +1 -1
- data/lib/datadog/tracing/otel_thread_context.rb +3 -3
- data/lib/datadog/tracing/pipeline.rb +1 -1
- data/lib/datadog/tracing/sampling/priority_sampler.rb +1 -1
- data/lib/datadog/tracing/sampling/rule.rb +1 -1
- data/lib/datadog/tracing/sampling/rule_sampler.rb +1 -1
- data/lib/datadog/tracing/sampling/span/rule_parser.rb +2 -2
- data/lib/datadog/tracing/span_operation.rb +1 -1
- data/lib/datadog/tracing/trace_digest.rb +1 -1
- data/lib/datadog/tracing/trace_operation.rb +6 -6
- data/lib/datadog/tracing/tracer.rb +6 -6
- data/lib/datadog/tracing/transport/http/telemetry.rb +1 -1
- data/lib/datadog/tracing/transport/http.rb +2 -2
- data/lib/datadog/tracing/transport/io.rb +1 -1
- data/lib/datadog/tracing/transport/native.rb +3 -3
- data/lib/datadog/tracing/transport/statistics.rb +2 -2
- data/lib/datadog/tracing/transport/telemetry.rb +3 -1
- data/lib/datadog/tracing/transport/trace_formatter.rb +12 -12
- data/lib/datadog/tracing/transport/traces.rb +1 -1
- data/lib/datadog/tracing/utils.rb +1 -1
- data/lib/datadog/tracing/workers.rb +1 -1
- data/lib/datadog/version.rb +1 -1
- 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("
|
|
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)
|
|
@@ -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
|
|
23
|
-
return
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
103
|
-
@logger.debug { "
|
|
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
|
|
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
|
|
@@ -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
|
|
|
@@ -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
|
-
|
|
183
|
+
telemetry_hooks = [
|
|
181
184
|
component&.flag_eval_metrics_hook,
|
|
182
185
|
component&.flag_eval_evp_hook,
|
|
183
186
|
].compact
|
|
184
|
-
|
|
187
|
+
if @enable_evaluation_telemetry_opt_out_parameter
|
|
188
|
+
telemetry_hooks = telemetry_hooks.map { |hook| Hooks::EvaluationTelemetryOptOutHook.new(hook) }
|
|
189
|
+
end
|
|
185
190
|
|
|
186
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|