コード例 #1
0
 public CosmosOfferResult(
     HttpStatusCode statusCode,
     CosmosException cosmosRequestException)
 {
     this.StatusCode      = statusCode;
     this.CosmosException = cosmosRequestException;
 }
コード例 #2
0
        public void ValidateExceptionStackTraceHandling()
        {
            CosmosException cosmosException = CosmosExceptionFactory.CreateNotFoundException("TestMessage");

            Assert.AreEqual(null, cosmosException.StackTrace);
            Assert.IsFalse(cosmosException.ToString().Contains(nameof(ValidateExceptionStackTraceHandling)));
            try
            {
                throw cosmosException;
            }
            catch (CosmosException ce)
            {
                Assert.IsTrue(ce.StackTrace.Contains(nameof(ValidateExceptionStackTraceHandling)), ce.StackTrace);
            }

            string stackTrace = "OriginalDocumentClientExceptionStackTrace";

            try
            {
                throw CosmosExceptionFactory.CreateNotFoundException("TestMessage", stackTrace: stackTrace);
            }
            catch (CosmosException ce)
            {
                Assert.AreEqual(stackTrace, ce.StackTrace);
            }
        }
コード例 #3
0
 internal CosmosException(
     HttpStatusCode statusCode,
     string message,
     int subStatusCode,
     string stackTrace,
     string activityId,
     double requestCharge,
     TimeSpan?retryAfter,
     Headers headers,
     ITrace trace,
     Error error,
     Exception innerException)
     : base(CosmosException.GetMessageHelper(
                statusCode,
                subStatusCode,
                message,
                activityId), innerException)
 {
     this.ResponseBody  = message;
     this.stackTrace    = stackTrace;
     this.ActivityId    = activityId;
     this.StatusCode    = statusCode;
     this.SubStatusCode = subStatusCode;
     this.RetryAfter    = retryAfter;
     this.RequestCharge = requestCharge;
     this.Headers       = headers;
     this.Error         = error;
     this.Trace         = trace;
 }
コード例 #4
0
        internal CosmosException(
            HttpStatusCode statusCodes,
            string message,
            int subStatusCode,
            string stackTrace,
            string activityId,
            double requestCharge,
            TimeSpan?retryAfter,
            Headers headers,
            CosmosDiagnosticsContext diagnosticsContext,
            Error error,
            Exception innerException)
            : base(CosmosException.GetMessageHelper(
                       statusCodes,
                       subStatusCode,
                       message,
                       activityId), innerException)
        {
            this.ResponseBody  = message;
            this.stackTrace    = stackTrace;
            this.ActivityId    = activityId;
            this.StatusCode    = statusCodes;
            this.SubStatusCode = subStatusCode;
            this.RetryAfter    = retryAfter;
            this.RequestCharge = requestCharge;
            this.Headers       = headers;
            this.Error         = error;

            // Always have a diagnostic context. A new diagnostic will have useful info like user agent
            this.DiagnosticsContext = diagnosticsContext ?? new CosmosDiagnosticsContextCore();
        }
コード例 #5
0
        private static string GetMessageHelper(
            HttpStatusCode statusCode,
            Headers headers,
            string responseBody,
            CosmosDiagnostics diagnostics)
        {
            StringBuilder stringBuilder = new StringBuilder();

            CosmosException.AppendMessageWithoutDiagnostics(
                stringBuilder,
                statusCode,
                headers,
                responseBody);

            // Include the diagnostics for exceptions where it is critical
            // to root cause failures.
            if (statusCode == HttpStatusCode.RequestTimeout ||
                statusCode == HttpStatusCode.InternalServerError ||
                statusCode == HttpStatusCode.ServiceUnavailable ||
                (statusCode == HttpStatusCode.NotFound && headers.SubStatusCode == SubStatusCodes.ReadSessionNotAvailable))
            {
                stringBuilder.Append("; Diagnostics:");
                stringBuilder.Append(diagnostics.ToString());
            }

            return(stringBuilder.ToString());
        }
コード例 #6
0
        public void EnsureCorrectStatusCode()
        {
            string testMessage       = "Test" + Guid.NewGuid().ToString();
            string activityId        = Guid.NewGuid().ToString();
            int    substatuscode     = 9000;
            string substatus         = substatuscode.ToString();
            double requestCharge     = 42;
            double retryAfter        = 9000;
            string retryAfterLiteral = retryAfter.ToString();
            List <(HttpStatusCode statusCode, CosmosException exception)> exceptionsToStatusCodes = new List <(HttpStatusCode, CosmosException)>()
            {
                (HttpStatusCode.NotFound, CosmosExceptionFactory.CreateNotFoundException(testMessage, new Headers()
                {
                    SubStatusCodeLiteral = substatus, ActivityId = activityId, RequestCharge = requestCharge, RetryAfterLiteral = retryAfterLiteral
                })),
                (HttpStatusCode.InternalServerError, CosmosExceptionFactory.CreateInternalServerErrorException(testMessage, new Headers()
                {
                    SubStatusCodeLiteral = substatus, ActivityId = activityId, RequestCharge = requestCharge, RetryAfterLiteral = retryAfterLiteral
                })),
                (HttpStatusCode.BadRequest, CosmosExceptionFactory.CreateBadRequestException(testMessage, new Headers()
                {
                    SubStatusCodeLiteral = substatus, ActivityId = activityId, RequestCharge = requestCharge, RetryAfterLiteral = retryAfterLiteral
                })),
                (HttpStatusCode.RequestTimeout, CosmosExceptionFactory.CreateRequestTimeoutException(testMessage, new Headers()
                {
                    SubStatusCodeLiteral = substatus, ActivityId = activityId, RequestCharge = requestCharge, RetryAfterLiteral = retryAfterLiteral
                })),
                ((HttpStatusCode)429, CosmosExceptionFactory.CreateThrottledException(testMessage, new Headers()
                {
                    SubStatusCodeLiteral = substatus, ActivityId = activityId, RequestCharge = requestCharge, RetryAfterLiteral = retryAfterLiteral
                })),
            };

            foreach ((HttpStatusCode statusCode, CosmosException exception) in exceptionsToStatusCodes)
            {
                this.ValidateExceptionInfo(
                    exception,
                    statusCode,
                    substatus,
                    testMessage,
                    activityId,
                    requestCharge,
                    retryAfter);
            }

            CosmosException cosmosException = CosmosExceptionFactory.CreateNotFoundException(testMessage, new Headers()
            {
                SubStatusCodeLiteral = ((int)SubStatusCodes.ReadSessionNotAvailable).ToString(), ActivityId = activityId, RequestCharge = requestCharge, RetryAfterLiteral = retryAfterLiteral
            });

            this.ValidateExceptionInfo(
                cosmosException,
                HttpStatusCode.NotFound,
                ((int)SubStatusCodes.ReadSessionNotAvailable).ToString(),
                testMessage,
                activityId,
                requestCharge,
                retryAfter);
        }
