-
Notifications
You must be signed in to change notification settings - Fork 182
Expand file tree
/
Copy pathNativeEvaluator.php
More file actions
141 lines (114 loc) · 4.62 KB
/
Copy pathNativeEvaluator.php
File metadata and controls
141 lines (114 loc) · 4.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<?php
namespace DDTrace\FeatureFlags\Internal;
use DDTrace\FeatureFlags\EvaluationType;
use DDTrace\FeatureFlags\SpanEnrichmentRegistry;
final class NativeEvaluator implements Evaluator
{
const WARNING_MESSAGE = 'Datadog-backed PHP feature flag evaluation has no Remote Configuration data loaded for this request. Returning default values.';
private $mapper;
private $recordMetrics;
private function __construct($mapper = null, bool $recordMetrics = true)
{
if ($mapper !== null && !$mapper instanceof ResultMapper) {
throw new \InvalidArgumentException('Expected a ResultMapper instance');
}
$this->mapper = $mapper ?: new ResultMapper();
$this->recordMetrics = $recordMetrics;
}
public static function isAvailable()
{
return function_exists('DDTrace\\ffe_evaluate');
}
public static function create($recordMetrics = true)
{
return self::isAvailable() ? new self(null, $recordMetrics) : new UnavailableEvaluator();
}
public function evaluate(
$flagKey,
$expectedType,
$defaultValue,
$targetingKey = null,
array $attributes = array()
) {
$rawResult = \DDTrace\ffe_evaluate(
$flagKey,
$this->typeId($expectedType),
$targetingKey,
$this->normalizeAttributes($attributes),
$this->recordMetrics
);
if (is_array($rawResult) || is_object($rawResult)) {
$rawResult = $this->withProviderState($rawResult);
}
$details = $this->mapper->map($rawResult, $expectedType, $defaultValue);
// APM feature-flag span enrichment. This is the single choke point both
// the native Client and the OpenFeature DataDogProvider evaluate through,
// and it is only reachable with the extension loaded (UnavailableEvaluator
// is returned otherwise), so enrichment is recorded here once rather than
// duplicated in each caller. No-op when the gate is off or there is no
// active root span; never throws into evaluation.
SpanEnrichmentRegistry::record($flagKey, $details, $targetingKey);
return $details;
}
private function typeId($expectedType)
{
switch ($expectedType) {
case EvaluationType::STRING:
return \DDTrace\FFE_STRING;
case EvaluationType::INTEGER:
return \DDTrace\FFE_INT;
case EvaluationType::FLOAT:
return \DDTrace\FFE_FLOAT;
case EvaluationType::BOOLEAN:
return \DDTrace\FFE_BOOL;
case EvaluationType::OBJECT:
return \DDTrace\FFE_OBJECT;
}
throw new \InvalidArgumentException('Unknown feature flag value type: ' . (string) $expectedType);
}
private function normalizeAttributes(array $attributes)
{
$normalized = array();
foreach ($attributes as $key => $value) {
if (is_bool($value) || is_int($value) || is_float($value) || is_string($value)) {
$normalized[(string) $key] = $value;
}
}
return $normalized;
}
private function withProviderState($rawResult)
{
$hasConfig = \DDTrace\ffe_has_config();
$configVersion = \DDTrace\ffe_config_version();
$providerState = array(
'ready' => $hasConfig,
'hasConfig' => $hasConfig,
'configVersion' => $configVersion,
'productionRuntime' => true,
'mode' => 'native_remote_config',
'reason' => $hasConfig ? 'ready' : 'configuration_missing',
);
if (is_array($rawResult)) {
if (isset($rawResult['provider_state']) && is_array($rawResult['provider_state'])) {
$providerState = array_merge($providerState, $rawResult['provider_state']);
}
if (!$hasConfig) {
$rawResult['error_message'] = self::WARNING_MESSAGE;
}
$rawResult['provider_state'] = $providerState;
$rawResult['has_config'] = $hasConfig;
$rawResult['config_version'] = $configVersion;
return $rawResult;
}
if (isset($rawResult->providerState) && is_array($rawResult->providerState)) {
$providerState = array_merge($providerState, $rawResult->providerState);
}
if (!$hasConfig) {
$rawResult->errorMessage = self::WARNING_MESSAGE;
}
$rawResult->providerState = $providerState;
$rawResult->hasConfig = $hasConfig;
$rawResult->configVersion = $configVersion;
return $rawResult;
}
}