示例#1
0
        public void MSSqlServerCallsSinkFactoryWithSinkOptionsFromSystemConfig()
        {
            // Arrange
            var configSinkOptions = new SinkOptions();

            _applySystemConfigurationMock.Setup(c => c.GetSinkConfigurationSection(It.IsAny <string>()))
            .Returns(new MSSqlServerConfigurationSection());
            _applySystemConfigurationMock.Setup(c => c.ConfigureSinkOptions(It.IsAny <MSSqlServerConfigurationSection>(), It.IsAny <SinkOptions>()))
            .Returns(configSinkOptions);
            var sinkFactoryMock = new Mock <IMSSqlServerSinkFactory>();

            // Act
            _loggerConfiguration.WriteTo.MSSqlServerInternal(
                configSectionName: "TestConfigSectionName",
                connectionString: "TestConnectionString",
                sinkOptions: new SinkOptions {
                TableName = "TestTableName"
            },
                columnOptions: new Serilog.Sinks.MSSqlServer.ColumnOptions(),
                applySystemConfiguration: _applySystemConfigurationMock.Object,
                sinkFactory: sinkFactoryMock.Object);

            // Assert
            sinkFactoryMock.Verify(f => f.Create(It.IsAny <string>(), configSinkOptions,
                                                 It.IsAny <IFormatProvider>(), It.IsAny <Serilog.Sinks.MSSqlServer.ColumnOptions>(), It.IsAny <ITextFormatter>()), Times.Once);
        }
        public void MSSqlServerAuditCallsSinkFactoryWithSuppliedParameters()
        {
            // Arrange
            const string connectionString      = "TestConnectionString";
            var          sinkOptions           = new SinkOptions();
            var          columnOptions         = new Serilog.Sinks.MSSqlServer.ColumnOptions();
            var          formatProviderMock    = new Mock <IFormatProvider>();
            var          logEventFormatterMock = new Mock <ITextFormatter>();

            var auditSinkFactoryMock = new Mock <IMSSqlServerAuditSinkFactory>();

            // Act
            _loggerConfiguration.AuditTo.MSSqlServerInternal(
                connectionString: connectionString,
                sinkOptions: sinkOptions,
                columnOptions: columnOptions,
                formatProvider: formatProviderMock.Object,
                logEventFormatter: logEventFormatterMock.Object,
                applySystemConfiguration: _applySystemConfigurationMock.Object,
                applyMicrosoftExtensionsConfiguration: _applyMicrosoftExtensionsConfigurationMock.Object,
                auditSinkFactory: auditSinkFactoryMock.Object);

            // Assert
            auditSinkFactoryMock.Verify(f => f.Create(connectionString, sinkOptions,
                                                      formatProviderMock.Object, columnOptions, logEventFormatterMock.Object), Times.Once);
        }
 private static void ValidateParameters(SinkOptions sinkOptions)
 {
     if (sinkOptions?.TableName == null)
     {
         throw new InvalidOperationException("Table name must be specified!");
     }
 }
示例#4
0
        public MSSqlServerAuditSinkTests()
        {
            _sinkOptions = new SinkOptions
            {
                TableName  = _tableName,
                SchemaName = _schemaName
            };

            _columnOptions = new Serilog.Sinks.MSSqlServer.ColumnOptions();

            _dataTable            = new DataTable(_tableName);
            _dataTableCreatorMock = new Mock <IDataTableCreator>();
            _dataTableCreatorMock.Setup(d => d.CreateDataTable())
            .Returns(_dataTable);

            _sqlTableCreatorMock = new Mock <ISqlTableCreator>();
            _sqlLogEventWriter   = new Mock <ISqlLogEventWriter>();

            _sinkDependencies = new SinkDependencies
            {
                DataTableCreator  = _dataTableCreatorMock.Object,
                SqlTableCreator   = _sqlTableCreatorMock.Object,
                SqlLogEventWriter = _sqlLogEventWriter.Object
            };
        }
