public async Task ProcessEventsAsync(IEnumerable <EventData> events) { Logger.LogInformation("Processing events from event hub."); if (events != null) { foreach (EventData eventData in events) { eventData.Properties.TryGetValue(TestConstants.Message.TrackingIdPropertyName, out object trackingIdFromEvent); eventData.SystemProperties.TryGetValue(DeviceIdPropertyName, out object deviceIdFromEvent); eventData.SystemProperties.TryGetValue(ModuleIdPropertyName, out object moduleIdFromEvent); Logger.LogDebug($"Received event from Event Hub: trackingId={(string)trackingIdFromEvent}, deviceId={(string)deviceIdFromEvent}, moduleId={(string)moduleIdFromEvent}"); if (!string.IsNullOrWhiteSpace((string)trackingIdFromEvent) && string.Equals(trackingIdFromEvent.ToString(), this.trackingId, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace((string)deviceIdFromEvent) && string.Equals(deviceIdFromEvent.ToString(), this.deviceId, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace((string)moduleIdFromEvent)) { eventData.Properties.TryGetValue(TestConstants.Message.SequenceNumberPropertyName, out object sequenceNumberFromEvent); eventData.Properties.TryGetValue(TestConstants.Message.BatchIdPropertyName, out object batchIdFromEvent); Logger.LogDebug($"Received event from Event Hub: batchId={(string)batchIdFromEvent}, sequenceNumber={(string)sequenceNumberFromEvent}"); if (!string.IsNullOrWhiteSpace((string)sequenceNumberFromEvent) && !string.IsNullOrWhiteSpace((string)batchIdFromEvent)) { if (long.TryParse(sequenceNumberFromEvent.ToString(), out long sequenceNumber)) { DateTime enqueuedtime = GetEnqueuedTime(deviceIdFromEvent.ToString(), moduleIdFromEvent.ToString(), eventData); // TODO: remove hardcoded eventHub string in next line var result = new TestOperationResult( (string)moduleIdFromEvent + ".eventHub", TestOperationResultType.Messages.ToString(), ModuleUtil.FormatMessagesTestResultValue( (string)trackingIdFromEvent, (string)batchIdFromEvent, (string)sequenceNumberFromEvent), enqueuedtime); await this.storage.AddResultAsync(result); Logger.LogInformation($"Received event from Event Hub persisted to store: trackingId={(string)trackingIdFromEvent}, deviceId={(string)deviceIdFromEvent}, moduleId={(string)moduleIdFromEvent}, batchId={(string)batchIdFromEvent}, sequenceNumber={(string)sequenceNumberFromEvent}"); } else { Logger.LogError($"Message for module [{moduleIdFromEvent}] and device [{this.deviceId}] contains invalid sequence number [{(string)sequenceNumberFromEvent}]."); } } else { Logger.LogDebug($"Message for module [{moduleIdFromEvent}] and device [{this.deviceId}] doesn't contain batch id and/or sequence number."); } } } } }
static async Task Main() { Logger.LogInformation($"Starting load gen with the following settings:\r\n{Settings.Current}"); ModuleClient moduleClient = null; try { (CancellationTokenSource cts, ManualResetEventSlim completed, Option <object> handler) = ShutdownHandler.Init(TimeSpan.FromSeconds(5), Logger); Guid batchId = Guid.NewGuid(); Logger.LogInformation($"Batch Id={batchId}"); moduleClient = await ModuleUtil.CreateModuleClientAsync( Settings.Current.TransportType, ModuleUtil.DefaultTimeoutErrorDetectionStrategy, ModuleUtil.DefaultTransientRetryStrategy, Logger); Logger.LogInformation($"Load gen delay start for {Settings.Current.TestStartDelay}."); await Task.Delay(Settings.Current.TestStartDelay); DateTime testStartAt = DateTime.UtcNow; long messageIdCounter = 1; while (!cts.IsCancellationRequested && (Settings.Current.TestDuration == TimeSpan.Zero || DateTime.UtcNow - testStartAt < Settings.Current.TestDuration)) { try { await SendEventAsync(moduleClient, batchId, Settings.Current.TrackingId, messageIdCounter); // Report sending message successfully to Test Result Coordinator await Settings.Current.TestResultCoordinatorUrl.ForEachAsync( async trcUrl => { Uri testResultCoordinatorUrl = new Uri( trcUrl, UriKind.Absolute); TestResultCoordinatorClient trcClient = new TestResultCoordinatorClient { BaseUrl = testResultCoordinatorUrl.AbsoluteUri }; await ModuleUtil.ReportStatus( trcClient, Logger, Settings.Current.ModuleId + ".send", ModuleUtil.FormatMessagesTestResultValue( Settings.Current.TrackingId, batchId.ToString(), messageIdCounter.ToString()), TestOperationResultType.Messages.ToString()); }); if (messageIdCounter % 1000 == 0) { Logger.LogInformation($"Sent {messageIdCounter} messages."); } await Task.Delay(Settings.Current.MessageFrequency); messageIdCounter++; } catch (Exception ex) { Logger.LogError(ex, $"[SendEventAsync] Sequence number {messageIdCounter}, BatchId: {batchId.ToString()};"); } } Logger.LogInformation("Finish sending messages."); await cts.Token.WhenCanceled(); completed.Set(); handler.ForEach(h => GC.KeepAlive(h)); } catch (Exception ex) { Logger.LogError(ex, "Error occurred during load gen."); } finally { Logger.LogInformation("Closing connection to Edge Hub."); moduleClient?.CloseAsync(); moduleClient?.Dispose(); } Logger.LogInformation("Load Gen complete. Exiting."); }
static async Task <MessageResponse> ProcessAndSendMessageAsync(Message message, object userContext) { Uri testResultCoordinatorUrl = Settings.Current.TestResultCoordinatorUrl; try { if (!(userContext is ModuleClient moduleClient)) { throw new InvalidOperationException("UserContext doesn't contain expected value"); } // Must make a new message instead of reusing the old message because of the way the SDK sends messages string trackingId = string.Empty; string batchId = string.Empty; string sequenceNumber = string.Empty; var messageProperties = new List <KeyValuePair <string, string> >(); foreach (KeyValuePair <string, string> prop in message.Properties) { switch (prop.Key) { case TestConstants.Message.TrackingIdPropertyName: trackingId = prop.Value ?? string.Empty; break; case TestConstants.Message.BatchIdPropertyName: batchId = prop.Value ?? string.Empty; break; case TestConstants.Message.SequenceNumberPropertyName: sequenceNumber = prop.Value ?? string.Empty; break; } messageProperties.Add(new KeyValuePair <string, string>(prop.Key, prop.Value)); } if (string.IsNullOrWhiteSpace(trackingId) || string.IsNullOrWhiteSpace(batchId) || string.IsNullOrWhiteSpace(sequenceNumber)) { Logger.LogWarning($"Received message missing info: trackingid={trackingId}, batchId={batchId}, sequenceNumber={sequenceNumber}"); return(MessageResponse.Completed); } // Report receiving message successfully to Test Result Coordinator TestResultCoordinatorClient trcClient = new TestResultCoordinatorClient { BaseUrl = testResultCoordinatorUrl.AbsoluteUri }; await ModuleUtil.ReportStatus( trcClient, Logger, Settings.Current.ModuleId + ".receive", ModuleUtil.FormatMessagesTestResultValue(trackingId, batchId, sequenceNumber), TestOperationResultType.Messages.ToString()); Logger.LogInformation($"Successfully received message: trackingid={trackingId}, batchId={batchId}, sequenceNumber={sequenceNumber}"); byte[] messageBytes = message.GetBytes(); var messageCopy = new Message(messageBytes); messageProperties.ForEach(kvp => messageCopy.Properties.Add(kvp)); await moduleClient.SendEventAsync(Settings.Current.OutputName, messageCopy); // Report sending message successfully to Test Result Coordinator await ModuleUtil.ReportStatus( trcClient, Logger, Settings.Current.ModuleId + ".send", ModuleUtil.FormatMessagesTestResultValue(trackingId, batchId, sequenceNumber), TestOperationResultType.Messages.ToString()); Logger.LogInformation($"Successfully sent message: trackingid={trackingId}, batchId={batchId}, sequenceNumber={sequenceNumber}"); } catch (Exception ex) { Logger.LogError(ex, "Error in ProcessAndSendMessageAsync"); } return(MessageResponse.Completed); }