コード例 #7
0
 /// <summary>
 /// RecordOtelAttributes
 /// </summary>
 /// <param name="exception"></param>
 /// <param name="scope"></param>
 internal static void RecordOtelAttributes(CosmosException exception, DiagnosticScope scope)
 {
     scope.AddAttribute(OpenTelemetryAttributeKeys.StatusCode, exception.StatusCode);
     scope.AddAttribute(OpenTelemetryAttributeKeys.RequestCharge, exception.RequestCharge);
     scope.AddAttribute(OpenTelemetryAttributeKeys.Region, ClientTelemetryHelper.GetContactedRegions(exception.Diagnostics));
     scope.AddAttribute(OpenTelemetryAttributeKeys.RequestDiagnostics, exception.Diagnostics);
     scope.AddAttribute(OpenTelemetryAttributeKeys.ExceptionMessage, exception.Message);
 }
コード例 #8
0
 private void ValidateExceptionInfo(
     CosmosException exception,
     HttpStatusCode httpStatusCode,
     string message)
 {
     Assert.AreEqual(httpStatusCode, exception.StatusCode);
     Assert.IsTrue(exception.ToString().Contains(message));
 }
コード例 #9
0
        internal async Task <ThroughputResponse> ReplaceThroughputPropertiesIfExistsAsync(
            string targetRID,
            ThroughputProperties throughputProperties,
            RequestOptions requestOptions,
            CancellationToken cancellationToken = default)
        {
            try
            {
                (ThroughputProperties currentProperty, double requestCharge) = await this.GetOfferV2Async <ThroughputProperties>(targetRID, failIfNotConfigured : false, cancellationToken : cancellationToken);

                if (currentProperty == null)
                {
                    CosmosException notFound = CosmosExceptionFactory.CreateNotFoundException(
                        $"Throughput is not configured for {targetRID}",
                        headers: new Headers()
                    {
                        RequestCharge = requestCharge
                    });
                    return(new ThroughputResponse(
                               httpStatusCode: notFound.StatusCode,
                               headers: notFound.Headers,
                               throughputProperties: null,
                               diagnostics: notFound.Diagnostics,
                               requestMessage: null));
                }

                currentProperty.Content = throughputProperties.Content;

                return(await this.GetThroughputResponseAsync(
                           streamPayload : this.ClientContext.SerializerCore.ToStream(currentProperty),
                           operationType : OperationType.Replace,
                           linkUri : new Uri(currentProperty.SelfLink, UriKind.Relative),
                           resourceType : ResourceType.Offer,
                           currentRequestCharge : requestCharge,
                           requestOptions : requestOptions,
                           cancellationToken : cancellationToken));
            }
            catch (DocumentClientException dce)
            {
                ResponseMessage responseMessage = dce.ToCosmosResponseMessage(null);
                return(new ThroughputResponse(
                           responseMessage.StatusCode,
                           headers: responseMessage.Headers,
                           throughputProperties: null,
                           diagnostics: responseMessage.Diagnostics,
                           requestMessage: responseMessage.RequestMessage));
            }
            catch (AggregateException ex)
            {
                ResponseMessage responseMessage = TransportHandler.AggregateExceptionConverter(ex, null);
                return(new ThroughputResponse(
                           responseMessage.StatusCode,
                           headers: responseMessage.Headers,
                           throughputProperties: null,
                           diagnostics: responseMessage.Diagnostics,
                           requestMessage: responseMessage.RequestMessage));
            }
        }
コード例 #10
0
        public void VerifyDiagnosticsInTimeoutAndServerError()
        {
            ITrace trace            = NoOpTrace.Singleton;
            string diagnosticString = new Diagnostics.CosmosTraceDiagnostics(trace).ToString();

            CosmosException cosmosException = new CosmosException(
                statusCode: HttpStatusCode.RequestTimeout,
                message: "Test",
                stackTrace: null,
                headers: null,
                trace: trace,
                error: null,
                innerException: null);

            Assert.IsTrue(cosmosException.Message.EndsWith(diagnosticString));
            Assert.IsTrue(cosmosException.ToString().Contains(diagnosticString));

            cosmosException = new CosmosException(
                statusCode: HttpStatusCode.InternalServerError,
                message: "Test",
                stackTrace: null,
                headers: null,
                trace: trace,
                error: null,
                innerException: null);

            Assert.IsTrue(cosmosException.Message.EndsWith(diagnosticString));
            Assert.IsTrue(cosmosException.ToString().Contains(diagnosticString));

            cosmosException = new CosmosException(
                statusCode: HttpStatusCode.ServiceUnavailable,
                message: "Test",
                stackTrace: null,
                headers: null,
                trace: trace,
                error: null,
                innerException: null);

            Assert.IsTrue(cosmosException.Message.EndsWith(diagnosticString));
            Assert.IsTrue(cosmosException.ToString().Contains(diagnosticString));

            cosmosException = new CosmosException(
                statusCode: HttpStatusCode.NotFound,
                message: "Test",
                stackTrace: null,
                headers: null,
                trace: trace,
                error: null,
                innerException: null);

            Assert.IsFalse(cosmosException.Message.Contains(diagnosticString));
            Assert.IsTrue(cosmosException.ToString().Contains(diagnosticString));
        }