示例#5
0
 public SinkDependenciesFactoryTests()
 {
     _sinkOptions = new SinkOptions {
         TableName = "LogEvents"
     };
     _columnOptions = new Serilog.Sinks.MSSqlServer.ColumnOptions();
 }
        // Internal overload with parameters used by tests to override the config section and inject mocks
        internal static LoggerConfiguration MSSqlServerInternal(
            this LoggerAuditSinkConfiguration loggerAuditSinkConfiguration,
            string connectionString,
            SinkOptions sinkOptions = null,
            IConfigurationSection sinkOptionsSection = null,
            IConfiguration appConfiguration          = null,
            LogEventLevel restrictedToMinimumLevel   = LevelAlias.Minimum,
            IFormatProvider formatProvider           = null,
            ColumnOptions columnOptions = null,
            IConfigurationSection columnOptionsSection         = null,
            ITextFormatter logEventFormatter                   = null,
            IApplySystemConfiguration applySystemConfiguration = null,
            IApplyMicrosoftExtensionsConfiguration applyMicrosoftExtensionsConfiguration = null,
            IMSSqlServerAuditSinkFactory auditSinkFactory = null)
        {
            if (loggerAuditSinkConfiguration == null)
            {
                throw new ArgumentNullException(nameof(loggerAuditSinkConfiguration));
            }

            ReadConfiguration(ref connectionString, ref sinkOptions, sinkOptionsSection, appConfiguration,
                              ref columnOptions, columnOptionsSection, applySystemConfiguration, applyMicrosoftExtensionsConfiguration);

            var auditSink = auditSinkFactory.Create(connectionString, sinkOptions, formatProvider, columnOptions, logEventFormatter);

            return(loggerAuditSinkConfiguration.Sink(auditSink, restrictedToMinimumLevel));
        }
示例#7
0
        public static LoggerConfiguration MSSqlServer(
            this LoggerSinkConfiguration loggerConfiguration,
            string connectionString,
            string tableName,
            string schemaName = MSSqlServerSink.DefaultSchemaName,
            LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
            int batchPostingLimit            = MSSqlServerSink.DefaultBatchPostingLimit,
            TimeSpan?period                  = null,
            IFormatProvider formatProvider   = null,
            bool autoCreateSqlTable          = false,
            ColumnOptions columnOptions      = null,
            ITextFormatter logEventFormatter = null)
        {
            // Do not add new parameters here. This interface is considered legacy and will be deprecated in the future.
            // For adding new input parameters use the SinkOptions class and the method overload that accepts SinkOptions.

            var sinkOptions = new SinkOptions(tableName, batchPostingLimit, period, autoCreateSqlTable, schemaName);

            return(loggerConfiguration.MSSqlServer(
                       connectionString: connectionString,
                       sinkOptions: sinkOptions,
                       restrictedToMinimumLevel: restrictedToMinimumLevel,
                       formatProvider: formatProvider,
                       columnOptions: columnOptions,
                       logEventFormatter: logEventFormatter));
        }
示例#8
0
        public void MSSqlServerCallsSinkFactoryWithSuppliedParameters()
        {
            // Arrange
            var sinkOptions = new SinkOptions {
                TableName = "TestTableName"
            };
            var columnOptions         = new Serilog.Sinks.MSSqlServer.ColumnOptions();
            var formatProviderMock    = new Mock <IFormatProvider>();
            var logEventFormatterMock = new Mock <ITextFormatter>();
            var sinkFactoryMock       = new Mock <IMSSqlServerSinkFactory>();

            _applySystemConfigurationMock.Setup(c => c.GetConnectionString(It.IsAny <string>()))
            .Returns <string>(c => c);

            // Act
            _loggerConfiguration.WriteTo.MSSqlServerInternal(
                configSectionName: "TestConfigSectionName",
                connectionString: "TestConnectionString",
                sinkOptions: sinkOptions,
                columnOptions: columnOptions,
                formatProvider: formatProviderMock.Object,
                logEventFormatter: logEventFormatterMock.Object,
                applySystemConfiguration: _applySystemConfigurationMock.Object,
                sinkFactory: sinkFactoryMock.Object);

            // Assert
            sinkFactoryMock.Verify(f => f.Create(It.IsAny <string>(), sinkOptions, formatProviderMock.Object,
                                                 columnOptions, logEventFormatterMock.Object), Times.Once);
        }
