Skip to content

Commit 7b7ad49

Browse files
committed
Inferred Routes and Resource Renaming: new APM trace metrics tag
Signed-off-by: sezen.leblay <[email protected]>
1 parent e42a5b2 commit 7b7ad49

File tree

14 files changed

+1001
-4
lines changed

14 files changed

+1001
-4
lines changed
Submodule integrations-core updated 4981 files
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package datadog.smoketest
2+
3+
import okhttp3.Request
4+
import java.util.concurrent.atomic.AtomicInteger
5+
import java.util.regex.Pattern
6+
7+
class HttpEndpointTaggingSmokeTest extends AbstractServerSmokeTest {
8+
9+
@Override
10+
ProcessBuilder createProcessBuilder() {
11+
String springBootShadowJar = System.getProperty("datadog.smoketest.springboot.shadowJar.path")
12+
13+
List<String> command = new ArrayList<>()
14+
command.add(javaPath())
15+
command.addAll(defaultJavaProperties)
16+
command.addAll((String[]) [
17+
"-Ddd.writer.type=MultiWriter:TraceStructureWriter:${output.getAbsolutePath()}:includeResource,DDAgentWriter",
18+
"-Ddd.trace.resource.renaming.enabled=true",
19+
"-jar",
20+
springBootShadowJar,
21+
"--server.port=${httpPort}"
22+
])
23+
ProcessBuilder processBuilder = new ProcessBuilder(command)
24+
processBuilder.directory(new File(buildDirectory))
25+
}
26+
27+
@Override
28+
File createTemporaryFile() {
29+
return File.createTempFile("http-endpoint-tagging-trace", "out")
30+
}
31+
32+
@Override
33+
protected Set<String> expectedTraces() {
34+
return [
35+
Pattern.quote("[servlet.request:GET /greeting[spring.handler:IastWebController.greeting]]")
36+
]
37+
}
38+
39+
@Override
40+
protected Set<String> assertTraceCounts(Set<String> expected, Map<String, AtomicInteger> traceCounts) {
41+
List<Pattern> remaining = expected.collect { Pattern.compile(it) }.toList()
42+
for (def i = remaining.size() - 1; i >= 0; i--) {
43+
for (Map.Entry<String, AtomicInteger> entry : traceCounts.entrySet()) {
44+
if (entry.getValue() > 0 && remaining.get(i).matcher(entry.getKey()).matches()) {
45+
remaining.remove(i)
46+
break
47+
}
48+
}
49+
}
50+
return remaining.collect { it.pattern() }.toSet()
51+
}
52+
53+
def "test basic HTTP endpoint tagging"() {
54+
setup:
55+
String url = "http://localhost:${httpPort}/greeting"
56+
def request = new Request.Builder().url(url).get().build()
57+
58+
when:
59+
def response = client.newCall(request).execute()
60+
61+
then:
62+
def responseBodyStr = response.body().string()
63+
responseBodyStr != null
64+
responseBodyStr.contains("Sup Dawg")
65+
response.code() == 200
66+
waitForTraceCount(1)
67+
}
68+
69+
def "test URL parameterization for numeric IDs"() {
70+
setup:
71+
String url = "http://localhost:${httpPort}/users/123"
72+
def request = new Request.Builder().url(url).get().build()
73+
74+
when:
75+
def response = client.newCall(request).execute()
76+
77+
then:
78+
// May return 404 since endpoint doesn't exist, but span should still be created
79+
response.code() in [200, 404]
80+
waitForTraceCount(1)
81+
}
82+
83+
def "test URL parameterization for hex patterns"() {
84+
setup:
85+
String url = "http://localhost:${httpPort}/session/abc123def456"
86+
def request = new Request.Builder().url(url).get().build()
87+
88+
when:
89+
def response = client.newCall(request).execute()
90+
91+
then:
92+
// May return 404 since endpoint doesn't exist, but span should still be created
93+
response.code() in [200, 404]
94+
waitForTraceCount(1)
95+
}
96+
}

