11// Copyright (c) Microsoft Corporation. All rights reserved.
22// Licensed under the MIT License.
33
4- package com .azure .cosmos .examples .clientmetrics .async ;
4+ package com .azure .cosmos .examples .prometheus .async ;
55
66import com .azure .cosmos .ConsistencyLevel ;
77import com .azure .cosmos .CosmosAsyncClient ;
88import com .azure .cosmos .CosmosAsyncContainer ;
99import com .azure .cosmos .CosmosAsyncDatabase ;
1010import com .azure .cosmos .CosmosClientBuilder ;
1111import com .azure .cosmos .CosmosDiagnostics ;
12- import com .azure .cosmos .CosmosException ;
1312import com .azure .cosmos .examples .common .AccountSettings ;
1413import com .azure .cosmos .examples .common .Family ;
1514import com .azure .cosmos .models .CosmosClientTelemetryConfig ;
2019import com .azure .cosmos .models .CosmosItemRequestOptions ;
2120import com .azure .cosmos .models .CosmosItemResponse ;
2221import com .azure .cosmos .models .CosmosMicrometerMetricsOptions ;
23- import com .azure .cosmos .models .CosmosQueryRequestOptions ;
2422import com .azure .cosmos .models .PartitionKey ;
2523import com .azure .cosmos .models .ThroughputProperties ;
26- import com .azure .cosmos .util .CosmosPagedFlux ;
24+ import com .azure .cosmos .test .faultinjection .FaultInjectionConditionBuilder ;
25+ import com .azure .cosmos .test .faultinjection .FaultInjectionOperationType ;
26+ import com .azure .cosmos .test .faultinjection .FaultInjectionResultBuilders ;
27+ import com .azure .cosmos .test .faultinjection .FaultInjectionRule ;
28+ import com .azure .cosmos .test .faultinjection .FaultInjectionRuleBuilder ;
29+ import com .azure .cosmos .test .faultinjection .FaultInjectionServerErrorType ;
2730import com .fasterxml .jackson .databind .JsonNode ;
2831import com .sun .net .httpserver .HttpServer ;
2932import io .micrometer .prometheus .PrometheusConfig ;
3639import java .io .IOException ;
3740import java .io .OutputStream ;
3841import java .net .InetSocketAddress ;
42+ import java .time .Duration ;
3943import java .util .ArrayList ;
44+ import java .util .List ;
4045import java .util .UUID ;
4146import java .util .concurrent .atomic .AtomicInteger ;
4247
48+ import static com .azure .cosmos .examples .common .Profile .generateDocs ;
49+
4350public class CosmosClientMetricsQuickStartAsync {
4451
4552 private CosmosAsyncClient client ;
4653
47- private final String databaseName = "AzureSampleFamilyDB " ;
54+ private final String databaseName = "ClientMetricsPrometheusTestDB " ;
4855 private final String containerName = "FamilyContainer" ;
4956 private final String documentId = UUID .randomUUID ().toString ();
5057 private final String documentLastName = "Witherspoon" ;
@@ -66,8 +73,13 @@ public void close() {
6673 public static void main (String [] args ) {
6774 CosmosClientMetricsQuickStartAsync quickStart = new CosmosClientMetricsQuickStartAsync ();
6875
76+
77+
78+
79+
6980 try {
7081 logger .info ("Starting ASYNC main" );
82+
7183 quickStart .clientMetricsDemo ();
7284 logger .info ("Demo complete, please hold while resources are released" );
7385 } catch (Exception e ) {
@@ -82,6 +94,24 @@ private void clientMetricsDemo() throws Exception {
8294
8395 logger .info ("Using Azure Cosmos DB endpoint: {}" , AccountSettings .HOST );
8496
97+ FaultInjectionRule serverConnectionDelayRule =
98+ new FaultInjectionRuleBuilder ("ServerError-ConnectionTimeout" )
99+ .condition (
100+ new FaultInjectionConditionBuilder ()
101+ .operationType (FaultInjectionOperationType .CREATE_ITEM )
102+ .build ()
103+ )
104+ .result (
105+ FaultInjectionResultBuilders
106+ .getResultBuilder (FaultInjectionServerErrorType .RESPONSE_DELAY )
107+ .delay (Duration .ofSeconds (6 )) // default connection timeout is 5s
108+ .times (1 )
109+ .build ()
110+ )
111+ .duration (Duration .ofMillis (10 ))
112+ .hitLimit (2 )
113+ .build ();
114+
85115
86116 PrometheusMeterRegistry prometheusRegistry = new PrometheusMeterRegistry (PrometheusConfig .DEFAULT );
87117 CosmosClientTelemetryConfig telemetryConfig = new CosmosClientTelemetryConfig ()
@@ -105,6 +135,7 @@ private void clientMetricsDemo() throws Exception {
105135 }
106136
107137
138+
108139 // Create sync client
109140 client = new CosmosClientBuilder ()
110141 .endpoint (AccountSettings .HOST )
@@ -118,12 +149,11 @@ private void clientMetricsDemo() throws Exception {
118149 createDatabaseIfNotExists ();
119150 createContainerIfNotExists ();
120151
121- createDocuments ();
122- readDocumentById ();
123- readDocumentDoesntExist ();
124- queryDocuments ();
125- replaceDocument ();
126- upsertDocument ();
152+ //CosmosFaultInjectionHelper.configureFaultInjectionRules(container, Arrays.asList(serverConnectionDelayRule)).block();
153+
154+ docs = generateDocs (NUMBER_OF_DOCS );
155+ createManyDocuments ();
156+ readManyDocuments ();
127157 pressAnyKeyToContinue ("Press any key to continue ..." );
128158 }
129159
@@ -137,50 +167,6 @@ private void pressAnyKeyToContinue(String message) {
137167 }
138168 }
139169
140- /* private static MeterRegistry createConsoleLoggingMeterRegistry() {
141-
142- final MetricRegistry dropwizardRegistry = new MetricRegistry();
143-
144- final ConsoleReporter consoleReporter = ConsoleReporter
145- .forRegistry(dropwizardRegistry)
146- .convertRatesTo(TimeUnit.SECONDS)
147- .convertDurationsTo(TimeUnit.MILLISECONDS)
148- .build();
149-
150- consoleReporter.start(1, TimeUnit.SECONDS);
151-
152- DropwizardConfig dropwizardConfig = new DropwizardConfig() {
153-
154- @Override
155- public String get(@Nullable String key) {
156- return null;
157- }
158-
159- @Override
160- public String prefix() {
161- return "console";
162- }
163-
164- };
165-
166- final DropwizardMeterRegistry consoleLoggingRegistry = new DropwizardMeterRegistry(
167- dropwizardConfig, dropwizardRegistry, HierarchicalNameMapper.DEFAULT, Clock.SYSTEM) {
168- @Override
169- protected Double nullGaugeValue() {
170- return Double.NaN;
171- }
172-
173- @Override
174- public void close() {
175- super.close();
176- consoleReporter.stop();
177- consoleReporter.close();
178- }
179- };
180-
181- consoleLoggingRegistry.config().namingConvention(NamingConvention.dot);
182- return consoleLoggingRegistry;
183- }*/
184170
185171 // Database Diagnostics
186172 private void createDatabaseIfNotExists () throws Exception {
@@ -204,10 +190,10 @@ private void createContainerIfNotExists() throws Exception {
204190
205191 // Create container if not exists
206192 CosmosContainerProperties containerProperties =
207- new CosmosContainerProperties (containerName , "/lastName " );
193+ new CosmosContainerProperties (containerName , "/id " );
208194
209195 // Provision throughput
210- ThroughputProperties throughputProperties = ThroughputProperties .createManualThroughput (400 );
196+ ThroughputProperties throughputProperties = ThroughputProperties .createManualThroughput (10000 );
211197
212198 // Create container with 200 RU/s
213199 Mono <CosmosContainerResponse > containerResponseMono = database .createContainerIfNotExists (containerProperties ,
@@ -242,9 +228,7 @@ private void createDocuments() throws Exception {
242228 logger .info ("Done." );
243229 }
244230
245- private void createManyDocuments (ArrayList <JsonNode > docs ) throws Exception {
246- docs = c
247- final long startTime = System .currentTimeMillis ();
231+ private void createManyDocuments () throws Exception {
248232 Flux .fromIterable (docs ).flatMap (doc -> container .createItem (doc ))
249233 .flatMap (itemResponse -> {
250234 if (itemResponse .getStatusCode () == 201 ) {
@@ -261,117 +245,28 @@ private void createManyDocuments(ArrayList<JsonNode> docs) throws Exception {
261245
262246 }
263247
264- // Document read
265- private void readDocumentById () throws Exception {
266- logger .info ("Read document by ID : {}" , documentId );
267-
268- // Read document by ID
269- Mono <CosmosItemResponse <Family >> itemResponseMono = container .readItem (documentId ,
270- new PartitionKey (documentLastName ), Family .class );
271-
272- CosmosItemResponse <Family > familyCosmosItemResponse = itemResponseMono .block ();
273- CosmosDiagnostics diagnostics = familyCosmosItemResponse .getDiagnostics ();
274- logger .info ("Read item diagnostics : {}" , diagnostics );
275-
276- Family family = familyCosmosItemResponse .getItem ();
277-
278- // Check result
279- logger .info ("Finished reading family {} with partition key {}" , family .getId (), family .getLastName ());
280-
281- logger .info ("Done." );
282- }
283-
284- // Document read doesn't exist
285- private void readDocumentDoesntExist () throws Exception {
286- logger .info ("Read document by ID : bad-ID" );
287-
288- // Read document by ID
289- try {
290- CosmosItemResponse <Family > familyCosmosItemResponse = container .readItem ("bad-ID" ,
291- new PartitionKey ("bad-lastName" ), Family .class ).block ();
292- } catch (CosmosException cosmosException ) {
293- CosmosDiagnostics diagnostics = cosmosException .getDiagnostics ();
294- logger .info ("Read item exception diagnostics : {}" , diagnostics );
248+ private void readManyDocuments () throws InterruptedException {
249+ // collect the ids that were generated when writing the data.
250+ List <String > list = new ArrayList <String >();
251+ for (final JsonNode doc : docs ) {
252+ list .add (doc .get ("id" ).asText ());
295253 }
296254
297- logger .info ("Done." );
298- }
299-
300- private void queryDocuments () throws Exception {
301- logger .info ("Query documents in the container : {}" , containerName );
302-
303- String sql = "SELECT * FROM c WHERE c.lastName = 'Witherspoon'" ;
304-
305- CosmosPagedFlux <Family > filteredFamilies = container .queryItems (sql , new CosmosQueryRequestOptions (),
306- Family .class );
307-
308- // Add handler to capture diagnostics
309- filteredFamilies = filteredFamilies .handle (familyFeedResponse -> {
310- logger .info ("Query Item diagnostics through handler : {}" , familyFeedResponse .getCosmosDiagnostics ());
311- });
312-
313- // Or capture diagnostics through byPage() APIs.
314- filteredFamilies .byPage ().toIterable ().forEach (familyFeedResponse -> {
315- logger .info ("Query item diagnostics through iterableByPage : {}" ,
316- familyFeedResponse .getCosmosDiagnostics ());
317- });
318-
319- logger .info ("Done." );
320- }
321-
322- private void replaceDocument () throws Exception {
323- logger .info ("Replace document : {}" , documentId );
324-
325- // Replace existing document with new modified document
326- Family family = new Family ();
327- family .setLastName (documentLastName );
328- family .setId (documentId );
329- family .setDistrict ("Columbia" ); // Document modification
330-
331- Mono <CosmosItemResponse <Family >> itemResponseMono =
332- container .replaceItem (family , family .getId (), new PartitionKey (family .getLastName ()),
333- new CosmosItemRequestOptions ());
334-
335- CosmosItemResponse <Family > itemResponse = itemResponseMono .block ();
336- CosmosDiagnostics diagnostics = itemResponse .getDiagnostics ();
337- logger .info ("Replace item diagnostics : {}" , diagnostics );
338- logger .info ("Request charge of replace operation: {} RU" , itemResponse .getRequestCharge ());
339-
340- logger .info ("Done." );
341- }
342-
343- private void upsertDocument () throws Exception {
344- logger .info ("Replace document : {}" , documentId );
345-
346- // Replace existing document with new modified document (contingent on modification).
347- Family family = new Family ();
348- family .setLastName (documentLastName );
349- family .setId (documentId );
350- family .setDistrict ("Columbia" ); // Document modification
351-
352- Mono <CosmosItemResponse <Family >> itemResponseMono =
353- container .upsertItem (family , new CosmosItemRequestOptions ());
354-
355- CosmosItemResponse <Family > itemResponse = itemResponseMono .block ();
356- CosmosDiagnostics diagnostics = itemResponse .getDiagnostics ();
357- logger .info ("Upsert item diagnostics : {}" , diagnostics );
358-
359- logger .info ("Done." );
360- }
361-
362- // Document delete
363- private void deleteDocument () throws Exception {
364- logger .info ("Delete document by ID {}" , documentId );
365-
366- // Delete document
367- Mono <CosmosItemResponse <Object >> itemResponseMono = container .deleteItem (documentId ,
368- new PartitionKey (documentLastName ), new CosmosItemRequestOptions ());
369-
370- CosmosItemResponse <Object > itemResponse = itemResponseMono .block ();
371- CosmosDiagnostics diagnostics = itemResponse .getDiagnostics ();
372- logger .info ("Delete item diagnostics : {}" , diagnostics );
373-
374- logger .info ("Done." );
255+ final long startTime = System .currentTimeMillis ();
256+ Flux .fromIterable (list )
257+ .flatMap (id -> container .readItem (id , new PartitionKey (id ), JsonNode .class ))
258+ .flatMap (itemResponse -> {
259+ if (itemResponse .getStatusCode () == 200 ) {
260+ logger .info ("read item with id: " + itemResponse .getItem ().get ("id" ));
261+ } else
262+ logger .info ("WARNING insert status code {} != 200" + itemResponse .getStatusCode ());
263+ request_count .getAndIncrement ();
264+ return Mono .empty ();
265+ }).subscribe ();
266+ logger .info ("Waiting while subscribed async operation completes all threads..." );
267+ while (request_count .get () < NUMBER_OF_DOCS ) {
268+ // looping while subscribed async operation completes all threads
269+ }
375270 }
376271
377272 // Database delete
@@ -390,7 +285,6 @@ private void deleteDatabase() throws Exception {
390285 private void shutdown () {
391286 try {
392287 //Clean shutdown
393- deleteDocument ();
394288 deleteDatabase ();
395289 } catch (Exception err ) {
396290 logger .error ("Deleting Cosmos DB resources failed, will still attempt to close the client" , err );
0 commit comments