示例#9
0
        public Logger CreateDefault()
        {
            var config = ConfigurationHelper.GetConfiguration();

            var telemetryConfiguration = TelemetryConfiguration.CreateDefault();

            telemetryConfiguration.InstrumentationKey =
                config.GetValue <string>(ConfigurationKeys.ApplicationInsightsInstrumentationKey);

            var logDb    = config.GetConnectionString(ConfigurationKeys.SystemSqlConnectionStringName);
            var sinkOpts = new SinkOptions
            {
                SchemaName = Constants.Log.LogSchemaName,
                TableName  = Constants.Log.LogTableName
            };

            return(new LoggerConfiguration()
                   .ReadFrom.Configuration(config)
                   .Enrich.WithMachineName()
                   .Enrich.WithProcessId()
                   .Enrich.FromLogContext()
                   .WriteTo.ApplicationInsights(telemetryConfiguration, TelemetryConverter.Traces)
                   .WriteTo.MSSqlServer(logDb, sinkOpts)
                   .WriteTo.Console()
                   .CreateLogger());
        }
        /// <summary>
        /// Adds a sink that writes log events to a table in a MSSqlServer database.
        /// Create a database and execute the table creation script found here
        /// https://gist.github.com/mivano/10429656
        /// or use the autoCreateSqlTable option.
        /// </summary>
        /// <param name="loggerConfiguration">The logger configuration.</param>
        /// <param name="connectionString">The connection string to the database where to store the events.</param>
        /// <param name="sinkOptions">Supplies additional settings for the sink</param>
        /// <param name="appConfiguration">Additional application-level configuration. Required if connectionString is a name.</param>
        /// <param name="restrictedToMinimumLevel">The minimum log event level required in order to write an event to the sink.</param>
        /// <param name="formatProvider">Supplies culture-specific formatting information, or null.</param>
        /// <param name="columnOptions">An externally-modified group of column settings</param>
        /// <param name="columnOptionsSection">A config section defining various column settings</param>
        /// <param name="logEventFormatter">Supplies custom formatter for the LogEvent column, or null</param>
        /// <param name="sinkOptionsSection">A config section defining additional settings for the sink</param>
        /// <returns>Logger configuration, allowing configuration to continue.</returns>
        /// <exception cref="ArgumentNullException">A required parameter is null.</exception>
        public static LoggerConfiguration MSSqlServer(
            this LoggerSinkConfiguration loggerConfiguration,
            string connectionString,
            SinkOptions sinkOptions                    = null,
            IConfiguration appConfiguration            = null,
            LogEventLevel restrictedToMinimumLevel     = LevelAlias.Minimum,
            IFormatProvider formatProvider             = null,
            ColumnOptions columnOptions                = null,
            IConfigurationSection columnOptionsSection = null,
            ITextFormatter logEventFormatter           = null,
            IConfigurationSection sinkOptionsSection   = null)
        {
            if (loggerConfiguration == null)
            {
                throw new ArgumentNullException(nameof(loggerConfiguration));
            }

            ReadConfiguration(ref connectionString, ref sinkOptions, appConfiguration, ref columnOptions,
                              columnOptionsSection, sinkOptionsSection);

            IMSSqlServerSinkFactory sinkFactory = new MSSqlServerSinkFactory();
            var sink = sinkFactory.Create(connectionString, sinkOptions, formatProvider, columnOptions, logEventFormatter);

            return(loggerConfiguration.Sink(sink, restrictedToMinimumLevel));
        }
 private void CreateTable(SinkOptions sinkOptions, SinkDependencies sinkDependencies)
 {
     if (sinkOptions.AutoCreateSqlTable)
     {
         sinkDependencies.SqlTableCreator.CreateTable(_eventTable);
     }
 }
