From 5543802439b36dd4f93aae37c1fdc60fcd333c34 Mon Sep 17 00:00:00 2001 From: Sean Feldman Date: Tue, 5 Sep 2023 13:52:25 -0600 Subject: [PATCH 1/6] Local serviceBusHelper2 initialization --- src/ServiceBusExplorer/Controls/HandleQueueControl.cs | 3 +-- src/ServiceBusExplorer/Controls/HandleTopicControl.cs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ServiceBusExplorer/Controls/HandleQueueControl.cs b/src/ServiceBusExplorer/Controls/HandleQueueControl.cs index b62d89dd..48c644fe 100644 --- a/src/ServiceBusExplorer/Controls/HandleQueueControl.cs +++ b/src/ServiceBusExplorer/Controls/HandleQueueControl.cs @@ -235,7 +235,6 @@ public partial class HandleQueueControl : UserControl private QueueDescription queueDescription = default!; private readonly ServiceBusHelper serviceBusHelper = default!; - private readonly ServiceBusHelper2 serviceBusHelper2 = default!; private readonly WriteToLogDelegate writeToLog = default!; private readonly string path = default!; private readonly List hiddenPages = new List(); @@ -297,9 +296,9 @@ public HandleQueueControl(WriteToLogDelegate writeToLog, ServiceBusHelper servic { this.writeToLog = writeToLog; this.serviceBusHelper = serviceBusHelper; - this.serviceBusHelper2 = serviceBusHelper.GetServiceBusHelper2(); this.path = path; this.queueDescription = queueDescription; + var serviceBusHelper2 = serviceBusHelper.GetServiceBusHelper2(); if (!serviceBusHelper2.ConnectionStringContainsEntityPath()) { diff --git a/src/ServiceBusExplorer/Controls/HandleTopicControl.cs b/src/ServiceBusExplorer/Controls/HandleTopicControl.cs index 996ae4b5..9ebc8052 100644 --- a/src/ServiceBusExplorer/Controls/HandleTopicControl.cs +++ b/src/ServiceBusExplorer/Controls/HandleTopicControl.cs @@ -125,7 +125,6 @@ public partial class HandleTopicControl : UserControl private readonly List hiddenPages = new List(); private TopicDescription topicDescription; private readonly ServiceBusHelper serviceBusHelper; - private readonly ServiceBusHelper2 serviceBusHelper2 = default!; private readonly WriteToLogDelegate writeToLog; private readonly bool premiumNamespace; private readonly string path; @@ -153,7 +152,7 @@ public HandleTopicControl(WriteToLogDelegate writeToLog, ServiceBusHelper servic { this.writeToLog = writeToLog; this.serviceBusHelper = serviceBusHelper; - this.serviceBusHelper2 = serviceBusHelper.GetServiceBusHelper2(); + var serviceBusHelper2 = serviceBusHelper.GetServiceBusHelper2(); if (!serviceBusHelper2.ConnectionStringContainsEntityPath()) { From 3db943a457ba21db9129d0e972d2b66f14c8f005 Mon Sep 17 00:00:00 2001 From: Sean Feldman Date: Tue, 5 Sep 2023 13:57:26 -0600 Subject: [PATCH 2/6] Patch the code to see events --- src/Common/Helpers/ServiceBusHelper.cs | 35 ++++++++++--------- .../Controls/PartitionListenerControl.cs | 27 +++++++++++--- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/Common/Helpers/ServiceBusHelper.cs b/src/Common/Helpers/ServiceBusHelper.cs index 637f28d2..ca031101 100644 --- a/src/Common/Helpers/ServiceBusHelper.cs +++ b/src/Common/Helpers/ServiceBusHelper.cs @@ -5060,19 +5060,19 @@ private static string GetMessageText(Stream stream, bool isBinary = false) public string GetMessageText(EventData eventDataToRead, out BodyType bodyType, bool doNotSerializeBody = false) { string eventDataText = null; - Stream stream = null; bodyType = BodyType.Stream; if (eventDataToRead == null) { return null; } - var inboundMessage = eventDataToRead.Clone(); + + using var stream = eventDataToRead.GetBodyStream(); + var bBodyParsed = false; if (!doNotSerializeBody) { try { - stream = inboundMessage.GetBodyStream(); if (stream != null) { var element = new BinaryMessageEncodingBindingElement @@ -5106,12 +5106,12 @@ public string GetMessageText(EventData eventDataToRead, out BodyType bodyType, b } catch (Exception) { - inboundMessage = eventDataToRead.Clone(); try { - stream = inboundMessage.GetBodyStream(); if (stream != null) { + stream.Seek(0, SeekOrigin.Begin); + var element = new BinaryMessageEncodingBindingElement { ReaderQuotas = new XmlDictionaryReaderQuotas @@ -5169,21 +5169,22 @@ public string GetMessageText(EventData eventDataToRead, out BodyType bodyType, b { try { - inboundMessage = eventDataToRead.Clone(); - stream = inboundMessage.GetBodyStream(); - stream.Seek(0, SeekOrigin.Begin); - using (var reader = new StreamReader(stream)) + if (stream != null) { - eventDataText = reader.ReadToEnd(); - if (eventDataText.ToCharArray().GroupBy(c => c). - Where(g => char.IsControl(g.Key) && g.Key != '\t' && g.Key != '\n' && g.Key != '\r'). - Select(g => g.First()).Any()) + stream.Seek(0, SeekOrigin.Begin); + using (var reader = new StreamReader(stream)) { - stream.Seek(0, SeekOrigin.Begin); - using (var binaryReader = new BinaryReader(stream)) + eventDataText = reader.ReadToEnd(); + if (eventDataText.ToCharArray().GroupBy(c => c). + Where(g => char.IsControl(g.Key) && g.Key != '\t' && g.Key != '\n' && g.Key != '\r'). + Select(g => g.First()).Any()) { - var bytes = binaryReader.ReadBytes((int)stream.Length); - eventDataText = BitConverter.ToString(bytes).Replace('-', ' '); + stream.Seek(0, SeekOrigin.Begin); + using (var binaryReader = new BinaryReader(stream)) + { + var bytes = binaryReader.ReadBytes((int)stream.Length); + eventDataText = BitConverter.ToString(bytes).Replace('-', ' '); + } } } } diff --git a/src/ServiceBusExplorer/Controls/PartitionListenerControl.cs b/src/ServiceBusExplorer/Controls/PartitionListenerControl.cs index b8f79e7f..de7fc672 100644 --- a/src/ServiceBusExplorer/Controls/PartitionListenerControl.cs +++ b/src/ServiceBusExplorer/Controls/PartitionListenerControl.cs @@ -644,11 +644,30 @@ private void eventDataDataGridView_RowEnter(object sender, DataGridViewCellEvent currentEventData = bindingList[e.RowIndex]; eventDataPropertyGrid.SelectedObject = currentEventData; - LanguageDetector.SetFormattedMessage(serviceBusHelper, currentEventData.Clone(), txtMessageText); + try + { + //var eventData = currentEventData.Clone(); + LanguageDetector.SetFormattedMessage(serviceBusHelper, currentEventData, txtMessageText); + } + catch (Exception exception) + { + HandleException(exception); + } - var listViewItems = currentEventData.Properties.Select(p => new ListViewItem(new[] { p.Key, (p.Value ?? string.Empty).ToString() })).ToArray(); - eventDataPropertyListView.Items.Clear(); - eventDataPropertyListView.Items.AddRange(listViewItems); + try + { + var type = typeof(EventData); + var fieldInfo = type.GetField("properties", BindingFlags.Instance | BindingFlags.NonPublic); + var value = fieldInfo.GetValue(currentEventData); + + var listViewItems = currentEventData.Properties.Select(p => new ListViewItem(new[] { p.Key, (p.Value ?? string.Empty).ToString() })).ToArray(); + eventDataPropertyListView.Items.Clear(); + eventDataPropertyListView.Items.AddRange(listViewItems); + } + catch (Exception exception) + { + HandleException(exception); + } } private void tabPageMessages_Resize(object sender, EventArgs e) From d4b786acfe1b17a21b977ebcd780dc4f788dd9cc Mon Sep 17 00:00:00 2001 From: Sean Feldman Date: Tue, 5 Sep 2023 14:03:44 -0600 Subject: [PATCH 3/6] Disable reflection code for investigation --- .../Controls/PartitionListenerControl.cs | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/ServiceBusExplorer/Controls/PartitionListenerControl.cs b/src/ServiceBusExplorer/Controls/PartitionListenerControl.cs index de7fc672..f896ce52 100644 --- a/src/ServiceBusExplorer/Controls/PartitionListenerControl.cs +++ b/src/ServiceBusExplorer/Controls/PartitionListenerControl.cs @@ -1,20 +1,20 @@ #region Copyright //======================================================================================= -// Microsoft Azure Customer Advisory Team +// Microsoft Azure Customer Advisory Team // // This sample is supplemental to the technical guidance published on my personal -// blog at http://blogs.msdn.com/b/paolos/. -// +// blog at http://blogs.msdn.com/b/paolos/. +// // Author: Paolo Salvatori //======================================================================================= // Copyright (c) Microsoft Corporation. All rights reserved. -// -// LICENSED UNDER THE APACHE LICENSE, VERSION 2.0 (THE "LICENSE"); YOU MAY NOT USE THESE -// FILES EXCEPT IN COMPLIANCE WITH THE LICENSE. YOU MAY OBTAIN A COPY OF THE LICENSE AT +// +// LICENSED UNDER THE APACHE LICENSE, VERSION 2.0 (THE "LICENSE"); YOU MAY NOT USE THESE +// FILES EXCEPT IN COMPLIANCE WITH THE LICENSE. YOU MAY OBTAIN A COPY OF THE LICENSE AT // http://www.apache.org/licenses/LICENSE-2.0 -// UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE DISTRIBUTED UNDER THE -// LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, EITHER EXPRESS OR IMPLIED. SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING +// UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE DISTRIBUTED UNDER THE +// LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, EITHER EXPRESS OR IMPLIED. SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING // PERMISSIONS AND LIMITATIONS UNDER THE LICENSE. //======================================================================================= #endregion @@ -315,12 +315,12 @@ private void InitializeControls() eventDataDataGridView.DefaultCellStyle.SelectionBackColor = Color.FromArgb(92, 125, 150); eventDataDataGridView.DefaultCellStyle.SelectionForeColor = SystemColors.Window; - // Set RowHeadersDefaultCellStyle.SelectionBackColor so that its default + // Set RowHeadersDefaultCellStyle.SelectionBackColor so that its default // value won't override DataGridView.DefaultCellStyle.SelectionBackColor. eventDataDataGridView.RowHeadersDefaultCellStyle.SelectionBackColor = Color.FromArgb(153, 180, 209); - // Set the background color for all rows and for alternating rows. - // The value for alternating rows overrides the value for all rows. + // Set the background color for all rows and for alternating rows. + // The value for alternating rows overrides the value for all rows. eventDataDataGridView.RowsDefaultCellStyle.BackColor = SystemColors.Window; eventDataDataGridView.RowsDefaultCellStyle.ForeColor = SystemColors.ControlText; //eventDataDataGridView.AlternatingRowsDefaultCellStyle.BackColor = Color.White; @@ -656,9 +656,10 @@ private void eventDataDataGridView_RowEnter(object sender, DataGridViewCellEvent try { - var type = typeof(EventData); - var fieldInfo = type.GetField("properties", BindingFlags.Instance | BindingFlags.NonPublic); - var value = fieldInfo.GetValue(currentEventData); + // Investigation: Properties throws OOTB. Can access the member field but it has no values. + // var type = typeof(EventData); + // var fieldInfo = type.GetField("properties", BindingFlags.Instance | BindingFlags.NonPublic); + // var value = fieldInfo.GetValue(currentEventData); var listViewItems = currentEventData.Properties.Select(p => new ListViewItem(new[] { p.Key, (p.Value ?? string.Empty).ToString() })).ToArray(); eventDataPropertyListView.Items.Clear(); @@ -1185,8 +1186,8 @@ private void RefreshGraph() if (InvokeRequired) { Invoke(new Action(InternalUpdateStatistics), - new object[] { receiveTuple.Item1, - receiveTuple.Item2, + new object[] { receiveTuple.Item1, + receiveTuple.Item2, receiveTuple.Item3, graph}); } @@ -1357,7 +1358,7 @@ private void PartitionListenerControl_Paint(object sender, PaintEventArgs e) cboReceiverInspector.Size.Height + 1); } - /// + /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. From f09ab5c6c16409699a376fb9fe84888fe31b345a Mon Sep 17 00:00:00 2001 From: Sean Feldman Date: Tue, 5 Sep 2023 22:13:59 -0600 Subject: [PATCH 4/6] Introduce EventData abstraction --- src/Common/Abstractions/EventDataMessage.cs | 50 +++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/Common/Abstractions/EventDataMessage.cs diff --git a/src/Common/Abstractions/EventDataMessage.cs b/src/Common/Abstractions/EventDataMessage.cs new file mode 100644 index 00000000..8e0dd55a --- /dev/null +++ b/src/Common/Abstractions/EventDataMessage.cs @@ -0,0 +1,50 @@ +namespace ServiceBusExplorer.Abstractions +{ + using System; + using System.Collections.Generic; + using System.IO; + using Microsoft.Azure.Amqp; + using Microsoft.ServiceBus.Messaging; + + public class EventDataMessage : IDisposable + { + readonly EventData eventData; + Stream stream; + + public EventDataMessage(EventData eventData) + { + this.eventData = eventData; + stream = eventData.GetBodyStream(); + Properties = eventData.Properties; + PartitionKey = eventData.PartitionKey; + SequenceNumber = eventData.SequenceNumber; + Offset = eventData.Offset; + SerializedSizeInBytes = eventData.SerializedSizeInBytes; + EnqueuedTimeUtc = eventData.EnqueuedTimeUtc; + SystemProperties = eventData.SystemProperties; + } + + public string PartitionKey { get; private set; } + public long SequenceNumber { get; private set; } + public long SerializedSizeInBytes { get; private set; } + public string Offset { get; private set; } + public DateTime EnqueuedTimeUtc { get; private set; } + public IDictionary Properties { get; private set; } + public IDictionary SystemProperties { get; private set; } + + public Stream GetBodyStream() + { + var memoryStream = new MemoryStream(); + + stream.CopyTo(memoryStream); + stream.Seek(0L, SeekOrigin.Begin); + + return memoryStream; + } + + public void Dispose() + { + eventData.Dispose(); + } + } +} From e83ac49ce7276c7694eed94c9312b5acb34065be Mon Sep 17 00:00:00 2001 From: Sean Feldman Date: Tue, 5 Sep 2023 22:14:50 -0600 Subject: [PATCH 5/6] Use abstraction --- src/Common/Helpers/ServiceBusHelper.cs | 63 ++++++++++--------- src/ServiceBus/Helpers/ServiceBusPurger.cs | 27 ++++---- .../Controls/PartitionListenerControl.cs | 22 ++++--- src/ServiceBusExplorer/Forms/EventDataForm.cs | 34 +++++----- .../UIHelpers/LanguageDetector.cs | 24 +++---- 5 files changed, 88 insertions(+), 82 deletions(-) diff --git a/src/Common/Helpers/ServiceBusHelper.cs b/src/Common/Helpers/ServiceBusHelper.cs index ca031101..62a8cee0 100644 --- a/src/Common/Helpers/ServiceBusHelper.cs +++ b/src/Common/Helpers/ServiceBusHelper.cs @@ -1,20 +1,20 @@ #region Copyright //======================================================================================= -// Microsoft Azure Customer Advisory Team +// Microsoft Azure Customer Advisory Team // // This sample is supplemental to the technical guidance published on my personal -// blog at http://blogs.msdn.com/b/paolos/. -// +// blog at http://blogs.msdn.com/b/paolos/. +// // Author: Paolo Salvatori //======================================================================================= // Copyright (c) Microsoft Corporation. All rights reserved. -// -// LICENSED UNDER THE APACHE LICENSE, VERSION 2.0 (THE "LICENSE"); YOU MAY NOT USE THESE -// FILES EXCEPT IN COMPLIANCE WITH THE LICENSE. YOU MAY OBTAIN A COPY OF THE LICENSE AT +// +// LICENSED UNDER THE APACHE LICENSE, VERSION 2.0 (THE "LICENSE"); YOU MAY NOT USE THESE +// FILES EXCEPT IN COMPLIANCE WITH THE LICENSE. YOU MAY OBTAIN A COPY OF THE LICENSE AT // http://www.apache.org/licenses/LICENSE-2.0 -// UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE DISTRIBUTED UNDER THE -// LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, EITHER EXPRESS OR IMPLIED. SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING +// UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE DISTRIBUTED UNDER THE +// LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, EITHER EXPRESS OR IMPLIED. SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING // PERMISSIONS AND LIMITATIONS UNDER THE LICENSE. //======================================================================================= #endregion @@ -54,6 +54,7 @@ namespace ServiceBusExplorer { using System.IO.Compression; using System.Web.UI.WebControls; + using Abstractions; using ServiceBusConnectionStringBuilder = Microsoft.ServiceBus.ServiceBusConnectionStringBuilder; public enum BodyType @@ -425,7 +426,7 @@ public string ServicePath public string ConnectionStringWithoutEntityPath { get - { + { var builder = new ServiceBusConnectionStringBuilder(connectionString) { EntityPath = string.Empty @@ -700,7 +701,7 @@ public MessagingFactory CreateMessagingFactory() TokenProvider = tokenProvider, OperationTimeout = TimeSpan.FromMinutes(5) }; - // In the first release of the service bus, the only available transport protocol is sb + // In the first release of the service bus, the only available transport protocol is sb if (scheme == DefaultScheme) { messagingFactorySettings.NetMessagingTransportSettings = new NetMessagingTransportSettings(); @@ -734,16 +735,16 @@ public bool Connect(ServiceBusNamespace serviceBusNamespace) throw new Exception($"Could not contact host in connection string: { serviceBusNamespace.ConnectionString }."); } - Func func = (() => + var func = (() => { connectionString = serviceBusNamespace.ConnectionString; currentSharedAccessKey = serviceBusNamespace.SharedAccessKey; currentSharedAccessKeyName = serviceBusNamespace.SharedAccessKeyName; currentTransportType = serviceBusNamespace.TransportType; - // The NamespaceManager class can be used for managing entities, - // such as queues, topics, subscriptions, and rules, in your service namespace. - // You must provide service namespace address and access credentials in order + // The NamespaceManager class can be used for managing entities, + // such as queues, topics, subscriptions, and rules, in your service namespace. + // You must provide service namespace address and access credentials in order // to manage your service namespace. namespaceManager = Microsoft.ServiceBus.NamespaceManager.CreateFromConnectionString(ConnectionStringWithoutEntityPath); @@ -809,7 +810,7 @@ public RelayDescription GetRelay(string path) /// /// Retrieves an enumerable collection of all relays in the service bus namespace. /// - /// Returns an IEnumerable collection of all relays in the service namespace. + /// Returns an IEnumerable collection of all relays in the service namespace. /// Returns an empty collection if no relay exists in this service namespace. public IEnumerable GetRelays(int timeoutInSeconds) { @@ -955,7 +956,7 @@ public EventHubDescription GetEventHub(string path) /// /// Retrieves an enumerable collection of all event hubs in the service bus namespace. /// - /// Returns an IEnumerable collection of all event hubs in the service namespace. + /// Returns an IEnumerable collection of all event hubs in the service namespace. /// Returns an empty collection if no event hub exists in this service namespace. public Task> GetEventHubs(int timeoutInSeconds) { @@ -1228,7 +1229,7 @@ public Uri GetPartitionUri(string eventHubName, string consumerGroupName, string /// Retrieves the collection of consumer groups of the event hub passed as a parameter. /// /// The path of a event hub. - /// The name of a consumer group. + /// The name of a consumer group. /// Returns an IEnumerable collection of consumer groups attached to the event hub passed as a parameter. public ConsumerGroupDescription GetConsumerGroup(string eventHubPath, string name) { @@ -1419,7 +1420,7 @@ public AzureNotificationHubs.NotificationHubDescription GetNotificationHub(strin /// /// Retrieves an enumerable collection of all notification hubs in the service bus namespace. /// - /// Returns an IEnumerable collection of all notification hubs in the service namespace. + /// Returns an IEnumerable collection of all notification hubs in the service namespace. /// Returns an empty collection if no notification hub exists in this service namespace. public IEnumerable GetNotificationHubs(int timeoutInSeconds) { @@ -1554,8 +1555,8 @@ public Uri GetNotificationHubUri(string notificationHubPath) /// /// Retrieves an enumerable collection of all queues in the service bus namespace. /// - /// OData filter. - /// Returns an IEnumerable collection of all queues in the service namespace. + /// OData filter. + /// Returns an IEnumerable collection of all queues in the service namespace. /// Returns an empty collection if no queue exists in this service namespace. public IEnumerable GetQueues(string filter, int timeoutInSeconds) { @@ -1648,8 +1649,8 @@ public QueueDescription GetQueue(string path) /// /// Retrieves an enumerable collection of all message sessions for the queue passed as argument. /// - /// The queue for which to search message sessions. - /// The time the session was last updated. + /// The queue for which to search message sessions. + /// The time the session was last updated. /// Returns an IEnumerable collection of message sessions. public IEnumerable GetMessageSessions(string path, DateTime? dateTime) { @@ -1669,8 +1670,8 @@ public IEnumerable GetMessageSessions(string path, DateTime? dat /// /// Retrieves an enumerable collection of all message sessions for the queue passed as argument. /// - /// The queue for which to search message sessions. - /// The time the session was last updated. + /// The queue for which to search message sessions. + /// The time the session was last updated. /// Returns an IEnumerable collection of message sessions. public IEnumerable GetMessageSessions(QueueDescription queue, DateTime? dateTime) { @@ -1708,8 +1709,8 @@ public TopicDescription GetTopic(string path) /// /// Retrieves an enumerable collection of all topics in the service bus namespace. /// - /// OData filter. - /// Returns an IEnumerable collection of all topics in the service namespace. + /// OData filter. + /// Returns an IEnumerable collection of all topics in the service namespace. /// Returns an empty collection if no topic exists in this service namespace. public IEnumerable GetTopics(string filter, int timeoutInSeconds) { @@ -1848,8 +1849,8 @@ public IEnumerable GetSubscriptions(string topicPath) /// /// Retrieves an enumerable collection of all message sessions for the subscription passed as argument. /// - /// The subscription for which to search message sessions. - /// The time the session was last updated. + /// The subscription for which to search message sessions. + /// The time the session was last updated. /// Returns an IEnumerable collection of message sessions. public IEnumerable GetMessageSessions(SubscriptionDescription subscription, DateTime? dateTime) { @@ -2515,7 +2516,7 @@ public RuleDescription AddRule(SubscriptionDescription subscriptionDescription, subscriptionDescription.Name), writeToLog); RetryHelper.RetryAction(() => subscriptionClient.AddRule(ruleDescription), writeToLog); - Func> func = (() => namespaceManager.GetRules(subscriptionDescription.TopicPath, subscriptionDescription.Name)); + var func = (() => namespaceManager.GetRules(subscriptionDescription.TopicPath, subscriptionDescription.Name)); var rules = RetryHelper.RetryFunc(func, writeToLog); var rule = rules.FirstOrDefault(r => r.Name == ruleDescription.Name); WriteToLogIf(traceEnabled, string.Format(CultureInfo.CurrentCulture, RuleCreated, ruleDescription.Name, subscriptionDescription.Name)); @@ -5057,7 +5058,7 @@ private static string GetMessageText(Stream stream, bool isBinary = false) /// BodyType /// /// The content of the EventData. - public string GetMessageText(EventData eventDataToRead, out BodyType bodyType, bool doNotSerializeBody = false) + public string GetMessageText(EventDataMessage eventDataToRead, out BodyType bodyType, bool doNotSerializeBody = false) { string eventDataText = null; bodyType = BodyType.Stream; diff --git a/src/ServiceBus/Helpers/ServiceBusPurger.cs b/src/ServiceBus/Helpers/ServiceBusPurger.cs index 75a4ebad..a217bc1b 100644 --- a/src/ServiceBus/Helpers/ServiceBusPurger.cs +++ b/src/ServiceBus/Helpers/ServiceBusPurger.cs @@ -1,20 +1,20 @@ #region Copyright //======================================================================================= -// Microsoft Azure Customer Advisory Team +// Microsoft Azure Customer Advisory Team // // This sample is supplemental to the technical guidance published on my personal -// blog at http://blogs.msdn.com/b/paolos/. -// +// blog at http://blogs.msdn.com/b/paolos/. +// // Author: Paolo Salvatori //======================================================================================= // Copyright (c) Microsoft Corporation. All rights reserved. -// -// LICENSED UNDER THE APACHE LICENSE, VERSION 2.0 (THE "LICENSE"); YOU MAY NOT USE THESE -// FILES EXCEPT IN COMPLIANCE WITH THE LICENSE. YOU MAY OBTAIN A COPY OF THE LICENSE AT +// +// LICENSED UNDER THE APACHE LICENSE, VERSION 2.0 (THE "LICENSE"); YOU MAY NOT USE THESE +// FILES EXCEPT IN COMPLIANCE WITH THE LICENSE. YOU MAY OBTAIN A COPY OF THE LICENSE AT // http://www.apache.org/licenses/LICENSE-2.0 -// UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE DISTRIBUTED UNDER THE -// LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, EITHER EXPRESS OR IMPLIED. SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING +// UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE DISTRIBUTED UNDER THE +// LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, EITHER EXPRESS OR IMPLIED. SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING // PERMISSIONS AND LIMITATIONS UNDER THE LICENSE. //======================================================================================= #endregion @@ -100,7 +100,6 @@ private async Task PurgeSessionEntity(TEntity entity) { long totalMessagesPurged = 0; var consecutiveSessionTimeOuts = 0; - ServiceBusSessionReceiver sessionReceiver = null; long messagesToPurgeCount = await GetMessageCount(entity, deadLetterQueueData: false) .ConfigureAwait(false); @@ -117,9 +116,9 @@ private async Task PurgeSessionEntity(TEntity entity) while (consecutiveSessionTimeOuts < enoughZeroReceives && totalMessagesPurged < messagesToPurgeCount) { - sessionReceiver = await CreateServiceBusSessionReceiver(entity, - client, - purgeDeadLetterQueueInstead: false) + var sessionReceiver = await CreateServiceBusSessionReceiver(entity, + client, + purgeDeadLetterQueueInstead: false) .ConfigureAwait(false); var consecutiveZeroBatchReceives = 0; @@ -236,7 +235,7 @@ private async Task DoPurgeNonSessionEntity(TEntity entity, long messagesTo await receiver.CloseAsync().ConfigureAwait(false); } } - }); // End of lambda + }); // End of lambda } await Task.WhenAll(tasks).ConfigureAwait(false); diff --git a/src/ServiceBusExplorer/Controls/PartitionListenerControl.cs b/src/ServiceBusExplorer/Controls/PartitionListenerControl.cs index f896ce52..86ee13fd 100644 --- a/src/ServiceBusExplorer/Controls/PartitionListenerControl.cs +++ b/src/ServiceBusExplorer/Controls/PartitionListenerControl.cs @@ -45,6 +45,8 @@ namespace ServiceBusExplorer.Controls { + using Abstractions; + public partial class PartitionListenerControl : UserControl { #region Private Constants @@ -115,14 +117,13 @@ public partial class PartitionListenerControl : UserControl private readonly WriteToLogDelegate writeToLog; private readonly Func stopLog; private readonly Action startLog; - private EventData currentEventData; - private int grouperEventDataCustomPropertiesWidth; + private EventDataMessage currentEventData; private int currentMessageRowIndex; private readonly int partitionCount; private bool sorting; - private readonly SortableBindingList eventDataBindingList = new SortableBindingList { AllowNew = false, AllowEdit = false, AllowRemove = false }; + private readonly SortableBindingList eventDataBindingList = new SortableBindingList { AllowNew = false, AllowEdit = false, AllowRemove = false }; private readonly IList partitionRuntumeInformationList = new List(); - private BlockingCollection eventDataCollection = new BlockingCollection(); + private BlockingCollection eventDataCollection = new BlockingCollection(); private System.Timers.Timer timer; private long receiverMessageNumber; private long receiverMessageSizeTotal; @@ -151,6 +152,7 @@ public partial class PartitionListenerControl : UserControl private bool clearing; private bool cleared; private readonly string iotHubConnectionString; + int grouperEventDataCustomPropertiesWidth; public Task AsyncTrackEventDataTask { get; private set; } #endregion @@ -631,7 +633,7 @@ private void CalculateLastColumnWidth(object sender) private void eventDataDataGridView_RowEnter(object sender, DataGridViewCellEventArgs e) { - var bindingList = eventDataBindingSource.DataSource as BindingList; + var bindingList = eventDataBindingSource.DataSource as BindingList; currentMessageRowIndex = e.RowIndex; if (bindingList == null) { @@ -711,7 +713,7 @@ private void eventDataDataGridView_CellDoubleClick(object sender, DataGridViewCe { return; } - var bindingList = eventDataBindingSource.DataSource as BindingList; + var bindingList = eventDataBindingSource.DataSource as BindingList; if (bindingList == null) { return; @@ -851,7 +853,7 @@ private async void btnStart_Click(object sender, EventArgs e) checkBoxCheckpoint, cancellationTokenSource.Token) { - TrackEvent = ev => Invoke(new Action(m => eventDataCollection.Add(m)), ev), + TrackEvent = ev => Invoke(new Action(m => eventDataCollection.Add(new EventDataMessage(m))), ev), GetElapsedTime = GetElapsedTime, UpdateStatistics = UpdateStatistics, WriteToLog = writeToLog, @@ -973,7 +975,7 @@ private void btnClear_Click(object sender, EventArgs e) clearing = true; cleared = true; eventDataCollection.Dispose(); - eventDataCollection = new BlockingCollection(); + eventDataCollection = new BlockingCollection(); ClearTrackedMessages(); ClearStatistics(); ClearCharts(); @@ -1563,8 +1565,8 @@ private void saveSelectedEventsToolStripMenuItem_Click(object sender, EventArgs { return; } - var messages = eventDataDataGridView.SelectedRows.Cast().Select(r => r.DataBoundItem as EventData); - IEnumerable events = messages as EventData[] ?? messages.ToArray(); + var messages = eventDataDataGridView.SelectedRows.Cast().Select(r => r.DataBoundItem as EventDataMessage); + IEnumerable events = messages as EventDataMessage[] ?? messages.ToArray(); if (!events.Any()) { return; diff --git a/src/ServiceBusExplorer/Forms/EventDataForm.cs b/src/ServiceBusExplorer/Forms/EventDataForm.cs index 29f69bbe..833b528c 100644 --- a/src/ServiceBusExplorer/Forms/EventDataForm.cs +++ b/src/ServiceBusExplorer/Forms/EventDataForm.cs @@ -1,20 +1,20 @@ #region Copyright //======================================================================================= -// Microsoft Azure Customer Advisory Team +// Microsoft Azure Customer Advisory Team // // This sample is supplemental to the technical guidance published on my personal -// blog at http://blogs.msdn.com/b/paolos/. -// +// blog at http://blogs.msdn.com/b/paolos/. +// // Author: Paolo Salvatori //======================================================================================= // Copyright (c) Microsoft Corporation. All rights reserved. -// -// LICENSED UNDER THE APACHE LICENSE, VERSION 2.0 (THE "LICENSE"); YOU MAY NOT USE THESE -// FILES EXCEPT IN COMPLIANCE WITH THE LICENSE. YOU MAY OBTAIN A COPY OF THE LICENSE AT +// +// LICENSED UNDER THE APACHE LICENSE, VERSION 2.0 (THE "LICENSE"); YOU MAY NOT USE THESE +// FILES EXCEPT IN COMPLIANCE WITH THE LICENSE. YOU MAY OBTAIN A COPY OF THE LICENSE AT // http://www.apache.org/licenses/LICENSE-2.0 -// UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE DISTRIBUTED UNDER THE -// LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, EITHER EXPRESS OR IMPLIED. SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING +// UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE DISTRIBUTED UNDER THE +// LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, EITHER EXPRESS OR IMPLIED. SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING // PERMISSIONS AND LIMITATIONS UNDER THE LICENSE. //======================================================================================= #endregion @@ -38,6 +38,8 @@ namespace ServiceBusExplorer.Forms { + using Abstractions; + public partial class EventDataForm : Form { #region Private Constants @@ -67,7 +69,7 @@ public partial class EventDataForm : Form private readonly ServiceBusHelper serviceBusHelper; private readonly WriteToLogDelegate writeToLog; private readonly BindingSource bindingSource = new BindingSource(); - private readonly EventData eventData; + private readonly EventDataMessage eventData; #endregion #region Private Static Fields @@ -75,7 +77,7 @@ public partial class EventDataForm : Form #endregion #region Public Constructor - public EventDataForm(EventData eventData, ServiceBusHelper serviceBusHelper, WriteToLogDelegate writeToLog) + public EventDataForm(EventDataMessage eventData, ServiceBusHelper serviceBusHelper, WriteToLogDelegate writeToLog) { this.eventData = eventData; this.serviceBusHelper = serviceBusHelper; @@ -102,7 +104,7 @@ public EventDataForm(EventData eventData, ServiceBusHelper serviceBusHelper, Wri } // Initialize the DataGridView. - bindingSource.DataSource = new BindingList(eventData.Properties.Select(p => new MessagePropertyInfo(p.Key, + bindingSource.DataSource = new BindingList(eventData.Properties.Select(p => new MessagePropertyInfo(p.Key, p.Value.GetType().ToString().Substring(7), p.Value)).ToList()); propertiesDataGridView.AutoGenerateColumns = false; @@ -146,12 +148,12 @@ public EventDataForm(EventData eventData, ServiceBusHelper serviceBusHelper, Wri propertiesDataGridView.DefaultCellStyle.SelectionBackColor = Color.FromArgb(92, 125, 150); propertiesDataGridView.DefaultCellStyle.SelectionForeColor = SystemColors.Window; - // Set RowHeadersDefaultCellStyle.SelectionBackColor so that its default + // Set RowHeadersDefaultCellStyle.SelectionBackColor so that its default // value won't override DataGridView.DefaultCellStyle.SelectionBackColor. propertiesDataGridView.RowHeadersDefaultCellStyle.SelectionBackColor = Color.FromArgb(153, 180, 209); - // Set the background color for all rows and for alternating rows. - // The value for alternating rows overrides the value for all rows. + // Set the background color for all rows and for alternating rows. + // The value for alternating rows overrides the value for all rows. propertiesDataGridView.RowsDefaultCellStyle.BackColor = SystemColors.Window; propertiesDataGridView.RowsDefaultCellStyle.ForeColor = SystemColors.ControlText; //propertiesDataGridView.AlternatingRowsDefaultCellStyle.BackColor = Color.White; @@ -286,7 +288,7 @@ private string CreateFileName() CultureInfo.CurrentCulture.TextInfo.ToTitleCase(serviceBusHelper.Namespace), DateTime.Now.ToString(CultureInfo.InvariantCulture).Replace('/', '-').Replace(':', '-')); } - + private void propertiesDataGridView_DataError(object sender, DataGridViewDataErrorEventArgs e) { e.Cancel = true; diff --git a/src/ServiceBusExplorer/UIHelpers/LanguageDetector.cs b/src/ServiceBusExplorer/UIHelpers/LanguageDetector.cs index a341c7c8..7b743744 100644 --- a/src/ServiceBusExplorer/UIHelpers/LanguageDetector.cs +++ b/src/ServiceBusExplorer/UIHelpers/LanguageDetector.cs @@ -1,21 +1,21 @@ #region Copyright //======================================================================================= -// Microsoft Azure Customer Advisory Team +// Microsoft Azure Customer Advisory Team // // This sample is supplemental to the technical guidance published on my personal -// blog at http://blogs.msdn.com/b/paolos/. -// +// blog at http://blogs.msdn.com/b/paolos/. +// // Author: Paolo Salvatori //======================================================================================= // Copyright (c) Microsoft Corporation. All rights reserved. -// -// LICENSED UNDER THE APACHE LICENSE, VERSION 2.0 (THE "LICENSE"); YOU MAY NOT USE THESE -// FILES EXCEPT IN COMPLIANCE WITH THE LICENSE. YOU MAY OBTAIN A COPY OF THE LICENSE AT +// +// LICENSED UNDER THE APACHE LICENSE, VERSION 2.0 (THE "LICENSE"); YOU MAY NOT USE THESE +// FILES EXCEPT IN COMPLIANCE WITH THE LICENSE. YOU MAY OBTAIN A COPY OF THE LICENSE AT // http://www.apache.org/licenses/LICENSE-2.0 -// UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE DISTRIBUTED UNDER THE -// LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, EITHER EXPRESS OR IMPLIED. SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING +// UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE DISTRIBUTED UNDER THE +// LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, EITHER EXPRESS OR IMPLIED. SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING // PERMISSIONS AND LIMITATIONS UNDER THE LICENSE. //======================================================================================= @@ -35,6 +35,8 @@ namespace ServiceBusExplorer.UIHelpers { + using Abstractions; + public class LanguageDetector { #region Public Static Methods @@ -55,11 +57,11 @@ public static void SetFormattedMessage(ServiceBusHelper serviceBusHelper, Broker throw new ArgumentNullException(nameof(textBox), $"{nameof(textBox)} parameter cannot be null"); } - InternalSetFormattedMessage(serviceBusHelper.GetMessageText(message, + InternalSetFormattedMessage(serviceBusHelper.GetMessageText(message, MainForm.SingletonMainForm.UseAscii, out _), textBox); } - public static void SetFormattedMessage(ServiceBusHelper serviceBusHelper, EventData message, FastColoredTextBox textBox) + public static void SetFormattedMessage(ServiceBusHelper serviceBusHelper, EventDataMessage message, FastColoredTextBox textBox) { if (serviceBusHelper == null) { From c90eca89b5338e77ece6a56c8a3eb8e98be89077 Mon Sep 17 00:00:00 2001 From: Sean Feldman Date: Wed, 6 Sep 2023 21:20:00 -0600 Subject: [PATCH 6/6] Fix single event saving --- .../Controls/PartitionListenerControl.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/ServiceBusExplorer/Controls/PartitionListenerControl.cs b/src/ServiceBusExplorer/Controls/PartitionListenerControl.cs index 86ee13fd..b9eee34e 100644 --- a/src/ServiceBusExplorer/Controls/PartitionListenerControl.cs +++ b/src/ServiceBusExplorer/Controls/PartitionListenerControl.cs @@ -658,11 +658,6 @@ private void eventDataDataGridView_RowEnter(object sender, DataGridViewCellEvent try { - // Investigation: Properties throws OOTB. Can access the member field but it has no values. - // var type = typeof(EventData); - // var fieldInfo = type.GetField("properties", BindingFlags.Instance | BindingFlags.NonPublic); - // var value = fieldInfo.GetValue(currentEventData); - var listViewItems = currentEventData.Properties.Select(p => new ListViewItem(new[] { p.Key, (p.Value ?? string.Empty).ToString() })).ToArray(); eventDataPropertyListView.Items.Clear(); eventDataPropertyListView.Items.AddRange(listViewItems); @@ -1523,7 +1518,7 @@ private void saveSelectedEventToolStripMenuItem_Click(object sender, EventArgs e { return; } - var bindingList = eventDataBindingSource.DataSource as BindingList; + var bindingList = eventDataBindingSource.DataSource as BindingList; if (bindingList == null) { return;