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

Commit e9092b4

Browse files
Merge pull request #62 from thefringeninja/ops-help
Logging Improvements
2 parents b18d725 + 97dfc91 commit e9092b4

3 files changed

Lines changed: 118 additions & 79 deletions

File tree

src/SqlStreamStore.Server/Program.cs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
42
using System.Threading;
53
using System.Threading.Tasks;
64
using Microsoft.AspNetCore.Hosting;
@@ -17,28 +15,29 @@ internal class Program : IDisposable
1715

1816
public static async Task<int> Main(string[] args)
1917
{
20-
using (var program = new Program(args))
18+
var configuration = new SqlStreamStoreServerConfiguration(
19+
Environment.GetEnvironmentVariables(),
20+
args);
21+
22+
using (var program = new Program(configuration))
2123
{
2224
return await program.Run();
2325
}
2426
}
2527

26-
private Program(string[] args)
28+
private Program(SqlStreamStoreServerConfiguration configuration)
2729
{
28-
_configuration = new SqlStreamStoreServerConfiguration(
29-
Environment.GetEnvironmentVariables(),
30-
args);
31-
32-
Console.WriteLine(_configuration.ToString());
33-
3430
Log.Logger = new LoggerConfiguration()
35-
.MinimumLevel.Is(_configuration.LogLevel)
31+
.MinimumLevel.Is(configuration.LogLevel)
3632
.Enrich.FromLogContext()
3733
.WriteTo.Console()
3834
.CreateLogger();
3935

36+
Log.Information(configuration.ToString());
37+
38+
_configuration = configuration;
4039
_cts = new CancellationTokenSource();
41-
_factory = new SqlStreamStoreFactory(_configuration);
40+
_factory = new SqlStreamStoreFactory(configuration);
4241
}
4342

