Skip to content

Commit 19f8596

Browse files
authored
Collect process tags for tracing (#8698)
* Collect process tags for tracing * fix tests and experimental features * Only add to first span in chunk * fix tests * use the good tag name * target all spring boot advices * fix coverage * Add process tags to client stats payload (#8704) * Use the correct setting name * update system test commit * refactor * add more tests
1 parent 0698839 commit 19f8596

File tree

25 files changed

+531
-48
lines changed

25 files changed

+531
-48
lines changed

.circleci/config.continue.yml.j2

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ instrumentation_modules: &instrumentation_modules "dd-java-agent/instrumentation
3636
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"
3737
profiling_modules: &profiling_modules "dd-java-agent/agent-profiling"
3838

39-
default_system_tests_commit: &default_system_tests_commit 761b9e7a82ffb136c4653a4d1623d120d67b005b
39+
default_system_tests_commit: &default_system_tests_commit 08276e905c5c81055412ea4c318856d879cf15e5
4040

4141
parameters:
4242
nightly:

dd-java-agent/instrumentation/graal/native-image/src/main/java/datadog/trace/instrumentation/graal/nativeimage/NativeImageGeneratorRunnerInstrumentation.java

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public static void onEnter(@Advice.Argument(value = 0, readOnly = false) String[
7676
+ "datadog.trace.api.Platform:rerun,"
7777
+ "datadog.trace.api.Platform$Captured:build_time,"
7878
+ "datadog.trace.api.env.CapturedEnvironment:build_time,"
79+
+ "datadog.trace.api.env.CapturedEnvironment$ProcessInfo:build_time,"
7980
+ "datadog.trace.api.ConfigCollector:rerun,"
8081
+ "datadog.trace.api.ConfigDefaults:build_time,"
8182
+ "datadog.trace.api.ConfigOrigin:build_time,"

dd-java-agent/instrumentation/spring-boot/src/main/java/datadog/trace/instrumentation/springboot/SpringApplicationInstrumentation.java

+25
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import datadog.trace.agent.tooling.Instrumenter;
88
import datadog.trace.agent.tooling.InstrumenterModule;
99
import datadog.trace.api.Config;
10+
import datadog.trace.api.ProcessTags;
1011
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
1112
import net.bytebuddy.asm.Advice;
1213
import org.springframework.core.env.ConfigurableEnvironment;
@@ -60,6 +61,18 @@ public static void afterEnvironmentPostProcessed(
6061
final String applicationName = environment.getProperty("spring.application.name");
6162
if (applicationName != null && !applicationName.isEmpty()) {
6263
AgentTracer.get().updatePreferredServiceName(applicationName);
64+
ProcessTags.addTag("springboot.application", applicationName);
65+
}
66+
if (Config.get().isExperimentalPropagateProcessTagsEnabled()) {
67+
final String[] profiles = environment.getActiveProfiles();
68+
if (profiles != null && profiles.length > 0) {
69+
ProcessTags.addTag("springboot.profile", profiles[0]);
70+
} else {
71+
final String[] defaultProfiles = environment.getDefaultProfiles();
72+
if (defaultProfiles != null && defaultProfiles.length > 0) {
73+
ProcessTags.addTag("springboot.profile", defaultProfiles[0]);
74+
}
75+
}
6376
}
6477
}
6578
}
@@ -77,6 +90,18 @@ public static void afterEnvironmentPostProcessed(
7790
final String applicationName = environment.getProperty("spring.application.name");
7891
if (applicationName != null && !applicationName.isEmpty()) {
7992
AgentTracer.get().updatePreferredServiceName(applicationName);
93+
ProcessTags.addTag("springboot.application", applicationName);
94+
}
95+
if (Config.get().isExperimentalPropagateProcessTagsEnabled()) {
96+
final String[] profiles = environment.getActiveProfiles();
97+
if (profiles != null && profiles.length > 0) {
98+
ProcessTags.addTag("springboot.profile", profiles[0]);
99+
} else {
100+
final String[] defaultProfiles = environment.getDefaultProfiles();
101+
if (defaultProfiles != null && defaultProfiles.length > 0) {
102+
ProcessTags.addTag("springboot.profile", defaultProfiles[0]);
103+
}
104+
}
80105
}
81106
}
82107
}

dd-java-agent/instrumentation/spring-boot/src/test/groovy/SpringBootApplicationTest.groovy

+14-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1+
import datadog.trace.api.ProcessTags
2+
13
import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace
24

35
import datadog.trace.agent.test.AgentTestRunner
4-
import datadog.trace.api.Config
56
import org.springframework.beans.factory.InitializingBean
67
import org.springframework.boot.SpringApplication
78

9+
import static datadog.trace.api.config.GeneralConfig.EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED
10+
811
class SpringBootApplicationTest extends AgentTestRunner {
912
@Override
1013
protected void configurePreAgent() {
1114
super.configurePreAgent()
15+
injectSysConfig(EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED, "true")
1216
}
17+
1318
static class BeanWhoTraces implements InitializingBean {
1419

1520
@Override
@@ -32,15 +37,19 @@ class SpringBootApplicationTest extends AgentTestRunner {
3237
}
3338
}
3439
})
40+
and:
41+
def processTags = ProcessTags.getTagsForSerialization()
42+
assert processTags.toString() =~ ".+,springboot.application:$expectedService,springboot.profile:$expectedProfile"
3543
context != null
3644
cleanup:
3745
context?.stop()
3846
where:
39-
expectedService | args
40-
"application-name-from-args" | new String[]{
41-
"--spring.application.name=application-name-from-args"
47+
expectedService | expectedProfile | args
48+
"application-name-from-args" | "prod" | new String[]{
49+
"--spring.application.name=application-name-from-args",
50+
"--spring.profiles.active=prod,common",
4251
}
43-
"application-name-from-properties" | new String[0] // will load from properties
52+
"application-name-from-properties" | "default" | new String[0] // will load from properties
4453
}
4554
}
4655

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

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import datadog.trace.agent.tooling.bytebuddy.matcher.GlobalIgnores
2727
import datadog.trace.api.Config
2828
import datadog.trace.api.DDSpanId
2929
import datadog.trace.api.IdGenerationStrategy
30+
import datadog.trace.api.ProcessTags
3031
import datadog.trace.api.StatsDClient
3132
import datadog.trace.api.TraceConfig
3233
import datadog.trace.api.WellKnownTags
@@ -509,6 +510,7 @@ abstract class AgentTestRunner extends DDSpecification implements AgentBuilder.L
509510
ActiveSubsystems.APPSEC_ACTIVE = true
510511
}
511512
InstrumentationErrors.resetErrorCount()
513+
ProcessTags.reset()
512514
}
513515

