Skip to content

Commit 3e58f24

Browse files
Generalize test retry logic
1 parent 9efa100 commit 3e58f24

File tree

17 files changed

+65
-45
lines changed

17 files changed

+65
-45
lines changed

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestImpl.java

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@
1515
import datadog.trace.api.civisibility.domain.TestContext;
1616
import datadog.trace.api.civisibility.telemetry.CiVisibilityCountMetric;
1717
import datadog.trace.api.civisibility.telemetry.CiVisibilityMetricCollector;
18+
import datadog.trace.api.civisibility.telemetry.TagValue;
1819
import datadog.trace.api.civisibility.telemetry.tag.BrowserDriver;
1920
import datadog.trace.api.civisibility.telemetry.tag.EventType;
2021
import datadog.trace.api.civisibility.telemetry.tag.IsModified;
2122
import datadog.trace.api.civisibility.telemetry.tag.IsNew;
2223
import datadog.trace.api.civisibility.telemetry.tag.IsRetry;
2324
import datadog.trace.api.civisibility.telemetry.tag.IsRum;
24-
import datadog.trace.api.civisibility.telemetry.tag.RetryReason;
2525
import datadog.trace.api.civisibility.telemetry.tag.SkipReason;
2626
import datadog.trace.api.civisibility.telemetry.tag.TestFrameworkInstrumentation;
2727
import datadog.trace.api.gateway.RequestContextSlot;
@@ -263,6 +263,7 @@ public void end(@Nullable Long endTime) {
263263
span.finish();
264264
}
265265

266+
Object retryReason = span.getTag(Tags.TEST_RETRY_REASON);
266267
metricCollector.add(
267268
CiVisibilityCountMetric.EVENT_FINISHED,
268269
1,
@@ -271,25 +272,13 @@ public void end(@Nullable Long endTime) {
271272
span.getTag(Tags.TEST_IS_NEW) != null ? IsNew.TRUE : null,
272273
span.getTag(Tags.TEST_IS_MODIFIED) != null ? IsModified.TRUE : null,
273274
span.getTag(Tags.TEST_IS_RETRY) != null ? IsRetry.TRUE : null,
274-
getRetryReason(),
275+
retryReason instanceof TagValue ? (TagValue) retryReason : null,
275276
span.getTag(Tags.TEST_IS_RUM_ACTIVE) != null ? IsRum.TRUE : null,
276277
CIConstants.SELENIUM_BROWSER_DRIVER.equals(span.getTag(Tags.TEST_BROWSER_DRIVER))
277278
? BrowserDriver.SELENIUM
278279
: null);
279280
}
280281