コード例 #11
0
        private void ValidateExceptionInfo(
            CosmosException exception,
            HttpStatusCode httpStatusCode,
            string message)
        {
            Assert.AreEqual(message, exception.ResponseBody);
            Assert.AreEqual(httpStatusCode, exception.StatusCode);
            Assert.IsTrue(exception.ToString().Contains(message));
            string expectedMessage = $"Response status code does not indicate success: {httpStatusCode} ({(int)httpStatusCode}); Substatus: 0; ActivityId: {exception.ActivityId}; Reason: ({message});";

            Assert.AreEqual(expectedMessage, exception.Message);
        }
コード例 #12
0
        internal static ResponseMessage ToCosmosResponseMessage(this DocumentClientException documentClientException, RequestMessage requestMessage)
        {
            CosmosDiagnosticsContext diagnosticsContext = requestMessage?.DiagnosticsContext;

            if (requestMessage != null)
            {
                diagnosticsContext = requestMessage.DiagnosticsContext;

                if (diagnosticsContext == null)
                {
                    throw new ArgumentNullException("Request message should contain a DiagnosticsContext");
                }
            }
            else
            {
                diagnosticsContext = new CosmosDiagnosticsContextCore();
            }

            CosmosException cosmosException = CosmosExceptionFactory.Create(
                documentClientException,
                diagnosticsContext);

            PointOperationStatistics pointOperationStatistics = new PointOperationStatistics(
                activityId: cosmosException.Headers.ActivityId,
                statusCode: cosmosException.StatusCode,
                subStatusCode: (int)SubStatusCodes.Unknown,
                responseTimeUtc: DateTime.UtcNow,
                requestCharge: cosmosException.Headers.RequestCharge,
                errorMessage: documentClientException.ToString(),
                method: requestMessage?.Method,
                requestUri: requestMessage?.RequestUriString,
                requestSessionToken: requestMessage?.Headers?.Session,
                responseSessionToken: cosmosException.Headers.Session);

            diagnosticsContext.AddDiagnosticsInternal(pointOperationStatistics);

            // if StatusCode is null it is a client business logic error and it never hit the backend, so throw
            if (documentClientException.StatusCode == null)
            {
                throw cosmosException;
            }

            // if there is a status code then it came from the backend, return error as http error instead of throwing the exception
            ResponseMessage responseMessage = cosmosException.ToCosmosResponseMessage(requestMessage);

            if (requestMessage != null)
            {
                requestMessage.Properties.Remove(nameof(DocumentClientException));
                requestMessage.Properties.Add(nameof(DocumentClientException), documentClientException);
            }

            return(responseMessage);
        }
コード例 #13
0
        private void ValidateExceptionInfo(
            CosmosException exception,
            HttpStatusCode httpStatusCode,
            string substatus,
            string message,
            string activityId,
            double requestCharge,
            double retryAfter)
        {
            Assert.AreEqual(message, exception.ResponseBody);
            Assert.AreEqual(httpStatusCode, exception.StatusCode);
            Assert.AreEqual(int.Parse(substatus), exception.SubStatusCode);
            Assert.AreEqual(substatus, exception.Headers.SubStatusCodeLiteral);
            Assert.AreEqual(activityId, exception.ActivityId);
            Assert.AreEqual(activityId, exception.Headers.ActivityId);
            Assert.AreEqual(requestCharge, exception.RequestCharge);
            Assert.AreEqual(requestCharge, exception.Headers.RequestCharge);
            Assert.AreEqual(TimeSpan.FromMilliseconds(retryAfter), exception.RetryAfter);
            Assert.AreEqual(TimeSpan.FromMilliseconds(retryAfter), exception.Headers.RetryAfter);
            Assert.IsTrue(exception.ToString().Contains(message));
            string expectedMessage = $"Response status code does not indicate success: {httpStatusCode} ({(int)httpStatusCode}); Substatus: {substatus}; ActivityId: {exception.ActivityId}; Reason: ({message});";

            if (httpStatusCode == HttpStatusCode.RequestTimeout ||
                httpStatusCode == HttpStatusCode.InternalServerError ||
                httpStatusCode == HttpStatusCode.ServiceUnavailable ||
                (httpStatusCode == HttpStatusCode.NotFound && exception.Headers.SubStatusCode == SubStatusCodes.ReadSessionNotAvailable))
            {
                expectedMessage += "; Diagnostics:" + new Diagnostics.CosmosTraceDiagnostics(NoOpTrace.Singleton).ToString();
            }

            Assert.AreEqual(expectedMessage, exception.Message);

            // Verify updating the header updates the exception info
            exception.Headers.SubStatusCodeLiteral = "1234";
            Assert.AreEqual(1234, exception.SubStatusCode);
            Assert.AreEqual("1234", exception.Headers.SubStatusCodeLiteral);

            activityId = Guid.NewGuid().ToString();
            exception.Headers.ActivityId = activityId;
            Assert.AreEqual(activityId, exception.ActivityId);
            Assert.AreEqual(activityId, exception.Headers.ActivityId);

            requestCharge = 4321.09;
            exception.Headers.RequestCharge = requestCharge;
            Assert.AreEqual(requestCharge, exception.RequestCharge);
            Assert.AreEqual(requestCharge, exception.Headers.RequestCharge);

            retryAfter = 98754;
            exception.Headers.RetryAfterLiteral = retryAfter.ToString();
            Assert.AreEqual(TimeSpan.FromMilliseconds(retryAfter), exception.RetryAfter);
            Assert.AreEqual(TimeSpan.FromMilliseconds(retryAfter), exception.Headers.RetryAfter);
        }
