datadog 2.46.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 +56 -2
- data/LICENSE-3rdparty.csv +1 -0
- data/ext/datadog_profiling_native_extension/collectors_stack.c +143 -86
- 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 +67 -14
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +8 -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 +2 -2
- 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 +31 -4
- data/lib/datadog/appsec/contrib/rails/patcher.rb +2 -2
- data/lib/datadog/appsec/contrib/rails/patches/render_to_body_patch.rb +8 -7
- data/lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +17 -5
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/patches/json_patch.rb +8 -7
- 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 +8 -7
- 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 +12 -11
- data/lib/datadog/core/configuration/components_state.rb +8 -1
- data/lib/datadog/core/configuration/settings.rb +5 -2
- data/lib/datadog/core/configuration/supported_configurations.rb +3 -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/client.rb +44 -3
- data/lib/datadog/core/remote/dispatcher.rb +34 -3
- 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 +2 -2
- 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 +73 -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/remote.rb +46 -2
- data/lib/datadog/di/serializer.rb +47 -13
- 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 +10 -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/evaluation_telemetry_opt_out_hook.rb +25 -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 +69 -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/info.rb +37 -6
- data/lib/datadog/profiling/collectors/thread_context.rb +1 -1
- data/lib/datadog/profiling/component.rb +41 -39
- data/lib/datadog/profiling/exporter.rb +4 -6
- 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 +15 -10
- data/lib/datadog/tracing/configuration/dynamic/option.rb +2 -2
- data/lib/datadog/tracing/configuration/ext.rb +2 -0
- data/lib/datadog/tracing/configuration/settings.rb +14 -3
- data/lib/datadog/tracing/context.rb +1 -1
- data/lib/datadog/tracing/context_provider.rb +8 -0
- 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 +17 -12
- 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 +16 -9
- data/lib/datadog/tracing/contrib/faraday/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/faraday/middleware.rb +14 -8
- 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 +21 -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 +14 -8
- data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +1 -1
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +14 -8
- 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 +17 -10
- 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/utils/quantization/http.rb +102 -0
- 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/remote.rb +50 -19
- 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 +9 -8
- data/lib/datadog/appsec/utils/hash_coercion.rb +0 -23
|
@@ -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
|
|
data/lib/datadog/kit/identity.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
237
|
+
status = response.status
|
|
238
|
+
case status
|
|
185
239
|
when 200
|
|
240
|
+
log_recovery
|
|
186
241
|
apply_configuration(response)
|
|
187
242
|
when 304
|
|
188
|
-
|
|
243
|
+
log_recovery
|
|
189
244
|
when 401, 403
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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
|
-
|
|
107
|
-
|
|
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
|
|
@@ -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
|
|
@@ -78,6 +78,12 @@ module Datadog
|
|
|
78
78
|
o.default true
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
+
option :evaluation_telemetry_per_subject_opt_out_enabled do |o|
|
|
82
|
+
o.type :bool
|
|
83
|
+
o.env "DD_FEATURE_FLAGS_EVALUATION_TELEMETRY_PER_SUBJECT_OPT_OUT_ENABLED"
|
|
84
|
+
o.default false
|
|
85
|
+
end
|
|
86
|
+
|
|
81
87
|
option :configuration_source do |o|
|
|
82
88
|
o.type :string
|
|
83
89
|
o.env "DD_FEATURE_FLAGS_CONFIGURATION_SOURCE"
|
|
@@ -112,7 +118,7 @@ module Datadog
|
|
|
112
118
|
value
|
|
113
119
|
else
|
|
114
120
|
Datadog.logger.warn(
|
|
115
|
-
"Feature Flags agentless poll interval must be positive; using the default"
|
|
121
|
+
"Feature Flags agentless poll interval must be positive; using the default",
|
|
116
122
|
)
|
|
117
123
|
Settings::DEFAULT_POLL_INTERVAL_SECONDS
|
|
118
124
|
end
|
|
@@ -132,7 +138,7 @@ module Datadog
|
|
|
132
138
|
else
|
|
133
139
|
Datadog.logger.warn(
|
|
134
140
|
"Feature Flags agentless request timeout must be within (0, " \
|
|
135
|
-
"#{Settings::MAX_REQUEST_TIMEOUT_SECONDS}]; using the default"
|
|
141
|
+
"#{Settings::MAX_REQUEST_TIMEOUT_SECONDS}]; using the default",
|
|
136
142
|
)
|
|
137
143
|
Settings::DEFAULT_REQUEST_TIMEOUT_SECONDS
|
|
138
144
|
end
|
|
@@ -153,7 +159,7 @@ module Datadog
|
|
|
153
159
|
else
|
|
154
160
|
Datadog.logger.warn(
|
|
155
161
|
"Feature Flags provider initialization timeout must be within (0, " \
|
|
156
|
-
"#{Settings::MAX_INITIALIZATION_TIMEOUT_MS}]; using the default"
|
|
162
|
+
"#{Settings::MAX_INITIALIZATION_TIMEOUT_MS}]; using the default",
|
|
157
163
|
)
|
|
158
164
|
Settings::DEFAULT_INITIALIZATION_TIMEOUT_MS
|
|
159
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
|