Skip to content

Commit b543bc2

Browse files
authored
Cosmos improve request diagnostics to capture ClientStatistics counts / config (Azure#15738)
Adds Client Config summary to the cosmos request diagnostics : ``` "clientCfgs": { "id": 0, "numberOfClients": 1, "connCfg": { "rntbd": "(cto:PT5S, rto:PT5S, icto:PT0S, ieto:PT1H, mcpe:130, mrpc:30)", "gw": "(cps:1000, rto:PT5S, icto:null, p:false)", "other": "(ed: true, cs: false)" }, "consistencyCfg": "(consistency: Eventual, mm: true, prgns: [westus1,eastus1])" } ```
1 parent 051a979 commit b543bc2

File tree

69 files changed

+1342
-717
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+1342
-717
lines changed

sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/BridgeInternal.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.azure.cosmos.implementation.Constants;
88
import com.azure.cosmos.implementation.CosmosError;
99
import com.azure.cosmos.implementation.DatabaseAccount;
10+
import com.azure.cosmos.implementation.DiagnosticsClientContext;
1011
import com.azure.cosmos.implementation.Document;
1112
import com.azure.cosmos.implementation.FeedResponseDiagnostics;
1213
import com.azure.cosmos.implementation.InternalObjectNode;
@@ -17,6 +18,7 @@
1718
import com.azure.cosmos.implementation.RequestTimeline;
1819
import com.azure.cosmos.implementation.Resource;
1920
import com.azure.cosmos.implementation.ResourceResponse;
21+
import com.azure.cosmos.implementation.RxDocumentClientImpl;
2022
import com.azure.cosmos.implementation.RxDocumentServiceRequest;
2123
import com.azure.cosmos.implementation.RxDocumentServiceResponse;
2224
import com.azure.cosmos.implementation.SerializationDiagnosticsContext;
@@ -62,6 +64,11 @@ public final class BridgeInternal {
6264

6365
private BridgeInternal() {}
6466

67+
@Warning(value = INTERNAL_USE_ONLY_WARNING)
68+
public static CosmosDiagnostics createCosmosDiagnostics(DiagnosticsClientContext diagnosticsClientContext) {
69+
return new CosmosDiagnostics(diagnosticsClientContext);
70+
}
71+
6572
@Warning(value = INTERNAL_USE_ONLY_WARNING)
6673
public static Document documentFromObject(Object document, ObjectMapper mapper) {
6774
return Document.fromObject(document, mapper);
@@ -438,11 +445,6 @@ public static void setTimestamp(Resource resource, Instant date) {
438445
ModelBridgeInternal.setTimestamp(resource, date);
439446
}
440447

441-
@Warning(value = INTERNAL_USE_ONLY_WARNING)
442-
public static CosmosDiagnostics createCosmosDiagnostics() {
443-
return new CosmosDiagnostics();
444-
}
445-
446448
@Warning(value = INTERNAL_USE_ONLY_WARNING)
447449
public static void setTransportClientRequestTimelineOnDiagnostics(CosmosDiagnostics cosmosDiagnostics,
448450
RequestTimeline requestTimeline) {

sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/ClientSideRequestStatistics.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33
package com.azure.cosmos;
44

5+
import com.azure.cosmos.implementation.DiagnosticsClientContext;
56
import com.azure.cosmos.implementation.HttpConstants;
67
import com.azure.cosmos.implementation.MetadataDiagnosticsContext;
78
import com.azure.cosmos.implementation.OperationType;
@@ -38,6 +39,8 @@
3839
@JsonSerialize(using = ClientSideRequestStatistics.ClientSideRequestStatisticsSerializer.class)
3940
class ClientSideRequestStatistics {
4041
private static final int MAX_SUPPLEMENTAL_REQUESTS_FOR_TO_STRING = 10;
42+
private final DiagnosticsClientContext clientContext;
43+
private final DiagnosticsClientContext diagnosticsClientContext;
4144
private ConnectionMode connectionMode;
4245

4346
private List<StoreResponseStatistics> responseStatisticsList;
@@ -55,7 +58,9 @@ class ClientSideRequestStatistics {
5558
private MetadataDiagnosticsContext metadataDiagnosticsContext;
5659
private SerializationDiagnosticsContext serializationDiagnosticsContext;
5760

58-
ClientSideRequestStatistics() {
61+
ClientSideRequestStatistics(DiagnosticsClientContext diagnosticsClientContext) {
62+
this.diagnosticsClientContext = diagnosticsClientContext;
63+
this.clientContext = null;
5964
this.requestStartTimeUTC = Instant.now();
6065
this.requestEndTimeUTC = Instant.now();
6166
this.responseStatisticsList = new ArrayList<>();
@@ -312,6 +317,8 @@ public void serialize(
312317
} catch (Exception e) {
313318
// Error while evaluating system information, do nothing
314319
}
320+
321+
generator.writeObjectField("clientCfgs", statistics.diagnosticsClientContext);
315322
generator.writeEndObject();
316323
}
317324
}

sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/CosmosDiagnostics.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33
package com.azure.cosmos;
44

5+
import com.azure.cosmos.implementation.DiagnosticsClientContext;
56
import com.azure.cosmos.implementation.FeedResponseDiagnostics;
67
import com.azure.cosmos.implementation.Utils;
78
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -23,8 +24,8 @@ public final class CosmosDiagnostics {
2324

2425
static final String USER_AGENT = Utils.getUserAgent();
2526

26-
CosmosDiagnostics() {
27-
this.clientSideRequestStatistics = new ClientSideRequestStatistics();
27+
CosmosDiagnostics(DiagnosticsClientContext diagnosticsClientContext) {
28+
this.clientSideRequestStatistics = new ClientSideRequestStatistics(diagnosticsClientContext);
2829
}
2930

3031
CosmosDiagnostics(FeedResponseDiagnostics feedResponseDiagnostics) {

sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/ChangeFeedQueryImpl.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class ChangeFeedQueryImpl<T extends Resource> {
2020

2121
private static final String IfNonMatchAllHeaderValue = "*";
2222
private final RxDocumentClientImpl client;
23+
private final DiagnosticsClientContext clientContext;
2324
private final ResourceType resourceType;
2425
private final Class<T> klass;
2526
private final String documentsLink;
@@ -30,7 +31,7 @@ public ChangeFeedQueryImpl(RxDocumentClientImpl client,
3031
Class<T> klass,
3132
String collectionLink,
3233
ChangeFeedOptions changeFeedOptions) {
33-
34+
this.clientContext = client;
3435
this.client = client;
3536
this.resourceType = resourceType;
3637
this.klass = klass;
@@ -71,7 +72,7 @@ public ChangeFeedQueryImpl(RxDocumentClientImpl client,
7172

7273
private RxDocumentServiceRequest createDocumentServiceRequest(String continuationToken, int pageSize) {
7374
Map<String, String> headers = new HashMap<>();
74-
RxDocumentServiceRequest req = RxDocumentServiceRequest.create(
75+
RxDocumentServiceRequest req = RxDocumentServiceRequest.create(clientContext,
7576
OperationType.ReadFeed,
7677
resourceType,
7778
documentsLink,

sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/ClientRetryPolicy.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ public class ClientRetryPolicy extends DocumentClientRetryPolicy {
4949
private int queryPlanAddressRefreshCount;
5050
private RxDocumentServiceRequest request;
5151

52-
public ClientRetryPolicy(GlobalEndpointManager globalEndpointManager,
52+
public ClientRetryPolicy(DiagnosticsClientContext diagnosticsClientContext,
53+
GlobalEndpointManager globalEndpointManager,
5354
boolean enableEndpointDiscovery,
5455
ThrottlingRetryOptions throttlingRetryOptions) {
5556

@@ -61,7 +62,7 @@ public ClientRetryPolicy(GlobalEndpointManager globalEndpointManager,
6162
this.enableEndpointDiscovery = enableEndpointDiscovery;
6263
this.sessionTokenRetryCount = 0;
6364
this.canUseMultipleWriteLocations = false;
64-
this.cosmosDiagnostics = BridgeInternal.createCosmosDiagnostics();
65+
this.cosmosDiagnostics = diagnosticsClientContext.createDiagnostics();
6566
}
6667

6768
@Override

sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/implementation/ConnectionPolicy.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ public final class ConnectionPolicy {
2222
private static final int defaultGatewayMaxConnectionPoolSize = GatewayConnectionConfig.getDefaultConfig()
2323
.getMaxConnectionPoolSize();
2424

25-
private static final ConnectionPolicy defaultPolicy =
26-
new ConnectionPolicy(DirectConnectionConfig.getDefaultConfig());
27-
2825
private ConnectionMode connectionMode;
2926
private boolean endpointDiscoveryEnabled;
3027
private boolean multipleWriteRegionsEnabled;
@@ -84,7 +81,7 @@ private ConnectionPolicy(ConnectionMode connectionMode) {
8481
* @return the default connection policy.
8582
*/
8683
public static ConnectionPolicy getDefaultPolicy() {
87-
return ConnectionPolicy.defaultPolicy;
84+
return new ConnectionPolicy(DirectConnectionConfig.getDefaultConfig());
8885
}
8986

9087
/**
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.azure.cosmos.implementation;
5+
6+
import com.azure.cosmos.ConsistencyLevel;
7+
import com.azure.cosmos.CosmosDiagnostics;
8+
import com.azure.cosmos.implementation.directconnectivity.RntbdTransportClient;
9+
import com.azure.cosmos.implementation.guava27.Strings;
10+
import com.azure.cosmos.implementation.http.HttpClientConfig;
11+
import com.fasterxml.jackson.core.JsonGenerator;
12+
import com.fasterxml.jackson.databind.SerializerProvider;
13+
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
14+
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
15+
import org.slf4j.Logger;
16+
import org.slf4j.LoggerFactory;
17+
18+
import java.io.IOException;
19+
import java.util.List;
20+
import java.util.Locale;
21+
import java.util.concurrent.atomic.AtomicInteger;
22+
import java.util.stream.Collectors;
23+
24+
@JsonSerialize(using = DiagnosticsClientContext.ClientContextSerializer.class)
25+
public interface DiagnosticsClientContext {
26+
27+
DiagnosticsClientConfig getConfig();
28+
29+
CosmosDiagnostics createDiagnostics();
30+
31+
32+
static final class ClientContextSerializer extends StdSerializer<DiagnosticsClientContext> {
33+
private final static Logger logger = LoggerFactory.getLogger(ClientContextSerializer.class);
34+
public final static ClientContextSerializer INSTACE = new ClientContextSerializer();
35+
36+
private static final long serialVersionUID = 1;
37+
38+
protected ClientContextSerializer() {
39+
this(null);
40+
}
41+
42+
protected ClientContextSerializer(Class<DiagnosticsClientContext> t) {
43+
super(t);
44+
}
45+
46+
@Override
47+
public void serialize(DiagnosticsClientContext clientContext, JsonGenerator generator,
48+
SerializerProvider serializerProvider) throws IOException {
49+
generator.writeStartObject();
50+
try {
51+
generator.writeNumberField("id", clientContext.getConfig().getClientId());
52+
generator.writeNumberField("numberOfClients", clientContext.getConfig().getActiveClientsCount());
53+
generator.writeObjectFieldStart("connCfg");
54+
try {
55+
generator.writeStringField("rntbd", clientContext.getConfig().rntbdConfig());
56+
generator.writeStringField("gw", clientContext.getConfig().gwConfig());
57+
generator.writeStringField("other", clientContext.getConfig().otherConnectionConfig());
58+
} catch (Exception e) {
59+
logger.debug("unexpected failure", e);
60+
}
61+
generator.writeEndObject();
62+
generator.writeStringField("consistencyCfg", clientContext.getConfig().consistencyRelatedConfig());
63+
} catch (Exception e) {
64+
logger.debug("unexpected failure", e);
65+
}
66+
generator.writeEndObject();
67+
}
68+
}
69+
70+
class DiagnosticsClientConfig {
71+
72+
private AtomicInteger activeClientsCnt;
73+
private int clientId;
74+
75+
private ConsistencyLevel consistencyLevel;
76+
private boolean connectionSharingAcrossClientsEnabled;
77+
private String consistencyRelatedConfigAsString;
78+
private String httpConfigAsString;
79+
private String otherCfgAsString;
80+
private List<String> preferredRegions;
81+
private boolean endpointDiscoveryEnabled;
82+
private boolean multipleWriteRegionsEnabled;
83+
84+
private HttpClientConfig httpClientConfig;
85+
private RntbdTransportClient.Options options;
86+
private String rntbdConfigAsString;
87+
88+
public void withActiveClientCounter(AtomicInteger activeClientsCnt) {
89+
this.activeClientsCnt = activeClientsCnt;
90+
}
91+
92+
public void withClientId(int clientId) {
93+
this.clientId = clientId;
94+
}
95+
96+
public DiagnosticsClientConfig withEndpointDiscoveryEnabled(boolean endpointDiscoveryEnabled) {
97+
this.endpointDiscoveryEnabled = endpointDiscoveryEnabled;
98+
return this;
99+
}
100+
101+
public DiagnosticsClientConfig withMultipleWriteRegionsEnabled(boolean multipleWriteRegionsEnabled) {
102+
this.multipleWriteRegionsEnabled = multipleWriteRegionsEnabled;
103+
return this;
104+
}
105+
106+
public DiagnosticsClientConfig withPreferredRegions(List<String> preferredRegions) {
107+
this.preferredRegions = preferredRegions;
108+
return this;
109+
}
110+
111+
public DiagnosticsClientConfig withConnectionSharingAcrossClientsEnabled(boolean connectionSharingAcrossClientsEnabled) {
112+
this.connectionSharingAcrossClientsEnabled = connectionSharingAcrossClientsEnabled;
113+
return this;
114+
}
115+
116+
public DiagnosticsClientConfig withConsistency(ConsistencyLevel consistencyLevel) {
117+
this.consistencyLevel = consistencyLevel;
118+
return this;
119+
}
120+
121+
public DiagnosticsClientConfig withRntbdOptions(RntbdTransportClient.Options options) {
122+
this.options = options;
123+
return this;
124+
}
125+
126+
public DiagnosticsClientConfig withGatewayHttpClientConfig(HttpClientConfig httpClientConfig) {
127+
this.httpClientConfig = httpClientConfig;
128+
return this;
129+
}
130+
131+
132+
public String consistencyRelatedConfig() {
133+
if (consistencyRelatedConfigAsString == null) {
134+
this.consistencyRelatedConfigAsString = this.consistencyRelatedConfigInternal();
135+
}
136+
137+
return this.consistencyRelatedConfigAsString;
138+
}
139+
140+
public String rntbdConfig() {
141+
if (this.rntbdConfigAsString == null) {
142+
this.rntbdConfigAsString = this.rntbdConfigInternal(this.options);
143+
}
144+
145+
return this.rntbdConfigAsString;
146+
}
147+
148+
public String gwConfig() {
149+
if (this.httpConfigAsString == null) {
150+
this.httpConfigAsString = this.gwConfigInternal();
151+
}
152+
153+
return this.httpConfigAsString;
154+
}
155+
156+
public String otherConnectionConfig() {
157+
if (this.otherCfgAsString == null) {
158+
this.otherCfgAsString = Strings.lenientFormat("(ed: %s, cs: %s)",
159+
this.endpointDiscoveryEnabled,
160+
this.connectionSharingAcrossClientsEnabled);
161+
}
162+
163+
return this.otherCfgAsString;
164+
}
165+
166+
public int getClientId() {
167+
return this.clientId;
168+
}
169+
170+
public int getActiveClientsCount() {
171+
return this.activeClientsCnt != null ? this.activeClientsCnt.get() : -1;
172+
}
173+
174+
private String gwConfigInternal() {
175+
if (this.httpClientConfig == null) {
176+
return null;
177+
}
178+
return Strings.lenientFormat("(cps:%s, rto:%s, icto:%s, p:%s)",
179+
this.httpClientConfig.getMaxPoolSize(),
180+
this.httpClientConfig.getRequestTimeout(),
181+
this.httpClientConfig.getMaxIdleConnectionTimeout(),
182+
this.httpClientConfig.getProxy() != null);
183+
}
184+
185+
private String rntbdConfigInternal(RntbdTransportClient.Options rntbdOptions) {
186+
if (rntbdOptions == null) {
187+
return null;
188+
}
189+
return Strings.lenientFormat("(cto:%s, rto:%s, icto:%s, ieto:%s, mcpe:%s, mrpc:%s)",
190+
rntbdOptions.connectTimeout(),
191+
rntbdOptions.requestTimeout(),
192+
rntbdOptions.idleChannelTimeout(),
193+
rntbdOptions.idleEndpointTimeout(),
194+
rntbdOptions.maxChannelsPerEndpoint(),
195+
rntbdOptions.maxRequestsPerChannel());
196+
}
197+
198+
private String preferredRegionsInternal() {
199+
if (preferredRegions == null) {
200+
return "";
201+
}
202+
203+
return preferredRegions.stream().map(r -> r.toLowerCase(Locale.ROOT).replaceAll(" ", "")).collect(Collectors.joining(","));
204+
}
205+
206+
private String consistencyRelatedConfigInternal() {
207+
return Strings.lenientFormat("(consistency: %s, mm: %s, prgns: [%s])", this.consistencyLevel,
208+
this.multipleWriteRegionsEnabled,
209+
preferredRegionsInternal());
210+
}
211+
}
212+
}

0 commit comments

Comments
 (0)