-
Notifications
You must be signed in to change notification settings - Fork 67
fix: httpjson callables to trace attempts (started, failed) #3300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 20 commits
6635019
944e8d6
1edf557
4db1d2b
9ab23d5
6364aab
ae1eb44
1ebc3a2
25e778f
b363a29
5c11e10
9b48dbe
c8e8a7d
af3adb5
035be17
8e2a58a
8f3331e
f647320
2df2e9f
e7bc1c3
e2385ad
58e874a
87f807a
e57b4db
58a0daa
325eba4
2120960
0630fdf
9697e8a
065b01f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,6 +43,7 @@ | |
import com.google.api.core.ApiFutures; | ||
import com.google.api.gax.core.FakeApiClock; | ||
import com.google.api.gax.core.RecordingScheduler; | ||
import com.google.api.gax.httpjson.testing.TestApiTracerFactory; | ||
import com.google.api.gax.retrying.RetrySettings; | ||
import com.google.api.gax.rpc.ApiCallContext; | ||
import com.google.api.gax.rpc.ApiException; | ||
|
@@ -80,6 +81,7 @@ class RetryingTest { | |
|
||
private final Integer initialRequest = 1; | ||
private final Integer modifiedRequest = 0; | ||
private TestApiTracerFactory tracerFactory; | ||
|
||
private final HttpJsonCallSettings<Integer, Integer> httpJsonCallSettings = | ||
HttpJsonCallSettings.<Integer, Integer>newBuilder() | ||
|
@@ -115,8 +117,11 @@ class RetryingTest { | |
void resetClock() { | ||
fakeClock = new FakeApiClock(System.nanoTime()); | ||
executor = RecordingScheduler.create(fakeClock); | ||
tracerFactory = new TestApiTracerFactory(); | ||
clientContext = | ||
ClientContext.newBuilder() | ||
// we use a custom tracer to confirm whether the retrials are being recorded. | ||
.setTracerFactory(tracerFactory) | ||
.setExecutor(executor) | ||
.setClock(fakeClock) | ||
.setDefaultCallContext(HttpJsonCallContext.createDefault()) | ||
|
@@ -130,6 +135,7 @@ void teardown() { | |
|
||
@Test | ||
void retry() { | ||
// set a retriable that will fail 3 times before returning "2" | ||
ImmutableSet<StatusCode.Code> retryable = ImmutableSet.of(Code.UNAVAILABLE); | ||
Mockito.when(callInt.futureCall((Integer) any(), (ApiCallContext) any())) | ||
.thenReturn(ApiFutures.<Integer>immediateFailedFuture(HTTP_SERVICE_UNAVAILABLE_EXCEPTION)) | ||
|
@@ -143,6 +149,10 @@ void retry() { | |
HttpJsonCallableFactory.createUnaryCallable( | ||
callInt, callSettings, httpJsonCallSettings, clientContext); | ||
assertThat(callable.call(initialRequest)).isEqualTo(2); | ||
assertThat(tracerFactory.getTracerAttemptsFailed().get()).isEqualTo(3); | ||
assertThat(tracerFactory.getTracerAttempts().get()).isEqualTo(4); | ||
assertThat(tracerFactory.getTracerOperationFailed().get()).isFalse(); | ||
assertThat(tracerFactory.getTracerFailedRetriesExhausted().get()).isFalse(); | ||
|
||
// Capture the argument passed to futureCall | ||
ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor.forClass(Integer.class); | ||
|
@@ -180,6 +190,10 @@ void retryTotalTimeoutExceeded() { | |
HttpJsonCallableFactory.createUnaryCallable( | ||
callInt, callSettings, httpJsonCallSettings, clientContext); | ||
assertThrows(ApiException.class, () -> callable.call(initialRequest)); | ||
assertThat(tracerFactory.getTracerAttempts().get()).isEqualTo(1); | ||
assertThat(tracerFactory.getTracerAttemptsFailed().get()).isEqualTo(0); | ||
assertThat(tracerFactory.getTracerFailedRetriesExhausted().get()).isFalse(); | ||
assertThat(tracerFactory.getTracerOperationFailed().get()).isTrue(); | ||
// Capture the argument passed to futureCall | ||
ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor.forClass(Integer.class); | ||
verify(callInt, atLeastOnce()).futureCall(argumentCaptor.capture(), any(ApiCallContext.class)); | ||
|
@@ -200,6 +214,10 @@ void retryMaxAttemptsExceeded() { | |
HttpJsonCallableFactory.createUnaryCallable( | ||
callInt, callSettings, httpJsonCallSettings, clientContext); | ||
assertThrows(ApiException.class, () -> callable.call(initialRequest)); | ||
assertThat(tracerFactory.getTracerAttempts().get()).isEqualTo(2); | ||
assertThat(tracerFactory.getTracerAttemptsFailed().get()).isEqualTo(1); | ||
assertThat(tracerFactory.getTracerFailedRetriesExhausted().get()).isTrue(); | ||
assertThat(tracerFactory.getTracerOperationFailed().get()).isTrue(); | ||
// Capture the argument passed to futureCall | ||
ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor.forClass(Integer.class); | ||
verify(callInt, atLeastOnce()).futureCall(argumentCaptor.capture(), any(ApiCallContext.class)); | ||
|
@@ -220,6 +238,10 @@ void retryWithinMaxAttempts() { | |
HttpJsonCallableFactory.createUnaryCallable( | ||
callInt, callSettings, httpJsonCallSettings, clientContext); | ||
assertThat(callable.call(initialRequest)).isEqualTo(2); | ||
assertThat(tracerFactory.getTracerAttempts().get()).isEqualTo(3); | ||
assertThat(tracerFactory.getTracerAttemptsFailed().get()).isEqualTo(2); | ||
assertThat(tracerFactory.getTracerFailedRetriesExhausted().get()).isFalse(); | ||
assertThat(tracerFactory.getTracerOperationFailed().get()).isFalse(); | ||
// Capture the argument passed to futureCall | ||
ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor.forClass(Integer.class); | ||
verify(callInt, atLeastOnce()).futureCall(argumentCaptor.capture(), any(ApiCallContext.class)); | ||
|
@@ -246,6 +268,10 @@ void retryOnStatusUnknown() { | |
HttpJsonCallableFactory.createUnaryCallable( | ||
callInt, callSettings, httpJsonCallSettings, clientContext); | ||
assertThat(callable.call(initialRequest)).isEqualTo(2); | ||
assertThat(tracerFactory.getTracerAttempts().get()).isEqualTo(4); | ||
assertThat(tracerFactory.getTracerAttemptsFailed().get()).isEqualTo(3); | ||
assertThat(tracerFactory.getTracerFailedRetriesExhausted().get()).isFalse(); | ||
assertThat(tracerFactory.getTracerOperationFailed().get()).isFalse(); | ||
// Capture the argument passed to futureCall | ||
ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor.forClass(Integer.class); | ||
verify(callInt, atLeastOnce()).futureCall(argumentCaptor.capture(), any(ApiCallContext.class)); | ||
|
@@ -264,6 +290,10 @@ void retryOnUnexpectedException() { | |
HttpJsonCallableFactory.createUnaryCallable( | ||
callInt, callSettings, httpJsonCallSettings, clientContext); | ||
ApiException exception = assertThrows(ApiException.class, () -> callable.call(initialRequest)); | ||
assertThat(tracerFactory.getTracerAttempts().get()).isEqualTo(1); | ||
assertThat(tracerFactory.getTracerAttemptsFailed().get()).isEqualTo(0); | ||
assertThat(tracerFactory.getTracerFailedRetriesExhausted().get()).isFalse(); | ||
assertThat(tracerFactory.getTracerOperationFailed().get()).isTrue(); | ||
assertThat(exception).hasCauseThat().isSameInstanceAs(throwable); | ||
// Capture the argument passed to futureCall | ||
ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor.forClass(Integer.class); | ||
|
@@ -293,6 +323,10 @@ void retryNoRecover() { | |
HttpJsonCallableFactory.createUnaryCallable( | ||
callInt, callSettings, httpJsonCallSettings, clientContext); | ||
ApiException exception = assertThrows(ApiException.class, () -> callable.call(initialRequest)); | ||
assertThat(tracerFactory.getTracerAttempts().get()).isEqualTo(1); | ||
assertThat(tracerFactory.getTracerAttemptsFailed().get()).isEqualTo(0); | ||
assertThat(tracerFactory.getTracerFailedRetriesExhausted().get()).isFalse(); | ||
assertThat(tracerFactory.getTracerOperationFailed().get()).isTrue(); | ||
assertThat(exception).isSameInstanceAs(apiException); | ||
// Capture the argument passed to futureCall | ||
ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor.forClass(Integer.class); | ||
|
@@ -319,6 +353,14 @@ void retryKeepFailing() { | |
|
||
UncheckedExecutionException exception = | ||
assertThrows(UncheckedExecutionException.class, () -> Futures.getUnchecked(future)); | ||
// the number of attempts varies. Here we just make sure that all of them except the last are | ||
// considered as failed | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. qq, isn't the last one also considered a failed attempt? Why is the tracerAttemptsFailed != tracerAttempts? Also, can we add the operationfailed == true check here as well? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm not sure and I agree they should be the same value since this test just fetches an exception until it can't retry anymore (retries exhausted). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. showcase has another tracer we can use to cross check |
||
// attempts and that the operation was considered as failed. | ||
assertThat(tracerFactory.getTracerAttemptsFailed().get()).isGreaterThan(0); | ||
assertThat(tracerFactory.getTracerAttemptsFailed().get()) | ||
.isEqualTo(tracerFactory.getTracerAttempts().get() - 1); | ||
assertThat(tracerFactory.getTracerFailedRetriesExhausted().get()).isTrue(); | ||
assertThat(tracerFactory.getTracerOperationFailed().get()).isTrue(); | ||
assertThat(exception).hasCauseThat().isInstanceOf(ApiException.class); | ||
assertThat(exception).hasCauseThat().hasMessageThat().contains("Unavailable"); | ||
// Capture the argument passed to futureCall | ||
|
@@ -359,6 +401,10 @@ void testKnownStatusCode() { | |
callInt, callSettings, httpJsonCallSettings, clientContext); | ||
ApiException exception = | ||
assertThrows(FailedPreconditionException.class, () -> callable.call(initialRequest)); | ||
assertThat(tracerFactory.getTracerAttempts().get()).isEqualTo(1); | ||
assertThat(tracerFactory.getTracerAttemptsFailed().get()).isEqualTo(0); | ||
assertThat(tracerFactory.getTracerFailedRetriesExhausted().get()).isFalse(); | ||
assertThat(tracerFactory.getTracerOperationFailed().get()).isTrue(); | ||
assertThat(exception.getStatusCode().getTransportCode()) | ||
.isEqualTo(HTTP_CODE_PRECONDITION_FAILED); | ||
assertThat(exception).hasMessageThat().contains("precondition failed"); | ||
|
@@ -383,6 +429,10 @@ void testUnknownStatusCode() { | |
UnknownException exception = | ||
assertThrows(UnknownException.class, () -> callable.call(initialRequest)); | ||
assertThat(exception).hasMessageThat().isEqualTo("java.lang.RuntimeException: unknown"); | ||
assertThat(tracerFactory.getTracerAttempts().get()).isEqualTo(1); | ||
assertThat(tracerFactory.getTracerAttemptsFailed().get()).isEqualTo(0); | ||
assertThat(tracerFactory.getTracerFailedRetriesExhausted().get()).isFalse(); | ||
assertThat(tracerFactory.getTracerOperationFailed().get()).isTrue(); | ||
// Capture the argument passed to futureCall | ||
ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor.forClass(Integer.class); | ||
verify(callInt, atLeastOnce()).futureCall(argumentCaptor.capture(), any(ApiCallContext.class)); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the idea of a test tracer in general. On the other hand, we should only implement what is needed for our use cases, so that we have lower chance to run into issues that are not related to our PR. For example, maybe we don't need to implement There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @lqiu96 figured that the retries exhausted event records the missing failed attempt in our tests:
I'll keep this implementation and its retries exhausted flag. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/* | ||
* Copyright 2024 Google LLC | ||
* | ||
* Redistribution and use in source and binary forms, with or without | ||
* modification, are permitted provided that the following conditions are | ||
* met: | ||
* | ||
* * Redistributions of source code must retain the above copyright | ||
* notice, this list of conditions and the following disclaimer. | ||
* * Redistributions in binary form must reproduce the above | ||
* copyright notice, this list of conditions and the following disclaimer | ||
* in the documentation and/or other materials provided with the | ||
* distribution. | ||
* * Neither the name of Google LLC nor the names of its | ||
* contributors may be used to endorse or promote products derived from | ||
* this software without specific prior written permission. | ||
* | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
*/ | ||
package com.google.api.gax.httpjson.testing; | ||
|
||
import com.google.api.gax.tracing.BaseApiTracer; | ||
import java.util.concurrent.atomic.AtomicBoolean; | ||
import java.util.concurrent.atomic.AtomicInteger; | ||
import org.threeten.bp.Duration; | ||
|
||
/** | ||
* Test tracer that keeps count of different events. See {@link TestApiTracerFactory} for more | ||
* details. | ||
*/ | ||
public class TestApiTracer extends BaseApiTracer { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should use the interface There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
|
||
private final AtomicInteger tracerAttempts; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think they can be called just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. renamed to |
||
private final AtomicInteger tracerAttemptsFailed; | ||
private final AtomicBoolean tracerOperationFailed; | ||
private final AtomicBoolean tracerFailedRetriesExhausted; | ||
|
||
public TestApiTracer( | ||
AtomicInteger tracerAttempts, | ||
AtomicInteger tracerAttemptsFailed, | ||
AtomicBoolean tracerOperationFailed, | ||
AtomicBoolean tracerFailedRetriesExhausted) { | ||
this.tracerAttempts = tracerAttempts; | ||
this.tracerAttemptsFailed = tracerAttemptsFailed; | ||
this.tracerOperationFailed = tracerOperationFailed; | ||
this.tracerFailedRetriesExhausted = tracerFailedRetriesExhausted; | ||
} | ||
|
||
@Override | ||
public void attemptFailed(Throwable error, Duration delay) { | ||
tracerAttemptsFailed.incrementAndGet(); | ||
super.attemptFailed(error, delay); | ||
} | ||
|
||
@Override | ||
public void attemptStarted(int attemptNumber) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
tracerAttempts.incrementAndGet(); | ||
super.attemptStarted(attemptNumber); | ||
} | ||
|
||
@Override | ||
public void operationFailed(Throwable error) { | ||
tracerOperationFailed.set(true); | ||
super.operationFailed(error); | ||
} | ||
|
||
@Override | ||
public void attemptFailedRetriesExhausted(Throwable error) { | ||
tracerFailedRetriesExhausted.set(true); | ||
super.attemptFailedRetriesExhausted(error); | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,75 @@ | ||||||||||||||||||
/* | ||||||||||||||||||
* Copyright 2024 Google LLC | ||||||||||||||||||
* | ||||||||||||||||||
* Redistribution and use in source and binary forms, with or without | ||||||||||||||||||
* modification, are permitted provided that the following conditions are | ||||||||||||||||||
* met: | ||||||||||||||||||
* | ||||||||||||||||||
* * Redistributions of source code must retain the above copyright | ||||||||||||||||||
* notice, this list of conditions and the following disclaimer. | ||||||||||||||||||
* * Redistributions in binary form must reproduce the above | ||||||||||||||||||
* copyright notice, this list of conditions and the following disclaimer | ||||||||||||||||||
* in the documentation and/or other materials provided with the | ||||||||||||||||||
* distribution. | ||||||||||||||||||
* * Neither the name of Google LLC nor the names of its | ||||||||||||||||||
* contributors may be used to endorse or promote products derived from | ||||||||||||||||||
* this software without specific prior written permission. | ||||||||||||||||||
* | ||||||||||||||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||||||||||||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||||||||||||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||||||||||||||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||||||||||||||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||||||||||||||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||||||||||||||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||||||||||||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||||||||||||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||||||||||||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||||||||||||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||||||||||||||
*/ | ||||||||||||||||||
package com.google.api.gax.httpjson.testing; | ||||||||||||||||||
|
||||||||||||||||||
import com.google.api.gax.tracing.ApiTracer; | ||||||||||||||||||
import com.google.api.gax.tracing.ApiTracerFactory; | ||||||||||||||||||
import com.google.api.gax.tracing.SpanName; | ||||||||||||||||||
import java.util.concurrent.atomic.AtomicBoolean; | ||||||||||||||||||
import java.util.concurrent.atomic.AtomicInteger; | ||||||||||||||||||
|
||||||||||||||||||
/** | ||||||||||||||||||
* Produces a {@link TestApiTracer}, which keeps count of the attempts made and attempts | ||||||||||||||||||
* made-and-failed. It also keeps count of the operations failed and when the retries have been | ||||||||||||||||||
* exhausted. | ||||||||||||||||||
*/ | ||||||||||||||||||
public class TestApiTracerFactory implements ApiTracerFactory { | ||||||||||||||||||
private final AtomicInteger tracerAttempts = new AtomicInteger(); | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These can be initialized within the tracer for better encapsulation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd like to initialize them in the tracer itself. However the clients only expect tracer factories, so there is no way to have control over how the actual tracers are instantiated. sdk-platform-java/gax-java/gax-httpjson/src/test/java/com/google/api/gax/httpjson/RetryingTest.java Lines 121 to 128 in 2df2e9f
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah nvm, I realized that accessing the ApiTracer instance should be enough. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
private final AtomicInteger tracerAttemptsFailed = new AtomicInteger(); | ||||||||||||||||||
private final AtomicBoolean tracerOperationFailed = new AtomicBoolean(false); | ||||||||||||||||||
private final AtomicBoolean tracerFailedRetriesExhausted = new AtomicBoolean(false); | ||||||||||||||||||
private final TestApiTracer instance = | ||||||||||||||||||
new TestApiTracer( | ||||||||||||||||||
tracerAttempts, | ||||||||||||||||||
tracerAttemptsFailed, | ||||||||||||||||||
tracerOperationFailed, | ||||||||||||||||||
tracerFailedRetriesExhausted); | ||||||||||||||||||
|
||||||||||||||||||
public AtomicInteger getTracerAttempts() { | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's better to get the tracer instance, and use the getters from the tracer in unit tests. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||
return tracerAttempts; | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
public AtomicInteger getTracerAttemptsFailed() { | ||||||||||||||||||
return tracerAttemptsFailed; | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
public AtomicBoolean getTracerOperationFailed() { | ||||||||||||||||||
return tracerOperationFailed; | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
public AtomicBoolean getTracerFailedRetriesExhausted() { | ||||||||||||||||||
return tracerFailedRetriesExhausted; | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
@Override | ||||||||||||||||||
public ApiTracer newTracer(ApiTracer parent, SpanName spanName, OperationType operationType) { | ||||||||||||||||||
return instance; | ||||||||||||||||||
} | ||||||||||||||||||
} |
Uh oh!
There was an error while loading. Please reload this page.