コード例 #14
0
        public void VerifyHeaderAlwaysExists()
        {
            CosmosException cosmosException = new CosmosException(
                statusCode: HttpStatusCode.BadRequest,
                message: "Test",
                stackTrace: null,
                headers: null,
                trace: NoOpTrace.Singleton,
                error: null,
                innerException: null);

            Assert.IsNotNull(cosmosException.Headers, "Header should always be created to avoid null refs caused by users always expecting it to be there");
        }
コード例 #15
0
 /// <summary>
 /// Create a <see cref="ResponseMessage"/>
 /// </summary>
 /// <param name="statusCode">The HttpStatusCode of the response</param>
 /// <param name="requestMessage">The <see cref="Cosmos.RequestMessage"/> object</param>
 /// <param name="headers">The headers for the response.</param>
 /// <param name="cosmosException">The exception if the response is from an error.</param>
 /// <param name="diagnostics">The diagnostics for the request</param>
 internal ResponseMessage(
     HttpStatusCode statusCode,
     RequestMessage requestMessage,
     Headers headers,
     CosmosException cosmosException,
     CosmosDiagnosticsContext diagnostics)
 {
     this.StatusCode         = statusCode;
     this.RequestMessage     = requestMessage;
     this.CosmosException    = cosmosException;
     this.Headers            = headers ?? new Headers();
     this.DiagnosticsContext = diagnostics ?? throw new ArgumentNullException(nameof(diagnostics));
 }
コード例 #16
0
        internal static ResponseMessage ToCosmosResponseMessage(this DocumentServiceResponse documentServiceResponse, RequestMessage requestMessage)
        {
            Debug.Assert(requestMessage != null, nameof(requestMessage));
            Headers headers = documentServiceResponse.Headers.ToCosmosHeaders();

            // Only record point operation stats if ClientSideRequestStats did not record the response.
            CosmosClientSideRequestStatistics clientSideRequestStatistics = documentServiceResponse.RequestStats as CosmosClientSideRequestStatistics;

            if (clientSideRequestStatistics == null ||
                (clientSideRequestStatistics.ContactedReplicas.Count == 0 && clientSideRequestStatistics.FailedReplicas.Count == 0))
            {
                requestMessage.DiagnosticsContext.AddDiagnosticsInternal(new PointOperationStatistics(
                                                                             activityId: headers.ActivityId,
                                                                             responseTimeUtc: DateTime.UtcNow,
                                                                             statusCode: documentServiceResponse.StatusCode,
                                                                             subStatusCode: documentServiceResponse.SubStatusCode,
                                                                             requestCharge: headers.RequestCharge,
                                                                             errorMessage: null,
                                                                             method: requestMessage?.Method,
                                                                             requestUri: requestMessage?.RequestUri,
                                                                             requestSessionToken: requestMessage?.Headers?.Session,
                                                                             responseSessionToken: headers.Session));
            }

            // If it's considered a failure create the corresponding CosmosException
            if (!documentServiceResponse.StatusCode.IsSuccess())
            {
                CosmosException cosmosException = CosmosExceptionFactory.Create(
                    documentServiceResponse,
                    headers,
                    requestMessage);

                return(cosmosException.ToCosmosResponseMessage(requestMessage));
            }

            ResponseMessage responseMessage = new ResponseMessage(
                statusCode: documentServiceResponse.StatusCode,
                requestMessage: requestMessage,
                headers: headers,
                cosmosException: null,
                diagnostics: requestMessage.DiagnosticsContext)
            {
                Content = documentServiceResponse.ResponseBody
            };

            return(responseMessage);
        }
コード例 #17
0
        private void ValidateExceptionInfo(
            CosmosException exception,
            HttpStatusCode httpStatusCode,
            string substatus,
            string message,
            string activityId,
            double requestCharge,
            double retryAfter)
        {
            Assert.AreEqual(message, exception.ResponseBody);
            Assert.AreEqual(httpStatusCode, exception.StatusCode);
            Assert.AreEqual(int.Parse(substatus), exception.SubStatusCode);
            Assert.AreEqual(substatus, exception.Headers.SubStatusCodeLiteral);
            Assert.AreEqual(activityId, exception.ActivityId);
            Assert.AreEqual(activityId, exception.Headers.ActivityId);
            Assert.AreEqual(requestCharge, exception.RequestCharge);
            Assert.AreEqual(requestCharge, exception.Headers.RequestCharge);
            Assert.AreEqual(TimeSpan.FromMilliseconds(retryAfter), exception.RetryAfter);
            Assert.AreEqual(TimeSpan.FromMilliseconds(retryAfter), exception.Headers.RetryAfter);
            Assert.IsTrue(exception.ToString().Contains(message));
            string expectedMessage = $"Response status code does not indicate success: {httpStatusCode} ({(int)httpStatusCode}); Substatus: {substatus}; ActivityId: {exception.ActivityId}; Reason: ({message});";

            Assert.AreEqual(expectedMessage, exception.Message);

            // Verify updating the header updates the exception info
            exception.Headers.SubStatusCodeLiteral = "1234";
            Assert.AreEqual(1234, exception.SubStatusCode);
            Assert.AreEqual("1234", exception.Headers.SubStatusCodeLiteral);

            activityId = Guid.NewGuid().ToString();
            exception.Headers.ActivityId = activityId;
            Assert.AreEqual(activityId, exception.ActivityId);
            Assert.AreEqual(activityId, exception.Headers.ActivityId);

            requestCharge = 4321.09;
            exception.Headers.RequestCharge = requestCharge;
            Assert.AreEqual(requestCharge, exception.RequestCharge);
            Assert.AreEqual(requestCharge, exception.Headers.RequestCharge);

            retryAfter = 98754;
            exception.Headers.RetryAfterLiteral = retryAfter.ToString();
            Assert.AreEqual(TimeSpan.FromMilliseconds(retryAfter), exception.RetryAfter);
            Assert.AreEqual(TimeSpan.FromMilliseconds(retryAfter), exception.Headers.RetryAfter);
        }