示例#12
0
 private void ReadTableOptions(MSSqlServerConfigurationSection config, SinkOptions sinkOptions)
 {
     SetProperty.IfProvided <string>(config.TableName, nameof(config.TableName.Value), value => sinkOptions.TableName    = value);
     SetProperty.IfProvided <string>(config.SchemaName, nameof(config.SchemaName.Value), value => sinkOptions.SchemaName = value);
     SetProperty.IfProvided <bool>(config.AutoCreateSqlTable, nameof(config.AutoCreateSqlTable.Value),
                                   value => sinkOptions.AutoCreateSqlTable = value);
 }
        public void MSSqlServerAuditCallsSinkFactoryWithSinkOptionsFromMicrosoftConfigExtensions()
        {
            // Arrange
            var configSinkOptions      = new SinkOptions();
            var sinkOptionsSectionMock = new Mock <IConfigurationSection>();

            _applyMicrosoftExtensionsConfigurationMock.Setup(c => c.ConfigureSinkOptions(It.IsAny <SinkOptions>(), It.IsAny <IConfigurationSection>()))
            .Returns(configSinkOptions);
            var auditSinkFactoryMock = new Mock <IMSSqlServerAuditSinkFactory>();

            // Act
            _loggerConfiguration.AuditTo.MSSqlServerInternal(
                connectionString: "TestConnectionString",
                sinkOptions: new SinkOptions {
                TableName = "TestTableName"
            },
                sinkOptionsSection: sinkOptionsSectionMock.Object,
                applySystemConfiguration: _applySystemConfigurationMock.Object,
                applyMicrosoftExtensionsConfiguration: _applyMicrosoftExtensionsConfigurationMock.Object,
                auditSinkFactory: auditSinkFactoryMock.Object);

            // Assert
            auditSinkFactoryMock.Verify(f => f.Create(It.IsAny <string>(), configSinkOptions, It.IsAny <IFormatProvider>(),
                                                      It.IsAny <Serilog.Sinks.MSSqlServer.ColumnOptions>(), It.IsAny <ITextFormatter>()), Times.Once);
        }
示例#14
0
 /// <summary>
 /// Construct a sink posting to the specified database.
 /// </summary>
 /// <param name="connectionString">Connection string to access the database.</param>
 /// <param name="sinkOptions">Supplies additional options for the sink</param>
 /// <param name="formatProvider">Supplies culture-specific formatting information, or null.</param>
 /// <param name="columnOptions">Options that pertain to columns</param>
 /// <param name="logEventFormatter">Supplies custom formatter for the LogEvent column, or null</param>
 public MSSqlServerSink(
     string connectionString,
     SinkOptions sinkOptions,
     IFormatProvider formatProvider   = null,
     ColumnOptions columnOptions      = null,
     ITextFormatter logEventFormatter = null)
     : this(sinkOptions, SinkDependenciesFactory.Create(connectionString, sinkOptions, formatProvider, columnOptions, logEventFormatter))
 {
 }
 private static void CreateTable(SinkOptions sinkOptions, SinkDependencies sinkDependencies)
 {
     if (sinkOptions.AutoCreateSqlTable)
     {
         using (var eventTable = sinkDependencies.DataTableCreator.CreateDataTable())
         {
             sinkDependencies.SqlTableCreator.CreateTable(eventTable);
         }
     }
 }
示例#16
0
        public void InitializesDefaultedPropertiesWithDefaultsWhenCalledWithParameters()
        {
            // Act
            var sut = new SinkOptions("TestTableName", null, null, true, null);

            // Assert
            Assert.Equal(MSSqlServerSink.DefaultSchemaName, sut.SchemaName);
            Assert.Equal(MSSqlServerSink.DefaultBatchPostingLimit, sut.BatchPostingLimit);
            Assert.Equal(MSSqlServerSink.DefaultPeriod, sut.BatchPeriod);
        }
        private static void ValidateParameters(SinkOptions sinkOptions, ColumnOptions columnOptions)
        {
            if (sinkOptions?.TableName == null)
            {
                throw new InvalidOperationException("Table name must be specified!");
            }

            if (columnOptions.DisableTriggers)
            {
                throw new NotSupportedException($"The {nameof(ColumnOptions.DisableTriggers)} option is not supported for auditing.");
            }
        }
        // Internal constructor with injectable dependencies for better testability
        internal MSSqlServerAuditSink(
            SinkOptions sinkOptions,
            ColumnOptions columnOptions,
            SinkDependencies sinkDependencies)
        {
            ValidateParameters(sinkOptions, columnOptions);
            CheckSinkDependencies(sinkDependencies);

            _sqlLogEventWriter = sinkDependencies.SqlLogEventWriter;

            CreateTable(sinkOptions, sinkDependencies);
        }
