Skip to content

Commit 3e35d3a

Browse files
committed
Search the configuration sources in reverse, to ensure we record config for all of them
1 parent fd924ab commit 3e35d3a

File tree

2 files changed

+268
-55
lines changed

2 files changed

+268
-55
lines changed

tracer/src/Datadog.Trace/Configuration/ConfigurationSources/CompositeConfigurationSource.cs

Lines changed: 234 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -53,50 +53,260 @@ public void Add(IConfigurationSource source)
5353

5454
/// <inheritdoc />
5555
public ConfigurationResult<string> GetString(string key, IConfigurationTelemetry telemetry, Func<string, bool>? validator, bool recordValue)
56-
=> _sources
57-
.Select(source => source.GetString(key, telemetry, validator, recordValue))
58-
.FirstOrDefault(value => value.IsValid, ConfigurationResult<string>.NotFound());
56+
{
57+
// We iterate in reverse order, and keep the last successful value
58+
// because we need to record the data for all the sources in telemetry
59+
// We also have to keep track of whether the last value was the last _found_ value
60+
// as we need to "restore" the telemetry if so.
61+
var result = ConfigurationResult<string>.NotFound();
62+
var isLastFound = false;
63+
var origin = ConfigurationOrigins.Unknown;
64+
for (var i = _sources.Count - 1; i >= 0; i--)
65+
{
66+
var source = _sources[i];
67+
var value = source.GetString(key, telemetry, validator, recordValue);
68+
if (value.IsValid)
69+
{
70+
result = value;
71+
isLastFound = true;
72+
origin = source.Origin;
73+
}
74+
else if (value.IsPresent)
75+
{
76+
isLastFound = false;
77+
}
78+
}
79+
80+
if (result.IsValid && !isLastFound)
81+
{
82+
telemetry.Record(key, result.Result, recordValue, origin);
83+
}
84+
85+
return result;
86+
}
5987

6088
/// <inheritdoc />
6189
public ConfigurationResult<int> GetInt32(string key, IConfigurationTelemetry telemetry, Func<int, bool>? validator)
62-
=> _sources
63-
.Select(source => source.GetInt32(key, telemetry, validator))
64-
.FirstOrDefault(value => value.IsValid, ConfigurationResult<int>.NotFound());
90+
{
91+
// We iterate in reverse order, and keep the last successful value
92+
// because we need to record the data for all the sources in telemetry
93+
var result = ConfigurationResult<int>.NotFound();
94+
var isLastFound = false;
95+
var origin = ConfigurationOrigins.Unknown;
96+
for (var i = _sources.Count - 1; i >= 0; i--)
97+
{
98+
var source = _sources[i];
99+
var value = source.GetInt32(key, telemetry, validator);
100+
if (value.IsValid)
101+
{
102+
result = value;
103+
isLastFound = true;
104+
origin = source.Origin;
105+
}
106+
else if (value.IsPresent)
107+
{
108+
isLastFound = false;
109+
}
110+
}
111+
112+
if (result.IsValid && !isLastFound)
113+
{
114+
telemetry.Record(key, result.Result, origin);
115+
}
116+
117+
return result;
118+
}
65119

66120
/// <inheritdoc />
67121
public ConfigurationResult<double> GetDouble(string key, IConfigurationTelemetry telemetry, Func<double, bool>? validator)
68-
=> _sources
69-
.Select(source => source.GetDouble(key, telemetry, validator))
70-
.FirstOrDefault(value => value.IsValid, ConfigurationResult<double>.NotFound());
122+
{
123+
// We iterate in reverse order, and keep the last successful value
124+
// because we need to record the data for all the sources in telemetry
125+
var result = ConfigurationResult<double>.NotFound();
126+
var isLastFound = false;
127+
var origin = ConfigurationOrigins.Unknown;
128+
for (var i = _sources.Count - 1; i >= 0; i--)
129+
{
130+
var source = _sources[i];
131+
var value = source.GetDouble(key, telemetry, validator);
132+
if (value.IsValid)
133+
{
134+
result = value;
135+
isLastFound = true;
136+
origin = source.Origin;
137+
}
138+
else if (value.IsPresent)
139+
{
140+
isLastFound = false;
141+
}
142+
}
143+
144+
if (result.IsValid && !isLastFound)
145+
{
146+
telemetry.Record(key, result.Result, origin);
147+
}
148+
149+
return result;
150+
}
71151

72152
/// <inheritdoc />
73153
public ConfigurationResult<bool> GetBool(string key, IConfigurationTelemetry telemetry, Func<bool, bool>? validator)
74-
=> _sources
75-
.Select(source => source.GetBool(key, telemetry, validator))
76-
.FirstOrDefault(value => value.IsValid, ConfigurationResult<bool>.NotFound());
154+
{
155+
// We iterate in reverse order, and keep the last successful value
156+
// because we need to record the data for all the sources in telemetry
157+
var result = ConfigurationResult<bool>.NotFound();
158+
var isLastFound = false;
159+
var origin = ConfigurationOrigins.Unknown;
160+
for (var i = _sources.Count - 1; i >= 0; i--)
161+
{
162+
var source = _sources[i];
163+
var value = source.GetBool(key, telemetry, validator);
164+
if (value.IsValid)
165+
{
166+
result = value;
167+
isLastFound = true;
168+
origin = source.Origin;
169+
}
170+
else if (value.IsPresent)
171+
{
172+
isLastFound = false;
173+
}
174+
}
175+
176+
if (result.IsValid && !isLastFound)
177+
{
178+
telemetry.Record(key, result.Result, origin);
179+
}
180+
181+
return result;
182+
}
77183

