9

I'm leveraging services of the Azure SDK to log telemetry data to Azure Event Hubs. My client application calls an API endpoint which instantiates the EventHubProducerClient to log data to Event Hubs. I am managing many api calls and was wondering if the EventHubProducerClient can be reused across multiple calls or should I use a new instance per call.

Mike Check
  • 89
  • 3

2 Answers2

13

Yes. The EventHubProducerClient is safe to cache and use for the lifetime of the application, and that is the best practice for use when your application publishes events regularly or semi-regularly. Internally, the producer will manage it's underlying resources and transparently attempt to keep resource usage low during periods of inactivity and manage their health during periods of higher use.

Calling its CloseAsync method as your application is shutting down will ensure that network resources and other unmanaged objects are properly cleaned up.

Side Note: A common question for the EventHubProducerClient is why does it implement IAsyncDisposable if it is safe to treat as long-lived. This was done partially for convenience in scenarios where publishing is very infrequent and resources are a concern for the application, and partially to mimic the pattern of the HttpClient.

Jesse Squire
  • 6,107
  • 1
  • 27
  • 30
  • It's unfortunate the documentation isn't better about this, because since it implements `IAsyncDisposable`, many code examples simply demonstrate using it inline, which has HUGE performance costs (on an HTTP request, add 100-200ms if you don't cache the producer). – qJake Sep 09 '20 at 14:12
  • 1
    Agreed. I'll take a follow-up to see if we can get the official docs updated to better reflect this. – Jesse Squire Sep 09 '20 at 14:21
  • Would this recommendation change at all with an Azure function and a static client? How would or should CloseAsync be used in this instance? – Mike Sep 09 '21 at 20:30
  • The same guidance applies to Functions. The easiest way to manage the lifespan in that scenario is to use the `AddEventHubProducerClient` on the builder when [registering services](https://learn.microsoft.com/azure/azure-functions/functions-dotnet-dependency-injection#register-services) for dependency injection. That will register the producer as a Singleton and ensure that disposal is taken care of. _(that's the other reason it supports IAsyncDisposable)_ – Jesse Squire Sep 10 '21 at 12:48
0

This is the implementation I use and I reuse this for all the calls.

public class MyEventHubService : IMyEventHubService, IAsyncDisposable
    {
        public MyEventHubService(ILogger logger, IOptions<MyConfigs> MyConfigs)
        {
            this.myConfigs = myConfigs?.Value;
            this.logger = logger;
            this.eventHubProducerClient = new EventHubProducerClient(this.myConfigs.EventHubConnection, this.myConfigs.EventHubName);
            this.logger.LogInfo($"{nameof(MyEventHubService)} created EventHubProducerClient");
        }

// Implementations of my interface goes here

        public async ValueTask DisposeAsync()
        {
            // Perform async cleanup.
            await DisposeAsyncCore();

            // Suppress finalization.
            GC.SuppressFinalize(this);
        }

        private async Task DisposeAsyncCore()
        {
            await this.eventHubProducerClient.DisposeAsync();
        }
    }
Sibeesh Venu
  • 18,755
  • 12
  • 103
  • 140