コード例 #18
0
        /// <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(CancellationToken))
        {
            CosmosDiagnosticsContext diagnostics = CosmosDiagnosticsContext.Create(this.changeFeedOptions);

            using (diagnostics.GetOverallScope())
            {
                diagnostics.AddDiagnosticsInternal(new FeedRangeStatistics(this.FeedRangeInternal));
                if (!this.lazyContainerRid.ValueInitialized)
                {
                    using (diagnostics.CreateScope("InitializeContainerResourceId"))
                    {
                        TryCatch <string> tryInitializeContainerRId = await this.lazyContainerRid.GetValueAsync(cancellationToken);

                        if (!tryInitializeContainerRId.Succeeded)
                        {
                            CosmosException cosmosException = tryInitializeContainerRId.Exception.InnerException as CosmosException;
                            return(cosmosException.ToCosmosResponseMessage(new RequestMessage(method: null, requestUri: null, diagnosticsContext: diagnostics)));
                        }
                    }

                    using (diagnostics.CreateScope("InitializeContinuation"))
                    {
                        if (this.FeedRangeContinuation != null)
                        {
                            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, requestUri: null, diagnosticsContext: diagnostics)));
                            }
                        }
                        else
                        {
                            await this.InitializeFeedContinuationAsync(cancellationToken);
                        }
                    }
                }

                return(await this.ReadNextInternalAsync(diagnostics, cancellationToken));
            }
        }
コード例 #19
0
 /// <summary>
 /// Create a <see cref="ResponseMessage"/>
 /// </summary>
 /// <param name="statusCode">The HttpStatusCode of the response</param>
 /// <param name="requestMessage">The <see cref="Cosmos.RequestMessage"/> object</param>
 /// <param name="headers">The headers for the response.</param>
 /// <param name="cosmosException">The exception if the response is from an error.</param>
 /// <param name="trace">The trace for the request</param>
 internal ResponseMessage(
     HttpStatusCode statusCode,
     RequestMessage requestMessage,
     Headers headers,
     CosmosException cosmosException,
     ITrace trace)
 {
     this.StatusCode      = statusCode;
     this.RequestMessage  = requestMessage;
     this.CosmosException = cosmosException;
     this.Headers         = headers ?? new Headers();
     if (requestMessage != null && requestMessage.Trace != null)
     {
         this.Trace = requestMessage.Trace;
     }
     else
     {
         this.Trace = trace ?? throw new ArgumentNullException(nameof(trace));
     }
 }
コード例 #20
0
 internal CosmosException(
     HttpStatusCode statusCode,
     string message,
     string stackTrace,
     Headers headers,
     ITrace trace,
     Error error,
     Exception innerException)
     : base(CosmosException.GetMessageHelper(
                statusCode,
                headers,
                message), innerException)
 {
     this.ResponseBody = message;
     this.stackTrace   = stackTrace;
     this.StatusCode   = statusCode;
     this.Headers      = headers ?? new Headers();
     this.Error        = error;
     this.Trace        = trace;
 }
コード例 #21
0
        internal static QueryResponse CreateFailure(
            CosmosQueryResponseMessageHeaders responseHeaders,
            HttpStatusCode statusCode,
            RequestMessage requestMessage,
            CosmosException cosmosException,
            CosmosDiagnosticsContext diagnostics)
        {
            QueryResponse cosmosQueryResponse = new QueryResponse(
                result: new List <CosmosElement>(),
                count: 0,
                responseLengthBytes: 0,
                responseHeaders: responseHeaders,
                diagnostics: diagnostics,
                statusCode: statusCode,
                cosmosException: cosmosException,
                requestMessage: requestMessage,
                memoryStream: null,
                serializationOptions: null);

            return(cosmosQueryResponse);
        }
コード例 #22
0
        private string ToStringHelper(
            StringBuilder stringBuilder)
        {
            if (stringBuilder == null)
            {
                throw new ArgumentNullException(nameof(stringBuilder));
            }

            CosmosException.AppendMessageWithoutDiagnostics(
                stringBuilder,
                this.StatusCode,
                this.Headers,
                this.ResponseBody);
            stringBuilder.AppendLine();

            if (this.InnerException != null)
            {
                stringBuilder.Append(" ---> ");
                stringBuilder.Append(this.InnerException);
                stringBuilder.AppendLine();
                stringBuilder.Append("   ");
                stringBuilder.Append("--- End of inner exception stack trace ---");
                stringBuilder.AppendLine();
            }

            if (this.StackTrace != null)
            {
                stringBuilder.Append(this.StackTrace);
                stringBuilder.AppendLine();
            }

            if (this.Diagnostics != null)
            {
                stringBuilder.Append("--- Cosmos Diagnostics ---");
                stringBuilder.Append(this.Diagnostics);
            }

            return(stringBuilder.ToString());
        }
