|
90 | 90 | * </pre> |
91 | 91 | * |
92 | 92 | * <p>Data may take up to 60 seconds (one periodic flush interval) to appear. |
| 93 | + * |
| 94 | + * <p><b>Note on Cloud Monitoring verification:</b> This test does not programmatically verify that |
| 95 | + * metrics are successfully received by the Cloud Monitoring backend. Querying Cloud Monitoring for |
| 96 | + * recently written metrics can be flaky due to ingestion delays (which can take up to 10 minutes |
| 97 | + * for new metrics). Following the strategy used in tracing tests (which only use in-memory |
| 98 | + * exporters), this test relies on {@link InMemoryMetricReader} to verify that metrics are correctly |
| 99 | + * generated with expected attributes. |
93 | 100 | */ |
94 | 101 | @RunWith(Parameterized.class) |
95 | 102 | @SuppressWarnings("checkstyle:abbreviationaswordinname") |
@@ -389,99 +396,5 @@ private static boolean dataContainsStringAttribute( |
389 | 396 | String actual = point.getAttributes().get(AttributeKey.stringKey(attributeKey)); |
390 | 397 | return expectedValue.equals(actual); |
391 | 398 | } |
392 | | - @Test |
393 | | - public void metricsExportedToCloudMonitoring() throws Exception { |
394 | | - // Perform an operation to generate metrics |
395 | | - Key key = datastore.newKeyFactory().setKind(kind).newKey("metrics-it-entity"); |
396 | | - Entity initial = Entity.newBuilder(key).set("value", 0L).build(); |
397 | | - datastore.put(initial); |
398 | | - |
399 | | - datastore.runInTransaction( |
400 | | - tx -> { |
401 | | - Entity current = tx.get(key); |
402 | | - tx.put(Entity.newBuilder(current).set("value", current.getLong("value") + 1).build()); |
403 | | - return null; |
404 | | - }); |
405 | | - |
406 | | - // Perform a lookup to generate GAX metrics |
407 | | - datastore.get(key); |
408 | | - |
409 | | - // Clean up entity before closing client |
410 | | - datastore.delete(key); |
411 | | - |
412 | | - // Close client to force flush metrics |
413 | | - datastore.close(); |
414 | | - isDatastoreClosed = true; |
415 | | - |
416 | | - // List of metrics to verify in Cloud Monitoring |
417 | | - java.util.List<String> metricNames = Arrays.asList( |
418 | | - TelemetryConstants.METRIC_NAME_TRANSACTION_LATENCY, |
419 | | - TelemetryConstants.METRIC_NAME_TRANSACTION_ATTEMPT_COUNT, |
420 | | - TelemetryConstants.METRIC_PREFIX + "/operation_latencies", |
421 | | - TelemetryConstants.METRIC_PREFIX + "/attempt_latencies", |
422 | | - TelemetryConstants.METRIC_PREFIX + "/operation_count", |
423 | | - TelemetryConstants.METRIC_PREFIX + "/attempt_count" |
424 | | - ); |
425 | | - |
426 | | - for (String metricName : metricNames) { |
427 | | - String filter = "metric.type = \"" + metricName + "\""; |
428 | | - boolean found = verifyWithPolling(filter); |
429 | | - assertWithMessage("Metric " + metricName + " should be present in Cloud Monitoring").that(found).isTrue(); |
430 | | - } |
431 | | - } |
432 | 399 |
|
433 | | - private boolean verifyWithPolling(String filter) throws Exception { |
434 | | - // Try to read immediately first |
435 | | - if (isMetricPresent(filter)) { |
436 | | - System.out.println("Metric found immediately!"); |
437 | | - return true; |
438 | | - } |
439 | | - |
440 | | - // Fallback to short polling loop (30 seconds total) |
441 | | - long startTimeMillis = System.currentTimeMillis(); |
442 | | - int attempts = 0; |
443 | | - while (System.currentTimeMillis() - startTimeMillis < 30000) { |
444 | | - attempts++; |
445 | | - System.out.println("Polling Cloud Monitoring for metric (attempt " + attempts + ")..."); |
446 | | - if (isMetricPresent(filter)) { |
447 | | - return true; |
448 | | - } |
449 | | - Thread.sleep(5000); // Wait 5 seconds between attempts |
450 | | - } |
451 | | - return false; |
452 | | - } |
453 | | - |
454 | | - private boolean isMetricPresent(String filter) throws Exception { |
455 | | - try (MetricServiceClient client = MetricServiceClient.create()) { |
456 | | - String name = "projects/" + PROJECT_ID; |
457 | | - |
458 | | - // Use a time interval covering the last 5 minutes |
459 | | - long now = System.currentTimeMillis(); |
460 | | - Timestamp endTime = Timestamp.newBuilder().setSeconds(now / 1000).build(); |
461 | | - Timestamp startTime = Timestamp.newBuilder().setSeconds((now - 300000) / 1000).build(); |
462 | | - |
463 | | - TimeInterval interval = TimeInterval.newBuilder() |
464 | | - .setStartTime(startTime) |
465 | | - .setEndTime(endTime) |
466 | | - .build(); |
467 | | - |
468 | | - ListTimeSeriesRequest request = ListTimeSeriesRequest.newBuilder() |
469 | | - .setName(name) |
470 | | - .setFilter(filter) |
471 | | - .setInterval(interval) |
472 | | - .setView(ListTimeSeriesRequest.TimeSeriesView.FULL) |
473 | | - .build(); |
474 | | - |
475 | | - try { |
476 | | - MetricServiceClient.ListTimeSeriesPagedResponse response = client.listTimeSeries(request); |
477 | | - return response.iterateAll().iterator().hasNext(); |
478 | | - } catch (ApiException e) { |
479 | | - if (e.getStatusCode().getCode() == com.google.api.gax.rpc.StatusCode.Code.NOT_FOUND) { |
480 | | - System.out.println("Metric not found yet (NOT_FOUND status)."); |
481 | | - return false; |
482 | | - } |
483 | | - throw e; |
484 | | - } |
485 | | - } |
486 | | - } |
487 | 400 | } |
0 commit comments