Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
d06652d
WIP: baggage span tags
rachelyangdog Jul 14, 2025
bb005f5
simple test
rachelyangdog Jul 14, 2025
2f2b83c
Merge branch 'master' into rachel.yang/baggage-span-tags
rachelyangdog Jul 14, 2025
22631c5
fix build errors
rachelyangdog Jul 15, 2025
87e2aaa
adding more tests
rachelyangdog Jul 15, 2025
20885c9
Merge branch 'master' into rachel.yang/baggage-span-tags
rachelyangdog Jul 15, 2025
2ca1604
Add baggage span tags functionality and tests
rachelyangdog Jul 16, 2025
de8a55a
Move baggage tags feature to HttpServerDecorator.getExtractedSpanCont…
mcculls Jul 18, 2025
5b52ea4
Fix potential corner-case where TagContext.getTags() may return an im…
mcculls Jul 18, 2025
af0a640
Move baggage tags unit test to HttpServerDecoratorTest
mcculls Jul 18, 2025
eca080e
Baggage tags unit tests have been moved to HttpServerDecoratorTest
mcculls Jul 18, 2025
2d45a1f
Merge remote-tracking branch 'origin/master' into rachel.yang/baggage…
mcculls Jul 22, 2025
85d573f
Move W3C baggage tag injection to just before the span is serialized
mcculls Jul 22, 2025
33fe83e
Update test trace writer so injected baggage metadata can be asserted…
mcculls Jul 22, 2025
3a8d4a8
spotless format
mcculls Jul 22, 2025
a4fb5a6
Remove unused method
mcculls Jul 22, 2025
988bed8
Fix test code
mcculls Jul 22, 2025
dd9bbdd
Merge remote-tracking branch 'origin/master' into rachel.yang/baggage…
mcculls Jul 22, 2025
a22edab
Support recording of baggage, that would be sent to agent as trace me…
mcculls Jul 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
import datadog.trace.bootstrap.instrumentation.api.AgentSpanContext;
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
import datadog.trace.bootstrap.instrumentation.api.Baggage;
import datadog.trace.bootstrap.instrumentation.api.ErrorPriorities;
import datadog.trace.bootstrap.instrumentation.api.InternalSpanTypes;
import datadog.trace.bootstrap.instrumentation.api.ResourceNamePriorities;
Expand All @@ -37,6 +38,7 @@
import datadog.trace.bootstrap.instrumentation.decorator.http.ClientIpAddressResolver;
import java.net.InetAddress;
import java.util.BitSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ExecutionException;
Expand Down Expand Up @@ -149,7 +151,17 @@ public AgentSpan startSpan(REQUEST_CARRIER carrier, Context context) {

public AgentSpanContext.Extracted getExtractedSpanContext(Context context) {
AgentSpan extractedSpan = AgentSpan.fromContext(context);
return extractedSpan == null ? null : (AgentSpanContext.Extracted) extractedSpan.context();
AgentSpanContext.Extracted extractedContext = null;
if (extractedSpan != null) {
extractedContext = (AgentSpanContext.Extracted) extractedSpan.context();
if (extractedContext instanceof TagContext) {
Baggage baggage = Baggage.fromContext(context);
if (baggage != null) {
setBaggageTags((TagContext) extractedContext, baggage.asMap());
}
}
}
return extractedContext;
}

public AgentSpan onRequest(
Expand Down Expand Up @@ -644,4 +656,24 @@ public boolean accept(String key, String value) {
return true;
}
}

static void setBaggageTags(TagContext tagContext, Map<String, String> baggage) {
List<String> baggageTagKeys = Config.get().getTraceBaggageTagKeys();
if (baggageTagKeys.isEmpty()) {
return;
}
for (String key : baggageTagKeys) {
if ("*".equals(key)) {
// If the key is "*", we add all baggage items
for (Map.Entry<String, String> entry : baggage.entrySet()) {
tagContext.putTagIfAbsent("baggage." + entry.getKey(), entry.getValue());
}
break;
}
String value = baggage.get(key);
if (value != null) {
tagContext.putTagIfAbsent("baggage." + key, value);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import datadog.trace.bootstrap.instrumentation.api.AgentTracer.TracerAPI
import datadog.trace.bootstrap.instrumentation.api.ContextVisitors
import datadog.trace.bootstrap.instrumentation.api.ErrorPriorities
import datadog.trace.bootstrap.instrumentation.api.ResourceNamePriorities
import datadog.trace.bootstrap.instrumentation.api.TagContext
import datadog.trace.bootstrap.instrumentation.api.Tags
import datadog.trace.bootstrap.instrumentation.api.URIDataAdapter
import datadog.trace.bootstrap.instrumentation.api.URIDefaultDataAdapter
Expand All @@ -29,6 +30,7 @@ import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_DE
import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_RAW_QUERY_STRING
import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_RAW_RESOURCE
import static datadog.trace.api.config.TraceInstrumentationConfig.HTTP_SERVER_TAG_QUERY_STRING
import static datadog.trace.api.config.TracerConfig.TRACE_BAGGAGE_TAG_KEYS
import static datadog.trace.api.gateway.Events.EVENTS

class HttpServerDecoratorTest extends ServerDecoratorTest {
Expand Down Expand Up @@ -566,4 +568,54 @@ class HttpServerDecoratorTest extends ServerDecoratorTest {
return reqHeaderDoneCount
}
}

def "test setBaggageTags default"() {
setup:
def tags = [:]

when:
def tagContext = new TagContext()
HttpServerDecorator.setBaggageTags(tagContext, ["user.id": "doggo", "account.id": "test", "session.id": "1234", "region": "us -east - 1"])
tagContext.tags.fillMap(tags)

then:
tags == ["baggage.user.id": "doggo", "baggage.account.id": "test", "baggage.session.id": "1234"]
}

def "test setBaggageTags does not overwrite"() {
setup:
def tags = [:]

when:
def tagContext = new TagContext()
tagContext.putTag("baggage.account.id", "staging")
HttpServerDecorator.setBaggageTags(tagContext, ["user.id": "doggo", "account.id": "test", "session.id": "1234", "region": "us -east - 1"])
tagContext.tags.fillMap(tags)

then:
tags == ["baggage.user.id": "doggo", "baggage.account.id": "staging", "baggage.session.id": "1234"]
}

def "test setBaggageTags with different configurations"() {
setup:
injectSysConfig(TRACE_BAGGAGE_TAG_KEYS, baggageTagKeysConfig)
def tags = [:]

when:
def tagContext = new TagContext()
HttpServerDecorator.setBaggageTags(tagContext, ["user.id": "doggo", "foo": "bar", "language": "en"])
tagContext.tags.fillMap(tags)

then:
tags == expectedTags

where:
baggageTagKeysConfig | expectedTags
"*" | ["baggage.user.id": "doggo", "baggage.foo": "bar", "baggage.language": "en"]
" " | [:]
"system.id" | [:]
"user.id" | ["baggage.user.id": "doggo"]
"foo" | ["baggage.foo": "bar"]
"user.id,foo" | ["baggage.user.id": "doggo", "baggage.foo": "bar"]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,53 @@ abstract class HttpServerTest<SERVER> extends WithHttpServer<SERVER> {
'GET' | null | 'x-datadog-test-request-header' | 'bar' | ['request_header_tag': 'bar']
}

def "test baggage span tags are properly added"() {
setup:
// Use default configuration for TRACE_BAGGAGE_TAG_KEYS (user.id, session.id, account.id)
def baggageHeader = "user.id=test-user,session.id=test-session,account.id=test-account,language=en"
def request = request(SUCCESS, 'GET', null)
.header("baggage", baggageHeader)
.build()
def response = client.newCall(request).execute()
if (isDataStreamsEnabled()) {
TEST_DATA_STREAMS_WRITER.waitForGroups(1)
}

expect:
response.code() == SUCCESS.status
response.body().string() == SUCCESS.body

and:
assertTraces(1) {
trace(spanCount(SUCCESS)) {
sortSpansByStart()
// Verify baggage tags are added for default configured keys only
serverSpan(it, null, null, 'GET', SUCCESS, [
"baggage.user.id": "test-user",
"baggage.session.id": "test-session",
"baggage.account.id": "test-account"
// "baggage.language" should NOT be present since it's not in default config
])
if (hasHandlerSpan()) {
handlerSpan(it)
}
controllerSpan(it)
if (hasResponseSpan(SUCCESS)) {
responseSpan(it, SUCCESS)
}
}
}

and:
if (isDataStreamsEnabled()) {
StatsGroup first = TEST_DATA_STREAMS_WRITER.groups.find { it.parentHash == 0 }
verifyAll(first) {
edgeTags.containsAll(DSM_EDGE_TAGS)
edgeTags.size() == DSM_EDGE_TAGS.size()
}
}
}

@Flaky(value = "https://github.com/DataDog/dd-trace-java/issues/4690", suites = ["MuleHttpServerForkedTest"])
def "test QUERY_ENCODED_BOTH with response header x-ig-response-header tag mapping"() {
setup:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ public final class ConfigDefaults {
new LinkedHashSet<>(asList(PropagationStyle.DATADOG));
static final int DEFAULT_TRACE_BAGGAGE_MAX_ITEMS = 64;
static final int DEFAULT_TRACE_BAGGAGE_MAX_BYTES = 8192;
static final List<String> DEFAULT_TRACE_BAGGAGE_TAG_KEYS =
Arrays.asList("user.id", "session.id", "account.id");
static final boolean DEFAULT_JMX_FETCH_ENABLED = true;
static final boolean DEFAULT_TRACE_AGENT_V05_ENABLED = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ public final class TracerConfig {
public static final String TRACE_PROPAGATION_EXTRACT_FIRST = "trace.propagation.extract.first";
public static final String TRACE_BAGGAGE_MAX_ITEMS = "trace.baggage.max.items";
public static final String TRACE_BAGGAGE_MAX_BYTES = "trace.baggage.max.bytes";
public static final String TRACE_BAGGAGE_TAG_KEYS = "trace.baggage.tag.keys";

public static final String ENABLE_TRACE_AGENT_V05 = "trace.agent.v0.5.enabled";

Expand Down
14 changes: 14 additions & 0 deletions internal-api/src/main/java/datadog/trace/api/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@
import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_ANALYTICS_ENABLED;
import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_BAGGAGE_MAX_BYTES;
import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_BAGGAGE_MAX_ITEMS;
import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_BAGGAGE_TAG_KEYS;
import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_CLOUD_PAYLOAD_TAGGING_SERVICES;
import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_EXPERIMENTAL_FEATURES_ENABLED;
import static datadog.trace.api.ConfigDefaults.DEFAULT_TRACE_HTTP_RESOURCE_REMOVE_TRAILING_SLASH;
Expand Down Expand Up @@ -583,6 +584,7 @@
import static datadog.trace.api.config.TracerConfig.TRACE_ANALYTICS_ENABLED;
import static datadog.trace.api.config.TracerConfig.TRACE_BAGGAGE_MAX_BYTES;
import static datadog.trace.api.config.TracerConfig.TRACE_BAGGAGE_MAX_ITEMS;
import static datadog.trace.api.config.TracerConfig.TRACE_BAGGAGE_TAG_KEYS;
import static datadog.trace.api.config.TracerConfig.TRACE_CLIENT_IP_HEADER;
import static datadog.trace.api.config.TracerConfig.TRACE_CLIENT_IP_RESOLVER_ENABLED;
import static datadog.trace.api.config.TracerConfig.TRACE_CLOUD_PAYLOAD_TAGGING_MAX_DEPTH;
Expand Down Expand Up @@ -823,6 +825,7 @@ public static String getHostName() {
private final boolean tracePropagationExtractFirst;
private final int traceBaggageMaxItems;
private final int traceBaggageMaxBytes;
private final List<String> traceBaggageTagKeys;
private final int clockSyncPeriod;
private final boolean logsInjectionEnabled;

Expand Down Expand Up @@ -1695,6 +1698,11 @@ private Config(final ConfigProvider configProvider, final InstrumenterConfig ins
// If we have a new setting, we log a warning
logOverriddenDeprecatedSettingWarning(PROPAGATION_STYLE_INJECT, injectOrigin, inject);
}

// Parse the baggage tag keys configuration
traceBaggageTagKeys =
configProvider.getList(TRACE_BAGGAGE_TAG_KEYS, DEFAULT_TRACE_BAGGAGE_TAG_KEYS);

// Now we can check if we should pick the default injection/extraction

tracePropagationStylesToExtract =
Expand Down Expand Up @@ -2966,6 +2974,10 @@ public Map<String, String> getBaggageMapping() {
return baggageMapping;
}

public List<String> getTraceBaggageTagKeys() {
return traceBaggageTagKeys;
}

public Map<String, String> getHttpServerPathResourceNameMapping() {
return httpServerPathResourceNameMapping;
}
Expand Down Expand Up @@ -5374,6 +5386,8 @@ public String toString() {
+ traceKeepLatencyThreshold
+ ", traceStrictWritesEnabled="
+ traceStrictWritesEnabled
+ ", traceBaggageTagKeys="
+ traceBaggageTagKeys
+ ", tracePropagationStylesToExtract="
+ tracePropagationStylesToExtract
+ ", tracePropagationStylesToInject="
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,15 @@ public void putTag(final String key, final String value) {
this.tags.set(key, value);
}

public void putTagIfAbsent(final String key, final String value) {
if (this.tags == null) {
this.tags = TagMap.create(4);
}
if (!this.tags.containsKey(key)) {
this.tags.set(key, value);
}
}

@Override
public final int getSamplingPriority() {
return samplingPriority;
Expand Down