示例#19
0
 public MSSqlServerSink Create(
     string connectionString,
     SinkOptions sinkOptions,
     IFormatProvider formatProvider,
     ColumnOptions columnOptions,
     ITextFormatter logEventFormatter) =>
 new MSSqlServerSink(
     connectionString,
     sinkOptions,
     formatProvider,
     columnOptions,
     logEventFormatter);
示例#20
0
        // Internal constructor with injectable dependencies for better testability
        internal MSSqlServerSink(
            SinkOptions sinkOptions,
            SinkDependencies sinkDependencies)
            : base(sinkOptions?.BatchPostingLimit ?? DefaultBatchPostingLimit, sinkOptions?.BatchPeriod ?? DefaultPeriod)
        {
            ValidateParameters(sinkOptions);
            CheckSinkDependencies(sinkDependencies);

            _sqlBulkBatchWriter = sinkDependencies.SqlBulkBatchWriter;
            _eventTable         = sinkDependencies.DataTableCreator.CreateDataTable();

            CreateTable(sinkOptions, sinkDependencies);
        }
        public SinkOptions ConfigureSinkOptions(SinkOptions sinkOptions, IConfigurationSection config)
        {
            if (config == null)
            {
                return(sinkOptions);
            }

            ReadTableOptions(config, sinkOptions);
            ReadBatchSettings(config, sinkOptions);
            ReadAzureManagedIdentitiesOptions(config, sinkOptions);

            return(sinkOptions);
        }
示例#22
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            //services.AddCors();
            services.AddControllers()
            .AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore)
            .AddFluentValidation();

            services.AddDbContext <ShopContext>(x => x.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            services.AddScoped <IUnitOfWork, UnitOfWork>();

            services.AddScoped <ICustomerRepository, CustomerRepository>();
            services.AddScoped <IOrderRepository, OrderRepository>();
            services.AddScoped <IProductRepository, ProductRepository>();



            services.AddTransient <IValidator <CustomerUpdateDto>, CustomerUpdateValidator>();

            services.AddApplication();

            services.AddAuth().AddSwaggerAuth();

            services.AddCors(confg =>
                             confg.AddPolicy("AllowAll",
                                             p => p.AllowAnyOrigin()
                                             .AllowAnyMethod()
                                             .AllowAnyHeader()));

            services.AddSingleton <Serilog.ILogger>(x => {
                var connectionString = Configuration["Serilog:DefaultConnection"];
                var tableName        = Configuration["Serilog:TableName"];

                var sqlLoggerOptions = new SinkOptions
                {
                    AutoCreateSqlTable = true,
                    SchemaName         = "Logger",
                    TableName          = tableName,
                    BatchPostingLimit  = 1
                };

                return(new LoggerConfiguration()
                       .MinimumLevel.Debug()
                       .WriteTo.MSSqlServer(connectionString, sqlLoggerOptions)
                       .CreateLogger());
            });

            //Infra
            //Domain
        }
示例#23
0
        public void InitializeWithDisableTriggersThrows()
        {
            // Arrange
            var sinkOptions = new SinkOptions {
                TableName = "TestTableName"
            };
            var columnOptions = new Serilog.Sinks.MSSqlServer.ColumnOptions {
                DisableTriggers = true
            };

            // Act + assert
            Assert.Throws <NotSupportedException>(() =>
                                                  new MSSqlServerAuditSink(sinkOptions, columnOptions, _sinkDependencies));
        }
