public async Task GetMetricsAsync()

in src/WebJobs.Extensions.CosmosDB/Trigger/CosmosDBMetricsProvider.cs [45:142]


        public async Task<CosmosDBTriggerMetrics> GetMetricsAsync()
        {
            int partitionCount = 0;
            long remainingWork = 0;

            try
            {
                List<ChangeFeedProcessorState> partitionWorkList = new List<ChangeFeedProcessorState>();
                ChangeFeedEstimator estimator = _monitoredContainer.GetChangeFeedEstimator(_processorName, _leaseContainer);
                using (FeedIterator<ChangeFeedProcessorState> iterator = estimator.GetCurrentStateIterator())
                {
                    while (iterator.HasMoreResults)
                    {
                        FeedResponse<ChangeFeedProcessorState> response = await iterator.ReadNextAsync();
                        partitionWorkList.AddRange(response);
                    }
                }

                partitionCount = partitionWorkList.Count;
                if (partitionCount == 0)
                {
                    partitionCount = 1;
                    remainingWork = 1;
                    _logger.LogWarning(Events.OnScaling, "PartitionCount is 0, the lease container exists but it has not been initialized, scale out to 1 and wait for the first execution.");
                }
                else
                {
                    remainingWork = partitionWorkList.Sum(item => item.EstimatedLag);
                }
            }
            catch (CosmosException cosmosException) when (cosmosException.StatusCode == HttpStatusCode.Gone)
            {
                // Temporary handling of split issue described in https://github.com/Azure/azure-cosmos-dotnet-v3/issues/4285
                // This happens if the main instance is not running, potentially using Consumption Plan
                // In this case, we return a positive value to make the Scale Controller consider spinning at least a single instance
                partitionCount = 1;
                remainingWork = 1;
            }
            catch (CosmosException cosmosException) when (cosmosException.StatusCode == HttpStatusCode.NotFound 
                && _assignWorkerOnNotFoundCount < _maxAssignWorkerOnNotFoundCount)
            {
                // An exception "Not found" may indicate that the lease container does not exist.
                // We vote to scale out, assign a worker to create the lease container.
                // However, it could also signal an issue with the monitoring container configuration.
                // As a result, we make a limited number of attempts to create the lease container.
                _assignWorkerOnNotFoundCount++;
                _logger.LogWarning(Events.OnScaling, $"Possible non-exiting lease container detected. Trying to create the lease container, attempt '{_assignWorkerOnNotFoundCount}'",
                    cosmosException.GetType().ToString(), cosmosException.Message);
                partitionCount = 1;
                remainingWork = 1;
            }
            catch (Exception e) when (e is CosmosException || e is InvalidOperationException)
            {
                if (!TryHandleCosmosException(e))
                {
                    _logger.LogWarning(Events.OnScaling, "Unable to handle {0}: {1}", e.GetType().ToString(), e.Message);
                    if (e is InvalidOperationException)
                    {
                        throw;
                    }
                }
            }
            catch (System.Net.Http.HttpRequestException e)
            {
                string errormsg;

                var webException = e.InnerException as WebException;
                if (webException != null &&
                    webException.Status == WebExceptionStatus.ProtocolError)
                {
                    string statusCode = ((HttpWebResponse)webException.Response).StatusCode.ToString();
                    string statusDesc = ((HttpWebResponse)webException.Response).StatusDescription;
                    errormsg = string.Format("CosmosDBTrigger status {0}: {1}.", statusCode, statusDesc);
                }
                else if (webException != null &&
                    webException.Status == WebExceptionStatus.NameResolutionFailure)
                {
                    errormsg = string.Format("CosmosDBTrigger Exception message: {0}.", webException.Message);
                }
                else
                {
                    errormsg = e.ToString();
                }

                _logger.LogWarning(Events.OnScaling, errormsg);
            }
            catch (Exception e)
            {
                _logger.LogWarning(Events.OnScaling, "Exception occurred while obtaining metrics for CosmosDB {0}: {1}.", e.GetType().ToString(), e.ToString());
            }

            return new CosmosDBTriggerMetrics
            {
                Timestamp = DateTime.UtcNow,
                PartitionCount = partitionCount,
                RemainingWork = remainingWork
            };
        }