public static ReserveOrReleaseCapacityRecord CaptureDestinationRecord(
            Guid subscriptionId,
            Guid resourceId,
            DateTimeOffset dateTime,
            string meter,
            int amount,
            string reason,
            IDictionary <string, string> internalContext,
            IDictionary <string, string> subOwnerContext,
            string eventMessageTemplate)
        {
            var mockedDestination = new Mock <IReservedCapacityMetricsDestination>();

            var capturedInternalContext = new Dictionary <string, string>();

            mockedDestination
            .Setup(d => d.ForInternalContext(It.IsAny <string>(), It.IsAny <string>()))
            .Callback((string propertyName, string value) => capturedInternalContext.Add(propertyName, value))
            .Returns(mockedDestination.Object);

            var capturedSubOwnerContext = new Dictionary <string, string>();

            mockedDestination
            .Setup(d => d.ForSubscriptionOwnerContext(It.IsAny <string>(), It.IsAny <string>()))
            .Callback((string propertyName, string value) => capturedSubOwnerContext.Add(propertyName, value))
            .Returns(mockedDestination.Object);

            var capturedSubscriptionId = default(Guid);
            var capturedResourceId     = default(Guid);
            var capturedDateTime       = default(DateTimeOffset);
            var capturedMeter          = default(string);
            var capturedAmount         = default(int);
            var capturedReason         = default(string);

            mockedDestination
            .Setup(d => d.ReserveCapacity(It.IsAny <Guid>(), It.IsAny <Guid>(), It.IsAny <DateTimeOffset>(), It.IsAny <string>(), It.IsAny <int>(), It.IsAny <string>()))
            .Callback((Guid callbackSubscriptionId, Guid callbackResourceId, DateTimeOffset callbackDateTime, string callbackMeter, int callbackAmount, string callbackReason) =>
                      (capturedSubscriptionId, capturedResourceId, capturedDateTime, capturedMeter, capturedAmount, capturedReason) =
                          (callbackSubscriptionId, callbackResourceId, callbackDateTime, callbackMeter, callbackAmount, callbackReason));

            mockedDestination
            .Setup(d => d.ReleaseCapacity(It.IsAny <Guid>(), It.IsAny <Guid>(), It.IsAny <DateTimeOffset>(), It.IsAny <string>(), It.IsAny <int>(), It.IsAny <string>()))
            .Callback((Guid callbackSubscriptionId, Guid callbackResourceId, DateTimeOffset callbackDateTime, string callbackMeter, int callbackAmount, string callbackReason) =>
                      (capturedSubscriptionId, capturedResourceId, capturedDateTime, capturedMeter, capturedAmount, capturedReason) =
                          (callbackSubscriptionId, callbackResourceId, callbackDateTime, callbackMeter, callbackAmount, callbackReason));

            IReservedCapacityMetrics reservedCapacity = new ReservedCapacityMetrics(mockedDestination.Object);

            // Act
            reservedCapacity = internalContext?.Aggregate(reservedCapacity, (client, kvp) => client.ForInternalContext(kvp.Key, kvp.Value)) ?? reservedCapacity;
            reservedCapacity = subOwnerContext?.Aggregate(reservedCapacity, (client, kvp) => client.ForSubscriptionOwnerContext(kvp.Key, kvp.Value)) ?? reservedCapacity;

            if (eventMessageTemplate.StartsWith("Increased", StringComparison.InvariantCultureIgnoreCase))
            {
                reservedCapacity.Increase(subscriptionId, resourceId, dateTime, meter, amount, reason);
            }
            else if (eventMessageTemplate.StartsWith("Decreased", StringComparison.InvariantCultureIgnoreCase))
            {
                reservedCapacity.Decrease(subscriptionId, resourceId, dateTime, meter, amount, reason);
            }
            else
            {
                throw new Exception($"Unhandled message template: {eventMessageTemplate}");
            }

            return(new ReserveOrReleaseCapacityRecord(
                       eventMessageTemplate: eventMessageTemplate,
                       subscriptionId: capturedSubscriptionId,
                       resourceId: capturedResourceId,
                       dateTime: capturedDateTime,
                       meter: capturedMeter,
                       amount: capturedAmount,
                       reason: capturedReason,
                       internalContext: capturedInternalContext,
                       subscriptionOwnerContext: capturedSubOwnerContext));
        }
        private static void RecordReservedAndReleaseCapacity(
            IAudit auditClient,
            int numberOfEvents,
            int numberOfThreads,
            string eventHubsTopic,
            string eventHubsHost,
            AppConfigMeterData meterData,
            AppConfigReservedAndReleaseCapacityData data)
        {
            var reservedCapacityDestination = new AuditClientReservedCapacityMetricsDestination(auditClient);

            var groupId        = Guid.NewGuid();
            var subscriptionId = meterData.SubscriptionId;
            var resourceId     = meterData.ResourceId;
            var meter          = meterData.Meter;

            Log.Information(
                "Sending {NumberOfEvents} {EventKind} events ({NumberOfThreads} threads) in GroupId {GroupId} to the {EventHubsTopic} topic on EventHubs {EventHubsHost}",
                numberOfEvents,
                ConsumptionKind.ReserveAndReleaseCapacity,
                numberOfThreads,
                groupId,
                eventHubsTopic,
                eventHubsHost);

            var reservedCapacity = new ReservedCapacityMetrics(reservedCapacityDestination);

            using (Operation.Time(
                       "Sending {NumberOfEvents} {EventKind} events ({NumberOfThreads} threads) in GroupId {GroupId} to the {EventHubsTopic} topic on EventHubs {EventHubsHost}",
                       numberOfEvents,
                       ConsumptionKind.ReserveAndReleaseCapacity,
                       numberOfThreads,
                       groupId,
                       eventHubsTopic,
                       eventHubsHost))
            {
                Enumerable
                .Range(0, numberOfEvents)
                .AsParallel()
                .WithDegreeOfParallelism(degreeOfParallelism: numberOfThreads)
                .WithExecutionMode(ParallelExecutionMode.ForceParallelism)
                .Select(eventNumber =>
                {
                    var contextReservedCapacity = reservedCapacity
                                                  .ForInternalContext("GroupId", $"{groupId}")
                                                  .ForInternalContext("EventNumber", $"{eventNumber}");

                    contextReservedCapacity
                    .Increase(
                        subscriptionId: subscriptionId,
                        resourceId: resourceId,
                        meter: meter,
                        amount: data.CapacityAmount,
                        dateTime: data.ReservedDateTime);

                    contextReservedCapacity
                    .Decrease(
                        subscriptionId: subscriptionId,
                        resourceId: resourceId,
                        meter: meter,
                        amount: data.CapacityAmount,
                        dateTime: data.ReservedDateTime);

                    return(eventNumber);
                })
                .ToArray();
            }
        }