dd-trace-api/src/main/java/datadog/trace/api/ConfigDefaults.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,12 @@ public final class ConfigDefaults {
168168
"datadog.trace.*:org.apache.commons.*:org.mockito.*";
169169
static final boolean DEFAULT_CIVISIBILITY_GIT_UPLOAD_ENABLED = true;
170170
static final boolean DEFAULT_CIVISIBILITY_GIT_UNSHALLOW_ENABLED = true;
171+
172+
// HTTP Endpoint Tagging feature flags
173+
static final boolean DEFAULT_RESOURCE_RENAMING_ENABLED =
174+
false; // Default enablement of resource renaming
175+
static final boolean DEFAULT_RESOURCE_RENAMING_ALWAYS_SIMPLIFIED_ENDPOINT =
176+
false; // Manual disablement of resource renaming
171177
static final long DEFAULT_CIVISIBILITY_GIT_COMMAND_TIMEOUT_MILLIS = 30_000;
172178
static final long DEFAULT_CIVISIBILITY_BACKEND_API_TIMEOUT_MILLIS = 30_000;
173179
static final long DEFAULT_CIVISIBILITY_GIT_UPLOAD_TIMEOUT_MILLIS = 60_000;

dd-trace-api/src/main/java/datadog/trace/api/config/TracerConfig.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ public final class TracerConfig {
6666
"trace.http.resource.remove-trailing-slash";
6767
public static final String TRACE_HTTP_SERVER_PATH_RESOURCE_NAME_MAPPING =
6868
"trace.http.server.path-resource-name-mapping";
69+
70+
// HTTP Endpoint Tagging feature flags
71+
public static final String TRACE_RESOURCE_RENAMING_ENABLED = "trace.resource.renaming.enabled";
72+
public static final String TRACE_RESOURCE_RENAMING_ALWAYS_SIMPLIFIED_ENDPOINT =
73+
"trace.resource.renaming.always-simplified-endpoint";
6974
public static final String TRACE_HTTP_CLIENT_PATH_RESOURCE_NAME_MAPPING =
7075
"trace.http.client.path-resource-name-mapping";
7176
// Use TRACE_HTTP_SERVER_ERROR_STATUSES instead

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import static datadog.communication.ddagent.DDAgentFeaturesDiscovery.V6_METRICS_ENDPOINT;
44
import static datadog.trace.api.DDTags.BASE_SERVICE;
55
import static datadog.trace.api.Functions.UTF8_ENCODE;
6+
import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_ENDPOINT;
7+
import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_METHOD;
68
import static datadog.trace.bootstrap.instrumentation.api.Tags.SPAN_KIND;
79
import static datadog.trace.bootstrap.instrumentation.api.Tags.SPAN_KIND_CLIENT;
810
import static datadog.trace.bootstrap.instrumentation.api.Tags.SPAN_KIND_CONSUMER;
@@ -306,6 +308,8 @@ private boolean spanKindEligible(CoreSpan<?> span) {
306308

307309
private boolean publish(CoreSpan<?> span, boolean isTopLevel) {
308310
final CharSequence spanKind = span.getTag(SPAN_KIND, "");
311+
final CharSequence httpMethod = span.getTag(HTTP_METHOD, "");
312+
final CharSequence httpEndpoint = span.getTag(HTTP_ENDPOINT, "");
309313
MetricKey newKey =
310314
new MetricKey(
311315
span.getResourceName(),
@@ -317,7 +321,9 @@ private boolean publish(CoreSpan<?> span, boolean isTopLevel) {
317321
span.getParentId() == 0,
318322
SPAN_KINDS.computeIfAbsent(
319323
spanKind, UTF8BytesString::create), // save repeated utf8 conversions
320-
getPeerTags(span, spanKind.toString()));
324+
getPeerTags(span, spanKind.toString()),
325+
httpMethod,
326+
httpEndpoint);
321327
boolean isNewKey = false;
322328
MetricKey key = keys.putIfAbsent(newKey, newKey);
323329
if (null == key) {

0 commit comments

Comments
 (0)