Skip to content
This repository was archived by the owner on Sep 3, 2024. It is now read-only.

Commit 2e56694

Browse files
Merge pull request #60 from thefringeninja/print-configuration
Print Configuration on Startup
2 parents dfe3c50 + 1e78391 commit 2e56694

2 files changed

Lines changed: 256 additions & 22 deletions

File tree

src/SqlStreamStore.Server/Program.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
24
using System.Threading;
35
using System.Threading.Tasks;
46
using Microsoft.AspNetCore.Hosting;
@@ -23,7 +25,11 @@ public static async Task<int> Main(string[] args)
2325

2426
private Program(string[] args)
2527
{
26-
_configuration = new SqlStreamStoreServerConfiguration(Environment.GetEnvironmentVariables(), args);
28+
_configuration = new SqlStreamStoreServerConfiguration(
29+
Environment.GetEnvironmentVariables(),
30+
args);
31+
32+
Console.WriteLine(_configuration.ToString());
2733

2834
Log.Logger = new LoggerConfiguration()
2935
.MinimumLevel.Is(_configuration.LogLevel)
Lines changed: 249 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,294 @@
11
using System;
22
using System.Collections;
3+
using System.Collections.Generic;
34
using System.Linq;
5+
using System.Reflection;
6+
using System.Text;
47
using Microsoft.Extensions.Configuration;
58
using Serilog.Events;
69

710
namespace SqlStreamStore.Server
811
{
912
internal class SqlStreamStoreServerConfiguration
1013
{
11-
private readonly IConfigurationRoot _configuration;
14+
private static readonly string[] s_sensitiveKeys = typeof(ConfigurationData).GetProperties()
15+
.Where(property => property.GetCustomAttributes<SensitiveAttribute>().Any())
16+
.Select(property => property.Name)
17+
.ToArray();
1218

13-
public bool UseCanonicalUris => _configuration.GetValue<bool>("use-canonical-uris");
14-
public LogEventLevel LogLevel => _configuration.GetValue("log-level", LogEventLevel.Information);
15-
public string ConnectionString => _configuration.GetValue<string>("connection-string");
16-
public string Schema => _configuration.GetValue<string>("schema");
17-
public string Provider => _configuration.GetValue<string>("provider");
19+
private static readonly string[] s_allKeys = typeof(ConfigurationData).GetProperties()
20+
.Select(property => property.Name)
21+
.ToArray();
1822

19-
public SqlStreamStoreServerConfiguration(IDictionary environment, string[] args)
23+
private readonly ConfigurationData _configuration;
24+
private readonly IDictionary<string, (string source, string value)> _values;
25+
26+
public bool UseCanonicalUris => _configuration.UseCanonicalUris;
27+
public LogEventLevel LogLevel => _configuration.LogLevel;
28+
public string ConnectionString => _configuration.ConnectionString;
29+
public string Schema => _configuration.Schema;
30+
public string Provider => _configuration.Provider;
31+
32+
public SqlStreamStoreServerConfiguration(
33+
IDictionary environment,
34+
string[] args)
2035
{
21-
if(environment == null)
36+
if (environment == null)
2237
throw new ArgumentNullException(nameof(environment));
23-
if(args == null)
38+
if (args == null)
2439
throw new ArgumentNullException(nameof(args));
25-
_configuration = new ConfigurationBuilder()
26-
.AddCommandLine(args)
27-
.Add(new UpperCasedEnvironmentVariablesConfigurationSource(environment))
28-
.Build();
40+
41+
_values = new Dictionary<string, (string source, string value)>();
42+
43+
void Log(string logName, IDictionary<string, string> data)
44+
{
45+
foreach (var (key, value) in data)
46+
{
47+
_values[key] = (logName, value);
48+
}
49+
}
50+
51+
_configuration = new ConfigurationData(
52+
new ConfigurationBuilder()
53+
.Add(new Default(Log))
54+
.Add(new CommandLine(args, Log))
55+
.Add(new EnvironmentVariables(environment, Log))
56+
.Build());
57+
}
58+
59+
public override string ToString()
60+
{
61+
const string delimiter = " │ ";
62+
63+
var column0Width = _values.Keys.Count > 0 ? _values.Keys.Max(x => x?.Length ?? 0) : 0;
64+
var column1Width = _values.Values.Count > 0 ? _values.Values.Max(_ => _.value?.Length ?? 0) : 0;
65+
var column2Width = _values.Values.Count > 0 ? _values.Values.Max(_ => _.source?.Length ?? 0) : 0;
66+
67+
return new[]
68+
{
69+
new[]
70+
{
71+
delimiter,
72+
"Argument",
73+
"Value",
74+
"Source"
75+
},
76+
new[]
77+
{
78+
"─┼─",
79+
new string('─', column0Width),
80+
new string('─', column1Width),
81+
new string('─', column2Width)
82+
}
83+
}
84+
.Concat(
85+
s_allKeys
86+
.Select(key => new[] {delimiter, key, _values[key].value, _values[key].source}))
87+
.Aggregate(
88+
new StringBuilder().AppendLine("SQL Stream Store Configuration:"),
89+
(builder, values) => builder
90+
.Append((values[1] ?? string.Empty).PadRight(column0Width, ' '))
91+
.Append(values[0])
92+
.Append((s_sensitiveKeys.Contains(values[1])
93+
? new string('*', Math.Min(column1Width, 8))
94+
: values[2] ?? string.Empty).PadRight(column1Width, ' '))
95+
.Append(values[0])
96+
.AppendLine(values[3])).ToString();
97+
}
98+
99+
private static string Computerize(string value) =>
100+
string.Join(
101+
string.Empty,
102+
(value?.Replace("-", "_").ToLowerInvariant()
103+
?? string.Empty).Split('_')
104+
.Select(x => new string(x.Select((c, i) => i == 0 ? char.ToUpper(c) : c).ToArray())));
105+
106+
private class ConfigurationData
107+
{
108+
private readonly IConfigurationRoot _configuration;
109+
110+
public bool UseCanonicalUris => _configuration.GetValue<bool>(nameof(UseCanonicalUris));
111+
public LogEventLevel LogLevel => _configuration.GetValue(nameof(LogLevel), LogEventLevel.Information);
112+
[Sensitive] public string ConnectionString => _configuration.GetValue<string>(nameof(ConnectionString));
113+
public string Schema => _configuration.GetValue<string>(nameof(Schema));
114+
public string Provider => _configuration.GetValue<string>(nameof(Provider));
115+
116+
public ConfigurationData(IConfigurationRoot configuration)
117+
{
118+
if (configuration == null) throw new ArgumentNullException(nameof(configuration));
119+
_configuration = configuration;
120+
}
121+
}
122+
123+
private class Default : IConfigurationSource
124+
{
125+
private readonly Action<string, IDictionary<string, string>> _log;
126+
127+
public Default(Action<string, IDictionary<string, string>> log)
128+
{
129+
if (log == null)
130+
{
131+
throw new ArgumentNullException(nameof(log));
132+
}
133+
134+
_log = log;
135+
}
136+
137+
public IConfigurationProvider Build(IConfigurationBuilder builder) =>
138+
new DefaultConfigurtationProvider(_log);
139+
}
140+
141+
private class DefaultConfigurtationProvider : ConfigurationProvider
142+
{
143+
private readonly Action<string, IDictionary<string, string>> _log;
144+
145+
public DefaultConfigurtationProvider(Action<string, IDictionary<string, string>> log)
146+
{
147+
if (log == null) throw new ArgumentNullException(nameof(log));
148+
_log = log;
149+
}
150+
151+
public override void Load()
152+
{
153+
Data = new Dictionary<string, string>
154+
{
155+
[nameof(ConnectionString)] = default,
156+
[nameof(Provider)] = "inmemory",
157+
[nameof(LogLevel)] = nameof(LogEventLevel.Information),
158+
[nameof(Schema)] = default,
159+
[nameof(UseCanonicalUris)] = default
160+
};
161+
162+
_log(nameof(Default), Data);
163+
}
164+
}
165+
166+
private class CommandLine : IConfigurationSource
167+
{
168+
private readonly IEnumerable<string> _args;
169+
private readonly Action<string, IDictionary<string, string>> _log;
170+
171+
public CommandLine(
172+
IEnumerable<string> args,
173+
Action<string, IDictionary<string, string>> log)
174+
{
175+
if (args == null)
176+
{
177+
throw new ArgumentNullException(nameof(args));
178+
}
179+
180+
if (log == null)
181+
{
182+
throw new ArgumentNullException(nameof(log));
183+
}
184+
185+
_args = args;
186+
_log = log;
187+
}
188+
189+
public IConfigurationProvider Build(IConfigurationBuilder builder)
190+
=> new CommandLineConfigurationProvider(_args, _log);
191+
}
192+
193+
private class CommandLineConfigurationProvider
194+
: Microsoft.Extensions.Configuration.CommandLine.CommandLineConfigurationProvider
195+
{
196+
private readonly Action<string, IDictionary<string, string>> _log;
197+
198+
public CommandLineConfigurationProvider(IEnumerable<string> args,
199+
Action<string, IDictionary<string, string>> log,
200+
IDictionary<string, string> switchMappings = null) : base(args, switchMappings)
201+
{
202+
if (log == null)
203+
{
204+
throw new ArgumentNullException(nameof(log));
205+
}
206+
207+
_log = log;
208+
}
209+
210+
public override void Load()
211+
{
212+
base.Load();
213+
214+
Data = Data.Keys.ToDictionary(Computerize, x => Data[x]);
215+
216+
_log(nameof(CommandLine), Data);
217+
}
29218
}
30219

31-
private class UpperCasedEnvironmentVariablesConfigurationSource : IConfigurationSource
220+
private class EnvironmentVariables : IConfigurationSource
32221
{
33222
private readonly IDictionary _environment;
223+
private readonly Action<string, IDictionary<string, string>> _log;
34224
public string Prefix { get; set; } = "SQLSTREAMSTORE";
35225

36-
public UpperCasedEnvironmentVariablesConfigurationSource(IDictionary environment)
226+
public EnvironmentVariables(
227+
IDictionary environment,
228+
Action<string, IDictionary<string, string>> log)
37229
{
230+
if (log == null)
231+
{
232+
throw new ArgumentNullException(nameof(log));
233+
}
234+
235+
if (environment == null)
236+
{
237+
throw new ArgumentNullException(nameof(environment));
238+
}
239+
38240
_environment = environment;
241+
_log = log;
39242
}
40243

41244
public IConfigurationProvider Build(IConfigurationBuilder builder)
42-
=> new UpperCasedEnvironmentVariablesConfigurationProvider(Prefix, _environment);
245+
=> new EnvironmentVariablesConfigurationProvider(Prefix, _environment, _log);
43246
}
44247

45-
private class UpperCasedEnvironmentVariablesConfigurationProvider : ConfigurationProvider
248+
private class EnvironmentVariablesConfigurationProvider : ConfigurationProvider
46249
{
47250
private readonly IDictionary _environment;
251+
private readonly Action<string, IDictionary<string, string>> _log;
48252
private readonly string _prefix;
49253

50-
public UpperCasedEnvironmentVariablesConfigurationProvider(string prefix, IDictionary environment)
254+
public EnvironmentVariablesConfigurationProvider(
255+
string prefix,
256+
IDictionary environment,
257+
Action<string, IDictionary<string, string>> log)
51258
{
52-
_environment = environment;
259+
if (log == null)
260+
{
261+
throw new ArgumentNullException(nameof(log));
262+
}
263+
264+
if (environment == null)
265+
{
266+
throw new ArgumentNullException(nameof(environment));
267+
}
268+
53269
_prefix = $"{prefix}_";
270+
_environment = environment;
271+
_log = log;
54272
}
55273

56274
public override void Load()
57275
{
58276
Data = (from entry in _environment.OfType<DictionaryEntry>()
59277
let key = (string) entry.Key
60278
where key.StartsWith(_prefix)
61-
select new { key = key.Remove(0, _prefix.Length).Replace('_', '-').ToLowerInvariant(), value = (string) entry.Value })
279+
select new
280+
{
281+
key = Computerize(key.Remove(0, _prefix.Length)),
282+
value = (string) entry.Value
283+
})
62284
.ToDictionary(x => x.key, x => x.value);
285+
286+
_log(nameof(EnvironmentVariables), Data);
63287
}
64288
}
289+
290+
private class SensitiveAttribute : Attribute
291+
{
292+
}
65293
}
66-
}
294+
}

0 commit comments

Comments
 (0)