From 714ba9e75996605438125e8fdca1c184ce1679b7 Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Fri, 12 Jul 2019 04:40:35 -0700 Subject: [PATCH 01/21] Some test files included (a lot of changes expected). Single incomplete failing test was added as well. --- .../tests/Diagnostics/DiagnosticsCommon.cs | 36 +++++++++ .../tests/Diagnostics/DiagnosticsLiveTests.cs | 76 +++++++++++++++++++ .../tests/Diagnostics/DiagnosticsTests.cs | 14 ++++ .../Diagnostics/FakeDiagnosticListener.cs | 72 ++++++++++++++++++ 4 files changed, 198 insertions(+) create mode 100644 sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsCommon.cs create mode 100644 sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs create mode 100644 sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs create mode 100644 sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/FakeDiagnosticListener.cs diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsCommon.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsCommon.cs new file mode 100644 index 0000000000000..3d5032c9325d7 --- /dev/null +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsCommon.cs @@ -0,0 +1,36 @@ +using NUnit.Framework; +using System; +using System.Collections.Concurrent; +using System.Diagnostics; +using TrackOne; + +namespace Azure.Messaging.EventHubs.Tests +{ + internal static class DiagnosticsCommon + { + public static ConcurrentQueue<(string eventName, object payload, Activity activity)> CreateEventQueue() => + new ConcurrentQueue<(string eventName, object payload, Activity activity)>(); + + public static IDisposable SubscribeToEvents(IObserver listener) => + DiagnosticListener.AllListeners.Subscribe(listener); + + public static FakeDiagnosticListener CreateEventListener(string entityName, ConcurrentQueue<(string eventName, object payload, Activity activity)> eventQueue) => + new FakeDiagnosticListener(kvp => + { + if (kvp.Key == null || kvp.Value == null) + { + return; + } + + eventQueue?.Enqueue((kvp.Key, kvp.Value, Activity.Current)); + }); + + public static void AssertSendStart(string name, object payload, Activity activity, Activity parentActivity, string partitionKey, EventHubsConnectionStringBuilder connectionStringBuilder, int eventCount = 1) + { + } + + public static void AssertSendStop(string name, object payload, Activity activity, Activity sendActivity, string partitionKey, EventHubsConnectionStringBuilder connectionStringBuilder, bool isFaulted = false) + { + } + } +} diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs new file mode 100644 index 0000000000000..123847f08b4b3 --- /dev/null +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs @@ -0,0 +1,76 @@ +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Azure.Messaging.EventHubs.Tests.Infrastructure; +using NUnit.Framework; + +namespace Azure.Messaging.EventHubs.Tests +{ + /// + /// Dummy. + /// + /// + [TestFixture] + [NonParallelizable] + [Category(TestCategory.Live)] + [Category(TestCategory.DisallowVisualStudioLiveUnitTesting)] + class DiagnosticsLiveTests + { + [Test] + [Ignore("Injection step not working")] + public async Task SendFiresEvents() + { + await using (var scope = await EventHubScope.CreateAsync(1)) + { + var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); + + await using (var client = new EventHubClient(connectionString)) + await using (var producer = client.CreateProducer()) + { + var eventQueue = DiagnosticsCommon.CreateEventQueue(); + + using (var listener = DiagnosticsCommon.CreateEventListener(null, eventQueue)) + using (var subscription = DiagnosticsCommon.SubscribeToEvents(listener)) + { + var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); + var eventData = new EventData(Encoding.UTF8.GetBytes("I hope it works!")); + var partitionKey = "AmIaGoodPartitionKey"; + + // Enable Send .Start & .Stop events. + + listener.Enable((name, queueName, arg) => name.Contains("Send") && !name.EndsWith(".Exception")); + + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.False); + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.False); + + parentActivity.Start(); + + await producer.SendAsync(eventData, new SendOptions { PartitionKey = partitionKey }); + + parentActivity.Stop(); + + // Check Diagnostic-Id injection. + + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.True); + + // Check Correlation-Context injection. + + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.True); + Assert.That(TrackOne.EventHubsDiagnosticSource.SerializeCorrelationContext(parentActivity.Baggage.ToList()), Is.EqualTo(eventData.Properties[TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName])); + + Assert.That(eventQueue.TryDequeue(out var sendStart), Is.True); + // SendStart + + Assert.That(eventQueue.TryDequeue(out var sendStop), Is.True); + // SendStop + + // There should be no more events to dequeue. + + Assert.That(eventQueue.TryDequeue(out var evnt), Is.False); + } + } + } + } + } +} diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs new file mode 100644 index 0000000000000..10073636c9812 --- /dev/null +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs @@ -0,0 +1,14 @@ +using NUnit.Framework; + +namespace Azure.Messaging.EventHubs.Tests +{ + /// + /// Dummy. + /// + /// + [TestFixture] + [NonParallelizable] + public class DiagnosticsTests + { + } +} diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/FakeDiagnosticListener.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/FakeDiagnosticListener.cs new file mode 100644 index 0000000000000..b06acf9b28b17 --- /dev/null +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/FakeDiagnosticListener.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Azure.Messaging.EventHubs.Tests +{ + internal sealed class FakeDiagnosticListener : IObserver, IDisposable + { + private IDisposable subscription; + + private readonly Action> writeCallback; + + private Func writeObserverEnabled = (name, arg1, arg2) => false; + + public FakeDiagnosticListener(Action> writeCallback) + { + this.writeCallback = writeCallback; + } + + public void OnCompleted() { } + + public void OnError(Exception error) { } + + public void OnNext(DiagnosticListener value) + { + if (value.Name.Equals("Microsoft.Azure.EventHubs")) + { + this.subscription = value.Subscribe(new FakeDiagnosticSourceWriteObserver(this.writeCallback), this.IsEnabled); + } + } + + public void Enable(Func writeObserverEnabled) + { + this.writeObserverEnabled = writeObserverEnabled; + } + + public void Disable() + { + this.writeObserverEnabled = (name, arg1, arg2) => false; + } + + public bool IsEnabled(string s, object arg1, object arg2) + { + return this.writeObserverEnabled.Invoke(s, arg1, arg2); + } + + public void Dispose() + { + this.Disable(); + this.subscription?.Dispose(); + } + + private class FakeDiagnosticSourceWriteObserver : IObserver> + { + private readonly Action> writeCallback; + + public FakeDiagnosticSourceWriteObserver(Action> writeCallback) + { + this.writeCallback = writeCallback; + } + + public void OnCompleted() { } + + public void OnError(Exception error) { } + + public void OnNext(KeyValuePair value) + { + this.writeCallback(value); + } + } + } +} From d05b4c1ec4916a6f4458b4a16d93e47bcc3f6ce8 Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Fri, 12 Jul 2019 11:23:52 -0700 Subject: [PATCH 02/21] Using only LiveTests for now. Single test failing, but complete. --- .../tests/Diagnostics/DiagnosticsCommon.cs | 36 ------ .../tests/Diagnostics/DiagnosticsLiveTests.cs | 115 +++++++++++++++++- .../tests/Diagnostics/DiagnosticsTests.cs | 14 --- 3 files changed, 109 insertions(+), 56 deletions(-) delete mode 100644 sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsCommon.cs delete mode 100644 sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsCommon.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsCommon.cs deleted file mode 100644 index 3d5032c9325d7..0000000000000 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsCommon.cs +++ /dev/null @@ -1,36 +0,0 @@ -using NUnit.Framework; -using System; -using System.Collections.Concurrent; -using System.Diagnostics; -using TrackOne; - -namespace Azure.Messaging.EventHubs.Tests -{ - internal static class DiagnosticsCommon - { - public static ConcurrentQueue<(string eventName, object payload, Activity activity)> CreateEventQueue() => - new ConcurrentQueue<(string eventName, object payload, Activity activity)>(); - - public static IDisposable SubscribeToEvents(IObserver listener) => - DiagnosticListener.AllListeners.Subscribe(listener); - - public static FakeDiagnosticListener CreateEventListener(string entityName, ConcurrentQueue<(string eventName, object payload, Activity activity)> eventQueue) => - new FakeDiagnosticListener(kvp => - { - if (kvp.Key == null || kvp.Value == null) - { - return; - } - - eventQueue?.Enqueue((kvp.Key, kvp.Value, Activity.Current)); - }); - - public static void AssertSendStart(string name, object payload, Activity activity, Activity parentActivity, string partitionKey, EventHubsConnectionStringBuilder connectionStringBuilder, int eventCount = 1) - { - } - - public static void AssertSendStop(string name, object payload, Activity activity, Activity sendActivity, string partitionKey, EventHubsConnectionStringBuilder connectionStringBuilder, bool isFaulted = false) - { - } - } -} diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs index 123847f08b4b3..325c1b2b830a9 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs @@ -1,7 +1,13 @@ -using System.Diagnostics; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; using System.Linq; +using System.Reflection; using System.Text; using System.Threading.Tasks; +using Azure.Messaging.EventHubs.Core; +using Azure.Messaging.EventHubs.Metadata; using Azure.Messaging.EventHubs.Tests.Infrastructure; using NUnit.Framework; @@ -17,6 +23,23 @@ namespace Azure.Messaging.EventHubs.Tests [Category(TestCategory.DisallowVisualStudioLiveUnitTesting)] class DiagnosticsLiveTests { + public static ConcurrentQueue<(string eventName, object payload, Activity activity)> CreateEventQueue() => + new ConcurrentQueue<(string eventName, object payload, Activity activity)>(); + + public static IDisposable SubscribeToEvents(IObserver listener) => + DiagnosticListener.AllListeners.Subscribe(listener); + + public static FakeDiagnosticListener CreateEventListener(string entityName, ConcurrentQueue<(string eventName, object payload, Activity activity)> eventQueue) => + new FakeDiagnosticListener(kvp => + { + if (kvp.Key == null || kvp.Value == null) + { + return; + } + + eventQueue?.Enqueue((kvp.Key, kvp.Value, Activity.Current)); + }); + [Test] [Ignore("Injection step not working")] public async Task SendFiresEvents() @@ -28,10 +51,10 @@ public async Task SendFiresEvents() await using (var client = new EventHubClient(connectionString)) await using (var producer = client.CreateProducer()) { - var eventQueue = DiagnosticsCommon.CreateEventQueue(); + var eventQueue = CreateEventQueue(); - using (var listener = DiagnosticsCommon.CreateEventListener(null, eventQueue)) - using (var subscription = DiagnosticsCommon.SubscribeToEvents(listener)) + using (var listener = CreateEventListener(null, eventQueue)) + using (var subscription = SubscribeToEvents(listener)) { var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); var eventData = new EventData(Encoding.UTF8.GetBytes("I hope it works!")); @@ -60,10 +83,10 @@ public async Task SendFiresEvents() Assert.That(TrackOne.EventHubsDiagnosticSource.SerializeCorrelationContext(parentActivity.Baggage.ToList()), Is.EqualTo(eventData.Properties[TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName])); Assert.That(eventQueue.TryDequeue(out var sendStart), Is.True); - // SendStart + AssertSendStart(sendStart.eventName, sendStart.payload, sendStart.activity, parentActivity, partitionKey, connectionString); Assert.That(eventQueue.TryDequeue(out var sendStop), Is.True); - // SendStop + AssertSendStop(sendStop.eventName, sendStop.payload, sendStop.activity, sendStart.activity, partitionKey, connectionString); // There should be no more events to dequeue. @@ -72,5 +95,85 @@ public async Task SendFiresEvents() } } } + + private void AssertSendStart(string name, object payload, Activity activity, Activity parentActivity, string partitionKey, string connectionString, int eventCount = 1) + { + var connectionStringProperties = ConnectionStringParser.Parse(connectionString); + + Assert.That(name, Is.EqualTo("Microsoft.Azure.EventHubs.Send.Start")); + AssertCommonPayloadProperties(payload, partitionKey, connectionStringProperties); + + var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); + Assert.That(eventDatas.Count, Is.EqualTo(eventCount)); + + Assert.That(activity, Is.Not.Null); + Assert.That(activity.Parent, Is.EqualTo(parentActivity)); + + AssertTagMatches(activity, "peer.hostname", connectionStringProperties.Endpoint.Host); + AssertTagMatches(activity, "eh.event_hub_name", connectionStringProperties.EventHubPath); + + if (partitionKey != null) + { + AssertTagMatches(activity, "eh.partition_key", partitionKey); + } + + AssertTagMatches(activity, "eh.event_count", eventCount.ToString()); + AssertTagExists(activity, "eh.client_id"); + } + + private void AssertSendStop(string name, object payload, Activity activity, Activity sendActivity, string partitionKey, string connectionString, bool isFaulted = false) + { + var connectionStringProperties = ConnectionStringParser.Parse(connectionString); + + Assert.That(name, Is.EqualTo("Microsoft.Azure.EventHubs.Send.Stop")); + AssertCommonStopPayloadProperties(payload, partitionKey, isFaulted, connectionStringProperties); ; + + if (sendActivity != null) + { + Assert.That(activity, Is.EqualTo(sendActivity)); + } + + var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); + Assert.That(eventDatas, Is.Not.Null); + } + + private void AssertTagExists(Activity activity, string tagName) + { + Assert.That(activity.Tags.Select(t => t.Key).Contains(tagName), Is.True); + } + + private void AssertTagMatches(Activity activity, string tagName, string tagValue) + { + Assert.That(activity.Tags.Select(t => t.Key).Contains(tagName), Is.True); + Assert.That(activity.Tags.Single(t => t.Key == tagName).Value, Is.EqualTo(tagValue)); + } + + private void AssertCommonPayloadProperties(object eventPayload, string partitionKey, ConnectionStringProperties connectionStringProperties) + { + var endpoint = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "Endpoint"); + var entityPath = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "Entity"); + var pKey = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "PartitionKey"); + + Assert.That(endpoint, Is.EqualTo(connectionStringProperties.Endpoint)); + Assert.That(entityPath, Is.EqualTo(connectionStringProperties.EventHubPath)); + Assert.That(pKey, Is.EqualTo(partitionKey)); + } + + private void AssertCommonStopPayloadProperties(object eventPayload, string partitionKey, bool isFaulted, ConnectionStringProperties connectionStringProperties) + { + AssertCommonPayloadProperties(eventPayload, partitionKey, connectionStringProperties); + } + + private T GetPropertyValueFromAnonymousTypeInstance(object obj, string propertyName) + { + Type t = obj.GetType(); + PropertyInfo p = t.GetRuntimeProperty(propertyName); + object propertyValue = p.GetValue(obj); + + Assert.That(propertyValue, Is.Not.Null); + Assert.That(propertyValue, Is.AssignableFrom()); + + return (T)propertyValue; + } } } diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs deleted file mode 100644 index 10073636c9812..0000000000000 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs +++ /dev/null @@ -1,14 +0,0 @@ -using NUnit.Framework; - -namespace Azure.Messaging.EventHubs.Tests -{ - /// - /// Dummy. - /// - /// - [TestFixture] - [NonParallelizable] - public class DiagnosticsTests - { - } -} From 1d56125d1bfd2abc8a3ccde1d5831099b330f4c0 Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Mon, 15 Jul 2019 04:12:02 -0700 Subject: [PATCH 03/21] All send live tests added. Diagnostics not working as expected --- .../tests/Diagnostics/DiagnosticsLiveTests.cs | 314 +++++++++++++++++- 1 file changed, 304 insertions(+), 10 deletions(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs index 325c1b2b830a9..b3d1388e87834 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs @@ -23,13 +23,13 @@ namespace Azure.Messaging.EventHubs.Tests [Category(TestCategory.DisallowVisualStudioLiveUnitTesting)] class DiagnosticsLiveTests { - public static ConcurrentQueue<(string eventName, object payload, Activity activity)> CreateEventQueue() => + private static ConcurrentQueue<(string eventName, object payload, Activity activity)> CreateEventQueue() => new ConcurrentQueue<(string eventName, object payload, Activity activity)>(); - public static IDisposable SubscribeToEvents(IObserver listener) => + private static IDisposable SubscribeToEvents(IObserver listener) => DiagnosticListener.AllListeners.Subscribe(listener); - public static FakeDiagnosticListener CreateEventListener(string entityName, ConcurrentQueue<(string eventName, object payload, Activity activity)> eventQueue) => + private static FakeDiagnosticListener CreateEventListener(string entityName, ConcurrentQueue<(string eventName, object payload, Activity activity)> eventQueue) => new FakeDiagnosticListener(kvp => { if (kvp.Key == null || kvp.Value == null) @@ -96,7 +96,281 @@ public async Task SendFiresEvents() } } - private void AssertSendStart(string name, object payload, Activity activity, Activity parentActivity, string partitionKey, string connectionString, int eventCount = 1) + [Test] + public async Task SendDoesNotInjectContextWhenNoListeners() + { + await using (var scope = await EventHubScope.CreateAsync(1)) + { + var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); + + await using (var client = new EventHubClient(connectionString)) + await using (var producer = client.CreateProducer()) + { + var eventQueue = CreateEventQueue(); + + using (var listener = CreateEventListener(null, eventQueue)) + using (var subscription = SubscribeToEvents(listener)) + { + // TODO: is parentActivity necessary? + var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); + var eventData = new EventData(Encoding.UTF8.GetBytes("I hope it works!")); + + // Disable all events. + + listener.Disable(); + + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.False); + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.False); + + parentActivity.Start(); + + await producer.SendAsync(eventData); + + parentActivity.Stop(); + + // There should be no Diagnostic-Id injection. + + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.False); + + // There should be no Correlation-Context injection. + + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.False); + + // There should be no more events to dequeue. + + Assert.That(eventQueue.TryDequeue(out var evnt), Is.False); + } + } + } + } + + [Test] + [Ignore("Exception is thrown but no event is caught.")] + public async Task SendFiresExceptionEvents() + { + await using (var scope = await EventHubScope.CreateAsync(1)) + { + var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); + + await using (var client = new EventHubClient(connectionString)) + await using (var producer = client.CreateProducer()) + { + var eventQueue = CreateEventQueue(); + + using (var listener = CreateEventListener(null, eventQueue)) + using (var subscription = SubscribeToEvents(listener)) + { + var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); + var eventData = new EventData(new byte[300 * 1024 * 1024]); + var partitionKey = "AmIaGoodPartitionKey"; + + // Enable Send .Exception & .Stop events. + + listener.Enable((name, queueName, arg) => name.Contains("Send") && !name.EndsWith(".Start")); + + parentActivity.Start(); + + // Try sending a large message. A SizeLimitException is expected. + + try + { + await producer.SendAsync(eventData, new SendOptions { PartitionKey = partitionKey }); + throw new Exception(); + // TODO: throw exception? + } + catch (Exception) + { } + + parentActivity.Stop(); + + Assert.That(eventQueue.TryDequeue(out var exception), Is.True); + AssertSendException(exception.eventName, exception.payload, exception.activity, null, partitionKey, connectionString); + + Assert.That(eventQueue.TryDequeue(out var sendStop), Is.True); + AssertSendStop(sendStop.eventName, sendStop.payload, sendStop.activity, null, partitionKey, connectionString); + + Assert.That(sendStop.activity, Is.EqualTo(exception.activity)); + + // There should be no more events to dequeue. + + Assert.That(eventQueue.TryDequeue(out var evnt), Is.False); + } + } + } + } + + [Test] + [Ignore("Injection step not working")] + public async Task SendingToPartitionFiresEvents() + { + await using (var scope = await EventHubScope.CreateAsync(1)) + { + var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); + + await using (var client = new EventHubClient(connectionString)) + { + var partition = (await client.GetPartitionIdsAsync()).First(); + + await using (var producer = client.CreateProducer(new EventHubProducerOptions { PartitionId = partition })) + { + var eventQueue = CreateEventQueue(); + + using (var listener = CreateEventListener(null, eventQueue)) + using (var subscription = SubscribeToEvents(listener)) + { + var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); + var eventData = new EventData(Encoding.UTF8.GetBytes("I hope it works!")); + + // Enable Send .Start & .Stop events. + + listener.Enable((name, queueName, arg) => name.Contains("Send") && !name.EndsWith(".Exception")); + + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.False); + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.False); + + parentActivity.Start(); + + await producer.SendAsync(eventData); + + parentActivity.Stop(); + + // Check Diagnostic-Id injection. + + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.True); + + // Check Correlation-Context injection. + + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.True); + Assert.That(TrackOne.EventHubsDiagnosticSource.SerializeCorrelationContext(parentActivity.Baggage.ToList()), Is.EqualTo(eventData.Properties[TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName])); + + // TODO: rename partitionKey to partition? What? + Assert.That(eventQueue.TryDequeue(out var sendStart), Is.True); + AssertSendStart(sendStart.eventName, sendStart.payload, sendStart.activity, parentActivity, partition, connectionString); + + Assert.That(eventQueue.TryDequeue(out var sendStop), Is.True); + AssertSendStop(sendStop.eventName, sendStop.payload, sendStop.activity, sendStart.activity, partition, connectionString); + + // There should be no more events to dequeue. + + Assert.That(eventQueue.TryDequeue(out var evnt), Is.False); + } + } + } + } + } + + [Test] + public async Task SendingToPartitionDoesNotInjectContextWhenNoListeners() + { + await using (var scope = await EventHubScope.CreateAsync(1)) + { + var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); + + await using (var client = new EventHubClient(connectionString)) + { + var partition = (await client.GetPartitionIdsAsync()).First(); + + await using (var producer = client.CreateProducer(new EventHubProducerOptions { PartitionId = partition })) + { + var eventQueue = CreateEventQueue(); + + using (var listener = CreateEventListener(null, eventQueue)) + using (var subscription = SubscribeToEvents(listener)) + { + // TODO: is parentActivity necessary? + var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); + var eventData = new EventData(Encoding.UTF8.GetBytes("I hope it works!")); + + // Disable all events. + + listener.Disable(); + + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.False); + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.False); + + parentActivity.Start(); + + await producer.SendAsync(eventData); + + parentActivity.Stop(); + + // There should be no Diagnostic-Id injection. + + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.False); + + // There should be no Correlation-Context injection. + + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.False); + + // There should be no more events to dequeue. + + Assert.That(eventQueue.TryDequeue(out var evnt), Is.False); + } + } + } + } + } + + [Test] + [Ignore("Exception is thrown but no event is caught.")] + public async Task SendingToPartitionFiresExceptionEvents() + { + await using (var scope = await EventHubScope.CreateAsync(1)) + { + var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); + + await using (var client = new EventHubClient(connectionString)) + { + var partition = (await client.GetPartitionIdsAsync()).First(); + + await using (var producer = client.CreateProducer(new EventHubProducerOptions { PartitionId = partition })) + { + var eventQueue = CreateEventQueue(); + + using (var listener = CreateEventListener(null, eventQueue)) + using (var subscription = SubscribeToEvents(listener)) + { + // TODO: is parentActivity necessary? + var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); + var eventData = new EventData(new byte[300 * 1024 * 1024]); + + // Enable Send .Exception & .Stop events. + + listener.Enable((name, queueName, arg) => name.Contains("Send") && !name.EndsWith(".Start")); + + parentActivity.Start(); + + // Try sending a large message. A SizeLimitException is expected. + + try + { + await producer.SendAsync(eventData); + throw new Exception(); + // TODO: throw exception? + } + catch (Exception) + { } + + parentActivity.Stop(); + + Assert.That(eventQueue.TryDequeue(out var exception), Is.True); + AssertSendException(exception.eventName, exception.payload, exception.activity, null, partition, connectionString); + + Assert.That(eventQueue.TryDequeue(out var sendStop), Is.True); + AssertSendStop(sendStop.eventName, sendStop.payload, sendStop.activity, null, partition, connectionString); + + Assert.That(sendStop.activity, Is.EqualTo(exception.activity)); + + // There should be no more events to dequeue. + + Assert.That(eventQueue.TryDequeue(out var evnt), Is.False); + } + } + } + } + } + + private static void AssertSendStart(string name, object payload, Activity activity, Activity parentActivity, string partitionKey, string connectionString, int eventCount = 1) { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); @@ -121,7 +395,27 @@ private void AssertSendStart(string name, object payload, Activity activity, Act AssertTagExists(activity, "eh.client_id"); } - private void AssertSendStop(string name, object payload, Activity activity, Activity sendActivity, string partitionKey, string connectionString, bool isFaulted = false) + private void AssertSendException(string name, object payload, Activity activity, Activity parentActivity, string partitionKey, string connectionString) + { + var connectionStringProperties = ConnectionStringParser.Parse(connectionString); + + Assert.That(name, Is.EqualTo("Microsoft.Azure.EventHubs.Send.Exception")); + AssertCommonPayloadProperties(payload, partitionKey, connectionStringProperties); + + GetPropertyValueFromAnonymousTypeInstance(payload, "Exception"); + + Assert.That(activity, Is.Not.Null); + + if (parentActivity != null) + { + Assert.That(activity.Parent, Is.EqualTo(parentActivity)); + } + + var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); + Assert.That(eventDatas, Is.Not.Null); + } + + private static void AssertSendStop(string name, object payload, Activity activity, Activity sendActivity, string partitionKey, string connectionString, bool isFaulted = false) { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); @@ -137,18 +431,18 @@ private void AssertSendStop(string name, object payload, Activity activity, Acti Assert.That(eventDatas, Is.Not.Null); } - private void AssertTagExists(Activity activity, string tagName) + private static void AssertTagExists(Activity activity, string tagName) { Assert.That(activity.Tags.Select(t => t.Key).Contains(tagName), Is.True); } - private void AssertTagMatches(Activity activity, string tagName, string tagValue) + private static void AssertTagMatches(Activity activity, string tagName, string tagValue) { Assert.That(activity.Tags.Select(t => t.Key).Contains(tagName), Is.True); Assert.That(activity.Tags.Single(t => t.Key == tagName).Value, Is.EqualTo(tagValue)); } - private void AssertCommonPayloadProperties(object eventPayload, string partitionKey, ConnectionStringProperties connectionStringProperties) + private static void AssertCommonPayloadProperties(object eventPayload, string partitionKey, ConnectionStringProperties connectionStringProperties) { var endpoint = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "Endpoint"); var entityPath = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "Entity"); @@ -159,12 +453,12 @@ private void AssertCommonPayloadProperties(object eventPayload, string partition Assert.That(pKey, Is.EqualTo(partitionKey)); } - private void AssertCommonStopPayloadProperties(object eventPayload, string partitionKey, bool isFaulted, ConnectionStringProperties connectionStringProperties) + private static void AssertCommonStopPayloadProperties(object eventPayload, string partitionKey, bool isFaulted, ConnectionStringProperties connectionStringProperties) { AssertCommonPayloadProperties(eventPayload, partitionKey, connectionStringProperties); } - private T GetPropertyValueFromAnonymousTypeInstance(object obj, string propertyName) + private static T GetPropertyValueFromAnonymousTypeInstance(object obj, string propertyName) { Type t = obj.GetType(); PropertyInfo p = t.GetRuntimeProperty(propertyName); From d8f76f432cdf62e941d9d94472f2cc92f494e1bf Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Mon, 15 Jul 2019 20:23:24 -0700 Subject: [PATCH 04/21] PartitionSender tests not necessary. Injection issue needs to be fixed. --- .../EventHubsDiagnosticSource.cs | 2 +- .../tests/Diagnostics/DiagnosticsLiveTests.cs | 235 +++--------------- .../Diagnostics/FakeDiagnosticListener.cs | 2 +- 3 files changed, 34 insertions(+), 205 deletions(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventHubsDiagnosticSource.cs b/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventHubsDiagnosticSource.cs index 5f82e15a99a92..c0eabe464173d 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventHubsDiagnosticSource.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventHubsDiagnosticSource.cs @@ -14,7 +14,7 @@ namespace TrackOne /// internal static class EventHubsDiagnosticSource { - public const string DiagnosticSourceName = "TrackOne"; + public const string DiagnosticSourceName = "Azure.Messaging.EventHubs"; public const string ActivityIdPropertyName = "Diagnostic-Id"; public const string CorrelationContextPropertyName = "Correlation-Context"; diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs index b3d1388e87834..1d3abf4bafea8 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs @@ -7,6 +7,7 @@ using System.Text; using System.Threading.Tasks; using Azure.Messaging.EventHubs.Core; +using Azure.Messaging.EventHubs.Errors; using Azure.Messaging.EventHubs.Metadata; using Azure.Messaging.EventHubs.Tests.Infrastructure; using NUnit.Framework; @@ -29,7 +30,7 @@ class DiagnosticsLiveTests private static IDisposable SubscribeToEvents(IObserver listener) => DiagnosticListener.AllListeners.Subscribe(listener); - private static FakeDiagnosticListener CreateEventListener(string entityName, ConcurrentQueue<(string eventName, object payload, Activity activity)> eventQueue) => + private static FakeDiagnosticListener CreateEventListener(ConcurrentQueue<(string eventName, object payload, Activity activity)> eventQueue) => new FakeDiagnosticListener(kvp => { if (kvp.Key == null || kvp.Value == null) @@ -40,6 +41,18 @@ private static FakeDiagnosticListener CreateEventListener(string entityName, Con eventQueue?.Enqueue((kvp.Key, kvp.Value, Activity.Current)); }); + private static T GetPropertyValueFromAnonymousTypeInstance(object obj, string propertyName) + { + Type t = obj.GetType(); + PropertyInfo p = t.GetRuntimeProperty(propertyName); + object propertyValue = p.GetValue(obj); + + Assert.That(propertyValue, Is.Not.Null); + Assert.That(propertyValue, Is.AssignableTo()); + + return (T)propertyValue; + } + [Test] [Ignore("Injection step not working")] public async Task SendFiresEvents() @@ -53,7 +66,7 @@ public async Task SendFiresEvents() { var eventQueue = CreateEventQueue(); - using (var listener = CreateEventListener(null, eventQueue)) + using (var listener = CreateEventListener(eventQueue)) using (var subscription = SubscribeToEvents(listener)) { var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); @@ -108,7 +121,7 @@ public async Task SendDoesNotInjectContextWhenNoListeners() { var eventQueue = CreateEventQueue(); - using (var listener = CreateEventListener(null, eventQueue)) + using (var listener = CreateEventListener(eventQueue)) using (var subscription = SubscribeToEvents(listener)) { // TODO: is parentActivity necessary? @@ -145,7 +158,6 @@ public async Task SendDoesNotInjectContextWhenNoListeners() } [Test] - [Ignore("Exception is thrown but no event is caught.")] public async Task SendFiresExceptionEvents() { await using (var scope = await EventHubScope.CreateAsync(1)) @@ -157,7 +169,7 @@ public async Task SendFiresExceptionEvents() { var eventQueue = CreateEventQueue(); - using (var listener = CreateEventListener(null, eventQueue)) + using (var listener = CreateEventListener(eventQueue)) using (var subscription = SubscribeToEvents(listener)) { var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); @@ -172,14 +184,7 @@ public async Task SendFiresExceptionEvents() // Try sending a large message. A SizeLimitException is expected. - try - { - await producer.SendAsync(eventData, new SendOptions { PartitionKey = partitionKey }); - throw new Exception(); - // TODO: throw exception? - } - catch (Exception) - { } + Assert.That(async () => await producer.SendAsync(eventData, new SendOptions { PartitionKey = partitionKey }), Throws.InstanceOf()); parentActivity.Stop(); @@ -199,185 +204,14 @@ public async Task SendFiresExceptionEvents() } } - [Test] - [Ignore("Injection step not working")] - public async Task SendingToPartitionFiresEvents() - { - await using (var scope = await EventHubScope.CreateAsync(1)) - { - var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var client = new EventHubClient(connectionString)) - { - var partition = (await client.GetPartitionIdsAsync()).First(); - - await using (var producer = client.CreateProducer(new EventHubProducerOptions { PartitionId = partition })) - { - var eventQueue = CreateEventQueue(); - - using (var listener = CreateEventListener(null, eventQueue)) - using (var subscription = SubscribeToEvents(listener)) - { - var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); - var eventData = new EventData(Encoding.UTF8.GetBytes("I hope it works!")); - - // Enable Send .Start & .Stop events. - - listener.Enable((name, queueName, arg) => name.Contains("Send") && !name.EndsWith(".Exception")); - - Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.False); - Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.False); - - parentActivity.Start(); - - await producer.SendAsync(eventData); - - parentActivity.Stop(); - - // Check Diagnostic-Id injection. - - Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.True); - - // Check Correlation-Context injection. - - Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.True); - Assert.That(TrackOne.EventHubsDiagnosticSource.SerializeCorrelationContext(parentActivity.Baggage.ToList()), Is.EqualTo(eventData.Properties[TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName])); - - // TODO: rename partitionKey to partition? What? - Assert.That(eventQueue.TryDequeue(out var sendStart), Is.True); - AssertSendStart(sendStart.eventName, sendStart.payload, sendStart.activity, parentActivity, partition, connectionString); - - Assert.That(eventQueue.TryDequeue(out var sendStop), Is.True); - AssertSendStop(sendStop.eventName, sendStop.payload, sendStop.activity, sendStart.activity, partition, connectionString); - - // There should be no more events to dequeue. - - Assert.That(eventQueue.TryDequeue(out var evnt), Is.False); - } - } - } - } - } - - [Test] - public async Task SendingToPartitionDoesNotInjectContextWhenNoListeners() - { - await using (var scope = await EventHubScope.CreateAsync(1)) - { - var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var client = new EventHubClient(connectionString)) - { - var partition = (await client.GetPartitionIdsAsync()).First(); - - await using (var producer = client.CreateProducer(new EventHubProducerOptions { PartitionId = partition })) - { - var eventQueue = CreateEventQueue(); - - using (var listener = CreateEventListener(null, eventQueue)) - using (var subscription = SubscribeToEvents(listener)) - { - // TODO: is parentActivity necessary? - var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); - var eventData = new EventData(Encoding.UTF8.GetBytes("I hope it works!")); - - // Disable all events. - - listener.Disable(); - - Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.False); - Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.False); - - parentActivity.Start(); - - await producer.SendAsync(eventData); - - parentActivity.Stop(); - - // There should be no Diagnostic-Id injection. - - Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.False); - - // There should be no Correlation-Context injection. - - Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.False); - - // There should be no more events to dequeue. - - Assert.That(eventQueue.TryDequeue(out var evnt), Is.False); - } - } - } - } - } - - [Test] - [Ignore("Exception is thrown but no event is caught.")] - public async Task SendingToPartitionFiresExceptionEvents() - { - await using (var scope = await EventHubScope.CreateAsync(1)) - { - var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var client = new EventHubClient(connectionString)) - { - var partition = (await client.GetPartitionIdsAsync()).First(); - - await using (var producer = client.CreateProducer(new EventHubProducerOptions { PartitionId = partition })) - { - var eventQueue = CreateEventQueue(); - - using (var listener = CreateEventListener(null, eventQueue)) - using (var subscription = SubscribeToEvents(listener)) - { - // TODO: is parentActivity necessary? - var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); - var eventData = new EventData(new byte[300 * 1024 * 1024]); - - // Enable Send .Exception & .Stop events. - - listener.Enable((name, queueName, arg) => name.Contains("Send") && !name.EndsWith(".Start")); - - parentActivity.Start(); - - // Try sending a large message. A SizeLimitException is expected. - - try - { - await producer.SendAsync(eventData); - throw new Exception(); - // TODO: throw exception? - } - catch (Exception) - { } - - parentActivity.Stop(); - - Assert.That(eventQueue.TryDequeue(out var exception), Is.True); - AssertSendException(exception.eventName, exception.payload, exception.activity, null, partition, connectionString); - - Assert.That(eventQueue.TryDequeue(out var sendStop), Is.True); - AssertSendStop(sendStop.eventName, sendStop.payload, sendStop.activity, null, partition, connectionString); - - Assert.That(sendStop.activity, Is.EqualTo(exception.activity)); - - // There should be no more events to dequeue. - - Assert.That(eventQueue.TryDequeue(out var evnt), Is.False); - } - } - } - } - } - private static void AssertSendStart(string name, object payload, Activity activity, Activity parentActivity, string partitionKey, string connectionString, int eventCount = 1) { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); - Assert.That(name, Is.EqualTo("Microsoft.Azure.EventHubs.Send.Start")); + Assert.That(name, Is.EqualTo("Azure.Messaging.EventHubs.Send.Start")); AssertCommonPayloadProperties(payload, partitionKey, connectionStringProperties); - var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); + var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); Assert.That(eventDatas.Count, Is.EqualTo(eventCount)); Assert.That(activity, Is.Not.Null); @@ -399,7 +233,7 @@ private void AssertSendException(string name, object payload, Activity activity, { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); - Assert.That(name, Is.EqualTo("Microsoft.Azure.EventHubs.Send.Exception")); + Assert.That(name, Is.EqualTo("Azure.Messaging.EventHubs.Send.Exception")); AssertCommonPayloadProperties(payload, partitionKey, connectionStringProperties); GetPropertyValueFromAnonymousTypeInstance(payload, "Exception"); @@ -411,7 +245,9 @@ private void AssertSendException(string name, object payload, Activity activity, Assert.That(activity.Parent, Is.EqualTo(parentActivity)); } - var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); + // TODO: keep track one? + // TODO: why doesn't IList work? + var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); Assert.That(eventDatas, Is.Not.Null); } @@ -419,7 +255,7 @@ private static void AssertSendStop(string name, object payload, Activity activit { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); - Assert.That(name, Is.EqualTo("Microsoft.Azure.EventHubs.Send.Stop")); + Assert.That(name, Is.EqualTo("Azure.Messaging.EventHubs.Send.Stop")); AssertCommonStopPayloadProperties(payload, partitionKey, isFaulted, connectionStringProperties); ; if (sendActivity != null) @@ -427,7 +263,7 @@ private static void AssertSendStop(string name, object payload, Activity activit Assert.That(activity, Is.EqualTo(sendActivity)); } - var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); + var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); Assert.That(eventDatas, Is.Not.Null); } @@ -448,7 +284,12 @@ private static void AssertCommonPayloadProperties(object eventPayload, string pa var entityPath = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "Entity"); var pKey = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "PartitionKey"); - Assert.That(endpoint, Is.EqualTo(connectionStringProperties.Endpoint)); + // endpoint is amqps://cooleventhubs.servicebus.windows.net/SendFiresExceptionEvents-a2fda415 + // connectionString is sb://cooleventhubs.servicebus.windows.net/ + // TODO: should we update the diagnostics output? + var expectedEndpointStart = "amqps://" + connectionStringProperties.Endpoint.Host; + + Assert.That(endpoint.AbsoluteUri.StartsWith(expectedEndpointStart), Is.True); Assert.That(entityPath, Is.EqualTo(connectionStringProperties.EventHubPath)); Assert.That(pKey, Is.EqualTo(partitionKey)); } @@ -457,17 +298,5 @@ private static void AssertCommonStopPayloadProperties(object eventPayload, strin { AssertCommonPayloadProperties(eventPayload, partitionKey, connectionStringProperties); } - - private static T GetPropertyValueFromAnonymousTypeInstance(object obj, string propertyName) - { - Type t = obj.GetType(); - PropertyInfo p = t.GetRuntimeProperty(propertyName); - object propertyValue = p.GetValue(obj); - - Assert.That(propertyValue, Is.Not.Null); - Assert.That(propertyValue, Is.AssignableFrom()); - - return (T)propertyValue; - } } } diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/FakeDiagnosticListener.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/FakeDiagnosticListener.cs index b06acf9b28b17..90577d462c28b 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/FakeDiagnosticListener.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/FakeDiagnosticListener.cs @@ -23,7 +23,7 @@ public void OnError(Exception error) { } public void OnNext(DiagnosticListener value) { - if (value.Name.Equals("Microsoft.Azure.EventHubs")) + if (value.Name.Equals("Azure.Messaging.EventHubs")) { this.subscription = value.Subscribe(new FakeDiagnosticSourceWriteObserver(this.writeCallback), this.IsEnabled); } From d6cdb8602e90d3cc24568a4314df9fd882f197dd Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Mon, 15 Jul 2019 21:19:16 -0700 Subject: [PATCH 05/21] Receive test included as well. Injection still not working. --- .../tests/Diagnostics/DiagnosticsLiveTests.cs | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs index 1d3abf4bafea8..ceba8e1341a94 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs @@ -24,6 +24,9 @@ namespace Azure.Messaging.EventHubs.Tests [Category(TestCategory.DisallowVisualStudioLiveUnitTesting)] class DiagnosticsLiveTests { + /// The maximum number of times that the receive loop should iterate to collect the expected number of messages. + private const int ReceiveRetryLimit = 10; + private static ConcurrentQueue<(string eventName, object payload, Activity activity)> CreateEventQueue() => new ConcurrentQueue<(string eventName, object payload, Activity activity)>(); @@ -204,6 +207,94 @@ public async Task SendFiresExceptionEvents() } } + [Test] + [Ignore("Injection step not working")] + public async Task ReceiveFiresEvents() + { + await using (var scope = await EventHubScope.CreateAsync(1)) + { + var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); + + await using (var client = new EventHubClient(connectionString)) + await using (var producer = client.CreateProducer()) + { + var eventQueue = CreateEventQueue(); + var partition = (await client.GetPartitionIdsAsync()).First(); + + using (var listener = CreateEventListener(eventQueue)) + using (var subscription = SubscribeToEvents(listener)) + await using (var consumer = client.CreateConsumer(EventHubConsumer.DefaultConsumerGroupName, partition, EventPosition.Latest)) + { + var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); + var sendEvent = new EventData(Encoding.UTF8.GetBytes("I hope it works!")); + var partitionKey = "AmIaGoodPartitionKey"; + + // Enable Send & Receive .Start & .Stop events. + + listener.Enable((name, queueName, arg) => !name.EndsWith(".Exception")); + + // Initiate an operation to force the consumer to connect and set its position at the + // end of the event stream. + + await consumer.ReceiveAsync(1, TimeSpan.Zero); + + // Send the batch of events. + + Assert.That(sendEvent.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.False); + Assert.That(sendEvent.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.False); + + await producer.SendAsync(sendEvent, new SendOptions { PartitionKey = partitionKey }); + + // Receive and the event; because there is some non-determinism in the messaging flow, the + // sent event may not be immediately available. Allow for a small number of attempts to receive, in order + // to account for availability delays. + + var expectedEventsCount = 1; + var receivedEvents = new List(); + var index = 0; + + parentActivity.Start(); + + while ((receivedEvents.Count < expectedEventsCount) && (++index < ReceiveRetryLimit)) + { + receivedEvents.AddRange(await consumer.ReceiveAsync(10, TimeSpan.FromMilliseconds(25))); + } + + parentActivity.Stop(); + + var receivedEvent = receivedEvents.Single(); + // TODO: check payload string? + + // Check Diagnostic-Id injection. + + Assert.That(receivedEvent.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.True); + // TODO: check if key is present in sendEvent? + Assert.That(receivedEvent.Properties[TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName], Is.EqualTo(sendEvent.Properties[TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName])); + + // Check Correlation-Context injection. + + Assert.That(receivedEvent.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.True); + // TODO: change order + Assert.That(TrackOne.EventHubsDiagnosticSource.SerializeCorrelationContext(parentActivity.Baggage.ToList()), Is.EqualTo(receivedEvent.Properties[TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName])); + + Assert.That(eventQueue.TryDequeue(out var sendStart), Is.True); + Assert.That(eventQueue.TryDequeue(out var sendStop), Is.True); + + // TODO: isParentActivity necessary? + Assert.That(eventQueue.TryDequeue(out var receiveStart), Is.True); + AssertReceiveStart(receiveStart.eventName, receiveStart.payload, receiveStart.activity, partitionKey, connectionString); + + Assert.That(eventQueue.TryDequeue(out var receiveStop), Is.True); + AssertReceiveStop(receiveStop.eventName, receiveStop.payload, receiveStop.activity, receiveStart.activity, partitionKey, connectionString, relatedId: sendStop.activity.Id); + + // There should be no more events to dequeue. + + Assert.That(eventQueue.TryDequeue(out var evnt), Is.False); + } + } + } + } + private static void AssertSendStart(string name, object payload, Activity activity, Activity parentActivity, string partitionKey, string connectionString, int eventCount = 1) { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); @@ -267,6 +358,51 @@ private static void AssertSendStop(string name, object payload, Activity activit Assert.That(eventDatas, Is.Not.Null); } + private static void AssertReceiveStart(string name, object payload, Activity activity, string partitionKey, string connectionString) + { + var connectionStringProperties = ConnectionStringParser.Parse(connectionString); + + Assert.That(name, Is.EqualTo("Azure.Messaging.EventHubs.Receive.Start")); + AssertCommonPayloadProperties(payload, partitionKey, connectionStringProperties); + + Assert.That(activity, Is.Not.Null); + + AssertTagMatches(activity, "peer.hostname", connectionStringProperties.Endpoint.Host); + AssertTagMatches(activity, "eh.event_hub_name", connectionStringProperties.EventHubPath); + + if (partitionKey != null) + { + AssertTagMatches(activity, "eh.partition_key", partitionKey); + } + + AssertTagExists(activity, "eh.event_count"); + AssertTagExists(activity, "eh.client_id"); + AssertTagExists(activity, "eh.consumer_group"); + AssertTagExists(activity, "eh.start_offset"); + } + + private static void AssertReceiveStop(string name, object payload, Activity activity, Activity receiveActivity, string partitionKey, string connectionString, bool isFaulted = false, string relatedId = null) + { + var connectionStringProperties = ConnectionStringParser.Parse(connectionString); + + Assert.That(name, Is.EqualTo("Azure.Messaging.EventHubs.Receive.Stop")); + AssertCommonStopPayloadProperties(payload, partitionKey, isFaulted, connectionStringProperties); + + if (receiveActivity != null) + { + Assert.That(activity, Is.EqualTo(receiveActivity)); + } + + if (!string.IsNullOrEmpty(relatedId)) + { + var relatedToTag = activity.Tags.FirstOrDefault(tag => tag.Key == TrackOne.EventHubsDiagnosticSource.RelatedToTagName); + + Assert.That(relatedToTag, Is.Not.Null); + Assert.That(relatedToTag.Value, Is.Not.Null); + Assert.That(relatedToTag.Value.Contains(relatedId), Is.True); + } + } + private static void AssertTagExists(Activity activity, string tagName) { Assert.That(activity.Tags.Select(t => t.Key).Contains(tagName), Is.True); From 3676acf514d2804c2aeb069698d768004839bc23 Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Tue, 16 Jul 2019 02:12:18 -0700 Subject: [PATCH 06/21] Receive test working. The order matters. --- .../tests/Diagnostics/DiagnosticsLiveTests.cs | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs index ceba8e1341a94..77df7c05c2c8a 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs @@ -208,7 +208,6 @@ public async Task SendFiresExceptionEvents() } [Test] - [Ignore("Injection step not working")] public async Task ReceiveFiresEvents() { await using (var scope = await EventHubScope.CreateAsync(1)) @@ -227,23 +226,24 @@ public async Task ReceiveFiresEvents() { var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); var sendEvent = new EventData(Encoding.UTF8.GetBytes("I hope it works!")); - var partitionKey = "AmIaGoodPartitionKey"; - - // Enable Send & Receive .Start & .Stop events. - - listener.Enable((name, queueName, arg) => !name.EndsWith(".Exception")); // Initiate an operation to force the consumer to connect and set its position at the // end of the event stream. await consumer.ReceiveAsync(1, TimeSpan.Zero); + // Enable Send & Receive .Start & .Stop events. + + listener.Enable((name, queueName, arg) => !name.EndsWith(".Exception")); + // Send the batch of events. Assert.That(sendEvent.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.False); Assert.That(sendEvent.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.False); - await producer.SendAsync(sendEvent, new SendOptions { PartitionKey = partitionKey }); + parentActivity.Start(); + + await producer.SendAsync(sendEvent); // Receive and the event; because there is some non-determinism in the messaging flow, the // sent event may not be immediately available. Allow for a small number of attempts to receive, in order @@ -253,8 +253,6 @@ public async Task ReceiveFiresEvents() var receivedEvents = new List(); var index = 0; - parentActivity.Start(); - while ((receivedEvents.Count < expectedEventsCount) && (++index < ReceiveRetryLimit)) { receivedEvents.AddRange(await consumer.ReceiveAsync(10, TimeSpan.FromMilliseconds(25))); @@ -282,10 +280,10 @@ public async Task ReceiveFiresEvents() // TODO: isParentActivity necessary? Assert.That(eventQueue.TryDequeue(out var receiveStart), Is.True); - AssertReceiveStart(receiveStart.eventName, receiveStart.payload, receiveStart.activity, partitionKey, connectionString); + AssertReceiveStart(receiveStart.eventName, receiveStart.payload, receiveStart.activity, partition, connectionString); Assert.That(eventQueue.TryDequeue(out var receiveStop), Is.True); - AssertReceiveStop(receiveStop.eventName, receiveStop.payload, receiveStop.activity, receiveStart.activity, partitionKey, connectionString, relatedId: sendStop.activity.Id); + AssertReceiveStop(receiveStop.eventName, receiveStop.payload, receiveStop.activity, receiveStart.activity, partition, connectionString, relatedId: sendStop.activity.Id); // There should be no more events to dequeue. From 43785028a009a03f1e0bc87151862a75c3338f51 Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Tue, 16 Jul 2019 02:37:23 -0700 Subject: [PATCH 07/21] Injection issue somehow solved. --- .../tests/Diagnostics/DiagnosticsLiveTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs index 77df7c05c2c8a..99a28adc22d4e 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs @@ -57,7 +57,6 @@ private static T GetPropertyValueFromAnonymousTypeInstance(object obj, string } [Test] - [Ignore("Injection step not working")] public async Task SendFiresEvents() { await using (var scope = await EventHubScope.CreateAsync(1)) @@ -265,8 +264,8 @@ public async Task ReceiveFiresEvents() // Check Diagnostic-Id injection. + Assert.That(sendEvent.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.True); Assert.That(receivedEvent.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.True); - // TODO: check if key is present in sendEvent? Assert.That(receivedEvent.Properties[TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName], Is.EqualTo(sendEvent.Properties[TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName])); // Check Correlation-Context injection. From 786d491c1d5214285ed52e2133cf0d5b3230dfbb Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Tue, 16 Jul 2019 03:14:34 -0700 Subject: [PATCH 08/21] PartitionKey property in diagnostics may receive partition id --- .../src/TrackOneClient/EventDataSender.cs | 9 +- .../tests/Diagnostics/DiagnosticsLiveTests.cs | 124 +++++++++++------- 2 files changed, 83 insertions(+), 50 deletions(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventDataSender.cs b/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventDataSender.cs index 4ae9b245e2fe2..3d42c769e9a33 100755 --- a/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventDataSender.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventDataSender.cs @@ -26,9 +26,12 @@ protected EventDataSender(EventHubClient eventHubClient, string partitionId) public async Task SendAsync(IEnumerable eventDatas, string partitionKey) { int count = ValidateEvents(eventDatas); + var diagnosticPartitionKey = String.IsNullOrEmpty(partitionKey) ? + this.PartitionId : + partitionKey; EventHubsEventSource.Log.EventSendStart(this.ClientId, count, partitionKey); - Activity activity = EventHubsDiagnosticSource.StartSendActivity(this.ClientId, this.EventHubClient.ConnectionStringBuilder, partitionKey, eventDatas, count); + Activity activity = EventHubsDiagnosticSource.StartSendActivity(this.ClientId, this.EventHubClient.ConnectionStringBuilder, diagnosticPartitionKey, eventDatas, count); Task sendTask = null; try @@ -41,13 +44,13 @@ public async Task SendAsync(IEnumerable eventDatas, string partitionK catch (Exception exception) { EventHubsEventSource.Log.EventSendException(this.ClientId, exception.ToString()); - EventHubsDiagnosticSource.FailSendActivity(activity, this.EventHubClient.ConnectionStringBuilder, partitionKey, eventDatas, exception); + EventHubsDiagnosticSource.FailSendActivity(activity, this.EventHubClient.ConnectionStringBuilder, diagnosticPartitionKey, eventDatas, exception); throw; } finally { EventHubsEventSource.Log.EventSendStop(this.ClientId); - EventHubsDiagnosticSource.StopSendActivity(activity, this.EventHubClient.ConnectionStringBuilder, partitionKey, eventDatas, sendTask); + EventHubsDiagnosticSource.StopSendActivity(activity, this.EventHubClient.ConnectionStringBuilder, diagnosticPartitionKey, eventDatas, sendTask); } } diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs index 99a28adc22d4e..dd095e5ff177b 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs @@ -57,55 +57,70 @@ private static T GetPropertyValueFromAnonymousTypeInstance(object obj, string } [Test] - public async Task SendFiresEvents() + [TestCase(true)] + [TestCase(false)] + public async Task SendFiresEvents(bool usePartitionId) { await using (var scope = await EventHubScope.CreateAsync(1)) { var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); await using (var client = new EventHubClient(connectionString)) - await using (var producer = client.CreateProducer()) { - var eventQueue = CreateEventQueue(); + string partitionId = null; + string partitionKey = null; - using (var listener = CreateEventListener(eventQueue)) - using (var subscription = SubscribeToEvents(listener)) + if (usePartitionId) { - var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); - var eventData = new EventData(Encoding.UTF8.GetBytes("I hope it works!")); - var partitionKey = "AmIaGoodPartitionKey"; + partitionId = (await client.GetPartitionIdsAsync()).First(); + } + else + { + partitionKey = "AmIaGoodPartitionKey"; + } - // Enable Send .Start & .Stop events. + await using (var producer = client.CreateProducer(new EventHubProducerOptions { PartitionId = partitionId })) + { + var eventQueue = CreateEventQueue(); - listener.Enable((name, queueName, arg) => name.Contains("Send") && !name.EndsWith(".Exception")); + using (var listener = CreateEventListener(eventQueue)) + using (var subscription = SubscribeToEvents(listener)) + { + var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); + var eventData = new EventData(Encoding.UTF8.GetBytes("I hope it works!")); - Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.False); - Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.False); + // Enable Send .Start & .Stop events. - parentActivity.Start(); + listener.Enable((name, queueName, arg) => name.Contains("Send") && !name.EndsWith(".Exception")); - await producer.SendAsync(eventData, new SendOptions { PartitionKey = partitionKey }); + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.False); + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.False); - parentActivity.Stop(); + parentActivity.Start(); - // Check Diagnostic-Id injection. + await producer.SendAsync(eventData, new SendOptions { PartitionKey = partitionKey }); - Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.True); + parentActivity.Stop(); - // Check Correlation-Context injection. + // Check Diagnostic-Id injection. - Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.True); - Assert.That(TrackOne.EventHubsDiagnosticSource.SerializeCorrelationContext(parentActivity.Baggage.ToList()), Is.EqualTo(eventData.Properties[TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName])); + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.True); - Assert.That(eventQueue.TryDequeue(out var sendStart), Is.True); - AssertSendStart(sendStart.eventName, sendStart.payload, sendStart.activity, parentActivity, partitionKey, connectionString); + // Check Correlation-Context injection. - Assert.That(eventQueue.TryDequeue(out var sendStop), Is.True); - AssertSendStop(sendStop.eventName, sendStop.payload, sendStop.activity, sendStart.activity, partitionKey, connectionString); + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.True); + Assert.That(TrackOne.EventHubsDiagnosticSource.SerializeCorrelationContext(parentActivity.Baggage.ToList()), Is.EqualTo(eventData.Properties[TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName])); - // There should be no more events to dequeue. + Assert.That(eventQueue.TryDequeue(out var sendStart), Is.True); + AssertSendStart(sendStart.eventName, sendStart.payload, sendStart.activity, parentActivity, partitionKey ?? partitionId, connectionString); - Assert.That(eventQueue.TryDequeue(out var evnt), Is.False); + Assert.That(eventQueue.TryDequeue(out var sendStop), Is.True); + AssertSendStop(sendStop.eventName, sendStop.payload, sendStop.activity, sendStart.activity, partitionKey ?? partitionId, connectionString); + + // There should be no more events to dequeue. + + Assert.That(eventQueue.TryDequeue(out var evnt), Is.False); + } } } } @@ -160,47 +175,62 @@ public async Task SendDoesNotInjectContextWhenNoListeners() } [Test] - public async Task SendFiresExceptionEvents() + [TestCase(true)] + [TestCase(false)] + public async Task SendFiresExceptionEvents(bool usePartitionId) { await using (var scope = await EventHubScope.CreateAsync(1)) { var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); await using (var client = new EventHubClient(connectionString)) - await using (var producer = client.CreateProducer()) { - var eventQueue = CreateEventQueue(); + string partitionId = null; + string partitionKey = null; - using (var listener = CreateEventListener(eventQueue)) - using (var subscription = SubscribeToEvents(listener)) + if (usePartitionId) { - var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); - var eventData = new EventData(new byte[300 * 1024 * 1024]); - var partitionKey = "AmIaGoodPartitionKey"; + partitionId = (await client.GetPartitionIdsAsync()).First(); + } + else + { + partitionKey = "AmIaGoodPartitionKey"; + } - // Enable Send .Exception & .Stop events. + await using (var producer = client.CreateProducer(new EventHubProducerOptions { PartitionId = partitionId })) + { + var eventQueue = CreateEventQueue(); - listener.Enable((name, queueName, arg) => name.Contains("Send") && !name.EndsWith(".Start")); + using (var listener = CreateEventListener(eventQueue)) + using (var subscription = SubscribeToEvents(listener)) + { + var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); + var eventData = new EventData(new byte[1500000]); - parentActivity.Start(); + // Enable Send .Exception & .Stop events. - // Try sending a large message. A SizeLimitException is expected. + listener.Enable((name, queueName, arg) => name.Contains("Send") && !name.EndsWith(".Start")); - Assert.That(async () => await producer.SendAsync(eventData, new SendOptions { PartitionKey = partitionKey }), Throws.InstanceOf()); + parentActivity.Start(); - parentActivity.Stop(); + // Try sending a large message. A SizeLimitException is expected. - Assert.That(eventQueue.TryDequeue(out var exception), Is.True); - AssertSendException(exception.eventName, exception.payload, exception.activity, null, partitionKey, connectionString); + Assert.That(async () => await producer.SendAsync(eventData, new SendOptions { PartitionKey = partitionKey }), Throws.InstanceOf()); - Assert.That(eventQueue.TryDequeue(out var sendStop), Is.True); - AssertSendStop(sendStop.eventName, sendStop.payload, sendStop.activity, null, partitionKey, connectionString); + parentActivity.Stop(); - Assert.That(sendStop.activity, Is.EqualTo(exception.activity)); + Assert.That(eventQueue.TryDequeue(out var exception), Is.True); + AssertSendException(exception.eventName, exception.payload, exception.activity, null, partitionKey ?? partitionId, connectionString); - // There should be no more events to dequeue. + Assert.That(eventQueue.TryDequeue(out var sendStop), Is.True); + AssertSendStop(sendStop.eventName, sendStop.payload, sendStop.activity, null, partitionKey ?? partitionId, connectionString); - Assert.That(eventQueue.TryDequeue(out var evnt), Is.False); + Assert.That(sendStop.activity, Is.EqualTo(exception.activity)); + + // There should be no more events to dequeue. + + Assert.That(eventQueue.TryDequeue(out var evnt), Is.False); + } } } } From d70476054c8e1a4f20f59ba3fd8059ab8bf352a8 Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Tue, 16 Jul 2019 11:12:37 -0700 Subject: [PATCH 09/21] Non-live diagnostics tests added --- .../EventDataDiagnosticExtensions.cs | 2 +- .../tests/Diagnostics/DiagnosticsTests.cs | 148 ++++++++++++++++++ 2 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventDataDiagnosticExtensions.cs b/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventDataDiagnosticExtensions.cs index e881158e6c2e2..3de7d732b90cb 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventDataDiagnosticExtensions.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventDataDiagnosticExtensions.cs @@ -65,7 +65,7 @@ internal static class EventDataDiagnosticExtensions /// /// - public static Activity ExtractActivity(this EventData eventData, string activityName = null) + internal static Activity ExtractActivity(this EventData eventData, string activityName = null) { Guard.ArgumentNotNull(nameof(eventData), eventData); diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs new file mode 100644 index 0000000000000..2788326d0379d --- /dev/null +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs @@ -0,0 +1,148 @@ +using System.Diagnostics; +using System.Linq; +using System.Text; +using NUnit.Framework; + +namespace Azure.Messaging.EventHubs.Tests +{ + /// + /// Dummy. + /// + /// + [TestFixture] + [Parallelizable(ParallelScope.Children)] + class DiagnosticsTests + { + [Test] + public void ExtractsActivityWithIdAndNoContext() + { + var eventData = new EventData(Encoding.UTF8.GetBytes("test")); + + eventData.Properties["Diagnostic-Id"] = "diagnostic-id"; + + var activity = eventData.ExtractActivity(); + + Assert.That(activity.ParentId, Is.EqualTo("diagnostic-id")); + Assert.That(activity.RootId, Is.EqualTo("diagnostic-id")); + Assert.That(activity.Id, Is.Null); + + var baggage = activity.Baggage.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + Assert.That(baggage, Is.Empty); + } + + [Test] + public void ExtractsActivityWithIdAndSingleContext() + { + var eventData = new EventData(Encoding.UTF8.GetBytes("test")); + + eventData.Properties["Diagnostic-Id"] = "diagnostic-id"; + eventData.Properties["Correlation-Context"] = "k1=v1"; + + var activity = eventData.ExtractActivity(); + + Assert.That(activity.ParentId, Is.EqualTo("diagnostic-id")); + Assert.That(activity.RootId, Is.EqualTo("diagnostic-id")); + Assert.That(activity.Id, Is.Null); + + var baggage = activity.Baggage.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + + Assert.That(baggage.Count, Is.EqualTo(1)); + Assert.That(baggage.Keys.Contains("k1"), Is.True); + Assert.That(baggage["k1"], Is.EqualTo("v1")); + } + + [Test] + public void ExtractsActivityWithIdAndMultiContext() + { + var eventData = new EventData(Encoding.UTF8.GetBytes("test")); + + eventData.Properties["Diagnostic-Id"] = "diagnostic-id"; + eventData.Properties["Correlation-Context"] = "k1=v1,k2=v2,k3=v3"; + + var activity = eventData.ExtractActivity(); + + Assert.That(activity.ParentId, Is.EqualTo("diagnostic-id")); + Assert.That(activity.RootId, Is.EqualTo("diagnostic-id")); + Assert.That(activity.Id, Is.Null); + + var baggage = activity.Baggage.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + + Assert.That(baggage.Count, Is.EqualTo(3)); + Assert.That(baggage.Keys.Contains("k1"), Is.True); + Assert.That(baggage.Keys.Contains("k2"), Is.True); + Assert.That(baggage.Keys.Contains("k3"), Is.True); + Assert.That(baggage["k1"], Is.EqualTo("v1")); + Assert.That(baggage["k2"], Is.EqualTo("v2")); + Assert.That(baggage["k3"], Is.EqualTo("v3")); + } + + [Test] + public void ExtractActivityWithAlternateName() + { + var eventData = new EventData(Encoding.UTF8.GetBytes("test")); + + eventData.Properties["Diagnostic-Id"] = "diagnostic-id"; + + var activity = eventData.ExtractActivity("My activity"); + Assert.That(activity.OperationName, Is.EqualTo("My activity")); + } + + [Test] + [TestCase(null)] + [TestCase("")] + [TestCase("not valid context")] + [TestCase("not,valid,context")] + public void ExtractsActivityWithIdAndInvalidContext(string context) + { + var eventData = new EventData(Encoding.UTF8.GetBytes("test")); + + eventData.Properties["Diagnostic-Id"] = "diagnostic-id"; + eventData.Properties["Correlation-Context"] = context; + + var activity = eventData.ExtractActivity(); + + Assert.That(activity.ParentId, Is.EqualTo("diagnostic-id")); + Assert.That(activity.RootId, Is.EqualTo("diagnostic-id")); + Assert.That(activity.Id, Is.Null); + + var baggage = activity.Baggage.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + Assert.That(baggage, Is.Empty); + } + + [Test] + [TestCase(null)] + [TestCase("")] + public void ExtractsActivityWithoutIdAsRoot(string id) + { + var eventData = new EventData(Encoding.UTF8.GetBytes("test")); + + eventData.Properties["Diagnostic-Id"] = id; + eventData.Properties["Correlation-Context"] = "k1=v1,k2=v2"; + + var activity = eventData.ExtractActivity(); + + Assert.That(activity.ParentId, Is.Null); + Assert.That(activity.RootId, Is.Null); + Assert.That(activity.Id, Is.Null); + + // Baggage is ignored in absence of Id. + + var baggage = activity.Baggage.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + Assert.That(baggage, Is.Empty); + } + } + + internal static class EventDataDiagnosticExtensions + { + public static Activity ExtractActivity(this EventData eventData, string activityName = null) + { + static TrackOne.EventData TransformEvent(EventData eventData) => + new TrackOne.EventData(eventData.Body.ToArray()) + { + Properties = eventData.Properties + }; + + return TrackOne.EventDataDiagnosticExtensions.ExtractActivity(TransformEvent(eventData), activityName); + } + } +} From e422bc39b9ff2205e8404fe9912d830d1057dc27 Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Tue, 16 Jul 2019 14:15:13 -0700 Subject: [PATCH 10/21] Extension class moved to new namespace --- .../EventDataDiagnosticsExtensions.cs | 18 ++++++++++++++++++ .../tests/Diagnostics/DiagnosticsTests.cs | 18 ++---------------- 2 files changed, 20 insertions(+), 16 deletions(-) create mode 100644 sdk/eventhub/Azure.Messaging.EventHubs/src/Diagnostics/EventDataDiagnosticsExtensions.cs diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/src/Diagnostics/EventDataDiagnosticsExtensions.cs b/sdk/eventhub/Azure.Messaging.EventHubs/src/Diagnostics/EventDataDiagnosticsExtensions.cs new file mode 100644 index 0000000000000..61b275683cd7c --- /dev/null +++ b/sdk/eventhub/Azure.Messaging.EventHubs/src/Diagnostics/EventDataDiagnosticsExtensions.cs @@ -0,0 +1,18 @@ +using System.Diagnostics; + +namespace Azure.Messaging.EventHubs.Diagnostics +{ + internal static class EventDataDiagnosticsExtensions + { + public static Activity ExtractActivity(this EventData eventData, string activityName = null) + { + static TrackOne.EventData TransformEvent(EventData eventData) => + new TrackOne.EventData(eventData.Body.ToArray()) + { + Properties = eventData.Properties + }; + + return TrackOne.EventDataDiagnosticExtensions.ExtractActivity(TransformEvent(eventData), activityName); + } + } +} diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs index 2788326d0379d..aab383f274cb9 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs @@ -1,6 +1,6 @@ -using System.Diagnostics; -using System.Linq; +using System.Linq; using System.Text; +using Azure.Messaging.EventHubs.Diagnostics; using NUnit.Framework; namespace Azure.Messaging.EventHubs.Tests @@ -131,18 +131,4 @@ public void ExtractsActivityWithoutIdAsRoot(string id) Assert.That(baggage, Is.Empty); } } - - internal static class EventDataDiagnosticExtensions - { - public static Activity ExtractActivity(this EventData eventData, string activityName = null) - { - static TrackOne.EventData TransformEvent(EventData eventData) => - new TrackOne.EventData(eventData.Body.ToArray()) - { - Properties = eventData.Properties - }; - - return TrackOne.EventDataDiagnosticExtensions.ExtractActivity(TransformEvent(eventData), activityName); - } - } } From 4c5c446692dd4853e37fdc6c5e506149cbeb924f Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Wed, 17 Jul 2019 00:05:32 -0700 Subject: [PATCH 11/21] final comments --- .../samples/Sample7_ConsumeEvents.cs | 2 +- .../TrackOneExceptionExtensions.cs | 2 +- .../EventDataDiagnosticsExtensions.cs | 18 ++++- .../src/ExponentialRetry.cs | 2 +- .../Metadata/ConnectionStringProperties.cs | 2 +- .../Compatibility/TrackOneComparerTests.cs | 4 +- .../TrackOneEventHubProducerTests.cs | 8 +- .../tests/Core/ExponentialRetryTests.cs | 2 +- .../tests/Diagnostics/DiagnosticsLiveTests.cs | 74 ++++++++++++++----- .../tests/Diagnostics/DiagnosticsTests.cs | 38 +++++++++- .../Diagnostics/FakeDiagnosticListener.cs | 5 +- .../EventHubClient/EventHubClientLiveTests.cs | 2 +- .../EventHubConsumerLiveTests.cs | 2 +- .../EventHubProducerLiveTests.cs | 2 +- .../Infrastructure/EventDataExtensions.cs | 6 +- .../tests/Samples/SamplesLiveTests.cs | 2 +- 16 files changed, 132 insertions(+), 39 deletions(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample7_ConsumeEvents.cs b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample7_ConsumeEvents.cs index 73599a0a98ad2..a9b87fa7bf2b2 100755 --- a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample7_ConsumeEvents.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample7_ConsumeEvents.cs @@ -103,7 +103,7 @@ public async Task RunAsync(string connectionString, // time that we've allowed. // // We will ask for just our event, but allow a fairly long wait period to ensure that we're able to receive it. - // If you observe the time that the call takes, it is extremely likely that the request to recieve will complete + // If you observe the time that the call takes, it is extremely likely that the request to receive will complete // long before the maximum wait time. Stopwatch watch = Stopwatch.StartNew(); diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/src/Compatibility/TrackOneExceptionExtensions.cs b/sdk/eventhub/Azure.Messaging.EventHubs/src/Compatibility/TrackOneExceptionExtensions.cs index 9cf1ee8a870a9..2f2faddeedd4d 100755 --- a/sdk/eventhub/Azure.Messaging.EventHubs/src/Compatibility/TrackOneExceptionExtensions.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/src/Compatibility/TrackOneExceptionExtensions.cs @@ -13,7 +13,7 @@ namespace Azure.Messaging.EventHubs.Compatibility internal static class TrackOneExceptionExtensions { /// - /// Maps a or a child of it to the equivilent + /// Maps a or a child of it to the equivalent /// exception for the new API surface. /// /// diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/src/Diagnostics/EventDataDiagnosticsExtensions.cs b/sdk/eventhub/Azure.Messaging.EventHubs/src/Diagnostics/EventDataDiagnosticsExtensions.cs index 61b275683cd7c..ac8e622bb8246 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/src/Diagnostics/EventDataDiagnosticsExtensions.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/src/Diagnostics/EventDataDiagnosticsExtensions.cs @@ -1,9 +1,25 @@ -using System.Diagnostics; +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Diagnostics; namespace Azure.Messaging.EventHubs.Diagnostics { + /// + /// Diagnostic extension methods for . + /// + /// internal static class EventDataDiagnosticsExtensions { + /// + /// Creates based on the tracing context stored in the . + /// + /// + /// The event received from EventHub. + /// Optional Activity name. + /// + /// New with tracing context. + /// public static Activity ExtractActivity(this EventData eventData, string activityName = null) { static TrackOne.EventData TransformEvent(EventData eventData) => diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/src/ExponentialRetry.cs b/sdk/eventhub/Azure.Messaging.EventHubs/src/ExponentialRetry.cs index 82695132ac81a..2425736a50b8c 100755 --- a/sdk/eventhub/Azure.Messaging.EventHubs/src/ExponentialRetry.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/src/ExponentialRetry.cs @@ -94,7 +94,7 @@ internal override Retry Clone() => /// The set of properties for the retry policy. /// /// - /// This method is intended to allow for compatibility shims to create the equivilent retry + /// This method is intended to allow for compatibility shims to create the equivalent retry /// policy within the track one code; it will be removed after the first preview and should /// not be depended upon outside of that context. /// diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/src/Metadata/ConnectionStringProperties.cs b/sdk/eventhub/Azure.Messaging.EventHubs/src/Metadata/ConnectionStringProperties.cs index a8d3c42075f6a..9a414f449b14b 100755 --- a/sdk/eventhub/Azure.Messaging.EventHubs/src/Metadata/ConnectionStringProperties.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/src/Metadata/ConnectionStringProperties.cs @@ -44,7 +44,7 @@ internal struct ConnectionStringProperties /// Initializes a new instance of the struct. /// /// - /// The endpoint of the EVent Hubs namespace. + /// The endpoint of the Event Hubs namespace. /// The path to the specific Event Hub under the namespace. /// The name of the shared access key, to use authorization. /// The shared access key to use for authorization. diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Compatibility/TrackOneComparerTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Compatibility/TrackOneComparerTests.cs index 94856c867833b..068504e4e39e2 100755 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Compatibility/TrackOneComparerTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Compatibility/TrackOneComparerTests.cs @@ -142,7 +142,7 @@ public void IsEventPositionEquivalentDetectsDifferentOffsets() var trackOnePosition = TrackOne.EventPosition.FromOffset("12", false); var trackTwoPosition = EventPosition.FromOffset(12); - Assert.That(TrackOneComparer.IsEventPositionEquivalent(trackOnePosition, trackTwoPosition), Is.False, "The offset for track two is inclusive; even the same base offset with non-inclusive is not equivilent."); + Assert.That(TrackOneComparer.IsEventPositionEquivalent(trackOnePosition, trackTwoPosition), Is.False, "The offset for track two is inclusive; even the same base offset with non-inclusive is not equivalent."); } /// @@ -156,7 +156,7 @@ public void IsEventPositionEquivalentRecognizesSameOffsets() var trackOnePosition = TrackOne.EventPosition.FromOffset("12", true); var trackTwoPosition = EventPosition.FromOffset(12); - Assert.That(TrackOneComparer.IsEventPositionEquivalent(trackOnePosition, trackTwoPosition), Is.True, "The offset for track two is inclusive; the equivilent offset set as inclusive should match."); + Assert.That(TrackOneComparer.IsEventPositionEquivalent(trackOnePosition, trackTwoPosition), Is.True, "The offset for track two is inclusive; the equivalent offset set as inclusive should match."); } /// diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Compatibility/TrackOneEventHubProducerTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Compatibility/TrackOneEventHubProducerTests.cs index 3371b31e14f4f..96e47fa5dce2e 100755 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Compatibility/TrackOneEventHubProducerTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Compatibility/TrackOneEventHubProducerTests.cs @@ -98,8 +98,8 @@ public async Task SendAsyncTransformsSimpleEvents() var sentEvents = mock.SendCalledWithParameters.Events.ToArray(); Assert.That(sentEvents.Length, Is.EqualTo(sourceEvents.Length), "The number of events sent should match the number of source events."); - // The events should not only be structurally equivilent, the ordering of them should be preserved. Compare the - // sequence in order and validate that the events in each position are equivilent. + // The events should not only be structurally equivalent, the ordering of them should be preserved. Compare the + // sequence in order and validate that the events in each position are equivalent. for (var index = 0; index < sentEvents.Length; ++index) { @@ -138,8 +138,8 @@ public async Task SendAsyncTransformsComplexEvents() var sentEvents = mock.SendCalledWithParameters.Events.ToArray(); Assert.That(sentEvents.Length, Is.EqualTo(sourceEvents.Length), "The number of events sent should match the number of source events."); - // The events should not only be structurally equivilent, the ordering of them should be preserved. Compare the - // sequence in order and validate that the events in each position are equivilent. + // The events should not only be structurally equivalent, the ordering of them should be preserved. Compare the + // sequence in order and validate that the events in each position are equivalent. for (var index = 0; index < sentEvents.Length; ++index) { diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Core/ExponentialRetryTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Core/ExponentialRetryTests.cs index d71a0040cb596..3543d6919e472 100755 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Core/ExponentialRetryTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Core/ExponentialRetryTests.cs @@ -62,7 +62,7 @@ public void ConstructorValidatesArguments() /// [Test] [TestCaseSource(nameof(SameConfigurationCases))] - public void HaveSameConfigurationRecognizesEquivilentConfiguration(ExponentialRetry first, + public void HaveSameConfigurationRecognizesEquivalentConfiguration(ExponentialRetry first, ExponentialRetry second, string description) { diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs index dd095e5ff177b..5131dc7eaf7a6 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; @@ -15,9 +18,15 @@ namespace Azure.Messaging.EventHubs.Tests { /// - /// Dummy. + /// The suite of live tests for the + /// class. /// /// + /// + /// These tests have a depenency on live Azure services and may + /// incur costs for the associated Azure subscription. + /// + /// [TestFixture] [NonParallelizable] [Category(TestCategory.Live)] @@ -56,6 +65,11 @@ private static T GetPropertyValueFromAnonymousTypeInstance(object obj, string return (T)propertyValue; } + /// + /// Verifies that the fires + /// events as expected. + /// + /// [Test] [TestCase(true)] [TestCase(false)] @@ -93,9 +107,13 @@ public async Task SendFiresEvents(bool usePartitionId) listener.Enable((name, queueName, arg) => name.Contains("Send") && !name.EndsWith(".Exception")); + // Assert that the properties we want to inject are not already included. + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.False); Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.False); + // Send the event. + parentActivity.Start(); await producer.SendAsync(eventData, new SendOptions { PartitionKey = partitionKey }); @@ -111,6 +129,8 @@ public async Task SendFiresEvents(bool usePartitionId) Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.True); Assert.That(TrackOne.EventHubsDiagnosticSource.SerializeCorrelationContext(parentActivity.Baggage.ToList()), Is.EqualTo(eventData.Properties[TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName])); + // Check diagnostics information. + Assert.That(eventQueue.TryDequeue(out var sendStart), Is.True); AssertSendStart(sendStart.eventName, sendStart.payload, sendStart.activity, parentActivity, partitionKey ?? partitionId, connectionString); @@ -126,6 +146,11 @@ public async Task SendFiresEvents(bool usePartitionId) } } + /// + /// Verifies that the fires + /// events as expected. + /// + /// [Test] public async Task SendDoesNotInjectContextWhenNoListeners() { @@ -141,7 +166,6 @@ public async Task SendDoesNotInjectContextWhenNoListeners() using (var listener = CreateEventListener(eventQueue)) using (var subscription = SubscribeToEvents(listener)) { - // TODO: is parentActivity necessary? var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); var eventData = new EventData(Encoding.UTF8.GetBytes("I hope it works!")); @@ -149,9 +173,13 @@ public async Task SendDoesNotInjectContextWhenNoListeners() listener.Disable(); + // Assert that the properties we will check are not already included. + Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.False); Assert.That(eventData.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.False); + // Send the event. + parentActivity.Start(); await producer.SendAsync(eventData); @@ -174,6 +202,11 @@ public async Task SendDoesNotInjectContextWhenNoListeners() } } + /// + /// Verifies that the fires + /// events as expected. + /// + /// [Test] [TestCase(true)] [TestCase(false)] @@ -211,14 +244,16 @@ public async Task SendFiresExceptionEvents(bool usePartitionId) listener.Enable((name, queueName, arg) => name.Contains("Send") && !name.EndsWith(".Start")); - parentActivity.Start(); - // Try sending a large message. A SizeLimitException is expected. + parentActivity.Start(); + Assert.That(async () => await producer.SendAsync(eventData, new SendOptions { PartitionKey = partitionKey }), Throws.InstanceOf()); parentActivity.Stop(); + // Check diagnostics information. + Assert.That(eventQueue.TryDequeue(out var exception), Is.True); AssertSendException(exception.eventName, exception.payload, exception.activity, null, partitionKey ?? partitionId, connectionString); @@ -236,6 +271,11 @@ public async Task SendFiresExceptionEvents(bool usePartitionId) } } + /// + /// Verifies that the fires + /// events as expected. + /// + /// [Test] public async Task ReceiveFiresEvents() { @@ -253,8 +293,9 @@ public async Task ReceiveFiresEvents() using (var subscription = SubscribeToEvents(listener)) await using (var consumer = client.CreateConsumer(EventHubConsumer.DefaultConsumerGroupName, partition, EventPosition.Latest)) { + var payloadString = "Easter Egg"; var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); - var sendEvent = new EventData(Encoding.UTF8.GetBytes("I hope it works!")); + var sendEvent = new EventData(Encoding.UTF8.GetBytes(payloadString)); // Initiate an operation to force the consumer to connect and set its position at the // end of the event stream. @@ -265,16 +306,18 @@ public async Task ReceiveFiresEvents() listener.Enable((name, queueName, arg) => !name.EndsWith(".Exception")); - // Send the batch of events. + // Assert that the properties we want to inject are not already included. Assert.That(sendEvent.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.ActivityIdPropertyName), Is.False); Assert.That(sendEvent.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.False); + // Send the event. + parentActivity.Start(); await producer.SendAsync(sendEvent); - // Receive and the event; because there is some non-determinism in the messaging flow, the + // Receive the event; because there is some non-determinism in the messaging flow, the // sent event may not be immediately available. Allow for a small number of attempts to receive, in order // to account for availability delays. @@ -289,8 +332,10 @@ public async Task ReceiveFiresEvents() parentActivity.Stop(); + // Validate the received event body. + var receivedEvent = receivedEvents.Single(); - // TODO: check payload string? + Assert.That(Encoding.UTF8.GetString(receivedEvent.Body.ToArray()), Is.EqualTo(payloadString)); // Check Diagnostic-Id injection. @@ -301,13 +346,13 @@ public async Task ReceiveFiresEvents() // Check Correlation-Context injection. Assert.That(receivedEvent.Properties.ContainsKey(TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName), Is.True); - // TODO: change order - Assert.That(TrackOne.EventHubsDiagnosticSource.SerializeCorrelationContext(parentActivity.Baggage.ToList()), Is.EqualTo(receivedEvent.Properties[TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName])); + Assert.That(receivedEvent.Properties[TrackOne.EventHubsDiagnosticSource.CorrelationContextPropertyName], Is.EqualTo(TrackOne.EventHubsDiagnosticSource.SerializeCorrelationContext(parentActivity.Baggage.ToList()))); + + // Check diagnostics information. Assert.That(eventQueue.TryDequeue(out var sendStart), Is.True); Assert.That(eventQueue.TryDequeue(out var sendStop), Is.True); - // TODO: isParentActivity necessary? Assert.That(eventQueue.TryDequeue(out var receiveStart), Is.True); AssertReceiveStart(receiveStart.eventName, receiveStart.payload, receiveStart.activity, partition, connectionString); @@ -363,8 +408,6 @@ private void AssertSendException(string name, object payload, Activity activity, Assert.That(activity.Parent, Is.EqualTo(parentActivity)); } - // TODO: keep track one? - // TODO: why doesn't IList work? var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); Assert.That(eventDatas, Is.Not.Null); } @@ -447,9 +490,6 @@ private static void AssertCommonPayloadProperties(object eventPayload, string pa var entityPath = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "Entity"); var pKey = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "PartitionKey"); - // endpoint is amqps://cooleventhubs.servicebus.windows.net/SendFiresExceptionEvents-a2fda415 - // connectionString is sb://cooleventhubs.servicebus.windows.net/ - // TODO: should we update the diagnostics output? var expectedEndpointStart = "amqps://" + connectionStringProperties.Endpoint.Host; Assert.That(endpoint.AbsoluteUri.StartsWith(expectedEndpointStart), Is.True); diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs index aab383f274cb9..12964dc1e7954 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs @@ -1,4 +1,7 @@ -using System.Linq; +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Linq; using System.Text; using Azure.Messaging.EventHubs.Diagnostics; using NUnit.Framework; @@ -6,13 +9,19 @@ namespace Azure.Messaging.EventHubs.Tests { /// - /// Dummy. + /// The suite of tests for the + /// class. /// /// [TestFixture] [Parallelizable(ParallelScope.Children)] class DiagnosticsTests { + /// + /// Verifies functionality of the extension + /// method. + /// + /// [Test] public void ExtractsActivityWithIdAndNoContext() { @@ -30,6 +39,11 @@ public void ExtractsActivityWithIdAndNoContext() Assert.That(baggage, Is.Empty); } + /// + /// Verifies functionality of the extension + /// method. + /// + /// [Test] public void ExtractsActivityWithIdAndSingleContext() { @@ -51,6 +65,11 @@ public void ExtractsActivityWithIdAndSingleContext() Assert.That(baggage["k1"], Is.EqualTo("v1")); } + /// + /// Verifies functionality of the extension + /// method. + /// + /// [Test] public void ExtractsActivityWithIdAndMultiContext() { @@ -76,6 +95,11 @@ public void ExtractsActivityWithIdAndMultiContext() Assert.That(baggage["k3"], Is.EqualTo("v3")); } + /// + /// Verifies functionality of the extension + /// method. + /// + /// [Test] public void ExtractActivityWithAlternateName() { @@ -87,6 +111,11 @@ public void ExtractActivityWithAlternateName() Assert.That(activity.OperationName, Is.EqualTo("My activity")); } + /// + /// Verifies functionality of the extension + /// method. + /// + /// [Test] [TestCase(null)] [TestCase("")] @@ -109,6 +138,11 @@ public void ExtractsActivityWithIdAndInvalidContext(string context) Assert.That(baggage, Is.Empty); } + /// + /// Verifies functionality of the extension + /// method. + /// + /// [Test] [TestCase(null)] [TestCase("")] diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/FakeDiagnosticListener.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/FakeDiagnosticListener.cs index 90577d462c28b..8cd75d9a1e69b 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/FakeDiagnosticListener.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/FakeDiagnosticListener.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/EventHubClient/EventHubClientLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/EventHubClient/EventHubClientLiveTests.cs index bf9a0aab51bd1..6a9f47eb77313 100755 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/EventHubClient/EventHubClientLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/EventHubClient/EventHubClientLiveTests.cs @@ -22,7 +22,7 @@ namespace Azure.Messaging.EventHubs.Tests /// /// /// These tests have a depenency on live Azure services and may - /// incur costs for the assocaied Azure subscription. + /// incur costs for the associated Azure subscription. /// /// [TestFixture] diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/EventHubConsumer/EventHubConsumerLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/EventHubConsumer/EventHubConsumerLiveTests.cs index a7825b7873373..394636b10bf1a 100755 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/EventHubConsumer/EventHubConsumerLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/EventHubConsumer/EventHubConsumerLiveTests.cs @@ -195,7 +195,7 @@ public async Task ReceiveCanReadMultipleEventBatches() await producer.SendAsync(eventBatch); - // Recieve and validate the events; because there is some non-determinism in the messaging flow, the + // Receive and validate the events; because there is some non-determinism in the messaging flow, the // sent events may not be immediately available. Allow for a small number of attempts to receive, in order // to account for availability delays. diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/EventHubProducer/EventHubProducerLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/EventHubProducer/EventHubProducerLiveTests.cs index 3d80976268796..603f8204e3577 100755 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/EventHubProducer/EventHubProducerLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/EventHubProducer/EventHubProducerLiveTests.cs @@ -21,7 +21,7 @@ namespace Azure.Messaging.EventHubs.Tests /// /// /// These tests have a depenency on live Azure services and may - /// incur costs for the assocaied Azure subscription. + /// incur costs for the associated Azure subscription. /// /// [TestFixture] diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Infrastructure/EventDataExtensions.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Infrastructure/EventDataExtensions.cs index 215ce5f23241b..9f645b035eee3 100755 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Infrastructure/EventDataExtensions.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Infrastructure/EventDataExtensions.cs @@ -22,7 +22,7 @@ internal static class EventDataExtensions /// The other event to consider. /// If true, the will be considered; otherwise, differences will be ignored. /// - /// true, if the two events are structurally equivilent; otherwise, false. + /// true, if the two events are structurally equivalent; otherwise, false. /// public static bool IsEquivalentTo(this EventData instance, EventData other, @@ -60,7 +60,7 @@ public static bool IsEquivalentTo(this EventData instance, return false; } - // Verify the system properties are equivilent, unless they're the same reference. + // Verify the system properties are equivalent, unless they're the same reference. if ((considerSystemProperties) && (!Object.ReferenceEquals(instance.SystemProperties, other.SystemProperties))) { @@ -99,7 +99,7 @@ public static bool IsEquivalentTo(this EventData instance, return false; } - // The only meaningful comparison left is to ensure that the property sets are equivilent, + // The only meaningful comparison left is to ensure that the property sets are equivalent, // the outcome of this check is the final word on equality. if (instance.Properties.Count != other.Properties.Count) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Samples/SamplesLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Samples/SamplesLiveTests.cs index b46660de4511b..5ce6866386600 100755 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Samples/SamplesLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Samples/SamplesLiveTests.cs @@ -18,7 +18,7 @@ namespace Azure.Messaging.EventHubs.Tests /// /// /// These tests have a depenency on live Azure services and may - /// incur costs for the assocaied Azure subscription. + /// incur costs for the associated Azure subscription. /// /// [TestFixture] From 6fea5fac9781d3db4f89fdebc1ef6aa5acc2b5e5 Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Wed, 17 Jul 2019 00:17:37 -0700 Subject: [PATCH 12/21] Diagnostics contain Track Two Event Data. --- .../TrackOneClient/EventHubsDiagnosticSource.cs | 14 ++++++++++---- .../tests/Diagnostics/DiagnosticsLiveTests.cs | 6 +++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventHubsDiagnosticSource.cs b/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventHubsDiagnosticSource.cs index c0eabe464173d..4bf303beb38da 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventHubsDiagnosticSource.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventHubsDiagnosticSource.cs @@ -64,7 +64,7 @@ internal static Activity StartSendActivity(string clientId, EventHubsConnectionS csb.Endpoint, Entity = csb.EntityPath, PartitionKey = partitionKey, - EventDatas = eventDatas + EventDatas = eventDatas.Select(TransformEvent) }); } else @@ -90,7 +90,7 @@ internal static void FailSendActivity(Activity activity, EventHubsConnectionStri csb.Endpoint, Entity = csb.EntityPath, PartitionKey = partitionKey, - EventDatas = eventDatas, + EventDatas = eventDatas.Select(TransformEvent), Exception = ex }); } @@ -108,7 +108,7 @@ internal static void StopSendActivity(Activity activity, EventHubsConnectionStri csb.Endpoint, Entity = csb.EntityPath, PartitionKey = partitionKey, - EventDatas = eventDatas, + EventDatas = eventDatas.Select(TransformEvent), sendTask?.Status }); } @@ -201,7 +201,7 @@ internal static void StopReceiveActivity(Activity activity, EventHubsConnectionS Entity = csb.EntityPath, PartitionKey = partitionKey, ConsumerGroup = consumerGroup, - EventDatas = events, + EventDatas = events.Select(TransformEvent), receiveTask?.Status }); } @@ -262,5 +262,11 @@ private static void SetRelatedOperations(Activity activity, IEnumerable + new Azure.Messaging.EventHubs.EventData(eventData.Body.ToArray()) + { + Properties = eventData.Properties + }; } } diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs index 5131dc7eaf7a6..78e807ce8c10e 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs @@ -374,7 +374,7 @@ private static void AssertSendStart(string name, object payload, Activity activi Assert.That(name, Is.EqualTo("Azure.Messaging.EventHubs.Send.Start")); AssertCommonPayloadProperties(payload, partitionKey, connectionStringProperties); - var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); + var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); Assert.That(eventDatas.Count, Is.EqualTo(eventCount)); Assert.That(activity, Is.Not.Null); @@ -408,7 +408,7 @@ private void AssertSendException(string name, object payload, Activity activity, Assert.That(activity.Parent, Is.EqualTo(parentActivity)); } - var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); + var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); Assert.That(eventDatas, Is.Not.Null); } @@ -424,7 +424,7 @@ private static void AssertSendStop(string name, object payload, Activity activit Assert.That(activity, Is.EqualTo(sendActivity)); } - var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); + var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); Assert.That(eventDatas, Is.Not.Null); } From dd6eb762aa7d384398518a49d74e512c9e861bcf Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Wed, 17 Jul 2019 02:00:28 -0700 Subject: [PATCH 13/21] Reorder; more comments and small fix in diagnostics asserts. --- .../tests/Diagnostics/DiagnosticsLiveTests.cs | 54 ++++++++++++++++--- 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs index 78e807ce8c10e..630decf49c4cf 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs @@ -371,12 +371,19 @@ private static void AssertSendStart(string name, object payload, Activity activi { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); + // Check name. + Assert.That(name, Is.EqualTo("Azure.Messaging.EventHubs.Send.Start")); + + // Check payload. + AssertCommonPayloadProperties(payload, partitionKey, connectionStringProperties); var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); Assert.That(eventDatas.Count, Is.EqualTo(eventCount)); + // Check Activity and its tags. + Assert.That(activity, Is.Not.Null); Assert.That(activity.Parent, Is.EqualTo(parentActivity)); @@ -396,45 +403,66 @@ private void AssertSendException(string name, object payload, Activity activity, { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); + // Check name. + Assert.That(name, Is.EqualTo("Azure.Messaging.EventHubs.Send.Exception")); + + // Check payload. + AssertCommonPayloadProperties(payload, partitionKey, connectionStringProperties); + var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); + Assert.That(eventDatas, Is.Not.Null); + GetPropertyValueFromAnonymousTypeInstance(payload, "Exception"); + // Check Activity. + Assert.That(activity, Is.Not.Null); if (parentActivity != null) { Assert.That(activity.Parent, Is.EqualTo(parentActivity)); } - - var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); - Assert.That(eventDatas, Is.Not.Null); } private static void AssertSendStop(string name, object payload, Activity activity, Activity sendActivity, string partitionKey, string connectionString, bool isFaulted = false) { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); + // Check name. + Assert.That(name, Is.EqualTo("Azure.Messaging.EventHubs.Send.Stop")); - AssertCommonStopPayloadProperties(payload, partitionKey, isFaulted, connectionStringProperties); ; + + // Check payload. + + AssertCommonStopPayloadProperties(payload, partitionKey, isFaulted, connectionStringProperties); + + var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); + Assert.That(eventDatas, Is.Not.Null); + + // Check Activity. if (sendActivity != null) { Assert.That(activity, Is.EqualTo(sendActivity)); } - - var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); - Assert.That(eventDatas, Is.Not.Null); } private static void AssertReceiveStart(string name, object payload, Activity activity, string partitionKey, string connectionString) { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); + // Check name. + Assert.That(name, Is.EqualTo("Azure.Messaging.EventHubs.Receive.Start")); + + // Check payload. + AssertCommonPayloadProperties(payload, partitionKey, connectionStringProperties); + // Check Activity and its tags. + Assert.That(activity, Is.Not.Null); AssertTagMatches(activity, "peer.hostname", connectionStringProperties.Endpoint.Host); @@ -455,9 +483,16 @@ private static void AssertReceiveStop(string name, object payload, Activity acti { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); + // Check name. + Assert.That(name, Is.EqualTo("Azure.Messaging.EventHubs.Receive.Stop")); + + // Check payload. + AssertCommonStopPayloadProperties(payload, partitionKey, isFaulted, connectionStringProperties); + // Check Activity and its tags. + if (receiveActivity != null) { Assert.That(activity, Is.EqualTo(receiveActivity)); @@ -499,7 +534,12 @@ private static void AssertCommonPayloadProperties(object eventPayload, string pa private static void AssertCommonStopPayloadProperties(object eventPayload, string partitionKey, bool isFaulted, ConnectionStringProperties connectionStringProperties) { + var expectedStatus = isFaulted ? TaskStatus.Faulted : TaskStatus.RanToCompletion; + AssertCommonPayloadProperties(eventPayload, partitionKey, connectionStringProperties); + + var status = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "Status"); + Assert.That(status, Is.EqualTo(expectedStatus)); } } } From 40e7963a6874479ebd7475f483b032c26bbcd250 Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Wed, 17 Jul 2019 02:04:13 -0700 Subject: [PATCH 14/21] Small fix: isFaulted --- .../tests/Diagnostics/DiagnosticsLiveTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs index 630decf49c4cf..1fecff0822ce4 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs @@ -258,7 +258,7 @@ public async Task SendFiresExceptionEvents(bool usePartitionId) AssertSendException(exception.eventName, exception.payload, exception.activity, null, partitionKey ?? partitionId, connectionString); Assert.That(eventQueue.TryDequeue(out var sendStop), Is.True); - AssertSendStop(sendStop.eventName, sendStop.payload, sendStop.activity, null, partitionKey ?? partitionId, connectionString); + AssertSendStop(sendStop.eventName, sendStop.payload, sendStop.activity, null, partitionKey ?? partitionId, connectionString, isFaulted: true); Assert.That(sendStop.activity, Is.EqualTo(exception.activity)); From b1da09828c52787d62e7a055d47fe04335990468 Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Wed, 17 Jul 2019 03:23:04 -0700 Subject: [PATCH 15/21] Final changes to increase coverage. --- .../tests/Diagnostics/DiagnosticsLiveTests.cs | 82 +++++++++++-------- 1 file changed, 46 insertions(+), 36 deletions(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs index 1fecff0822ce4..221ddf4cae48a 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs @@ -59,6 +59,14 @@ private static T GetPropertyValueFromAnonymousTypeInstance(object obj, string PropertyInfo p = t.GetRuntimeProperty(propertyName); object propertyValue = p.GetValue(obj); + // If a null string property was found, return it. This is necessary for testing + // the PartitionKey property when no Partition Key or Partition Id was set. + + if (typeof(T) == typeof(string) && propertyValue == null) + { + return (T)propertyValue; + } + Assert.That(propertyValue, Is.Not.Null); Assert.That(propertyValue, Is.AssignableTo()); @@ -71,9 +79,10 @@ private static T GetPropertyValueFromAnonymousTypeInstance(object obj, string /// /// [Test] - [TestCase(true)] - [TestCase(false)] - public async Task SendFiresEvents(bool usePartitionId) + [TestCase(null, false)] + [TestCase(null, true)] + [TestCase("AmIaGoodPartitionKey", false)] + public async Task SendFiresEvents(string partitionKey, bool usePartitionId) { await using (var scope = await EventHubScope.CreateAsync(1)) { @@ -82,16 +91,11 @@ public async Task SendFiresEvents(bool usePartitionId) await using (var client = new EventHubClient(connectionString)) { string partitionId = null; - string partitionKey = null; if (usePartitionId) { partitionId = (await client.GetPartitionIdsAsync()).First(); } - else - { - partitionKey = "AmIaGoodPartitionKey"; - } await using (var producer = client.CreateProducer(new EventHubProducerOptions { PartitionId = partitionId })) { @@ -208,9 +212,10 @@ public async Task SendDoesNotInjectContextWhenNoListeners() /// /// [Test] - [TestCase(true)] - [TestCase(false)] - public async Task SendFiresExceptionEvents(bool usePartitionId) + [TestCase(null, false)] + [TestCase(null, true)] + [TestCase("AmIaGoodPartitionKey", false)] + public async Task SendFiresExceptionEvents(string partitionKey, bool usePartitionId) { await using (var scope = await EventHubScope.CreateAsync(1)) { @@ -219,16 +224,11 @@ public async Task SendFiresExceptionEvents(bool usePartitionId) await using (var client = new EventHubClient(connectionString)) { string partitionId = null; - string partitionKey = null; if (usePartitionId) { partitionId = (await client.GetPartitionIdsAsync()).First(); } - else - { - partitionKey = "AmIaGoodPartitionKey"; - } await using (var producer = client.CreateProducer(new EventHubProducerOptions { PartitionId = partitionId })) { @@ -255,7 +255,7 @@ public async Task SendFiresExceptionEvents(bool usePartitionId) // Check diagnostics information. Assert.That(eventQueue.TryDequeue(out var exception), Is.True); - AssertSendException(exception.eventName, exception.payload, exception.activity, null, partitionKey ?? partitionId, connectionString); + AssertSendException(exception.eventName, exception.payload, exception.activity, parentActivity, partitionKey ?? partitionId, connectionString); Assert.That(eventQueue.TryDequeue(out var sendStop), Is.True); AssertSendStop(sendStop.eventName, sendStop.payload, sendStop.activity, null, partitionKey ?? partitionId, connectionString, isFaulted: true); @@ -288,10 +288,12 @@ public async Task ReceiveFiresEvents() { var eventQueue = CreateEventQueue(); var partition = (await client.GetPartitionIdsAsync()).First(); + var consumerGroup = EventHubConsumer.DefaultConsumerGroupName; + EventPosition position = EventPosition.Latest; using (var listener = CreateEventListener(eventQueue)) using (var subscription = SubscribeToEvents(listener)) - await using (var consumer = client.CreateConsumer(EventHubConsumer.DefaultConsumerGroupName, partition, EventPosition.Latest)) + await using (var consumer = client.CreateConsumer(consumerGroup, partition, position)) { var payloadString = "Easter Egg"; var parentActivity = new Activity("RandomName").AddBaggage("k1", "v1").AddBaggage("k2", "v2"); @@ -354,10 +356,10 @@ public async Task ReceiveFiresEvents() Assert.That(eventQueue.TryDequeue(out var sendStop), Is.True); Assert.That(eventQueue.TryDequeue(out var receiveStart), Is.True); - AssertReceiveStart(receiveStart.eventName, receiveStart.payload, receiveStart.activity, partition, connectionString); + AssertReceiveStart(receiveStart.eventName, receiveStart.payload, receiveStart.activity, parentActivity, consumerGroup, position, partition, connectionString); Assert.That(eventQueue.TryDequeue(out var receiveStop), Is.True); - AssertReceiveStop(receiveStop.eventName, receiveStop.payload, receiveStop.activity, receiveStart.activity, partition, connectionString, relatedId: sendStop.activity.Id); + AssertReceiveStop(receiveStop.eventName, receiveStop.payload, receiveStop.activity, receiveStart.activity, consumerGroup, partition, connectionString, relatedId: sendStop.activity.Id); // There should be no more events to dequeue. @@ -385,16 +387,15 @@ private static void AssertSendStart(string name, object payload, Activity activi // Check Activity and its tags. Assert.That(activity, Is.Not.Null); - Assert.That(activity.Parent, Is.EqualTo(parentActivity)); - - AssertTagMatches(activity, "peer.hostname", connectionStringProperties.Endpoint.Host); - AssertTagMatches(activity, "eh.event_hub_name", connectionStringProperties.EventHubPath); - if (partitionKey != null) + if (parentActivity != null) { - AssertTagMatches(activity, "eh.partition_key", partitionKey); + Assert.That(activity.Parent, Is.EqualTo(parentActivity)); } + AssertTagMatches(activity, "peer.hostname", connectionStringProperties.Endpoint.Host); + AssertTagMatches(activity, "eh.event_hub_name", connectionStringProperties.EventHubPath); + AssertTagMatches(activity, "eh.partition_key", partitionKey); AssertTagMatches(activity, "eh.event_count", eventCount.ToString()); AssertTagExists(activity, "eh.client_id"); } @@ -449,7 +450,7 @@ private static void AssertSendStop(string name, object payload, Activity activit } } - private static void AssertReceiveStart(string name, object payload, Activity activity, string partitionKey, string connectionString) + private static void AssertReceiveStart(string name, object payload, Activity activity, Activity parentActivity, string consumerGroup, EventPosition position, string partitionKey, string connectionString) { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); @@ -465,21 +466,22 @@ private static void AssertReceiveStart(string name, object payload, Activity act Assert.That(activity, Is.Not.Null); - AssertTagMatches(activity, "peer.hostname", connectionStringProperties.Endpoint.Host); - AssertTagMatches(activity, "eh.event_hub_name", connectionStringProperties.EventHubPath); - - if (partitionKey != null) + if (parentActivity != null) { - AssertTagMatches(activity, "eh.partition_key", partitionKey); + Assert.That(activity.Parent, Is.EqualTo(parentActivity)); } - AssertTagExists(activity, "eh.event_count"); + AssertTagMatches(activity, "peer.hostname", connectionStringProperties.Endpoint.Host); + AssertTagMatches(activity, "eh.event_hub_name", connectionStringProperties.EventHubPath); + AssertTagMatches(activity, "eh.partition_key", partitionKey); + AssertTagMatches(activity, "eh.consumer_group", consumerGroup); + AssertTagMatches(activity, "eh.start_offset", position.Offset); + AssertTagMatches(activity, "eh.start_sequence_number", position.SequenceNumber?.ToString()); + AssertTagMatches(activity, "eh.start_date_time", position.EnqueuedTime?.UtcDateTime.ToString()); AssertTagExists(activity, "eh.client_id"); - AssertTagExists(activity, "eh.consumer_group"); - AssertTagExists(activity, "eh.start_offset"); } - private static void AssertReceiveStop(string name, object payload, Activity activity, Activity receiveActivity, string partitionKey, string connectionString, bool isFaulted = false, string relatedId = null) + private static void AssertReceiveStop(string name, object payload, Activity activity, Activity receiveActivity, string consumerGroup, string partitionKey, string connectionString, int eventCount = 1, bool isFaulted = false, string relatedId = null) { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); @@ -491,6 +493,12 @@ private static void AssertReceiveStop(string name, object payload, Activity acti AssertCommonStopPayloadProperties(payload, partitionKey, isFaulted, connectionStringProperties); + var payloadConsumerGroup = GetPropertyValueFromAnonymousTypeInstance(payload, "ConsumerGroup"); + Assert.That(payloadConsumerGroup, Is.EqualTo(consumerGroup)); + + var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); + Assert.That(eventDatas.Count, Is.EqualTo(eventCount)); + // Check Activity and its tags. if (receiveActivity != null) @@ -506,6 +514,8 @@ private static void AssertReceiveStop(string name, object payload, Activity acti Assert.That(relatedToTag.Value, Is.Not.Null); Assert.That(relatedToTag.Value.Contains(relatedId), Is.True); } + + AssertTagMatches(activity, "eh.event_count", eventCount.ToString()); } private static void AssertTagExists(Activity activity, string tagName) From d0c5c610ba34af6a4ba4baada8f1b49740c29777 Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Wed, 17 Jul 2019 12:07:01 -0700 Subject: [PATCH 16/21] Addressed some comments --- .../EventDataDiagnosticExtensions.cs | 2 +- .../src/TrackOneClient/EventDataSender.cs | 8 ++-- .../EventHubsDiagnosticSource.cs | 28 ++++++------ .../tests/Diagnostics/DiagnosticsLiveTests.cs | 44 ++++++++++--------- .../tests/Diagnostics/DiagnosticsTests.cs | 4 +- 5 files changed, 44 insertions(+), 42 deletions(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventDataDiagnosticExtensions.cs b/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventDataDiagnosticExtensions.cs index 3de7d732b90cb..e881158e6c2e2 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventDataDiagnosticExtensions.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventDataDiagnosticExtensions.cs @@ -65,7 +65,7 @@ internal static class EventDataDiagnosticExtensions /// /// - internal static Activity ExtractActivity(this EventData eventData, string activityName = null) + public static Activity ExtractActivity(this EventData eventData, string activityName = null) { Guard.ArgumentNotNull(nameof(eventData), eventData); diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventDataSender.cs b/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventDataSender.cs index 3d42c769e9a33..663d2a5856be9 100755 --- a/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventDataSender.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventDataSender.cs @@ -26,12 +26,12 @@ protected EventDataSender(EventHubClient eventHubClient, string partitionId) public async Task SendAsync(IEnumerable eventDatas, string partitionKey) { int count = ValidateEvents(eventDatas); - var diagnosticPartitionKey = String.IsNullOrEmpty(partitionKey) ? + var activePartitionRouting = String.IsNullOrEmpty(partitionKey) ? this.PartitionId : partitionKey; EventHubsEventSource.Log.EventSendStart(this.ClientId, count, partitionKey); - Activity activity = EventHubsDiagnosticSource.StartSendActivity(this.ClientId, this.EventHubClient.ConnectionStringBuilder, diagnosticPartitionKey, eventDatas, count); + Activity activity = EventHubsDiagnosticSource.StartSendActivity(this.ClientId, this.EventHubClient.ConnectionStringBuilder, activePartitionRouting, eventDatas, count); Task sendTask = null; try @@ -44,13 +44,13 @@ public async Task SendAsync(IEnumerable eventDatas, string partitionK catch (Exception exception) { EventHubsEventSource.Log.EventSendException(this.ClientId, exception.ToString()); - EventHubsDiagnosticSource.FailSendActivity(activity, this.EventHubClient.ConnectionStringBuilder, diagnosticPartitionKey, eventDatas, exception); + EventHubsDiagnosticSource.FailSendActivity(activity, this.EventHubClient.ConnectionStringBuilder, activePartitionRouting, eventDatas, exception); throw; } finally { EventHubsEventSource.Log.EventSendStop(this.ClientId); - EventHubsDiagnosticSource.StopSendActivity(activity, this.EventHubClient.ConnectionStringBuilder, diagnosticPartitionKey, eventDatas, sendTask); + EventHubsDiagnosticSource.StopSendActivity(activity, this.EventHubClient.ConnectionStringBuilder, activePartitionRouting, eventDatas, sendTask); } } diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventHubsDiagnosticSource.cs b/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventHubsDiagnosticSource.cs index 4bf303beb38da..b77fe1e4a36e6 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventHubsDiagnosticSource.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/src/TrackOneClient/EventHubsDiagnosticSource.cs @@ -32,7 +32,7 @@ internal static class EventHubsDiagnosticSource internal static readonly DiagnosticListener DiagnosticListener = new DiagnosticListener(DiagnosticSourceName); - internal static Activity StartSendActivity(string clientId, EventHubsConnectionStringBuilder csb, string partitionKey, IEnumerable eventDatas, int count) + internal static Activity StartSendActivity(string clientId, EventHubsConnectionStringBuilder csb, string activePartitionRouting, IEnumerable eventDatas, int count) { // skip if diagnostic source not enabled if (!DiagnosticListener.IsEnabled()) @@ -50,7 +50,7 @@ internal static Activity StartSendActivity(string clientId, EventHubsConnectionS activity.AddTag("peer.hostname", csb.Endpoint.Host); activity.AddTag("eh.event_hub_name", csb.EntityPath); - activity.AddTag("eh.partition_key", partitionKey); + activity.AddTag("eh.active_partition_routing", activePartitionRouting); activity.AddTag("eh.event_count", count.ToString()); activity.AddTag("eh.client_id", clientId); @@ -63,7 +63,7 @@ internal static Activity StartSendActivity(string clientId, EventHubsConnectionS { csb.Endpoint, Entity = csb.EntityPath, - PartitionKey = partitionKey, + ActivePartitionRouting = activePartitionRouting, EventDatas = eventDatas.Select(TransformEvent) }); } @@ -77,7 +77,7 @@ internal static Activity StartSendActivity(string clientId, EventHubsConnectionS return activity; } - internal static void FailSendActivity(Activity activity, EventHubsConnectionStringBuilder csb, string partitionKey, IEnumerable eventDatas, Exception ex) + internal static void FailSendActivity(Activity activity, EventHubsConnectionStringBuilder csb, string activePartitionRouting, IEnumerable eventDatas, Exception ex) { if (!DiagnosticListener.IsEnabled() || !DiagnosticListener.IsEnabled(SendActivityExceptionName)) { @@ -89,13 +89,13 @@ internal static void FailSendActivity(Activity activity, EventHubsConnectionStri { csb.Endpoint, Entity = csb.EntityPath, - PartitionKey = partitionKey, + ActivePartitionRouting = activePartitionRouting, EventDatas = eventDatas.Select(TransformEvent), Exception = ex }); } - internal static void StopSendActivity(Activity activity, EventHubsConnectionStringBuilder csb, string partitionKey, IEnumerable eventDatas, Task sendTask) + internal static void StopSendActivity(Activity activity, EventHubsConnectionStringBuilder csb, string activePartitionRouting, IEnumerable eventDatas, Task sendTask) { if (activity == null) { @@ -107,7 +107,7 @@ internal static void StopSendActivity(Activity activity, EventHubsConnectionStri { csb.Endpoint, Entity = csb.EntityPath, - PartitionKey = partitionKey, + ActivePartitionRouting = activePartitionRouting, EventDatas = eventDatas.Select(TransformEvent), sendTask?.Status }); @@ -116,7 +116,7 @@ internal static void StopSendActivity(Activity activity, EventHubsConnectionStri internal static Activity StartReceiveActivity( string clientId, EventHubsConnectionStringBuilder csb, - string partitionKey, + string activePartitionRouting, string consumerGroup, EventPosition eventPosition) { @@ -137,7 +137,7 @@ internal static Activity StartReceiveActivity( // extract activity tags from input activity.AddTag("peer.hostname", csb.Endpoint.Host); activity.AddTag("eh.event_hub_name", csb.EntityPath); - activity.AddTag("eh.partition_key", partitionKey); + activity.AddTag("eh.active_partition_routing", activePartitionRouting); activity.AddTag("eh.consumer_group", consumerGroup); activity.AddTag("eh.start_offset", eventPosition.Offset); activity.AddTag("eh.start_sequence_number", eventPosition.SequenceNumber?.ToString()); @@ -153,7 +153,7 @@ internal static Activity StartReceiveActivity( { Endpoint = csb.Endpoint, Entity = csb.EntityPath, - PartitionKey = partitionKey, + ActivePartitionRouting = activePartitionRouting, ConsumerGroup = consumerGroup }); } @@ -165,7 +165,7 @@ internal static Activity StartReceiveActivity( return activity; } - internal static void FailReceiveActivity(Activity activity, EventHubsConnectionStringBuilder csb, string partitionKey, string consumerGroup, Exception ex) + internal static void FailReceiveActivity(Activity activity, EventHubsConnectionStringBuilder csb, string activePartitionRouting, string consumerGroup, Exception ex) { // TODO consider enriching activity with data from exception if (!DiagnosticListener.IsEnabled() || !DiagnosticListener.IsEnabled(ReceiveActivityExceptionName)) @@ -178,13 +178,13 @@ internal static void FailReceiveActivity(Activity activity, EventHubsConnectionS { csb.Endpoint, Entity = csb.EntityPath, - PartitionKey = partitionKey, + ActivePartitionRouting = activePartitionRouting, ConsumerGroup = consumerGroup, Exception = ex }); } - internal static void StopReceiveActivity(Activity activity, EventHubsConnectionStringBuilder csb, string partitionKey, string consumerGroup, IList events, Task receiveTask) + internal static void StopReceiveActivity(Activity activity, EventHubsConnectionStringBuilder csb, string activePartitionRouting, string consumerGroup, IList events, Task receiveTask) { if (activity == null) { @@ -199,7 +199,7 @@ internal static void StopReceiveActivity(Activity activity, EventHubsConnectionS { csb.Endpoint, Entity = csb.EntityPath, - PartitionKey = partitionKey, + ActivePartitionRouting = activePartitionRouting, ConsumerGroup = consumerGroup, EventDatas = events.Select(TransformEvent), receiveTask?.Status diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs index 221ddf4cae48a..3d47946df51e9 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs @@ -31,7 +31,7 @@ namespace Azure.Messaging.EventHubs.Tests [NonParallelizable] [Category(TestCategory.Live)] [Category(TestCategory.DisallowVisualStudioLiveUnitTesting)] - class DiagnosticsLiveTests + public class DiagnosticsLiveTests { /// The maximum number of times that the receive loop should iterate to collect the expected number of messages. private const int ReceiveRetryLimit = 10; @@ -60,7 +60,7 @@ private static T GetPropertyValueFromAnonymousTypeInstance(object obj, string object propertyValue = p.GetValue(obj); // If a null string property was found, return it. This is necessary for testing - // the PartitionKey property when no Partition Key or Partition Id was set. + // the ActivePartitionRouting property when no Partition Key or Partition Id was set. if (typeof(T) == typeof(string) && propertyValue == null) { @@ -82,7 +82,8 @@ private static T GetPropertyValueFromAnonymousTypeInstance(object obj, string [TestCase(null, false)] [TestCase(null, true)] [TestCase("AmIaGoodPartitionKey", false)] - public async Task SendFiresEvents(string partitionKey, bool usePartitionId) + public async Task SendFiresEvents(string partitionKey, + bool usePartitionId) { await using (var scope = await EventHubScope.CreateAsync(1)) { @@ -215,7 +216,8 @@ public async Task SendDoesNotInjectContextWhenNoListeners() [TestCase(null, false)] [TestCase(null, true)] [TestCase("AmIaGoodPartitionKey", false)] - public async Task SendFiresExceptionEvents(string partitionKey, bool usePartitionId) + public async Task SendFiresExceptionEvents(string partitionKey, + bool usePartitionId) { await using (var scope = await EventHubScope.CreateAsync(1)) { @@ -369,7 +371,7 @@ public async Task ReceiveFiresEvents() } } - private static void AssertSendStart(string name, object payload, Activity activity, Activity parentActivity, string partitionKey, string connectionString, int eventCount = 1) + private static void AssertSendStart(string name, object payload, Activity activity, Activity parentActivity, string activePartitionRouting, string connectionString, int eventCount = 1) { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); @@ -379,7 +381,7 @@ private static void AssertSendStart(string name, object payload, Activity activi // Check payload. - AssertCommonPayloadProperties(payload, partitionKey, connectionStringProperties); + AssertCommonPayloadProperties(payload, activePartitionRouting, connectionStringProperties); var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); Assert.That(eventDatas.Count, Is.EqualTo(eventCount)); @@ -395,12 +397,12 @@ private static void AssertSendStart(string name, object payload, Activity activi AssertTagMatches(activity, "peer.hostname", connectionStringProperties.Endpoint.Host); AssertTagMatches(activity, "eh.event_hub_name", connectionStringProperties.EventHubPath); - AssertTagMatches(activity, "eh.partition_key", partitionKey); + AssertTagMatches(activity, "eh.active_partition_routing", activePartitionRouting); AssertTagMatches(activity, "eh.event_count", eventCount.ToString()); AssertTagExists(activity, "eh.client_id"); } - private void AssertSendException(string name, object payload, Activity activity, Activity parentActivity, string partitionKey, string connectionString) + private void AssertSendException(string name, object payload, Activity activity, Activity parentActivity, string activePartitionRouting, string connectionString) { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); @@ -410,7 +412,7 @@ private void AssertSendException(string name, object payload, Activity activity, // Check payload. - AssertCommonPayloadProperties(payload, partitionKey, connectionStringProperties); + AssertCommonPayloadProperties(payload, activePartitionRouting, connectionStringProperties); var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); Assert.That(eventDatas, Is.Not.Null); @@ -427,7 +429,7 @@ private void AssertSendException(string name, object payload, Activity activity, } } - private static void AssertSendStop(string name, object payload, Activity activity, Activity sendActivity, string partitionKey, string connectionString, bool isFaulted = false) + private static void AssertSendStop(string name, object payload, Activity activity, Activity sendActivity, string activePartitionRouting, string connectionString, bool isFaulted = false) { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); @@ -437,7 +439,7 @@ private static void AssertSendStop(string name, object payload, Activity activit // Check payload. - AssertCommonStopPayloadProperties(payload, partitionKey, isFaulted, connectionStringProperties); + AssertCommonStopPayloadProperties(payload, activePartitionRouting, isFaulted, connectionStringProperties); var eventDatas = GetPropertyValueFromAnonymousTypeInstance>(payload, "EventDatas"); Assert.That(eventDatas, Is.Not.Null); @@ -450,7 +452,7 @@ private static void AssertSendStop(string name, object payload, Activity activit } } - private static void AssertReceiveStart(string name, object payload, Activity activity, Activity parentActivity, string consumerGroup, EventPosition position, string partitionKey, string connectionString) + private static void AssertReceiveStart(string name, object payload, Activity activity, Activity parentActivity, string consumerGroup, EventPosition position, string activePartitionRouting, string connectionString) { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); @@ -460,7 +462,7 @@ private static void AssertReceiveStart(string name, object payload, Activity act // Check payload. - AssertCommonPayloadProperties(payload, partitionKey, connectionStringProperties); + AssertCommonPayloadProperties(payload, activePartitionRouting, connectionStringProperties); // Check Activity and its tags. @@ -473,7 +475,7 @@ private static void AssertReceiveStart(string name, object payload, Activity act AssertTagMatches(activity, "peer.hostname", connectionStringProperties.Endpoint.Host); AssertTagMatches(activity, "eh.event_hub_name", connectionStringProperties.EventHubPath); - AssertTagMatches(activity, "eh.partition_key", partitionKey); + AssertTagMatches(activity, "eh.active_partition_routing", activePartitionRouting); AssertTagMatches(activity, "eh.consumer_group", consumerGroup); AssertTagMatches(activity, "eh.start_offset", position.Offset); AssertTagMatches(activity, "eh.start_sequence_number", position.SequenceNumber?.ToString()); @@ -481,7 +483,7 @@ private static void AssertReceiveStart(string name, object payload, Activity act AssertTagExists(activity, "eh.client_id"); } - private static void AssertReceiveStop(string name, object payload, Activity activity, Activity receiveActivity, string consumerGroup, string partitionKey, string connectionString, int eventCount = 1, bool isFaulted = false, string relatedId = null) + private static void AssertReceiveStop(string name, object payload, Activity activity, Activity receiveActivity, string consumerGroup, string activePartitionRouting, string connectionString, int eventCount = 1, bool isFaulted = false, string relatedId = null) { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); @@ -491,7 +493,7 @@ private static void AssertReceiveStop(string name, object payload, Activity acti // Check payload. - AssertCommonStopPayloadProperties(payload, partitionKey, isFaulted, connectionStringProperties); + AssertCommonStopPayloadProperties(payload, activePartitionRouting, isFaulted, connectionStringProperties); var payloadConsumerGroup = GetPropertyValueFromAnonymousTypeInstance(payload, "ConsumerGroup"); Assert.That(payloadConsumerGroup, Is.EqualTo(consumerGroup)); @@ -529,24 +531,24 @@ private static void AssertTagMatches(Activity activity, string tagName, string t Assert.That(activity.Tags.Single(t => t.Key == tagName).Value, Is.EqualTo(tagValue)); } - private static void AssertCommonPayloadProperties(object eventPayload, string partitionKey, ConnectionStringProperties connectionStringProperties) + private static void AssertCommonPayloadProperties(object eventPayload, string activePartitionRouting, ConnectionStringProperties connectionStringProperties) { var endpoint = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "Endpoint"); var entityPath = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "Entity"); - var pKey = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "PartitionKey"); + var pRouting = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "ActivePartitionRouting"); var expectedEndpointStart = "amqps://" + connectionStringProperties.Endpoint.Host; Assert.That(endpoint.AbsoluteUri.StartsWith(expectedEndpointStart), Is.True); Assert.That(entityPath, Is.EqualTo(connectionStringProperties.EventHubPath)); - Assert.That(pKey, Is.EqualTo(partitionKey)); + Assert.That(pRouting, Is.EqualTo(activePartitionRouting)); } - private static void AssertCommonStopPayloadProperties(object eventPayload, string partitionKey, bool isFaulted, ConnectionStringProperties connectionStringProperties) + private static void AssertCommonStopPayloadProperties(object eventPayload, string activePartitionRouting, bool isFaulted, ConnectionStringProperties connectionStringProperties) { var expectedStatus = isFaulted ? TaskStatus.Faulted : TaskStatus.RanToCompletion; - AssertCommonPayloadProperties(eventPayload, partitionKey, connectionStringProperties); + AssertCommonPayloadProperties(eventPayload, activePartitionRouting, connectionStringProperties); var status = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "Status"); Assert.That(status, Is.EqualTo(expectedStatus)); diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs index 12964dc1e7954..d31b3c8a46a56 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs @@ -14,8 +14,8 @@ namespace Azure.Messaging.EventHubs.Tests /// /// [TestFixture] - [Parallelizable(ParallelScope.Children)] - class DiagnosticsTests + [Parallelizable(ParallelScope.All)] + public class DiagnosticsTests { /// /// Verifies functionality of the extension From 357936e8d142fa8c0ffa185847c985c2e5032bb9 Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Wed, 17 Jul 2019 12:47:55 -0700 Subject: [PATCH 17/21] Deleted diagnostics event data extension method related stuff --- .../EventDataDiagnosticsExtensions.cs | 34 ---- .../tests/Diagnostics/DiagnosticsTests.cs | 168 ------------------ 2 files changed, 202 deletions(-) delete mode 100644 sdk/eventhub/Azure.Messaging.EventHubs/src/Diagnostics/EventDataDiagnosticsExtensions.cs delete mode 100644 sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/src/Diagnostics/EventDataDiagnosticsExtensions.cs b/sdk/eventhub/Azure.Messaging.EventHubs/src/Diagnostics/EventDataDiagnosticsExtensions.cs deleted file mode 100644 index ac8e622bb8246..0000000000000 --- a/sdk/eventhub/Azure.Messaging.EventHubs/src/Diagnostics/EventDataDiagnosticsExtensions.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Diagnostics; - -namespace Azure.Messaging.EventHubs.Diagnostics -{ - /// - /// Diagnostic extension methods for . - /// - /// - internal static class EventDataDiagnosticsExtensions - { - /// - /// Creates based on the tracing context stored in the . - /// - /// - /// The event received from EventHub. - /// Optional Activity name. - /// - /// New with tracing context. - /// - public static Activity ExtractActivity(this EventData eventData, string activityName = null) - { - static TrackOne.EventData TransformEvent(EventData eventData) => - new TrackOne.EventData(eventData.Body.ToArray()) - { - Properties = eventData.Properties - }; - - return TrackOne.EventDataDiagnosticExtensions.ExtractActivity(TransformEvent(eventData), activityName); - } - } -} diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs deleted file mode 100644 index d31b3c8a46a56..0000000000000 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsTests.cs +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Linq; -using System.Text; -using Azure.Messaging.EventHubs.Diagnostics; -using NUnit.Framework; - -namespace Azure.Messaging.EventHubs.Tests -{ - /// - /// The suite of tests for the - /// class. - /// - /// - [TestFixture] - [Parallelizable(ParallelScope.All)] - public class DiagnosticsTests - { - /// - /// Verifies functionality of the extension - /// method. - /// - /// - [Test] - public void ExtractsActivityWithIdAndNoContext() - { - var eventData = new EventData(Encoding.UTF8.GetBytes("test")); - - eventData.Properties["Diagnostic-Id"] = "diagnostic-id"; - - var activity = eventData.ExtractActivity(); - - Assert.That(activity.ParentId, Is.EqualTo("diagnostic-id")); - Assert.That(activity.RootId, Is.EqualTo("diagnostic-id")); - Assert.That(activity.Id, Is.Null); - - var baggage = activity.Baggage.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); - Assert.That(baggage, Is.Empty); - } - - /// - /// Verifies functionality of the extension - /// method. - /// - /// - [Test] - public void ExtractsActivityWithIdAndSingleContext() - { - var eventData = new EventData(Encoding.UTF8.GetBytes("test")); - - eventData.Properties["Diagnostic-Id"] = "diagnostic-id"; - eventData.Properties["Correlation-Context"] = "k1=v1"; - - var activity = eventData.ExtractActivity(); - - Assert.That(activity.ParentId, Is.EqualTo("diagnostic-id")); - Assert.That(activity.RootId, Is.EqualTo("diagnostic-id")); - Assert.That(activity.Id, Is.Null); - - var baggage = activity.Baggage.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); - - Assert.That(baggage.Count, Is.EqualTo(1)); - Assert.That(baggage.Keys.Contains("k1"), Is.True); - Assert.That(baggage["k1"], Is.EqualTo("v1")); - } - - /// - /// Verifies functionality of the extension - /// method. - /// - /// - [Test] - public void ExtractsActivityWithIdAndMultiContext() - { - var eventData = new EventData(Encoding.UTF8.GetBytes("test")); - - eventData.Properties["Diagnostic-Id"] = "diagnostic-id"; - eventData.Properties["Correlation-Context"] = "k1=v1,k2=v2,k3=v3"; - - var activity = eventData.ExtractActivity(); - - Assert.That(activity.ParentId, Is.EqualTo("diagnostic-id")); - Assert.That(activity.RootId, Is.EqualTo("diagnostic-id")); - Assert.That(activity.Id, Is.Null); - - var baggage = activity.Baggage.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); - - Assert.That(baggage.Count, Is.EqualTo(3)); - Assert.That(baggage.Keys.Contains("k1"), Is.True); - Assert.That(baggage.Keys.Contains("k2"), Is.True); - Assert.That(baggage.Keys.Contains("k3"), Is.True); - Assert.That(baggage["k1"], Is.EqualTo("v1")); - Assert.That(baggage["k2"], Is.EqualTo("v2")); - Assert.That(baggage["k3"], Is.EqualTo("v3")); - } - - /// - /// Verifies functionality of the extension - /// method. - /// - /// - [Test] - public void ExtractActivityWithAlternateName() - { - var eventData = new EventData(Encoding.UTF8.GetBytes("test")); - - eventData.Properties["Diagnostic-Id"] = "diagnostic-id"; - - var activity = eventData.ExtractActivity("My activity"); - Assert.That(activity.OperationName, Is.EqualTo("My activity")); - } - - /// - /// Verifies functionality of the extension - /// method. - /// - /// - [Test] - [TestCase(null)] - [TestCase("")] - [TestCase("not valid context")] - [TestCase("not,valid,context")] - public void ExtractsActivityWithIdAndInvalidContext(string context) - { - var eventData = new EventData(Encoding.UTF8.GetBytes("test")); - - eventData.Properties["Diagnostic-Id"] = "diagnostic-id"; - eventData.Properties["Correlation-Context"] = context; - - var activity = eventData.ExtractActivity(); - - Assert.That(activity.ParentId, Is.EqualTo("diagnostic-id")); - Assert.That(activity.RootId, Is.EqualTo("diagnostic-id")); - Assert.That(activity.Id, Is.Null); - - var baggage = activity.Baggage.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); - Assert.That(baggage, Is.Empty); - } - - /// - /// Verifies functionality of the extension - /// method. - /// - /// - [Test] - [TestCase(null)] - [TestCase("")] - public void ExtractsActivityWithoutIdAsRoot(string id) - { - var eventData = new EventData(Encoding.UTF8.GetBytes("test")); - - eventData.Properties["Diagnostic-Id"] = id; - eventData.Properties["Correlation-Context"] = "k1=v1,k2=v2"; - - var activity = eventData.ExtractActivity(); - - Assert.That(activity.ParentId, Is.Null); - Assert.That(activity.RootId, Is.Null); - Assert.That(activity.Id, Is.Null); - - // Baggage is ignored in absence of Id. - - var baggage = activity.Baggage.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); - Assert.That(baggage, Is.Empty); - } - } -} From c96806174fa0f2bf9b013aadbe891ee4168a6347 Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Wed, 17 Jul 2019 12:50:34 -0700 Subject: [PATCH 18/21] Moved fake listener to infrastructure --- .../{Diagnostics => Infrastructure}/FakeDiagnosticListener.cs | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename sdk/eventhub/Azure.Messaging.EventHubs/tests/{Diagnostics => Infrastructure}/FakeDiagnosticListener.cs (100%) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/FakeDiagnosticListener.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Infrastructure/FakeDiagnosticListener.cs similarity index 100% rename from sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/FakeDiagnosticListener.cs rename to sdk/eventhub/Azure.Messaging.EventHubs/tests/Infrastructure/FakeDiagnosticListener.cs From 6c087b91d1ce321dafdd17f1ae7b6664b03b61c9 Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Thu, 18 Jul 2019 05:07:18 -0700 Subject: [PATCH 19/21] Added comments and made small changes. --- .../tests/Diagnostics/DiagnosticsLiveTests.cs | 149 +++++++++++++++++- .../Infrastructure/FakeDiagnosticListener.cs | 123 ++++++++++++++- 2 files changed, 263 insertions(+), 9 deletions(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs index 3d47946df51e9..e8f59b6446453 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs @@ -25,6 +25,12 @@ namespace Azure.Messaging.EventHubs.Tests /// /// These tests have a depenency on live Azure services and may /// incur costs for the associated Azure subscription. + /// + /// Every send or receive call will trigger diagnostics events as + /// long as they are being listened to. Therefore, other tests may + /// interfere with these. For this reason, these tests are marked + /// as non-parallelizable. + /// /// /// [TestFixture] @@ -36,12 +42,40 @@ public class DiagnosticsLiveTests /// The maximum number of times that the receive loop should iterate to collect the expected number of messages. private const int ReceiveRetryLimit = 10; + /// + /// Provides a new empty queue to store diagnostics events. + /// + /// + /// An empty to store diagnostics events. + /// private static ConcurrentQueue<(string eventName, object payload, Activity activity)> CreateEventQueue() => new ConcurrentQueue<(string eventName, object payload, Activity activity)>(); + /// + /// Subscribes an to so it + /// can locate the Azure.Messaging.EventHubs . + /// + /// + /// The that will subscribe to the Azure.Messaging.EventHubs . + /// + /// An subscription. The subscription can be cancelled by disposing of it. + /// private static IDisposable SubscribeToEvents(IObserver listener) => DiagnosticListener.AllListeners.Subscribe(listener); + /// + /// Provides a new that populates a given with + /// event information once enabled. + /// + /// + /// The event queue to be populated. + /// + /// A that will populate the given event queue once enabled. + /// + /// + /// must be called before listening to events. + /// + /// private static FakeDiagnosticListener CreateEventListener(ConcurrentQueue<(string eventName, object payload, Activity activity)> eventQueue) => new FakeDiagnosticListener(kvp => { @@ -53,6 +87,20 @@ private static FakeDiagnosticListener CreateEventListener(ConcurrentQueue<(strin eventQueue?.Enqueue((kvp.Key, kvp.Value, Activity.Current)); }); + /// + /// Extracts a property from a payload object given its type and name. + /// + /// + /// The payload object containing the property. + /// The name of the property. + /// + /// The typed property extracted from the given payload object. + /// + /// + /// If a non-string type property value is found to be null, an assertion + /// error is expected. + /// + /// private static T GetPropertyValueFromAnonymousTypeInstance(object obj, string propertyName) { Type t = obj.GetType(); @@ -110,7 +158,7 @@ public async Task SendFiresEvents(string partitionKey, // Enable Send .Start & .Stop events. - listener.Enable((name, queueName, arg) => name.Contains("Send") && !name.EndsWith(".Exception")); + listener.Enable(name => name.Contains("Send") && !name.EndsWith(".Exception")); // Assert that the properties we want to inject are not already included. @@ -244,7 +292,7 @@ public async Task SendFiresExceptionEvents(string partitionKey, // Enable Send .Exception & .Stop events. - listener.Enable((name, queueName, arg) => name.Contains("Send") && !name.EndsWith(".Start")); + listener.Enable(name => name.Contains("Send") && !name.EndsWith(".Start")); // Try sending a large message. A SizeLimitException is expected. @@ -308,7 +356,7 @@ public async Task ReceiveFiresEvents() // Enable Send & Receive .Start & .Stop events. - listener.Enable((name, queueName, arg) => !name.EndsWith(".Exception")); + listener.Enable(name => !name.EndsWith(".Exception")); // Assert that the properties we want to inject are not already included. @@ -371,6 +419,18 @@ public async Task ReceiveFiresEvents() } } + /// + /// Asserts that the information received from a Send .Start event is accurate. + /// + /// + /// The event name received from the event. + /// The payload object received from the event. + /// The activity received from the event. + /// The current just before receiving. If null, the corresponding assertion will be skipped. + /// The expected partition routing method in use. It may be null, a Partition Key or a Partition Id. + /// The client's connection string. + /// The expected number of events. + /// private static void AssertSendStart(string name, object payload, Activity activity, Activity parentActivity, string activePartitionRouting, string connectionString, int eventCount = 1) { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); @@ -402,6 +462,17 @@ private static void AssertSendStart(string name, object payload, Activity activi AssertTagExists(activity, "eh.client_id"); } + /// + /// Asserts that the information received from a Send .Exception event is accurate. + /// + /// + /// The event name received from the event. + /// The payload object received from the event. + /// The activity received from the event. + /// The current just before receiving. If null, the corresponding assertion will be skipped. + /// The expected partition routing method in use. It may be null, a Partition Key or a Partition Id. + /// The client's connection string. + /// private void AssertSendException(string name, object payload, Activity activity, Activity parentActivity, string activePartitionRouting, string connectionString) { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); @@ -429,6 +500,18 @@ private void AssertSendException(string name, object payload, Activity activity, } } + /// + /// Asserts that the information received from a Send .Stop event is accurate. + /// + /// + /// The event name received from the event. + /// The payload object received from the event. + /// The activity received from the event. + /// The activity received from the associated Send.Start event. If null, the corresponding assertion will be skipped. + /// The expected partition routing method in use. It may be null, a Partition Key or a Partition Id. + /// The client's connection string. + /// true if the expected is ; false if it is . + /// private static void AssertSendStop(string name, object payload, Activity activity, Activity sendActivity, string activePartitionRouting, string connectionString, bool isFaulted = false) { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); @@ -452,6 +535,19 @@ private static void AssertSendStop(string name, object payload, Activity activit } } + /// + /// Asserts that the information received from a Receive .Start event is accurate. + /// + /// + /// The event name received from the event. + /// The payload object received from the event. + /// The activity received from the event. + /// The current just before receiving. If null, the corresponding assertion will be skipped. + /// The consumer group of the receiving consumer. + /// The used when creating the receiving consumer. + /// The expected partition routing method in use. It may be null, a Partition Key or a Partition Id. + /// The client's connection string. + /// private static void AssertReceiveStart(string name, object payload, Activity activity, Activity parentActivity, string consumerGroup, EventPosition position, string activePartitionRouting, string connectionString) { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); @@ -483,6 +579,21 @@ private static void AssertReceiveStart(string name, object payload, Activity act AssertTagExists(activity, "eh.client_id"); } + /// + /// Asserts that the information received from a Receive .Stop event is accurate. + /// + /// + /// The event name received from the event. + /// The payload object received from the event. + /// The activity received from the event. + /// The activity received from the associated Receive.Start event. If null, the corresponding assertion will be skipped. + /// The consumer group of the receiving consumer. + /// The expected partition routing method in use. It may be null, a Partition Key or a Partition Id. + /// The client's connection string. + /// The expected number of events. + /// true if the expected is ; false if it is . + /// The id of the related send activity. If null or empty, the corresponding assertion will be skipped. + /// private static void AssertReceiveStop(string name, object payload, Activity activity, Activity receiveActivity, string consumerGroup, string activePartitionRouting, string connectionString, int eventCount = 1, bool isFaulted = false, string relatedId = null) { var connectionStringProperties = ConnectionStringParser.Parse(connectionString); @@ -520,17 +631,40 @@ private static void AssertReceiveStop(string name, object payload, Activity acti AssertTagMatches(activity, "eh.event_count", eventCount.ToString()); } + /// + /// Asserts that an activity contains a specified tag. + /// + /// + /// The activity containing the tag to be checked. + /// The name of the tag. + /// private static void AssertTagExists(Activity activity, string tagName) { Assert.That(activity.Tags.Select(t => t.Key).Contains(tagName), Is.True); } + /// + /// Asserts that an activity contains a specified tag and it matches a specified value. + /// + /// + /// The activity containing the tag to be checked. + /// The name of the tag. + /// The expected value of the tag. + /// private static void AssertTagMatches(Activity activity, string tagName, string tagValue) { Assert.That(activity.Tags.Select(t => t.Key).Contains(tagName), Is.True); Assert.That(activity.Tags.Single(t => t.Key == tagName).Value, Is.EqualTo(tagValue)); } + /// + /// Asserts that the common payload properties of Send & Receive .Start & .Exception events contain the expected values. + /// + /// + /// The payload object received from the event. + /// The expected partition routing method in use. It may be null, a Partition Key or a Partition Id. + /// The client's connection string properties. + /// private static void AssertCommonPayloadProperties(object eventPayload, string activePartitionRouting, ConnectionStringProperties connectionStringProperties) { var endpoint = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "Endpoint"); @@ -544,6 +678,15 @@ private static void AssertCommonPayloadProperties(object eventPayload, string ac Assert.That(pRouting, Is.EqualTo(activePartitionRouting)); } + /// + /// Asserts that the common payload properties of Send & Receive .Stop events contain the expected values. + /// + /// + /// The payload object received from the event. + /// The expected partition routing method in use. It may be null, a Partition Key or a Partition Id. + /// true if the expected is ; false if it is . + /// The client's connection string properties. + /// private static void AssertCommonStopPayloadProperties(object eventPayload, string activePartitionRouting, bool isFaulted, ConnectionStringProperties connectionStringProperties) { var expectedStatus = isFaulted ? TaskStatus.Faulted : TaskStatus.RanToCompletion; diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Infrastructure/FakeDiagnosticListener.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Infrastructure/FakeDiagnosticListener.cs index 8cd75d9a1e69b..e0f253ff5b351 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Infrastructure/FakeDiagnosticListener.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Infrastructure/FakeDiagnosticListener.cs @@ -7,65 +7,176 @@ namespace Azure.Messaging.EventHubs.Tests { + /// + /// Encapsulates the necessary structure to locate the Azure.Messaging.EventHubs + /// and listen to its events. + /// + /// + /// + /// An instance of this class must subscribe to the observable. + /// It will be possible to locate the Azure.Messaging.EventHubs this way. + /// An inner class will subscribe to it and deal with its events. + /// + /// internal sealed class FakeDiagnosticListener : IObserver, IDisposable { + /// A subscription to the Azure.Messaging.EventHubs used by the inner class. private IDisposable subscription; + /// The callback to be called on every event fired by the Azure.Messaging.EventHubs . private readonly Action> writeCallback; - private Func writeObserverEnabled = (name, arg1, arg2) => false; - + /// Determines whether this instance is enabled given the name of the fired event. + private Func writeObserverEnabled = name => false; + + /// + /// Initializes a new instance of the class. + /// + /// + /// The callback to be called on every event fired by the Azure.Messaging.EventHubs . + /// + /// + /// The action only takes a as a parameter. + /// This parameter contains the event name and its payload object. + /// + /// public FakeDiagnosticListener(Action> writeCallback) { this.writeCallback = writeCallback; } + /// + /// This method is necessary for the interface, + /// but it won't be used. + /// + /// public void OnCompleted() { } + /// + /// This method is necessary for the interface, + /// but it won't be used. + /// + /// public void OnError(Exception error) { } + /// + /// The method to be called whenever a this + /// has subscribed to fires an event. + /// + /// + /// A reference to an active . + /// + /// + /// A reference to every active will be passed to this method once. + /// These references will be used to find the Azure.Messaging.EventHubs . + /// + /// public void OnNext(DiagnosticListener value) { if (value.Name.Equals("Azure.Messaging.EventHubs")) { + this.subscription?.Dispose(); this.subscription = value.Subscribe(new FakeDiagnosticSourceWriteObserver(this.writeCallback), this.IsEnabled); } } - public void Enable(Func writeObserverEnabled) + /// + /// Enables this instance for every upcoming event that passes a specified callback filter. + /// + /// + /// The callback filter to be applied to every upcoming event. + /// + /// + /// The callback function only takes an event name as a parameter. + /// It should return true if this instance is enabled for the + /// specified event name; otherwise, it should return false. + /// + /// + public void Enable(Func writeObserverEnabled) { this.writeObserverEnabled = writeObserverEnabled; } + /// + /// Disables this instance for every upcoming event. + /// + /// public void Disable() { - this.writeObserverEnabled = (name, arg1, arg2) => false; + this.writeObserverEnabled = name => false; } - public bool IsEnabled(string s, object arg1, object arg2) + /// + /// Determines whether this instance is enabled given the name of the fired event. + /// + /// + /// The name of the event. + /// + /// true if this instance is enabled for the specified event name; otherwise, false. + /// + public bool IsEnabled(string name) { - return this.writeObserverEnabled.Invoke(s, arg1, arg2); + return this.writeObserverEnabled.Invoke(name); } + /// + /// Disables this instance and cancels + /// its current subscription, if existing. + /// + /// public void Dispose() { this.Disable(); this.subscription?.Dispose(); } + /// + /// Subscribes to a and listens to the + /// events fired by it. + /// + /// private class FakeDiagnosticSourceWriteObserver : IObserver> { + /// The callback to be called on every fired event. private readonly Action> writeCallback; + /// + /// Initializes a new instance of the class. + /// + /// + /// The callback to be called on every fired event. + /// + /// + /// The action only takes a as a parameter. + /// This parameter contains the event name and its payload object. + /// + /// public FakeDiagnosticSourceWriteObserver(Action> writeCallback) { this.writeCallback = writeCallback; } + /// + /// This method is necessary for the interface, + /// but it won't be used. + /// + /// public void OnCompleted() { } + /// + /// This method is necessary for the interface, + /// but it won't be used. + /// + /// public void OnError(Exception error) { } + /// + /// The method to be called whenever a this + /// has subscribed to fires an event. + /// + /// + /// A containing the event name and its payload object. + /// public void OnNext(KeyValuePair value) { this.writeCallback(value); From 8fef3d5470574d3021f3e3a7e9ba246e0edae92f Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Thu, 18 Jul 2019 05:19:39 -0700 Subject: [PATCH 20/21] Wording --- .../tests/Diagnostics/DiagnosticsLiveTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs index e8f59b6446453..f020debe8f1f0 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs @@ -27,9 +27,9 @@ namespace Azure.Messaging.EventHubs.Tests /// incur costs for the associated Azure subscription. /// /// Every send or receive call will trigger diagnostics events as - /// long as they are being listened to. Therefore, other tests may - /// interfere with these. For this reason, these tests are marked - /// as non-parallelizable. + /// long as they are being listened to, making it possible for other + /// tests to interfere with these. For this reason, these tests are + /// marked as non-parallelizable. /// /// /// From fd7416307ff18234958d1d32a5d26dbbd939c316 Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Thu, 18 Jul 2019 10:25:44 -0700 Subject: [PATCH 21/21] Final fixes. --- .../tests/Diagnostics/DiagnosticsLiveTests.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs index f020debe8f1f0..6ce81cac8c0ef 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Diagnostics/DiagnosticsLiveTests.cs @@ -30,7 +30,6 @@ namespace Azure.Messaging.EventHubs.Tests /// long as they are being listened to, making it possible for other /// tests to interfere with these. For this reason, these tests are /// marked as non-parallelizable. - /// /// /// [TestFixture] @@ -669,13 +668,13 @@ private static void AssertCommonPayloadProperties(object eventPayload, string ac { var endpoint = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "Endpoint"); var entityPath = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "Entity"); - var pRouting = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "ActivePartitionRouting"); + var partitionRouting = GetPropertyValueFromAnonymousTypeInstance(eventPayload, "ActivePartitionRouting"); var expectedEndpointStart = "amqps://" + connectionStringProperties.Endpoint.Host; Assert.That(endpoint.AbsoluteUri.StartsWith(expectedEndpointStart), Is.True); Assert.That(entityPath, Is.EqualTo(connectionStringProperties.EventHubPath)); - Assert.That(pRouting, Is.EqualTo(activePartitionRouting)); + Assert.That(partitionRouting, Is.EqualTo(activePartitionRouting)); } ///