Skip to content

Commit b550bc8

Browse files
Implement telemetry for CI Visibility APIs (#6667)
1 parent 85a5f5a commit b550bc8

14 files changed

Lines changed: 308 additions & 40 deletions

File tree

dd-java-agent/agent-ci-visibility/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ excludedClassesCoverage += [
3838
"datadog.trace.civisibility.config.CachingModuleExecutionSettingsFactory",
3939
"datadog.trace.civisibility.config.CachingModuleExecutionSettingsFactory.Key",
4040
"datadog.trace.civisibility.config.CiVisibilitySettings",
41+
"datadog.trace.civisibility.config.ConfigurationApiImpl",
4142
"datadog.trace.civisibility.config.ConfigurationApiImpl.MultiEnvelopeDto",
4243
"datadog.trace.civisibility.config.ConfigurationApi.1",
4344
"datadog.trace.civisibility.config.ModuleExecutionSettingsFactoryImpl",

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

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

33
import datadog.trace.api.Config;
44
import datadog.trace.api.civisibility.config.ModuleExecutionSettings;
5+
import datadog.trace.api.civisibility.telemetry.CiVisibilityMetricCollector;
56
import datadog.trace.api.git.GitInfoProvider;
67
import datadog.trace.civisibility.ci.CIInfo;
78
import datadog.trace.civisibility.ci.CIProviderInfo;
@@ -61,6 +62,7 @@ public class CiVisibilityRepoServices {
6162
gitDataUploader =
6263
buildGitDataUploader(
6364
services.config,
65+
services.metricCollector,
6466
services.gitInfoProvider,
6567
services.gitClientFactory,
6668
services.backendApi,
@@ -75,7 +77,12 @@ public class CiVisibilityRepoServices {
7577
} else {
7678
moduleExecutionSettingsFactory =
7779
buildModuleExecutionSettingsFactory(
78-
services.config, services.backendApi, gitDataUploader, repoIndexProvider, repoRoot);
80+
services.config,
81+
services.metricCollector,
82+
services.backendApi,
83+
gitDataUploader,
84+
repoIndexProvider,
85+
repoRoot);
7986
}
8087
}
8188

@@ -112,6 +119,7 @@ private static ModuleExecutionSettingsFactory buildModuleExecutionSettingsFetche
112119

113120
private static ModuleExecutionSettingsFactory buildModuleExecutionSettingsFactory(
114121
Config config,
122+
CiVisibilityMetricCollector metricCollector,
115123
BackendApi backendApi,
116124
GitDataUploader gitDataUploader,
117125
RepoIndexProvider repoIndexProvider,
@@ -122,7 +130,7 @@ private static ModuleExecutionSettingsFactory buildModuleExecutionSettingsFactor
122130
"Remote config and skippable tests requests will be skipped since backend API client could not be created");
123131
configurationApi = ConfigurationApi.NO_OP;
124132
} else {
125-
configurationApi = new ConfigurationApiImpl(backendApi);
133+
configurationApi = new ConfigurationApiImpl(backendApi, metricCollector);
126134
}
127135
return new CachingModuleExecutionSettingsFactory(
128136
config,
@@ -132,6 +140,7 @@ private static ModuleExecutionSettingsFactory buildModuleExecutionSettingsFactor
132140

133141
private static GitDataUploader buildGitDataUploader(
134142
Config config,
143+
CiVisibilityMetricCollector metricCollector,
135144
GitInfoProvider gitInfoProvider,
136145
GitClient.Factory gitClientFactory,
137146
BackendApi backendApi,
@@ -153,10 +162,10 @@ private static GitDataUploader buildGitDataUploader(
153162
}
154163

155164
String remoteName = config.getCiVisibilityGitRemoteName();
156-
GitDataApi gitDataApi = new GitDataApi(backendApi);
165+
GitDataApi gitDataApi = new GitDataApi(backendApi, metricCollector);
157166
GitClient gitClient = gitClientFactory.create(repoRoot);
158167
return new GitDataUploaderImpl(
159-
config, gitDataApi, gitClient, gitInfoProvider, repoRoot, remoteName);
168+
config, metricCollector, gitDataApi, gitClient, gitInfoProvider, repoRoot, remoteName);
160169
}
161170

162171
private static SourcePathResolver buildSourcePathResolver(
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
package datadog.trace.civisibility.communication;
22

3+
import datadog.communication.http.OkHttpUtils;
34
import datadog.trace.civisibility.utils.IOThrowingFunction;
45
import java.io.IOException;
56
import java.io.InputStream;
7+
import javax.annotation.Nullable;
68
import okhttp3.RequestBody;
79

810
/** API for posting HTTP requests to backend */
911
public interface BackendApi {
1012

11-
<T> T post(String uri, RequestBody requestBody, IOThrowingFunction<InputStream, T> responseParser)
13+
<T> T post(
14+
String uri,
15+
RequestBody requestBody,
16+
IOThrowingFunction<InputStream, T> responseParser,
17+
@Nullable OkHttpUtils.CustomListener requestListener)
1218
throws IOException;
1319
}

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/communication/EvpProxyApi.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.io.IOException;
77
import java.io.InputStream;
88
import java.util.zip.GZIPInputStream;
9+
import javax.annotation.Nullable;
910
import okhttp3.HttpUrl;
1011
import okhttp3.OkHttpClient;
1112
import okhttp3.Request;
@@ -56,7 +57,10 @@ public EvpProxyApi(
5657

5758
@Override
5859
public <T> T post(
59-
String uri, RequestBody requestBody, IOThrowingFunction<InputStream, T> responseParser)
60+
String uri,
61+
RequestBody requestBody,
62+
IOThrowingFunction<InputStream, T> responseParser,
63+
@Nullable OkHttpUtils.CustomListener requestListener)
6064
throws IOException {
6165
final HttpUrl url = evpProxyUrl.resolve(uri);
6266

@@ -67,6 +71,10 @@ public <T> T post(
6771
.addHeader(X_DATADOG_TRACE_ID_HEADER, traceId)
6872
.addHeader(X_DATADOG_PARENT_ID_HEADER, traceId);
6973

74+
if (requestListener != null) {
75+
requestBuilder.tag(OkHttpUtils.CustomListener.class, requestListener);
76+
}
77+
7078
if (gzipEnabled) {
7179
requestBuilder.addHeader(ACCEPT_ENCODING_HEADER, GZIP_ENCODING);
7280
}

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/communication/IntakeApi.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.io.IOException;
77
import java.io.InputStream;
88
import java.util.zip.GZIPInputStream;
9+
import javax.annotation.Nullable;
910
import okhttp3.HttpUrl;
1011
import okhttp3.OkHttpClient;
1112
import okhttp3.Request;
@@ -61,7 +62,10 @@ public IntakeApi(
6162

6263
@Override
6364
public <T> T post(
64-
String uri, RequestBody requestBody, IOThrowingFunction<InputStream, T> responseParser)
65+
String uri,
66+
RequestBody requestBody,
67+
IOThrowingFunction<InputStream, T> responseParser,
68+
@Nullable OkHttpUtils.CustomListener requestListener)
6569
throws IOException {
6670
HttpUrl url = hostUrl.resolve(uri);
6771
Request.Builder requestBuilder =
@@ -72,6 +76,10 @@ public <T> T post(
7276
.addHeader(X_DATADOG_TRACE_ID_HEADER, traceId)
7377
.addHeader(X_DATADOG_PARENT_ID_HEADER, traceId);
7478

79+
if (requestListener != null) {
80+
requestBuilder.tag(OkHttpUtils.CustomListener.class, requestListener);
81+
}
82+
7583
if (gzipEnabled) {
7684
requestBuilder.addHeader(ACCEPT_ENCODING_HEADER, GZIP_ENCODING);
7785
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package datadog.trace.civisibility.communication;
2+
3+
import datadog.communication.http.OkHttpUtils;
4+
import datadog.trace.api.civisibility.telemetry.CiVisibilityCountMetric;
5+
import datadog.trace.api.civisibility.telemetry.CiVisibilityDistributionMetric;
6+
import datadog.trace.api.civisibility.telemetry.CiVisibilityMetricCollector;
7+
import datadog.trace.api.civisibility.telemetry.tag.ErrorType;
8+
import java.io.IOException;
9+
import javax.annotation.Nullable;
10+
import okhttp3.Call;
11+
import okhttp3.Response;
12+
13+
public class TelemetryListener extends OkHttpUtils.CustomListener {
14+
15+
private final CiVisibilityMetricCollector metricCollector;
16+
private final @Nullable CiVisibilityCountMetric requestCountMetric;
17+
private final @Nullable CiVisibilityCountMetric requestErrorsMetric;
18+
private final @Nullable CiVisibilityDistributionMetric requestBytesMetric;
19+
private final @Nullable CiVisibilityDistributionMetric requestDurationMetric;
20+
private final @Nullable CiVisibilityDistributionMetric responseBytesMetric;
21+
private long callStartTimestamp;
22+
23+
private TelemetryListener(
24+
CiVisibilityMetricCollector metricCollector,
25+
@Nullable CiVisibilityCountMetric requestCountMetric,
26+
@Nullable CiVisibilityCountMetric requestErrorsMetric,
27+
@Nullable CiVisibilityDistributionMetric requestBytesMetric,
28+
@Nullable CiVisibilityDistributionMetric requestDurationMetric,
29+
@Nullable CiVisibilityDistributionMetric responseBytesMetric) {
30+
this.metricCollector = metricCollector;
31+
this.requestCountMetric = requestCountMetric;
32+
this.requestErrorsMetric = requestErrorsMetric;
33+
this.requestBytesMetric = requestBytesMetric;
34+
this.requestDurationMetric = requestDurationMetric;
35+
this.responseBytesMetric = responseBytesMetric;
36+
}
37+
38+
public void callStart(Call call) {
39+
callStartTimestamp = System.currentTimeMillis();
40+
if (requestCountMetric != null) {
41+
metricCollector.add(requestCountMetric, 1);
42+
}
43+
}
44+
45+
public void requestBodyEnd(Call call, long byteCount) {
46+
if (requestBytesMetric != null) {
47+
metricCollector.add(requestBytesMetric, (int) byteCount);
48+
}
49+
}
50+
51+
public void responseHeadersEnd(Call call, Response response) {
52+
if (requestErrorsMetric != null) {
53+
if (!response.isSuccessful()) {
54+
int responseCode = response.code();
55+
metricCollector.add(requestErrorsMetric, 1, ErrorType.from(responseCode));
56+
}
57+
}
58+
}
59+
60+
@Override
61+
public void responseBodyEnd(Call call, long byteCount) {
62+
if (responseBytesMetric != null) {
63+
metricCollector.add(responseBytesMetric, (int) byteCount);
64+
}
65+
}
66+
67+
public void callEnd(Call call) {
68+
if (requestDurationMetric != null) {
69+
int durationMillis = (int) (System.currentTimeMillis() - callStartTimestamp);
70+
metricCollector.add(requestDurationMetric, durationMillis);
71+
}
72+
}
73+
74+
public void callFailed(Call call, IOException ioe) {
75+
if (requestDurationMetric != null) {
76+
int durationMillis = (int) (System.currentTimeMillis() - callStartTimestamp);
77+
metricCollector.add(requestDurationMetric, durationMillis);
78+
}
79+
80+
if (requestErrorsMetric != null) {
81+
metricCollector.add(requestErrorsMetric, 1, ErrorType.NETWORK);
82+
}
83+
}
84+
85+
public static final class Builder {
86+
private final CiVisibilityMetricCollector metricCollector;
87+
private @Nullable CiVisibilityCountMetric requestCountMetric;
88+
private @Nullable CiVisibilityCountMetric requestErrorsMetric;
89+
private @Nullable CiVisibilityDistributionMetric requestBytesMetric;
90+
private @Nullable CiVisibilityDistributionMetric requestDurationMetric;
91+
private @Nullable CiVisibilityDistributionMetric responseBytesMetric;
92+
93+
public Builder(CiVisibilityMetricCollector metricCollector) {
94+
this.metricCollector = metricCollector;
95+
}
96+
97+
public Builder requestCount(@Nullable CiVisibilityCountMetric requestCountMetric) {
98+
this.requestCountMetric = requestCountMetric;
99+
return this;
100+
}
101+
102+
public Builder requestErrors(@Nullable CiVisibilityCountMetric requestErrorsMetric) {
103+
this.requestErrorsMetric = requestErrorsMetric;
104+
return this;
105+
}
106+
107+
public Builder requestBytes(@Nullable CiVisibilityDistributionMetric requestBytesMetric) {
108+
this.requestBytesMetric = requestBytesMetric;
109+
return this;
110+
}
111+
112+
public Builder requestDuration(@Nullable CiVisibilityDistributionMetric requestDurationMetric) {
113+
this.requestDurationMetric = requestDurationMetric;
114+
return this;
115+
}
116+
117+
public Builder responseBytes(@Nullable CiVisibilityDistributionMetric responseBytesMetric) {
118+
this.responseBytesMetric = responseBytesMetric;
119+
return this;
120+
}
121+
122+
public OkHttpUtils.CustomListener build() {
123+
return new TelemetryListener(
124+
metricCollector,
125+
requestCountMetric,
126+
requestErrorsMetric,
127+
requestBytesMetric,
128+
requestDurationMetric,
129+
responseBytesMetric);
130+
}
131+
}
132+
}

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/config/CiVisibilitySettings.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,31 @@
55
public class CiVisibilitySettings {
66

77
public static final CiVisibilitySettings DEFAULT =
8-
new CiVisibilitySettings(false, false, false, false);
8+
new CiVisibilitySettings(false, false, false, false, false);
99

10+
private final boolean itr_enabled;
1011
private final boolean code_coverage;
1112
private final boolean tests_skipping;
1213
private final boolean require_git;
1314
private final boolean flaky_test_retries_enabled;
1415

1516
public CiVisibilitySettings(
17+
boolean itr_enabled,
1618
boolean code_coverage,
1719
boolean tests_skipping,
1820
boolean require_git,
1921
boolean flaky_test_retries_enabled) {
22+
this.itr_enabled = itr_enabled;
2023
this.code_coverage = code_coverage;
2124
this.tests_skipping = tests_skipping;
2225
this.require_git = require_git;
2326
this.flaky_test_retries_enabled = flaky_test_retries_enabled;
2427
}
2528

29+
public boolean isItrEnabled() {
30+
return itr_enabled;
31+
}
32+
2633
public boolean isCodeCoverageEnabled() {
2734
return code_coverage;
2835
}

0 commit comments

Comments
 (0)