514516
@Override

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,8 @@ public final class ConfigDefaults {
241241
static final int DEFAULT_TELEMETRY_DEPENDENCY_RESOLUTION_QUEUE_SIZE = 100000;
242242

243243
static final Set<String> DEFAULT_TRACE_EXPERIMENTAL_FEATURES_ENABLED =
244-
new HashSet<>(asList("DD_TAGS", "DD_LOGS_INJECTION"));
244+
new HashSet<>(
245+
asList("DD_TAGS", "DD_LOGS_INJECTION", "DD_EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED"));
245246

246247
static final boolean DEFAULT_TRACE_128_BIT_TRACEID_GENERATION_ENABLED = true;
247248
static final boolean DEFAULT_TRACE_128_BIT_TRACEID_LOGGING_ENABLED = true;

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

+1
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,5 @@ public class DDTags {
9898
public static final String DECISION_MAKER_INHERITED = "_dd.dm.inherited";
9999
public static final String DECISION_MAKER_SERVICE = "_dd.dm.service";
100100
public static final String DECISION_MAKER_RESOURCE = "_dd.dm.resource";
101+
public static final String PROCESS_TAGS = "_dd.tags.process";
101102
}

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

+3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ public final class GeneralConfig {
2929
@Deprecated // Use dd.tags instead
3030
public static final String GLOBAL_TAGS = "trace.global.tags";
3131

32+
public static final String EXPERIMENTAL_PROPAGATE_PROCESS_TAGS_ENABLED =
33+
"experimental.propagate.process.tags.enabled";
34+
3235
public static final String LOG_LEVEL = "log.level";
3336
public static final String TRACE_DEBUG = "trace.debug";
3437
public static final String TRACE_TRIAGE = "trace.triage";

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

+12-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
import datadog.communication.serialization.GrowableBuffer;
66
import datadog.communication.serialization.WritableFormatter;
77
import datadog.communication.serialization.msgpack.MsgPackWriter;
8+
import datadog.trace.api.ProcessTags;
89
import datadog.trace.api.WellKnownTags;
10+
import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString;
911

1012
public final class SerializingMetricWriter implements MetricWriter {
1113

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

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

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

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

73+
if (writeProcessTags) {
74+
writer.writeUTF8(PROCESS_TAGS);
75+
writer.writeUTF8(processTags);
76+
}
77+
6878
writer.writeUTF8(STATS);
79+
6980
writer.startArray(1);
7081

7182
writer.startMap(3);

dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/TraceMapper.java

+1
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ public interface TraceMapper extends RemoteMapper {
1212
UTF8BytesString SAMPLING_PRIORITY_KEY =
1313
UTF8BytesString.create(DDSpanContext.PRIORITY_SAMPLING_KEY);
1414
UTF8BytesString ORIGIN_KEY = UTF8BytesString.create(DDTags.ORIGIN_KEY);
15+
UTF8BytesString PROCESS_TAGS_KEY = UTF8BytesString.create(DDTags.PROCESS_TAGS);
1516
}

dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/TraceMapperV0_4.java

+20-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import datadog.communication.serialization.GrowableBuffer;
77
import datadog.communication.serialization.Writable;
88
import datadog.communication.serialization.msgpack.MsgPackWriter;
9+
import datadog.trace.api.ProcessTags;
910
import datadog.trace.bootstrap.instrumentation.api.InstrumentationTags;
1011
import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString;
1112
import datadog.trace.common.writer.Payload;
@@ -36,25 +37,35 @@ public TraceMapperV0_4() {
3637
private static final class MetaWriter implements MetadataConsumer {
3738

3839
private Writable writable;
39-
private boolean writeSamplingPriority;
40+
private boolean firstSpanInChunk;
41+
private boolean lastSpanInChunk;
4042

4143
MetaWriter withWritable(Writable writable) {
4244
this.writable = writable;
4345
return this;
4446
}
4547

46-
MetaWriter withWriteSamplingPriority(final boolean writeSamplingPriority) {
47-
this.writeSamplingPriority = writeSamplingPriority;
48+
MetaWriter forFirstSpanInChunk(final boolean firstSpanInChunk) {
49+
this.firstSpanInChunk = firstSpanInChunk;
50+
return this;
51+
}
52+
53+
MetaWriter forLastSpanInChunk(final boolean lastSpanInChunk) {
54+
this.lastSpanInChunk = lastSpanInChunk;
4855
return this;
4956
}
5057

5158
@Override
5259
public void accept(Metadata metadata) {
60+
final boolean writeSamplingPriority = firstSpanInChunk || lastSpanInChunk;
61+
final UTF8BytesString processTags =
62+
firstSpanInChunk ? ProcessTags.getTagsForSerialization() : null;
5363
int metaSize =
5464
metadata.getBaggage().size()
5565
+ metadata.getTags().size()
5666
+ (null == metadata.getHttpStatusCode() ? 0 : 1)
5767
+ (null == metadata.getOrigin() ? 0 : 1)
68+
+ (null == processTags ? 0 : 1)
5869
+ 1;
5970
int metricsSize =
6071
(writeSamplingPriority && metadata.hasSamplingPriority() ? 1 : 0)
@@ -124,6 +135,10 @@ public void accept(Metadata metadata) {
124135
writable.writeUTF8(ORIGIN_KEY);
125136
writable.writeString(metadata.getOrigin(), null);
126137
}
138+
if (processTags != null) {
139+
writable.writeUTF8(PROCESS_TAGS_KEY);
140+
writable.writeUTF8(processTags);
141+
}
127142
for (Map.Entry<String, Object> entry : metadata.getTags().entrySet()) {
128143
String key = entry.getKey();
129144
Object value = entry.getValue();
@@ -273,7 +288,8 @@ public void map(List<? extends CoreSpan<?>> trace, final Writable writable) {
273288
span.processTagsAndBaggage(
274289
metaWriter
275290
.withWritable(writable)
276-
.withWriteSamplingPriority(i == 0 || i == trace.size() - 1));
291+
.forFirstSpanInChunk(i == 0)
292+
.forLastSpanInChunk(i == trace.size() - 1));
277293
if (!metaStruct.isEmpty()) {
278294
/* 13 */
279295
metaStructWriter.withWritable(writable).write(metaStruct);

dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/TraceMapperV0_5.java

+20-4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import datadog.communication.serialization.Writable;
88
import datadog.communication.serialization.WritableFormatter;
99
import datadog.communication.serialization.msgpack.MsgPackWriter;
10+
import datadog.trace.api.ProcessTags;
1011
import datadog.trace.bootstrap.instrumentation.api.InstrumentationTags;
1112
import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString;
1213
import datadog.trace.common.writer.Payload;
@@ -78,7 +79,8 @@ public void map(final List<? extends CoreSpan<?>> trace, final Writable writable
7879
span.processTagsAndBaggage(
7980
metaWriter
8081
.withWritable(writable)
81-
.withWriteSamplingPriority(i == 0 || i == trace.size() - 1));
82+
.forFirstSpanInChunk(i == 0)
83+
.forLastSpanInChunk(i == trace.size() - 1));
8284
/* 12 */
8385
writeDictionaryEncoded(writable, span.getType());
8486
}
@@ -179,25 +181,35 @@ private List<ByteBuffer> toList() {
179181
private final class MetaWriter implements MetadataConsumer {
180182

181183
private Writable writable;
182-
private boolean writeSamplingPriority;
184+
private boolean firstSpanInChunk;
185+
private boolean lastSpanInChunk;
183186

184187
MetaWriter withWritable(final Writable writable) {
185188
this.writable = writable;
186189
return this;
187190
}
188191

189-
MetaWriter withWriteSamplingPriority(final boolean writeSamplingPriority) {
190-
this.writeSamplingPriority = writeSamplingPriority;
192+
MetaWriter forFirstSpanInChunk(final boolean firstSpanInChunk) {
193+
this.firstSpanInChunk = firstSpanInChunk;
194+
return this;
195+
}
196+
197+
MetaWriter forLastSpanInChunk(final boolean lastSpanInChunk) {
198+
this.lastSpanInChunk = lastSpanInChunk;
191199
return this;
192200
}
193201

194202
@Override
195203
public void accept(Metadata metadata) {
204+
final boolean writeSamplingPriority = firstSpanInChunk || lastSpanInChunk;
205+
final UTF8BytesString processTags =
206+
firstSpanInChunk ? ProcessTags.getTagsForSerialization() : null;
196207
int metaSize =
197208
metadata.getBaggage().size()
198209
+ metadata.getTags().size()
199210
+ (null == metadata.getHttpStatusCode() ? 0 : 1)
200211
+ (null == metadata.getOrigin() ? 0 : 1)
212+
+ (null == processTags ? 0 : 1)
201213
+ 1;
202214
int metricsSize =
203215
(writeSamplingPriority && metadata.hasSamplingPriority() ? 1 : 0)
@@ -234,6 +246,10 @@ public void accept(Metadata metadata) {
234246
writeDictionaryEncoded(writable, ORIGIN_KEY);
235247
writeDictionaryEncoded(writable, metadata.getOrigin());
236248
}
249+
if (null != processTags) {
250+
writeDictionaryEncoded(writable, PROCESS_TAGS_KEY);
251+
writeDictionaryEncoded(writable, processTags);
252+
}
237253
for (Map.Entry<String, Object> entry : metadata.getTags().entrySet()) {
238254
String key = entry.getKey();
239255
Object value = entry.getValue();

dd-trace-core/src/main/java/datadog/trace/core/DDSpanContext.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import datadog.trace.api.DDTags;
88
import datadog.trace.api.DDTraceId;
99
import datadog.trace.api.Functions;
10+
import datadog.trace.api.ProcessTags;
1011
import datadog.trace.api.cache.DDCache;
1112
import datadog.trace.api.cache.DDCaches;
1213
import datadog.trace.api.config.TracerConfig;
@@ -874,7 +875,8 @@ public void processTagsAndBaggage(
874875
httpStatusCode == 0 ? null : HTTP_STATUSES.get(httpStatusCode),
875876
// Get origin from rootSpan.context
876877
getOrigin(),
877-
longRunningVersion));
878+
longRunningVersion,
879+
ProcessTags.getTagsForSerialization()));
878880
}
879881
}
880882

dd-trace-core/src/main/java/datadog/trace/core/Metadata.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public final class Metadata {
1717
private final boolean topLevel;
1818
private final CharSequence origin;
1919
private final int longRunningVersion;
20+
private final UTF8BytesString processTags;
2021

2122
public Metadata(
2223
long threadId,
@@ -28,7 +29,8 @@ public Metadata(
2829
boolean topLevel,
2930
UTF8BytesString httpStatusCode,
3031
CharSequence origin,
31-
int longRunningVersion) {
32+
int longRunningVersion,
33+
UTF8BytesString processTags) {
3234
this.threadId = threadId;
3335
this.threadName = threadName;
3436
this.httpStatusCode = httpStatusCode;
@@ -39,6 +41,7 @@ public Metadata(
3941
this.topLevel = topLevel;
4042
this.origin = origin;
4143
this.longRunningVersion = longRunningVersion;
44+
this.processTags = processTags;
4245
}
4346

4447
public UTF8BytesString getHttpStatusCode() {
@@ -84,4 +87,8 @@ public boolean hasSamplingPriority() {
8487
public int samplingPriority() {
8588
return samplingPriority;
8689
}
90+
91+
public UTF8BytesString processTags() {
92+
return processTags;
93+
}
8794
}

0 commit comments

Comments
 (0)