@@ -53,50 +53,260 @@ public void Add(IConfigurationSource source)
53
53
54
54
/// <inheritdoc />
55
55
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
+ }
59
87
60
88
/// <inheritdoc />
61
89
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
+ }
65
119
66
120
/// <inheritdoc />
67
121
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
+ }
71
151
72
152
/// <inheritdoc />
73
153
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
+ }
77
183
78
184
/// <inheritdoc />
79
185
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
+ }
83
215
84
216
/// <inheritdoc />
85
217
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
+ }
89
247
90
248
/// <inheritdoc />
91
249
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
+ }
95
279
96
280
/// <inheritdoc />
97
281
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
+ }
101
311
}
102
312
}
0 commit comments