Skip to content

Commit c6c245f

Browse files
authored
Initial version of transactions tracking implementation for DSM (#9899)
1 parent 82f9e4b commit c6c245f

49 files changed

Lines changed: 910 additions & 33 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/HttpClientDecorator.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
import datadog.trace.api.InstrumenterConfig;
1212
import datadog.trace.api.ProductActivation;
1313
import datadog.trace.api.appsec.HttpClientRequest;
14+
import datadog.trace.api.datastreams.DataStreamsTransactionExtractor;
15+
import datadog.trace.api.datastreams.DataStreamsTransactionTracker;
1416
import datadog.trace.api.gateway.BlockResponseFunction;
1517
import datadog.trace.api.gateway.Flow;
1618
import datadog.trace.api.gateway.RequestContext;
@@ -68,8 +70,19 @@ protected boolean shouldSetResourceName() {
6870
return true;
6971
}
7072

73+
private final DataStreamsTransactionTracker.TransactionSourceReader
74+
DSM_TRANSACTION_SOURCE_READER =
75+
(source, headerName) -> getRequestHeader((REQUEST) source, headerName);
76+
7177
public AgentSpan onRequest(final AgentSpan span, final REQUEST request) {
7278
if (request != null) {
79+
AgentTracer.get()
80+
.getDataStreamsMonitoring()
81+
.trackTransaction(
82+
span,
83+
DataStreamsTransactionExtractor.Type.HTTP_OUT_HEADERS,
84+
request,
85+
DSM_TRANSACTION_SOURCE_READER);
7386

7487
String method = method(request);
7588
span.setTag(Tags.HTTP_METHOD, method);

dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/HttpServerDecorator.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import datadog.context.propagation.Propagators;
1414
import datadog.trace.api.Config;
1515
import datadog.trace.api.DDTags;
16+
import datadog.trace.api.datastreams.DataStreamsTransactionExtractor;
17+
import datadog.trace.api.datastreams.DataStreamsTransactionTracker;
1618
import datadog.trace.api.function.TriConsumer;
1719
import datadog.trace.api.function.TriFunction;
1820
import datadog.trace.api.gateway.BlockResponseFunction;
@@ -95,6 +97,14 @@ public abstract class HttpServerDecorator<REQUEST, CONNECTION, RESPONSE, REQUEST
9597

9698
protected abstract int status(RESPONSE response);
9799

100+
protected String getRequestHeader(REQUEST request, String key) {
101+
// This method was not marked as abstract in order to avoid changing all server instrumentation
102+
// at once.
103+
// Instead, only ones required (by DSM specifically) have it implemented.
104+
// This can change in the future.
105+
return null;
106+
}
107+
98108
protected String requestedSessionId(REQUEST request) {
99109
return null;
100110
}
@@ -174,6 +184,10 @@ protected AgentSpanContext startInferredProxySpan(Context context, AgentSpanCont
174184
return span.start(extracted);
175185
}
176186

187+
private final DataStreamsTransactionTracker.TransactionSourceReader
188+
DSM_TRANSACTION_SOURCE_READER =
189+
(source, headerName) -> getRequestHeader((REQUEST) source, headerName);
190+
177191
public AgentSpan onRequest(
178192
final AgentSpan span,
179193
final CONNECTION connection,
@@ -326,6 +340,13 @@ public AgentSpan onRequest(
326340
span.setRequestBlockingAction((RequestBlockingAction) flow.getAction());
327341
}
328342

343+
AgentTracer.get()
344+
.getDataStreamsMonitoring()
345+
.trackTransaction(
346+
span,
347+
DataStreamsTransactionExtractor.Type.HTTP_IN_HEADERS,
348+
request,
349+
DSM_TRANSACTION_SOURCE_READER);
329350
return span;
330351
}
331352

dd-java-agent/agent-bootstrap/src/main/resources/META-INF/native-image/com.datadoghq/dd-java-agent/reflect-config.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,31 @@
7070
{"name": "toJson"}
7171
]
7272
},
73+
{
74+
"name" : "datadog.trace.agent.core.datastreams.DataStreamsTransactionExtractors$DataStreamsTransactionExtractorAdapter",
75+
"methods": [
76+
{"name": "fromJson"},
77+
{"name": "toJson"}
78+
]
79+
},
80+
{
81+
"name" : "datadog.trace.agent.core.datastreams.DataStreamsTransactionExtractors$DataStreamsTransactionExtractorImpl",
82+
"allDeclaredConstructors" : true,
83+
"allPublicConstructors" : true,
84+
"allDeclaredFields" : true,
85+
"allPublicFields" : true
86+
},
87+
{
88+
"name" : "datadog.trace.api.datastreams.DataStreamsTransactionExtractor$Type",
89+
"allDeclaredFields" : true
90+
},
91+
{
92+
"name" : "datadog.trace.agent.core.datastreams.DataStreamsTransactionExtractors$DataStreamsTransactionExtractorsAdapter",
93+
"methods": [
94+
{"name": "fromJson"},
95+
{"name": "toJson"}
96+
]
97+
},
7398
{
7499
"name" : "datadog.trace.agent.core.DDSpanLink$SpanLinkAdapter",
75100
"methods": [

dd-java-agent/agent-bootstrap/src/test/groovy/datadog/trace/bootstrap/instrumentation/decorator/HttpServerDecoratorTest.groovy

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,11 @@ class HttpServerDecoratorTest extends ServerDecoratorTest {
468468
protected int status(Map m) {
469469
return m.status == null ? 0 : m.status
470470
}
471+
472+
@Override
473+
protected String getRequestHeader(Map map, String key) {
474+
return map.getOrDefault(key, null)
475+
}
471476
}
472477
}
473478

dd-java-agent/instrumentation-testing/src/main/groovy/datadog/trace/agent/test/InstrumentationSpecification.groovy

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
package datadog.trace.agent.test
22

3+
import static datadog.communication.http.OkHttpUtils.buildHttpClient
4+
import static datadog.trace.api.ConfigDefaults.DEFAULT_AGENT_HOST
5+
import static datadog.trace.api.ConfigDefaults.DEFAULT_AGENT_TIMEOUT
6+
import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_AGENT_PORT
7+
import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_SNAPSHOT_URL
8+
import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_VERIFY_BYTECODE
9+
import static datadog.trace.api.config.TraceInstrumentationConfig.CODE_ORIGIN_FOR_SPANS_ENABLED
10+
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.closePrevious
11+
import static datadog.trace.util.AgentThreadFactory.AgentThread.TASK_SCHEDULER
12+
313
import ch.qos.logback.classic.Level
414
import ch.qos.logback.classic.util.ContextInitializer
515
import com.datadog.debugger.agent.ClassesToRetransformFinder
@@ -33,6 +43,7 @@ import datadog.trace.api.TraceConfig
3343
import datadog.trace.api.config.GeneralConfig
3444
import datadog.trace.api.config.TracerConfig
3545
import datadog.trace.api.datastreams.AgentDataStreamsMonitoring
46+
import datadog.trace.api.datastreams.DataStreamsTransactionExtractor
3647
import datadog.trace.api.sampling.SamplingRule
3748
import datadog.trace.api.time.SystemTimeSource
3849
import datadog.trace.bootstrap.ActiveSubsystems
@@ -56,6 +67,13 @@ import de.thetaphi.forbiddenapis.SuppressForbidden
5667
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
5768
import groovy.transform.stc.ClosureParams
5869
import groovy.transform.stc.SimpleType
70+
import java.lang.instrument.ClassFileTransformer
71+
import java.lang.instrument.Instrumentation
72+
import java.nio.ByteBuffer
73+
import java.util.concurrent.ConcurrentHashMap
74+
import java.util.concurrent.TimeUnit
75+
import java.util.concurrent.TimeoutException
76+
import java.util.concurrent.atomic.AtomicInteger
5977
import net.bytebuddy.agent.ByteBuddyAgent
6078
import net.bytebuddy.agent.builder.AgentBuilder
6179
import net.bytebuddy.description.type.TypeDescription
@@ -69,24 +87,6 @@ import org.slf4j.LoggerFactory
6987
import org.spockframework.mock.MockUtil
7088
import spock.lang.Shared
7189

72-
import java.lang.instrument.ClassFileTransformer
73-
import java.lang.instrument.Instrumentation
74-
import java.nio.ByteBuffer
75-
import java.util.concurrent.ConcurrentHashMap
76-
import java.util.concurrent.TimeUnit
77-
import java.util.concurrent.TimeoutException
78-
import java.util.concurrent.atomic.AtomicInteger
79-
80-
import static datadog.communication.http.OkHttpUtils.buildHttpClient
81-
import static datadog.trace.api.ConfigDefaults.DEFAULT_AGENT_HOST
82-
import static datadog.trace.api.ConfigDefaults.DEFAULT_AGENT_TIMEOUT
83-
import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_AGENT_PORT
84-
import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_SNAPSHOT_URL
85-
import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_VERIFY_BYTECODE
86-
import static datadog.trace.api.config.TraceInstrumentationConfig.CODE_ORIGIN_FOR_SPANS_ENABLED
87-
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.closePrevious
88-
import static datadog.trace.util.AgentThreadFactory.AgentThread.TASK_SCHEDULER
89-
9090
/**
9191
* A specification that automatically applies instrumentation and exposes a global trace
9292
* writer.
@@ -250,6 +250,10 @@ abstract class InstrumentationSpecification extends DDSpecification implements A
250250
List<? extends SamplingRule.TraceSamplingRule> getTraceSamplingRules() {
251251
return null
252252
}
253+
254+
List<DataStreamsTransactionExtractor> getDataStreamsTransactionExtractors() {
255+
return null
256+
}
253257
}
254258

255259
@SuppressFBWarnings(value = "AT_STALE_THREAD_WRITE_OF_PRIMITIVE", justification = "The variable is accessed only by the test thread in setup and cleanup.")

dd-java-agent/instrumentation/akka/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerDecorator.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ protected int status(final HttpResponse httpResponse) {
8888
return httpResponse.status().intValue();
8989
}
9090

91+
@Override
92+
protected String getRequestHeader(HttpRequest httpRequest, String key) {
93+
Optional<akka.http.javadsl.model.HttpHeader> header = httpRequest.getHeader(key);
94+
return header.map(HttpHeader::value).orElse(null);
95+
}
96+
9197
@Override
9298
protected boolean isAppSecOnResponseSeparate() {
9399
return true;

dd-java-agent/instrumentation/jetty/jetty-server/jetty-server-10.0/src/main/java11/datadog/trace/instrumentation/jetty10/JettyDecorator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ protected boolean isAppSecOnResponseSeparate() {
7878
return true;
7979
}
8080

81+
@Override
82+
protected String getRequestHeader(final Request request, String key) {
83+
return request.getHeader(key);
84+
}
85+
8186
@Override
8287
protected BlockResponseFunction createBlockResponseFunction(Request request, Request connection) {
8388
return new JettyBlockResponseFunction(request);

dd-java-agent/instrumentation/jetty/jetty-server/jetty-server-11.0/src/main/java11/datadog/trace/instrumentation/jetty11/JettyDecorator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ protected boolean isAppSecOnResponseSeparate() {
7878
return true;
7979
}
8080

81+
@Override
82+
protected String getRequestHeader(final Request request, String key) {
83+
return request.getHeader(key);
84+
}
85+
8186
public AgentSpan onResponse(AgentSpan span, HttpChannel channel) {
8287
Request request = channel.getRequest();
8388
Response response = channel.getResponse();

dd-java-agent/instrumentation/jetty/jetty-server/jetty-server-12.0/src/main/java17/datadog/trace/instrumentation/jetty12/JettyDecorator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ protected int status(final Response response) {
8383
return response.getStatus();
8484
}
8585

86+
@Override
87+
protected String getRequestHeader(final Request request, String key) {
88+
return request.getHeaders().get(key);
89+
}
90+
8691
public AgentSpan onResponse(AgentSpan span, HttpChannelState channel) {
8792
Request request = channel.getRequest();
8893
Response response = channel.getResponse();

dd-java-agent/instrumentation/jetty/jetty-server/jetty-server-7.0/src/main/java/datadog/trace/instrumentation/jetty70/JettyDecorator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ protected boolean isAppSecOnResponseSeparate() {
7777
return true;
7878
}
7979

80+
@Override
81+
protected String getRequestHeader(final Request request, String key) {
82+
return request.getHeader(key);
83+
}
84+
8085
public AgentSpan onResponse(AgentSpan span, HttpConnection channel) {
8186
Request request = channel.getRequest();
8287
Response response = channel.getResponse();

0 commit comments

Comments
 (0)