// Ignoring because the storage client library considers inexistant account as transient so it retries and the exponential back-off could take time public void when_cannot_connect_to_storage_account_then_on_completed_should_not_stall_or_throw() { const string ValidNotExisting = "DefaultEndpointsProtocol=https;AccountName=InexistantDoesntReallyMatter;AccountKey=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=="; using (var sink = new WindowsAzureTableSink("instanceName", ValidNotExisting, "Table", TimeSpan.FromSeconds(1), 5000, TimeSpan.FromSeconds(20))) using (var collectErrorsListener = new MockEventListener()) { collectErrorsListener.EnableEvents(SemanticLoggingEventSource.Log, EventLevel.Error, Keywords.All); sink.OnNext(new CloudEventEntry(EventEntryTestHelper.Create())); Assert.IsTrue(Task.Run(() => sink.OnCompleted()).Wait(TimeSpan.FromSeconds(15))); Assert.IsTrue(collectErrorsListener.WrittenEntries.Any(x => x.EventId == 500)); } }
/// <summary> /// Subscribes to an <see cref="IObservable{EventEntry}" /> using a <see cref="WindowsAzureTableSink" />. /// </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 for the storage account.</param> /// <param name="tableAddress">Either the name of the table, or the absolute URI to the table.</param> /// <param name="bufferingInterval">The buffering interval between each batch publishing. Default value is <see cref="Buffering.DefaultBufferingInterval" />.</param> /// <param name="sortKeysAscending">The value indicating whether to sort the row keys in ascending order.</param> /// <param name="onCompletedTimeout">Defines a timeout interval for when flushing the entries after an <see cref="WindowsAzureTableSink.OnCompleted" /> call is received and before disposing the sink.</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<WindowsAzureTableSink> LogToWindowsAzureTable(this IObservable<EventEntry> eventStream, string instanceName, string connectionString, string tableAddress = DefaultTableName, TimeSpan? bufferingInterval = null, bool sortKeysAscending = false, TimeSpan? onCompletedTimeout = null, int maxBufferSize = Buffering.DefaultMaxBufferSize) { var sink = new WindowsAzureTableSink( instanceName, connectionString, tableAddress, bufferingInterval ?? Buffering.DefaultBufferingInterval, maxBufferSize, onCompletedTimeout ?? Timeout.InfiniteTimeSpan) { SortKeysAscending = sortKeysAscending }; var subscription = eventStream.SubscribeWithConversion(sink); return new SinkSubscription<WindowsAzureTableSink>(subscription, sink); }
protected override void Arrange() { this.connectionString = ConfigurationHelper.GetSetting("StorageConnectionString"); if (string.IsNullOrEmpty(connectionString) || connectionString.Contains("[AccountName]") || connectionString.Contains("[AccountKey]")) { Assert.Inconclusive("Cannot run tests because the Windows Azure Storage credentials are not configured"); } this.account = CloudStorageAccount.Parse(connectionString); this.client = this.account.CreateCloudTableClient(); this.tableName = "AzureTableEventListenerTests" + new Random(unchecked ((int)DateTime.Now.Ticks)).Next(10000).ToString(); this.sink = new WindowsAzureTableSink(InstanceName, connectionString, tableName, TimeSpan.FromSeconds(1), 5000, Timeout.InfiniteTimeSpan); }
/// <summary> /// Subscribes to an <see cref="IObservable{EventEntry}" /> using a <see cref="WindowsAzureTableSink" />. /// </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 for the storage account.</param> /// <param name="tableAddress">Either the name of the table, or the absolute URI to the table.</param> /// <param name="bufferingInterval">The buffering interval between each batch publishing. Default value is <see cref="Buffering.DefaultBufferingInterval" />.</param> /// <param name="sortKeysAscending">The value indicating whether to sort the row keys in ascending order.</param> /// <param name="onCompletedTimeout">Defines a timeout interval for when flushing the entries after an <see cref="WindowsAzureTableSink.OnCompleted" /> call is received and before disposing the sink.</param> /// <param name="maxBufferSize">The maximum number of entries that can be buffered while it's sending to 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 <WindowsAzureTableSink> LogToWindowsAzureTable(this IObservable <EventEntry> eventStream, string instanceName, string connectionString, string tableAddress = DefaultTableName, TimeSpan?bufferingInterval = null, bool sortKeysAscending = false, TimeSpan?onCompletedTimeout = null, int maxBufferSize = Buffering.DefaultMaxBufferSize) { var sink = new WindowsAzureTableSink( instanceName, connectionString, tableAddress, bufferingInterval ?? Buffering.DefaultBufferingInterval, maxBufferSize, onCompletedTimeout ?? Timeout.InfiniteTimeSpan) { SortKeysAscending = sortKeysAscending }; var subscription = eventStream.Subscribe(sink); return(new SinkSubscription <WindowsAzureTableSink>(subscription, sink)); }
protected override void Arrange() { this.connectionString = ConfigurationHelper.GetSetting("StorageConnectionString"); if (string.IsNullOrEmpty(connectionString) || connectionString.Contains("[AccountName]") || connectionString.Contains("[AccountKey]")) { Assert.Inconclusive("Cannot run tests because the Windows Azure Storage credentials are not configured"); } this.account = CloudStorageAccount.Parse(connectionString); this.client = this.account.CreateCloudTableClient(); this.tableName = "AzureTableEventListenerTests" + new Random(unchecked((int)DateTime.Now.Ticks)).Next(10000).ToString(); this.sink = new WindowsAzureTableSink(InstanceName, connectionString, tableName, TimeSpan.FromSeconds(1), 5000, Timeout.InfiniteTimeSpan); }
// Ignoring because the storage client library considers inexistant account as transient so it retries and the exponential back-off could take time public void when_cannot_connect_to_storage_account_then_flush_should_finish_faulted() { const string ValidNotExisting = "DefaultEndpointsProtocol=https;AccountName=InexistantDoesntReallyMatter;AccountKey=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=="; using (var sink = new WindowsAzureTableSink("instanceName", ValidNotExisting, "Table", TimeSpan.FromSeconds(1), 5000, TimeSpan.FromSeconds(20))) using (var collectErrorsListener = new MockEventListener()) { collectErrorsListener.EnableEvents(SemanticLoggingEventSource.Log, EventLevel.Error, Keywords.All); sink.OnNext(new CloudEventEntry(EventEntryTestHelper.Create())); try { Assert.IsTrue(sink.FlushAsync().Wait(TimeSpan.FromSeconds(15))); Assert.Fail("Exception should be thrown."); } catch (AggregateException ex) { Assert.IsInstanceOfType(ex.InnerException, typeof(FlushFailedException)); } Assert.IsTrue(collectErrorsListener.WrittenEntries.Any(x => x.EventId == 500)); } }