-
Notifications
You must be signed in to change notification settings - Fork 98
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update eventHub SDK to version 5.1.0 (#92)
Updated frameworks in ASA latency monitoring utility: * Updated .NET Core to 3.1 * Update eventHub SDK to version 5.1.0 * Removed dependency of Newtonsoft, added System.Text.Json dependency. Refactor based on comments. * Remove the ReceiverProcessor type and merge its ProcessEvents method into EventReceiver also split EventReceiver into it's own file. * Some changes in read me, and add comments * Remove lock in EventReceiver and some codestyle changing. * Quick mention the condition to run this sample. * updated to GA package * some describing details updated Co-authored-by: Frank Li (Wicresoft North America Ltd) <v-cheli@microsoft.com>
- Loading branch information
1 parent
c175b67
commit 063f301
Showing
4 changed files
with
171 additions
and
159 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,50 @@ | ||
# Testing End-To-End Latency | ||
--- | ||
page_type: sample | ||
languages: | ||
- csharp | ||
products: | ||
- azure | ||
- azure-event-hubs | ||
extensions: | ||
- platforms: dotnet | ||
--- | ||
|
||
Get the Event Hub connection string created and displayed during the script execution. If you cannot find it, just grab the execution string for the `Listen` Shared Access Policy for the output eventhub. | ||
# Getting started on processing received message from Event Hubs # | ||
|
||
The `eventhubs-streamanalytics-eventhubs` sample demonstrates processing messages from Event Hubs. The `EventReceiver` will: | ||
|
||
- Connect to an existing event hub. | ||
- Read events from all partitions using the `EventHubConsumerClient`. | ||
- Process each received message and output to a `.csv` file. | ||
|
||
# Running this Sample # | ||
To run this sample: | ||
|
||
If you don't have an Azure subscription, create a [free account] before you begin. | ||
|
||
Go to [Azure portal], sign in with your account. You can find how to [create event hub] from here. | ||
|
||
After creating an event hub within the Event Hubs namespace, you can get the Event Hub-level EventHubConnectionString with following steps. | ||
1. In the list of event hubs, select your event hub. | ||
2. On the Event Hubs Instance page, select Shared Access Policies on the left menu. | ||
3. Add a policy with appropriate permissions(Listen or Manage). | ||
4. Click on added policy. | ||
|
||
Hints:While running this sample, You should have an existing Azure Stream Analytics configuration(a producer sends events) | ||
that publishes events to this event hub. | ||
|
||
Run the following command. | ||
```bash | ||
git clone https://github.com/Azure-Samples/streaming-at-scale.git | ||
``` | ||
From within the `eh-asa-perform` folder run: | ||
|
||
```bash | ||
dotnet run -- -c "<connection string>" | ||
dotnet run -- -c "<EventHubConnectionString>" | ||
``` | ||
The application will read from the event hub and will measure latency (difference from Enqueued and Processed time) for each batch of recevied messages. | ||
|
||
The application will read from the output eventhub and will measure latency (difference from Enqueued and Processed time) for each batch of recevied messages. | ||
<!-- LINKS --> | ||
[free account]: https://azure.microsoft.com/free/?WT.mc_id=A261C142F | ||
[Azure portal]: https://portal.azure.com/ | ||
[create event hub]: https://docs.microsoft.com/en-us/azure/event-hubs/event-hubs-create |
111 changes: 111 additions & 0 deletions
111
eventhubs-streamanalytics-eventhubs/tools/eh-asa-perfmon/EventReceiver.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
using Azure.Messaging.EventHubs.Consumer; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Text.Json; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace StreamingAtScale | ||
{ | ||
public class EventReceiver | ||
{ | ||
public async Task Receive(string connectionString, CancellationToken cancellationToken) | ||
{ | ||
// In here, our consumer will read from the latest position instead of the earliest. As a result, it won't see events that | ||
// have previously been published. | ||
// | ||
// Each partition of an Event Hub represents a potentially infinite stream of events. When a consumer is reading, there is no definitive | ||
// point where it can assess that all events have been read and no more will be available. As a result, when the consumer reaches the end of | ||
// the available events for a partition, it will continue to wait for new events to arrive so that it can surface them to be processed. During this | ||
// time, the iterator will block. | ||
// | ||
// In order to prevent the consumer from waiting forever for events, and blocking other code, there is a method available for developers to | ||
// control this behavior. It's signaling the cancellation token passed when reading will cause the consumer to stop waiting and end iteration | ||
// immediately. This is desirable when you have decided that you are done reading and do not wish to continue. | ||
|
||
await using (var consumerClient = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) | ||
{ | ||
Console.WriteLine("The application will now start to listen for incoming message."); | ||
|
||
// Each time the consumer looks to read events, we'll ask that it waits only a short time before emitting | ||
// an empty event, so that our code has the chance to run without indefinite blocking. | ||
|
||
ReadEventOptions readOptions = new ReadEventOptions | ||
{ | ||
MaximumWaitTime = TimeSpan.FromMilliseconds(500) | ||
}; | ||
|
||
using (var csvOutput = File.CreateText("./result.csv")) | ||
{ | ||
csvOutput.WriteLine("EventCount,BatchCount,BatchFrom,BatchTo,MinLatency,MaxLatency,AvgLatency"); | ||
try | ||
{ | ||
// The client is safe and intended to be long-lived. | ||
|
||
await foreach (PartitionEvent currentEvent in consumerClient.ReadEventsAsync(readOptions, cancellationToken)) | ||
{ | ||
var eventData = currentEvent.Data; | ||
|
||
// Because publishing and receiving events is asynchronous, the events that published may not | ||
// be immediately available for our consumer to see, so we'll have to guard against an empty event being sent | ||
if (eventData == null) continue; | ||
|
||
int eventCount = 0; | ||
var listTimeSpan = new List<TimeSpan>(); | ||
var listDateTime = new List<DateTimeOffset>(); | ||
|
||
var eventBody = Encoding.UTF8.GetString(eventData.Body.ToArray()).Split('\n'); | ||
|
||
foreach (var bodyInfo in eventBody) | ||
{ | ||
try | ||
{ | ||
var message = JsonSerializer.Deserialize<Dictionary<string, object>>(bodyInfo); | ||
eventCount++; | ||
|
||
var timeCreated = DateTime.Parse(message["createdAt"].ToString()); | ||
var timeIn = DateTime.Parse(message["EventEnqueuedUtcTime"].ToString()); | ||
var timeProcessed = DateTime.Parse(message["EventProcessedUtcTime"].ToString()); | ||
var timeAsaProcessed = DateTime.Parse(message["ASAProcessedUtcTime"].ToString()); | ||
var timeOut = eventData.EnqueuedTime.UtcDateTime.ToLocalTime(); | ||
|
||
listDateTime.Add(timeIn); | ||
var elapsed = timeOut - timeIn; | ||
listTimeSpan.Add(elapsed); | ||
} | ||
catch (Exception ex) | ||
{ | ||
Console.WriteLine("Error while parsing event body."); | ||
Console.WriteLine("Error:" + ex.Message); | ||
Console.WriteLine("Message:" + bodyInfo); | ||
} | ||
} | ||
|
||
var batchFrom = listDateTime.Min(); | ||
var batchTo = listDateTime.Min(); | ||
var minLatency = listTimeSpan.Min().TotalMilliseconds; | ||
var maxLatency = listTimeSpan.Max().TotalMilliseconds; | ||
var avgLatency = Math.Round(listTimeSpan.Average(ts => ts.TotalMilliseconds), 0); | ||
|
||
Console.Write($"Received {eventCount} events."); | ||
Console.Write($"\tBatch (From/To): {batchFrom.ToString("HH:mm:ss.ffffff")}/{batchTo.ToString("HH:mm:ss.ffffff")}"); | ||
Console.Write($"\tElapsed msec (Min/Max/Avg): {minLatency}/{maxLatency}/{avgLatency}"); | ||
Console.WriteLine(); | ||
|
||
csvOutput.WriteLine($"{eventCount},{eventCount},{batchFrom.ToString("o")},{batchTo.ToString("o")},{minLatency},{maxLatency},{avgLatency}"); | ||
} | ||
} | ||
catch (TaskCanceledException) | ||
{ | ||
// This is okay because the task was cancelled. | ||
} | ||
} | ||
} | ||
// At this point, our clients have passed their "using" scope and have safely been disposed of. We | ||
// have no further obligations. | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 6 additions & 4 deletions
10
eventhubs-streamanalytics-eventhubs/tools/eh-asa-perfmon/eh-asa-perfmon.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,16 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>netcoreapp2.1</TargetFramework> | ||
<TargetFramework>netcoreapp3.1</TargetFramework> | ||
<RootNamespace>StreamingAtScale</RootNamespace> | ||
<LangVersion>8.0</LangVersion> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="CommandLineParser" Version="2.5.0" /> | ||
<PackageReference Include="Microsoft.Azure.EventHubs" Version="3.0.0" /> | ||
<PackageReference Include="Azure.Messaging.EventHubs" Version="5.1.0" /> | ||
<PackageReference Include="CommandLineParser" Version="2.8.0" /> | ||
<PackageReference Include="System.Text.Json" Version="4.7.2" /> | ||
</ItemGroup> | ||
|
||
</Project> |