Skip to content

Collect process tags for tracing #8698

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Apr 29, 2025
2 changes: 1 addition & 1 deletion .circleci/config.continue.yml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ instrumentation_modules: &instrumentation_modules "dd-java-agent/instrumentation
debugger_modules: &debugger_modules "dd-java-agent/agent-debugger|dd-java-agent/agent-bootstrap|dd-java-agent/agent-builder|internal-api|communication|dd-trace-core"
profiling_modules: &profiling_modules "dd-java-agent/agent-profiling"

default_system_tests_commit: &default_system_tests_commit 761b9e7a82ffb136c4653a4d1623d120d67b005b
default_system_tests_commit: &default_system_tests_commit 08276e905c5c81055412ea4c318856d879cf15e5

parameters:
nightly:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public static void onEnter(@Advice.Argument(value = 0, readOnly = false) String[
+ "datadog.trace.api.Platform:rerun,"
+ "datadog.trace.api.Platform$Captured:build_time,"
+ "datadog.trace.api.env.CapturedEnvironment:build_time,"
+ "datadog.trace.api.env.CapturedEnvironment$ProcessInfo:build_time,"
+ "datadog.trace.api.ConfigCollector:rerun,"
+ "datadog.trace.api.ConfigDefaults:build_time,"
+ "datadog.trace.api.ConfigOrigin:build_time,"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.agent.tooling.InstrumenterModule;
import datadog.trace.api.Config;
import datadog.trace.api.ProcessTags;
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
import net.bytebuddy.asm.Advice;
import org.springframework.core.env.ConfigurableEnvironment;
Expand Down Expand Up @@ -60,6 +61,18 @@ public static void afterEnvironmentPostProcessed(
final String applicationName = environment.getProperty("spring.application.name");
if (applicationName != null && !applicationName.isEmpty()) {
AgentTracer.get().updatePreferredServiceName(applicationName);
ProcessTags.addTag("springboot.application", applicationName);
}
if (Config.get().isExperimentalPropagateProcessTagsEnabled()) {
final String[] profiles = environment.getActiveProfiles();
if (profiles != null && profiles.length > 0) {
ProcessTags.addTag("springboot.profile", profiles[0]);
} else {
final String[] defaultProfiles = environment.getDefaultProfiles();
if (defaultProfiles != null && defaultProfiles.length > 0) {
ProcessTags.addTag("springboot.profile", defaultProfiles[0]);
}
}
}
}
}
Expand All @@ -77,6 +90,18 @@ public static void afterEnvironmentPostProcessed(
final String applicationName = environment.getProperty("spring.application.name");
if (applicationName != null && !applicationName.isEmpty()) {
AgentTracer.get().updatePreferredServiceName(applicationName);
ProcessTags.addTag("springboot.application", applicationName);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be extracted into a helper to avoid duplicating this logic in two places?

}
if (Config.get().isExperimentalPropagateProcessTagsEnabled()) {
final String[] profiles = environment.getActiveProfiles();
if (profiles != null && profiles.length > 0) {
ProcessTags.addTag("springboot.profile", profiles[0]);
} else {
final String[] defaultProfiles = environment.getDefaultProfiles();
if (defaultProfiles != null && defaultProfiles.length > 0) {
ProcessTags.addTag("springboot.profile", defaultProfiles[0]);
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import datadog.trace.api.ProcessTags

import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace

import datadog.trace.agent.test.AgentTestRunner
import datadog.trace.api.Config
import org.springframework.beans.factory.InitializingBean
import org.springframework.boot.SpringApplication

import static datadog.trace.api.config.GeneralConfig.EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED

class SpringBootApplicationTest extends AgentTestRunner {
@Override
protected void configurePreAgent() {
super.configurePreAgent()
injectSysConfig(EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED, "true")
}

static class BeanWhoTraces implements InitializingBean {

@Override
Expand All @@ -32,15 +37,19 @@ class SpringBootApplicationTest extends AgentTestRunner {
}
}
})
and:
def processTags = ProcessTags.getTagsForSerialization()
assert processTags.toString() =~ ".+,springboot.application:$expectedService,springboot.profile:$expectedProfile"
context != null
cleanup:
context?.stop()
where:
expectedService | args
"application-name-from-args" | new String[]{
"--spring.application.name=application-name-from-args"
expectedService | expectedProfile | args
"application-name-from-args" | "prod" | new String[]{
"--spring.application.name=application-name-from-args",
"--spring.profiles.active=prod,common",
}
"application-name-from-properties" | new String[0] // will load from properties
"application-name-from-properties" | "default" | new String[0] // will load from properties
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import datadog.trace.agent.tooling.bytebuddy.matcher.GlobalIgnores
import datadog.trace.api.Config
import datadog.trace.api.DDSpanId
import datadog.trace.api.IdGenerationStrategy
import datadog.trace.api.ProcessTags
import datadog.trace.api.StatsDClient
import datadog.trace.api.TraceConfig
import datadog.trace.api.WellKnownTags
Expand Down Expand Up @@ -509,6 +510,7 @@ abstract class AgentTestRunner extends DDSpecification implements AgentBuilder.L
ActiveSubsystems.APPSEC_ACTIVE = true
}
InstrumentationErrors.resetErrorCount()
ProcessTags.reset()
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,8 @@ public final class ConfigDefaults {
static final int DEFAULT_TELEMETRY_DEPENDENCY_RESOLUTION_QUEUE_SIZE = 100000;

static final Set<String> DEFAULT_TRACE_EXPERIMENTAL_FEATURES_ENABLED =
new HashSet<>(asList("DD_TAGS", "DD_LOGS_INJECTION"));
new HashSet<>(
asList("DD_TAGS", "DD_LOGS_INJECTION", "DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED"));

static final boolean DEFAULT_TRACE_128_BIT_TRACEID_GENERATION_ENABLED = true;
static final boolean DEFAULT_TRACE_128_BIT_TRACEID_LOGGING_ENABLED = true;
Expand Down
1 change: 1 addition & 0 deletions dd-trace-api/src/main/java/datadog/trace/api/DDTags.java
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,5 @@ public class DDTags {
public static final String DECISION_MAKER_INHERITED = "_dd.dm.inherited";
public static final String DECISION_MAKER_SERVICE = "_dd.dm.service";
public static final String DECISION_MAKER_RESOURCE = "_dd.dm.resource";
public static final String PROCESS_TAGS = "_dd.tags.process";
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ public final class GeneralConfig {
@Deprecated // Use dd.tags instead
public static final String GLOBAL_TAGS = "trace.global.tags";

public static final String EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED =
"experimental.propagate.process.tags.enabled";

public static final String LOG_LEVEL = "log.level";
public static final String TRACE_DEBUG = "trace.debug";
public static final String TRACE_TRIAGE = "trace.triage";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import datadog.communication.serialization.GrowableBuffer;
import datadog.communication.serialization.WritableFormatter;
import datadog.communication.serialization.msgpack.MsgPackWriter;
import datadog.trace.api.ProcessTags;
import datadog.trace.api.WellKnownTags;
import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString;

public final class SerializingMetricWriter implements MetricWriter {

Expand All @@ -28,6 +30,7 @@ public final class SerializingMetricWriter implements MetricWriter {
private static final byte[] STATS = "Stats".getBytes(ISO_8859_1);
private static final byte[] OK_SUMMARY = "OkSummary".getBytes(ISO_8859_1);
private static final byte[] ERROR_SUMMARY = "ErrorSummary".getBytes(ISO_8859_1);
private static final byte[] PROCESS_TAGS = "ProcessTags".getBytes(ISO_8859_1);

private final WellKnownTags wellKnownTags;
private final WritableFormatter writer;
Expand All @@ -48,7 +51,9 @@ public SerializingMetricWriter(WellKnownTags wellKnownTags, Sink sink, int initi

@Override
public void startBucket(int metricCount, long start, long duration) {
writer.startMap(6);
final UTF8BytesString processTags = ProcessTags.getTagsForSerialization();
final boolean writeProcessTags = processTags != null;
writer.startMap(6 + (writeProcessTags ? 1 : 0));

writer.writeUTF8(RUNTIME_ID);
writer.writeUTF8(wellKnownTags.getRuntimeId());
Expand All @@ -65,7 +70,13 @@ public void startBucket(int metricCount, long start, long duration) {
writer.writeUTF8(VERSION);
writer.writeUTF8(wellKnownTags.getVersion());

if (writeProcessTags) {
writer.writeUTF8(PROCESS_TAGS);
writer.writeUTF8(processTags);
}

writer.writeUTF8(STATS);

writer.startArray(1);

writer.startMap(3);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ public interface TraceMapper extends RemoteMapper {
UTF8BytesString SAMPLING_PRIORITY_KEY =
UTF8BytesString.create(DDSpanContext.PRIORITY_SAMPLING_KEY);
UTF8BytesString ORIGIN_KEY = UTF8BytesString.create(DDTags.ORIGIN_KEY);
UTF8BytesString PROCESS_TAGS_KEY = UTF8BytesString.create(DDTags.PROCESS_TAGS);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import datadog.communication.serialization.GrowableBuffer;
import datadog.communication.serialization.Writable;
import datadog.communication.serialization.msgpack.MsgPackWriter;
import datadog.trace.api.ProcessTags;
import datadog.trace.bootstrap.instrumentation.api.InstrumentationTags;
import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString;
import datadog.trace.common.writer.Payload;
Expand Down Expand Up @@ -36,25 +37,35 @@ public TraceMapperV0_4() {
private static final class MetaWriter implements MetadataConsumer {

private Writable writable;
private boolean writeSamplingPriority;
private boolean firstSpanInChunk;
private boolean lastSpanInChunk;

MetaWriter withWritable(Writable writable) {
this.writable = writable;
return this;
}

MetaWriter withWriteSamplingPriority(final boolean writeSamplingPriority) {
this.writeSamplingPriority = writeSamplingPriority;
MetaWriter forFirstSpanInChunk(final boolean firstSpanInChunk) {
this.firstSpanInChunk = firstSpanInChunk;
return this;
}

MetaWriter forLastSpanInChunk(final boolean lastSpanInChunk) {
this.lastSpanInChunk = lastSpanInChunk;
return this;
}

@Override
public void accept(Metadata metadata) {
final boolean writeSamplingPriority = firstSpanInChunk || lastSpanInChunk;
final UTF8BytesString processTags =
firstSpanInChunk ? ProcessTags.getTagsForSerialization() : null;
int metaSize =
metadata.getBaggage().size()
+ metadata.getTags().size()
+ (null == metadata.getHttpStatusCode() ? 0 : 1)
+ (null == metadata.getOrigin() ? 0 : 1)
+ (null == processTags ? 0 : 1)
+ 1;
int metricsSize =
(writeSamplingPriority && metadata.hasSamplingPriority() ? 1 : 0)
Expand Down Expand Up @@ -124,6 +135,10 @@ public void accept(Metadata metadata) {
writable.writeUTF8(ORIGIN_KEY);
writable.writeString(metadata.getOrigin(), null);
}
if (processTags != null) {
writable.writeUTF8(PROCESS_TAGS_KEY);
writable.writeUTF8(processTags);
}
for (Map.Entry<String, Object> entry : metadata.getTags().entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
Expand Down Expand Up @@ -273,7 +288,8 @@ public void map(List<? extends CoreSpan<?>> trace, final Writable writable) {
span.processTagsAndBaggage(
metaWriter
.withWritable(writable)
.withWriteSamplingPriority(i == 0 || i == trace.size() - 1));
.forFirstSpanInChunk(i == 0)
.forLastSpanInChunk(i == trace.size() - 1));
if (!metaStruct.isEmpty()) {
/* 13 */
metaStructWriter.withWritable(writable).write(metaStruct);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import datadog.communication.serialization.Writable;
import datadog.communication.serialization.WritableFormatter;
import datadog.communication.serialization.msgpack.MsgPackWriter;
import datadog.trace.api.ProcessTags;
import datadog.trace.bootstrap.instrumentation.api.InstrumentationTags;
import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString;
import datadog.trace.common.writer.Payload;
Expand Down Expand Up @@ -78,7 +79,8 @@ public void map(final List<? extends CoreSpan<?>> trace, final Writable writable
span.processTagsAndBaggage(
metaWriter
.withWritable(writable)
.withWriteSamplingPriority(i == 0 || i == trace.size() - 1));
.forFirstSpanInChunk(i == 0)
.forLastSpanInChunk(i == trace.size() - 1));
/* 12 */
writeDictionaryEncoded(writable, span.getType());
}
Expand Down Expand Up @@ -179,25 +181,35 @@ private List<ByteBuffer> toList() {
private final class MetaWriter implements MetadataConsumer {

private Writable writable;
private boolean writeSamplingPriority;
private boolean firstSpanInChunk;
private boolean lastSpanInChunk;

MetaWriter withWritable(final Writable writable) {
this.writable = writable;
return this;
}

MetaWriter withWriteSamplingPriority(final boolean writeSamplingPriority) {
this.writeSamplingPriority = writeSamplingPriority;
MetaWriter forFirstSpanInChunk(final boolean firstSpanInChunk) {
this.firstSpanInChunk = firstSpanInChunk;
return this;
}

MetaWriter forLastSpanInChunk(final boolean lastSpanInChunk) {
this.lastSpanInChunk = lastSpanInChunk;
return this;
}

@Override
public void accept(Metadata metadata) {
final boolean writeSamplingPriority = firstSpanInChunk || lastSpanInChunk;
final UTF8BytesString processTags =
firstSpanInChunk ? ProcessTags.getTagsForSerialization() : null;
int metaSize =
metadata.getBaggage().size()
+ metadata.getTags().size()
+ (null == metadata.getHttpStatusCode() ? 0 : 1)
+ (null == metadata.getOrigin() ? 0 : 1)
+ (null == processTags ? 0 : 1)
+ 1;
int metricsSize =
(writeSamplingPriority && metadata.hasSamplingPriority() ? 1 : 0)
Expand Down Expand Up @@ -234,6 +246,10 @@ public void accept(Metadata metadata) {
writeDictionaryEncoded(writable, ORIGIN_KEY);
writeDictionaryEncoded(writable, metadata.getOrigin());
}
if (null != processTags) {
writeDictionaryEncoded(writable, PROCESS_TAGS_KEY);
writeDictionaryEncoded(writable, processTags);
}
for (Map.Entry<String, Object> entry : metadata.getTags().entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import datadog.trace.api.DDTags;
import datadog.trace.api.DDTraceId;
import datadog.trace.api.Functions;
import datadog.trace.api.ProcessTags;
import datadog.trace.api.cache.DDCache;
import datadog.trace.api.cache.DDCaches;
import datadog.trace.api.config.TracerConfig;
Expand Down Expand Up @@ -874,7 +875,8 @@ public void processTagsAndBaggage(
httpStatusCode == 0 ? null : HTTP_STATUSES.get(httpStatusCode),
// Get origin from rootSpan.context
getOrigin(),
longRunningVersion));
longRunningVersion,
ProcessTags.getTagsForSerialization()));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public final class Metadata {
private final boolean topLevel;
private final CharSequence origin;
private final int longRunningVersion;
private final UTF8BytesString processTags;

public Metadata(
long threadId,
Expand All @@ -28,7 +29,8 @@ public Metadata(
boolean topLevel,
UTF8BytesString httpStatusCode,
CharSequence origin,
int longRunningVersion) {
int longRunningVersion,
UTF8BytesString processTags) {
this.threadId = threadId;
this.threadName = threadName;
this.httpStatusCode = httpStatusCode;
Expand All @@ -39,6 +41,7 @@ public Metadata(
this.topLevel = topLevel;
this.origin = origin;
this.longRunningVersion = longRunningVersion;
this.processTags = processTags;
}

public UTF8BytesString getHttpStatusCode() {
Expand Down Expand Up @@ -84,4 +87,8 @@ public boolean hasSamplingPriority() {
public int samplingPriority() {
return samplingPriority;
}

public UTF8BytesString processTags() {
return processTags;
}
}
Loading
Loading