Skip to content
Merged
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
17 changes: 9 additions & 8 deletions dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@
import datadog.trace.api.Config;
import datadog.trace.api.DDSpanId;
import datadog.trace.api.DDTraceId;
import datadog.trace.api.DynamicConfig;
import datadog.trace.api.EndpointCheckpointer;
import datadog.trace.api.EndpointCheckpointerHolder;
import datadog.trace.api.EndpointTracker;
import datadog.trace.api.IdGenerationStrategy;
import datadog.trace.api.InstrumenterConfig;
import datadog.trace.api.StatsDClient;
import datadog.trace.api.TraceConfig;
import datadog.trace.api.TracePropagationStyle;
import datadog.trace.api.config.GeneralConfig;
import datadog.trace.api.experimental.DataStreamsCheckpointer;
Expand Down Expand Up @@ -151,12 +153,12 @@ public static CoreTracerBuilder builder() {

final MetricsAggregator metricsAggregator;

/** Maintains dynamic configuration associated with the tracer */
private final DynamicConfig dynamicConfig;
/** A set of tags that are added only to the application's root span */
private final Map<String, ?> localRootSpanTags;
/** A set of tags that are added to every span */
private final Map<String, ?> defaultSpanTags;
/** A configured mapping of service names to update with new values */
private final Map<String, String> serviceNameMappings;

/** number of spans in a pending trace before they get flushed */
private final int partialFlushMinSpans;
Expand Down Expand Up @@ -205,6 +207,10 @@ public static CoreTracerBuilder builder() {

private final PropagationTags.Factory propagationTagsFactory;

TraceConfig captureTraceConfig() {
return dynamicConfig.captureTraceConfig();
}

PropagationTags.Factory getPropagationTagsFactory() {
return propagationTagsFactory;
}
Expand Down Expand Up @@ -479,13 +485,13 @@ private CoreTracer(

endpointCheckpointer = EndpointCheckpointerHolder.create();
this.serviceName = serviceName;
this.dynamicConfig = DynamicConfig.create().setServiceMapping(serviceNameMappings).apply();
this.sampler = sampler;
this.injector = injector;
this.extractor = extractor;
this.logs128bTraceIdEnabled = InstrumenterConfig.get().isLogs128bTraceIdEnabled();
this.localRootSpanTags = localRootSpanTags;
this.defaultSpanTags = defaultSpanTags;
this.serviceNameMappings = serviceNameMappings;
this.partialFlushMinSpans = partialFlushMinSpans;
this.idGenerationStrategy =
null == idGenerationStrategy
Expand Down Expand Up @@ -636,11 +642,6 @@ public PendingTrace createTrace(DDTraceId id) {
return pendingTraceFactory.create(id);
}

public String mapServiceName(String serviceName) {
String mapped = serviceNameMappings.get(serviceName);
return null == mapped ? serviceName : mapped;
}

/**
* If an application is using a non-system classloader, that classloader should be registered
* here. Due to the way Spring Boot structures its' executable jar, this might log some warnings.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ public String getServiceName() {
}

public void setServiceName(final String serviceName) {
this.serviceName = trace.getTracer().mapServiceName(serviceName);
this.serviceName = trace.mapServiceName(serviceName);
this.topLevel = isTopLevel(parentServiceName, this.serviceName);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import datadog.communication.monitor.Recording;
import datadog.trace.api.DDTraceId;
import datadog.trace.api.TraceConfig;
import datadog.trace.api.time.TimeSource;
import datadog.trace.bootstrap.instrumentation.api.AgentScope;
import datadog.trace.bootstrap.instrumentation.api.AgentTrace;
Expand Down Expand Up @@ -72,6 +73,8 @@ PendingTrace create(@Nonnull DDTraceId traceId) {
private final TimeSource timeSource;
private final boolean strictTraceWrites;
private final HealthMetrics healthMetrics;
private final TraceConfig traceConfig;

private final ConcurrentLinkedDeque<DDSpan> finishedSpans = new ConcurrentLinkedDeque<>();

// We must maintain a separate count because ConcurrentLinkedDeque.size() is a linear operation.
Expand Down Expand Up @@ -121,12 +124,17 @@ private PendingTrace(
this.timeSource = timeSource;
this.strictTraceWrites = strictTraceWrites;
this.healthMetrics = healthMetrics;
this.traceConfig = tracer.captureTraceConfig();
}

CoreTracer getTracer() {
return tracer;
}

String mapServiceName(String serviceName) {
return traceConfig.getServiceMapping().getOrDefault(serviceName, serviceName);
}

/**
* Current timestamp in nanoseconds; 'touches' the trace by updating {@link #lastReferenced}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,8 @@ class DDAgentWriterCombinedTest extends DDCoreSpecification {

def createMinimalContext() {
def tracer = Mock(CoreTracer)
tracer.mapServiceName(_) >> { String serviceName -> serviceName }
def trace = Mock(PendingTrace)
trace.mapServiceName(_) >> { String serviceName -> serviceName }
trace.getTracer() >> tracer
return new DDSpanContext(
DDTraceId.ONE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@ class DDAgentWriterTest extends DDCoreSpecification {

def newSpan() {
CoreTracer tracer = Mock(CoreTracer)
tracer.mapServiceName(_) >> { String serviceName -> serviceName }
PendingTrace trace = Mock(PendingTrace)
trace.mapServiceName(_) >> { String serviceName -> serviceName }
trace.getTracer() >> tracer
def context = new DDSpanContext(
DDTraceId.ONE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -730,8 +730,8 @@ class DDIntakeWriterCombinedTest extends DDCoreSpecification {

def createMinimalContext() {
def tracer = Mock(CoreTracer)
tracer.mapServiceName(_) >> { String serviceName -> serviceName }
def trace = Mock(PendingTrace)
trace.mapServiceName(_) >> { String serviceName -> serviceName }
trace.getTracer() >> tracer
return new DDSpanContext(
DDTraceId.ONE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ class DDIntakeWriterTest extends DDCoreSpecification{

def newSpan() {
CoreTracer tracer = Mock(CoreTracer)
tracer.mapServiceName(_) >> { String serviceName -> serviceName }
PendingTrace trace = Mock(PendingTrace)
trace.mapServiceName(_) >> { String serviceName -> serviceName }
trace.getTracer() >> tracer
def context = new DDSpanContext(
DDTraceId.ONE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,9 @@ class PayloadDispatcherTest extends DDSpecification {

def realSpan() {
CoreTracer tracer = Mock(CoreTracer)
tracer.mapServiceName(_) >> { String serviceName ->
serviceName
}
PendingTrace trace = Mock(PendingTrace)
trace.getTracer() >> tracer
trace.mapServiceName(_) >> { String serviceName -> serviceName }
def context = new DDSpanContext(
DDTraceId.ONE,
1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ class CoreTracerTest extends DDCoreSpecification {

then:
tracer.defaultSpanTags == map
tracer.serviceNameMappings == map
tracer.captureTraceConfig().serviceMapping == map
taggedHeaders == map

cleanup:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import datadog.communication.monitor.Monitoring
import datadog.trace.SamplingPriorityMetadataChecker
import datadog.trace.api.DDSpanId
import datadog.trace.api.DDTraceId
import datadog.trace.api.TraceConfig
import datadog.trace.api.sampling.PrioritySampling
import datadog.trace.api.time.SystemTimeSource
import datadog.trace.bootstrap.instrumentation.api.AgentTracer.NoopPathwayContext
Expand All @@ -29,10 +30,16 @@ class PendingTraceBufferTest extends DDSpecification {
def bufferSpy = Spy(buffer)

def tracer = Mock(CoreTracer)
def traceConfig = Mock(TraceConfig)
def scopeManager = new ContinuableScopeManager(10, true, true)
def factory = new PendingTrace.Factory(tracer, bufferSpy, SystemTimeSource.INSTANCE, false, HealthMetrics.NO_OP)
List<TraceScope.Continuation> continuations = []

def setup() {
tracer.captureTraceConfig() >> traceConfig
traceConfig.getServiceMapping() >> [:]
}

def cleanup() {
buffer.close()
buffer.worker.join(1000)
Expand Down Expand Up @@ -142,7 +149,7 @@ class PendingTraceBufferTest extends DDSpecification {

then:
_ * tracer.getPartialFlushMinSpans() >> 10
_ * tracer.mapServiceName(_)
_ * traceConfig.getServiceMapping() >> [:]
_ * tracer.getTimeWithNanoTicks(_)
1 * tracer.writeTimer() >> Monitoring.DISABLED.newTimer("")
1 * tracer.write(_) >> { List<List<DDSpan>> spans ->
Expand All @@ -162,10 +169,11 @@ class PendingTraceBufferTest extends DDSpecification {
}

then:
_ * tracer.captureTraceConfig() >> traceConfig
buffer.queue.size() == BUFFER_SIZE
buffer.queue.capacity() * bufferSpy.enqueue(_)
_ * tracer.getPartialFlushMinSpans() >> 10
_ * tracer.mapServiceName(_)
_ * traceConfig.getServiceMapping() >> [:]
_ * tracer.getTimeWithNanoTicks(_)
0 * _

Expand All @@ -174,11 +182,12 @@ class PendingTraceBufferTest extends DDSpecification {
addContinuation(newSpanOf(pendingTrace)).finish()

then:
1 * tracer.captureTraceConfig() >> traceConfig
1 * bufferSpy.enqueue(_)
1 * tracer.writeTimer() >> Monitoring.DISABLED.newTimer("")
1 * tracer.write({ it.size() == 1 })
_ * tracer.getPartialFlushMinSpans() >> 10
_ * tracer.mapServiceName(_)
_ * traceConfig.getServiceMapping() >> [:]
2 * tracer.getTimeWithNanoTicks(_)
0 * _
pendingTrace.isEnqueued == 0
Expand Down Expand Up @@ -273,7 +282,7 @@ class PendingTraceBufferTest extends DDSpecification {
1 * tracer.write({ it.size() == 1 }) >> {
childLatch.countDown()
}
_ * tracer.mapServiceName(_)
_ * traceConfig.getServiceMapping() >> [:]
2 * tracer.getTimeWithNanoTicks(_)
0 * _
}
Expand Down Expand Up @@ -335,13 +344,14 @@ class PendingTraceBufferTest extends DDSpecification {
span.finish()

then:
1 * tracer.captureTraceConfig() >> traceConfig
pendingTrace.rootSpanWritten
pendingTrace.isEnqueued == 0
buffer.queue.size() == 0
1 * tracer.writeTimer() >> Monitoring.DISABLED.newTimer("")
1 * tracer.write({ it.size() == 1 })
1 * tracer.getPartialFlushMinSpans() >> 10000
1 * tracer.mapServiceName(_)
1 * traceConfig.getServiceMapping() >> [:]
2 * tracer.getTimeWithNanoTicks(_)
0 * _

Expand All @@ -355,7 +365,7 @@ class PendingTraceBufferTest extends DDSpecification {
buffer.queue.size() == 1
buffer.queue.capacity() * bufferSpy.enqueue(_)
_ * tracer.getPartialFlushMinSpans() >> 10000
_ * tracer.mapServiceName(_)
_ * traceConfig.getServiceMapping() >> [:]
_ * tracer.getTimeWithNanoTicks(_)
0 * _

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package datadog.trace.core

import datadog.trace.api.DDTraceId
import datadog.trace.api.TraceConfig
import datadog.trace.api.sampling.PrioritySampling
import datadog.trace.api.time.TimeSource
import datadog.trace.bootstrap.instrumentation.api.AgentTracer
Expand Down Expand Up @@ -66,8 +67,11 @@ class PendingTraceTest extends PendingTraceTestBase {
def "verify healthmetrics called"() {
setup:
def tracer = Mock(CoreTracer)
def traceConfig = Mock(TraceConfig)
def buffer = Mock(PendingTraceBuffer)
def healthMetrics = Mock(HealthMetrics)
tracer.captureTraceConfig() >> traceConfig
traceConfig.getServiceMapping() >> [:]
PendingTrace trace = new PendingTrace(tracer,DDTraceId.from(0),buffer,Mock(TimeSource),false,healthMetrics)
when:
rootSpan = createSimpleSpan(trace)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ class TypeConverterTest extends DDSpecification {

def createTestSpanContext() {
def tracer = Mock(CoreTracer)
tracer.mapServiceName(_) >> { String serviceName -> serviceName }
def trace = Mock(PendingTrace)
trace.mapServiceName(_) >> { String serviceName -> serviceName }
trace.getTracer() >> tracer

return new DDSpanContext(
Expand Down
3 changes: 3 additions & 0 deletions internal-api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ excludedClassesCoverage += [
"datadog.trace.api.ConfigCollector.Holder",
"datadog.trace.api.Config.HostNameHolder",
"datadog.trace.api.Config.RuntimeIdHolder",
"datadog.trace.api.DynamicConfig",
"datadog.trace.api.DynamicConfig.Builder",
"datadog.trace.api.DynamicConfig.State",
"datadog.trace.api.InstrumenterConfig",
// can't reliably force same identity hash for different instance to cover branch
"datadog.trace.api.cache.FixedSizeCache.IdentityHash",
Expand Down
62 changes: 62 additions & 0 deletions internal-api/src/main/java/datadog/trace/api/DynamicConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package datadog.trace.api;

import static datadog.trace.util.CollectionUtils.tryMakeImmutableMap;

import java.util.Collections;
import java.util.Map;

/** Manages dynamic configuration for a particular {@link Tracer} instance. */
public final class DynamicConfig {
private volatile State currentState;

private DynamicConfig() {}

public static Builder create() {
return new DynamicConfig().prepare();
}

/** Captures a snapshot of the configuration at the start of a trace. */
public TraceConfig captureTraceConfig() {
return currentState;
}

public Builder prepare() {
return new Builder(currentState);
}

public final class Builder {
Map<String, String> serviceMapping;

Builder(State state) {
if (null == state) {
this.serviceMapping = Collections.emptyMap();
} else {
this.serviceMapping = state.serviceMapping;
}
}

public Builder setServiceMapping(Map<String, String> serviceMapping) {
this.serviceMapping = tryMakeImmutableMap(serviceMapping);
return this;
}

/** Overwrites the current configuration with a new snapshot. */
public DynamicConfig apply() {
DynamicConfig.this.currentState = new State(this);
return DynamicConfig.this;
}
}

/** Immutable snapshot of the configuration. */
static final class State implements TraceConfig {
final Map<String, String> serviceMapping;

State(Builder builder) {
this.serviceMapping = builder.serviceMapping;
}

public Map<String, String> getServiceMapping() {
return serviceMapping;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package datadog.trace.api;

import java.util.Map;

/** Snapshot of dynamic configuration; valid for the duration of a trace. */
public interface TraceConfig {

Map<String, String> getServiceMapping();
Comment thread
mcculls marked this conversation as resolved.
}