public override async Task <ResponseMessage> ReadNextAsync(CancellationToken cancellationToken = default) { CosmosDiagnosticsContext diagnostics = CosmosDiagnosticsContext.Create(this.requestOptions); using (diagnostics.GetOverallScope()) { // This catches exception thrown by the pipeline and converts it to QueryResponse QueryResponseCore responseCore = await this.cosmosQueryExecutionContext.ExecuteNextAsync(cancellationToken); // This swaps the diagnostics in the context. This shows all the page reads between the previous ReadNextAsync and the current ReadNextAsync diagnostics.AddDiagnosticsInternal(this.cosmosQueryContext.GetAndResetDiagnostics()); if (responseCore.IsSuccess) { List <CosmosElement> decryptedCosmosElements = null; if (this.clientContext.ClientOptions.Encryptor != null) { decryptedCosmosElements = await this.GetDecryptedElementResponseAsync(responseCore.CosmosElements, diagnostics, cancellationToken); } return(QueryResponse.CreateSuccess( result: decryptedCosmosElements ?? responseCore.CosmosElements, count: responseCore.CosmosElements.Count, responseLengthBytes: responseCore.ResponseLengthBytes, diagnostics: diagnostics, serializationOptions: this.cosmosSerializationFormatOptions, responseHeaders: new CosmosQueryResponseMessageHeaders( responseCore.ContinuationToken, responseCore.DisallowContinuationTokenMessage, this.cosmosQueryContext.ResourceTypeEnum, this.cosmosQueryContext.ContainerResourceId) { RequestCharge = responseCore.RequestCharge, ActivityId = responseCore.ActivityId, SubStatusCode = responseCore.SubStatusCode ?? Documents.SubStatusCodes.Unknown })); } if (responseCore.CosmosException != null) { return(responseCore.CosmosException.ToCosmosResponseMessage(null)); } return(QueryResponse.CreateFailure( statusCode: responseCore.StatusCode, cosmosException: responseCore.CosmosException, requestMessage: null, diagnostics: diagnostics, responseHeaders: new CosmosQueryResponseMessageHeaders( responseCore.ContinuationToken, responseCore.DisallowContinuationTokenMessage, this.cosmosQueryContext.ResourceTypeEnum, this.cosmosQueryContext.ContainerResourceId) { RequestCharge = responseCore.RequestCharge, ActivityId = responseCore.ActivityId, SubStatusCode = responseCore.SubStatusCode ?? Documents.SubStatusCodes.Unknown, })); } }
public static QueryResponseCore CreateQueryResponse( IList <ToDoItem> items, bool isOrderByQuery, string continuationToken, string collectionRid) { MemoryStream memoryStream; string json; if (isOrderByQuery) { memoryStream = SerializeForOrderByQuery(items); using (StreamReader sr = new StreamReader(SerializeForOrderByQuery(items))) { json = sr.ReadToEnd(); } } else { memoryStream = (MemoryStream)MockCosmosUtil.Serializer.ToStream <IList <ToDoItem> >(items); } long responseLengthBytes = memoryStream.Length; IJsonNavigator jsonNavigator = JsonNavigator.Create(memoryStream.ToArray()); IJsonNavigatorNode jsonNavigatorNode = jsonNavigator.GetRootNode(); CosmosArray cosmosArray = CosmosArray.Create(jsonNavigator, jsonNavigatorNode); CosmosDiagnosticsContext diagnosticsContext = new CosmosDiagnosticsContext(); diagnosticsContext.AddDiagnosticsInternal(new PointOperationStatistics( activityId: Guid.NewGuid().ToString(), statusCode: HttpStatusCode.OK, subStatusCode: SubStatusCodes.Unknown, requestCharge: 4, errorMessage: null, method: HttpMethod.Post, requestUri: new Uri("http://localhost.com"), requestSessionToken: null, responseSessionToken: null, clientSideRequestStatistics: null)); IReadOnlyCollection <QueryPageDiagnostics> diagnostics = new List <QueryPageDiagnostics>() { new QueryPageDiagnostics("0", "SomeQueryMetricText", "SomeIndexUtilText", diagnosticsContext, new SchedulingStopwatch()) }; QueryResponseCore message = QueryResponseCore.CreateSuccess( result: cosmosArray, requestCharge: 4, activityId: Guid.NewGuid().ToString(), diagnostics: diagnostics, responseLengthBytes: responseLengthBytes, disallowContinuationTokenMessage: null, continuationToken: continuationToken); return(message); }
public override async Task <ResponseMessage> ReadNextAsync(CancellationToken cancellationToken = default) { CosmosDiagnosticsContext diagnostics = new CosmosDiagnosticsContext(); using (diagnostics.CreateScope("QueryReadNextAsync")) { // This catches exception thrown by the pipeline and converts it to QueryResponse QueryResponseCore responseCore = await this.cosmosQueryExecutionContext.ExecuteNextAsync(cancellationToken); CosmosQueryContext cosmosQueryContext = this.cosmosQueryContext; foreach (QueryPageDiagnostics queryPage in responseCore.Diagnostics) { diagnostics.Summary.Append(queryPage.DiagnosticsContext.Summary); diagnostics.AddDiagnosticsInternal(queryPage); } QueryResponse queryResponse; if (responseCore.IsSuccess) { queryResponse = QueryResponse.CreateSuccess( result: responseCore.CosmosElements, count: responseCore.CosmosElements.Count, responseLengthBytes: responseCore.ResponseLengthBytes, diagnostics: diagnostics, serializationOptions: this.cosmosSerializationFormatOptions, responseHeaders: new CosmosQueryResponseMessageHeaders( responseCore.ContinuationToken, responseCore.DisallowContinuationTokenMessage, cosmosQueryContext.ResourceTypeEnum, cosmosQueryContext.ContainerResourceId) { RequestCharge = responseCore.RequestCharge, ActivityId = responseCore.ActivityId, SubStatusCode = responseCore.SubStatusCode ?? Documents.SubStatusCodes.Unknown }); } else { queryResponse = QueryResponse.CreateFailure( statusCode: responseCore.StatusCode, error: null, errorMessage: responseCore.ErrorMessage, requestMessage: null, diagnostics: diagnostics, responseHeaders: new CosmosQueryResponseMessageHeaders( responseCore.ContinuationToken, responseCore.DisallowContinuationTokenMessage, cosmosQueryContext.ResourceTypeEnum, cosmosQueryContext.ContainerResourceId) { RequestCharge = responseCore.RequestCharge, ActivityId = responseCore.ActivityId, SubStatusCode = responseCore.SubStatusCode ?? Documents.SubStatusCodes.Unknown }); } return(queryResponse); } }
public void ValidateDiagnosticsAppendContext() { CosmosDiagnosticsContext cosmosDiagnostics = CosmosDiagnosticsContext.Create(); // Test all the different operations on diagnostics context using (cosmosDiagnostics.CreateScope("ValidateScope")) { Thread.Sleep(TimeSpan.FromSeconds(2)); } cosmosDiagnostics.SetSdkUserAgent("MyCustomUserAgentString"); CosmosDiagnosticsContext cosmosDiagnostics2 = CosmosDiagnosticsContext.Create(); using (cosmosDiagnostics.CreateScope("CosmosDiagnostics2Scope")) { Thread.Sleep(TimeSpan.FromMilliseconds(100)); } cosmosDiagnostics2.AddDiagnosticsInternal(cosmosDiagnostics); string diagnostics = cosmosDiagnostics2.ToString(); Assert.IsTrue(diagnostics.Contains("MyCustomUserAgentString")); Assert.IsTrue(diagnostics.Contains("ValidateScope")); Assert.IsTrue(diagnostics.Contains("CosmosDiagnostics2Scope")); }
private (Func <string, Task <TryCatch <IDocumentQueryExecutionComponent> > >, QueryResponseCore) SetupBaseContextToVerifyFailureScenario() { CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(); diagnosticsContext.AddDiagnosticsInternal(new PointOperationStatistics( Guid.NewGuid().ToString(), System.Net.HttpStatusCode.Unauthorized, subStatusCode: SubStatusCodes.PartitionKeyMismatch, requestCharge: 4, errorMessage: null, method: HttpMethod.Post, requestUri: new Uri("http://localhost.com"), requestSessionToken: null, responseSessionToken: null, clientSideRequestStatistics: null)); IReadOnlyCollection <QueryPageDiagnostics> diagnostics = new List <QueryPageDiagnostics>() { new QueryPageDiagnostics( "0", "SomeQueryMetricText", "SomeIndexUtilText", diagnosticsContext, new SchedulingStopwatch()) }; QueryResponseCore failure = QueryResponseCore.CreateFailure( System.Net.HttpStatusCode.Unauthorized, SubStatusCodes.PartitionKeyMismatch, new CosmosException( statusCodes: HttpStatusCode.Unauthorized, message: "Random error message", subStatusCode: default,
public static (QueryResponseCore queryResponse, IList <ToDoItem> items) Create( string itemIdPrefix, string continuationToken, string collectionRid, int itemCount = 50) { // Use -1 to represent a split response if (itemCount == QueryResponseMessageFactory.SPLIT) { return(CreateSplitResponse(collectionRid), new List <ToDoItem>().AsReadOnly()); } IList <ToDoItem> items = ToDoItem.CreateItems(itemCount, itemIdPrefix); MemoryStream memoryStream = (MemoryStream)MockCosmosUtil.Serializer.ToStream <IList <ToDoItem> >(items); long responseLengthBytes = memoryStream.Length; IJsonNavigator jsonNavigator = JsonNavigator.Create(memoryStream.ToArray()); IJsonNavigatorNode jsonNavigatorNode = jsonNavigator.GetRootNode(); CosmosArray cosmosArray = CosmosArray.Create(jsonNavigator, jsonNavigatorNode); double requestCharge = 42; string activityId = Guid.NewGuid().ToString(); CosmosDiagnosticsContext diagnosticsContext = new CosmosDiagnosticsContext(); diagnosticsContext.AddDiagnosticsInternal(new PointOperationStatistics( activityId: Guid.NewGuid().ToString(), statusCode: HttpStatusCode.OK, subStatusCode: SubStatusCodes.Unknown, requestCharge: requestCharge, errorMessage: null, method: HttpMethod.Post, requestUri: new Uri("http://localhost.com"), requestSessionToken: null, responseSessionToken: null, clientSideRequestStatistics: null)); IReadOnlyCollection <QueryPageDiagnostics> diagnostics = new List <QueryPageDiagnostics>() { new QueryPageDiagnostics("0", "SomeQueryMetricText", "SomeIndexUtilText", diagnosticsContext, new SchedulingStopwatch()) }; QueryResponseCore message = QueryResponseCore.CreateSuccess( result: cosmosArray, continuationToken: continuationToken, disallowContinuationTokenMessage: null, activityId: activityId, requestCharge: requestCharge, diagnostics: diagnostics, responseLengthBytes: responseLengthBytes); return(message, items); }
/// <summary> /// Get the next set of results from the cosmos service /// </summary> /// <param name="cancellationToken">(Optional) <see cref="CancellationToken"/> representing request cancellation.</param> /// <returns>A query response from cosmos service</returns> public override async Task <ResponseMessage> ReadNextAsync(CancellationToken cancellationToken = default) { CosmosDiagnosticsContext diagnostics = CosmosDiagnosticsContext.Create(this.changeFeedOptions); using (diagnostics.GetOverallScope()) { diagnostics.AddDiagnosticsInternal( new FeedRangeStatistics( this.changeFeedStartFrom.Accept(ChangeFeedRangeExtractor.Singleton))); if (!this.lazyContainerRid.ValueInitialized) { using (diagnostics.CreateScope("InitializeContainerResourceId")) { TryCatch <string> tryInitializeContainerRId = await this.lazyContainerRid.GetValueAsync(cancellationToken); if (!tryInitializeContainerRId.Succeeded) { if (!(tryInitializeContainerRId.Exception.InnerException is CosmosException cosmosException)) { throw new InvalidOperationException("Failed to convert to CosmosException."); } return(cosmosException.ToCosmosResponseMessage( new RequestMessage( method: null, requestUriString: null, diagnosticsContext: diagnostics))); } } using (diagnostics.CreateScope("InitializeContinuation")) { await this.InitializeFeedContinuationAsync(cancellationToken); } TryCatch validateContainer = this.FeedRangeContinuation.ValidateContainer(this.lazyContainerRid.Result.Result); if (!validateContainer.Succeeded) { return(CosmosExceptionFactory .CreateBadRequestException( message: validateContainer.Exception.InnerException.Message, innerException: validateContainer.Exception.InnerException, diagnosticsContext: diagnostics) .ToCosmosResponseMessage( new RequestMessage( method: null, requestUriString: null, diagnosticsContext: diagnostics))); } } return(await this.ReadNextInternalAsync(diagnostics, cancellationToken)); } }
public void TestCosmosDiagnosticScope() { (BackendMetricsExtractor.ParseFailureReason parseFailureReason, BackendMetrics extractedBackendMetrics)notFoundResult = MockCosmosDiagnosticScope.Accept(BackendMetricsExtractor.Singleton); Assert.AreEqual(BackendMetricsExtractor.ParseFailureReason.MetricsNotFound, notFoundResult.parseFailureReason); CosmosDiagnosticsContext contextWithQueryMetrics = CosmosDiagnosticsContext.Create(); contextWithQueryMetrics.AddDiagnosticsInternal(MockQueryPageDiagnostics); (BackendMetricsExtractor.ParseFailureReason parseFailureReason, BackendMetrics extractedBackendMetrics)foundResult = contextWithQueryMetrics.Accept(BackendMetricsExtractor.Singleton); Assert.AreEqual(BackendMetricsExtractor.ParseFailureReason.None, foundResult.parseFailureReason); Assert.AreEqual(BackendMetricsTests.MockBackendMetrics.IndexLookupTime, foundResult.extractedBackendMetrics.IndexLookupTime); }
private async Task <FeedResponse <ChangeFeedProcessorState> > ReadNextInternalAsync( CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (this.lazyLeaseDocuments.Result.Result.Count == 0) { // Lease store is empty this.hasMoreResults = false; return(new ChangeFeedEstimatorEmptyFeedResponse(diagnosticsContext.Diagnostics)); } IEnumerable <DocumentServiceLease> leasesForCurrentPage = this.lazyLeaseDocuments.Result.Result.Skip(this.currentPage * this.pageSize).Take(this.pageSize); IEnumerable <Task <List <(ChangeFeedProcessorState, double)> > > tasks = Partitioner.Create(leasesForCurrentPage) .GetPartitions(this.pageSize) .Select(partition => Task.Run(async() => { List <(ChangeFeedProcessorState, double)> partialResults = new List <(ChangeFeedProcessorState, double)>(); using (partition) { while (!cancellationToken.IsCancellationRequested && partition.MoveNext()) { DocumentServiceLease item = partition.Current; if (item?.CurrentLeaseToken == null) { continue; } (long estimation, ResponseMessage responseMessage) = await this.GetRemainingWorkAsync(item, cancellationToken).ConfigureAwait(false); // Attach each diagnostics diagnosticsContext.AddDiagnosticsInternal(responseMessage.DiagnosticsContext); partialResults.Add((new ChangeFeedProcessorState(item.CurrentLeaseToken, estimation, item.Owner), responseMessage.Headers.RequestCharge)); } } return(partialResults); })).ToArray(); IEnumerable <List <(ChangeFeedProcessorState, double)> > partitionResults = await Task.WhenAll(tasks); IEnumerable <(ChangeFeedProcessorState, double)> unifiedResults = partitionResults.SelectMany(r => r); ReadOnlyCollection <ChangeFeedProcessorState> estimations = unifiedResults.Select(r => r.Item1).ToList().AsReadOnly(); double totalRUCost = unifiedResults.Sum(r => r.Item2); this.hasMoreResults = ++this.currentPage != this.maxPage; return(new ChangeFeedEstimatorFeedResponse(diagnosticsContext.Diagnostics, estimations, totalRUCost)); }
private async Task <FeedResponse <ChangeFeedProcessorState> > ReadNextInternalAsync( CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (this.lazyLeaseDocuments.Result.Result.Count == 0) { // Lease store is empty this.hasMoreResults = false; return(new ChangeFeedEstimatorEmptyFeedResponse(diagnosticsContext.Diagnostics)); } IEnumerable <DocumentServiceLease> leasesForCurrentPage = this.lazyLeaseDocuments.Result.Result.Skip(this.currentPage * this.pageSize).Take(this.pageSize); IEnumerable <Task <(ChangeFeedProcessorState, ResponseMessage)> > tasks = leasesForCurrentPage .Select(lease => Task.Run(async() => { (long estimation, ResponseMessage responseMessage) = await this.GetRemainingWorkAsync(lease, cancellationToken); return(new ChangeFeedProcessorState(lease.CurrentLeaseToken, estimation, lease.Owner), responseMessage); })).ToArray(); IEnumerable <(ChangeFeedProcessorState, ResponseMessage)> results = await Task.WhenAll(tasks); List <ChangeFeedProcessorState> estimations = new List <ChangeFeedProcessorState>(); double totalRUCost = 0; foreach ((ChangeFeedProcessorState, ResponseMessage)result in results) { using (result.Item2) { totalRUCost += result.Item2.Headers.RequestCharge; diagnosticsContext.AddDiagnosticsInternal(result.Item2.DiagnosticsContext); } estimations.Add(result.Item1); } this.hasMoreResults = ++this.currentPage != this.maxPage; return(new ChangeFeedEstimatorFeedResponse(diagnosticsContext.Diagnostics, estimations.AsReadOnly(), totalRUCost)); }
private (Func <string, Task <TryCatch <IDocumentQueryExecutionComponent> > >, QueryResponseCore) SetupBaseContextToVerifyFailureScenario() { CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(); diagnosticsContext.AddDiagnosticsInternal(new PointOperationStatistics( Guid.NewGuid().ToString(), System.Net.HttpStatusCode.Unauthorized, subStatusCode: SubStatusCodes.PartitionKeyMismatch, requestCharge: 4, errorMessage: null, method: HttpMethod.Post, requestUri: new Uri("http://localhost.com"), requestSessionToken: null, responseSessionToken: null, clientSideRequestStatistics: null)); IReadOnlyCollection <QueryPageDiagnostics> diagnostics = new List <QueryPageDiagnostics>() { new QueryPageDiagnostics( "0", "SomeQueryMetricText", "SomeIndexUtilText", diagnosticsContext, new SchedulingStopwatch()) }; QueryResponseCore failure = QueryResponseCore.CreateFailure( System.Net.HttpStatusCode.Unauthorized, SubStatusCodes.PartitionKeyMismatch, "Random error message", 42.89, "TestActivityId", diagnostics); Mock <IDocumentQueryExecutionComponent> baseContext = new Mock <IDocumentQueryExecutionComponent>(); baseContext.Setup(x => x.DrainAsync(It.IsAny <int>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult <QueryResponseCore>(failure)); Task <TryCatch <IDocumentQueryExecutionComponent> > callBack(string x) => Task.FromResult <TryCatch <IDocumentQueryExecutionComponent> >(TryCatch <IDocumentQueryExecutionComponent> .FromResult(baseContext.Object)); return(callBack, failure); }
public void ToResponseMessage_MapsProperties() { PointOperationStatistics pointOperationStatistics = new PointOperationStatistics( activityId: Guid.NewGuid().ToString(), statusCode: HttpStatusCode.OK, subStatusCode: SubStatusCodes.Unknown, requestCharge: 0, errorMessage: string.Empty, method: HttpMethod.Get, requestUri: new Uri("http://localhost"), requestSessionToken: null, responseSessionToken: null, clientSideRequestStatistics: new CosmosClientSideRequestStatistics()); CosmosDiagnosticsContext scope = CosmosDiagnosticsContext.Create(); scope.AddDiagnosticsInternal(pointOperationStatistics); TransactionalBatchOperationResult result = new TransactionalBatchOperationResult(HttpStatusCode.OK) { ResourceStream = new MemoryStream(new byte[] { 0x41, 0x42 }, index: 0, count: 2, writable: false, publiclyVisible: true), ETag = "1234", SubStatusCode = SubStatusCodes.CompletingSplit, RetryAfter = TimeSpan.FromSeconds(10), RequestCharge = 4.3, DiagnosticsContext = scope }; ResponseMessage response = result.ToResponseMessage(); Assert.AreEqual(result.ResourceStream, response.Content); Assert.AreEqual(result.SubStatusCode, response.Headers.SubStatusCode); Assert.AreEqual(result.RetryAfter, response.Headers.RetryAfter); Assert.AreEqual(result.StatusCode, response.StatusCode); Assert.AreEqual(result.RequestCharge, response.Headers.RequestCharge); string diagnostics = response.Diagnostics.ToString(); Assert.IsNotNull(diagnostics); Assert.IsTrue(diagnostics.Contains(pointOperationStatistics.ActivityId)); }
internal async Task <Response <T> > AggregateResultAsync(CancellationToken cancellationToken = default) { List <T> result = new List <T>(); CosmosDiagnosticsContext diagnosticsContext = null; Headers headers = new Headers(); FeedIterator <T> localFeedIterator = this.CreateFeedIterator(false); while (localFeedIterator.HasMoreResults) { FeedResponse <T> response = await localFeedIterator.ReadNextAsync(); headers.RequestCharge += response.RequestCharge; // If the first page has a diagnostic context use that. Else create a new one and add the diagnostic to it. if (response.Diagnostics is CosmosDiagnosticsContext responseDiagnosticContext) { if (diagnosticsContext == null) { diagnosticsContext = responseDiagnosticContext; } else { diagnosticsContext.AddDiagnosticsInternal(responseDiagnosticContext); } } else { throw new ArgumentException($"Invalid diagnostic object {response.Diagnostics.GetType().FullName}"); } result.AddRange(response); } return(new ItemResponse <T>( System.Net.HttpStatusCode.OK, headers, result.FirstOrDefault(), diagnosticsContext)); }
public static QueryResponseCore CreateFailureResponse( HttpStatusCode httpStatusCode, SubStatusCodes subStatusCodes, string errorMessage) { string acitivityId = Guid.NewGuid().ToString(); CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(); diagnosticsContext.AddDiagnosticsInternal(new PointOperationStatistics( acitivityId, System.Net.HttpStatusCode.Gone, subStatusCode: SubStatusCodes.PartitionKeyRangeGone, requestCharge: 10.4, errorMessage: null, method: HttpMethod.Post, requestUri: new Uri("http://localhost.com"), requestSessionToken: null, responseSessionToken: null, clientSideRequestStatistics: null)); IReadOnlyCollection <QueryPageDiagnostics> diagnostics = new List <QueryPageDiagnostics>() { new QueryPageDiagnostics("0", "SomeQueryMetricText", "SomeIndexUtilText", diagnosticsContext, new SchedulingStopwatch()) }; QueryResponseCore splitResponse = QueryResponseCore.CreateFailure( statusCode: httpStatusCode, subStatusCodes: subStatusCodes, cosmosException: CosmosExceptionFactory.Create( statusCode: httpStatusCode, subStatusCode: (int)subStatusCodes, message: errorMessage, stackTrace: new System.Diagnostics.StackTrace().ToString(), activityId: acitivityId, requestCharge: 10.4, retryAfter: default,
private void AddDiagnosticsInBackgroundLoop( int count, CosmosDiagnosticsContext cosmosDiagnostics, ConcurrentStack <Exception> concurrentStack) { CosmosDiagnosticsContext cosmosDiagnostics2 = new CosmosDiagnosticsContextCore( nameof(ValidateDiagnosticsAppendContext), "MyCustomUserAgentString"); Random random = new Random(); cosmosDiagnostics2.GetOverallScope().Dispose(); for (int i = 0; i < count; i++) { try { cosmosDiagnostics.AddDiagnosticsInternal(cosmosDiagnostics2); } catch (Exception e) { concurrentStack.Append(e); } } }
public void ValidateDiagnosticsContext() { CosmosDiagnosticsContext cosmosDiagnostics = CosmosDiagnosticsContext.Create(); string diagnostics = cosmosDiagnostics.ToString(); //Test the default user agent string JObject jObject = JObject.Parse(diagnostics); JToken summary = jObject["Summary"]; Assert.IsTrue(summary["UserAgent"].ToString().Contains("cosmos-netstandard-sdk"), "Diagnostics should have user agent string"); Assert.AreEqual("[]", jObject["Context"].ToString()); // Test all the different operations on diagnostics context using (cosmosDiagnostics.CreateOverallScope("OverallScope")) { Thread.Sleep(TimeSpan.FromSeconds(1)); using (cosmosDiagnostics.CreateScope("ValidateScope")) { Thread.Sleep(TimeSpan.FromSeconds(1)); cosmosDiagnostics.AddDiagnosticsInternal(new PointOperationStatistics( new Guid("692ab2f2-41ba-486b-aad7-8c7c6c52379f").ToString(), (HttpStatusCode)429, Documents.SubStatusCodes.Unknown, 42, null, HttpMethod.Get, new Uri("http://MockUri.com"), null, null, null)); } using (cosmosDiagnostics.CreateScope("SuccessScope")) { cosmosDiagnostics.AddDiagnosticsInternal(new PointOperationStatistics( new Guid("de09baab-71a4-4897-a163-470711c93ed3").ToString(), HttpStatusCode.OK, Documents.SubStatusCodes.Unknown, 42, null, HttpMethod.Get, new Uri("http://MockUri.com"), null, null, null)); } } cosmosDiagnostics.SetSdkUserAgent("MyCustomUserAgentString"); string result = cosmosDiagnostics.ToString(); string regex = @"\{""Summary"":\{""StartUtc"":"".+Z"",""ElapsedTime"":""00:00:.+"",""UserAgent"":""MyCustomUserAgentString"",""TotalRequestCount"":2,""FailedRequestCount"":1\},""Context"":\[\{""Id"":""OverallScope"",""ElapsedTime"":""00:00:0.+""\},\{""Id"":""ValidateScope"",""ElapsedTime"":""00:00:0.+""\},\{""Id"":""PointOperationStatistics"",""ActivityId"":""692ab2f2-41ba-486b-aad7-8c7c6c52379f"",""StatusCode"":429,""SubStatusCode"":0,""RequestCharge"":42.0,""RequestUri"":""http://MockUri.com"",""RequestSessionToken"":null,""ResponseSessionToken"":null\},\{""Id"":""SuccessScope"",""ElapsedTime"":""00:00:.+""\},\{""Id"":""PointOperationStatistics"",""ActivityId"":""de09baab-71a4-4897-a163-470711c93ed3"",""StatusCode"":200,""SubStatusCode"":0,""RequestCharge"":42.0,""RequestUri"":""http://MockUri.com"",""RequestSessionToken"":null,""ResponseSessionToken"":null\}\]\}"; Assert.IsTrue(Regex.IsMatch(result, regex), result); JToken jToken = JToken.Parse(result); TimeSpan total = jToken["Summary"]["ElapsedTime"].ToObject <TimeSpan>(); Assert.IsTrue(total > TimeSpan.FromSeconds(2)); TimeSpan overalScope = jToken["Context"][0]["ElapsedTime"].ToObject <TimeSpan>(); Assert.IsTrue(total == overalScope); TimeSpan innerScope = jToken["Context"][1]["ElapsedTime"].ToObject <TimeSpan>(); Assert.IsTrue(innerScope > TimeSpan.FromSeconds(1)); }
public async Task TestItemProducerTreeWithFailure() { int callBackCount = 0; Mock <CosmosQueryContext> mockQueryContext = new Mock <CosmosQueryContext>(); SqlQuerySpec sqlQuerySpec = new SqlQuerySpec("Select * from t"); PartitionKeyRange partitionKeyRange = new PartitionKeyRange { Id = "0", MinInclusive = "A", MaxExclusive = "B" }; void produceAsyncCompleteCallback( ItemProducerTree producer, int itemsBuffered, double resourceUnitUsage, IReadOnlyCollection <QueryPageDiagnostics> queryPageDiagnostics, long responseLengthBytes, CancellationToken token) { callBackCount++; } Mock <IComparer <ItemProducerTree> > comparer = new Mock <IComparer <ItemProducerTree> >(); Mock <IEqualityComparer <CosmosElement> > cosmosElementComparer = new Mock <IEqualityComparer <CosmosElement> >(); CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); IReadOnlyList <CosmosElement> cosmosElements = new List <CosmosElement>() { new Mock <CosmosElement>(CosmosElementType.Object).Object }; CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(); diagnosticsContext.AddDiagnosticsInternal(new PointOperationStatistics( Guid.NewGuid().ToString(), System.Net.HttpStatusCode.OK, subStatusCode: SubStatusCodes.Unknown, requestCharge: 42, errorMessage: null, method: HttpMethod.Post, requestUri: new Uri("http://localhost.com"), requestSessionToken: null, responseSessionToken: null, clientSideRequestStatistics: null)); QueryPageDiagnostics diagnostics = new QueryPageDiagnostics( partitionKeyRangeId: "0", queryMetricText: "SomeRandomQueryMetricText", indexUtilizationText: null, diagnosticsContext: diagnosticsContext, schedulingStopwatch: new SchedulingStopwatch()); IReadOnlyCollection <QueryPageDiagnostics> pageDiagnostics = new List <QueryPageDiagnostics>() { diagnostics }; mockQueryContext.Setup(x => x.ContainerResourceId).Returns("MockCollectionRid"); mockQueryContext.Setup(x => x.ExecuteQueryAsync( sqlQuerySpec, It.IsAny <string>(), It.IsAny <PartitionKeyRangeIdentity>(), It.IsAny <bool>(), It.IsAny <int>(), It.IsAny <SchedulingStopwatch>(), cancellationTokenSource.Token)).Returns( Task.FromResult(QueryResponseCore.CreateSuccess( result: cosmosElements, requestCharge: 42, activityId: "AA470D71-6DEF-4D61-9A08-272D8C9ABCFE", diagnostics: pageDiagnostics, responseLengthBytes: 500, disallowContinuationTokenMessage: null, continuationToken: "TestToken"))); ItemProducerTree itemProducerTree = new ItemProducerTree( queryContext: mockQueryContext.Object, querySpecForInit: sqlQuerySpec, partitionKeyRange: partitionKeyRange, produceAsyncCompleteCallback: produceAsyncCompleteCallback, itemProducerTreeComparer: comparer.Object, equalityComparer: cosmosElementComparer.Object, testSettings: new TestInjections(simulate429s: false, simulateEmptyPages: false), deferFirstPage: false, collectionRid: "collectionRid", initialContinuationToken: null, initialPageSize: 50); // Buffer to success responses await itemProducerTree.BufferMoreDocumentsAsync(cancellationTokenSource.Token); await itemProducerTree.BufferMoreDocumentsAsync(cancellationTokenSource.Token); CosmosDiagnosticsContext diagnosticsContextInternalServerError = CosmosDiagnosticsContext.Create(); diagnosticsContextInternalServerError.AddDiagnosticsInternal(new PointOperationStatistics( Guid.NewGuid().ToString(), System.Net.HttpStatusCode.InternalServerError, subStatusCode: SubStatusCodes.Unknown, requestCharge: 10.2, errorMessage: "Error message", method: HttpMethod.Post, requestUri: new Uri("http://localhost.com"), requestSessionToken: null, responseSessionToken: null, clientSideRequestStatistics: null)); diagnostics = new QueryPageDiagnostics( partitionKeyRangeId: "0", queryMetricText: null, indexUtilizationText: null, diagnosticsContext: diagnosticsContextInternalServerError, schedulingStopwatch: new SchedulingStopwatch()); pageDiagnostics = new List <QueryPageDiagnostics>() { diagnostics }; // Buffer a failure mockQueryContext.Setup(x => x.ExecuteQueryAsync( sqlQuerySpec, It.IsAny <string>(), It.IsAny <PartitionKeyRangeIdentity>(), It.IsAny <bool>(), It.IsAny <int>(), It.IsAny <SchedulingStopwatch>(), cancellationTokenSource.Token)).Returns( Task.FromResult(QueryResponseCore.CreateFailure( statusCode: HttpStatusCode.InternalServerError, subStatusCodes: null, cosmosException: CosmosExceptionFactory.CreateInternalServerErrorException( "Error message"), requestCharge: 10.2, activityId: Guid.NewGuid().ToString(), diagnostics: pageDiagnostics))); await itemProducerTree.BufferMoreDocumentsAsync(cancellationTokenSource.Token); // First item should be a success { (bool movedToNextPage, QueryResponseCore? failureResponse) = await itemProducerTree.TryMoveNextPageAsync(cancellationTokenSource.Token); Assert.IsTrue(movedToNextPage); Assert.IsNull(failureResponse); Assert.IsTrue(itemProducerTree.TryMoveNextDocumentWithinPage()); Assert.IsFalse(itemProducerTree.TryMoveNextDocumentWithinPage()); Assert.IsTrue(itemProducerTree.HasMoreResults); } // Second item should be a success { (bool movedToNextPage, QueryResponseCore? failureResponse) = await itemProducerTree.TryMoveNextPageAsync(cancellationTokenSource.Token); Assert.IsTrue(movedToNextPage); Assert.IsNull(failureResponse); Assert.IsTrue(itemProducerTree.TryMoveNextDocumentWithinPage()); Assert.IsFalse(itemProducerTree.TryMoveNextDocumentWithinPage()); Assert.IsTrue(itemProducerTree.HasMoreResults); } // Third item should be a failure { (bool movedToNextPage, QueryResponseCore? failureResponse) = await itemProducerTree.TryMoveNextPageAsync(cancellationTokenSource.Token); Assert.IsFalse(movedToNextPage); Assert.IsNotNull(failureResponse); Assert.IsFalse(itemProducerTree.HasMoreResults); } // Try to buffer after failure. It should return the previous cached failure and not try to buffer again. mockQueryContext.Setup(x => x.ExecuteQueryAsync( sqlQuerySpec, It.IsAny <string>(), It.IsAny <PartitionKeyRangeIdentity>(), It.IsAny <bool>(), It.IsAny <int>(), It.IsAny <SchedulingStopwatch>(), cancellationTokenSource.Token)). Throws(new Exception("Previous buffer failed. Operation should return original failure and not try again")); await itemProducerTree.BufferMoreDocumentsAsync(cancellationTokenSource.Token); Assert.IsFalse(itemProducerTree.HasMoreResults); }