4443
private async Task<int> Run()
@@ -47,8 +46,10 @@ private async Task<int> Run()
4746
{
4847
using (var streamStore = await _factory.Create(_cts.Token))
4948
using (var host = new WebHostBuilder()
49+
.SuppressStatusMessages(true)
5050
.UseKestrel()
51-
.UseStartup(new SqlStreamStoreServerStartup(streamStore,
51+
.UseStartup(new SqlStreamStoreServerStartup(
52+
streamStore,
5253
new SqlStreamStoreMiddlewareOptions
5354
{
5455
UseCanonicalUrls = _configuration.UseCanonicalUris,
Lines changed: 82 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Data.SqlClient;
4+
using System.Text;
45
using System.Threading;
56
using System.Threading.Tasks;
67
using Npgsql;
@@ -32,10 +33,11 @@ private static readonly IDictionary<string, CreateStreamStore> s_factories
3233

3334
public SqlStreamStoreFactory(SqlStreamStoreServerConfiguration configuration)
3435
{
35-
if(configuration == null)
36+
if (configuration == null)
3637
{
3738
throw new ArgumentNullException(nameof(configuration));
3839
}
40+
3941
_configuration = configuration;
4042
}
4143

@@ -46,15 +48,12 @@ public Task<IStreamStore> Create(CancellationToken cancellationToken = default)
4648

4749
Log.Information($"Creating stream store for provider '{provider}'");
4850

49-
if(!s_factories.TryGetValue(provider, out var factory))
51+
if (!s_factories.TryGetValue(provider, out var factory))
5052
{
5153
throw new InvalidOperationException($"No provider factory for provider '{provider}' found.");
5254
}
5355

54-
var connectionString = _configuration.ConnectionString;
55-
var schema = _configuration.Schema;
56-
57-
return factory(connectionString, schema, cancellationToken);
56+
return factory(_configuration.ConnectionString, _configuration.Schema, cancellationToken);
5857
}
5958

6059
private static Task<IStreamStore> CreateInMemoryStreamStore(
@@ -69,37 +68,45 @@ private static async Task<IStreamStore> CreateMssqlStreamStore(
6968
CancellationToken cancellationToken)
7069
{
7170
var connectionStringBuilder = new SqlConnectionStringBuilder(connectionString);
72-
using(var connection = new SqlConnection(new SqlConnectionStringBuilder(connectionString)
71+
var settings = new MsSqlStreamStoreV3Settings(connectionString);
72+
73+
if (schema != null)
7374
{
74-
InitialCatalog = "master"
75-
}.ConnectionString))
75+
settings.Schema = schema;
76+
}
77+
78+
var streamStore = new MsSqlStreamStoreV3(settings);
79+
80+
try
7681
{
77-
await connection.OpenAsync(cancellationToken).NotOnCapturedContext();
82+
using (var connection = new SqlConnection(new SqlConnectionStringBuilder(connectionString)
83+
{
84+
InitialCatalog = "master"
85+
}.ConnectionString))
86+
{
87+
await connection.OpenAsync(cancellationToken).NotOnCapturedContext();
7888

79-
using(var command = new SqlCommand(
80-
$@"
89+
using (var command = new SqlCommand(
90+
$@"
8191
IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = N'{connectionStringBuilder.InitialCatalog}')
8292
BEGIN
8393
CREATE DATABASE [{connectionStringBuilder.InitialCatalog}]
8494
END;
8595
",
86-
connection))
87-
{
88-
await command.ExecuteNonQueryAsync(cancellationToken).NotOnCapturedContext();
96+
connection))
97+
{
98+
await command.ExecuteNonQueryAsync(cancellationToken).NotOnCapturedContext();
99+
}
89100
}
90-
}
91-
92-
var settings = new MsSqlStreamStoreV3Settings(connectionString);
93101

94-
if(schema != null)
102+
await streamStore.CreateSchemaIfNotExists(cancellationToken);
103+
}
104+
catch (SqlException ex)
95105
{
96-
settings.Schema = schema;
106+
SchemaCreationFailed(streamStore.GetSchemaCreationScript, ex);
107+
throw;
97108
}
98109

99-
var streamStore = new MsSqlStreamStoreV3(settings);
100-
101-
await streamStore.CreateSchemaIfNotExists(cancellationToken);
102-
103110
return streamStore;
104111
}
105112

@@ -109,46 +116,67 @@ private static async Task<IStreamStore> CreatePostgresStreamStore(
109116
CancellationToken cancellationToken)
110117
{
111118
var connectionStringBuilder = new NpgsqlConnectionStringBuilder(connectionString);
119+
var settings = new PostgresStreamStoreSettings(connectionString);
112120

113-
using(var connection = new NpgsqlConnection(new NpgsqlConnectionStringBuilder(connectionString)
114-
{
115-
Database = null
116-
}.ConnectionString))
121+
if (schema != null)
117122
{
118-
bool exists;
119-
await connection.OpenAsync(cancellationToken).NotOnCapturedContext();
123+
settings.Schema = schema;
124+
}
120125

121-
using(var command = new NpgsqlCommand(
122-
$"SELECT 1 FROM pg_database WHERE datname = '{connectionStringBuilder.Database}'",
123-
connection))
124-
{
125-
exists = await command.ExecuteScalarAsync(cancellationToken).NotOnCapturedContext()
126-
!= null;
127-
}
126+
var streamStore = new PostgresStreamStore(settings);
128127

129-
if(!exists)
128+
try
129+
{
130+
using (var connection = new NpgsqlConnection(new NpgsqlConnectionStringBuilder(connectionString)
130131
{
131-
using(var command = new NpgsqlCommand(
132-
$"CREATE DATABASE {connectionStringBuilder.Database}",
133-
connection))
132+
Database = null
133+
}.ConnectionString))
134+
{
135+
await connection.OpenAsync(cancellationToken).NotOnCapturedContext();
136+
137+
async Task<bool> DatabaseExists()
134138
{
135-
await command.ExecuteNonQueryAsync(cancellationToken).NotOnCapturedContext();
139+
using (var command = new NpgsqlCommand(
140+
$"SELECT 1 FROM pg_database WHERE datname = '{connectionStringBuilder.Database}'",
141+
connection))
142+
{
143+
return await command.ExecuteScalarAsync(cancellationToken).NotOnCapturedContext()
144+
!= null;
145+
}
136146
}
137-
}
138147

139-
var settings = new PostgresStreamStoreSettings(connectionString);
148+
if (!await DatabaseExists())
149+
{
150+
using (var command = new NpgsqlCommand(
151+
$"CREATE DATABASE {connectionStringBuilder.Database}",
152+
connection))
153+
{
154+
await command.ExecuteNonQueryAsync(cancellationToken).NotOnCapturedContext();
155+
}
156+
}
140157

141-
if(schema != null)
142-
{
143-
settings.Schema = schema;
158+
await streamStore.CreateSchemaIfNotExists(cancellationToken);
144159
}
145-
146-
var streamStore = new PostgresStreamStore(settings);
147-
148-
await streamStore.CreateSchemaIfNotExists(cancellationToken);
149-
150-
return streamStore;
151160
}
161+
catch (NpgsqlException ex)
162+
{
163+
SchemaCreationFailed(streamStore.GetSchemaCreationScript, ex);
164+
throw;
165+
}
166+
167+
return streamStore;
152168
}
169+
170+
private static void SchemaCreationFailed(Func<string> getSchemaCreationScript, Exception ex)
171+
=> Log.Warning(
172+
new StringBuilder()
173+
.Append($"Could not create schema: {ex.Message}")
174+
.AppendLine()
175+
.Append(
176+
"Does your connection string have enough permissions? If not, run the following sql script as a privileged user:")
177+
.AppendLine()
178+
.Append(getSchemaCreationScript())
179+
.ToString(),
180+
ex);
153181
}
154-
}
182+
}

src/SqlStreamStore.Server/SqlStreamStoreServerConfiguration.cs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@ void Log(string logName, IDictionary<string, string> data)
4444
{
4545
foreach (var (key, value) in data)
4646
{
47-
_values[key] = (logName, value);
47+
_values[key] = (
48+
logName,
49+
s_sensitiveKeys.Contains(key)
50+
? new string('*', 8)
51+
: value);
4852
}
4953
}
5054

@@ -82,18 +86,16 @@ public override string ToString()
8286
}
8387
}
8488
.Concat(
85-
s_allKeys
86-
.Select(key => new[] {delimiter, key, _values[key].value, _values[key].source}))
89+
s_allKeys.Select(key => new[] {delimiter, key, _values[key].value, _values[key].source}))
8790
.Aggregate(
8891
new StringBuilder().AppendLine("SQL Stream Store Configuration:"),
8992
(builder, values) => builder
9093
.Append((values[1] ?? string.Empty).PadRight(column0Width, ' '))
9194
.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[2] ?? string.Empty).PadRight(column1Width, ' '))
9596
.Append(values[0])
96-
.AppendLine(values[3])).ToString();
97+
.AppendLine(values[3]))
98+
.ToString();
9799
}
98100

