Skip to content

Commit 6232eb0

Browse files
Merge branch 'master' into INPLAT-614
2 parents ba2423d + 6168591 commit 6232eb0

File tree

11 files changed

+143
-25
lines changed

11 files changed

+143
-25
lines changed

.gitlab-ci.yml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,12 @@ default:
137137
KUBERNETES_MEMORY_REQUEST: 8Gi
138138
KUBERNETES_MEMORY_LIMIT: 8Gi
139139
CACHE_TYPE: lib #default
140+
FF_USE_FASTZIP: "true"
141+
CACHE_COMPRESSION_LEVEL: "slowest"
142+
140143
RUNTIME_AVAILABLE_PROCESSORS_OVERRIDE: 4 # Runtime.getRuntime().availableProcessors() returns incorrect or very high values in Kubernetes
141144
cache:
142-
- key: '$CI_SERVER_VERSION-$CACHE_TYPE' # Dependencies cache. Reset the cache every time gitlab is upgraded. ~Every couple months
145+
- key: dependency-$CACHE_TYPE # Dependencies cache
143146
paths:
144147
# Cached dependencies and wrappers for gradle
145148
- .gradle/wrapper
@@ -148,8 +151,8 @@ default:
148151
policy: $DEPENDENCY_CACHE_POLICY
149152
unprotect: true
150153
fallback_keys: # Use fallback keys because all cache types are not populated. See note under: populate_dep_cache
151-
- '$CI_SERVER_VERSION-base'
152-
- '$CI_SERVER_VERSION-lib'
154+
- 'dependency-base'
155+
- 'dependency-lib'
153156
- key: $CI_PIPELINE_ID-$CACHE_TYPE # Incremental build cache. Shared by all jobs in the pipeline of the same type
154157
paths:
155158
- .gradle/caches/$GRADLE_VERSION
@@ -837,7 +840,7 @@ package-oci:
837840

838841
configure_system_tests:
839842
variables:
840-
SYSTEM_TESTS_SCENARIOS_GROUPS: "simple_onboarding,simple_onboarding_profiling,docker-ssi,lib-injection"
843+
SYSTEM_TESTS_SCENARIOS_GROUPS: "simple_onboarding,simple_onboarding_profiling,simple_onboarding_appsec,docker-ssi,lib-injection"
841844

842845
create_key:
843846
stage: generate-signing-key

communication/src/main/java/datadog/communication/ddagent/DDAgentFeaturesDiscovery.java

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package datadog.communication.ddagent;
22

3+
import static datadog.communication.http.OkHttpUtils.DATADOG_CONTAINER_ID;
4+
import static datadog.communication.http.OkHttpUtils.DATADOG_CONTAINER_TAGS_HASH;
35
import static datadog.communication.serialization.msgpack.MsgPackWriter.FIXARRAY;
4-
import static java.util.Collections.emptyList;
6+
import static java.util.Collections.emptySet;
57
import static java.util.Collections.singletonList;
6-
import static java.util.Collections.unmodifiableList;
8+
import static java.util.Collections.unmodifiableSet;
79