コード例 #23
0
        public void ValidateErrorHandling()
        {
            Error error = new Error()
            {
                Code                = System.Net.HttpStatusCode.BadRequest.ToString(),
                Message             = "Unsupported Query",
                AdditionalErrorInfo = "Additional error info message",
            };

            CosmosDiagnosticsContext diagnostics = new CosmosDiagnosticsContextCore();

            CosmosException cosmosException = CosmosExceptionFactory.CreateBadRequestException(
                error.ToString(),
                error: error,
                diagnosticsContext: diagnostics);

            ResponseMessage responseMessage = QueryResponse.CreateFailure(
                statusCode: System.Net.HttpStatusCode.BadRequest,
                cosmosException: cosmosException,
                requestMessage: null,
                diagnostics: diagnostics,
                responseHeaders: null);

            Assert.AreEqual(error, responseMessage.CosmosException.Error);
            Assert.IsTrue(responseMessage.ErrorMessage.Contains(error.Message));
            Assert.IsTrue(responseMessage.ErrorMessage.Contains(error.AdditionalErrorInfo));

            try
            {
                responseMessage.EnsureSuccessStatusCode();
                Assert.Fail("Should throw exception");
            }
            catch (CosmosException ce) when(ce.StatusCode == HttpStatusCode.BadRequest)
            {
                Assert.IsTrue(ce.Message.Contains(error.Message));
                Assert.IsTrue(ce.ToString().Contains(error.Message));
                Assert.IsTrue(ce.ToString().Contains(error.AdditionalErrorInfo));
            }
        }
コード例 #24
0
        internal static ResponseMessage ToCosmosResponseMessage(this StoreResponse storeResponse, RequestMessage requestMessage)
        {
            // If it's considered a failure create the corresponding CosmosException
            if (!storeResponse.StatusCode.IsSuccess())
            {
                CosmosException cosmosException = CosmosExceptionFactory.Create(
                    storeResponse,
                    requestMessage);

                return(cosmosException.ToCosmosResponseMessage(requestMessage));
            }

            // Is status code conversion lossy?
            ResponseMessage responseMessage = new ResponseMessage((HttpStatusCode)storeResponse.Status, requestMessage);

            if (storeResponse.ResponseBody != null)
            {
                responseMessage.Content = storeResponse.ResponseBody;
            }

            return(responseMessage);
        }
コード例 #25
0
 private QueryResponse(
     IReadOnlyList <CosmosElement> result,
     int count,
     long responseLengthBytes,
     CosmosQueryResponseMessageHeaders responseHeaders,
     HttpStatusCode statusCode,
     RequestMessage requestMessage,
     CosmosDiagnosticsContext diagnostics,
     CosmosException cosmosException,
     Lazy <MemoryStream> memoryStream,
     CosmosSerializationFormatOptions serializationOptions)
     : base(
         statusCode: statusCode,
         requestMessage: requestMessage,
         cosmosException: cosmosException,
         headers: responseHeaders,
         diagnostics: diagnostics)
 {
     this.CosmosElements             = result;
     this.Count                      = count;
     this.ResponseLengthBytes        = responseLengthBytes;
     this.memoryStream               = memoryStream;
     this.CosmosSerializationOptions = serializationOptions;
 }
コード例 #26
0
        public void VerifyNullHeaderLogic()
        {
            string testMessage = "Test" + Guid.NewGuid().ToString();

            CosmosException exception = new CosmosException(
                statusCode: HttpStatusCode.BadRequest,
                message: testMessage,
                stackTrace: null,
                headers: null,
                trace: NoOpTrace.Singleton,
                error: null,
                innerException: null);

            Assert.IsNotNull(exception.Headers, "Header should always be created to avoid null refs caused by users always expecting it to be there");
            Assert.AreEqual(HttpStatusCode.BadRequest, exception.StatusCode);
            Assert.IsTrue(exception.ToString().Contains(testMessage));

            exception = new CosmosException(
                statusCode: HttpStatusCode.BadRequest,
                message: testMessage,
                subStatusCode: 42,
                activityId: "test",
                requestCharge: 4);

            Assert.IsNotNull(exception.Headers, "Header should always be created to avoid null refs caused by users always expecting it to be there");
            Assert.AreEqual(HttpStatusCode.BadRequest, exception.StatusCode);
            Assert.AreEqual(testMessage, exception.ResponseBody);
            Assert.AreEqual(HttpStatusCode.BadRequest, exception.StatusCode);
            Assert.AreEqual(42, exception.SubStatusCode);
            Assert.AreEqual("42", exception.Headers.SubStatusCodeLiteral);
            Assert.AreEqual("test", exception.ActivityId);
            Assert.AreEqual("test", exception.Headers.ActivityId);
            Assert.AreEqual(4, exception.RequestCharge);
            Assert.AreEqual(4, exception.Headers.RequestCharge);
            Assert.IsTrue(exception.ToString().Contains(testMessage));
        }
コード例 #27
0
 internal CosmosException(
     HttpStatusCode statusCode,
     string message,
     string stackTrace,
     Headers headers,
     ITrace trace,
     Error error,
     Exception innerException)
 // The message is overridden. Base exception does not have CTOR for just innerException and the property is not virtual
     : base(string.Empty, innerException)
 {
     this.ResponseBody = message;
     this.stackTrace   = stackTrace;
     this.StatusCode   = statusCode;
     this.Headers      = headers ?? new Headers();
     this.Error        = error;
     this.Trace        = trace;
     this.Diagnostics  = new CosmosTraceDiagnostics(this.Trace ?? NoOpTrace.Singleton);
     this.lazyMessage  = new Lazy <string>(() => CosmosException.GetMessageHelper(
                                               statusCode,
                                               this.Headers,
                                               this.ResponseBody,
                                               this.Diagnostics));
 }