99101
private static string Computerize(string value) =>
@@ -115,7 +117,11 @@ private class ConfigurationData
115117

116118
public ConfigurationData(IConfigurationRoot configuration)
117119
{
118-
if (configuration == null) throw new ArgumentNullException(nameof(configuration));
120+
if (configuration == null)
121+
{
122+
throw new ArgumentNullException(nameof(configuration));
123+
}
124+
119125
_configuration = configuration;
120126
}
121127
}
@@ -135,16 +141,20 @@ public Default(Action<string, IDictionary<string, string>> log)
135141
}
136142

137143
public IConfigurationProvider Build(IConfigurationBuilder builder) =>
138-
new DefaultConfigurtationProvider(_log);
144+
new DefaultConfigurationProvider(_log);
139145
}
140146

141-
private class DefaultConfigurtationProvider : ConfigurationProvider
147+
private class DefaultConfigurationProvider : ConfigurationProvider
142148
{
143149
private readonly Action<string, IDictionary<string, string>> _log;
144150

145-
public DefaultConfigurtationProvider(Action<string, IDictionary<string, string>> log)
151+
public DefaultConfigurationProvider(Action<string, IDictionary<string, string>> log)
146152
{
147-
if (log == null) throw new ArgumentNullException(nameof(log));
153+
if (log == null)
154+
{
155+
throw new ArgumentNullException(nameof(log));
156+
}
157+
148158
_log = log;
149159
}
150160

0 commit comments

Comments
 (0)