Skip to content

Commit d9df78f

Browse files
authored
squashing & signing (#8589)
This change introduces TagMap as replacement for HashMap when working with tags. TagMap has two different implementations... - one that extends a regular HashMap - another that uses a different approach that allows for Entry sharing This change currently uses the HashMap approach by default, but allows for switching to the optimized Map via a configuration flag. The optimized TagMap is designed to be good at operations that the tracer performs regularly but HashMap isn't great at. Specifically, Map-to-Map copies and storing primitives. To get the benefit of the optimized TagMap, calling code needs to use TagMap-s for both the source and destination map. The calling code also needs to make sure to use the bulk operations that which are the most optimized. To take advantage of TagMap in span creation, a mechanism was introduced that allows for bypassing TagInterceptors. Bypassing TagInterceptors is done by analyzing a TagMap that is going to be reused ahead-of-time to determine if interception is needed. If interception isn't needed, then SpanBuilder can use a bulk operation to update the map. To maintain the insertion order semantics of SpanBuilder, TagMap also includes a Ledger. A Ledger is concatenative ledger of entry modifications to a map A Ledger is now used in place of a LinkedHashMap in SpanBuilder to provide the insertion order semantics. Since these changes primarily serve to reduce allocation, they should the biggest gain in memory constrained environments. In memory constrained environments, these changes yield a 10% increase in sustainable throughput with spring-petclinic.
1 parent b86f4f7 commit d9df78f

File tree

51 files changed

+6897
-247
lines changed

Some content is hidden

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

51 files changed

+6897
-247
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public AbstractTestSession(
7373
AgentSpanContext traceContext =
7474
new TagContext(
7575
CIConstants.CIAPP_TEST_ORIGIN,
76-
Collections.emptyMap(),
76+
null,
7777
null,
7878
null,
7979
PrioritySampling.UNSET,

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
import datadog.trace.civisibility.test.ExecutionResults;
4747
import java.lang.reflect.Method;
4848
import java.util.Collection;
49-
import java.util.Collections;
5049
import java.util.concurrent.TimeUnit;
5150
import java.util.function.Consumer;
5251
import javax.annotation.Nonnull;
@@ -105,8 +104,7 @@ public TestImpl(
105104

106105
this.context = new TestContextImpl(coverageStore);
107106

108-
AgentSpanContext traceContext =
109-
new TagContext(CIConstants.CIAPP_TEST_ORIGIN, Collections.emptyMap());
107+
AgentSpanContext traceContext = new TagContext(CIConstants.CIAPP_TEST_ORIGIN, null);
110108
AgentTracer.SpanBuilder spanBuilder =
111109
AgentTracer.get()
112110
.buildSpan(CI_VISIBILITY_INSTRUMENTATION_NAME, testDecorator.component() + ".test")

dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/exception/DefaultExceptionDebuggerTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.datadog.debugger.util.ExceptionHelper;
2828
import com.datadog.debugger.util.TestSnapshotListener;
2929
import datadog.trace.api.Config;
30+
import datadog.trace.api.TagMap;
3031
import datadog.trace.bootstrap.debugger.CapturedContext;
3132
import datadog.trace.bootstrap.debugger.CapturedStackFrame;
3233
import datadog.trace.bootstrap.debugger.MethodLocation;
@@ -41,7 +42,6 @@
4142
import java.util.ArrayList;
4243
import java.util.Arrays;
4344
import java.util.Deque;
44-
import java.util.HashMap;
4545
import java.util.HashSet;
4646
import java.util.List;
4747
import java.util.Map;
@@ -57,7 +57,7 @@ public class DefaultExceptionDebuggerTest {
5757
private ConfigurationUpdater configurationUpdater;
5858
private DefaultExceptionDebugger exceptionDebugger;
5959
private TestSnapshotListener listener;
60-
private Map<String, Object> spanTags = new HashMap<>();
60+
private TagMap spanTags = TagMap.create();
6161

6262
@BeforeEach
6363
public void setUp() {

dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/HstsMissingHeaderModuleTest.groovy

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import com.datadog.iast.model.Vulnerability
77
import com.datadog.iast.model.VulnerabilityType
88
import com.datadog.iast.overhead.Operation
99
import com.datadog.iast.overhead.OverheadController
10+
import datadog.trace.api.TagMap
1011
import datadog.trace.api.gateway.Flow
1112
import datadog.trace.api.iast.InstrumentationBridge
1213
import datadog.trace.api.internal.TraceSegment
@@ -45,10 +46,10 @@ class HstsMissingHeaderModuleTest extends IastModuleImplTestBase {
4546
final handler = new RequestEndedHandler(dependencies)
4647
ctx.xForwardedProto = 'https'
4748
ctx.contentType = "text/html"
48-
span.getTags() >> [
49+
span.getTags() >> TagMap.fromMap([
4950
'http.url': 'https://localhost/a',
5051
'http.status_code': 200i
51-
]
52+
])
5253

5354
when:
5455
def flow = handler.apply(reqCtx, span)

dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/InsecureAuthProtocolModuleTest.groovy

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.datadog.iast.Reporter
55
import com.datadog.iast.RequestEndedHandler
66
import com.datadog.iast.model.Vulnerability
77
import com.datadog.iast.model.VulnerabilityType
8+
import datadog.trace.api.TagMap
89
import datadog.trace.api.gateway.Flow
910
import datadog.trace.api.iast.InstrumentationBridge
1011
import datadog.trace.api.iast.sink.InsecureAuthProtocolModule
@@ -42,9 +43,9 @@ class InsecureAuthProtocolModuleTest extends IastModuleImplTestBase{
4243
given:
4344
final handler = new RequestEndedHandler(dependencies)
4445
ctx.authorization = value
45-
span.getTags() >> [
46+
span.getTags() >> TagMap.fromMap([
4647
'http.status_code': status_code
47-
]
48+
])
4849

4950
when:
5051
def flow = handler.apply(reqCtx, span)

dd-java-agent/agent-iast/src/test/groovy/com/datadog/iast/sink/XContentTypeOptionsModuleTest.groovy

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.datadog.iast.Reporter
55
import com.datadog.iast.RequestEndedHandler
66
import com.datadog.iast.model.Vulnerability
77
import com.datadog.iast.model.VulnerabilityType
8+
import datadog.trace.api.TagMap
89
import datadog.trace.api.gateway.Flow
910
import datadog.trace.api.iast.InstrumentationBridge
1011
import datadog.trace.api.internal.TraceSegment
@@ -33,9 +34,9 @@ class XContentTypeOptionsModuleTest extends IastModuleImplTestBase {
3334
given:
3435
final handler = new RequestEndedHandler(dependencies)
3536
ctx.contentType = "text/html"
36-
span.getTags() >> [
37+
span.getTags() >> TagMap.fromMap([
3738
'http.status_code': 200i
38-
]
39+
])
3940

4041
when:
4142
def flow = handler.apply(reqCtx, span)
@@ -56,10 +57,10 @@ class XContentTypeOptionsModuleTest extends IastModuleImplTestBase {
5657
final handler = new RequestEndedHandler(dependencies)
5758
ctx.xForwardedProto = 'https'
5859
ctx.contentType = "text/html"
59-
span.getTags() >> [
60+
span.getTags() >> TagMap.fromMap([
6061
'http.url': url,
6162
'http.status_code': status
62-
]
63+
])
6364

6465
when:
6566
def flow = handler.apply(reqCtx, span)

dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/AppSecSystemSpecification.groovy

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import datadog.remoteconfig.Product
1313
import datadog.remoteconfig.state.ConfigKey
1414
import datadog.remoteconfig.state.ProductListener
1515
import datadog.trace.api.Config
16+
import datadog.trace.api.TagMap
1617
import datadog.trace.api.gateway.Flow
1718
import datadog.trace.api.gateway.IGSpanInfo
1819
import datadog.trace.api.gateway.RequestContext
@@ -91,7 +92,7 @@ class AppSecSystemSpecification extends DDSpecification {
9192
requestEndedCB.apply(requestContext, span)
9293

9394
then:
94-
1 * span.getTags() >> ['http.client_ip':'1.1.1.1']
95+
1 * span.getTags() >> TagMap.fromMap(['http.client_ip':'1.1.1.1'])
9596
1 * subService.registerCallback(EVENTS.requestEnded(), _) >> { requestEndedCB = it[1]; null }
9697
1 * requestContext.getData(RequestContextSlot.APPSEC) >> appSecReqCtx
9798
1 * requestContext.traceSegment >> traceSegment

dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/gateway/GatewayBridgeSpecification.groovy

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import com.datadog.appsec.event.data.DataBundle
99
import com.datadog.appsec.event.data.KnownAddresses
1010
import com.datadog.appsec.report.AppSecEvent
1111
import com.datadog.appsec.report.AppSecEventWrapper
12+
import datadog.trace.api.TagMap
1213
import datadog.trace.api.ProductTraceSource
1314
import datadog.trace.api.config.GeneralConfig
1415
import static datadog.trace.api.config.IastConfig.IAST_DEDUPLICATION_ENABLED
@@ -173,7 +174,7 @@ class GatewayBridgeSpecification extends DDSpecification {
173174
def flow = requestEndedCB.apply(mockCtx, spanInfo)
174175

175176
then:
176-
1 * spanInfo.getTags() >> ['http.client_ip': '1.1.1.1']
177+
1 * spanInfo.getTags() >> TagMap.fromMap(['http.client_ip': '1.1.1.1'])
177178
1 * mockAppSecCtx.transferCollectedEvents() >> [event]
178179
1 * mockAppSecCtx.peerAddress >> '2001::1'
179180
1 * mockAppSecCtx.close()
@@ -212,7 +213,7 @@ class GatewayBridgeSpecification extends DDSpecification {
212213

213214
then:
214215
1 * mockAppSecCtx.transferCollectedEvents() >> [Stub(AppSecEvent)]
215-
1 * spanInfo.getTags() >> ['http.client_ip': '8.8.8.8']
216+
1 * spanInfo.getTags() >> TagMap.fromMap(['http.client_ip': '8.8.8.8'])
216217
1 * traceSegment.setTagTop('actor.ip', '8.8.8.8')
217218
}
218219

@@ -1008,7 +1009,7 @@ class GatewayBridgeSpecification extends DDSpecification {
10081009
getTraceSegment() >> traceSegment
10091010
}
10101011
final spanInfo = Mock(AgentSpan) {
1011-
getTags() >> ['http.route':'/']
1012+
getTags() >> TagMap.fromMap(['http.route':'/'])
10121013
}
10131014

10141015
when:
@@ -1196,7 +1197,7 @@ class GatewayBridgeSpecification extends DDSpecification {
11961197
def flow = requestEndedCB.apply(mockCtx, spanInfo)
11971198
then:
11981199
1 * mockAppSecCtx.transferCollectedEvents() >> []
1199-
1 * spanInfo.getTags() >> ['http.route': 'route']
1200+
1 * spanInfo.getTags() >> TagMap.fromMap(['http.route': 'route'])
12001201
1 * requestSampler.preSampleRequest(_) >> true
12011202
0 * traceSegment.setTagTop(Tags.ASM_KEEP, true)
12021203
0 * traceSegment.setTagTop(Tags.PROPAGATED_TRACE_SOURCE, ProductTraceSource.ASM)
@@ -1214,7 +1215,7 @@ class GatewayBridgeSpecification extends DDSpecification {
12141215
def flow = requestEndedCB.apply(mockCtx, spanInfo)
12151216
then:
12161217
1 * mockAppSecCtx.transferCollectedEvents() >> []
1217-
1 * spanInfo.getTags() >> ['http.route': 'route']
1218+
1 * spanInfo.getTags() >> TagMap.fromMap(['http.route': 'route'])
12181219
1 * requestSampler.preSampleRequest(_) >> false
12191220
0 * traceSegment.setTagTop(Tags.ASM_KEEP, true)
12201221
0 * traceSegment.setTagTop(Tags.PROPAGATED_TRACE_SOURCE, ProductTraceSource.ASM)
@@ -1233,7 +1234,7 @@ class GatewayBridgeSpecification extends DDSpecification {
12331234
def flow = requestEndedCB.apply(mockCtx, spanInfo)
12341235
then:
12351236
1 * mockAppSecCtx.transferCollectedEvents() >> []
1236-
1 * spanInfo.getTags() >> ['http.route': 'route']
1237+
1 * spanInfo.getTags() >> TagMap.fromMap(['http.route': 'route'])
12371238
1 * requestSampler.preSampleRequest(_) >> true
12381239
1 * traceSegment.setTagTop(Tags.ASM_KEEP, true)
12391240
1 * traceSegment.setTagTop(Tags.PROPAGATED_TRACE_SOURCE, ProductTraceSource.ASM)

dd-java-agent/instrumentation/websocket/javax-websocket-1.0/src/test/groovy/WebsocketTest.groovy

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import datadog.trace.agent.test.AgentTestRunner
22
import datadog.trace.api.DDTags
3+
import datadog.trace.api.TagMap
34
import datadog.trace.api.sampling.PrioritySampling
45
import datadog.trace.bootstrap.instrumentation.api.AgentSpan
56
import datadog.trace.bootstrap.instrumentation.api.InstrumentationTags
@@ -584,7 +585,7 @@ class WebsocketTest extends AgentTestRunner {
584585
clientHandshake.setSamplingPriority(PrioritySampling.SAMPLER_DROP) // simulate sampler drop
585586
def serverHandshake = createHandshakeSpan("servlet.request", url,
586587
new ExtractedContext(clientHandshake.context().getTraceId(), clientHandshake.context().getSpanId(), clientHandshake.context().getSamplingPriority(),
587-
"test", 0, ["example_baggage": "test"], null, null, null, null, null)) // simulate server span
588+
"test", 0, ["example_baggage": "test"], TagMap.EMPTY, null, null, null, null)) // simulate server span
588589
def session = deployEndpointAndConnect(new Endpoints.TestEndpoint(new Endpoints.FullStringHandler()),
589590
clientHandshake, serverHandshake, url)
590591

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ public final class GeneralConfig {
103103
public static final String APM_TRACING_ENABLED = "apm.tracing.enabled";
104104
public static final String JDK_SOCKET_ENABLED = "jdk.socket.enabled";
105105

106+
public static final String OPTIMIZED_MAP_ENABLED = "optimized.map.enabled";
106107
public static final String STACK_TRACE_LENGTH_LIMIT = "stack.trace.length.limit";
107108

108109
public static final String SSI_INJECTION_ENABLED = "injection.enabled";

0 commit comments

Comments
 (0)