示例#24
0
        public void ConfigureSinkOptionsCalledWithConfigSectionNullReturnsUnchangedSinkOptions()
        {
            // Arrange
            var sinkOptions = new SinkOptions {
                UseAzureManagedIdentity = true
            };
            var sut = new MicrosoftExtensionsSinkOptionsProvider();

            // Act
            var result = sut.ConfigureSinkOptions(sinkOptions, null);

            // Assert
            Assert.True(result.UseAzureManagedIdentity);
        }
        private static void ReadConfiguration(
            ref string connectionString,
            ref SinkOptions sinkOptions,
            IConfiguration appConfiguration,
            ref ColumnOptions columnOptions,
            IConfigurationSection columnOptionsSection,
            IConfigurationSection sinkOptionsSection)
        {
            sinkOptions   = sinkOptions ?? new SinkOptions();
            columnOptions = columnOptions ?? new ColumnOptions();

            IApplyMicrosoftExtensionsConfiguration microsoftExtensionsConfiguration = new ApplyMicrosoftExtensionsConfiguration();

            connectionString = microsoftExtensionsConfiguration.GetConnectionString(connectionString, appConfiguration);
            columnOptions    = microsoftExtensionsConfiguration.ConfigureColumnOptions(columnOptions, columnOptionsSection);
            sinkOptions      = microsoftExtensionsConfiguration.ConfigureSinkOptions(sinkOptions, sinkOptionsSection);
        }
示例#26
0
 /// <summary>
 /// Adds a sink that writes log events to a table in a MSSqlServer database.
 /// Create a database and execute the table creation script found here
 /// https://gist.github.com/mivano/10429656
 /// or use the autoCreateSqlTable option.
 /// </summary>
 /// <param name="loggerAuditSinkConfiguration">The logger configuration.</param>
 /// <param name="connectionString">The connection string to the database where to store the events.</param>
 /// <param name="sinkOptions">Supplies additional settings for the sink</param>
 /// <param name="restrictedToMinimumLevel">The minimum log event level required in order to write an event to the sink.</param>
 /// <param name="formatProvider">Supplies culture-specific formatting information, or null.</param>
 /// <param name="columnOptions"></param>
 /// <param name="logEventFormatter">Supplies custom formatter for the LogEvent column, or null</param>
 /// <returns>Logger configuration, allowing configuration to continue.</returns>
 /// <exception cref="ArgumentNullException">A required parameter is null.</exception>
 public static LoggerConfiguration MSSqlServer(
     this LoggerAuditSinkConfiguration loggerAuditSinkConfiguration,
     string connectionString,
     SinkOptions sinkOptions = null,
     LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum,
     IFormatProvider formatProvider         = null,
     ColumnOptions columnOptions            = null,
     ITextFormatter logEventFormatter       = null) =>
 loggerAuditSinkConfiguration.MSSqlServerInternal(
     configSectionName: AppConfigSectionName,
     connectionString: connectionString,
     sinkOptions: sinkOptions,
     restrictedToMinimumLevel: restrictedToMinimumLevel,
     formatProvider: formatProvider,
     columnOptions: columnOptions,
     logEventFormatter: logEventFormatter,
     applySystemConfiguration: new ApplySystemConfiguration(),
     auditSinkFactory: new MSSqlServerAuditSinkFactory());
示例#27
0
        public void InitializesPropertiesWithParameterValues()
        {
            // Arrange
            const string tableName         = "TestTableName";
            const int    batchPostingLimit = 23;
            const string schemaName        = "TestSchemaName";
            var          batchPeriod       = new TimeSpan(0, 3, 23);

            // Act
            var sut = new SinkOptions(tableName, batchPostingLimit, batchPeriod, true, schemaName);

            // Assert
            Assert.Equal(tableName, sut.TableName);
            Assert.Equal(batchPostingLimit, sut.BatchPostingLimit);
            Assert.Equal(batchPeriod, sut.BatchPeriod);
            Assert.True(sut.AutoCreateSqlTable);
            Assert.Equal(schemaName, sut.SchemaName);
        }
