Beispiel #1
0
        private async Task ExecuteOperationsAsync(
            CTLConfig config,
            ILogger logger,
            IMetrics metrics,
            InitializationResult initializationResult,
            ReadWriteQueryPercentage readWriteQueryPercentage,
            CancellationToken cancellationToken)
        {
            logger.LogInformation("Initializing counters and metrics.");
            CounterOptions readSuccessMeter = new CounterOptions {
                Name = "#Read Successful Operations", Context = nameof(WorkloadType.ReadWriteQuery)
            };
            CounterOptions readFailureMeter = new CounterOptions {
                Name = "#Read Unsuccessful Operations", Context = nameof(WorkloadType.ReadWriteQuery)
            };
            CounterOptions writeSuccessMeter = new CounterOptions {
                Name = "#Write Successful Operations", Context = nameof(WorkloadType.ReadWriteQuery)
            };
            CounterOptions writeFailureMeter = new CounterOptions {
                Name = "#Write Unsuccessful Operations", Context = nameof(WorkloadType.ReadWriteQuery)
            };
            CounterOptions querySuccessMeter = new CounterOptions {
                Name = "#Query Successful Operations", Context = nameof(WorkloadType.ReadWriteQuery)
            };
            CounterOptions queryFailureMeter = new CounterOptions {
                Name = "#Query Unsuccessful Operations", Context = nameof(WorkloadType.ReadWriteQuery)
            };

            TimerOptions readLatencyTimer = new TimerOptions
            {
                Name            = "Read latency",
                MeasurementUnit = Unit.Requests,
                DurationUnit    = TimeUnit.Milliseconds,
                RateUnit        = TimeUnit.Seconds,
                Context         = nameof(WorkloadType.ReadWriteQuery),
                Reservoir       = () => new App.Metrics.ReservoirSampling.Uniform.DefaultAlgorithmRReservoir()
            };

            TimerOptions writeLatencyTimer = new TimerOptions
            {
                Name            = "Write latency",
                MeasurementUnit = Unit.Requests,
                DurationUnit    = TimeUnit.Milliseconds,
                RateUnit        = TimeUnit.Seconds,
                Context         = nameof(WorkloadType.ReadWriteQuery),
                Reservoir       = () => new App.Metrics.ReservoirSampling.Uniform.DefaultAlgorithmRReservoir()
            };

            TimerOptions queryLatencyTimer = new TimerOptions
            {
                Name            = "Query latency",
                MeasurementUnit = Unit.Requests,
                DurationUnit    = TimeUnit.Milliseconds,
                RateUnit        = TimeUnit.Seconds,
                Context         = nameof(WorkloadType.ReadWriteQuery),
                Reservoir       = () => new App.Metrics.ReservoirSampling.Uniform.DefaultAlgorithmRReservoir()
            };

            SemaphoreSlim concurrencyControlSemaphore = new SemaphoreSlim(config.Concurrency);
            Stopwatch     stopwatch  = Stopwatch.StartNew();
            int           writeRange = readWriteQueryPercentage.ReadPercentage + readWriteQueryPercentage.WritePercentage;
            long          diagnosticsThresholdDuration = (long)config.DiagnosticsThresholdDurationAsTimespan.TotalMilliseconds;
            List <Task>   operations = new List <Task>((int)config.Operations);

            for (long i = 0; ShouldContinue(stopwatch, i, config); i++)
            {
                long index = (long)i % 100;
                if (index < readWriteQueryPercentage.ReadPercentage)
                {
                    operations.Add(CTLOperationHandler <ItemResponse <Dictionary <string, string> > > .PerformOperationAsync(
                                       semaphoreSlim: concurrencyControlSemaphore,
                                       diagnosticsLoggingThreshold: diagnosticsThresholdDuration,
                                       createTimerContext: () => metrics.Measure.Timer.Time(readLatencyTimer),
                                       resultProducer: new SingleExecutionResultProducer <ItemResponse <Dictionary <string, string> > >(() => this.CreateReadOperation(
                                                                                                                                            operation: i,
                                                                                                                                            containers: initializationResult.Containers,
                                                                                                                                            createdDocumentsPerContainer: this.createdDocuments)),
                                       onSuccess: () => metrics.Measure.Counter.Increment(readSuccessMeter),
                                       onFailure: (Exception ex) =>
                    {
                        metrics.Measure.Counter.Increment(readFailureMeter);
                        logger.LogError(ex, "Failure during read operation");
                    },
                                       logDiagnostics: (ItemResponse <Dictionary <string, string> > response) => logger.LogInformation("Read request took more than latency threshold {0}, diagnostics: {1}", config.DiagnosticsThresholdDuration, response.Diagnostics.ToString()),
                                       cancellationToken: cancellationToken));
                }
                else if (index < writeRange)
                {
                    operations.Add(CTLOperationHandler <ItemResponse <Dictionary <string, string> > > .PerformOperationAsync(
                                       semaphoreSlim: concurrencyControlSemaphore,
                                       diagnosticsLoggingThreshold: diagnosticsThresholdDuration,
                                       createTimerContext: () => metrics.Measure.Timer.Time(writeLatencyTimer),
                                       resultProducer: new SingleExecutionResultProducer <ItemResponse <Dictionary <string, string> > >(() => this.CreateWriteOperation(
                                                                                                                                            operation: i,
                                                                                                                                            containers: initializationResult.Containers,
                                                                                                                                            isContentResponseOnWriteEnabled: config.IsContentResponseOnWriteEnabled)),
                                       onSuccess: () => metrics.Measure.Counter.Increment(writeSuccessMeter),
                                       onFailure: (Exception ex) =>
                    {
                        metrics.Measure.Counter.Increment(writeFailureMeter);
                        logger.LogError(ex, "Failure during write operation");
                    },
                                       logDiagnostics: (ItemResponse <Dictionary <string, string> > response) => logger.LogInformation("Write request took more than latency threshold {0}, diagnostics: {1}", config.DiagnosticsThresholdDuration, response.Diagnostics.ToString()),
                                       cancellationToken: cancellationToken));
                }
                else
                {
                    operations.Add(CTLOperationHandler <FeedResponse <Dictionary <string, string> > > .PerformOperationAsync(
                                       semaphoreSlim: concurrencyControlSemaphore,
                                       diagnosticsLoggingThreshold: diagnosticsThresholdDuration,
                                       createTimerContext: () => metrics.Measure.Timer.Time(queryLatencyTimer),
                                       resultProducer: new IteratorResultProducer <Dictionary <string, string> >(this.CreateQueryOperation(
                                                                                                                     operation: i,
                                                                                                                     containers: initializationResult.Containers)),
                                       onSuccess: () => metrics.Measure.Counter.Increment(querySuccessMeter),
                                       onFailure: (Exception ex) =>
                    {
                        metrics.Measure.Counter.Increment(queryFailureMeter);
                        logger.LogError(ex, "Failure during query operation");
                    },
                                       logDiagnostics: (FeedResponse <Dictionary <string, string> > response) => logger.LogInformation("Query request took more than latency threshold {0}, diagnostics: {1}", config.DiagnosticsThresholdDuration, response.Diagnostics.ToString()),
                                       cancellationToken: cancellationToken));
                }
            }

            await Task.WhenAll(operations);

            stopwatch.Stop();
            logger.LogInformation("[{0}] operations performed in [{1}] seconds.",
                                  config.Operations, stopwatch.Elapsed.TotalSeconds);
        }
        private async Task ExecuteOperationsAsync(
            CTLConfig config,
            ILogger logger,
            IMetrics metrics,
            string loggingContextIdentifier,
            InitializationResult initializationResult,
            ReadWriteQueryPercentage readWriteQueryPercentage,
            CancellationToken cancellationToken)
        {
            logger.LogInformation("Initializing counters and metrics.");
            CounterOptions readSuccessMeter = new CounterOptions {
                Name = "#Read Successful Operations", Context = loggingContextIdentifier
            };
            CounterOptions readFailureMeter = new CounterOptions {
                Name = "#Read Unsuccessful Operations", Context = loggingContextIdentifier
            };
            CounterOptions writeSuccessMeter = new CounterOptions {
                Name = "#Write Successful Operations", Context = loggingContextIdentifier
            };
            CounterOptions writeFailureMeter = new CounterOptions {
                Name = "#Write Unsuccessful Operations", Context = loggingContextIdentifier
            };
            CounterOptions querySuccessMeter = new CounterOptions {
                Name = "#Query Successful Operations", Context = loggingContextIdentifier
            };
            CounterOptions queryFailureMeter = new CounterOptions {
                Name = "#Query Unsuccessful Operations", Context = loggingContextIdentifier
            };

            TimerOptions readLatencyTimer = new TimerOptions
            {
                Name            = "Read latency",
                MeasurementUnit = Unit.Requests,
                DurationUnit    = TimeUnit.Milliseconds,
                RateUnit        = TimeUnit.Seconds,
                Context         = loggingContextIdentifier,
                Reservoir       = () => new App.Metrics.ReservoirSampling.Uniform.DefaultAlgorithmRReservoir()
            };

            TimerOptions writeLatencyTimer = new TimerOptions
            {
                Name            = "Write latency",
                MeasurementUnit = Unit.Requests,
                DurationUnit    = TimeUnit.Milliseconds,
                RateUnit        = TimeUnit.Seconds,
                Context         = loggingContextIdentifier,
                Reservoir       = () => new App.Metrics.ReservoirSampling.Uniform.DefaultAlgorithmRReservoir()
            };

            TimerOptions queryLatencyTimer = new TimerOptions
            {
                Name            = "Query latency",
                MeasurementUnit = Unit.Requests,
                DurationUnit    = TimeUnit.Milliseconds,
                RateUnit        = TimeUnit.Seconds,
                Context         = loggingContextIdentifier,
                Reservoir       = () => new App.Metrics.ReservoirSampling.Uniform.DefaultAlgorithmRReservoir()
            };

            SemaphoreSlim concurrencyControlSemaphore = new SemaphoreSlim(config.Concurrency);
            Stopwatch     stopwatch  = Stopwatch.StartNew();
            int           writeRange = readWriteQueryPercentage.ReadPercentage + readWriteQueryPercentage.WritePercentage;
            List <Task>   operations = new List <Task>();

            for (long i = 0; ShouldContinue(stopwatch, i, config); i++)
            {
                await concurrencyControlSemaphore.WaitAsync(cancellationToken);

                long index = i % 100;
                if (index < readWriteQueryPercentage.ReadPercentage)
                {
                    operations.Add(CTLOperationHandler <ItemResponse <Dictionary <string, string> > > .PerformOperationAsync(
                                       createTimerContext: () => metrics.Measure.Timer.Time(readLatencyTimer),
                                       resultProducer: new SingleExecutionResultProducer <ItemResponse <Dictionary <string, string> > >(() => this.CreateReadOperation(
                                                                                                                                            operation: i,
                                                                                                                                            partitionKeyAttributeName: config.CollectionPartitionKey,
                                                                                                                                            containers: initializationResult.Containers,
                                                                                                                                            createdDocumentsPerContainer: this.createdDocuments)),
                                       onSuccess: () =>
                    {
                        concurrencyControlSemaphore.Release();
                        metrics.Measure.Counter.Increment(readSuccessMeter);
                    },
                                       onFailure: (Exception ex) =>
                    {
                        concurrencyControlSemaphore.Release();
                        metrics.Measure.Counter.Increment(readFailureMeter);
                        Utils.LogError(logger, loggingContextIdentifier, ex, "Failure during read operation");
                    },
                                       logDiagnostics: (ItemResponse <Dictionary <string, string> > response, TimeSpan latency) => Utils.LogDiagnostics(
                                           logger: logger,
                                           operationName: "Read",
                                           timerContextLatency: latency,
                                           config: config,
                                           cosmosDiagnostics: response.Diagnostics)));
                }
                else if (index < writeRange)
                {
                    operations.Add(CTLOperationHandler <ItemResponse <Dictionary <string, string> > > .PerformOperationAsync(
                                       createTimerContext: () => metrics.Measure.Timer.Time(writeLatencyTimer),
                                       resultProducer: new SingleExecutionResultProducer <ItemResponse <Dictionary <string, string> > >(() => this.CreateWriteOperation(
                                                                                                                                            operation: i,
                                                                                                                                            partitionKeyAttributeName: config.CollectionPartitionKey,
                                                                                                                                            containers: initializationResult.Containers,
                                                                                                                                            isContentResponseOnWriteEnabled: config.IsContentResponseOnWriteEnabled)),
                                       onSuccess: () =>
                    {
                        concurrencyControlSemaphore.Release();
                        metrics.Measure.Counter.Increment(writeSuccessMeter);
                    },
                                       onFailure: (Exception ex) =>
                    {
                        concurrencyControlSemaphore.Release();
                        metrics.Measure.Counter.Increment(writeFailureMeter);
                        Utils.LogError(logger, loggingContextIdentifier, ex, "Failure during write operation");
                    },
                                       logDiagnostics: (ItemResponse <Dictionary <string, string> > response, TimeSpan latency) => Utils.LogDiagnostics(
                                           logger: logger,
                                           operationName: "Write",
                                           timerContextLatency: latency,
                                           config: config,
                                           cosmosDiagnostics: response.Diagnostics)));
                }
                else
                {
                    operations.Add(CTLOperationHandler <FeedResponse <Dictionary <string, string> > > .PerformOperationAsync(
                                       createTimerContext: () => metrics.Measure.Timer.Time(queryLatencyTimer),
                                       resultProducer: new IteratorResultProducer <Dictionary <string, string> >(this.CreateQueryOperation(
                                                                                                                     operation: i,
                                                                                                                     containers: initializationResult.Containers)),
                                       onSuccess: () =>
                    {
                        concurrencyControlSemaphore.Release();
                        metrics.Measure.Counter.Increment(querySuccessMeter);
                    },
                                       onFailure: (Exception ex) =>
                    {
                        concurrencyControlSemaphore.Release();
                        metrics.Measure.Counter.Increment(queryFailureMeter);
                        Utils.LogError(logger, loggingContextIdentifier, ex, "Failure during query operation");
                    },
                                       logDiagnostics: (FeedResponse <Dictionary <string, string> > response, TimeSpan latency) => Utils.LogDiagnostics(
                                           logger: logger,
                                           operationName: "Query",
                                           timerContextLatency: latency,
                                           config: config,
                                           cosmosDiagnostics: response.Diagnostics)));
                }
            }

            await Task.WhenAll(operations);

            stopwatch.Stop();
            logger.LogInformation("[{0}] operations performed in [{1}] seconds.",
                                  operations.Count, stopwatch.Elapsed.TotalSeconds);
        }