// ReSharper disable once FunctionComplexityOverflow private async void btnStart_Click(object sender, EventArgs e) { if (string.Compare(btnStart.Text, Start, StringComparison.OrdinalIgnoreCase) == 0) { if (startLog != null && checkBoxLogging.Checked) { startLog(); } receiverEventDataInspector = cboReceiverInspector.SelectedIndex > 0 ? Activator.CreateInstance(serviceBusHelper.EventDataInspectors[cboReceiverInspector.Text]) as IEventDataInspector : null; cancellationTokenSource = new CancellationTokenSource(); btnStart.Text = Stop; blockingCollection = new BlockingCollection<Tuple<long, long, long>>(); timer = new System.Timers.Timer { AutoReset = true, Enabled = true, Interval = 1000 * txtRefreshInformation.IntegerValue }; timer.Elapsed += timer_Elapsed; var ns = serviceBusHelper != null && !string.IsNullOrWhiteSpace(serviceBusHelper.Namespace) ? serviceBusHelper.Namespace : iotHubConnectionString; var eventHub = eventHubClient.Path; var maxBatchSize = txtMaxBatchSize.IntegerValue > 0 ? txtMaxBatchSize.IntegerValue : 1; var receiveTimeout = TimeSpan.FromSeconds(txtReceiveTimeout.IntegerValue); try { registeredDictionary = new Dictionary<string, bool>(partitionRuntumeInformationList.Count); var startDateTimeEnabled = pickerStartingDateTimeUtc.Checked; var startDateTimeValue = DateTime.SpecifyKind(pickerStartingDateTimeUtc.Value, DateTimeKind.Utc); var eventProcessorOptions = new EventProcessorOptions { InitialOffsetProvider = partitionId => { if (startDateTimeEnabled) { return startDateTimeValue; } var lease = EventProcessorCheckpointHelper.GetLease(ns, eventHub, consumerGroup.GroupName, partitionId); return lease != null ? lease.Offset : "-1"; }, MaxBatchSize = maxBatchSize, ReceiveTimeOut = receiveTimeout }; eventProcessorOptions.ExceptionReceived += (s, ex) => HandleException(ex.Exception); var checkpointManager = new EventProcessorCheckpointManager { Namespace = ns, EventHub = eventHub, ConsumerGroup = consumerGroup.GroupName }; var eventProcessorFactoryConfiguration = new EventProcessorFactoryConfiguration(checkBoxLogging, checkBoxTrackMessages, checkBoxVerbose, checkBoxOffsetInclusive, checkBoxCheckpoint, cancellationTokenSource.Token) { TrackEvent = ev => Invoke(new Action<EventData>(m => eventDataCollection.Add(m)), ev), GetElapsedTime = GetElapsedTime, UpdateStatistics = UpdateStatistics, WriteToLog = writeToLog, MessageInspector = receiverEventDataInspector, ServiceBusHelper = serviceBusHelper }; foreach (var partitionRuntimeInformation in partitionRuntumeInformationList) { #pragma warning disable 4014 consumerGroup.RegisterProcessorFactoryAsync( #pragma warning restore 4014 EventProcessorCheckpointHelper.GetLease(ns, eventHub, consumerGroup.GroupName, partitionRuntimeInformation.PartitionId), checkpointManager, new EventProcessorFactory<EventProcessor>(eventProcessorFactoryConfiguration), eventProcessorOptions); registeredDictionary.Add(partitionRuntimeInformation.PartitionId, true); } #pragma warning disable 4014 Task.Run(new Action(RefreshGraph)); #pragma warning restore 4014 } catch (Exception ex) { HandleException(ex); StopListenerAsync().Wait(); btnStart.Text = Start; } } else { try { await StopListenerAsync(); btnStart.Text = Start; } catch (Exception ex) { HandleException(ex); } } }
/// <summary> /// This method can be used to send multiple messages to a queue or a topic. /// </summary> /// <param name="eventHubClient">An EventHubClient object used to send messages.</param> /// <param name="eventDataTemplateEnumerable">A collection of message templates to use to clone messages from.</param> /// <param name="getMessageNumber">This function returns the message number.</param> /// <param name="messageCount">The total number of messages to send.</param> /// <param name="taskId">The sender task id.</param> /// <param name="updatePartitionKey">Indicates whether to use a unique template key for each message.</param> /// <param name="addMessageNumber">Indicates whether to add a message number property.</param> /// <param name="logging">Indicates whether to enable logging of message content and properties.</param> /// <param name="verbose">Indicates whether to enable verbose logging.</param> /// <param name="statistics">Indicates whether to enable sender statistics.</param> /// <param name="eventDataInspector">Event Data inspector.</param> /// <param name="updateStatistics">When statistics = true, this delegate is invoked to update statistics.</param> /// <param name="sendBatch">Indicates whether to use SendBatch.</param> /// <param name="senderThinkTime">Indicates whether to use think time.</param> /// <param name="thinkTime">Indicates the value of the sender think time.</param> /// <param name="batchSize">Indicates the batch size.</param> /// <param name="cancellationTokenSource">The cancellation token.</param> /// <returns>Trace message.</returns> public async Task<string> SendEventData(EventHubClient eventHubClient, IEnumerable<EventData> eventDataTemplateEnumerable, Func<long> getMessageNumber, long messageCount, int taskId, bool updatePartitionKey, bool addMessageNumber, bool logging, bool verbose, bool statistics, bool sendBatch, int batchSize, bool senderThinkTime, int thinkTime, IEventDataInspector eventDataInspector, UpdateStatisticsDelegate updateStatistics, CancellationTokenSource cancellationTokenSource) { if (eventHubClient == null) { throw new ArgumentNullException(EventHubClientCannotBeNull); } if (eventDataTemplateEnumerable == null) { throw new ArgumentNullException(EventDataTemplateEnumerableCannotBeNull); } if (cancellationTokenSource == null) { throw new ArgumentNullException(CancellationTokenSourceCannotBeNull); } var eventDataCircularList = new CircularList<EventData>(eventDataTemplateEnumerable); long messagesSent = 0; long totalElapsedTime = 0; long minimumSendTime = long.MaxValue; long maximumSendTime = 0; string exceptionMessage = null; try { if (sendBatch && batchSize > 1) { //var more = true; //while (!cancellationTokenSource.Token.IsCancellationRequested && more) //{ // var eventDataList = new List<EventData>(); // var messageNumberList = new List<long>(); // while (!cancellationTokenSource.Token.IsCancellationRequested && // messageNumberList.Count < batchSize && more) // { // messageNumber = getMessageNumber(); // if (messageNumber < messageCount) // { // messageNumberList.Add(messageNumber); // } // else // { // more = false; // } // } // if (messageNumberList.Count > 0) // { // long elapsedMilliseconds = 0; // await RetryHelper.RetryActionAsync(async () => // { // for (var i = 0; i < messageNumberList.Count; i++) // { // eventDataList.Add(eventDataInspector != null? // eventDataInspector.BeforeSendMessage(eventDataCircularList.Next.Clone()) : // eventDataCircularList.Next.Clone()); // if (addMessageNumber) // { // eventDataList[i].Properties[MessageNumber] = messageNumberList[i]; // } // } // if (messageNumberList.Count > 0) // { // elapsedMilliseconds = await SendEventDataBatch(eventHubClient, // eventDataList, // messageNumberList, // taskId, // logging, // verbose); // } // }, // writeToLog); // messagesSent += eventDataList.Count; // if (elapsedMilliseconds > maximumSendTime) // { // maximumSendTime = elapsedMilliseconds; // } // if (elapsedMilliseconds < minimumSendTime) // { // minimumSendTime = elapsedMilliseconds; // } // totalElapsedTime += elapsedMilliseconds; // if (statistics) // { // updateStatistics(eventDataList.Count, elapsedMilliseconds, DirectionType.Send); // } // } // if (senderThinkTime) // { // WriteToLog(string.Format(SleepingFor, thinkTime)); // Thread.Sleep(thinkTime); // } //} } else { long messageNumber; while ((messageNumber = getMessageNumber()) < messageCount && !cancellationTokenSource.Token.IsCancellationRequested) { long elapsedMilliseconds = 0; long number = messageNumber; await RetryHelper.RetryActionAsync(async () => { var eventData = eventDataInspector != null ? eventDataInspector.BeforeSendMessage(eventDataCircularList.Next.Clone()) : eventDataCircularList.Next.Clone(); if (addMessageNumber) { // ReSharper disable AccessToModifiedClosure eventData.Properties[MessageNumber] = number; // ReSharper restore AccessToModifiedClosure } elapsedMilliseconds = await SendEventData(eventHubClient, eventData, number, taskId, logging, verbose); }, writeToLog); messagesSent++; if (elapsedMilliseconds > maximumSendTime) { maximumSendTime = elapsedMilliseconds; } if (elapsedMilliseconds < minimumSendTime) { minimumSendTime = elapsedMilliseconds; } totalElapsedTime += elapsedMilliseconds; if (statistics) { updateStatistics(1, elapsedMilliseconds, DirectionType.Send); } if (senderThinkTime) { WriteToLog(string.Format(SleepingFor, thinkTime)); Thread.Sleep(thinkTime); } } } } catch (ServerBusyException ex) { eventHubClient.Abort(); exceptionMessage = ex.Message; } catch (MessageLockLostException ex) { eventHubClient.Abort(); exceptionMessage = ex.Message; } catch (CommunicationObjectAbortedException ex) { eventHubClient.Abort(); exceptionMessage = ex.Message; } catch (CommunicationObjectFaultedException ex) { eventHubClient.Abort(); exceptionMessage = ex.Message; } catch (CommunicationException ex) { eventHubClient.Abort(); exceptionMessage = ex.Message; } catch (TimeoutException ex) { eventHubClient.Abort(); exceptionMessage = ex.Message; } catch (Exception ex) { eventHubClient.Abort(); exceptionMessage = ex.Message; } var averageSendTime = messagesSent > 0 ? totalElapsedTime / messagesSent : maximumSendTime; // ReSharper disable RedundantCast var messagesPerSecond = totalElapsedTime > 0 ? (double)(messagesSent * 1000) / (double)totalElapsedTime : 0; // ReSharper restore RedundantCast var builder = new StringBuilder(); builder.AppendLine(string.Format(CultureInfo.CurrentCulture, SenderStatisticsHeader, taskId)); if (!string.IsNullOrWhiteSpace(exceptionMessage)) { builder.AppendLine(exceptionMessage); throw new Exception(builder.ToString()); } builder.AppendLine(string.Format(CultureInfo.CurrentCulture, SenderStatitiscsLine1, messagesSent, messagesPerSecond, totalElapsedTime)); builder.AppendLine(string.Format(CultureInfo.CurrentCulture, SenderStatitiscsLine2, averageSendTime, minimumSendTime == long.MaxValue ? 0 : minimumSendTime, maximumSendTime)); return builder.ToString(); }
public EventProcessor() { this.cancellationTokenSource = new CancellationTokenSource(); this.eventDataInspector = new LogEventDataInspector(); this.eventDataInspector.StartTask(cancellationTokenSource.Token, Filter.Path); }
private async void btnStart_Click(object sender, EventArgs e) { try { if (btnStart.Text == StopCaption) { await CancelActions(); btnStart.Text = StartCaption; return; } if (serviceBusHelper != null && ValidateParameters()) { if (startLog != null) { startLog(); } btnStart.Enabled = false; Cursor.Current = Cursors.WaitCursor; //***************************************************************************************************** // Initialize Statistics and Manager Action //***************************************************************************************************** actionCount = 0; senderMessageNumber = 0; senderMessagesPerSecond = 0; senderMinimumTime = long.MaxValue; senderMaximumTime = 0; senderAverageTime = 0; senderTotalTime = 0; lblSenderLastTime.Text = string.Empty; lblSenderAverageTime.Text = string.Empty; lblSenderMaximumTime.Text = string.Empty; lblSenderMinimumTime.Text = string.Empty; lblSenderMessagesPerSecond.Text = string.Empty; lblSenderMessageNumber.Text = string.Empty; if (checkBoxSenderEnableGraph.Checked) { chart.Series.ToList().ForEach(s => s.Points.Clear()); } managerResetEvent = new ManualResetEventSlim(false); Action<CancellationTokenSource> managerAction = cts => { if (cts == null) { return; } try { managerResetEvent.Wait(cts.Token); } catch (OperationCanceledException) { } if (!cts.IsCancellationRequested) { Invoke((MethodInvoker) delegate { btnStart.Text = StartCaption; }); } }; Action updateGraphAction = () => { var ok = true; long max = 10; while (!graphCancellationTokenSource.IsCancellationRequested && (actionCount > 1 || ok)) { ok = true; long sendMessageNumber = 0; long sendTotalTime = 0; while (ok && sendMessageNumber < max) { Tuple<long, long, DirectionType> tuple; ok = blockingCollection.TryTake(out tuple, 10); if (ok) { sendMessageNumber += tuple.Item1; sendTotalTime += tuple.Item2; if (sendMessageNumber > max) { max = sendMessageNumber; } } } if (sendMessageNumber > 0) { var sendTuple = new Tuple<long, long, DirectionType>(sendMessageNumber, sendTotalTime, DirectionType.Send); if (InvokeRequired) { Invoke(new UpdateStatisticsDelegate(InternalUpdateStatistics), new object[] { sendTuple.Item1, sendTuple.Item2, sendTuple.Item3 }); } else { InternalUpdateStatistics(sendTuple.Item1, sendTuple.Item2, sendTuple.Item3); } } } if (Interlocked.Decrement(ref actionCount) == 0) { managerResetEvent.Set(); } }; AsyncCallback updateGraphCallback = a => { var action = a.AsyncState as Action; if (action != null) { action.EndInvoke(a); if (Interlocked.Decrement(ref actionCount) == 0) { managerResetEvent.Set(); } } }; blockingCollection = new BlockingCollection<Tuple<long, long, DirectionType>>(); //***************************************************************************************************** // Sending messages to a EventHub //***************************************************************************************************** if (eventDataCount > 0) { // Create event hub clients. They are cached for later usage to improve performance. if (isSenderFaulted || eventHubClientCollection == null || eventHubClientCollection.Count == 0 || eventHubClientCollection.Count < senderTaskCount) { eventHubClientCollection = new List<EventHubClient>(senderTaskCount); var amqpConnectionString = GetAmqpConnectionString(serviceBusHelper.ConnectionString); for (var i = 0; i < senderTaskCount; i++) { eventHubClientCollection.Add(EventHubClient.CreateFromConnectionString(amqpConnectionString, eventHubDescription.Path)); } isSenderFaulted = false; } // Create outbound message template list var eventDataTemplateList = new List<EventData>(); var updatePartitionKey = checkBoxUpdatePartitionKey.Checked; var noPartitionKey = checkBoxNoPartitionKey.Checked; if (messageTabControl.SelectedIndex == MessageTabPage) { eventDataTemplateList.Add(serviceBusHelper.CreateEventDataTemplate(txtMessageText.Text, GetPartitionKey(), bindingSource.Cast<MessagePropertyInfo>())); } else if (messageTabControl.SelectedIndex == FilesTabPage) { updatePartitionKey = !radioButtonJsonTemplate.Checked && !radioButtonXmlTemplate.Checked && checkBoxUpdatePartitionKey.Checked; var fileList = messageFileListView.Items.Cast<ListViewItem>() .Where(i => i.Checked) .Select(i => i.Text) .ToList(); if (fileList.Count == 0) { writeToLog(NoMessageSelected); return; } foreach (var fileName in fileList) { try { using (var streamReader = new StreamReader(fileName)) { var text = streamReader.ReadToEnd(); EventData template; if (radioButtonBinaryFile.Checked) { using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { using (var binaryReader = new BinaryReader(fileStream)) { var bytes = binaryReader.ReadBytes((int) fileStream.Length); template = serviceBusHelper.CreateEventDataTemplate(new MemoryStream(bytes), GetPartitionKey(), bindingSource.Cast<MessagePropertyInfo>()); } } } else { if (radioButtonTextFile.Checked) { template = serviceBusHelper.CreateEventDataTemplate(text, GetPartitionKey(), bindingSource.Cast<MessagePropertyInfo>()); } else if (radioButtonJsonTemplate.Checked) { try { var eventDataTemplate = JsonSerializerHelper.Deserialize<EventDataTemplate>(text); template = serviceBusHelper.CreateEventDataTemplate(eventDataTemplate); } catch (Exception) { writeToLog(string.Format(InvalidJsonTemplate, fileName)); template = serviceBusHelper.CreateEventDataTemplate(text, GetPartitionKey(), bindingSource.Cast<MessagePropertyInfo>()); } } else // XML Template { try { var eventDataTemplate = XmlSerializerHelper.Deserialize<EventDataTemplate>(text); template = serviceBusHelper.CreateEventDataTemplate(eventDataTemplate); } catch (Exception) { writeToLog(string.Format(InvalidXmlTemplate, fileName)); template = serviceBusHelper.CreateEventDataTemplate(text, GetPartitionKey(), bindingSource.Cast<MessagePropertyInfo>()); } } } if (template != null) { eventDataTemplateList.Add(template); } } } catch (Exception ex) { HandleException(ex); } } } else // Event Data Generator Tab { try { senderEventDataGenerator = eventDataGeneratorPropertyGrid.SelectedObject as IEventDataGenerator; if (senderEventDataGenerator != null) { eventDataTemplateList = new List<EventData>(senderEventDataGenerator.GenerateEventDataCollection(txtMessageCount.IntegerValue, writeToLog)); } } catch (Exception ex) { HandleException(ex); } } try { senderCancellationTokenSource = new CancellationTokenSource(); currentIndex = 0; senderEventDataInspector = cboSenderInspector.SelectedIndex > 0 ? Activator.CreateInstance(serviceBusHelper.EventDataInspectors[cboSenderInspector.Text]) as IEventDataInspector : null; Func<long> getMessageNumber = () => { lock (this) { return currentIndex++; } }; Action<int, IEnumerable<EventData>> senderAction = (taskId, messageTemplateEnumerable) => { try { var traceMessage = serviceBusHelper.SendEventData(eventHubClientCollection[taskId], messageTemplateEnumerable, getMessageNumber, eventDataCount, taskId, updatePartitionKey, noPartitionKey, checkBoxAddMessageNumber.Checked, checkBoxEnableSenderLogging.Checked, checkBoxSenderVerboseLogging.Checked, checkBoxSenderEnableStatistics.Checked, checkBoxSendBatch.Checked, senderBatchSize, checkBoxSenderThinkTime.Checked, senderThinkTime, senderEventDataInspector, UpdateStatistics, senderCancellationTokenSource, partitionDescription != null ? partitionDescription.PartitionId : null).Result; if (!string.IsNullOrWhiteSpace(traceMessage)) { writeToLog(traceMessage.Substring(0, traceMessage.Length - 1)); } } catch (Exception ex) { isSenderFaulted = true; HandleException(ex); } }; // Define Sender AsyncCallback AsyncCallback senderCallback = a => { var action = a.AsyncState as Action<int, IEnumerable<EventData>>; if (action != null) { action.EndInvoke(a); if (Interlocked.Decrement(ref actionCount) == 0) { managerResetEvent.Set(); } } }; // Start Sender Actions for (var i = 0; i < Math.Min(eventDataCount, senderTaskCount); i++) { senderAction.BeginInvoke(i, eventDataTemplateList, senderCallback, senderAction); Interlocked.Increment(ref actionCount); } } catch (Exception ex) { HandleException(ex); } } if (actionCount > 0) { managerCancellationTokenSource = new CancellationTokenSource(); managerAction.BeginInvoke(managerCancellationTokenSource, null, null); graphCancellationTokenSource = new CancellationTokenSource(); updateGraphAction.BeginInvoke(updateGraphCallback, updateGraphAction); Interlocked.Increment(ref actionCount); btnStart.Text = StopCaption; } } } catch (Exception ex) { HandleException(ex); } finally { btnStart.Enabled = true; Cursor.Current = Cursors.Default; } }
private void btnStart_Click(object sender, EventArgs e) { if (string.Compare(btnStart.Text, Start, StringComparison.OrdinalIgnoreCase) == 0) { receiverEventDataInspector = cboReceiverInspector.SelectedIndex > 0 ? Activator.CreateInstance(serviceBusHelper.EventDataInspectors[cboReceiverInspector.Text]) as IEventDataInspector : null; cancellationTokenSource = new CancellationTokenSource(); btnStart.Text = Stop; blockingCollection = new BlockingCollection<Tuple<long, long, long>>(); timer = new System.Timers.Timer { AutoReset = true, Enabled = true, Interval = 1000 * txtRefreshInformation.IntegerValue }; timer.Elapsed += timer_Elapsed; logging = checkBoxLogging.Checked; verbose = checkBoxVerbose.Checked; tracking = checkBoxTrackMessages.Checked; graph = checkBoxGraph.Checked; try { foreach (var partitionDescription in partitionDescriptions) { var description = partitionDescription; Task.Run(async () => { try { var eventHubClient = EventHubClient.CreateFromConnectionString(GetAmqpConnectionString(serviceBusHelper.ConnectionString), consumerGroupDescription.EventHubPath); var consumerGroup = string.Compare(consumerGroupDescription.Name, DefaultConsumerGroupName, StringComparison.InvariantCultureIgnoreCase) == 0 ? eventHubClient.GetDefaultConsumerGroup() : eventHubClient.GetConsumerGroup(consumerGroupDescription.Name); var epoch = txtEpoch.IntegerValue; var eventHubReceiver = epoch == 0 ? await consumerGroup.CreateReceiverAsync(description.PartitionId, txtOffset.Text, checkBoxOffsetInclusive.Checked) : await consumerGroup.CreateReceiverAsync(description.PartitionId, txtOffset.Text, checkBoxOffsetInclusive.Checked, epoch); eventHubReceiver.PrefetchCount = txtPrefetchCount.IntegerValue; var received = 0; EventData previousEventData = null; while (!cancellationTokenSource.Token.IsCancellationRequested) { var stopwatch = Stopwatch.StartNew(); var eventData = await eventHubReceiver.ReceiveAsync(TimeSpan.FromSeconds(txtReceiveTimeout.IntegerValue)); stopwatch.Stop(); if (eventData == null) { if (previousEventData != null && checkpoint) { checkpointMethodInfo.Invoke(eventHubReceiver, new object[] { previousEventData }); previousEventData = null; if (logging) { writeToLog(string.Format(CheckPointExecuted, description.PartitionId)); } } continue; } previousEventData = eventData; if (receiverEventDataInspector != null) { eventData = receiverEventDataInspector.AfterReceiveMessage(eventData); } received++; if (logging) { var builder = new StringBuilder(string.Format(EventDataSuccessfullyReceived, string.IsNullOrWhiteSpace(eventData.PartitionKey) ? NullValue : eventData.PartitionKey, eventData.Offset, eventData.EnqueuedTimeUtc)); if (verbose) { serviceBusHelper.GetMessageAndProperties(builder, eventData); } writeToLog(builder.ToString()); } if (tracking) { eventDataCollection.Add(eventData); } if (graph) { var bodySize = (long)0; var bodyStream = eventData.GetBodyStream(); if (bodyStream != null && bodyStream.CanSeek) { bodySize = bodyStream.Length; } UpdateStatistics(1, stopwatch.ElapsedMilliseconds, bodySize); } if (received == checkpointCount && checkpoint) { checkpointMethodInfo.Invoke(eventHubReceiver, new object[] { eventData }); received = 0; if (logging) { writeToLog(string.Format(CheckPointExecuted, description.PartitionId)); } } } } catch (TimeoutException) { } catch (Exception ex) { HandleException(ex); } }); } #pragma warning disable 4014 Task.Run(new Action(RefreshGraph)); #pragma warning restore 4014 } catch (Exception ex) { HandleException(ex); StopListener(); btnStart.Text = Start; } } else { try { StopListener(); btnStart.Text = Start; } catch (Exception ex) { HandleException(ex); } } }