78184
/// <inheritdoc />
79185
public ConfigurationResult<IDictionary<string, string>> GetDictionary(string key, IConfigurationTelemetry telemetry, Func<IDictionary<string, string>, bool>? validator)
80-
=> _sources
81-
.Select(source => source.GetDictionary(key, telemetry, validator))
82-
.FirstOrDefault(value => value.IsValid, ConfigurationResult<IDictionary<string, string>>.NotFound());
186+
{
187+
// We iterate in reverse order, and keep the last successful value
188+
// because we need to record the data for all the sources in telemetry
189+
var result = ConfigurationResult<IDictionary<string, string>>.NotFound();
190+
var isLastFound = false;
191+
var origin = ConfigurationOrigins.Unknown;
192+
for (var i = _sources.Count - 1; i >= 0; i--)
193+
{
194+
var source = _sources[i];
195+
var value = source.GetDictionary(key, telemetry, validator);
196+
if (value.IsValid)
197+
{
198+
result = value;
199+
isLastFound = true;
200+
origin = source.Origin;
201+
}
202+
else if (value.IsPresent)
203+
{
204+
isLastFound = false;
205+
}
206+
}
207+
208+
if (result.IsValid && !isLastFound)
209+
{
210+
telemetry.Record(key, result.TelemetryOverride ?? result.Result?.ToString(), recordValue: true, origin);
211+
}
212+
213+
return result;
214+
}
83215

84216
/// <inheritdoc />
85217
public ConfigurationResult<IDictionary<string, string>> GetDictionary(string key, IConfigurationTelemetry telemetry, Func<IDictionary<string, string>, bool>? validator, bool allowOptionalMappings, char separator)
86-
=> _sources
87-
.Select(source => source.GetDictionary(key, telemetry, validator, allowOptionalMappings, separator))
88-
.FirstOrDefault(value => value.IsValid, ConfigurationResult<IDictionary<string, string>>.NotFound());
218+
{
219+
// We iterate in reverse order, and keep the last successful value
220+
// because we need to record the data for all the sources in telemetry
221+
var result = ConfigurationResult<IDictionary<string, string>>.NotFound();
222+
var isLastFound = false;
223+
var origin = ConfigurationOrigins.Unknown;
224+
for (var i = _sources.Count - 1; i >= 0; i--)
225+
{
226+
var source = _sources[i];
227+
var value = source.GetDictionary(key, telemetry, validator, allowOptionalMappings, separator);
228+
if (value.IsValid)
229+
{
230+
result = value;
231+
isLastFound = true;
232+
origin = source.Origin;
233+
}
234+
else if (value.IsPresent)
235+
{
236+
isLastFound = false;
237+
}
238+
}
239+
240+
if (result.IsValid && !isLastFound)
241+
{
242+
telemetry.Record(key, result.TelemetryOverride ?? result.Result?.ToString(), recordValue: true, origin);
243+
}
244+
245+
return result;
246+
}
89247

90248
/// <inheritdoc />
91249
public ConfigurationResult<IDictionary<string, string>> GetDictionary(string key, IConfigurationTelemetry telemetry, Func<IDictionary<string, string>, bool>? validator, Func<string, IDictionary<string, string>> parser)
92-
=> _sources
93-
.Select(source => source.GetDictionary(key, telemetry, validator, parser))
94-
.FirstOrDefault(value => value.IsValid, ConfigurationResult<IDictionary<string, string>>.NotFound());
250+
{
251+
// We iterate in reverse order, and keep the last successful value
252+
// because we need to record the data for all the sources in telemetry
253+
var result = ConfigurationResult<IDictionary<string, string>>.NotFound();
254+
var isLastFound = false;
255+
var origin = ConfigurationOrigins.Unknown;
256+
for (var i = _sources.Count - 1; i >= 0; i--)
257+
{
258+
var source = _sources[i];
259+
var value = source.GetDictionary(key, telemetry, validator, parser);
260+
if (value.IsValid)
261+
{
262+
result = value;
263+
isLastFound = true;
264+
origin = source.Origin;
265+
}
266+
else if (value.IsPresent)
267+
{
268+
isLastFound = false;
269+
}
270+
}
271+
272+
if (result.IsValid && !isLastFound)
273+
{
274+
telemetry.Record(key, result.TelemetryOverride ?? result.Result?.ToString(), recordValue: true, origin);
275+
}
276+
277+
return result;
278+
}
95279

96280
/// <inheritdoc />
97281
public ConfigurationResult<T> GetAs<T>(string key, IConfigurationTelemetry telemetry, Func<string, ParsingResult<T>> converter, Func<T, bool>? validator, bool recordValue)
98-
=> _sources
99-
.Select(source => source.GetAs<T>(key, telemetry, converter, validator, recordValue))
100-
.FirstOrDefault(value => value.IsValid, ConfigurationResult<T>.NotFound());
282+
{
283+
// We iterate in reverse order, and keep the last successful value
284+
// because we need to record the data for all the sources in telemetry
285+
var result = ConfigurationResult<T>.NotFound();
286+
var isLastFound = false;
287+
var origin = ConfigurationOrigins.Unknown;
288+
for (var i = _sources.Count - 1; i >= 0; i--)
289+
{
290+
var source = _sources[i];
291+
var value = source.GetAs(key, telemetry, converter, validator, recordValue);
292+
if (value.IsValid)
293+
{
294+
result = value;
295+
isLastFound = true;
296+
origin = source.Origin;
297+
}
298+
else if (value.IsPresent)
299+
{
300+
isLastFound = false;
301+
}
302+
}
303+
304+
if (result.IsValid && !isLastFound)
305+
{
306+
telemetry.Record(key, result.TelemetryOverride ?? result.Result?.ToString(), recordValue: true, origin);
307+
}
308+
309+
return result;
310+
}
101311
}
102312
}

0 commit comments

Comments
 (0)