810
import com.squareup.moshi.JsonAdapter;
911
import com.squareup.moshi.Moshi;
1012
import com.squareup.moshi.Types;
13+
import datadog.common.container.ContainerInfo;
1114
import datadog.communication.http.OkHttpUtils;
1215
import datadog.communication.monitor.DDAgentStatsDClientManager;
1316
import datadog.communication.monitor.Monitoring;
@@ -88,8 +91,8 @@ public class DDAgentFeaturesDiscovery implements DroppingPolicy {
8891
private volatile String evpProxyEndpoint;
8992
private volatile String version;
9093
private volatile String telemetryProxyEndpoint;
91-
private volatile List<String> peerTags = emptyList();
92-
private volatile List<String> spanKindsToComputedStats = emptyList();
94+
private volatile Set<String> peerTags = emptySet();
95+
private volatile Set<String> spanKindsToComputedStats = emptySet();
9396

9497
private long lastTimeDiscovered;
9598

@@ -123,8 +126,8 @@ private void reset() {
123126
version = null;
124127
lastTimeDiscovered = 0;
125128
telemetryProxyEndpoint = null;
126-
peerTags = emptyList();
127-
spanKindsToComputedStats = emptyList();
129+
peerTags = emptySet();
130+
spanKindsToComputedStats = emptySet();
128131
}
129132

130133
/** Run feature discovery, unconditionally. */
@@ -157,11 +160,15 @@ private void doDiscovery() {
157160
// 3. fallback if the endpoint couldn't be found or the response couldn't be parsed
158161
try (Recording recording = discoveryTimer.start()) {
159162
boolean fallback = true;
160-
try (Response response =
161-
client
162-
.newCall(new Request.Builder().url(agentBaseUrl.resolve("info").url()).build())
163-
.execute()) {
163+
final Request.Builder requestBuilder =
164+
new Request.Builder().url(agentBaseUrl.resolve("info").url());
165+
final String containerId = ContainerInfo.get().getContainerId();
166+
if (containerId != null) {
167+
requestBuilder.header(DATADOG_CONTAINER_ID, containerId);
168+
}
169+
try (Response response = client.newCall(requestBuilder.build()).execute()) {
164170
if (response.isSuccessful()) {
171+
processInfoResponseHeaders(response);
165172
fallback = !processInfoResponse(response.body().string());
166173
}
167174
} catch (Throwable error) {
@@ -222,6 +229,10 @@ private String probeTracesEndpoint(String[] endpoints) {
222229
return V3_ENDPOINT;
223230
}
224231

232+
private void processInfoResponseHeaders(Response response) {
233+
ContainerInfo.get().setContainerTagsHash(response.header(DATADOG_CONTAINER_TAGS_HASH));
234+
}
235+
225236
@SuppressWarnings("unchecked")
226237
private boolean processInfoResponse(String response) {
227238
try {
@@ -295,11 +306,16 @@ private boolean processInfoResponse(String response) {
295306
|| Boolean.TRUE.equals(canDrop));
296307

297308
Object peer_tags = map.get("peer_tags");
298-
peerTags = peer_tags == null ? emptyList() : unmodifiableList((List<String>) peer_tags);
309+
peerTags =
310+
peer_tags instanceof List
311+
? unmodifiableSet(new HashSet<>((List<String>) peer_tags))
312+
: emptySet();
299313

300314
Object span_kinds = map.get("span_kinds_stats_computed");
301315
spanKindsToComputedStats =
302-
span_kinds == null ? emptyList() : unmodifiableList((List<String>) span_kinds);
316+
span_kinds instanceof List
317+
? unmodifiableSet(new HashSet<>((List<String>) span_kinds))
318+
: emptySet();
303319
}
304320
try {
305321
state = Strings.sha256(response);
@@ -357,11 +373,11 @@ public boolean supportsLongRunning() {
357373
return supportsLongRunning;
358374
}
359375

360-
public List<String> peerTags() {
376+
public Set<String> peerTags() {
361377
return peerTags;
362378
}
363379

364-
public List<String> spanKindsToComputedStats() {
380+
public Set<String> spanKindsToComputedStats() {
365381
return spanKindsToComputedStats;
366382
}
367383

communication/src/main/java/datadog/communication/http/OkHttpUtils.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ public final class OkHttpUtils {
4343
private static final String DATADOG_META_LANG_INTERPRETER = "Datadog-Meta-Lang-Interpreter";
4444
private static final String DATADOG_META_LANG_INTERPRETER_VENDOR =
4545
"Datadog-Meta-Lang-Interpreter-Vendor";
46-
private static final String DATADOG_CONTAINER_ID = "Datadog-Container-ID";
46+
public static final String DATADOG_CONTAINER_ID = "Datadog-Container-ID";
4747
private static final String DATADOG_ENTITY_ID = "Datadog-Entity-ID";
48+
public static final String DATADOG_CONTAINER_TAGS_HASH = "Datadog-Container-Tags-Hash";
4849

4950
private static final String DD_API_KEY = "DD-API-KEY";
5051

communication/src/test/groovy/datadog/communication/ddagent/DDAgentFeaturesDiscoveryTest.groovy

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package datadog.communication.ddagent
22

3+
import datadog.common.container.ContainerInfo
34
import datadog.communication.monitor.Monitoring
45
import datadog.trace.test.util.DDSpecification
56
import datadog.trace.util.Strings
67
import okhttp3.Call
8+
import okhttp3.Headers
79
import okhttp3.HttpUrl
810
import okhttp3.MediaType
911
import okhttp3.OkHttpClient
@@ -19,6 +21,8 @@ import java.nio.file.Paths
1921
import static datadog.communication.ddagent.DDAgentFeaturesDiscovery.V01_DATASTREAMS_ENDPOINT
2022
import static datadog.communication.ddagent.DDAgentFeaturesDiscovery.V6_METRICS_ENDPOINT
2123
import static datadog.communication.ddagent.DDAgentFeaturesDiscovery.V7_CONFIG_ENDPOINT
24+
import static datadog.communication.http.OkHttpUtils.DATADOG_CONTAINER_ID
25+
import static datadog.communication.http.OkHttpUtils.DATADOG_CONTAINER_TAGS_HASH
2226

2327
class DDAgentFeaturesDiscoveryTest extends DDSpecification {
2428

@@ -466,13 +470,37 @@ class DDAgentFeaturesDiscoveryTest extends DDSpecification {
466470
)
467471
}
468472

469-
def infoResponse(Request request, String json) {
473+
def "should send container id as header on the info request and parse the hash in the response"() {
474+
setup:
475+
OkHttpClient client = Mock(OkHttpClient)
476+
DDAgentFeaturesDiscovery features = new DDAgentFeaturesDiscovery(client, monitoring, agentUrl, true, true)
477+
def oldContainerId = ContainerInfo.get().getContainerId()
478+
def oldContainerTagsHash = ContainerInfo.get().getContainerTagsHash()
479+
ContainerInfo.get().setContainerId("test")
480+
481+
when: "/info requested"
482+
features.discover()
483+
484+
then:
485+
1 * client.newCall(_) >> { Request request ->
486+
assert request.header(DATADOG_CONTAINER_ID) == "test"
487+
infoResponse(request, INFO_RESPONSE, Headers.of(DATADOG_CONTAINER_TAGS_HASH, "test-hash"))
488+
}
489+
and:
490+
assert ContainerInfo.get().getContainerTagsHash() == "test-hash"
491+
cleanup:
492+
ContainerInfo.get().setContainerId(oldContainerId)
493+
ContainerInfo.get().setContainerTagsHash(oldContainerTagsHash)
494+
}
495+
496+
def infoResponse(Request request, String json, Headers headers = new Headers.Builder().build()) {
470497
return Mock(Call) {
471498
it.execute() >> new Response.Builder()
472499
.code(200)
473500
.request(request)
474501
.protocol(Protocol.HTTP_1_1)
475502
.message("")
503+
.headers(headers)
476504
.body(ResponseBody.create(MediaType.get("application/json"), json))
477505
.build()
478506
}

dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/bytebuddy/matcher/ClassLoaderMatchers.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,19 @@ public static boolean canSkipClassLoaderByName(final ClassLoader loader) {
4242
case "org.codehaus.groovy.runtime.callsite.CallSiteClassLoader":
4343
case "sun.reflect.DelegatingClassLoader":
4444
case "jdk.internal.reflect.DelegatingClassLoader":
45+
case "org.jvnet.hk2.internal.DelegatingClassLoader":
4546
case "clojure.lang.DynamicClassLoader":
4647
case "org.apache.cxf.common.util.ASMHelper$TypeHelperClassLoader":
4748
case "com.ibm.xml.xlxp2.jaxb.codegen.AbstractGeneratedStubFactory$RootStubClassLoader":
4849
case "sun.misc.Launcher$ExtClassLoader":
50+
case "org.springframework.context.support.ContextTypeMatchClassLoader$ContextOverridingClassLoader":
51+
case "org.openjdk.nashorn.internal.runtime.ScriptLoader":
52+
case "jdk.nashorn.internal.runtime.ScriptLoader":
53+
case "org.codehaus.janino.ByteArrayClassLoader":
54+
case "org.eclipse.persistence.internal.jaxb.JaxbClassLoader":
55+
case "com.alibaba.fastjson.util.ASMClassLoader":
4956
case "datadog.trace.bootstrap.DatadogClassLoader":
57+
case "datadog.trace.bootstrap.InstrumentationClassLoader":
5058
return true;
5159
}
5260
if (CHECK_EXCLUDES) {

dd-java-agent/instrumentation/karate/src/test/groovy/KarateTest.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import java.util.concurrent.CopyOnWriteArrayList
2121

2222
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass
2323

24-
@IgnoreIf(reason = "Karate instrumentation is creating an unclosed span of kind test_suite_end specifically for Java 24. Skip until we have a fix.", value = {
24+
@IgnoreIf(reason = "Karate does not support Java 24+ yet: https://github.com/karatelabs/karate/blob/master/.github/workflows/jdk-compat.yml#L18", value = {
2525
JavaVirtualMachine.isJavaVersionAtLeast(24)
2626
})
2727
@DisableTestTrace(reason = "avoid self-tracing")

dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/base/HttpClientTest.groovy

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase {
293293
status == 200
294294
assertTraces(2) {
295295
trace(size(2)) {
296+
sortSpansByStart()
296297
basicSpan(it, "parent")
297298
clientSpan(it, span(0), method)
298299
}
@@ -439,6 +440,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase {
439440
// only one trace (client).
440441
assertTraces(1) {
441442
trace(size(2)) {
443+
sortSpansByStart()
442444
basicSpan(it, "parent")
443445
clientSpan(it, span(0), method, renameService)
444446
}
@@ -482,6 +484,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase {
482484
assertTraces(1) {
483485
sortSpansByStart()
484486
trace(size(3)) {
487+
sortSpansByStart()
485488
basicSpan(it, "parent")
486489
clientSpan(it, span(0), method)
487490
basicSpan(it, "child", span(0))
@@ -721,6 +724,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase {
721724
def thrownException = ex instanceof ExecutionException ? ex.cause : ex
722725
assertTraces(1) {
723726
trace(size(2)) {
727+
sortSpansByStart()
724728
basicSpan(it, "parent", null, thrownException)
725729
clientSpan(it, span(0), method, false, false, uri, null, true, thrownException)
726730
}

dd-smoke-tests/play-2.4/src/test/groovy/datadog/smoketest/IastPlayNettySmokeTest.groovy

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package datadog.smoketest
22

3+
import datadog.trace.test.util.Flaky
34
import static java.util.concurrent.TimeUnit.SECONDS
45
import okhttp3.FormBody
56
import okhttp3.Request
@@ -8,6 +9,7 @@ import spock.lang.Shared
89
import java.nio.file.Files
910

1011

12+
@Flaky("https://datadoghq.atlassian.net/browse/APPSEC-58301")
1113
class IastPlayNettySmokeTest extends AbstractIastServerSmokeTest {
1214

1315
@Shared

dd-trace-core/src/main/java/datadog/trace/common/metrics/ConflatingMetricsAggregator.java

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

33
import static datadog.communication.ddagent.DDAgentFeaturesDiscovery.V6_METRICS_ENDPOINT;
44
import static datadog.trace.api.Functions.UTF8_ENCODE;
5+
import static datadog.trace.bootstrap.instrumentation.api.Tags.SPAN_KIND;
56
import static datadog.trace.common.metrics.AggregateMetric.ERROR_TAG;
67
import static datadog.trace.common.metrics.AggregateMetric.TOP_LEVEL_TAG;
78
import static datadog.trace.common.metrics.SignalItem.ReportSignal.REPORT;
@@ -230,7 +231,14 @@ public boolean publish(List<? extends CoreSpan<?>> trace) {
230231
}
231232

232233
private boolean shouldComputeMetric(CoreSpan<?> span) {
233-
return (span.isMeasured() || span.isTopLevel()) && span.getDurationNano() > 0;
234+
return (span.isMeasured() || span.isTopLevel() || spanKindEligible(span))
235+
&& span.getDurationNano() > 0;
236+
}
237+
238+
private boolean spanKindEligible(CoreSpan<?> span) {
239+
final Object spanKind = span.getTag(SPAN_KIND);
240+
// use toString since it could be a CharSequence...
241+
return spanKind != null && features.spanKindsToComputedStats().contains(spanKind.toString());
234242
}
235243

236244
private boolean publish(CoreSpan<?> span, boolean isTopLevel) {

dd-trace-core/src/test/groovy/datadog/trace/common/metrics/ConflatingMetricAggregatorTest.groovy

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import java.util.concurrent.TimeUnit
1313
import java.util.concurrent.TimeoutException
1414
import java.util.function.Supplier
1515

16+
import static datadog.trace.bootstrap.instrumentation.api.Tags.SPAN_KIND
1617
import static java.util.concurrent.TimeUnit.MILLISECONDS
1718
import static java.util.concurrent.TimeUnit.SECONDS
1819

@@ -32,7 +33,7 @@ class ConflatingMetricAggregatorTest extends DDSpecification {
3233
Sink sink = Mock(Sink)
3334
DDAgentFeaturesDiscovery features = Mock(DDAgentFeaturesDiscovery)
3435
features.supportsMetrics() >> true
35-
WellKnownTags wellKnownTags = new WellKnownTags("runtimeid", "hostname", "env", "service", "version","language")
36+
WellKnownTags wellKnownTags = new WellKnownTags("runtimeid", "hostname", "env", "service", "version", "language")
3637
ConflatingMetricsAggregator aggregator = new ConflatingMetricsAggregator(
3738
wellKnownTags,
3839
empty,
@@ -61,7 +62,7 @@ class ConflatingMetricAggregatorTest extends DDSpecification {
6162
Sink sink = Mock(Sink)
6263
DDAgentFeaturesDiscovery features = Mock(DDAgentFeaturesDiscovery)
6364
features.supportsMetrics() >> true
64-
WellKnownTags wellKnownTags = new WellKnownTags("runtimeid", "hostname", "env", "service", "version","language")
65+
WellKnownTags wellKnownTags = new WellKnownTags("runtimeid", "hostname", "env", "service", "version", "language")
6566
ConflatingMetricsAggregator aggregator = new ConflatingMetricsAggregator(
6667
wellKnownTags,
6768
[ignoredResourceName].toSet(),
@@ -120,6 +121,44 @@ class ConflatingMetricAggregatorTest extends DDSpecification {
120121
aggregator.close()
121122
}
122123

124+
def "should compute stats for span kind #kind"() {
125+
setup:
126+
MetricWriter writer = Mock(MetricWriter)
127+
Sink sink = Stub(Sink)
128+
DDAgentFeaturesDiscovery features = Mock(DDAgentFeaturesDiscovery)
129+
features.supportsMetrics() >> true
130+
features.spanKindsToComputedStats() >> ["client", "server", "producer", "consumer"]
131+
ConflatingMetricsAggregator aggregator = new ConflatingMetricsAggregator(empty,
132+
features, sink, writer, 10, queueSize, reportingInterval, SECONDS)
133+
aggregator.start()
134+
135+
when:
136+
CountDownLatch latch = new CountDownLatch(1)
137+
def span = Spy(new SimpleSpan("service", "operation", "resource", "type", false, false, false, 0, 100, HTTP_OK))
138+
span.getTag(SPAN_KIND) >> kind
139+
aggregator.publish([span])
140+
aggregator.report()
141+
def latchTriggered = latch.await(2, SECONDS)
142+
143+
then:
144+
latchTriggered == statsComputed
145+
(statsComputed ? 1 : 0) * writer.startBucket(1, _, _)
146+
(statsComputed ? 1 : 0) * writer.add(new MetricKey("resource", "service", "operation", "type", HTTP_OK, false), _) >> { MetricKey key, AggregateMetric value ->
147+
value.getHitCount() == 1 && value.getTopLevelCount() == 0 && value.getDuration() == 100
148+
}
149+
(statsComputed ? 1 : 0) * writer.finishBucket() >> { latch.countDown() }
150+
151+
cleanup:
152+
aggregator.close()
153+
154+
where:
155+
kind | statsComputed
156+
"client" | true
157+
UTF8BytesString.create("server") | true
158+
"internal" | false
159+
null | false
160+
}
161+
123162
def "measured spans do not contribute to top level count"() {
124163
setup:
125164
MetricWriter writer = Mock(MetricWriter)
@@ -472,7 +511,7 @@ class ConflatingMetricAggregatorTest extends DDSpecification {
472511
ConflatingMetricsAggregator aggregator = new ConflatingMetricsAggregator(empty,
473512
features, sink, writer, 10, queueSize, 200, MILLISECONDS)
474513
final spans = [
475-
new SimpleSpan("service" , "operation", "resource", "type", false, true, false, 0, 10, HTTP_OK)
514+
new SimpleSpan("service", "operation", "resource", "type", false, true, false, 0, 10, HTTP_OK)
476515
]
477516
aggregator.start()
478517

0 commit comments

Comments
 (0)