コード例 #28
0
        /// <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)
        {
            cancellationToken.ThrowIfCancellationRequested();

            if (!this.hasMoreResults)
            {
                throw new InvalidOperationException("Should not be calling FeedIterator that does not have any more results");
            }

            if (this.monadicEnumerator.Failed)
            {
                this.hasMoreResults = false;

                CosmosException cosmosException = ExceptionToCosmosException.CreateFromException(this.monadicEnumerator.Exception);
                return(new ResponseMessage(
                           statusCode: System.Net.HttpStatusCode.BadRequest,
                           requestMessage: null,
                           headers: cosmosException.Headers,
                           cosmosException: cosmosException,
                           diagnostics: cosmosException.DiagnosticsContext));
            }

            CrossPartitionReadFeedAsyncEnumerator enumerator = this.monadicEnumerator.Result;
            TryCatch <ReadFeedPage> monadicPage;

            try
            {
                if (!await enumerator.MoveNextAsync())
                {
                    throw new InvalidOperationException("Should not be calling enumerator that does not have any more results");
                }

                monadicPage = enumerator.Current;
            }
            catch (Exception ex)
            {
                monadicPage = TryCatch <ReadFeedPage> .FromException(ex);
            }

            if (monadicPage.Failed)
            {
                CosmosException cosmosException = ExceptionToCosmosException.CreateFromException(monadicPage.Exception);
                if (!IsRetriableException(cosmosException))
                {
                    this.hasMoreResults = false;
                }

                return(new ResponseMessage(
                           statusCode: cosmosException.StatusCode,
                           requestMessage: null,
                           headers: cosmosException.Headers,
                           cosmosException: cosmosException,
                           diagnostics: cosmosException.DiagnosticsContext));
            }

            ReadFeedPage readFeedPage = monadicPage.Result;

            if (readFeedPage.State == default)
            {
                this.hasMoreResults = false;
            }

            // Make the continuation token match the older format:
            string continuationToken;

            if (readFeedPage.State != null)
            {
                List <CompositeContinuationToken> compositeContinuationTokens = new List <CompositeContinuationToken>();
                CosmosArray compositeContinuationTokensCosmosArray            = (CosmosArray)readFeedPage.State.ContinuationToken;
                foreach (CosmosElement arrayItem in compositeContinuationTokensCosmosArray)
                {
                    ReadFeedContinuationToken readFeedContinuationToken = ReadFeedContinuationToken.MonadicConvertFromCosmosElement(arrayItem).Result;
                    FeedRangeEpk  feedRangeEpk  = (FeedRangeEpk)readFeedContinuationToken.Range;
                    ReadFeedState readFeedState = readFeedContinuationToken.State;
                    CompositeContinuationToken compositeContinuationToken = new CompositeContinuationToken()
                    {
                        Range = feedRangeEpk.Range,
                        Token = readFeedState.ContinuationToken.ToString(),
                    };

                    compositeContinuationTokens.Add(compositeContinuationToken);
                }

                FeedRangeCompositeContinuation feedRangeCompositeContinuation = new FeedRangeCompositeContinuation(
                    containerRid: string.Empty,
                    feedRange: FeedRangeEpk.FullRange,
                    compositeContinuationTokens);

                continuationToken = feedRangeCompositeContinuation.ToString();
            }
            else
            {
                continuationToken = null;
            }

            return(new ResponseMessage(
                       statusCode: System.Net.HttpStatusCode.OK,
                       requestMessage: default,
コード例 #29
0
        private static TryCatch <QueryPage> GetCosmosElementResponse(
            Guid clientQueryCorrelationId,
            QueryRequestOptions requestOptions,
            ResourceType resourceType,
            ResponseMessage cosmosResponseMessage,
            PartitionKeyRangeIdentity partitionKeyRangeIdentity,
            Action <QueryPageDiagnostics> queryPageDiagnostics,
            ITrace trace)
        {
            using (ITrace getCosmosElementResponse = trace.StartChild("Get Cosmos Element Response", TraceComponent.Json, Tracing.TraceLevel.Info))
            {
                using (cosmosResponseMessage)
                {
                    QueryPageDiagnostics queryPage = new QueryPageDiagnostics(
                        clientQueryCorrelationId: clientQueryCorrelationId,
                        partitionKeyRangeId: partitionKeyRangeIdentity.PartitionKeyRangeId,
                        queryMetricText: cosmosResponseMessage.Headers.QueryMetricsText,
                        indexUtilizationText: cosmosResponseMessage.Headers[HttpConstants.HttpHeaders.IndexUtilization],
                        diagnosticsContext: cosmosResponseMessage.DiagnosticsContext);
                    queryPageDiagnostics(queryPage);

                    if (
                        cosmosResponseMessage.Headers.QueryMetricsText != null &&
                        BackendMetricsParser.TryParse(cosmosResponseMessage.Headers.QueryMetricsText, out BackendMetrics backendMetrics))
                    {
                        QueryMetricsTraceDatum datum = new QueryMetricsTraceDatum(
                            new QueryMetrics(backendMetrics, IndexUtilizationInfo.Empty, ClientSideMetrics.Empty));
                        trace.AddDatum("Query Metrics", datum);
                    }

                    if (!cosmosResponseMessage.IsSuccessStatusCode)
                    {
                        CosmosException exception;
                        if (cosmosResponseMessage.CosmosException != null)
                        {
                            exception = cosmosResponseMessage.CosmosException;
                        }
                        else
                        {
                            exception = new CosmosException(
                                cosmosResponseMessage.ErrorMessage,
                                cosmosResponseMessage.StatusCode,
                                (int)cosmosResponseMessage.Headers.SubStatusCode,
                                cosmosResponseMessage.Headers.ActivityId,
                                cosmosResponseMessage.Headers.RequestCharge);
                        }

                        return(TryCatch <QueryPage> .FromException(exception));
                    }

                    if (!(cosmosResponseMessage.Content is MemoryStream memoryStream))
                    {
                        memoryStream = new MemoryStream();
                        cosmosResponseMessage.Content.CopyTo(memoryStream);
                    }

                    long        responseLengthBytes = memoryStream.Length;
                    CosmosArray documents           = CosmosQueryClientCore.ParseElementsFromRestStream(
                        memoryStream,
                        resourceType,
                        requestOptions.CosmosSerializationFormatOptions);

                    CosmosQueryExecutionInfo cosmosQueryExecutionInfo;
                    if (cosmosResponseMessage.Headers.TryGetValue(QueryExecutionInfoHeader, out string queryExecutionInfoString))
                    {
                        cosmosQueryExecutionInfo = JsonConvert.DeserializeObject <CosmosQueryExecutionInfo>(queryExecutionInfoString);
                    }
                    else
                    {
                        cosmosQueryExecutionInfo = default;
                    }

                    QueryState queryState;
                    if (cosmosResponseMessage.Headers.ContinuationToken != null)
                    {
                        queryState = new QueryState(CosmosString.Create(cosmosResponseMessage.Headers.ContinuationToken));
                    }
                    else
                    {
                        queryState = default;
                    }

                    QueryPage response = new QueryPage(
                        documents,
                        cosmosResponseMessage.Headers.RequestCharge,
                        cosmosResponseMessage.Headers.ActivityId,
                        responseLengthBytes,
                        cosmosQueryExecutionInfo,
                        disallowContinuationTokenMessage: null,
                        queryState);

                    return(TryCatch <QueryPage> .FromResult(response));
                }
            }
        }
コード例 #30
0
        private static TryCatch <QueryPage> GetCosmosElementResponse(
            QueryRequestOptions requestOptions,
            ResourceType resourceType,
            ResponseMessage cosmosResponseMessage,
            ITrace trace)
        {
            using (ITrace getCosmosElementResponse = trace.StartChild("Get Cosmos Element Response", TraceComponent.Json, Tracing.TraceLevel.Info))
            {
                using (cosmosResponseMessage)
                {
                    if (
                        cosmosResponseMessage.Headers.QueryMetricsText != null &&
                        BackendMetricsParser.TryParse(cosmosResponseMessage.Headers.QueryMetricsText, out BackendMetrics backendMetrics))
                    {
                        QueryMetricsTraceDatum datum = new QueryMetricsTraceDatum(
                            new QueryMetrics(backendMetrics, IndexUtilizationInfo.Empty, ClientSideMetrics.Empty));
                        trace.AddDatum("Query Metrics", datum);
                    }

                    if (!cosmosResponseMessage.IsSuccessStatusCode)
                    {
                        CosmosException exception = cosmosResponseMessage.CosmosException ?? new CosmosException(
                            cosmosResponseMessage.ErrorMessage,
                            cosmosResponseMessage.StatusCode,
                            (int)cosmosResponseMessage.Headers.SubStatusCode,
                            cosmosResponseMessage.Headers.ActivityId,
                            cosmosResponseMessage.Headers.RequestCharge);
                        return(TryCatch <QueryPage> .FromException(exception));
                    }

                    if (!(cosmosResponseMessage.Content is MemoryStream memoryStream))
                    {
                        memoryStream = new MemoryStream();
                        cosmosResponseMessage.Content.CopyTo(memoryStream);
                    }

                    long        responseLengthBytes = memoryStream.Length;
                    CosmosArray documents           = CosmosQueryClientCore.ParseElementsFromRestStream(
                        memoryStream,
                        resourceType,
                        requestOptions.CosmosSerializationFormatOptions);

                    CosmosQueryExecutionInfo cosmosQueryExecutionInfo;
                    if (cosmosResponseMessage.Headers.TryGetValue(QueryExecutionInfoHeader, out string queryExecutionInfoString))
                    {
                        cosmosQueryExecutionInfo = JsonConvert.DeserializeObject <CosmosQueryExecutionInfo>(queryExecutionInfoString);
                    }
                    else
                    {
                        cosmosQueryExecutionInfo = default;
                    }

                    QueryState queryState;
                    if (cosmosResponseMessage.Headers.ContinuationToken != null)
                    {
                        queryState = new QueryState(CosmosString.Create(cosmosResponseMessage.Headers.ContinuationToken));
                    }
                    else
                    {
                        queryState = default;
                    }

                    Dictionary <string, string> additionalHeaders = new Dictionary <string, string>();
                    foreach (string key in cosmosResponseMessage.Headers)
                    {
                        if (!QueryPage.BannedHeaders.Contains(key))
                        {
                            additionalHeaders[key] = cosmosResponseMessage.Headers[key];
                        }
                    }

                    QueryPage response = new QueryPage(
                        documents,
                        cosmosResponseMessage.Headers.RequestCharge,
                        cosmosResponseMessage.Headers.ActivityId,
                        responseLengthBytes,
                        cosmosQueryExecutionInfo,
                        disallowContinuationTokenMessage: null,
                        additionalHeaders,
                        queryState);

                    return(TryCatch <QueryPage> .FromResult(response));
                }
            }
        }