Skip to content

Commit 36c9d82

Browse files
authored
Merge pull request #613 from nhart12/sqlConnectionConfiguration
SqlConnection config action
2 parents 83fdfa5 + ec3422e commit 36c9d82

File tree

7 files changed

+61
-6
lines changed

7 files changed

+61
-6
lines changed

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ Basic settings of the sink are configured using the properties in a `MSSqlServer
249249
* `EagerlyEmitFirstEvent`
250250
* `LevelSwitch`
251251
* `UseSqlBulkCopy`
252+
* `ConnectionConfiguration`
252253

253254
### TableName
254255

@@ -299,6 +300,10 @@ A switch allowing the pass-through minimum level to be changed at runtime. If th
299300
A flag to use `SqlBulkCopy` instead of individual INSERT statements when writing log events. The default is `true`.
300301
This setting is not used by the audit sink as it always uses INSERT statements to write events.
301302

303+
### ConnectionConfiguration
304+
305+
An optional action to customize the underlying SqlConnection object. Can be used to set properties such as `AccessTokenCallback`.
306+
302307
## ColumnOptions Object
303308

304309
Features of the log table are defined by changing properties on a `ColumnOptions` object:

src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/Dependencies/SinkDependenciesFactory.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ internal static SinkDependencies Create(
2222
// unless sink option EnlistInTransaction is set to true.
2323
var sqlConnectionStringBuilderWrapper = new SqlConnectionStringBuilderWrapper(
2424
connectionString, sinkOptions.EnlistInTransaction);
25-
var sqlConnectionFactory = new SqlConnectionFactory(sqlConnectionStringBuilderWrapper);
25+
var sqlConnectionFactory = new SqlConnectionFactory(sqlConnectionStringBuilderWrapper, sinkOptions.ConnectionConfiguration);
2626
var sqlCommandFactory = new SqlCommandFactory();
2727
var dataTableCreator = new DataTableCreator(sinkOptions.TableName, columnOptions);
2828
var sqlCreateTableWriter = new SqlCreateTableWriter(sinkOptions.SchemaName,
@@ -34,7 +34,7 @@ internal static SinkDependencies Create(
3434
InitialCatalog = ""
3535
};
3636
var sqlConnectionFactoryNoDb =
37-
new SqlConnectionFactory(sqlConnectionStringBuilderWrapperNoDb);
37+
new SqlConnectionFactory(sqlConnectionStringBuilderWrapperNoDb, sinkOptions.ConnectionConfiguration);
3838
var sqlCreateDatabaseWriter = new SqlCreateDatabaseWriter(sqlConnectionStringBuilderWrapper.InitialCatalog);
3939

4040
var logEventDataGenerator =

src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/MSSqlServerSinkOptions.cs

+6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using Microsoft.Data.SqlClient;
23
using Serilog.Core;
34

45
namespace Serilog.Sinks.MSSqlServer
@@ -83,5 +84,10 @@ internal MSSqlServerSinkOptions(
8384
/// Flag to use <see cref="Microsoft.Data.SqlClient.SqlBulkCopy"/> instead of individual INSERT statements (default: true)
8485
/// </summary>
8586
public bool UseSqlBulkCopy { get; set; }
87+
88+
/// <summary>
89+
/// Supplies an extension point for customizing the underyling SqlConnection
90+
/// </summary>
91+
public Action<SqlConnection> ConnectionConfiguration { get; set; }
8692
}
8793
}

src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/Platform/SqlClient/SqlConnectionWrapper.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@ internal class SqlConnectionWrapper : ISqlConnectionWrapper
99
private readonly SqlConnection _sqlConnection;
1010
private bool _disposedValue;
1111

12-
public SqlConnectionWrapper(string connectionString)
12+
public SqlConnectionWrapper(string connectionString, Action<SqlConnection> connectionConfiguration = null)
1313
{
1414
_sqlConnection = new SqlConnection(connectionString);
15+
if (connectionConfiguration != null)
16+
{
17+
connectionConfiguration(_sqlConnection);
18+
}
1519
}
1620

1721
public SqlConnection SqlConnection => _sqlConnection;
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using Microsoft.Data.SqlClient;
23
using Serilog.Sinks.MSSqlServer.Platform.SqlClient;
34

45
namespace Serilog.Sinks.MSSqlServer.Platform
@@ -7,18 +8,21 @@ internal class SqlConnectionFactory : ISqlConnectionFactory
78
{
89
private readonly string _connectionString;
910
private readonly ISqlConnectionStringBuilderWrapper _sqlConnectionStringBuilderWrapper;
11+
private readonly Action<SqlConnection> _connectionConfiguration;
1012

11-
public SqlConnectionFactory(ISqlConnectionStringBuilderWrapper sqlConnectionStringBuilderWrapper)
13+
public SqlConnectionFactory(ISqlConnectionStringBuilderWrapper sqlConnectionStringBuilderWrapper,
14+
Action<SqlConnection> connectionConfiguration = null)
1215
{
1316
_sqlConnectionStringBuilderWrapper = sqlConnectionStringBuilderWrapper
1417
?? throw new ArgumentNullException(nameof(sqlConnectionStringBuilderWrapper));
1518

1619
_connectionString = _sqlConnectionStringBuilderWrapper.ConnectionString;
20+
_connectionConfiguration = connectionConfiguration;
1721
}
1822

1923
public ISqlConnectionWrapper Create()
2024
{
21-
return new SqlConnectionWrapper(_connectionString);
25+
return new SqlConnectionWrapper(_connectionString, _connectionConfiguration);
2226
}
2327
}
2428
}

test/Serilog.Sinks.MSSqlServer.Tests/Sinks/MSSqlServer/Dependencies/SinkDependenciesFactoryTests.cs

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
using Serilog.Sinks.MSSqlServer.Dependencies;
1+
using Moq;
2+
using System;
3+
using Serilog.Sinks.MSSqlServer.Dependencies;
24
using Serilog.Sinks.MSSqlServer.Platform;
35
using Serilog.Sinks.MSSqlServer.Tests.TestUtils;
46
using Xunit;
7+
using Microsoft.Data.SqlClient;
58

69
namespace Serilog.Sinks.MSSqlServer.Tests.Dependencies
710
{
@@ -68,5 +71,19 @@ public void DefaultsColumnOptionsIfNull()
6871
// Act (should not throw)
6972
SinkDependenciesFactory.Create(_connectionString, _sinkOptions, null, null, null);
7073
}
74+
75+
[Fact]
76+
public void CreatesSinkDependenciesWithSqlConnectionConfiguration()
77+
{
78+
// Arrange
79+
var mockConfigurationAction = new Mock<Action<SqlConnection>>();
80+
var sinkOptions = new MSSqlServerSinkOptions { TableName = "LogEvents", ConnectionConfiguration = mockConfigurationAction.Object };
81+
82+
// Act
83+
var result = SinkDependenciesFactory.Create(_connectionString, sinkOptions, null, _columnOptions, null);
84+
85+
// Assert
86+
Assert.NotNull(result.SqlDatabaseCreator);
87+
}
7188
}
7289
}

test/Serilog.Sinks.MSSqlServer.Tests/Sinks/MSSqlServer/Platform/SqlConnectionFactoryTests.cs

+19
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using Microsoft.Data.SqlClient;
23
using Moq;
34
using Serilog.Sinks.MSSqlServer.Platform;
45
using Serilog.Sinks.MSSqlServer.Platform.SqlClient;
@@ -38,5 +39,23 @@ public void CreateConnectionReturnsConnectionWrapper()
3839
Assert.IsAssignableFrom<ISqlConnectionWrapper>(connection);
3940
}
4041
}
42+
43+
44+
[Fact]
45+
public void CreateConnectionCallsCustomConfigurationAction()
46+
{
47+
// Arrange
48+
var mockAction = new Mock<Action<SqlConnection>>();
49+
var sut = new SqlConnectionFactory(_sqlConnectionStringBuilderWrapperMock.Object, mockAction.Object);
50+
51+
// Act
52+
using (var connection = sut.Create())
53+
{
54+
// Assert
55+
Assert.NotNull(connection);
56+
Assert.IsAssignableFrom<ISqlConnectionWrapper>(connection);
57+
mockAction.Verify(m => m.Invoke(connection.SqlConnection), Times.Once);
58+
}
59+
}
4160
}
4261
}

0 commit comments

Comments
 (0)