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

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -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().isExperimentalCollectProcessTagsEnabled()) {
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().isExperimentalCollectProcessTagsEnabled()) {
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,21 @@
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_COLLECT_PROCESS_TAGS_ENABLED

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

static class BeanWhoTraces implements InitializingBean {

@Override
Expand All @@ -32,15 +38,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_COLLECT_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_COLLECT_PROCESS_TAGS_ENABLED =
"experimental.collect.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 @@ -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));
.forLastSpanInChunk(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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public final class TagsPostProcessorFactory {

private static class Lazy {
private static TagsPostProcessor create() {
final List<TagsPostProcessor> processors = new ArrayList<>(4);
final List<TagsPostProcessor> processors = new ArrayList<>(7);
processors.add(new PeerServiceCalculator());
if (addBaseService) {
processors.add(new BaseServiceAdder(Config.get().getServiceName()));
Expand Down Expand Up @@ -52,6 +52,7 @@ public static void withAddBaseService(boolean enabled) {
addBaseService = enabled;
Lazy.instance = Lazy.create();
}

/**
* Mostly used for test purposes.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import datadog.trace.api.DDSpanId
import datadog.trace.api.DDTags
import datadog.trace.api.DDTraceId
import datadog.trace.api.IdGenerationStrategy
import datadog.trace.api.ProcessTags
import datadog.trace.api.sampling.PrioritySampling
import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString
import datadog.trace.core.CoreSpan
Expand Down Expand Up @@ -177,7 +178,8 @@ class TraceGenerator {
this.samplingPriority = samplingPriority
this.metadata = new Metadata(Thread.currentThread().getId(),
UTF8BytesString.create(Thread.currentThread().getName()), tags, baggage, samplingPriority, measured, topLevel,
statusCode == 0 ? null : UTF8BytesString.create(Integer.toString(statusCode)), origin, 0)
statusCode == 0 ? null : UTF8BytesString.create(Integer.toString(statusCode)), origin, 0,
ProcessTags.tagsForSerialization)
this.httpStatusCode = (short) statusCode
}

Expand Down
Loading