Skip to content

Commit d0f24bd

Browse files
authored
[Messaging] README Updates (Azure#35433)
The focus of these changes is to tweak the content and format of the Event Hubs README snippets to clarify lifetime guidance explicitly in each example and to add an illustration of registering with ASP.NET Core DI. Tweaked the layout of the Service Bus examples, moving the ASP.NET Core section to an example to streamline the "Authenticating the client" section and focus on the core "Getting Started" scenario.
1 parent 4f74eb8 commit d0f24bd

File tree

5 files changed

+225
-45
lines changed

5 files changed

+225
-45
lines changed

sdk/eventhub/Azure.Messaging.EventHubs.Processor/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ For the Event Hubs client library to interact with an Event Hub, it will need to
5454

5555
For the event processor client to make use of Azure Storage blobs for checkpointing, it will need to understand how to connect to a storage account and authorize with it. The most straightforward method of doing so is to use a connection string, which is generated at the time that the storage account is created. If you aren't familiar with storage account connection string authorization in Azure, you may wish to follow the step-by-step guide to [configure Azure Storage connection strings](https://docs.microsoft.com/azure/storage/common/storage-configure-connection-string).
5656

57+
Once you have the connection strings, see [Creating an Event Processor Client](#creating-an-event-processor-client) for an example of how to use them to create the processor.
58+
5759
## Key concepts
5860

5961
- An **event processor** is a construct intended to manage the responsibilities associated with connecting to a given Event Hub and processing events from each of its partitions, in the context of a specific consumer group. The act of processing events read from the partition and handling any errors that occur is delegated by the event processor to code that you provide, allowing your logic to concentrate on delivering business value while the processor handles the tasks associated with reading events, managing the partitions, and allowing state to be persisted in the form of checkpoints.

sdk/eventhub/Azure.Messaging.EventHubs/README.md

Lines changed: 107 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,24 @@ dotnet add package Azure.Messaging.EventHubs
4444
### Authenticate the client
4545

4646
For the Event Hubs client library to interact with an Event Hub, it will need to understand how to connect and authorize with it. The easiest means for doing so is to use a connection string, which is created automatically when creating an Event Hubs namespace. If you aren't familiar with using connection strings with Event Hubs, you may wish to follow the step-by-step guide to [get an Event Hubs connection string](https://docs.microsoft.com/azure/event-hubs/event-hubs-get-connection-string).
47+
48+
Once you have a connection string, any of the Event Hubs client types can be created with it:
49+
50+
```C# Snippet:EventHubs_ReadMe_Create_ConnectionString
51+
var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>";
52+
var eventHubName = "<< NAME OF THE EVENT HUB >>";
53+
54+
// It is recommended that you cache the Event Hubs clients for the lifetime of your
55+
// application, closing or disposing when application ends. This example disposes
56+
// after the immediate scope for simplicity.
57+
58+
await using var producer = new EventHubProducerClient(connectionString, eventHubName);
59+
```
60+
61+
For examples of authenticating the Event Hubs clients with credential types, see [Using an Azure Active Directory (AAD) principal](#using-an-active-directory-principal-with-the-event-hub-clients) or the [Identity and Shared Access Credentials](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample06_IdentityAndSharedAccessCredentials.md) sample.
62+
63+
For examples of authenticating the Event Hubs clients for an ASP.NET Core application, see [Registering with ASP.NET Core dependency injection](#registering-with-aspnet-core-dependency-injection).
64+
4765
## Key concepts
4866

4967
- An **Event Hub client** is the primary interface for developers interacting with the Event Hubs client library. There are several different Event Hub clients, each dedicated to a specific use of Event Hubs, such as publishing or consuming events.
@@ -85,6 +103,10 @@ Many Event Hub operations take place within the scope of a specific partition.
85103
var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>";
86104
var eventHubName = "<< NAME OF THE EVENT HUB >>";
87105

106+
// It is recommended that you cache the Event Hubs clients for the lifetime of your
107+
// application, closing or disposing when application ends. This example disposes
108+
// after the immediate scope for simplicity.
109+
88110
await using (var producer = new EventHubProducerClient(connectionString, eventHubName))
89111
{
90112
string[] partitionIds = await producer.GetPartitionIdsAsync();
@@ -99,11 +121,19 @@ In order to publish events, you'll need to create an `EventHubProducerClient`.
99121
var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>";
100122
var eventHubName = "<< NAME OF THE EVENT HUB >>";
101123

124+
// It is recommended that you cache the Event Hubs clients for the lifetime of your
125+
// application, closing or disposing when application ends. This example disposes
126+
// after the immediate scope for simplicity.
127+
102128
await using (var producer = new EventHubProducerClient(connectionString, eventHubName))
103129
{
104130
using EventDataBatch eventBatch = await producer.CreateBatchAsync();
105-
eventBatch.TryAdd(new EventData(new BinaryData("First")));
106-
eventBatch.TryAdd(new EventData(new BinaryData("Second")));
131+
132+
if ((!eventBatch.TryAdd(new EventData("First"))) ||
133+
(!eventBatch.TryAdd(new EventData("Second"))))
134+
{
135+
throw new ApplicationException("Not all events could be added to the batch!");
136+
}
107137

108138
await producer.SendAsync(eventBatch);
109139
}
@@ -121,6 +151,10 @@ var eventHubName = "<< NAME OF THE EVENT HUB >>";
121151

122152
string consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName;
123153

154+
// It is recommended that you cache the Event Hubs clients for the lifetime of your
155+
// application, closing or disposing when application ends. This example disposes
156+
// after the immediate scope for simplicity.
157+
124158
await using (var consumer = new EventHubConsumerClient(consumerGroup, connectionString, eventHubName))
125159
{
126160
using var cancellationSource = new CancellationTokenSource();
@@ -146,6 +180,10 @@ var eventHubName = "<< NAME OF THE EVENT HUB >>";
146180

147181
string consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName;
148182

183+
// It is recommended that you cache the Event Hubs clients for the lifetime of your
184+
// application, closing or disposing when application ends. This example disposes
185+
// after the immediate scope for simplicity.
186+
149187
await using (var consumer = new EventHubConsumerClient(consumerGroup, connectionString, eventHubName))
150188
{
151189
EventPosition startingPosition = EventPosition.Earliest;
@@ -221,7 +259,7 @@ More details can be found in the Event Processor Client [README](https://github.
221259

222260
### Using an Active Directory principal with the Event Hub clients
223261

224-
The [Azure Identity library](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/README.md) provides Azure Active Directory authentication support which can be used for the Azure client libraries, including Event Hubs.
262+
The [Azure Identity library](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/README.md) provides Azure Active Directory (AAD) authentication support which can be used for the Azure client libraries, including Event Hubs.
225263

226264
To make use of an Active Directory principal, one of the available credentials from the `Azure.Identity` library is specified when creating the Event Hubs client. In addition, the fully qualified Event Hubs namespace and the name of desired Event Hub are supplied in lieu of the Event Hubs connection string. For illustration, the `EventHubProducerClient` is demonstrated in these examples, but the concept and form are common across clients.
227265

@@ -230,18 +268,82 @@ var fullyQualifiedNamespace = "<< FULLY-QUALIFIED EVENT HUBS NAMESPACE (like som
230268
var eventHubName = "<< NAME OF THE EVENT HUB >>";
231269
var credential = new DefaultAzureCredential();
232270

271+
// It is recommended that you cache the Event Hubs clients for the lifetime of your
272+
// application, closing or disposing when application ends. This example disposes
273+
// after the immediate scope for simplicity.
274+
233275
await using (var producer = new EventHubProducerClient(fullyQualifiedNamespace, eventHubName, credential))
234276
{
235277
using EventDataBatch eventBatch = await producer.CreateBatchAsync();
236-
eventBatch.TryAdd(new EventData(new BinaryData("First")));
237-
eventBatch.TryAdd(new EventData(new BinaryData("Second")));
278+
279+
if ((!eventBatch.TryAdd(new EventData("First"))) ||
280+
(!eventBatch.TryAdd(new EventData("Second"))))
281+
{
282+
throw new ApplicationException("Not all events could be added to the batch!");
283+
}
238284

239285
await producer.SendAsync(eventBatch);
240286
}
241287
```
242288

243289
When using Azure Active Directory, your principal must be assigned a role which allows access to Event Hubs, such as the `Azure Event Hubs Data Owner` role. For more information about using Azure Active Directory authorization with Event Hubs, please refer to [the associated documentation](https://docs.microsoft.com/azure/event-hubs/authorize-access-azure-active-directory).
244290

291+
### Registering with ASP.NET Core dependency injection
292+
293+
To inject one of the Event Hubs clients as a dependency in an ASP.NET Core application, install the Azure client library integration for ASP.NET Core package.
294+
295+
```dotnetcli
296+
dotnet add package Microsoft.Extensions.Azure
297+
```
298+
299+
After installing, register the desired Event Hubs client types in the `Startup.ConfigureServices` method:
300+
301+
```csharp
302+
public void ConfigureServices(IServiceCollection services)
303+
{
304+
services.AddAzureClients(builder =>
305+
{
306+
builder.AddEventHubProducerClient(Configuration.GetConnectionString("EventHubs"));
307+
});
308+
309+
services.AddControllers();
310+
}
311+
```
312+
313+
To use the preceding code, add this to the configuration for your application:
314+
315+
```json
316+
{
317+
"ConnectionStrings": {
318+
"EventHubs": "<connection_string>"
319+
}
320+
}
321+
```
322+
323+
For applications that prefer using a shared `Azure.Identity` credential for their clients, registration looks slightly different:
324+
325+
```csharp
326+
var fullyQualifiedNamespace = "<< FULLY-QUALIFIED EVENT HUBS NAMESPACE (like something.servicebus.windows.net) >>";
327+
328+
public void ConfigureServices(IServiceCollection services)
329+
{
330+
services.AddAzureClients(builder =>
331+
{
332+
// This will register the EventHubProducerClient using the default credential.
333+
builder.AddEventHubProducerClientWithNamespace(fullyQualifiedNamespace);
334+
335+
// By default, DefaultAzureCredential is used, which is likely desired for most
336+
// scenarios. If you need to restrict to a specific credential instance, you could
337+
// register that instance as the default credential instead.
338+
builder.UseCredential(new ManagedIdentityCredential());
339+
});
340+
341+
services.AddControllers();
342+
}
343+
```
344+
345+
For more details, see [Dependency injection with the Azure SDK for .NET](https://docs.microsoft.com/dotnet/azure/sdk/dependency-injection).
346+
245347
## Troubleshooting
246348

247349
For detailed troubleshooting information, please refer to the [Event Hubs Troubleshooting Guide](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/TROUBLESHOOTING.md).

sdk/eventhub/Azure.Messaging.EventHubs/src/ApiCompatBaseline.txt

Lines changed: 0 additions & 2 deletions
This file was deleted.

sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/ReadMeSnippetsLiveTests.cs

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,32 @@ namespace Azure.Messaging.EventHubs.Tests.Snippets
2323
[Category(TestCategory.DisallowVisualStudioLiveUnitTesting)]
2424
public class ReadMeSnippetsLiveTests
2525
{
26+
/// <summary>
27+
/// Performs basic smoke test validation of the contained snippet.
28+
/// </summary>
29+
///
30+
[Test]
31+
public async Task CreateWithConnectionString()
32+
{
33+
#region Snippet:EventHubs_ReadMe_Create_ConnectionString
34+
35+
#if SNIPPET
36+
var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>";
37+
var eventHubName = "<< NAME OF THE EVENT HUB >>";
38+
#else
39+
var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString;
40+
var eventHubName = "fakeHub";
41+
#endif
42+
43+
// It is recommended that you cache the Event Hubs clients for the lifetime of your
44+
// application, closing or disposing when application ends. This example disposes
45+
// after the immediate scope for simplicity.
46+
47+
await using var producer = new EventHubProducerClient(connectionString, eventHubName);
48+
49+
#endregion
50+
}
51+
2652
/// <summary>
2753
/// Performs basic smoke test validation of the contained snippet.
2854
/// </summary>
@@ -42,6 +68,10 @@ public async Task Inspect()
4268
var eventHubName = scope.EventHubName;
4369
#endif
4470

71+
// It is recommended that you cache the Event Hubs clients for the lifetime of your
72+
// application, closing or disposing when application ends. This example disposes
73+
// after the immediate scope for simplicity.
74+
4575
await using (var producer = new EventHubProducerClient(connectionString, eventHubName))
4676
{
4777
string[] partitionIds = await producer.GetPartitionIdsAsync();
@@ -69,11 +99,19 @@ public async Task Publish()
6999
var eventHubName = scope.EventHubName;
70100
#endif
71101

102+
// It is recommended that you cache the Event Hubs clients for the lifetime of your
103+
// application, closing or disposing when application ends. This example disposes
104+
// after the immediate scope for simplicity.
105+
72106
await using (var producer = new EventHubProducerClient(connectionString, eventHubName))
73107
{
74108
using EventDataBatch eventBatch = await producer.CreateBatchAsync();
75-
eventBatch.TryAdd(new EventData(new BinaryData("First")));
76-
eventBatch.TryAdd(new EventData(new BinaryData("Second")));
109+
110+
if ((!eventBatch.TryAdd(new EventData("First"))) ||
111+
(!eventBatch.TryAdd(new EventData("Second"))))
112+
{
113+
throw new ApplicationException("Not all events could be added to the batch!");
114+
}
77115

78116
await producer.SendAsync(eventBatch);
79117
}
@@ -104,6 +142,10 @@ public async Task Read()
104142

105143
string consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName;
106144

145+
// It is recommended that you cache the Event Hubs clients for the lifetime of your
146+
// application, closing or disposing when application ends. This example disposes
147+
// after the immediate scope for simplicity.
148+
107149
await using (var consumer = new EventHubConsumerClient(consumerGroup, connectionString, eventHubName))
108150
{
109151
using var cancellationSource = new CancellationTokenSource();
@@ -149,6 +191,10 @@ public async Task ReadPartition()
149191

150192
string consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName;
151193

194+
// It is recommended that you cache the Event Hubs clients for the lifetime of your
195+
// application, closing or disposing when application ends. This example disposes
196+
// after the immediate scope for simplicity.
197+
152198
await using (var consumer = new EventHubConsumerClient(consumerGroup, connectionString, eventHubName))
153199
{
154200
EventPosition startingPosition = EventPosition.Earliest;
@@ -195,11 +241,19 @@ public async Task PublishIdentity()
195241
var credential = EventHubsTestEnvironment.Instance.Credential;
196242
#endif
197243

244+
// It is recommended that you cache the Event Hubs clients for the lifetime of your
245+
// application, closing or disposing when application ends. This example disposes
246+
// after the immediate scope for simplicity.
247+
198248
await using (var producer = new EventHubProducerClient(fullyQualifiedNamespace, eventHubName, credential))
199249
{
200250
using EventDataBatch eventBatch = await producer.CreateBatchAsync();
201-
eventBatch.TryAdd(new EventData(new BinaryData("First")));
202-
eventBatch.TryAdd(new EventData(new BinaryData("Second")));
251+
252+
if ((!eventBatch.TryAdd(new EventData("First"))) ||
253+
(!eventBatch.TryAdd(new EventData("Second"))))
254+
{
255+
throw new ApplicationException("Not all events could be added to the batch!");
256+
}
203257

204258
await producer.SendAsync(eventBatch);
205259
}

0 commit comments

Comments
 (0)