281-
private RetryReason getRetryReason() {
282-
String retryReason = (String) span.getTag(Tags.TEST_RETRY_REASON);
283-
if (retryReason != null) {
284-
try {
285-
return RetryReason.valueOf(retryReason.toUpperCase());
286-
} catch (IllegalArgumentException e) {
287-
log.debug("Non-standard retry-reason: {}", retryReason);
288-
}
289-
}
290-
return null;
291-
}
292-
293282
/**
294283
* Tests often perform operations that involve APM instrumentations: sending an HTTP request,
295284
* executing a database query, etc. APM instrumentations create spans that correspond to those

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/events/NoOpTestEventsHandler.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import datadog.trace.api.civisibility.config.TestSourceData;
77
import datadog.trace.api.civisibility.events.TestEventsHandler;
88
import datadog.trace.api.civisibility.retry.TestRetryPolicy;
9+
import datadog.trace.api.civisibility.telemetry.tag.RetryReason;
910
import datadog.trace.api.civisibility.telemetry.tag.SkipReason;
1011
import datadog.trace.api.civisibility.telemetry.tag.TestFrameworkInstrumentation;
1112
import datadog.trace.bootstrap.ContextStore;
@@ -57,7 +58,7 @@ public void onTestStart(
5758
@Nullable String testParameters,
5859
@Nullable Collection<String> categories,
5960
@Nonnull TestSourceData testSourceData,
60-
String retryReason,
61+
RetryReason retryReason,
6162
@Nullable Long startTime) {
6263
// do nothing
6364
}

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/events/TestEventsHandlerImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import datadog.trace.api.civisibility.telemetry.CiVisibilityCountMetric;
1313
import datadog.trace.api.civisibility.telemetry.CiVisibilityMetricCollector;
1414
import datadog.trace.api.civisibility.telemetry.tag.EventType;
15+
import datadog.trace.api.civisibility.telemetry.tag.RetryReason;
1516
import datadog.trace.api.civisibility.telemetry.tag.SkipReason;
1617
import datadog.trace.api.civisibility.telemetry.tag.TestFrameworkInstrumentation;
1718
import datadog.trace.bootstrap.ContextStore;
@@ -138,7 +139,7 @@ public void onTestStart(
138139
final @Nullable String testParameters,
139140
final @Nullable Collection<String> categories,
140141
final @Nonnull TestSourceData testSourceData,
141-
final @Nullable String retryReason,
142+
final @Nullable RetryReason retryReason,
142143
final @Nullable Long startTime) {
143144
if (skipTrace(testSourceData.getTestClass())) {
144145
return;

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/retry/NeverRetry.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package datadog.trace.civisibility.retry;
22

33
import datadog.trace.api.civisibility.retry.TestRetryPolicy;
4+
import datadog.trace.api.civisibility.telemetry.tag.RetryReason;
45
import org.jetbrains.annotations.Nullable;
56

67
public class NeverRetry implements TestRetryPolicy {
@@ -20,7 +21,7 @@ public boolean suppressFailures() {
2021
}
2122

2223
@Override
23-
public boolean retry(boolean successful, long duration) {
24+
public boolean retry(boolean successful, long durationMillis) {
2425
return false;
2526
}
2627

@@ -31,7 +32,7 @@ public boolean currentExecutionIsRetry() {
3132

3233
@Nullable
3334
@Override
34-
public String currentExecutionRetryReason() {
35+
public RetryReason currentExecutionRetryReason() {
3536
return null;
3637
}
3738
}

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/retry/RetryIfFailed.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
package datadog.trace.civisibility.retry;
22

33
import datadog.trace.api.civisibility.retry.TestRetryPolicy;
4+
import datadog.trace.api.civisibility.telemetry.tag.RetryReason;
45
import java.util.concurrent.atomic.AtomicInteger;
56
import org.jetbrains.annotations.Nullable;
67

78
/** Retries a test case if it failed, up to a maximum number of times. */
89
public class RetryIfFailed implements TestRetryPolicy {
910

10-
private static final String AUTO_TEST_RETRIES = "atr";
11-
1211
private final int maxExecutions;
1312
private int executions;
1413

@@ -32,7 +31,7 @@ public boolean suppressFailures() {
3231
}
3332

3433
@Override
35-
public boolean retry(boolean successful, long duration) {
34+
public boolean retry(boolean successful, long durationMillis) {
3635
if (!successful && ++executions < maxExecutions) {
3736
totalExecutions.incrementAndGet();
3837
return true;
@@ -48,7 +47,7 @@ public boolean currentExecutionIsRetry() {
4847

4948
@Nullable
5049
@Override
51-
public String currentExecutionRetryReason() {
52-
return currentExecutionIsRetry() ? AUTO_TEST_RETRIES : null;
50+
public RetryReason currentExecutionRetryReason() {
51+
return currentExecutionIsRetry() ? RetryReason.atr : null;
5352
}
5453
}

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/retry/RetryNTimes.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
package datadog.trace.civisibility.retry;
22

33
import datadog.trace.api.civisibility.retry.TestRetryPolicy;
4+
import datadog.trace.api.civisibility.telemetry.tag.RetryReason;
45
import datadog.trace.civisibility.config.EarlyFlakeDetectionSettings;
56
import org.jetbrains.annotations.Nullable;
67

78
/** Retries a test case N times (N depends on test duration) regardless of success or failure. */
89
public class RetryNTimes implements TestRetryPolicy {
910

10-
private static final String EARLY_FLAKINESS_DETECTION = "efd";
11-
1211
private final EarlyFlakeDetectionSettings earlyFlakeDetectionSettings;
1312
private int executions;
1413
private int maxExecutions;
@@ -30,9 +29,9 @@ public boolean suppressFailures() {
3029
}
3130

3231
@Override
33-
public boolean retry(boolean successful, long duration) {
32+
public boolean retry(boolean successful, long durationMillis) {
3433
// adjust maximum retries based on the now known test duration
35-
int maxExecutionsForGivenDuration = earlyFlakeDetectionSettings.getExecutions(duration);
34+
int maxExecutionsForGivenDuration = earlyFlakeDetectionSettings.getExecutions(durationMillis);
3635
maxExecutions = Math.min(maxExecutions, maxExecutionsForGivenDuration);
3736
return ++executions < maxExecutions;
3837
}
@@ -44,7 +43,7 @@ public boolean currentExecutionIsRetry() {
4443

4544
@Nullable
4645
@Override
47-
public String currentExecutionRetryReason() {
48-
return currentExecutionIsRetry() ? EARLY_FLAKINESS_DETECTION : null;
46+
public RetryReason currentExecutionRetryReason() {
47+
return currentExecutionIsRetry() ? RetryReason.efd : null;
4948
}
5049
}

dd-java-agent/instrumentation/junit-5.3/src/main/java/datadog/trace/instrumentation/junit5/JUnitPlatformUtils.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import datadog.trace.api.civisibility.config.TestIdentifier;
66
import datadog.trace.api.civisibility.config.TestSourceData;
7+
import datadog.trace.api.civisibility.telemetry.tag.RetryReason;
78
import datadog.trace.bootstrap.instrumentation.api.AgentScope;
89
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
910
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
@@ -185,8 +186,9 @@ public static boolean isParameterizedTest(TestDescriptor testDescriptor) {
185186
return "test-template".equals(lastSegment.getType());
186187
}
187188

188-
public static String retryReason(TestDescriptor testDescriptor) {
189-
return getIDSegmentValue(testDescriptor, RETRY_DESCRIPTOR_REASON_SUFFIX);
189+
public static RetryReason retryReason(TestDescriptor testDescriptor) {
190+
String retryReasonSegment = getIDSegmentValue(testDescriptor, RETRY_DESCRIPTOR_REASON_SUFFIX);
191+
return retryReasonSegment != null ? RetryReason.valueOf(retryReasonSegment) : null;
190192
}
191193

192194
public static boolean isRetry(TestDescriptor testDescriptor) {

dd-java-agent/instrumentation/junit-5.3/src/main/java/datadog/trace/instrumentation/junit5/retry/TestDescriptorHandle.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,12 @@ public TestDescriptorHandle(TestDescriptor testDescriptor) {
4343
}
4444

4545
public TestDescriptor withIdSuffix(
46-
String segmentName, String segmentValue, String otherSegmentName, String otherSegmentValue) {
46+
String segmentName, Object segmentValue, String otherSegmentName, Object otherSegmentValue) {
4747
UniqueId uniqueId = testDescriptor.getUniqueId();
4848
UniqueId updatedId =
49-
uniqueId.append(segmentName, segmentValue).append(otherSegmentName, otherSegmentValue);
49+
uniqueId
50+
.append(segmentName, String.valueOf(segmentValue))
51+
.append(otherSegmentName, String.valueOf(otherSegmentValue));
5052
TestDescriptor descriptorClone = UnsafeUtils.tryShallowClone(testDescriptor);
5153
METHOD_HANDLES.invoke(UNIQUE_ID_SETTER, descriptorClone, updatedId);
5254
return descriptorClone;

dd-java-agent/instrumentation/karate/src/main/java/datadog/trace/instrumentation/karate/KarateTracingHook.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import datadog.trace.api.civisibility.config.TestSourceData;
2020
import datadog.trace.api.civisibility.events.TestDescriptor;
2121
import datadog.trace.api.civisibility.events.TestSuiteDescriptor;
22+
import datadog.trace.api.civisibility.telemetry.tag.RetryReason;
2223
import datadog.trace.api.civisibility.telemetry.tag.SkipReason;
2324
import datadog.trace.api.civisibility.telemetry.tag.TestFrameworkInstrumentation;
2425
import datadog.trace.bootstrap.ContextStore;
@@ -143,7 +144,7 @@ public boolean beforeScenario(ScenarioRuntime sr) {
143144
parameters,
144145
categories,
145146
TestSourceData.UNKNOWN,
146-
(String) sr.magicVariables.get(KarateUtils.RETRY_MAGIC_VARIABLE),
147+
(RetryReason) sr.magicVariables.get(KarateUtils.RETRY_MAGIC_VARIABLE),
147148
null);
148149
return true;
149150
}

dd-java-agent/instrumentation/testng/src/main/java/datadog/trace/instrumentation/testng/TracingListener.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import datadog.trace.api.civisibility.config.TestSourceData;
44
import datadog.trace.api.civisibility.events.TestSuiteDescriptor;
5+
import datadog.trace.api.civisibility.telemetry.tag.RetryReason;
56
import datadog.trace.api.civisibility.telemetry.tag.TestFrameworkInstrumentation;
67
import datadog.trace.instrumentation.testng.retry.RetryAnalyzer;
78
import java.util.List;
@@ -94,7 +95,7 @@ public void onTestStart(final ITestResult result) {
9495
null);
9596
}
9697

97-
private String retryReason(final ITestResult result) {
98+
private RetryReason retryReason(final ITestResult result) {
9899
IRetryAnalyzer retryAnalyzer = TestNGUtils.getRetryAnalyzer(result);
99100
if (retryAnalyzer instanceof RetryAnalyzer) {
100101
RetryAnalyzer datadogAnalyzer = (RetryAnalyzer) retryAnalyzer;

0 commit comments

Comments
 (0)