diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/BridgeInternal.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/BridgeInternal.java index 393988646eff4..a81b03f32de84 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/BridgeInternal.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/BridgeInternal.java @@ -133,6 +133,17 @@ public static void setQueryPlanDiagnosticsContext(CosmosDiagnostics cosmosDiagno cosmosDiagnostics.getFeedResponseDiagnostics().setDiagnosticsContext(diagnosticsContext); } + @Warning(value = INTERNAL_USE_ONLY_WARNING) + public static E setRequestTimeline(E e, RequestTimeline requestTimeline) { + e.setRequestTimeline(requestTimeline); + return e; + } + + @Warning(value = INTERNAL_USE_ONLY_WARNING) + public static RequestTimeline getRequestTimeline(E e) { + return e.getRequestTimeline(); + } + @Warning(value = INTERNAL_USE_ONLY_WARNING) public static E setResourceAddress(E e, String resourceAddress) { e.setResourceAddress(resourceAddress); diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosException.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosException.java index cb135b5cbcc9b..1a0ca50c055b3 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosException.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosException.java @@ -44,7 +44,7 @@ public class CosmosException extends AzureException { private final Map responseHeaders; private CosmosDiagnostics cosmosDiagnostics; - private final RequestTimeline requestTimeline; + private RequestTimeline requestTimeline; private CosmosError cosmosError; long lsn; @@ -56,7 +56,6 @@ public class CosmosException extends AzureException { protected CosmosException(int statusCode, String message, Map responseHeaders, Throwable cause) { super(message, cause); this.statusCode = statusCode; - this.requestTimeline = RequestTimeline.empty(); this.responseHeaders = responseHeaders == null ? new HashMap<>() : new HashMap<>(responseHeaders); } @@ -302,4 +301,12 @@ private List> filterSensitiveData(Map void setResourceAddress(String resourceAddress) { this.resourceAddress = resourceAddress; } + + RequestTimeline getRequestTimeline() { + return this.requestTimeline; + } + + void setRequestTimeline(RequestTimeline requestTimeline) { + this.requestTimeline = requestTimeline; + } } diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/directconnectivity/RntbdTransportClient.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/directconnectivity/RntbdTransportClient.java index 8f14f5d276ef8..94c21155d0033 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/directconnectivity/RntbdTransportClient.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/directconnectivity/RntbdTransportClient.java @@ -188,7 +188,11 @@ public Mono invokeStoreAsync(final Uri addressUri, final RxDocume address.toString()); } - return error; + assert error instanceof CosmosException; + CosmosException cosmosException = (CosmosException) error; + BridgeInternal.setRequestTimeline(cosmosException, record.takeTimelineSnapshot()); + + return cosmosException; }); diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/directconnectivity/StoreResult.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/directconnectivity/StoreResult.java index 9d351b3838af2..785fa541864b8 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/directconnectivity/StoreResult.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/directconnectivity/StoreResult.java @@ -196,7 +196,9 @@ public void serialize(StoreResult storeResult, jsonGenerator.writeNumberField("itemLSN", storeResult.itemLSN); jsonGenerator.writeStringField("sessionToken", (storeResult.sessionToken != null ? storeResult.sessionToken.convertToString() : null)); jsonGenerator.writeStringField("exception", BridgeInternal.getInnerErrorMessage(storeResult.exception)); - jsonGenerator.writeObjectField("transportRequestTimeline", storeResult.storeResponse != null ? storeResult.storeResponse.getRequestTimeline() : null); + jsonGenerator.writeObjectField("transportRequestTimeline", storeResult.storeResponse != null ? + storeResult.storeResponse.getRequestTimeline() : + storeResult.exception != null ? BridgeInternal.getRequestTimeline(storeResult.exception) : null); jsonGenerator.writeEndObject(); } } diff --git a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/CosmosDiagnosticsTest.java b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/CosmosDiagnosticsTest.java index a4200e917bc5d..af1834398c51a 100644 --- a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/CosmosDiagnosticsTest.java +++ b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/CosmosDiagnosticsTest.java @@ -221,6 +221,14 @@ public void directDiagnostics() { assertThat(createResponse.getDiagnostics().getDuration()).isNotNull(); validateTransportRequestTimelineDirect(diagnostics); validateJson(diagnostics); + + // validate that on failed operation request timeline is populated + try { + cosmosContainer.createItem(internalObjectNode); + fail("expected 409"); + } catch (CosmosException e) { + validateTransportRequestTimelineDirect(e.getDiagnostics().toString()); + } } finally { if (testDirectClient != null) { testDirectClient.close(); @@ -489,6 +497,9 @@ public void serializationOnVariousScenarios() { assertThat(diagnostics).contains("\"userAgent\":\"" + Utils.getUserAgent() + "\""); } + + + @Test(groups = {"emulator"}, timeOut = TIMEOUT) public void addressResolutionStatistics() { CosmosClient client1 = null;