示例#28
0
        public void ConfigureSinkOptionsCallsAttachedSinkOptionsProvider()
        {
            // Arrange
            var inputConfigSection      = new MSSqlServerConfigurationSection();
            var inputSinkOptions        = new SinkOptions();
            var expectedResult          = new SinkOptions();
            var sinkOptionsProviderMock = new Mock <ISystemConfigurationSinkOptionsProvider>();

            sinkOptionsProviderMock.Setup(p => p.ConfigureSinkOptions(It.IsAny <MSSqlServerConfigurationSection>(), It.IsAny <SinkOptions>()))
            .Returns(expectedResult);
            var sut = new ApplySystemConfiguration(null, null, sinkOptionsProviderMock.Object);

            // Act
            var result = sut.ConfigureSinkOptions(inputConfigSection, inputSinkOptions);

            // Assert
            sinkOptionsProviderMock.Verify(p => p.ConfigureSinkOptions(inputConfigSection, inputSinkOptions), Times.Once);
            Assert.Same(expectedResult, result);
        }
        public void ConfigureSinkOptionsCallsAttachedSinkOptionsProvider()
        {
            // Arrange
            var inputSinkOptions         = new SinkOptions();
            var expectedResult           = new SinkOptions();
            var configurationSectionMock = new Mock <IConfigurationSection>();
            var sinkOptionsProviderMock  = new Mock <IMicrosoftExtensionsSinkOptionsProvider>();

            sinkOptionsProviderMock.Setup(p => p.ConfigureSinkOptions(It.IsAny <SinkOptions>(), It.IsAny <IConfigurationSection>()))
            .Returns(expectedResult);
            var sut = new ApplyMicrosoftExtensionsConfiguration(null, null, sinkOptionsProviderMock.Object);

            // Act
            var result = sut.ConfigureSinkOptions(inputSinkOptions, configurationSectionMock.Object);

            // Assert
            sinkOptionsProviderMock.Verify(p => p.ConfigureSinkOptions(inputSinkOptions, configurationSectionMock.Object), Times.Once);
            Assert.Same(expectedResult, result);
        }
        private static void ReadConfiguration(
            ref string connectionString,
            ref SinkOptions sinkOptions,
            IConfigurationSection sinkOptionsSection,
            IConfiguration appConfiguration,
            ref ColumnOptions columnOptions,
            IConfigurationSection columnOptionsSection,
            IApplySystemConfiguration applySystemConfiguration,
            IApplyMicrosoftExtensionsConfiguration applyMicrosoftExtensionsConfiguration)
        {
            sinkOptions   = sinkOptions ?? new SinkOptions();
            columnOptions = columnOptions ?? new ColumnOptions();

            var serviceConfigSection = applySystemConfiguration.GetSinkConfigurationSection(AppConfigSectionName);

            if (serviceConfigSection != null)
            {
                connectionString = applySystemConfiguration.GetConnectionString(connectionString);
                columnOptions    = applySystemConfiguration.ConfigureColumnOptions(serviceConfigSection, columnOptions);
                sinkOptions      = applySystemConfiguration.ConfigureSinkOptions(serviceConfigSection, sinkOptions);

                if (appConfiguration != null || columnOptionsSection != null || sinkOptionsSection != null)
                {
                    SelfLog.WriteLine("Warning: Both System.Configuration (app.config or web.config) and Microsoft.Extensions.Configuration are being applied to the MSSQLServer sink.");
                }
            }

            if (appConfiguration != null)
            {
                connectionString = applyMicrosoftExtensionsConfiguration.GetConnectionString(connectionString, appConfiguration);
            }

            if (columnOptionsSection != null)
            {
                columnOptions = applyMicrosoftExtensionsConfiguration.ConfigureColumnOptions(columnOptions, columnOptionsSection);
            }

            if (sinkOptionsSection != null)
            {
                sinkOptions = applyMicrosoftExtensionsConfiguration.ConfigureSinkOptions(sinkOptions, sinkOptionsSection);
            }
        }