Skip to content

Commit 8d71020

Browse files
authored
fix: fix MutateRowsAttemptCallable to avoid NPE in MetricTracer (#557)
1 parent 8240779 commit 8d71020

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/mutaterows/MutateRowsAttemptCallable.java

+8-4
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,17 @@ public void setExternalFuture(RetryingFuture<Void> externalFuture) {
160160
@Override
161161
public Void call() {
162162
try {
163+
// externalFuture is set from MutateRowsRetryingCallable before invoking this method. It
164+
// shouldn't be null unless the code changed
163165
Preconditions.checkNotNull(
164166
externalFuture, "External future must be set before starting an attempt");
165167

168+
// attemptStared should be called at the very start of the operation. This will initialize
169+
// variables in ApiTracer and avoid exceptions when the tracer marks the attempt as finished
170+
callContext
171+
.getTracer()
172+
.attemptStarted(externalFuture.getAttemptSettings().getOverallAttemptCount());
173+
166174
Preconditions.checkState(
167175
currentRequest.getEntriesCount() > 0, "Request doesn't have any mutations to send");
168176

@@ -179,10 +187,6 @@ public Void call() {
179187
return null;
180188
}
181189

182-
callContext
183-
.getTracer()
184-
.attemptStarted(externalFuture.getAttemptSettings().getOverallAttemptCount());
185-
186190
// Make the actual call
187191
ApiFuture<List<MutateRowsResponse>> innerFuture =
188192
innerCallable.futureCall(currentRequest, currentCallContext);

google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/metrics/MetricsTracerTest.java

+20
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.google.bigtable.v2.ReadRowsResponse.CellChunk;
2727
import com.google.cloud.bigtable.data.v2.BigtableDataSettings;
2828
import com.google.cloud.bigtable.data.v2.FakeServiceHelper;
29+
import com.google.cloud.bigtable.data.v2.models.BulkMutation;
2930
import com.google.cloud.bigtable.data.v2.models.Query;
3031
import com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStub;
3132
import com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStubSettings;
@@ -46,6 +47,7 @@
4647
import java.util.concurrent.TimeUnit;
4748
import java.util.concurrent.atomic.AtomicInteger;
4849
import org.junit.After;
50+
import org.junit.Assert;
4951
import org.junit.Before;
5052
import org.junit.Rule;
5153
import org.junit.Test;
@@ -327,6 +329,24 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
327329
assertThat(attemptLatency).isIn(Range.closed(sleepTime, elapsed - sleepTime));
328330
}
329331

332+
@Test
333+
public void testInvalidRequest() throws InterruptedException {
334+
try {
335+
stub.bulkMutateRowsCallable().call(BulkMutation.create(TABLE_ID));
336+
Assert.fail("Invalid request should throw exception");
337+
} catch (IllegalStateException e) {
338+
Thread.sleep(100);
339+
// Verify that the latency is recorded with an error code (in this case UNKNOWN)
340+
long attemptLatency =
341+
getAggregationValueAsLong(
342+
RpcViewConstants.BIGTABLE_ATTEMPT_LATENCY_VIEW,
343+
ImmutableMap.of(
344+
RpcMeasureConstants.BIGTABLE_OP, TagValue.create("Bigtable.MutateRows"),
345+
RpcMeasureConstants.BIGTABLE_STATUS, TagValue.create("UNKNOWN")));
346+
assertThat(attemptLatency).isAtLeast(0);
347+
}
348+
}
349+
330350
@SuppressWarnings("unchecked")
331351
private static <T> StreamObserver<T> anyObserver(Class<T> returnType) {
332352
return (StreamObserver<T>) any(returnType);

0 commit comments

Comments
 (0)