Skip to content

Commit 6b35f8c

Browse files
committed
fix: fix MutateRowsAttemptCallable to avoid NPE in MetricTracer
1 parent 2dea8ab commit 6b35f8c

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

Lines changed: 8 additions & 4 deletions
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

Lines changed: 20 additions & 0 deletions
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;
@@ -60,6 +61,7 @@
6061
import java.util.concurrent.TimeUnit;
6162
import java.util.concurrent.atomic.AtomicInteger;
6263
import org.junit.After;
64+
import org.junit.Assert;
6365
import org.junit.Before;
6466
import org.junit.Rule;
6567
import org.junit.Test;
@@ -322,6 +324,24 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
322324
assertThat(attemptLatency).isIn(Range.closed(sleepTime, elapsed - sleepTime));
323325
}
324326

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

0 commit comments

Comments
 (0)