Skip to content

Commit cdccbd2

Browse files
committed
Various fixes
- Improved log messages (and don't log multiple times), fix exception stack traces - Don't remote-fetch twice at startup (load + timer that immediately fired) - Moved options bind and remote-fetch from constructor to Load, fix combination with placeholder
1 parent a3dc452 commit cdccbd2

15 files changed

Lines changed: 238 additions & 226 deletions

src/Configuration/src/Abstractions/CompositeConfigurationProvider.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,9 @@ private void Load(bool isReload)
5353

5454
public IEnumerable<string> GetChildKeys(IEnumerable<string> earlierKeys, string? parentPath)
5555
{
56+
ArgumentNullException.ThrowIfNull(earlierKeys);
57+
5658
string[] earlierKeysArray = earlierKeys as string[] ?? earlierKeys.ToArray();
57-
#pragma warning disable S3236 // Caller information arguments should not be provided explicitly
58-
ArgumentNullException.ThrowIfNull(earlierKeysArray, nameof(earlierKeys));
59-
#pragma warning restore S3236 // Caller information arguments should not be provided explicitly
6059

6160
if (_logger.IsEnabled(LogLevel.Trace))
6261
{

src/Configuration/src/ConfigServer/ConfigServerClientOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public bool ValidateCertificatesAlt
133133
public int TokenTtl { get; set; } = 300_000;
134134

135135
/// <summary>
136-
/// Gets or sets the vault token renew rate (in milliseconds). Default value: 60_000 (1 minute).
136+
/// Gets or sets the Vault token renew rate (in milliseconds). Default value: 60_000 (1 minute).
137137
/// </summary>
138138
public int TokenRenewRate { get; set; } = 60_000;
139139

src/Configuration/src/ConfigServer/ConfigServerConfigurationBuilderExtensions.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,7 @@ internal static IConfigurationBuilder AddConfigServer(this IConfigurationBuilder
133133
builder.AddCloudFoundry();
134134
builder.AddKubernetesServiceBindings();
135135

136-
ConfigServerConfigurationSource source = builder is IConfiguration configuration
137-
? new ConfigServerConfigurationSource(options, configuration, configure, createHttpClientHandler, loggerFactory)
138-
: new ConfigServerConfigurationSource(options, builder.Sources, builder.Properties, configure, createHttpClientHandler, loggerFactory);
139-
136+
var source = new ConfigServerConfigurationSource(options, builder.Sources, builder.Properties, configure, createHttpClientHandler, loggerFactory);
140137
builder.Add(source);
141138
}
142139

src/Configuration/src/ConfigServer/ConfigServerConfigurationProvider.cs

Lines changed: 89 additions & 59 deletions
Large diffs are not rendered by default.

src/Configuration/src/ConfigServer/ConfigServerConfigurationSource.cs

Lines changed: 12 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ internal sealed class ConfigServerConfigurationSource : IConfigurationSource
1212
{
1313
private readonly ILoggerFactory _loggerFactory;
1414

15-
internal List<IConfigurationSource> Sources { get; } = [];
16-
internal Dictionary<string, object> Properties { get; } = [];
15+
internal List<IConfigurationSource> Sources { get; }
16+
internal Dictionary<string, object> Properties { get; }
1717

1818
/// <summary>
1919
/// Gets the initial options the client uses to contact Config Server.
@@ -36,39 +36,6 @@ internal sealed class ConfigServerConfigurationSource : IConfigurationSource
3636
/// </summary>
3737
public Func<HttpClientHandler>? CreateHttpClientHandler { get; }
3838

39-
/// <summary>
40-
/// Initializes a new instance of the <see cref="ConfigServerConfigurationSource" /> class.
41-
/// </summary>
42-
/// <param name="defaultOptions">
43-
/// The initial options the client uses to contact Config Server.
44-
/// </param>
45-
/// <param name="configuration">
46-
/// The configuration the client uses to contact Config Server. Entries overrule <paramref name="defaultOptions" />.
47-
/// </param>
48-
/// <param name="configure">
49-
/// An optional delegate that further configures options from code, after settings from <paramref name="configuration" /> have been applied.
50-
/// </param>
51-
/// <param name="createHttpClientHandler">
52-
/// An optional factory to create the HTTP client handler, used to mock HTTP requests to Config Server in tests. When provided, the caller is responsible
53-
/// for handler disposal.
54-
/// </param>
55-
/// <param name="loggerFactory">
56-
/// Used for internal logging. Pass <see cref="NullLoggerFactory.Instance" /> to disable logging.
57-
/// </param>
58-
public ConfigServerConfigurationSource(ConfigServerClientOptions defaultOptions, IConfiguration configuration, Action<ConfigServerClientOptions>? configure,
59-
Func<HttpClientHandler>? createHttpClientHandler, ILoggerFactory loggerFactory)
60-
{
61-
ArgumentNullException.ThrowIfNull(defaultOptions);
62-
ArgumentNullException.ThrowIfNull(configuration);
63-
ArgumentNullException.ThrowIfNull(loggerFactory);
64-
65-
DefaultOptions = defaultOptions;
66-
Configure = configure;
67-
CreateHttpClientHandler = createHttpClientHandler;
68-
Configuration = configuration;
69-
_loggerFactory = loggerFactory;
70-
}
71-
7239
/// <summary>
7340
/// Initializes a new instance of the <see cref="ConfigServerConfigurationSource" /> class.
7441
/// </summary>
@@ -102,11 +69,7 @@ public ConfigServerConfigurationSource(ConfigServerClientOptions defaultOptions,
10269
ArgumentNullException.ThrowIfNull(loggerFactory);
10370

10471
Sources = sources.ToList();
105-
106-
if (properties != null)
107-
{
108-
Properties = new Dictionary<string, object>(properties);
109-
}
72+
Properties = properties != null ? new Dictionary<string, object>(properties) : [];
11073

11174
DefaultOptions = defaultOptions;
11275
Configure = configure;
@@ -125,26 +88,19 @@ public ConfigServerConfigurationSource(ConfigServerClientOptions defaultOptions,
12588
/// </returns>
12689
public IConfigurationProvider Build(IConfigurationBuilder builder)
12790
{
128-
if (Configuration == null)
129-
{
130-
// Create our own builder to build sources
131-
var configurationBuilder = new ConfigurationBuilder();
91+
var configurationBuilder = new ConfigurationBuilder();
13292

133-
foreach (IConfigurationSource source in Sources)
134-
{
135-
configurationBuilder.Add(source);
136-
}
137-
138-
// Use properties provided
139-
foreach (KeyValuePair<string, object> pair in Properties)
140-
{
141-
configurationBuilder.Properties.Add(pair);
142-
}
93+
foreach (IConfigurationSource source in Sources)
94+
{
95+
configurationBuilder.Add(source);
96+
}
14397

144-
// Create configuration
145-
Configuration = configurationBuilder.Build();
98+
foreach (KeyValuePair<string, object> pair in Properties)
99+
{
100+
configurationBuilder.Properties.Add(pair);
146101
}
147102

103+
Configuration = configurationBuilder.Build();
148104
return new ConfigServerConfigurationProvider(this, _loggerFactory);
149105
}
150106
}

src/Configuration/src/ConfigServer/ConfigServerHealthContributor.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@ internal void UpdateHealth(HealthCheckResult health, IList<PropertySource> sourc
7676

7777
foreach (PropertySource source in sources)
7878
{
79-
LogReturningPropertySource(source.Name);
8079
names.Add(source.Name);
8180
}
8281

82+
LogReturningPropertySources(string.Join(", ", names));
8383
health.Details.Add("propertySources", names);
8484
}
8585

@@ -92,7 +92,17 @@ internal void UpdateHealth(HealthCheckResult health, IList<PropertySource> sourc
9292
{
9393
LastAccess = currentTime;
9494
LogCacheStale();
95-
Cached = await provider.LoadInternalAsync(optionsSnapshot, false, cancellationToken);
95+
96+
try
97+
{
98+
Cached = await provider.LoadInternalAsync(optionsSnapshot, false, cancellationToken);
99+
}
100+
catch (ConfigServerException exception)
101+
{
102+
LogFetchFailed(exception);
103+
Cached = null;
104+
return null;
105+
}
96106
}
97107

98108
return Cached?.PropertySources;
@@ -114,14 +124,17 @@ internal bool IsCacheStale(long accessTime, ConfigServerClientOptions optionsSna
114124
[LoggerMessage(Level = LogLevel.Debug, Message = "No Config Server provider found.")]
115125
private partial void LogNoProviderFound();
116126

127+
[LoggerMessage(Level = LogLevel.Debug, Message = "Failed fetching remote configuration from server(s).")]
128+
private partial void LogFetchFailed(Exception exception);
129+
117130
[LoggerMessage(Level = LogLevel.Debug, Message = "No property sources found.")]
118131
private partial void LogNoPropertySourcesFound();
119132

120133
[LoggerMessage(Level = LogLevel.Debug, Message = "Config Server health check returning UP.")]
121134
private partial void LogHealthCheckReturningUp();
122135

123-
[LoggerMessage(Level = LogLevel.Debug, Message = "Returning property source {PropertySource}.")]
124-
private partial void LogReturningPropertySource(string? propertySource);
136+
[LoggerMessage(Level = LogLevel.Debug, Message = "Returning property sources: {PropertySources}.")]
137+
private partial void LogReturningPropertySources(string propertySources);
125138

126139
[LoggerMessage(Level = LogLevel.Debug, Message = "Cache stale, fetching config server health.")]
127140
private partial void LogCacheStale();

src/Configuration/src/ConfigServer/ConfigurationSchema.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@
173173
},
174174
"TokenRenewRate": {
175175
"type": "integer",
176-
"description": "Gets or sets the vault token renew rate (in milliseconds). Default value: 60_000 (1 minute)."
176+
"description": "Gets or sets the Vault token renew rate (in milliseconds). Default value: 60_000 (1 minute)."
177177
},
178178
"TokenTtl": {
179179
"type": "integer",

src/Configuration/test/ConfigServer.Test/ConfigServerClientOptionsTest.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using Microsoft.Extensions.Options;
1111
using RichardSzalay.MockHttp;
1212
using Steeltoe.Common.TestResources;
13+
using Steeltoe.Configuration.Placeholder;
1314

1415
namespace Steeltoe.Configuration.ConfigServer.Test;
1516

@@ -333,12 +334,15 @@ public void Changes_in_IConfiguration_update_provider_options_and_injected_optio
333334

334335
fileProvider.IncludeAppSettingsJsonFile("""
335336
{
337+
"custom": {
338+
"profileName": "example-profile"
339+
},
336340
"spring": {
337341
"cloud": {
338342
"config": {
339343
"uri": "https://config.server.com:9999",
340344
"name": "example-app-name",
341-
"env": "example-profile",
345+
"env": "${custom:profileName}",
342346
"timeout": 30000
343347
}
344348
}
@@ -361,6 +365,7 @@ public void Changes_in_IConfiguration_update_provider_options_and_injected_optio
361365

362366
var configurationBuilder = new ConfigurationBuilder();
363367
configurationBuilder.AddInMemoryAppSettingsJsonFile(fileProvider);
368+
configurationBuilder.AddPlaceholderResolver();
364369
// ReSharper disable once AccessToDisposedClosure
365370
configurationBuilder.AddConfigServer(initialOptions, configureOptions, () => handler, NullLoggerFactory.Instance);
366371
IConfigurationRoot configuration = configurationBuilder.Build();
@@ -395,12 +400,15 @@ public void Changes_in_IConfiguration_update_provider_options_and_injected_optio
395400

396401
fileProvider.ReplaceAppSettingsJsonFile("""
397402
{
398-
"spring": {
403+
"custom": {
404+
"profileName": "example-profile"
405+
},
406+
"spring": {
399407
"cloud": {
400408
"config": {
401409
"uri": "https://alternate-config.server.com:7777",
402410
"name": "alternate-name",
403-
"env": "example-profile",
411+
"env": "${custom:profileName}",
404412
"timeout": 15000,
405413
"label": "alternate-label"
406414
}

src/Configuration/test/ConfigServer.Test/ConfigServerConfigurationBuilderExtensionsCoreTest.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ public void AddConfigServer_WithLoggerFactorySucceeds()
4242

4343
IList<string> logMessages = loggerProvider.GetAll();
4444

45-
logMessages.Should().Contain("DBUG Steeltoe.Configuration.ConfigServer.ConfigServerConfigurationProvider: Fetching configuration from server(s).");
45+
logMessages.Should().Contain(
46+
"DBUG Steeltoe.Configuration.ConfigServer.ConfigServerConfigurationProvider: Fetching remote configuration from server(s).");
4647
}
4748

4849
[Fact]

0 commit comments

Comments
 (0)