public override async Task UpdateProvisionAsync(
            IAutoscalingConfigurationSet configuration,
            DynamoDbThroughput updated,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            cancellationToken.ThrowIfCancellationRequested();

            await ThroughputClient.SetGlobalSecondaryIndexThroughputLevelAsync(
                tableName, indexName, updated.ReadThroughput, updated.WriteThroughput, cancellationToken)
                .ConfigureAwait(false);
        }
        public async Task ProvisionAsync(
            IAutoscalingConfigurationSet configuration,
            DynamoDbThroughput current,
            DynamoDbThroughput updated,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            cancellationToken.ThrowIfCancellationRequested();

            var demoMode = configuration.DemoMode.GetValueOrDefault(true);
            var increaseInterval = TimeSpan.FromMinutes(configuration.IncreaseInterval.GetValueOrDefault(DefaultIncreaseInterval));
            var decreaseInterval = TimeSpan.FromMinutes(configuration.DecreaseInterval.GetValueOrDefault(DefaultDecreaseInterval));
            var readsEnabled = configuration.Reads.EnableAutoscaling.GetValueOrDefault(true);
            var writesEnabled = configuration.Writes.EnableAutoscaling.GetValueOrDefault(true);

            var shouldUpdateReads = ShouldUpdate(configuration.EntityName, "reads", current.ReadThroughput,
                updated.ReadThroughput, readsEnabled, demoMode, current.LastDecreaseAt, current.LastIncreaseAt, increaseInterval, decreaseInterval);
            if (!shouldUpdateReads)
                updated.ReadThroughput = current.ReadThroughput;
            
            var shouldUpdateWrites = ShouldUpdate(configuration.EntityName, "writes", current.WriteThroughput,
                updated.WriteThroughput, writesEnabled, demoMode, current.LastDecreaseAt, current.LastIncreaseAt, increaseInterval, decreaseInterval);
            if (!shouldUpdateWrites)
                updated.WriteThroughput = current.WriteThroughput;

            if (shouldUpdateReads || shouldUpdateWrites)
            {
                try
                {
                    await UpdateProvisionAsync(configuration, updated, cancellationToken);

                    StructuredLogger.Warning(
                        "{EntityName}: updating reads {CurrentReadThroughput}->{UpdatedReadThroughput}, writes {CurrentWriteThroughput}->{UpdatedWriteThroughput}",
                        configuration.EntityName, current.ReadThroughput, updated.ReadThroughput, current.WriteThroughput, updated.WriteThroughput);
                }
                catch (ResourceInUseException)
                {
                    StructuredLogger.Information("{EntityName}: still updating provision", configuration.EntityName);
                }
                catch (LimitExceededException)
                {
                    StructuredLogger.Information("{EntityName}: reached maximum decreases per day", configuration.EntityName);
                }
            }
            else
            {
                StructuredLogger.Information(
                    "{EntityName}: no changes reads {CurrentReadThroughput}, writes {CurrentWriteThroughput}",
                    configuration.EntityName, current.ReadThroughput, current.WriteThroughput);
            }
        }
 public abstract Task UpdateProvisionAsync(
     IAutoscalingConfigurationSet configuration,
     DynamoDbThroughput current,
     CancellationToken cancellationToken = default(CancellationToken));
        private void LogStats(AutoscalingConfigurationSet configuration, DynamoDbThroughput throughput, DynamoDbMetrics metrics)
        {
            var entityName = configuration.EntityName;
            var readsProvisioned = throughput.ReadThroughput;
            var writesProvisioned = throughput.WriteThroughput;
            var readsConsumed = metrics.ConsumedReadCapacityUnits;
            var writesConsumed = metrics.ConsumedWriteCapacityUnits;
            var readsPercent = readsConsumed.ToPercentage(readsProvisioned);
            var writesPercent = writesConsumed.ToPercentage(writesProvisioned);

            structuredLogger.Information(
                "{EntityName}:reads {ReadsConsumed}/{ReadsProvisioned},{ReadsPercent}%,->{ReadConsumptionDirection},{ReadThrottleEvents}",
                entityName, readsConsumed, readsProvisioned, readsPercent, metrics.ReadConsumptionDirection.ToString("F4"), metrics.ReadThrottleEvents);

            structuredLogger.Information(
                "{EntityName}:writes {WritesConsumed}/{WritesProvisioned},{WritesPercent}%,->{WriteConsumptionDirection},{WriteThrottleEvents}",
                entityName, writesConsumed, writesProvisioned, writesPercent, metrics.WriteConsumptionDirection.ToString("F4"), metrics.WriteThrottleEvents);
        }