Class: Datadog::OpenFeature::Hooks::FlagEvalEVPHook
- Inherits:
-
Object
- Object
- Datadog::OpenFeature::Hooks::FlagEvalEVPHook
- Includes:
- OpenFeature::SDK::Hooks::Hook
- Defined in:
- lib/datadog/open_feature/hooks/flag_eval_evp_hook.rb
Overview
EVP flagevaluation hook — structural copy of FlagEvalMetricsHook for the new EVP path.
This hook does ONLY cheap capture + non-blocking enqueue on the caller's eval thread. All aggregation (canonical key, tier routing, cap enforcement) is performed in the background by the FlagEvaluation::Writer.
OTel non-regression: hooks/flag_eval_metrics_hook.rb and metrics/flag_eval_metrics.rb stay on the OTel path. This hook is registered as a provider hook so it receives the SDK-final EvaluationDetails after hook failures and type validation.
Class Method Summary collapse
-
.available? ⇒ Boolean
Returns true if the OpenFeature SDK supports hooks (>= 0.5.0).
Instance Method Summary collapse
-
#finally(hook_context:, evaluation_details:, **_opts) ⇒ Object
finally covers success, error, AND default paths (not just After).
-
#initialize(writer) ⇒ FlagEvalEVPHook
constructor
A new instance of FlagEvalEVPHook.
Constructor Details
#initialize(writer) ⇒ FlagEvalEVPHook
Returns a new instance of FlagEvalEVPHook.
27 28 29 |
# File 'lib/datadog/open_feature/hooks/flag_eval_evp_hook.rb', line 27 def initialize(writer) @writer = writer end |
Class Method Details
.available? ⇒ Boolean
Returns true if the OpenFeature SDK supports hooks (>= 0.5.0)
23 24 25 |
# File 'lib/datadog/open_feature/hooks/flag_eval_evp_hook.rb', line 23 def self.available? !!defined?(::OpenFeature::SDK::Hooks::Hook) end |
Instance Method Details
#finally(hook_context:, evaluation_details:, **_opts) ⇒ Object
finally covers success, error, AND default paths (not just After). Cheap extraction only — no aggregation on the caller thread.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/datadog/open_feature/hooks/flag_eval_evp_hook.rb', line 33 def finally(hook_context:, evaluation_details:, **_opts) writer = @writer return unless writer # Eval-time stamped by the provider at eval-entry time; fall back to hook-fire time. # Metadata key: 'dd.eval.timestamp_ms' (int, ms since epoch) — stamped at eval entry. = evaluation_details. eval_time_ms = .is_a?(Hash) ? ["dd.eval.timestamp_ms"] : nil eval_time_ms ||= (Core::Utils::Time.now.to_f * 1000).to_i # observe_full_evaluation_data travels on the event metadata (stamped from # the UFC the evaluation ran against), never read from live config. observe_full_evaluation_data = .is_a?(Hash) ? [Ext::METADATA_OBSERVE_FULL_EVALUATION_DATA] : nil observe_full_evaluation_data = false unless observe_full_evaluation_data == true attrs = if observe_full_evaluation_data extract_attributes(hook_context.evaluation_context) end # Raw messages may contain high-cardinality data, so only error codes enter EVP. reason = evaluation_details.reason.to_s runtime_default = runtime_default_reason?(reason) error_code = evaluation_details.error_code error_code = Ext::GENERAL if reason == Ext::ERROR && error_code.to_s.empty? writer.enqueue( flag_key: hook_context.flag_key, variant: runtime_default ? nil : evaluation_details.variant, allocation_key: runtime_default ? nil : extract_allocation_key(evaluation_details), error_message: error_code, runtime_default: runtime_default, targeting_key: extract_targeting_key(hook_context.evaluation_context), eval_time_ms: eval_time_ms, attrs: attrs, observe_full_evaluation_data: observe_full_evaluation_data, ) end |