private static async Task StartMonitoringAsync(string uri, string key, string collection, CancellationToken ctsToken) { IRemainingWorkEstimator estimator = await CreateEstimatorAsync(uri, key, collection); StringBuilder builder = new StringBuilder(); while (!ctsToken.IsCancellationRequested) { builder.Clear(); IReadOnlyList <RemainingPartitionWork> remainingWork = await estimator.GetEstimatedRemainingWorkPerPartitionAsync(); for (int i = 0; i < remainingWork.Count; i++) { var work = remainingWork[i]; if (i != 0) { builder.Append(","); } builder.AppendFormat(work.PartitionKeyRangeId + ":" + work.RemainingWork); } Console.WriteLine($"### Estimated work: {builder}"); try { await Task.Delay(5000, ctsToken); } catch (TaskCanceledException) { } } }
public CosmosDBTriggerListener(ITriggeredFunctionExecutor executor, string functionId, DocumentCollectionInfo documentCollectionLocation, DocumentCollectionInfo leaseCollectionLocation, ChangeFeedProcessorOptions processorOptions, ICosmosDBService monitoredCosmosDBService, ICosmosDBService leasesCosmosDBService, ILogger logger, IRemainingWorkEstimator workEstimator = null) { this._logger = logger; this._executor = executor; this._functionId = functionId; this._hostName = Guid.NewGuid().ToString(); this._monitorCollection = documentCollectionLocation; this._leaseCollection = leaseCollectionLocation; this._processorOptions = processorOptions; this._monitoredCosmosDBService = monitoredCosmosDBService; this._leasesCosmosDBService = leasesCosmosDBService; this._healthMonitor = new CosmosDBTriggerHealthMonitor(this._logger); this._workEstimator = workEstimator; this._scaleMonitorDescriptor = new ScaleMonitorDescriptor($"{_functionId}-CosmosDBTrigger-{_monitorCollection.DatabaseName}-{_monitorCollection.CollectionName}".ToLower()); }
public async Task <CosmosDBTriggerMetrics> GetMetricsAsync() { int partitionCount = 0; long remainingWork = 0; IReadOnlyList <RemainingPartitionWork> partitionWorkList = null; try { IRemainingWorkEstimator workEstimator = await GetWorkEstimatorAsync(); partitionWorkList = await workEstimator.GetEstimatedRemainingWorkPerPartitionAsync(); partitionCount = partitionWorkList.Count; remainingWork = partitionWorkList.Sum(item => item.RemainingWork); } catch (Exception e) when(e is DocumentClientException || e is InvalidOperationException) { if (!TryHandleDocumentClientException(e)) { _logger.LogWarning("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(errormsg); } return(new CosmosDBTriggerMetrics { Timestamp = DateTime.UtcNow, PartitionCount = partitionCount, RemainingWork = remainingWork }); }
/// <summary> /// Asynchronously checks the current existing leases and calculates an estimate of remaining work per leased partitions. /// </summary> /// <returns>An estimate amount of remaining documents to be processed</returns> public async Task <long> GetEstimatedRemainingWork() { if (this.remainingWorkEstimator == null) { this.remainingWorkEstimator = await this.builder.BuildEstimatorAsync().ConfigureAwait(false); } return(await this.remainingWorkEstimator.GetEstimatedRemainingWork().ConfigureAwait(false)); }
private async Task <IRemainingWorkEstimator> GetWorkEstimatorAsync() { if (_workEstimatorBuilder == null) { _workEstimatorBuilder = new ChangeFeedProcessorBuilder() .WithHostName(this._hostName) .WithFeedDocumentClient(this._monitoredCosmosDBService.GetClient()) .WithLeaseDocumentClient(this._leasesCosmosDBService.GetClient()) .WithFeedCollection(this._monitorCollection) .WithLeaseCollection(this._leaseCollection) .WithProcessorOptions(this._processorOptions) .WithHealthMonitor(this._healthMonitor) .WithObserverFactory(this); } if (_workEstimator == null) { _workEstimator = await _workEstimatorBuilder.BuildEstimatorAsync(); } return(_workEstimator); }