public async Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages) { var batch = new TableBatchOperation(); foreach(var msg in messages) { var snap = JsonConvert.DeserializeObject<BusSnapshotInfo>(Encoding.UTF8.GetString(msg.GetBytes())); var entity = new DynamicTableEntity(snap.RouteShortName, snap.VehicleId.ToString()); entity.Properties.Add("RouteShortName", EntityProperty.GeneratePropertyForString(snap.RouteShortName)); entity.Properties.Add("VehicleId", EntityProperty.GeneratePropertyForInt(snap.VehicleId)); entity.Properties.Add("TripId", EntityProperty.GeneratePropertyForInt(snap.TripId)); entity.Properties.Add("Latitude", EntityProperty.GeneratePropertyForDouble(snap.Latitude)); entity.Properties.Add("Longitude", EntityProperty.GeneratePropertyForDouble(snap.Longitude)); entity.Properties.Add("DirectionOfTravel", EntityProperty.GeneratePropertyForString(snap.DirectionOfTravel.ToString())); entity.Properties.Add("NextStopId", EntityProperty.GeneratePropertyForInt(snap.NextStopId)); entity.Properties.Add("Timeliness", EntityProperty.GeneratePropertyForString(snap.Timeliness.ToString())); entity.Properties.Add("TimelinessOffset", EntityProperty.GeneratePropertyForInt(snap.TimelinessOffset)); entity.Properties.Add("Timestamp", EntityProperty.GeneratePropertyForDateTimeOffset(snap.Timestamp)); batch.Add(TableOperation.InsertOrReplace(entity)); } var tableClient = _account.CreateCloudTableClient(); var table = tableClient.GetTableReference("snapshots"); await table.CreateIfNotExistsAsync(); await table.ExecuteBatchAsync(batch); await context.CheckpointAsync(); }
async Task IEventProcessor.ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages) { foreach (EventData eventData in messages) { _Logger.LogInfo(string.Format("Event received from partition: {0} - {1}", context.Lease.PartitionId,eventData.PartitionKey)); try { var httpMessage = HttpMessage.Parse(eventData.GetBodyStream()); await _MessageContentProcessor.ProcessHttpMessage(httpMessage); } catch (Exception ex) { _Logger.LogError(ex.Message); } } //Call checkpoint every 5 minutes, so that worker can resume processing from the 5 minutes back if it restarts. if (this.checkpointStopWatch.Elapsed > TimeSpan.FromMinutes(5)) { _Logger.LogInfo("Checkpointing"); await context.CheckpointAsync(); this.checkpointStopWatch.Restart(); } }
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages) { foreach (EventData eventData in messages) { if (eventData.Properties.ContainsKey("time")) { if (eventData.Properties.ContainsKey("temp")) Console.WriteLine(string.Format("time = {0}, temp = {1}", eventData.Properties["time"], eventData.Properties["temp"])); if (eventData.Properties.ContainsKey("hmdt")) Console.WriteLine(string.Format("time = {0}, hmdt = {1}", eventData.Properties["time"], eventData.Properties["hmdt"])); if (eventData.Properties.ContainsKey("accx") && eventData.Properties.ContainsKey("accy") && eventData.Properties.ContainsKey("accz")) Console.WriteLine(string.Format("time = {0}, accx = {1}, accy = {2}, accz = {3}", eventData.Properties["time"], eventData.Properties["accx"], eventData.Properties["accy"], eventData.Properties["accz"])); if (eventData.Properties.ContainsKey("bpm")) Console.WriteLine(string.Format("time = {0}, bpm = {1}", eventData.Properties["time"], eventData.Properties["bpm"])); } } //Call checkpoint every 5 minutes, so that worker can resume processing from the 5 minutes back if it restarts. //if (this.checkpointStopWatch.Elapsed > TimeSpan.FromMinutes(5)) if (this.checkpointStopWatch.Elapsed > TimeSpan.FromSeconds(30)) { await context.CheckpointAsync(); this.checkpointStopWatch.Restart(); } }
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages) { Trace.TraceInformation("\n"); Trace.TraceInformation("........ProcessEventsAsync........"); foreach (EventData eventData in messages) { try { string jsonString = Encoding.UTF8.GetString(eventData.GetBytes()); Trace.TraceInformation(string.Format("Message received at '{0}'. Partition: '{1}'", eventData.EnqueuedTimeUtc.ToLocalTime(), this.partitionContext.Lease.PartitionId)); Trace.TraceInformation(string.Format("-->Raw Data: '{0}'", jsonString)); SensorEvent newSensorEvent = this.DeserializeEventData(jsonString); Trace.TraceInformation(string.Format("-->Serialized Data: '{0}', '{1}', '{2}', '{3}', '{4}'", newSensorEvent.timestart, newSensorEvent.dsplalert, newSensorEvent.alerttype, newSensorEvent.message, newSensorEvent.targetalarmdevice)); // Issuing alarm to device. string commandParameterNew = "{\"Name\":\"AlarmThreshold\",\"Parameters\":{\"SensorId\":\"" + newSensorEvent.dsplalert + "\"}}"; Trace.TraceInformation("Issuing alarm to device: '{0}', from sensor: '{1}'", newSensorEvent.targetalarmdevice, newSensorEvent.dsplalert); Trace.TraceInformation("New Command Parameter: '{0}'", commandParameterNew); await WorkerRole.iotHubServiceClient.SendAsync(newSensorEvent.targetalarmdevice, new Microsoft.Azure.Devices.Message(Encoding.UTF8.GetBytes(commandParameterNew))); } catch (Exception ex) { Trace.TraceInformation("Error in ProssEventsAsync -- {0}\n", ex.Message); } } await context.CheckpointAsync(); }
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> events) { try { Notifications notifications = new Notifications(); foreach (EventData eventData in events) { var dataString = Encoding.UTF8.GetString(eventData.GetBytes()); var newData = JsonConvert.DeserializeObject<MetricEvent>(dataString); EventMessage message = GetMessage(newData.Type, dataString); if (message == null) message = newData.GetMessage(); notifications.Notify(message); Console.WriteLine(string.Format("Message received.Partition:'{0}',{1},Device:'{2}'", this.partitionContext.Lease.PartitionId, newData.Type, newData.DeviceId)); } //Call checkpoint every 5 minutes, so that worker can resume processing from the 5 minutes back if it restarts. if (this.checkpointStopWatch.Elapsed > TimeSpan.FromMinutes(5)) { await context.CheckpointAsync(); this.checkpointStopWatch.Restart(); } } catch (Exception exp) { Console.WriteLine("Error in processing: " + exp.Message); } }
public async Task CloseAsync(PartitionContext context, CloseReason reason) { if (reason == CloseReason.Shutdown) { await context.CheckpointAsync(); } }
async Task IEventProcessor.ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages) { var iDbService = new DbService(); _client = iDbService.GetFirebaseClient(); foreach (EventData eventData in messages) { string data = Encoding.UTF8.GetString(eventData.GetBytes()); FirebaseResponse response = await _client.PushAsync("event", new EHdata { offset = eventData.Offset, body = data, partitionId = context.Lease.PartitionId }); Console.WriteLine(String.Format("Message received. Partition: '{0}', Data: '{1}', Offset: '{2}'", context.Lease.PartitionId, data, eventData.Offset)); } //Call checkpoint every 5 minutes, so that worker can resume processing from the 5 minutes back if it restarts. if (this.checkpointStopWatch.Elapsed > TimeSpan.FromMinutes(5)) { Console.WriteLine(this.checkpointStopWatch.Elapsed); await context.CheckpointAsync(); this.checkpointStopWatch.Restart(); } }
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> events) { // Workaround for event hub sending null on timeout events = events ?? Enumerable.Empty<EventData>(); foreach (var eventData in events) { var updateTemperatureEvent = JsonConvert.DeserializeObject<UpdateTemperatureEvent>(Encoding.UTF8.GetString(eventData.GetBytes())); eventData.Properties["BuildingId"] = _buildingLookupService.GetBuildingId(updateTemperatureEvent.DeviceId); } if(!await _elasticSearchWriter.WriteAsync(events.ToList(), _token).ConfigureAwait(false)) { return; } try { EventData checkpointEventData = events.LastOrDefault(); await context.CheckpointAsync(checkpointEventData); WarmStorageEventSource.Log.CheckpointCompleted(ProcessorName, _eventHubName, context.Lease.PartitionId, checkpointEventData.Offset); } catch (Exception ex) { if (!(ex is StorageException || ex is LeaseLostException)) { throw; } WarmStorageEventSource.Log.UnableToCheckpoint(ex, ProcessorName, _eventHubName, context.Lease.PartitionId); } }
async Task IEventProcessor.ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages) { var partitionedMessages = messages.GroupBy(data => data.PartitionKey).ToDictionary(datas => datas.Key, datas => datas.ToList()); //For each partition spawn a Task which will sequentially iterate over its own block //Wait for all Tasks to complete, before proceeding. await Task.WhenAll(partitionedMessages.Select(partition => Task.Run(async () => { var block = partition.Value; foreach (var eventData in block) { try { var data = Encoding.UTF8.GetString(eventData.GetBytes()); System.Console.WriteLine(DateTime.Now + ":Message received. Partition: '{0}', Data: '{1}', Partition Key: '{2}'", context.Lease.PartitionId, data, eventData.PartitionKey); } catch (Exception e) { //do something with your logs.. } } }))); //Call checkpoint every 5 minutes, so that worker can resume processing from the 5 minutes back if it restarts. if (checkpointStopWatch.Elapsed > TimeSpan.FromMinutes(5)) { await context.CheckpointAsync(); checkpointStopWatch.Restart(); } }
async Task IEventProcessor.CloseAsync(PartitionContext context, CloseReason reason) { if (reason == CloseReason.Shutdown) { await context.CheckpointAsync(); } }
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> events) { // Workaround for event hub sending null on timeout events = events ?? Enumerable.Empty<EventData>(); if(!await _elasticSearchWriter.WriteAsync(events.ToList(), _token).ConfigureAwait(false)) { return; } try { EventData checkpointEventData = events.LastOrDefault(); await context.CheckpointAsync(checkpointEventData); WarmStorageEventSource.Log.CheckpointCompleted(ProcessorName, _eventHubName, context.Lease.PartitionId, checkpointEventData.Offset); } catch (Exception ex) { if (!(ex is StorageException || ex is LeaseLostException)) { throw; } WarmStorageEventSource.Log.UnableToCheckpoint(ex, ProcessorName, _eventHubName, context.Lease.PartitionId); } }
public Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages) { try { foreach (EventData message in messages) { string contents = Encoding.UTF8.GetString(message.GetBytes()); Console.WriteLine(string.Format("SimpleEventProcessor: {0}", contents)); OnMessageReceived(this, new MessageReceivedEventArgs() { ReceivedOn = DateTimeOffset.UtcNow, Message = message }); } if (this.checkpointStopWatch.Elapsed > TimeSpan.FromSeconds(2)) { lock (this) { this.checkpointStopWatch.Reset(); return context.CheckpointAsync(); } } } catch (Exception ex) { Console.WriteLine(ex); } return Task.FromResult<object>(null); }
async Task IEventProcessor.CloseAsync(PartitionContext context, CloseReason reason) { Console.WriteLine("Processor Shutting Down. Partition '{0}', Reason: '{1}'.", context.Lease.PartitionId, reason); if (reason == CloseReason.Shutdown) { await context.CheckpointAsync(); } }
public async Task CloseAsync(PartitionContext context, CloseReason reason) { Console.WriteLine(string.Format("Processor Shuting Down. Partition '{0}', Reason: '{1}'.", context.Lease.PartitionId, reason.ToString())); if (reason == CloseReason.Shutdown) { await context.CheckpointAsync(); } }
public async Task CloseAsync(PartitionContext context, CloseReason reason) { if (reason == CloseReason.Shutdown) { Clients.All.showMessageOnClient("XClose"); await context.CheckpointAsync(); } }
public Task CloseAsync(PartitionContext context, CloseReason reason) { if (reason == CloseReason.Shutdown) { return context.CheckpointAsync(); } return Task.FromResult(false); }
public async Task CloseAsync(PartitionContext context, CloseReason reason) { Console.WriteLine("Shutting Down Event Processor"); if (reason == CloseReason.Shutdown) { await context.CheckpointAsync(); } }
public async Task CloseAsync(PartitionContext context, CloseReason reason) { Trace.TraceInformation(string.Format("EventProcessor Shuting Down. Partition '{0}', Reason: '{1}'.", this.partitionContext.Lease.PartitionId, reason.ToString())); if (reason == CloseReason.Shutdown) { await context.CheckpointAsync(); } }
//------------------------------------------------------------------------------------------------------------------------ #endregion #region Functions //------------------------------------------------------------------------------------------------------------------------ async Task IEventProcessor.CloseAsync(PartitionContext context, CloseReason reason) { DebugEx.TraceLog("Processor Shutting Down. Partition :" + context.Lease.PartitionId + ", Reason: " + reason); if (reason == CloseReason.Shutdown) { await context.CheckpointAsync(); } }
public async Task CloseAsync(PartitionContext context, CloseReason reason) { Console.WriteLine($"Processor Shutting Down. Partition '{context.Lease.PartitionId}', Reason: '{reason}'."); if (reason == CloseReason.Shutdown) { await context.CheckpointAsync(); } }
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> events) { try { foreach (EventData eventData in events) { //string key = eventData.PartitionKey; // Get message from the eventData body and convert JSON string into message object string eventBodyAsString = Encoding.UTF8.GetString(eventData.GetBytes()); Console.WriteLine(); Console.WriteLine(eventBodyAsString); Console.WriteLine(); //IList<IDictionary<string, object>> messagePayloads; //try //{ // // Attempt to deserialze event body as single JSON message // messagePayloads = new List<IDictionary<string, object>> // { // JsonConvert.DeserializeObject<IDictionary<string, object>>(eventBodyAsString) // }; //} //catch //{ // // Not a single JSON message: attempt to deserialize as array of messages // // Azure Stream Analytics Preview generates invalid JSON for some multi-values queries // // Workaround: turn concatenated json objects (ivalid JSON) into array of json objects (valid JSON) // if (eventBodyAsString.IndexOf("}{") >= 0) // { // eventBodyAsString = eventBodyAsString.Replace("}{", "},{"); // eventBodyAsString = "[" + eventBodyAsString + "]"; // } // messagePayloads = JsonConvert.DeserializeObject<IList<IDictionary<string, object>>>(eventBodyAsString); //} } //Call checkpoint every 5 minutes, so that worker can resume processing from the 5 minutes back if it restarts. if (this.checkpointStopWatch.Elapsed > TimeSpan.FromMinutes(5)) { Console.WriteLine("Check point"); await context.CheckpointAsync(); lock (this) { this.checkpointStopWatch.Reset(); this.checkpointStopWatch.Start(); } } } catch (Exception exp) { Console.WriteLine("Error in processing: " + exp.Message); } }
public Task CloseAsync(PartitionContext context, CloseReason reason) { Trace.TraceInformation("Processor Shuting Down. Partition '{0}', Reason: '{1}'.", this.Context.Lease.PartitionId, reason.ToString()); this.IsClosed = true; this.OnProcessorClosed(); return context.CheckpointAsync(); }
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages) { // Todo: Improve performance by batching items foreach (EventData ev in messages) { await this.m_Handler.HandleEventData(this.m_ServiceBusNamespace, this.m_EventHubName, this.m_CounsumerGroupName, ev); await context.CheckpointAsync(); } }
public async Task CloseAsync(PartitionContext context, CloseReason reason) { if (sqlConnection != null) sqlConnection.Close(); if (!WebJobsHelper.RunAsWebJobs) Console.WriteLine(string.Format("Processor Shuting Down. Partition '{0}', Reason: '{1}'.", partitionContext.Lease.PartitionId, reason.ToString())); if (reason == CloseReason.Shutdown) await context.CheckpointAsync(); }
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> events) { foreach (var eventData in events) { dynamic data = JsonConvert.DeserializeObject(Encoding.Default.GetString(eventData.GetBytes())); // process data } await context.CheckpointAsync(); }
async Task IEventProcessor.CloseAsync(PartitionContext context, CloseReason reason) { _logger.EventProcessorStopped(reason.ToString(), context.EventHubPath, context.ConsumerGroupName, context.Lease.PartitionId, context.Lease.Offset, context.Lease.Epoch); if (reason == CloseReason.Shutdown) { await context.CheckpointAsync(); _logger.EventProcessorCheckpointed(context.EventHubPath, context.ConsumerGroupName, context.Lease.PartitionId, context.Lease.Offset, context.Lease.Epoch); } }
async Task IEventProcessor.ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages) { await Task.WhenAll(messages.Select(eventData => _processor(eventData))); //if (_lastCheckpointTime.Add(_checkpointTimeout) < DateTime.UtcNow) //{ await context.CheckpointAsync(); _logger.EventProcessorCheckpointed(context.EventHubPath, context.ConsumerGroupName, context.Lease.PartitionId, context.Lease.Offset, context.Lease.Epoch); // _lastCheckpointTime = DateTime.UtcNow; //} }
public Task CloseAsync(PartitionContext context, CloseReason reason) { WriteLog("{0} > Close called for processor with PartitionId '{1}' and Owner: {2} with reason '{3}'.", DateTime.Now.ToString(), context.Lease.PartitionId, context.Lease.Owner ?? string.Empty, reason); if (_checkpointingOn) { return context.CheckpointAsync(); } else { return Task.FromResult<object>(null); } }
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages) { foreach (var eventData in messages) { var packetData = Encoding.UTF8.GetString(eventData.GetBytes()); var packetContext = new PacketData(MakeUri(eventData), packetData); await _hostedMiddeMiddleware.Invoke(packetContext); } await context.CheckpointAsync(); }
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages) { foreach(var message in messages) { var importantMeasure = ImportantMeasure.FromByteArray(message.GetBytes()); // Do something with the measure here, like storing it in a table somewhere... Trace.WriteLine($"[Partition {context.Lease.PartitionId}] {DateTime.Now.ToString("HH:mm:ss")}: {importantMeasure.ImportantValue.ToString("0.00")}"); } await context.CheckpointAsync(); }
/// <summary> /// Receives a <see cref="EventData"/> from the event bus. /// </summary> protected virtual void ReceiveEvent(PartitionContext context, EventData eventData) { DateTimeOffset startedAt = DateTimeOffset.UtcNow; Stopwatch mainStopWatch = Stopwatch.StartNew(); string responseCode = "200"; // Null means it was skipped bool?wasSuccessfull = true; #if NET452 string telemetryName = string.Format("Cqrs/Handle/Event/{0}", eventData.SequenceNumber); #endif #if NETSTANDARD2_0 string telemetryName = string.Format("Cqrs/Handle/Event/{0}", eventData.SystemProperties.SequenceNumber); #endif ISingleSignOnToken authenticationToken = null; Guid? guidAuthenticationToken = null; string stringAuthenticationToken = null; int? intAuthenticationToken = null; IDictionary <string, string> telemetryProperties = new Dictionary <string, string> { { "Type", "Azure/EventHub" } }; object value; if (eventData.Properties.TryGetValue("Type", out value)) { telemetryProperties.Add("MessageType", value.ToString()); } TelemetryHelper.TrackMetric("Cqrs/Handle/Event", CurrentHandles++, telemetryProperties); // Do a manual 10 try attempt with back-off for (int i = 0; i < 10; i++) { try { #if NET452 Logger.LogDebug(string.Format("An event message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}'.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset)); #endif #if NETSTANDARD2_0 Logger.LogDebug(string.Format("An event message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}'.", eventData.SystemProperties.PartitionKey, eventData.SystemProperties.SequenceNumber, eventData.SystemProperties.Offset)); #endif #if NET452 string messageBody = Encoding.UTF8.GetString(eventData.GetBytes()); #endif #if NETSTANDARD2_0 string messageBody = Encoding.UTF8.GetString(eventData.Body.Array, eventData.Body.Offset, eventData.Body.Count); #endif IEvent <TAuthenticationToken> @event = AzureBusHelper.ReceiveEvent(null, messageBody, ReceiveEvent, #if NET452 string.Format("partition key '{0}', sequence number '{1}' and offset '{2}'", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset), #endif #if NETSTANDARD2_0 string.Format("partition key '{0}', sequence number '{1}' and offset '{2}'", eventData.SystemProperties.PartitionKey, eventData.SystemProperties.SequenceNumber, eventData.SystemProperties.Offset), #endif ExtractSignature(eventData), SigningTokenConfigurationKey, () => { wasSuccessfull = null; #if NET452 telemetryName = string.Format("Cqrs/Handle/Event/Skipped/{0}", eventData.SequenceNumber); #endif #if NETSTANDARD2_0 telemetryName = string.Format("Cqrs/Handle/Event/Skipped/{0}", eventData.SystemProperties.SequenceNumber); #endif responseCode = "204"; // Remove message from queue context.CheckpointAsync(eventData); #if NET452 Logger.LogDebug(string.Format("An event message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' but processing was skipped due to event settings.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset)); #endif #if NETSTANDARD2_0 Logger.LogDebug(string.Format("An event message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' but processing was skipped due to event settings.", eventData.SystemProperties.PartitionKey, eventData.SystemProperties.SequenceNumber, eventData.SystemProperties.Offset)); #endif TelemetryHelper.TrackEvent("Cqrs/Handle/Event/Skipped", telemetryProperties); } ); if (wasSuccessfull != null) { if (@event != null) { telemetryName = string.Format("{0}/{1}/{2}", @event.GetType().FullName, @event.GetIdentity(), @event.Id); authenticationToken = @event.AuthenticationToken as ISingleSignOnToken; if (AuthenticationTokenIsGuid) { guidAuthenticationToken = @event.AuthenticationToken as Guid?; } if (AuthenticationTokenIsString) { stringAuthenticationToken = @event.AuthenticationToken as string; } if (AuthenticationTokenIsInt) { intAuthenticationToken = @event.AuthenticationToken as int?; } var telemeteredMessage = @event as ITelemeteredMessage; if (telemeteredMessage != null) { telemetryName = telemeteredMessage.TelemetryName; } telemetryName = string.Format("Cqrs/Handle/Event/{0}", telemetryName); } // Remove message from queue context.CheckpointAsync(eventData); } #if NET452 Logger.LogDebug(string.Format("An event message arrived and was processed with the partition key '{0}', sequence number '{1}' and offset '{2}'.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset)); #endif #if NETSTANDARD2_0 Logger.LogDebug(string.Format("An event message arrived and was processed with the partition key '{0}', sequence number '{1}' and offset '{2}'.", eventData.SystemProperties.PartitionKey, eventData.SystemProperties.SequenceNumber, eventData.SystemProperties.Offset)); #endif IList <IEvent <TAuthenticationToken> > events; if (EventWaits.TryGetValue(@event.CorrelationId, out events)) { events.Add(@event); } wasSuccessfull = true; responseCode = "200"; return; } catch (UnAuthorisedMessageReceivedException exception) { TelemetryHelper.TrackException(exception, null, telemetryProperties); // Indicates a problem, unlock message in queue #if NET452 Logger.LogError(string.Format("An event message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' but was not authorised.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset), exception: exception); #endif #if NETSTANDARD2_0 Logger.LogError(string.Format("An event message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' but was not authorised.", eventData.SystemProperties.PartitionKey, eventData.SystemProperties.SequenceNumber, eventData.SystemProperties.Offset), exception: exception); #endif wasSuccessfull = false; responseCode = "401"; telemetryProperties.Add("ExceptionType", exception.GetType().FullName); telemetryProperties.Add("ExceptionMessage", exception.Message); } catch (NoHandlersRegisteredException exception) { TelemetryHelper.TrackException(exception, null, telemetryProperties); // Indicates a problem, unlock message in queue #if NET452 Logger.LogError(string.Format("An event message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' but no handlers were found to process it.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset), exception: exception); #endif #if NETSTANDARD2_0 Logger.LogError(string.Format("An event message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' but no handlers were found to process it.", eventData.SystemProperties.PartitionKey, eventData.SystemProperties.SequenceNumber, eventData.SystemProperties.Offset), exception: exception); #endif wasSuccessfull = false; responseCode = "501"; telemetryProperties.Add("ExceptionType", exception.GetType().FullName); telemetryProperties.Add("ExceptionMessage", exception.Message); } catch (NoHandlerRegisteredException exception) { TelemetryHelper.TrackException(exception, null, telemetryProperties); // Indicates a problem, unlock message in queue #if NET452 Logger.LogError(string.Format("An event message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}'s but no handler was found to process it.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset), exception: exception); #endif #if NETSTANDARD2_0 Logger.LogError(string.Format("An event message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}'s but no handler was found to process it.", eventData.SystemProperties.PartitionKey, eventData.SystemProperties.SequenceNumber, eventData.SystemProperties.Offset), exception: exception); #endif wasSuccessfull = false; responseCode = "501"; telemetryProperties.Add("ExceptionType", exception.GetType().FullName); telemetryProperties.Add("ExceptionMessage", exception.Message); } catch (Exception exception) { // Indicates a problem, unlock message in queue #if NET452 Logger.LogError(string.Format("An event message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' but failed to be process.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset), exception: exception); #endif #if NETSTANDARD2_0 Logger.LogError(string.Format("An event message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' but failed to be process.", eventData.SystemProperties.PartitionKey, eventData.SystemProperties.SequenceNumber, eventData.SystemProperties.Offset), exception: exception); #endif switch (i) { case 0: case 1: // 10 seconds Thread.Sleep(10 * 1000); break; case 2: case 3: // 30 seconds Thread.Sleep(30 * 1000); break; case 4: case 5: case 6: // 1 minute Thread.Sleep(60 * 1000); break; case 7: case 8: // 3 minutes Thread.Sleep(3 * 60 * 1000); break; case 9: telemetryProperties.Add("ExceptionType", exception.GetType().FullName); telemetryProperties.Add("ExceptionMessage", exception.Message); break; } wasSuccessfull = false; responseCode = "500"; } finally { // Eventually just accept it context.CheckpointAsync(eventData); TelemetryHelper.TrackMetric("Cqrs/Handle/Event", CurrentHandles--, telemetryProperties); mainStopWatch.Stop(); if (guidAuthenticationToken != null) { TelemetryHelper.TrackRequest ( telemetryName, guidAuthenticationToken, startedAt, mainStopWatch.Elapsed, responseCode, wasSuccessfull == null || wasSuccessfull.Value, telemetryProperties ); } else if (intAuthenticationToken != null) { TelemetryHelper.TrackRequest ( telemetryName, intAuthenticationToken, startedAt, mainStopWatch.Elapsed, responseCode, wasSuccessfull == null || wasSuccessfull.Value, telemetryProperties ); } else if (stringAuthenticationToken != null) { TelemetryHelper.TrackRequest ( telemetryName, stringAuthenticationToken, startedAt, mainStopWatch.Elapsed, responseCode, wasSuccessfull == null || wasSuccessfull.Value, telemetryProperties ); } else { TelemetryHelper.TrackRequest ( telemetryName, authenticationToken, startedAt, mainStopWatch.Elapsed, responseCode, wasSuccessfull == null || wasSuccessfull.Value, telemetryProperties ); } TelemetryHelper.Flush(); } } }
/// <inheritdoc/> public async Task ProcessEventsAsync(PartitionContext context, IEnumerable <EventData> messages) { if (messages == null || !messages.Any()) { return; } var messagesCount = 0; var messageSequence = 0L; foreach (var eventData in messages) { messagesCount++; if (_outer._config.SkipEventsOlderThan != null && eventData.SystemProperties.TryGetValue("x-opt-enqueued-time", out var enqueued) && (DateTime)enqueued + _outer._config.SkipEventsOlderThan < DateTime.UtcNow) { kOldEvent.WithLabels(_processorId, context.EventHubPath, context.ConsumerGroupName, context.PartitionId).Inc(); continue; } var properties = new EventProperties(eventData.SystemProperties, eventData.Properties); if (eventData.Body.Array == null) { _logger.Verbose("WARNING: Received empty message with properties {@properties}", properties); continue; } await _handler.HandleAsync(eventData.Body.Array, properties, () => CheckpointAsync(context, eventData)); if (context.CancellationToken.IsCancellationRequested) { // Checkpoint to the last processed event. await CheckpointAsync(context, eventData); context.CancellationToken.ThrowIfCancellationRequested(); } // sequence number of the message in eventhub which is used to calculate lag messageSequence = eventData.SystemProperties.SequenceNumber; } var lastEnqueuedSequence = context.RuntimeInformation.LastSequenceNumber; var sequenceDifference = lastEnqueuedSequence - messageSequence; TotalMessagesCount += messagesCount; kEventProcessorMessages.WithLabels(_processorId, context.EventHubPath, context.ConsumerGroupName, context.PartitionId).Set(TotalMessagesCount); kEventProcessorLag.WithLabels(_processorId, context.EventHubPath, context.ConsumerGroupName, context.PartitionId).Set(sequenceDifference); // Checkpoint if needed if (_sw.ElapsedMilliseconds >= _interval) { try { _logger.Debug("Checkpointing EventProcessor {id} for partition {partitionId}...", _processorId, context.PartitionId); await context.CheckpointAsync(); _sw.Restart(); } catch (Exception ex) { _logger.Warning(ex, "Failed checkpointing EventProcessor {id} for partition {partitionId}...", _processorId, context.PartitionId); kEventProcessorDetails.WithLabels(_processorId, context.EventHubPath, context.ConsumerGroupName, context.PartitionId, "checkpoint_failed").Inc(); if (_sw.ElapsedMilliseconds >= 2 * _interval) { // Give up checkpointing after trying a couple more times _sw.Restart(); } } } await Try.Async(_handler.OnBatchCompleteAsync); }
public async Task ProcessErrorAsync(PartitionContext context, Exception error) { await context.CheckpointAsync(); }
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable <EventData> events) { try { var now = DateTime.UtcNow; foreach (var eventData in events) { // Get message from the eventData body and convert JSON string into message object string eventBodyAsString = Encoding.UTF8.GetString(eventData.GetBytes()); IList <IDictionary <string, object> > messagePayloads; try { // Attempt to deserialze event body as single JSON message messagePayloads = new List <IDictionary <string, object> > { JsonConvert.DeserializeObject <IDictionary <string, object> >(eventBodyAsString) }; } catch { // Not a single JSON message: attempt to deserialize as array of messages // Azure Stream Analytics Preview generates invalid JSON for some multi-values queries // Workaround: turn concatenated json objects (ivalid JSON) into array of json objects (valid JSON) if (eventBodyAsString.IndexOf("}{") >= 0) { eventBodyAsString = eventBodyAsString.Replace("}{", "},{"); } if (!eventBodyAsString.EndsWith("]")) { eventBodyAsString = eventBodyAsString + "]"; } if (!eventBodyAsString.StartsWith("[")) { eventBodyAsString = "[" + eventBodyAsString; } messagePayloads = JsonConvert.DeserializeObject <IList <IDictionary <string, object> > >(eventBodyAsString); } // Only send messages within the display/buffer interval to clients, to speed up recovery after downtime if ((eventData.EnqueuedTimeUtc + bufferTimeInterval).AddMinutes(1) > now) { foreach (var messagePayload in messagePayloads) { // Build up the list of devices seen so far (in lieu of a formal device repository) // Also keep the last message received per device (not currently used in the sample) string deviceName = null; if (messagePayload.ContainsKey("dspl")) { deviceName = messagePayload["dspl"] as string; if (deviceName != null) { WebSocketEventProcessor.g_devices.TryAdd(deviceName, messagePayload); } } // Notify clients MyWebSocketHandler.SendToClients(messagePayload); // Buffer messages so we can resend them to clients that connect later // or when a client requests data for a different device // Lock to guard against concurrent reads from client resend // Note that the Add operations are not contentious with each other // because EH processor host serializes per partition, and we use one buffer per partition lock (bufferedMessages) { bufferedMessages.Add(messagePayload); if (messagePayload.ContainsKey("tempavg")) { bufferedMessagesAvg.Add(messagePayload); } } } } else { Debug.WriteLine("Received event older than {0} in EH {1}, partition {2}: {3} - Sequence Number {4}", bufferTimeInterval, context.EventHubPath, context.Lease.PartitionId, eventData.EnqueuedTimeUtc, eventData.SequenceNumber); eventForNextCheckpoint = eventData; } // Remember first event to checkpoint to later if (eventForNextCheckpoint == null) { eventForNextCheckpoint = eventData; } } // Checkpoint to an event before the buffer/display time period, so we can recover the events on VM restart if (eventForNextCheckpoint != null && eventForNextCheckpoint.EnqueuedTimeUtc + bufferTimeInterval < now && lastCheckPoint + maxCheckpointFrequency < now) // Don't checkpoint too often, as every checkpoint incurs at least one blob storage roundtrip { await context.CheckpointAsync(eventForNextCheckpoint); Trace.TraceInformation("Checkpointed EH {0}, partition {1}: offset {2}, Sequence Number {3}, time {4}", context.EventHubPath, context.Lease.PartitionId, eventForNextCheckpoint.Offset, eventForNextCheckpoint.SequenceNumber, eventForNextCheckpoint.EnqueuedTimeUtc); // Remove all older messages from the resend buffer lock (bufferedMessages) { if (this.indexOfLastCheckpoint >= 0) { bufferedMessages.RemoveRange(0, this.indexOfLastCheckpoint); } indexOfLastCheckpoint = bufferedMessages.Count - 1; } // Get ready for next checkpoint lastCheckPoint = now; eventForNextCheckpoint = events.Last <EventData>(); } } catch (Exception e) { Trace.TraceError("Error processing events in EH {0}, partition {1}: {0}", context.EventHubPath, context.Lease.PartitionId, e.Message); } }
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable <EventData> messages) { EventHubTriggerInput value = new EventHubTriggerInput { Events = messages.ToArray(), Context = context }; // Single dispatch if (_parent._singleDispatch) { int len = value.Events.Length; List <Task> dispatches = new List <Task>(); for (int i = 0; i < len; i++) { if (_cts.IsCancellationRequested) { // If we stopped the listener, then we may lose the lease and be unable to checkpoint. // So skip running the rest of the batch. The new listener will pick it up. continue; } else { TriggeredFunctionData input = new TriggeredFunctionData { ParentId = null, TriggerValue = value.GetSingleEventTriggerInput(i) }; Task task = this._parent._executor.TryExecuteAsync(input, _cts.Token); dispatches.Add(task); } } // Drain the whole batch before taking more work if (dispatches.Count > 0) { await Task.WhenAll(dispatches); } } else { // Batch dispatch TriggeredFunctionData input = new TriggeredFunctionData { ParentId = null, TriggerValue = value }; FunctionResult result = await this._parent._executor.TryExecuteAsync(input, CancellationToken.None); } // Dispose all messages to help with memory pressure. If this is missed, the finalizer thread will still get them. foreach (var message in messages) { message.Dispose(); } // There are lots of reasons this could fail. That just means that events will get double-processed, which is inevitable // with event hubs anyways. // For example, it could fail if we lost the lease. That could happen if we failed to renew it due to CPU starvation or an inability // to make the outbound network calls to renew. await context.CheckpointAsync(); }
protected virtual void ReceiveEvent(PartitionContext context, EventData eventData) { // Do a manual 10 try attempt with back-off for (int i = 0; i < 10; i++) { try { Logger.LogDebug(string.Format("An event message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}'.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset)); string messageBody = Encoding.UTF8.GetString(eventData.GetBytes()); IEvent <TAuthenticationToken> @event = AzureBusHelper.ReceiveEvent(messageBody, ReceiveEvent, string.Format("partition key '{0}', sequence number '{1}' and offset '{2}'", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset), () => { // Remove message from queue context.CheckpointAsync(eventData); Logger.LogDebug(string.Format("An event message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' but processing was skipped due to event settings.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset)); } ); // Remove message from queue context.CheckpointAsync(eventData); Logger.LogDebug(string.Format("An event message arrived and was processed with the partition key '{0}', sequence number '{1}' and offset '{2}'.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset)); IList <IEvent <TAuthenticationToken> > events; if (EventWaits.TryGetValue(@event.CorrelationId, out events)) { events.Add(@event); } return; } catch (Exception exception) { // Indicates a problem, unlock message in queue Logger.LogError(string.Format("An event message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' but failed to be process.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset), exception: exception); switch (i) { case 0: case 1: // 10 seconds Thread.Sleep(10 * 1000); break; case 2: case 3: // 30 seconds Thread.Sleep(30 * 1000); break; case 4: case 5: case 6: // 1 minute Thread.Sleep(60 * 1000); break; case 7: case 8: case 9: // 3 minutes Thread.Sleep(3 * 60 * 1000); break; } } } // Eventually just accept it context.CheckpointAsync(eventData); }
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable <EventData> events) { try { var now = DateTime.UtcNow; foreach (var eventData in events) { // We don't care about messages that are older than bufferTimeInterval if ((eventData.EnqueuedTimeUtc + bufferTimeInterval) >= now) { // Get message from the eventData body and convert JSON string into message object string eventBodyAsString = Encoding.UTF8.GetString(eventData.GetBytes()); // There can be several messages in one IList <IDictionary <string, object> > messagePayloads; try { // Attempt to deserialze event body as single JSON message messagePayloads = new List <IDictionary <string, object> > { JsonConvert.DeserializeObject <IDictionary <string, object> >(eventBodyAsString) }; } catch { // Not a single JSON message: attempt to deserialize as array of messages // Azure Stream Analytics Preview generates invalid JSON for some multi-values queries // Workaround: turn concatenated json objects (ivalid JSON) into array of json objects (valid JSON) if (eventBodyAsString.IndexOf("}{") >= 0) { eventBodyAsString = eventBodyAsString.Replace("}{", "},{"); } if (!eventBodyAsString.EndsWith("]")) { eventBodyAsString = eventBodyAsString + "]"; } if (!eventBodyAsString.StartsWith("[")) { eventBodyAsString = "[" + eventBodyAsString.Substring(eventBodyAsString.IndexOf("{")); } messagePayloads = JsonConvert.DeserializeObject <IList <IDictionary <string, object> > >(eventBodyAsString); } var rnd = new Random(); foreach (var messagePayload in messagePayloads) { // Read time value if (messagePayload.ContainsKey("timecreated")) { messagePayload["time"] = messagePayload["timecreated"]; } if (messagePayload.ContainsKey("timearrived")) { messagePayload["time"] = messagePayload["timearrived"]; } // process an alert if (messagePayload.ContainsKey("alerttype") && messagePayload.ContainsKey("timecreated")) { Debug.Print("Alert message received!"); DateTime time = DateTime.Parse(messagePayload["timecreated"].ToString()); // find the nearest point lock (sortedDataBuffer) { int idx = SearchHelper.FindFirstIndexGreaterThanOrEqualTo(sortedDataBuffer, time); bool found = false; string alertType = messagePayload["alerttype"] as string; if (idx >= sortedDataBuffer.Values.Count) { idx = sortedDataBuffer.Values.Count - 1; } while (idx >= 0) { List <IDictionary <string, object> > dictList = sortedDataBuffer.Values[idx]; foreach (IDictionary <string, object> dict in dictList) { if ( (dict.ContainsKey("guid") && messagePayload.ContainsKey("guid") && messagePayload["guid"].ToString() == dict["guid"].ToString()) && (dict.ContainsKey("measurename") && messagePayload.ContainsKey("measurename") && messagePayload["measurename"].ToString() == dict["measurename"].ToString()) && (!messagePayload.ContainsKey("displayname") || dict.ContainsKey("displayname") && messagePayload["measurename"].ToString() == dict["measurename"].ToString()) ) { // fill anomaly message if (!messagePayload.ContainsKey("value")) { messagePayload["value"] = dict["value"]; } if (!messagePayload.ContainsKey("displayname") && dict.ContainsKey("displayname")) { messagePayload["displayname"] = dict["displayname"]; } if (!messagePayload.ContainsKey("time")) { messagePayload["time"] = messagePayload["timecreated"]; } found = true; break; } } if (found) { break; } idx--; } } } if (messagePayload.ContainsKey("guid")) { var guid = messagePayload["guid"].ToString(); double val = Convert.ToDouble(messagePayload["value"]); if (!MinMaxValue.ContainsKey(guid)) { MinMaxValue.Add(guid, new MinMax { min = val, max = val }); } MinMax tmp = MinMaxValue[messagePayload["guid"].ToString()]; if (tmp.min > val) { tmp.min = val; } if (tmp.max < val) { tmp.max = val; } } // We want to read the time value from the message itself. // If none is found we will use the enqueued time DateTime messageTimeStamp = new DateTime(); if (messagePayload.ContainsKey("time")) { messageTimeStamp = DateTime.Parse(messagePayload["time"].ToString()); //data.Timestamp = messagePayload["time"].ToString(); //if (GenerateAnomalies && rnd.Next(100) >= 95) //{ // messagePayload.Add("alerttype", "testType"); // messagePayload.Add("dsplalert", "testAlert"); // messagePayload.Add("message", "Anomaly detected by Azure ML model."); // messagePayload.Add("timestart", messagePayload["time"]); // // correct value // if (rnd.Next(2) == 1) // messagePayload["value"] = MinMaxValue[messagePayload["guid"].ToString()].max * (1.01 + 0.05 * rnd.Next(100) / 100); // else // messagePayload["value"] = MinMaxValue[messagePayload["guid"].ToString()].min * (0.99 - 0.05 * rnd.Next(100) / 100); //} } else if (messagePayload.ContainsKey("timestart")) { messageTimeStamp = DateTime.Parse(messagePayload["timestart"].ToString()); } else { messageTimeStamp = eventData.EnqueuedTimeUtc; } // Build up the list of devices seen so far (in lieu of a formal device repository) // Also keep the last message received per device (not currently used in the sample) if (messagePayload.ContainsKey("guid") && !messagePayload.ContainsKey("valueAvg")) { string guid = messagePayload["guid"].ToString(); if (guid != null) { WebSocketEventProcessor.g_devices.TryAdd(guid, messagePayload); } } if (messagePayload["measurename"].ToString().ToLower().Equals("temperature")) { if (!String.IsNullOrEmpty(messagePayload["value"].ToString())) { CloudStorageAccount storageAccount = CloudStorageAccount.Parse("Storage Connection String"); // Create the table client. CloudTableClient tableClient = storageAccount.CreateCloudTableClient(); // Create the CloudTable object that represents the "people" table. CloudTable table = tableClient.GetTableReference("Table Storage Name"); // Create a new customer entity. DeloreanData data = new DeloreanData("Table Storage Primary Key", ""); if (messagePayload.ContainsKey("measurename")) { data.measurename = messagePayload["measurename"].ToString(); } if (messagePayload.ContainsKey("value")) { data.value = messagePayload["value"].ToString(); } if (messagePayload.ContainsKey("unitofmeasure")) { data.unitofmeasure = messagePayload["unitofmeasure"].ToString(); } if (messagePayload.ContainsKey("displayname")) { data.displayname = messagePayload["displayname"].ToString(); } if (messagePayload.ContainsKey("organization")) { data.organization = messagePayload["organization"].ToString(); } if (messagePayload.ContainsKey("location")) { data.location = messagePayload["location"].ToString(); } data.RowKey = DateTime.Parse(messagePayload["timecreated"].ToString()).Ticks.ToString() + "-" + data.measurename; TableOperation insertOperation = TableOperation.Insert(data); //var temperature = double.Parse(data.value); //if (temperature > 75) // { //NotificationHubClient hub = NotificationHubClient // .CreateClientFromConnectionString("Endpoint=sb://deloreantesthub-ns.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=wSpPlbYOksiifQGSa7qT1lXeWzxOKatCbHoGSqZOKfY=", "deloreantesthub"); //var toast = @"<toast><visual><binding template=""ToastText01""><text id=""1"">Hello from a .NET App!</text></binding></visual></toast>"; //await hub.SendWindowsNativeNotificationAsync(toast); table.Execute(insertOperation); //} } } // Create the TableOperation that inserts the customer entity. //table.Execute(insertOperation); // Notify clients MyWebSocketHandler.SendToClients(messagePayload); // Buffer messages so we can resend them to clients that connect later // or when a client requests data for a different device // Lock to guard against concurrent reads from client resend lock (sortedDataBuffer) { if (!sortedDataBuffer.ContainsKey(messageTimeStamp)) { sortedDataBuffer.Add(messageTimeStamp, new List <IDictionary <string, object> >()); } sortedDataBuffer[messageTimeStamp].Add(messagePayload); } } } else { Debug.Print("Received old message timestamped:" + eventData.EnqueuedTimeUtc.ToString()); } } //Call checkpoint every minute if (this.checkpointStopWatch.Elapsed > TimeSpan.FromMinutes(1)) { await context.CheckpointAsync(); lock (this) { this.checkpointStopWatch.Restart(); } // trim data buffer to keep only last 10 minutes of data lock (sortedDataBuffer) { DateTime oldDataPoint = now - bufferTimeInterval; // find the closest point int idx = SearchHelper.FindFirstIndexGreaterThanOrEqualTo(sortedDataBuffer, oldDataPoint); // trim while (idx > 0 && sortedDataBuffer.Count > 0 && sortedDataBuffer.Keys[0] <= oldDataPoint) { sortedDataBuffer.RemoveAt(0); } } } } catch (Exception e) { Trace.TraceError("Error processing events in EH {0}, partition {1}: {0}", context.EventHubPath, context.Lease.PartitionId, e.Message); } }
// ReSharper disable once FunctionComplexityOverflow public async Task ProcessEventsAsync(PartitionContext context, IEnumerable <EventData> messages) { try { if (configuration.CancellationToken.IsCancellationRequested) { return; } var events = messages as IList <EventData> ?? messages.ToList(); var bodySize = (long)0; for (var i = 0; i < events.Count; i++) { if (configuration.CancellationToken.IsCancellationRequested) { break; } if (configuration.MessageInspector != null) { events[i] = configuration.MessageInspector.AfterReceiveMessage(events[i]); } if (configuration.Logging) { var builder = new StringBuilder(string.IsNullOrWhiteSpace(events[i].PartitionKey)? string.Format(EventDataSuccessfullyNoPartitionKeyReceived, context.Lease.PartitionId, events[i].SequenceNumber, events[i].Offset, events[i].EnqueuedTimeUtc): string.Format(EventDataSuccessfullyReceived, context.Lease.PartitionId, events[i].PartitionKey, events[i].SequenceNumber, events[i].Offset, events[i].EnqueuedTimeUtc)); if (configuration.Verbose) { configuration.ServiceBusHelper.GetMessageAndProperties(builder, events[i]); } configuration.WriteToLog(builder.ToString()); } if (configuration.Tracking && !configuration.CancellationToken.IsCancellationRequested) { configuration.TrackEvent(events[i]); } bodySize += events[i].SerializedSizeInBytes; if (!configuration.Checkpoint) { continue; } await partitionContext.CheckpointAsync(events[events.Count - 1]); } configuration.UpdateStatistics(events.Count, configuration.GetElapsedTime(), bodySize); } catch (LeaseLostException) { } catch (Exception ex) { HandleException(ex); } }
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable <EventData> messages) { Trace.TraceInformation("CheckPointEventProcessor processing {0} messages from partition {1}...", messages.ToList().Count, context.Lease.PartitionId); await context.CheckpointAsync(); }
private async Task Checkpoint(EventData message, PartitionContext context) { Log.DebugFormat("Will checkpoint at Offset: {0}, {1}", message.SystemProperties.Offset, new PartitionContextInfo(context)); await context.CheckpointAsync(message); }
protected override void ReceiveCommand(PartitionContext context, EventData eventData) { // Do a manual 10 try attempt with back-off for (int i = 0; i < 10; i++) { try { Logger.LogDebug(string.Format("A command message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}'.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset)); string messageBody = Encoding.UTF8.GetString(eventData.GetBytes()); ICommand <TAuthenticationToken> command = MessageSerialiser.DeserialiseCommand(messageBody); CorrelationIdHelper.SetCorrelationId(command.CorrelationId); Logger.LogInfo(string.Format("A command message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' was of type {3}.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset, command.GetType().FullName)); Type commandType = command.GetType(); string targetQueueName = commandType.FullName; try { object rsn = commandType.GetProperty("Rsn").GetValue(command, null); targetQueueName = string.Format("{0}.{1}", targetQueueName, rsn); } catch { Logger.LogDebug(string.Format("A command message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' was of type {3} but with no Rsn property.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset, commandType)); // Do nothing if there is no rsn. Just use command type name } CreateQueueAndAttachListenerIfNotExist(targetQueueName); EnqueueCommand(targetQueueName, command); // remove the original message from the incoming queue context.CheckpointAsync(eventData); Logger.LogDebug(string.Format("A command message arrived and was processed with the partition key '{0}', sequence number '{1}' and offset '{2}'.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset)); return; } catch (Exception exception) { // Indicates a problem, unlock message in queue Logger.LogError(string.Format("A command message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' but failed to be process.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset), exception: exception); switch (i) { case 0: case 1: // 10 seconds Thread.Sleep(10 * 1000); break; case 2: case 3: // 30 seconds Thread.Sleep(30 * 1000); break; case 4: case 5: case 6: // 1 minute Thread.Sleep(60 * 1000); break; case 7: case 8: case 9: // 3 minutes Thread.Sleep(3 * 60 * 1000); break; } } } // Eventually just accept it context.CheckpointAsync(eventData); }
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable <EventData> events) { try { var now = DateTime.UtcNow; foreach (var eventData in events) { // We don't care about messages that are older than bufferTimeInterval if ((eventData.EnqueuedTimeUtc + bufferTimeInterval) >= now) { // Get message from the eventData body and convert JSON string into message object string eventBodyAsString = Encoding.UTF8.GetString(eventData.GetBytes()); // There can be several messages in one IList <IDictionary <string, object> > messagePayloads; try { // Attempt to deserialze event body as single JSON message messagePayloads = new List <IDictionary <string, object> > { JsonConvert.DeserializeObject <IDictionary <string, object> >(eventBodyAsString) }; } catch { // Not a single JSON message: attempt to deserialize as array of messages // Azure Stream Analytics Preview generates invalid JSON for some multi-values queries // Workaround: turn concatenated json objects (ivalid JSON) into array of json objects (valid JSON) if (eventBodyAsString.IndexOf("}{") >= 0) { eventBodyAsString = eventBodyAsString.Replace("}{", "},{"); } if (eventBodyAsString.IndexOf("}\r\n{") >= 0) { eventBodyAsString = eventBodyAsString.Replace("}\r\n{", "},{"); } if (!eventBodyAsString.EndsWith("]")) { eventBodyAsString = eventBodyAsString + "]"; } if (!eventBodyAsString.StartsWith("[")) { eventBodyAsString = "[" + eventBodyAsString.Substring(eventBodyAsString.IndexOf("{")); } messagePayloads = JsonConvert.DeserializeObject <IList <IDictionary <string, object> > >(eventBodyAsString); } var rnd = new Random(); foreach (var messagePayload in messagePayloads) { // Read time value if (messagePayload.ContainsKey("timecreated")) { messagePayload["time"] = messagePayload["timecreated"]; } if (messagePayload.ContainsKey("timearrived")) { messagePayload["time"] = messagePayload["timearrived"]; } // process an alert if (messagePayload.ContainsKey("alerttype") && messagePayload.ContainsKey("timecreated")) { Debug.Print("Alert message received!"); DateTime time = DateTime.Parse(messagePayload["timecreated"].ToString()); // find the nearest point lock (sortedDataBuffer) { int idx = SearchHelper.FindFirstIndexGreaterThanOrEqualTo(sortedDataBuffer, time); bool found = false; string alertType = messagePayload["alerttype"] as string; if (idx >= sortedDataBuffer.Values.Count) { idx = sortedDataBuffer.Values.Count - 1; } while (idx >= 0) { List <IDictionary <string, object> > dictList = sortedDataBuffer.Values[idx]; foreach (IDictionary <string, object> dict in dictList) { if ( (dict.ContainsKey("guid") && messagePayload.ContainsKey("guid") && messagePayload["guid"].ToString() == dict["guid"].ToString()) && (dict.ContainsKey("measurename") && messagePayload.ContainsKey("measurename") && messagePayload["measurename"].ToString() == dict["measurename"].ToString()) && (!messagePayload.ContainsKey("displayname") || dict.ContainsKey("displayname") && messagePayload["measurename"].ToString() == dict["measurename"].ToString()) ) { // fill anomaly message if (!messagePayload.ContainsKey("value")) { messagePayload["value"] = dict["value"]; } if (!messagePayload.ContainsKey("displayname") && dict.ContainsKey("displayname")) { messagePayload["displayname"] = dict["displayname"]; } if (!messagePayload.ContainsKey("time")) { messagePayload["time"] = messagePayload["timecreated"]; } found = true; break; } } if (found) { break; } idx--; } } } if (messagePayload.ContainsKey("guid")) { var guid = messagePayload["guid"].ToString(); double val = Convert.ToDouble(messagePayload["value"]); if (!MinMaxValue.ContainsKey(guid)) { MinMaxValue.Add(guid, new MinMax { min = val, max = val }); } MinMax tmp = MinMaxValue[messagePayload["guid"].ToString()]; if (tmp.min > val) { tmp.min = val; } if (tmp.max < val) { tmp.max = val; } } // We want to read the time value from the message itself. // If none is found we will use the enqueued time DateTime messageTimeStamp = new DateTime(); if (messagePayload.ContainsKey("time")) { messageTimeStamp = DateTime.Parse(messagePayload["time"].ToString()); //if (GenerateAnomalies && rnd.Next(100) >= 95) //{ // messagePayload.Add("alerttype", "testType"); // messagePayload.Add("dsplalert", "testAlert"); // messagePayload.Add("message", "Anomaly detected by Azure ML model."); // messagePayload.Add("timestart", messagePayload["time"]); // // correct value // if (rnd.Next(2) == 1) // messagePayload["value"] = MinMaxValue[messagePayload["guid"].ToString()].max * (1.01 + 0.05 * rnd.Next(100) / 100); // else // messagePayload["value"] = MinMaxValue[messagePayload["guid"].ToString()].min * (0.99 - 0.05 * rnd.Next(100) / 100); //} } else if (messagePayload.ContainsKey("timestart")) { messageTimeStamp = DateTime.Parse(messagePayload["timestart"].ToString()); } else { messageTimeStamp = eventData.EnqueuedTimeUtc; } // Build up the list of devices seen so far (in lieu of a formal device repository) // Also keep the last message received per device (not currently used in the sample) if (messagePayload.ContainsKey("guid") && !messagePayload.ContainsKey("valueAvg")) { string guid = messagePayload["guid"].ToString(); if (guid != null) { WebSocketEventProcessor.g_devices.TryAdd(guid, messagePayload); } } // Notify clients MyWebSocketHandler.SendToClients(messagePayload); // Buffer messages so we can resend them to clients that connect later // or when a client requests data for a different device // Lock to guard against concurrent reads from client resend lock (sortedDataBuffer) { if (!sortedDataBuffer.ContainsKey(messageTimeStamp)) { sortedDataBuffer.Add(messageTimeStamp, new List <IDictionary <string, object> >()); } sortedDataBuffer[messageTimeStamp].Add(messagePayload); } } } else { Debug.Print("Received old message timestamped:" + eventData.EnqueuedTimeUtc.ToString()); } } //Call checkpoint every minute if (this.checkpointStopWatch.Elapsed > TimeSpan.FromMinutes(1)) { await context.CheckpointAsync(); lock (this) { this.checkpointStopWatch.Restart(); } // trim data buffer to keep only last 10 minutes of data lock (sortedDataBuffer) { DateTime oldDataPoint = now - bufferTimeInterval; // find the closest point int idx = SearchHelper.FindFirstIndexGreaterThanOrEqualTo(sortedDataBuffer, oldDataPoint); // trim while (idx > 0 && sortedDataBuffer.Count > 0 && sortedDataBuffer.Keys[0] <= oldDataPoint) { sortedDataBuffer.RemoveAt(0); } } } } catch (Exception e) { Trace.TraceError("Error processing events in EH {0}, partition {1}: {0}", context.EventHubPath, context.Lease.PartitionId, e.Message); } }
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable <EventData> messages) { foreach (var eventData in messages) { Log.Logger.Information("Processing event: {sequenceNumber}", eventData.SequenceNumber); var data = Encoding.UTF8.GetString(eventData.GetBytes()); try { if (data.Contains("<")) { var eventXml = XElement.Parse(data); var lastChangeNode = eventXml.Descendants(XName.Get("LastChange")) .SingleOrDefault(); if (lastChangeNode != null) { var rawEvent = XElement.Parse(lastChangeNode.Value); var currentTrackMetaDataNode = rawEvent .Descendants(XName.Get("CurrentTrackMetaData", "urn:schemas-upnp-org:metadata-1-0/AVT/")) .SingleOrDefault(n => !String.IsNullOrEmpty(n.Attribute("val").Value)); if (currentTrackMetaDataNode != null) { var metadata = currentTrackMetaDataNode.Attribute(XName.Get("val")).Value; var metaXml = XElement.Parse(metadata); var classTypeNode = metaXml.Descendants(XName.Get("class", "urn:schemas-upnp-org:metadata-1-0/upnp/")) .SingleOrDefault(); if (classTypeNode != null) { var classType = classTypeNode.Value; switch (classType) { case "object.item.audioItem.musicTrack": var res = metaXml.Descendants(XName.Get("res", "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/")) .SingleOrDefault(); if (res != null) { var urlString = res.Value; var albumNode = metaXml.Descendants(XName.Get("album", "urn:schemas-upnp-org:metadata-1-0/upnp/")) .SingleOrDefault(); string album = null; if (albumNode != null) { album = albumNode.Value; } var track = metaXml.Descendants(XName.Get("title", "http://purl.org/dc/elements/1.1/")) .Single() .Value; var artist = metaXml.Descendants(XName.Get("creator", "http://purl.org/dc/elements/1.1/")) .Single() .Value; urlString = urlString.Replace("pndrradio-", string.Empty); var fileLocation = new Uri(urlString); var albumArtUriNode = metaXml.Descendants(XName.Get("albumArtURI", "urn:schemas-upnp-org:metadata-1-0/upnp/")).SingleOrDefault(); Uri albumArtUri = null; if (albumArtUriNode != null) { albumArtUri = new Uri(albumArtUriNode.Value); } recordCreator.Tell(new NewRecordMessage(artist, album, track, fileLocation, albumArtUri)); } break; } } } } } } catch (Exception e) { Log.Logger.Error(e, "Error: {e}"); } await context.CheckpointAsync(eventData); } }
public async Task CloseAsync(PartitionContext context, CloseReason reason) { this.logger.Debug("Event Processor Shutting Down.", () => new { context.PartitionId, reason }); await context.CheckpointAsync(); }
protected virtual void ReceiveCommand(PartitionContext context, EventData eventData) { DateTimeOffset startedAt = DateTimeOffset.UtcNow; Stopwatch mainStopWatch = Stopwatch.StartNew(); string responseCode = "200"; // Null means it was skipped bool? wasSuccessfull = true; string telemetryName = string.Format("Cqrs/Handle/Command/{0}", eventData.SequenceNumber); ISingleSignOnToken authenticationToken = null; IDictionary <string, string> telemetryProperties = new Dictionary <string, string> { { "Type", "Azure/EventHub" } }; object value; if (eventData.Properties.TryGetValue("Type", out value)) { telemetryProperties.Add("MessageType", value.ToString()); } TelemetryHelper.TrackMetric("Cqrs/Handle/Command", CurrentHandles++, telemetryProperties); // Do a manual 10 try attempt with back-off for (int i = 0; i < 10; i++) { try { Logger.LogDebug(string.Format("A command message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}'.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset)); string messageBody = Encoding.UTF8.GetString(eventData.GetBytes()); ICommand <TAuthenticationToken> command = AzureBusHelper.ReceiveCommand(messageBody, ReceiveCommand, string.Format("partition key '{0}', sequence number '{1}' and offset '{2}'", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset), () => { wasSuccessfull = null; telemetryName = string.Format("Cqrs/Handle/Command/Skipped/{0}", eventData.SequenceNumber); responseCode = "204"; // Remove message from queue context.CheckpointAsync(eventData); Logger.LogDebug(string.Format("A command message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' but processing was skipped due to command settings.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset)); TelemetryHelper.TrackEvent("Cqrs/Handle/Command/Skipped", telemetryProperties); } ); if (wasSuccessfull != null) { if (command != null) { telemetryName = string.Format("{0}/{1}", command.GetType().FullName, command.Id); authenticationToken = command.AuthenticationToken as ISingleSignOnToken; var telemeteredMessage = command as ITelemeteredMessage; if (telemeteredMessage != null) { telemetryName = telemeteredMessage.TelemetryName; } telemetryName = string.Format("Cqrs/Handle/Command/{0}", telemetryName); } // Remove message from queue context.CheckpointAsync(eventData); } Logger.LogDebug(string.Format("A command message arrived and was processed with the partition key '{0}', sequence number '{1}' and offset '{2}'.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset)); wasSuccessfull = true; responseCode = "200"; return; } catch (Exception exception) { // Indicates a problem, unlock message in queue Logger.LogError(string.Format("A command message arrived with the partition key '{0}', sequence number '{1}' and offset '{2}' but failed to be process.", eventData.PartitionKey, eventData.SequenceNumber, eventData.Offset), exception: exception); switch (i) { case 0: case 1: // 10 seconds Thread.Sleep(10 * 1000); break; case 2: case 3: // 30 seconds Thread.Sleep(30 * 1000); break; case 4: case 5: case 6: // 1 minute Thread.Sleep(60 * 1000); break; case 7: case 8: // 3 minutes Thread.Sleep(3 * 60 * 1000); break; case 9: telemetryProperties.Add("ExceptionType", exception.GetType().FullName); telemetryProperties.Add("ExceptionMessage", exception.Message); break; } wasSuccessfull = false; responseCode = "500"; } finally { // Eventually just accept it context.CheckpointAsync(eventData); TelemetryHelper.TrackMetric("Cqrs/Handle/Command", CurrentHandles--, telemetryProperties); mainStopWatch.Stop(); TelemetryHelper.TrackRequest ( telemetryName, authenticationToken, startedAt, mainStopWatch.Elapsed, responseCode, wasSuccessfull == null || wasSuccessfull.Value, telemetryProperties ); TelemetryHelper.Flush(); } } }
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable <EventData> messages) { Trace.TraceInformation("ActionProcessor: In ProcessEventsAsync"); List <LocationJerkModel> newLocationJerks = new List <LocationJerkModel>(); foreach (EventData message in messages) { try { Trace.TraceInformation("ActionProcessor: {0} - Partition {1}", message.Offset, context.Lease.PartitionId); this.LastMessageOffset = message.Offset; string jsonString = Encoding.UTF8.GetString(message.GetBytes()); List <TelemetryJerkModel> convertedList = JsonConvert.DeserializeObject <List <TelemetryJerkModel> >(jsonString); var results = convertedList.Distinct(new TelemetryJerkComparer()); if (results != null) { foreach (TelemetryJerkModel item in results) { UpdateLocationJerkList(GetLocationJerkFromTelemetry(item), ref newLocationJerks); } } ++_totalMessages; } catch (Exception e) { Trace.TraceError("ActionProcessor: Error in ProcessEventAsync -- " + e.ToString()); } } //finally save data to blob try { await SaveToLocationJerkInfo(newLocationJerks); } catch (Exception ex) { Trace.TraceError( "{0}{0}*** SaveLocationJerkInfo Exception - ActionProcessor.ProcessEventsAsync ***{0}{0}{1}{0}{0}", Console.Out.NewLine, ex); } // checkpoint after processing batch try { await context.CheckpointAsync(); } catch (Exception ex) { Trace.TraceError( "{0}{0}*** CheckpointAsync Exception - ActionProcessor.ProcessEventsAsync ***{0}{0}{1}{0}{0}", Console.Out.NewLine, ex); } if (this.IsClosed) { this.IsReceivedMessageAfterClose = true; } }
async Task ICheckpointer.CheckpointAsync(PartitionContext context) { await context.CheckpointAsync(); }
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable <EventData> events) { try { var now = DateTime.UtcNow; foreach (var eventData in events) { // We don't care about messages that are older than bufferTimeInterval if ((eventData.EnqueuedTimeUtc + bufferTimeInterval) >= now) { // Get message from the eventData body and convert JSON string into message object string eventBodyAsString = Encoding.UTF8.GetString(eventData.GetBytes()); // There can be several messages in one IList <IDictionary <string, object> > messagePayloads; try { // Attempt to deserialze event body as single JSON message messagePayloads = new List <IDictionary <string, object> > { JsonConvert.DeserializeObject <IDictionary <string, object> >(eventBodyAsString) }; } catch { // Not a single JSON message: attempt to deserialize as array of messages // Azure Stream Analytics Preview generates invalid JSON for some multi-values queries // Workaround: turn concatenated json objects (ivalid JSON) into array of json objects (valid JSON) if (eventBodyAsString.IndexOf("}{") >= 0) { eventBodyAsString = eventBodyAsString.Replace("}{", "},{"); } if (!eventBodyAsString.EndsWith("]")) { eventBodyAsString = eventBodyAsString + "]"; } if (!eventBodyAsString.StartsWith("[")) { eventBodyAsString = "[" + eventBodyAsString; } messagePayloads = JsonConvert.DeserializeObject <IList <IDictionary <string, object> > >(eventBodyAsString); } foreach (var messagePayload in messagePayloads) { // We want to read the time value from the message itself. // If none is found we will use the enqueued time DateTime messageTimeStamp = new DateTime(); if (messagePayload.ContainsKey("time")) { messageTimeStamp = DateTime.Parse(messagePayload["time"].ToString()); } else if (messagePayload.ContainsKey("timeStart")) { messageTimeStamp = DateTime.Parse(messagePayload["timeStart"].ToString()); } else { messageTimeStamp = eventData.EnqueuedTimeUtc; } // Build up the list of devices seen so far (in lieu of a formal device repository) // Also keep the last message received per device (not currently used in the sample) string deviceName = null; if (messagePayload.ContainsKey("dspl")) { deviceName = messagePayload["dspl"] as string; if (deviceName != null) { WebSocketEventProcessor.g_devices.TryAdd(deviceName, messagePayload); } } // Notify clients MyWebSocketHandler.SendToClients(messagePayload); // Buffer messages so we can resend them to clients that connect later // or when a client requests data for a different device // Lock to guard against concurrent reads from client resend // Note that the Add operations are not contentious with each other // because EH processor host serializes per partition, and we use one buffer per partition lock (this.sortedDataBuffer) { if (!sortedDataBuffer.ContainsKey(messageTimeStamp)) { this.sortedDataBuffer.Add(messageTimeStamp, messagePayload); } } } } } //Call checkpoint every minute if (this.checkpointStopWatch.Elapsed > TimeSpan.FromMinutes(1)) { await context.CheckpointAsync(); lock (this) { this.checkpointStopWatch.Reset(); } // trim data buffer to keep only last 10 minutes of data lock (this.sortedDataBuffer) { SortedList <DateTime, IDictionary <string, object> > tempBuffer = new SortedList <DateTime, IDictionary <string, object> >(); foreach (var item in this.sortedDataBuffer) { if (item.Key + bufferTimeInterval >= now) { tempBuffer.Add(item.Key, item.Value); } } this.sortedDataBuffer = tempBuffer; } } } catch (Exception e) { Trace.TraceError("Error processing events in EH {0}, partition {1}: {0}", context.EventHubPath, context.Lease.PartitionId, e.Message); } }
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable <EventData> messages) { foreach (var eventData in messages) { var reqTime = DateTime.UtcNow; var data = Encoding.UTF8.GetString(eventData.Body.Array, eventData.Body.Offset, eventData.Body.Count); _logger.LogInformation($"Message received. Partition: '{context.PartitionId}', Data: '{data}'"); var hitmsg = JsonConvert.DeserializeObject <HitCountMessage>(data); var devid = eventData.Properties["iothub-connection-device-id"].ToString(); //bool hasDevice; //try //{ // // Check the device exist // var device = await iotRegManager.GetDeviceAsync(devid); // hasDevice = (device != null ? true : false); //} //catch //{ // hasDevice = false; //} //bool ehResult = true; //if (hasDevice) //{ // try // { // // invoke direct method // var method = new CloudToDeviceMethod("ControlMethod"); // method.SetPayloadJson(data); // await serviceClient.InvokeDeviceMethodAsync(devid, method); // ehResult = true; // } // catch (Exception ex) // { // _logger.LogError(ex.ToString()); // ehResult = false; // } //} //else //{ // _logger.LogError("Device not found. No method call."); //} bool ehResult; try { // invoke direct method var method = new CloudToDeviceMethod("ControlMethod"); method.SetPayloadJson(data); await serviceClient.InvokeDeviceMethodAsync(devid, method); ehResult = true; } catch (Exception ex) { _logger.LogError(ex.ToString()); ehResult = false; } var reqid = Guid.NewGuid().ToString(); //var duration = reqTime.Subtract(DateTimeOffset.Parse(eventData.Properties["ruleset-request-time"].ToString())); var duration = reqTime.Subtract(eventData.SystemProperties.EnqueuedTimeUtc); var dependencyTelemetry = new DependencyTelemetry { Id = reqid, Duration = duration, Target = "IoT Hub", Success = ehResult, Name = "MessageService processing", Timestamp = reqTime }; dependencyTelemetry.Context.Operation.Id = hitmsg.corellationId; dependencyTelemetry.Context.Operation.ParentId = (eventData.Properties.ContainsKey("ruleset-request-id") ? eventData.Properties["ruleset-request-id"]?.ToString() : ""); dependencyTelemetry.Context.Cloud.RoleName = "MessageService"; dependencyTelemetry.Context.Cloud.RoleInstance = Environment.MachineName; dependencyTelemetry.Properties["device-id"] = devid; _telemetryClient.TrackDependency(dependencyTelemetry); _telemetryClient.Flush(); } await context.CheckpointAsync(); }