Skip to content

Commit

Permalink
fix: move resource detection to the first export to avoid slow start (g…
Browse files Browse the repository at this point in the history
…oogleapis#2450)

Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly:
- [ ] Make sure to open an issue as a [bug/issue](https://togithub.com/googleapis/java-bigtable/issues/new/choose) before writing your code!  That way we can discuss the change, evaluate designs, and agree on the general idea
- [ ] Ensure the tests and linter pass
- [ ] Code coverage does not decrease (if any source code was changed)
- [ ] Appropriate docs were updated (if necessary)
- [ ] Rollback plan is reviewed and LGTMed
- [ ] All new data plane features have a completed end to end testing plan

Fixes #<issue_number_goes_here> ☕️

If you write sample code, please follow the [samples format](
https://togithub.com/GoogleCloudPlatform/java-docs-samples/blob/main/SAMPLE_FORMAT.md).
  • Loading branch information
mutianf authored Dec 16, 2024
1 parent bb96c3e commit cec010a
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
import com.google.cloud.monitoring.v3.MetricServiceClient;
import com.google.cloud.monitoring.v3.MetricServiceSettings;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
Expand Down Expand Up @@ -96,8 +98,9 @@ public final class BigtableCloudMonitoringExporter implements MetricExporter {

private final String taskId;

// The resource the client application is running on
private final MonitoredResource applicationResource;
// Application resource is initialized on the first export, which runs on a background thread
// to avoid slowness when starting the client.
private final Supplier<MonitoredResource> applicationResource;

private final AtomicBoolean isShutdown = new AtomicBoolean(false);

Expand Down Expand Up @@ -148,28 +151,15 @@ public static BigtableCloudMonitoringExporter create(
// it as not retried for now.
settingsBuilder.createServiceTimeSeriesSettings().setSimpleTimeoutNoRetriesDuration(timeout);

// Detect the resource that the client application is running on. For example,
// this could be a GCE instance or a GKE pod. Currently, we only support GCE instance and
// GKE pod. This method will return null for everything else.
MonitoredResource applicationResource = null;
try {
applicationResource = BigtableExporterUtils.detectResource();
} catch (Exception e) {
logger.log(
Level.WARNING,
"Failed to detect resource, will skip exporting application level metrics ",
e);
}

return new BigtableCloudMonitoringExporter(
MetricServiceClient.create(settingsBuilder.build()),
applicationResource,
Suppliers.memoize(BigtableExporterUtils::detectResourceSafe),
BigtableExporterUtils.getDefaultTaskValue());
}

@VisibleForTesting
BigtableCloudMonitoringExporter(
MetricServiceClient client, @Nullable MonitoredResource applicationResource, String taskId) {
MetricServiceClient client, Supplier<MonitoredResource> applicationResource, String taskId) {
this.client = client;
this.taskId = taskId;
this.applicationResource = applicationResource;
Expand Down Expand Up @@ -257,7 +247,7 @@ public void onSuccess(List<Empty> emptyList) {
/** Export metrics associated with the resource the Application is running on. */
private CompletableResultCode exportApplicationResourceMetrics(
Collection<MetricData> collection) {
if (applicationResource == null) {
if (applicationResource.get() == null) {
return CompletableResultCode.ofSuccess();
}

Expand All @@ -276,7 +266,7 @@ private CompletableResultCode exportApplicationResourceMetrics(
try {
timeSeries =
BigtableExporterUtils.convertToApplicationResourceTimeSeries(
metricData, taskId, applicationResource);
metricData, taskId, applicationResource.get());
} catch (Throwable e) {
logger.log(
Level.WARNING,
Expand All @@ -291,7 +281,8 @@ private CompletableResultCode exportApplicationResourceMetrics(
CompletableResultCode exportCode = new CompletableResultCode();
try {
ProjectName projectName =
ProjectName.of(applicationResource.getLabelsOrThrow(APPLICATION_RESOURCE_PROJECT_ID));
ProjectName.of(
applicationResource.get().getLabelsOrThrow(APPLICATION_RESOURCE_PROJECT_ID));

gceOrGkeFuture = exportTimeSeries(projectName, timeSeries);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,20 @@ static List<TimeSeries> convertToApplicationResourceTimeSeries(
}

@Nullable
static MonitoredResource detectResource() {
static MonitoredResource detectResourceSafe() {
try {
return detectResource();
} catch (Exception e) {
logger.log(
Level.WARNING,
"Failed to detect resource, will skip exporting application level metrics ",
e);
return null;
}
}

@Nullable
private static MonitoredResource detectResource() {
GCPPlatformDetector detector = GCPPlatformDetector.DEFAULT_INSTANCE;
DetectedPlatform detectedPlatform = detector.detectPlatform();
MonitoredResource monitoredResource = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import com.google.api.gax.rpc.UnaryCallable;
import com.google.cloud.monitoring.v3.MetricServiceClient;
import com.google.cloud.monitoring.v3.stub.MetricServiceStub;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.monitoring.v3.CreateTimeSeriesRequest;
Expand Down Expand Up @@ -95,7 +96,7 @@ public void setUp() {

exporter =
new BigtableCloudMonitoringExporter(
fakeMetricServiceClient, /* applicationResource= */ null, taskId);
fakeMetricServiceClient, /* applicationResource= */ Suppliers.ofInstance(null), taskId);

attributes =
Attributes.builder()
Expand Down Expand Up @@ -308,11 +309,12 @@ public void testTimeSeriesForMetricWithGceOrGkeResource() {
BigtableCloudMonitoringExporter exporter =
new BigtableCloudMonitoringExporter(
fakeMetricServiceClient,
MonitoredResource.newBuilder()
.setType("gce-instance")
.putLabels("some-gce-key", "some-gce-value")
.putLabels("project_id", gceProjectId)
.build(),
Suppliers.ofInstance(
MonitoredResource.newBuilder()
.setType("gce-instance")
.putLabels("some-gce-key", "some-gce-value")
.putLabels("project_id", gceProjectId)
.build()),
taskId);
ArgumentCaptor<CreateTimeSeriesRequest> argumentCaptor =
ArgumentCaptor.forClass(CreateTimeSeriesRequest.class);
Expand Down

0 comments on commit cec010a

Please sign in to comment.