diff --git a/README.md b/README.md
index 7a0b7deb..686abcc4 100644
--- a/README.md
+++ b/README.md
@@ -249,6 +249,7 @@ Basic settings of the sink are configured using the properties in a `MSSqlServer
* `EagerlyEmitFirstEvent`
* `LevelSwitch`
* `UseSqlBulkCopy`
+* `ConnectionConfiguration`
### TableName
@@ -299,6 +300,10 @@ A switch allowing the pass-through minimum level to be changed at runtime. If th
A flag to use `SqlBulkCopy` instead of individual INSERT statements when writing log events. The default is `true`.
This setting is not used by the audit sink as it always uses INSERT statements to write events.
+### ConnectionConfiguration
+
+An optional action to customize the underlying SqlConnection object. Can be used to set properties such as `AccessTokenCallback`.
+
## ColumnOptions Object
Features of the log table are defined by changing properties on a `ColumnOptions` object:
diff --git a/src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/Dependencies/SinkDependenciesFactory.cs b/src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/Dependencies/SinkDependenciesFactory.cs
index f9a5cee7..ae84c4fd 100644
--- a/src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/Dependencies/SinkDependenciesFactory.cs
+++ b/src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/Dependencies/SinkDependenciesFactory.cs
@@ -22,7 +22,7 @@ internal static SinkDependencies Create(
// unless sink option EnlistInTransaction is set to true.
var sqlConnectionStringBuilderWrapper = new SqlConnectionStringBuilderWrapper(
connectionString, sinkOptions.EnlistInTransaction);
- var sqlConnectionFactory = new SqlConnectionFactory(sqlConnectionStringBuilderWrapper);
+ var sqlConnectionFactory = new SqlConnectionFactory(sqlConnectionStringBuilderWrapper, sinkOptions.ConnectionConfiguration);
var sqlCommandFactory = new SqlCommandFactory();
var dataTableCreator = new DataTableCreator(sinkOptions.TableName, columnOptions);
var sqlCreateTableWriter = new SqlCreateTableWriter(sinkOptions.SchemaName,
@@ -34,7 +34,7 @@ internal static SinkDependencies Create(
InitialCatalog = ""
};
var sqlConnectionFactoryNoDb =
- new SqlConnectionFactory(sqlConnectionStringBuilderWrapperNoDb);
+ new SqlConnectionFactory(sqlConnectionStringBuilderWrapperNoDb, sinkOptions.ConnectionConfiguration);
var sqlCreateDatabaseWriter = new SqlCreateDatabaseWriter(sqlConnectionStringBuilderWrapper.InitialCatalog);
var logEventDataGenerator =
diff --git a/src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/MSSqlServerSinkOptions.cs b/src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/MSSqlServerSinkOptions.cs
index c53dba43..34c16445 100644
--- a/src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/MSSqlServerSinkOptions.cs
+++ b/src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/MSSqlServerSinkOptions.cs
@@ -1,4 +1,5 @@
using System;
+using Microsoft.Data.SqlClient;
using Serilog.Core;
namespace Serilog.Sinks.MSSqlServer
@@ -83,5 +84,10 @@ internal MSSqlServerSinkOptions(
/// Flag to use instead of individual INSERT statements (default: true)
///
public bool UseSqlBulkCopy { get; set; }
+
+ ///
+ /// Supplies an extension point for customizing the underyling SqlConnection
+ ///
+ public Action ConnectionConfiguration { get; set; }
}
}
diff --git a/src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/Platform/SqlClient/SqlConnectionWrapper.cs b/src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/Platform/SqlClient/SqlConnectionWrapper.cs
index 638ae47d..5b398f8f 100644
--- a/src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/Platform/SqlClient/SqlConnectionWrapper.cs
+++ b/src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/Platform/SqlClient/SqlConnectionWrapper.cs
@@ -9,9 +9,13 @@ internal class SqlConnectionWrapper : ISqlConnectionWrapper
private readonly SqlConnection _sqlConnection;
private bool _disposedValue;
- public SqlConnectionWrapper(string connectionString)
+ public SqlConnectionWrapper(string connectionString, Action connectionConfiguration = null)
{
_sqlConnection = new SqlConnection(connectionString);
+ if (connectionConfiguration != null)
+ {
+ connectionConfiguration(_sqlConnection);
+ }
}
public SqlConnection SqlConnection => _sqlConnection;
diff --git a/src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/Platform/SqlConnectionFactory.cs b/src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/Platform/SqlConnectionFactory.cs
index b18f7878..004e1d84 100644
--- a/src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/Platform/SqlConnectionFactory.cs
+++ b/src/Serilog.Sinks.MSSqlServer/Sinks/MSSqlServer/Platform/SqlConnectionFactory.cs
@@ -1,4 +1,5 @@
using System;
+using Microsoft.Data.SqlClient;
using Serilog.Sinks.MSSqlServer.Platform.SqlClient;
namespace Serilog.Sinks.MSSqlServer.Platform
@@ -7,18 +8,21 @@ internal class SqlConnectionFactory : ISqlConnectionFactory
{
private readonly string _connectionString;
private readonly ISqlConnectionStringBuilderWrapper _sqlConnectionStringBuilderWrapper;
+ private readonly Action _connectionConfiguration;
- public SqlConnectionFactory(ISqlConnectionStringBuilderWrapper sqlConnectionStringBuilderWrapper)
+ public SqlConnectionFactory(ISqlConnectionStringBuilderWrapper sqlConnectionStringBuilderWrapper,
+ Action connectionConfiguration = null)
{
_sqlConnectionStringBuilderWrapper = sqlConnectionStringBuilderWrapper
?? throw new ArgumentNullException(nameof(sqlConnectionStringBuilderWrapper));
_connectionString = _sqlConnectionStringBuilderWrapper.ConnectionString;
+ _connectionConfiguration = connectionConfiguration;
}
public ISqlConnectionWrapper Create()
{
- return new SqlConnectionWrapper(_connectionString);
+ return new SqlConnectionWrapper(_connectionString, _connectionConfiguration);
}
}
}
diff --git a/test/Serilog.Sinks.MSSqlServer.Tests/Sinks/MSSqlServer/Dependencies/SinkDependenciesFactoryTests.cs b/test/Serilog.Sinks.MSSqlServer.Tests/Sinks/MSSqlServer/Dependencies/SinkDependenciesFactoryTests.cs
index 72d1bd38..91fd202c 100644
--- a/test/Serilog.Sinks.MSSqlServer.Tests/Sinks/MSSqlServer/Dependencies/SinkDependenciesFactoryTests.cs
+++ b/test/Serilog.Sinks.MSSqlServer.Tests/Sinks/MSSqlServer/Dependencies/SinkDependenciesFactoryTests.cs
@@ -1,7 +1,10 @@
-using Serilog.Sinks.MSSqlServer.Dependencies;
+using Moq;
+using System;
+using Serilog.Sinks.MSSqlServer.Dependencies;
using Serilog.Sinks.MSSqlServer.Platform;
using Serilog.Sinks.MSSqlServer.Tests.TestUtils;
using Xunit;
+using Microsoft.Data.SqlClient;
namespace Serilog.Sinks.MSSqlServer.Tests.Dependencies
{
@@ -68,5 +71,19 @@ public void DefaultsColumnOptionsIfNull()
// Act (should not throw)
SinkDependenciesFactory.Create(_connectionString, _sinkOptions, null, null, null);
}
+
+ [Fact]
+ public void CreatesSinkDependenciesWithSqlConnectionConfiguration()
+ {
+ // Arrange
+ var mockConfigurationAction = new Mock>();
+ var sinkOptions = new MSSqlServerSinkOptions { TableName = "LogEvents", ConnectionConfiguration = mockConfigurationAction.Object };
+
+ // Act
+ var result = SinkDependenciesFactory.Create(_connectionString, sinkOptions, null, _columnOptions, null);
+
+ // Assert
+ Assert.NotNull(result.SqlDatabaseCreator);
+ }
}
}
diff --git a/test/Serilog.Sinks.MSSqlServer.Tests/Sinks/MSSqlServer/Platform/SqlConnectionFactoryTests.cs b/test/Serilog.Sinks.MSSqlServer.Tests/Sinks/MSSqlServer/Platform/SqlConnectionFactoryTests.cs
index f14674f1..6f49e1c7 100644
--- a/test/Serilog.Sinks.MSSqlServer.Tests/Sinks/MSSqlServer/Platform/SqlConnectionFactoryTests.cs
+++ b/test/Serilog.Sinks.MSSqlServer.Tests/Sinks/MSSqlServer/Platform/SqlConnectionFactoryTests.cs
@@ -1,4 +1,5 @@
using System;
+using Microsoft.Data.SqlClient;
using Moq;
using Serilog.Sinks.MSSqlServer.Platform;
using Serilog.Sinks.MSSqlServer.Platform.SqlClient;
@@ -38,5 +39,23 @@ public void CreateConnectionReturnsConnectionWrapper()
Assert.IsAssignableFrom(connection);
}
}
+
+
+ [Fact]
+ public void CreateConnectionCallsCustomConfigurationAction()
+ {
+ // Arrange
+ var mockAction = new Mock>();
+ var sut = new SqlConnectionFactory(_sqlConnectionStringBuilderWrapperMock.Object, mockAction.Object);
+
+ // Act
+ using (var connection = sut.Create())
+ {
+ // Assert
+ Assert.NotNull(connection);
+ Assert.IsAssignableFrom(connection);
+ mockAction.Verify(m => m.Invoke(connection.SqlConnection), Times.Once);
+ }
+ }
}
}