public void ShouldRaiseFlushFailedOnFlushAsyncWhenEventHubClientFails() { var eventHubClient = Substitute.For <IEventHubClient>(); using (var sink = new EventHubAmqpSink(eventHubClient, Buffering.DefaultBufferingInterval, Buffering.DefaultBufferingCount, Buffering.DefaultMaxBufferSize, TimeSpan.Zero)) using (var collectErrorsListener = new MockEventListener()) { collectErrorsListener.EnableEvents(SemanticLoggingEventSource.Log, EventLevel.Error, Keywords.All); eventHubClient.When(client => client.SendBatchAsync(Arg.Any <IEnumerable <EventData> >())) .Do(action => { throw new Exception(); }); sink.OnNext(EventEntryTestHelper.Create()); try { sink.FlushAsync().Wait(); Assert.Fail("AggregateException should be thrown."); } catch (AggregateException ex) { Assert.IsInstanceOfType(ex.InnerException, typeof(FlushFailedException)); } Assert.IsTrue(collectErrorsListener.WrittenEntries.Any(x => x.EventId == 1)); } }
public void ShouldRaiseFlushFailedOnFlushAsyncWhenEventHubClientFails() { var eventHubClient = Substitute.For<IEventHubClient>(); using (var sink = new EventHubAmqpSink(eventHubClient, Buffering.DefaultBufferingInterval, Buffering.DefaultBufferingCount, Buffering.DefaultMaxBufferSize, TimeSpan.Zero)) using (var collectErrorsListener = new MockEventListener()) { collectErrorsListener.EnableEvents(SemanticLoggingEventSource.Log, EventLevel.Error, Keywords.All); eventHubClient.When(client => client.SendBatchAsync(Arg.Any<IEnumerable<EventData>>())) .Do(action => { throw new Exception(); }); sink.OnNext(EventEntryTestHelper.Create()); try { sink.FlushAsync().Wait(); Assert.Fail("AggregateException should be thrown."); } catch (AggregateException ex) { Assert.IsInstanceOfType(ex.InnerException, typeof(FlushFailedException)); } Assert.IsTrue(collectErrorsListener.WrittenEntries.Any(x => x.EventId == 1)); } }
public async Task ShouldWriteEntriesOnFlushAsync() { var eventHubClient = Substitute.For<IEventHubClient>(); using (var sink = new EventHubAmqpSink(eventHubClient, Buffering.DefaultBufferingInterval, Buffering.DefaultBufferingCount, Buffering.DefaultMaxBufferSize, TimeSpan.Zero)) { sink.OnNext(EventEntryTestHelper.Create()); sink.OnNext(EventEntryTestHelper.Create()); await sink.FlushAsync(); } eventHubClient.Received().SendBatchAsync(Arg.Is<IEnumerable<EventData>>(l => l.Count() == 2)).Wait(); }
/// <summary> /// Subscribes to an <see cref="IObservable{EventEntry}" /> using a <see cref="EventHubAmqpSink" />. /// </summary> /// <param name="eventStream">The event stream. Typically this is an instance of <see cref="ObservableEventListener" />.</param> /// <param name="eventHubConnectionString">The connection string for the eventhub.</param> /// <param name="eventHubName">The name of the eventhub.</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="EventHubAmqpSink.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 EventHub 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> /// <param name="partitionKey">PartitionKey is optional. If no partition key is supplied the log messages are sent to eventhub /// and distributed to various partitions in a round robin manner.</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<EventHubAmqpSink> LogToEventHubUsingAmqp(this IObservable<EventEntry> eventStream, string eventHubConnectionString, string eventHubName, TimeSpan? bufferingInterval = null, int bufferingCount = Buffering.DefaultBufferingCount, TimeSpan? onCompletedTimeout = null, int maxBufferSize = Buffering.DefaultMaxBufferSize, string partitionKey = null) { var sink = new EventHubAmqpSink( eventHubConnectionString, eventHubName, bufferingInterval ?? Buffering.DefaultBufferingInterval, bufferingCount, maxBufferSize, onCompletedTimeout ?? Timeout.InfiniteTimeSpan, partitionKey); var subscription = eventStream.Subscribe(sink); return new SinkSubscription<EventHubAmqpSink>(subscription, sink); }
public async Task ShouldWriteEntriesOnFlushAsync() { var eventHubClient = Substitute.For <IEventHubClient>(); using (var sink = new EventHubAmqpSink(eventHubClient, Buffering.DefaultBufferingInterval, Buffering.DefaultBufferingCount, Buffering.DefaultMaxBufferSize, TimeSpan.Zero)) { sink.OnNext(EventEntryTestHelper.Create()); sink.OnNext(EventEntryTestHelper.Create()); await sink.FlushAsync(); } eventHubClient.Received().SendBatchAsync(Arg.Is <IEnumerable <EventData> >(l => l.Count() == 2)).Wait(); }
public async Task ShouldWritePartitionKey() { var eventHubClient = Substitute.For <IEventHubClient>(); var entry = EventEntryTestHelper.Create(); const string partitionKey = "PartitionKey"; using (var sink = new EventHubAmqpSink(eventHubClient, Buffering.DefaultBufferingInterval, Buffering.DefaultBufferingCount, Buffering.DefaultMaxBufferSize, TimeSpan.Zero, partitionKey)) { sink.OnNext(entry); await sink.FlushAsync(); } eventHubClient.Received().SendBatchAsync(Arg.Is <IEnumerable <EventData> >(l => l.First().PartitionKey == partitionKey)).Wait(); }
public void ShouldNotStallOrThrowWhenEventHubClientFails() { var eventHubClient = Substitute.For<IEventHubClient>(); using (var sink = new EventHubAmqpSink(eventHubClient, Buffering.DefaultBufferingInterval, Buffering.DefaultBufferingCount, Buffering.DefaultMaxBufferSize, TimeSpan.Zero)) using (var collectErrorsListener = new MockEventListener()) { collectErrorsListener.EnableEvents(SemanticLoggingEventSource.Log, EventLevel.Error, Keywords.All); eventHubClient.When(client => client.SendBatchAsync(Arg.Any<IEnumerable<EventData>>())) .Do(action => { throw new Exception(); }); sink.OnNext(EventEntryTestHelper.Create()); Assert.IsTrue(Task.Run(() => sink.OnCompleted()).Wait(TimeSpan.FromSeconds(5))); Assert.IsTrue(collectErrorsListener.WrittenEntries.Any(x => x.EventId == 1)); } }
public async Task ShouldWriteProperties() { var eventHubClient = Substitute.For <IEventHubClient>(); var entry = EventEntryTestHelper.Create(); using (var sink = new EventHubAmqpSink(eventHubClient, Buffering.DefaultBufferingInterval, Buffering.DefaultBufferingCount, Buffering.DefaultMaxBufferSize, TimeSpan.Zero)) { sink.OnNext(entry); await sink.FlushAsync(); } var byteRepresentation = Encoding.Default.GetBytes(JsonConvert.SerializeObject(entry)); eventHubClient.Received().SendBatchAsync(Arg.Is <IEnumerable <EventData> >(l => byteRepresentation.SequenceEqual(l.First().GetBytes()))).Wait(); }
public void ShouldNotStallOrThrowWhenEventHubClientFails() { var eventHubClient = Substitute.For <IEventHubClient>(); using (var sink = new EventHubAmqpSink(eventHubClient, Buffering.DefaultBufferingInterval, Buffering.DefaultBufferingCount, Buffering.DefaultMaxBufferSize, TimeSpan.Zero)) using (var collectErrorsListener = new MockEventListener()) { collectErrorsListener.EnableEvents(SemanticLoggingEventSource.Log, EventLevel.Error, Keywords.All); eventHubClient.When(client => client.SendBatchAsync(Arg.Any <IEnumerable <EventData> >())) .Do(action => { throw new Exception(); }); sink.OnNext(EventEntryTestHelper.Create()); Assert.IsTrue(Task.Run(() => sink.OnCompleted()).Wait(TimeSpan.FromSeconds(5))); Assert.IsTrue(collectErrorsListener.WrittenEntries.Any(x => x.EventId == 1)); } }
public async Task ShouldWriteProperties() { var eventHubClient = Substitute.For<IEventHubClient>(); var entry = EventEntryTestHelper.Create(); using (var sink = new EventHubAmqpSink(eventHubClient, Buffering.DefaultBufferingInterval, Buffering.DefaultBufferingCount, Buffering.DefaultMaxBufferSize, TimeSpan.Zero)) { sink.OnNext(entry); await sink.FlushAsync(); } var byteRepresentation = Encoding.Default.GetBytes(JsonConvert.SerializeObject(entry)); eventHubClient.Received().SendBatchAsync(Arg.Is<IEnumerable<EventData>>(l => byteRepresentation.SequenceEqual(l.First().GetBytes()))).Wait(); }
public async Task ShouldWritePartitionKey() { var eventHubClient = Substitute.For<IEventHubClient>(); var entry = EventEntryTestHelper.Create(); const string partitionKey = "PartitionKey"; using (var sink = new EventHubAmqpSink(eventHubClient, Buffering.DefaultBufferingInterval, Buffering.DefaultBufferingCount, Buffering.DefaultMaxBufferSize, TimeSpan.Zero, partitionKey)) { sink.OnNext(entry); await sink.FlushAsync(); } eventHubClient.Received().SendBatchAsync(Arg.Is<IEnumerable<EventData>>(l => l.First().PartitionKey == partitionKey)).Wait(); }