protected override void Given() { base.Given(); this.sink = new SqlDatabaseSink(InstanceName, this.GetSqlConnectionString(), SqlDatabaseLog.DefaultTableName, Buffering.DefaultBufferingInterval, NumberOfEntries, Buffering.DefaultMaxBufferSize, Timeout.InfiniteTimeSpan); this.collectErrorsListener = new MockEventListener(); this.collectErrorsListener.EnableEvents(SemanticLoggingEventSource.Log, EventLevel.Error, Keywords.All); }
public SinLog() { BlockEventListener.EnableEvents(SemanticLoggingEventSource.Log, EventLevel.LogAlways, EventKeywords.All); BlockEventListener.LogToSqlDatabase("System", Settings.ConnectionString); Listener.EnableEvents("SIN", EventLevel.LogAlways, EventKeywords.All); _sink = Listener.LogToSqlDatabase(Settings.InstanceName, Settings.ConnectionString).Sink; #if DEBUG Listener.LogToConsole(); #endif }
protected override void Given() { base.Given(); this.sink = new SqlDatabaseSink( "TestInstanceName", this.GetSqlConnectionString(), SqlDatabaseLog.DefaultTableName, TimeSpan.FromMinutes(1), BufferingCount, Buffering.DefaultMaxBufferSize, Timeout.InfiniteTimeSpan); }
/// <summary> /// Subscribes to an <see cref="IObservable{EventEntry}"/> using a <see cref="SqlDatabaseSink"/>. /// </summary> /// <param name="eventStream">The event stream. Typically this is an instance of <see cref="ObservableEventListener" />.</param> /// <param name="instanceName">The name of the instance originating the entries.</param> /// <param name="connectionString">The connection string.</param> /// <param name="tableName">The name of the table.</param> /// <param name="bufferingInterval">The buffering interval between each batch publishing. Default value is <see cref="Buffering.DefaultBufferingInterval"/>.</param> /// <param name="bufferingCount">The number of entries that will trigger a batch publishing.</param> /// <param name="onCompletedTimeout">Defines a timeout interval for when flushing the entries after an <see cref="SqlDatabaseSink.OnCompleted"/> call is received and before disposing the sink. /// This means that if the timeout period elapses, some event entries will be dropped and not sent to the store. Normally, calling <see cref="IDisposable.Dispose"/> on /// the <see cref="System.Diagnostics.Tracing.EventListener"/> will block until all the entries are flushed or the interval elapses. /// If <see langword="null"/> is specified, then the call will block indefinitely until the flush operation finishes.</param> /// <param name="maxBufferSize">The maximum number of entries that can be buffered while it's sending to SQL Database before the sink starts dropping entries. /// This means that if the timeout period elapses, some event entries will be dropped and not sent to the store. Normally, calling <see cref="IDisposable.Dispose" /> on /// the <see cref="System.Diagnostics.Tracing.EventListener" /> will block until all the entries are flushed or the interval elapses. /// If <see langword="null" /> is specified, then the call will block indefinitely until the flush operation finishes.</param> /// <returns>A subscription to the sink that can be disposed to unsubscribe the sink and dispose it, or to get access to the sink instance.</returns> public static SinkSubscription <SqlDatabaseSink> LogToSqlDatabase(this IObservable <EventEntry> eventStream, string instanceName, string connectionString, string tableName = DefaultTableName, TimeSpan?bufferingInterval = null, int bufferingCount = Buffering.DefaultBufferingCount, TimeSpan?onCompletedTimeout = null, int maxBufferSize = Buffering.DefaultMaxBufferSize) { var sink = new SqlDatabaseSink( instanceName, connectionString, tableName, bufferingInterval ?? Buffering.DefaultBufferingInterval, bufferingCount, maxBufferSize, onCompletedTimeout ?? Timeout.InfiniteTimeSpan); var subscription = eventStream.Subscribe(sink); return(new SinkSubscription <SqlDatabaseSink>(subscription, sink)); }
public void when_cannot_connect_to_database_then_on_completed_should_not_stall_or_throw() { const string ValidNotExisting = @"Data Source=(localdb)\v11.0; AttachDBFilename='|DataDirectory|\DoesNotExist.mdf';Initial Catalog=SemanticLoggingTests;Integrated Security=True"; using (var sink = new SqlDatabaseSink("test", ValidNotExisting, "tableName", Buffering.DefaultBufferingInterval, Buffering.DefaultBufferingCount, Buffering.DefaultMaxBufferSize, TimeSpan.FromSeconds(20))) using (var collectErrorsListener = new MockEventListener()) { collectErrorsListener.EnableEvents(SemanticLoggingEventSource.Log, EventLevel.Error, Keywords.All); var closure = sink; closure.OnNext(EventEntryTestHelper.Create()); Assert.IsTrue(Task.Run(() => closure.OnCompleted()).Wait(TimeSpan.FromSeconds(5))); Assert.IsTrue(collectErrorsListener.WrittenEntries.Any(x => x.EventId == 101)); } }
/// <summary> /// Subscribes to an <see cref="IObservable{EventEntry}"/> using a <see cref="SqlDatabaseSink"/>. /// </summary> /// <param name="eventStream">The event stream. Typically this is an instance of <see cref="ObservableEventListener" />.</param> /// <param name="instanceName">The name of the instance originating the entries.</param> /// <param name="connectionString">The connection string.</param> /// <param name="tableName">The name of the table.</param> /// <param name="bufferingInterval">The buffering interval between each batch publishing. Default value is <see cref="Buffering.DefaultBufferingInterval"/>.</param> /// <param name="bufferingCount">The number of entries that will trigger a batch publishing.</param> /// <param name="onCompletedTimeout">Defines a timeout interval for when flushing the entries after an <see cref="SqlDatabaseSink.OnCompleted"/> call is received and before disposing the sink. /// This means that if the timeout period elapses, some event entries will be dropped and not sent to the store. Normally, calling <see cref="IDisposable.Dispose"/> on /// the <see cref="System.Diagnostics.Tracing.EventListener"/> will block until all the entries are flushed or the interval elapses. /// If <see langword="null"/> is specified, then the call will block indefinitely until the flush operation finishes.</param> /// <param name="maxBufferSize">The maximum number of entries that can be buffered while it's sending to Windows Azure Storage before the sink starts dropping entries. /// This means that if the timeout period elapses, some event entries will be dropped and not sent to the store. Normally, calling <see cref="IDisposable.Dispose" /> on /// the <see cref="System.Diagnostics.Tracing.EventListener" /> will block until all the entries are flushed or the interval elapses. /// If <see langword="null" /> is specified, then the call will block indefinitely until the flush operation finishes.</param> /// <returns>A subscription to the sink that can be disposed to unsubscribe the sink and dispose it, or to get access to the sink instance.</returns> public static SinkSubscription<SqlDatabaseSink> LogToSqlDatabase(this IObservable<EventEntry> eventStream, string instanceName, string connectionString, string tableName = DefaultTableName, TimeSpan? bufferingInterval = null, int bufferingCount = Buffering.DefaultBufferingCount, TimeSpan? onCompletedTimeout = null, int maxBufferSize = Buffering.DefaultMaxBufferSize) { var sink = new SqlDatabaseSink( instanceName, connectionString, tableName, bufferingInterval ?? Buffering.DefaultBufferingInterval, bufferingCount, maxBufferSize, onCompletedTimeout ?? Timeout.InfiniteTimeSpan); var subscription = eventStream.SubscribeWithConversion(sink); return new SinkSubscription<SqlDatabaseSink>(subscription, sink); }
public void when_cannot_connect_to_database_then_on_completed_should_not_stall_or_throw() { const string validNotExisting = @"Data Source=(localdb)\v11.0; AttachDBFilename='|DataDirectory|\DoesNotExist.mdf';Initial Catalog=SemanticLoggingTests;Integrated Security=True"; using (var sink = new SqlDatabaseSink("test", validNotExisting, "tableName", Buffering.DefaultBufferingInterval, Buffering.DefaultBufferingCount, Buffering.DefaultMaxBufferSize, TimeSpan.FromSeconds(20))) using (var collectErrorsListener = new MockEventListener()) { collectErrorsListener.EnableEvents(SemanticLoggingEventSource.Log, EventLevel.Error, Keywords.All); sink.OnNext(new EventRecord()); Assert.IsTrue(Task.Run(() => sink.OnCompleted()).Wait(TimeSpan.FromSeconds(5))); Assert.IsTrue(collectErrorsListener.WrittenEntries.Any(x => x.EventId == 101)); } }
public void when_cannot_connect_to_database_then_flush_should_finish_faulted() { const string ValidNotExisting = @"Data Source=(localdb)\v11.0; AttachDBFilename='|DataDirectory|\DoesNotExist.mdf';Initial Catalog=SemanticLoggingTests;Integrated Security=True"; using (var sink = new SqlDatabaseSink("test", ValidNotExisting, "tableName", Buffering.DefaultBufferingInterval, Buffering.DefaultBufferingCount, Buffering.DefaultMaxBufferSize, TimeSpan.FromSeconds(20))) using (var collectErrorsListener = new MockEventListener()) { collectErrorsListener.EnableEvents(SemanticLoggingEventSource.Log, EventLevel.Error, Keywords.All); sink.OnNext(EventEntryTestHelper.Create()); try { Assert.IsTrue(sink.FlushAsync().Wait(TimeSpan.FromSeconds(5))); Assert.Fail("Exception should be thrown."); } catch (AggregateException ex) { Assert.IsInstanceOfType(ex.InnerException, typeof(FlushFailedException)); } Assert.IsTrue(collectErrorsListener.WrittenEntries.Any(x => x.EventId == 101)); } }
public void when_cannot_connect_to_database_then_flush_should_finish_faulted() { const string ValidNotExisting = @"Data Source=(localdb)\MSSQLLocalDB; AttachDBFilename='|DataDirectory|\DoesNotExist.mdf';Initial Catalog=SemanticLoggingTests;Integrated Security=True"; using (var sink = new SqlDatabaseSink("test", ValidNotExisting, "tableName", "storedProcedureName", Buffering.DefaultBufferingInterval, Buffering.DefaultBufferingCount, Buffering.DefaultMaxBufferSize, TimeSpan.FromSeconds(20))) using (var collectErrorsListener = new MockEventListener()) { collectErrorsListener.EnableEvents(SemanticLoggingEventSource.Log, EventLevel.Error, Keywords.All); sink.OnNext(EventEntryTestHelper.Create()); try { Assert.IsTrue(sink.FlushAsync().Wait(TimeSpan.FromSeconds(5))); Assert.Fail("Exception should be thrown."); } catch (AggregateException ex) { Assert.IsInstanceOfType(ex.InnerException, typeof(FlushFailedException)); } Assert.IsTrue(collectErrorsListener.WrittenEntries.Any(x => x.EventId == 101)); } }
public void when_cannot_connect_to_database_then_flush_should_finish_faulted() { const string ValidNotExisting = @"Data Source=(localdb)\v11.0; AttachDBFilename='|DataDirectory|\DoesNotExist.mdf';Initial Catalog=SemanticLoggingTests;Integrated Security=True"; using (var sink = new SqlDatabaseSink("test", ValidNotExisting, "tableName", Buffering.DefaultBufferingInterval, Buffering.DefaultBufferingCount, Buffering.DefaultMaxBufferSize, TimeSpan.FromSeconds(20))) using (var collectErrorsListener = new MockEventListener()) { collectErrorsListener.EnableEvents(SemanticLoggingEventSource.Log, EventLevel.Error, Keywords.All); sink.OnNext(EventEntryTestHelper.Create()); //ERH 6.26.2015: there is volatility around the delay when under load; the longer the delay the more likely the test will pass. // This probably indicates some kind of missed case or a bad assumption about the underlying implementation const int waitTimeInSeconds = 10; try { Assert.IsTrue(sink.FlushAsync().Wait(TimeSpan.FromSeconds(waitTimeInSeconds))); Assert.Fail("Exception should be thrown."); } catch (AggregateException ex) { Console.WriteLine(ex.GetType()); Assert.IsNotNull(ex.InnerException, "ex.InnerException != null"); Console.WriteLine(ex.InnerException.GetType()); Assert.IsInstanceOfType(ex.InnerException, typeof(FlushFailedException), "exception should be of type FlushFailedException"); } Assert.IsTrue( collectErrorsListener.WrittenEntries.Any( x => x.EventId == 101 ), "should have entries for eventid 101" ); } }