Merge pull request #975 from DataDog/tyler/split-by-tag

Add new setting to allow renaming service by tag
This commit is contained in:
Tyler Benson 2019-09-05 14:24:20 -07:00 committed by GitHub
commit df017e044a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 150 additions and 50 deletions

View File

@ -33,6 +33,7 @@ public abstract class DatabaseClientDecorator<CONNECTION> extends ClientDecorato
Tags.DB_USER.set(span, dbUser(connection));
final String instanceName = dbInstance(connection);
Tags.DB_INSTANCE.set(span, instanceName);
if (instanceName != null && Config.get().isDbClientSplitByInstance()) {
span.setTag(DDTags.SERVICE_NAME, instanceName);
}

View File

@ -8,6 +8,7 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@ -71,6 +72,7 @@ public class Config {
public static final String HTTP_CLIENT_TAG_QUERY_STRING = "http.client.tag.query-string";
public static final String HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN = "trace.http.client.split-by-domain";
public static final String DB_CLIENT_HOST_SPLIT_BY_INSTANCE = "trace.db.client.split-by-instance";
public static final String SPLIT_BY_TAGS = "trace.split-by-tags";
public static final String PARTIAL_FLUSH_MIN_SPANS = "trace.partial.flush.min.spans";
public static final String RUNTIME_CONTEXT_FIELD_INJECTION =
"trace.runtime.context.field.injection";
@ -116,6 +118,7 @@ public class Config {
private static final boolean DEFAULT_HTTP_CLIENT_TAG_QUERY_STRING = false;
private static final boolean DEFAULT_HTTP_CLIENT_SPLIT_BY_DOMAIN = false;
private static final boolean DEFAULT_DB_CLIENT_HOST_SPLIT_BY_INSTANCE = false;
private static final String DEFAULT_SPLIT_BY_TAGS = "";
private static final int DEFAULT_PARTIAL_FLUSH_MIN_SPANS = 1000;
private static final String DEFAULT_PROPAGATION_STYLE_EXTRACT = PropagationStyle.DATADOG.name();
private static final String DEFAULT_PROPAGATION_STYLE_INJECT = PropagationStyle.DATADOG.name();
@ -171,6 +174,7 @@ public class Config {
@Getter private final boolean httpClientTagQueryString;
@Getter private final boolean httpClientSplitByDomain;
@Getter private final boolean dbClientSplitByInstance;
@Getter private final Set<String> splitByTags;
@Getter private final Integer partialFlushMinSpans;
@Getter private final boolean runtimeContextFieldInjection;
@Getter private final Set<PropagationStyle> propagationStylesToExtract;
@ -258,6 +262,11 @@ public class Config {
getBooleanSettingFromEnvironment(
DB_CLIENT_HOST_SPLIT_BY_INSTANCE, DEFAULT_DB_CLIENT_HOST_SPLIT_BY_INSTANCE);
splitByTags =
Collections.unmodifiableSet(
new LinkedHashSet<>(
getListSettingFromEnvironment(SPLIT_BY_TAGS, DEFAULT_SPLIT_BY_TAGS)));
partialFlushMinSpans =
getIntegerSettingFromEnvironment(PARTIAL_FLUSH_MIN_SPANS, DEFAULT_PARTIAL_FLUSH_MIN_SPANS);
@ -366,6 +375,12 @@ public class Config {
getPropertyBooleanValue(
properties, DB_CLIENT_HOST_SPLIT_BY_INSTANCE, parent.dbClientSplitByInstance);
splitByTags =
Collections.unmodifiableSet(
new LinkedHashSet<>(
getPropertyListValue(
properties, SPLIT_BY_TAGS, new ArrayList<>(parent.splitByTags))));
partialFlushMinSpans =
getPropertyIntegerValue(properties, PARTIAL_FLUSH_MIN_SPANS, parent.partialFlushMinSpans);
@ -850,6 +865,10 @@ public class Config {
}
final String[] tokens = str.split(",", -1);
// Remove whitespace from each item.
for (int i = 0; i < tokens.length; i++) {
tokens[i] = tokens[i].trim();
}
return Collections.unmodifiableList(Arrays.asList(tokens));
}

View File

@ -34,6 +34,7 @@ import static datadog.trace.api.Config.SERVICE
import static datadog.trace.api.Config.SERVICE_MAPPING
import static datadog.trace.api.Config.SERVICE_NAME
import static datadog.trace.api.Config.SPAN_TAGS
import static datadog.trace.api.Config.SPLIT_BY_TAGS
import static datadog.trace.api.Config.TRACE_AGENT_PORT
import static datadog.trace.api.Config.TRACE_ENABLED
import static datadog.trace.api.Config.TRACE_REPORT_HOSTNAME
@ -80,6 +81,7 @@ class ConfigTest extends Specification {
config.httpClientErrorStatuses == (400..499).toSet()
config.httpClientSplitByDomain == false
config.dbClientSplitByInstance == false
config.splitByTags == [].toSet()
config.partialFlushMinSpans == 1000
config.reportHostName == false
config.runtimeContextFieldInjection == true
@ -122,6 +124,7 @@ class ConfigTest extends Specification {
prop.setProperty(HTTP_CLIENT_ERROR_STATUSES, "111")
prop.setProperty(HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN, "true")
prop.setProperty(DB_CLIENT_HOST_SPLIT_BY_INSTANCE, "true")
prop.setProperty(SPLIT_BY_TAGS, "some.tag1,some.tag2,some.tag1")
prop.setProperty(PARTIAL_FLUSH_MIN_SPANS, "15")
prop.setProperty(TRACE_REPORT_HOSTNAME, "true")
prop.setProperty(RUNTIME_CONTEXT_FIELD_INJECTION, "false")
@ -154,6 +157,7 @@ class ConfigTest extends Specification {
config.httpClientErrorStatuses == (111..111).toSet()
config.httpClientSplitByDomain == true
config.dbClientSplitByInstance == true
config.splitByTags == ["some.tag1", "some.tag2"].toSet()
config.partialFlushMinSpans == 15
config.reportHostName == true
config.runtimeContextFieldInjection == false
@ -187,6 +191,7 @@ class ConfigTest extends Specification {
System.setProperty(PREFIX + HTTP_CLIENT_ERROR_STATUSES, "111")
System.setProperty(PREFIX + HTTP_CLIENT_HOST_SPLIT_BY_DOMAIN, "true")
System.setProperty(PREFIX + DB_CLIENT_HOST_SPLIT_BY_INSTANCE, "true")
System.setProperty(PREFIX + SPLIT_BY_TAGS, "some.tag3, some.tag2, some.tag1")
System.setProperty(PREFIX + PARTIAL_FLUSH_MIN_SPANS, "25")
System.setProperty(PREFIX + TRACE_REPORT_HOSTNAME, "true")
System.setProperty(PREFIX + RUNTIME_CONTEXT_FIELD_INJECTION, "false")
@ -219,6 +224,7 @@ class ConfigTest extends Specification {
config.httpClientErrorStatuses == (111..111).toSet()
config.httpClientSplitByDomain == true
config.dbClientSplitByInstance == true
config.splitByTags == ["some.tag3", "some.tag2", "some.tag1"].toSet()
config.partialFlushMinSpans == 25
config.reportHostName == true
config.runtimeContextFieldInjection == false
@ -314,6 +320,7 @@ class ConfigTest extends Specification {
config.httpClientErrorStatuses == (400..499).toSet()
config.httpClientSplitByDomain == false
config.dbClientSplitByInstance == false
config.splitByTags == [].toSet()
config.propagationStylesToExtract.toList() == [Config.PropagationStyle.DATADOG]
config.propagationStylesToInject.toList() == [Config.PropagationStyle.DATADOG]
}
@ -409,6 +416,7 @@ class ConfigTest extends Specification {
config.httpClientErrorStatuses == (111..111).toSet()
config.httpClientSplitByDomain == true
config.dbClientSplitByInstance == true
config.splitByTags == [].toSet()
config.partialFlushMinSpans == 15
config.propagationStylesToExtract.toList() == [Config.PropagationStyle.B3, Config.PropagationStyle.DATADOG]
config.propagationStylesToInject.toList() == [Config.PropagationStyle.DATADOG, Config.PropagationStyle.B3]

View File

@ -1,5 +1,7 @@
package datadog.opentracing.decorators;
import datadog.trace.api.Config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -7,22 +9,30 @@ import java.util.List;
public class DDDecoratorsFactory {
public static List<AbstractDecorator> createBuiltinDecorators() {
return Arrays.asList(
new AnalyticsSampleRateDecorator(),
new DBStatementAsResourceName(),
new DBTypeDecorator(),
new ErrorFlag(),
new ForceManualDropDecorator(),
new ForceManualKeepDecorator(),
new OperationDecorator(),
new PeerServiceDecorator(),
new ResourceNameDecorator(),
new ServiceDecorator(),
new ServiceNameDecorator(),
new ServletContextDecorator(),
new SpanTypeDecorator(),
new Status404Decorator(),
new Status5XXDecorator(),
new URLAsResourceName());
final List<AbstractDecorator> decorators =
new ArrayList<>(
Arrays.asList(
new AnalyticsSampleRateDecorator(),
new DBStatementAsResourceName(),
new DBTypeDecorator(),
new ErrorFlag(),
new ForceManualDropDecorator(),
new ForceManualKeepDecorator(),
new OperationDecorator(),
new PeerServiceDecorator(),
new ResourceNameDecorator(),
new ServiceNameDecorator(),
new ServiceNameDecorator("service", false),
new ServletContextDecorator(),
new SpanTypeDecorator(),
new Status404Decorator(),
new Status5XXDecorator(),
new URLAsResourceName()));
for (final String splitByTag : Config.get().getSplitByTags()) {
decorators.add(new ServiceNameDecorator(splitByTag, true));
}
return decorators;
}
}

View File

@ -1,17 +0,0 @@
package datadog.opentracing.decorators;
import datadog.opentracing.DDSpanContext;
public class ServiceDecorator extends AbstractDecorator {
public ServiceDecorator() {
super();
this.setMatchingTag("service"); // will be added to a future OT version.
}
@Override
public boolean shouldSetTag(final DDSpanContext context, final String tag, final Object value) {
context.setServiceName(String.valueOf(value));
return false;
}
}

View File

@ -5,14 +5,21 @@ import datadog.trace.api.DDTags;
public class ServiceNameDecorator extends AbstractDecorator {
private final boolean setTag;
public ServiceNameDecorator() {
this(DDTags.SERVICE_NAME, false);
}
public ServiceNameDecorator(final String splitByTag, final boolean setTag) {
super();
this.setMatchingTag(DDTags.SERVICE_NAME);
this.setTag = setTag;
setMatchingTag(splitByTag);
}
@Override
public boolean shouldSetTag(final DDSpanContext context, final String tag, final Object value) {
context.setServiceName(String.valueOf(value));
return false;
return setTag;
}
}

View File

@ -2,6 +2,7 @@ package datadog.opentracing
import datadog.opentracing.propagation.ExtractedContext
import datadog.opentracing.propagation.TagContext
import datadog.trace.agent.test.utils.ConfigUtils
import datadog.trace.api.Config
import datadog.trace.api.DDTags
import datadog.trace.api.sampling.PrioritySampling
@ -16,6 +17,10 @@ import static org.mockito.Mockito.mock
import static org.mockito.Mockito.when
class DDSpanBuilderTest extends Specification {
static {
ConfigUtils.makeConfigInstanceModifiable()
}
def writer = new ListWriter()
def config = Config.get()
def tracer = new DDTracer(writer)

View File

@ -3,6 +3,7 @@ package datadog.opentracing
import com.fasterxml.jackson.databind.ObjectMapper
import com.google.common.collect.Maps
import datadog.trace.agent.test.utils.ConfigUtils
import datadog.trace.api.DDTags
import datadog.trace.api.sampling.PrioritySampling
import datadog.trace.common.writer.ListWriter
@ -13,6 +14,9 @@ import org.msgpack.value.ValueType
import spock.lang.Specification
class DDSpanSerializationTest extends Specification {
static {
ConfigUtils.makeConfigInstanceModifiable()
}
def "serialize spans with sampling #samplingPriority"() throws Exception {
setup:

View File

@ -2,6 +2,7 @@ package datadog.opentracing
import datadog.opentracing.propagation.ExtractedContext
import datadog.opentracing.propagation.TagContext
import datadog.trace.agent.test.utils.ConfigUtils
import datadog.trace.api.sampling.PrioritySampling
import datadog.trace.common.sampling.RateByServiceSampler
import datadog.trace.common.writer.ListWriter
@ -14,6 +15,10 @@ import java.util.concurrent.TimeUnit
import static datadog.trace.api.Config.DEFAULT_SERVICE_NAME
class DDSpanTest extends Specification {
static {
ConfigUtils.makeConfigInstanceModifiable()
}
def writer = new ListWriter()
def tracer = new DDTracer(DEFAULT_SERVICE_NAME, writer, new RateByServiceSampler(), [:])
@ -210,7 +215,7 @@ class DDSpanTest extends Specification {
def "isRootSpan() in and not in the context of distributed tracing"() {
setup:
def root = tracer.buildSpan("root").asChildOf((SpanContext)extractedContext).start()
def root = tracer.buildSpan("root").asChildOf((SpanContext) extractedContext).start()
def child = tracer.buildSpan("child").asChildOf(root).start()
expect:
@ -222,14 +227,14 @@ class DDSpanTest extends Specification {
root.finish()
where:
extractedContext | isTraceRootSpan
null | true
extractedContext | isTraceRootSpan
null | true
new ExtractedContext("123", "456", 1, "789", [:], [:]) | false
}
def "getApplicationRootSpan() in and not in the context of distributed tracing"() {
setup:
def root = tracer.buildSpan("root").asChildOf((SpanContext)extractedContext).start()
def root = tracer.buildSpan("root").asChildOf((SpanContext) extractedContext).start()
def child = tracer.buildSpan("child").asChildOf(root).start()
expect:
@ -244,8 +249,8 @@ class DDSpanTest extends Specification {
root.finish()
where:
extractedContext | isTraceRootSpan
null | true
extractedContext | isTraceRootSpan
null | true
new ExtractedContext("123", "456", 1, "789", [:], [:]) | false
}
@ -264,9 +269,9 @@ class DDSpanTest extends Specification {
span.finish()
where:
tagName | tagValue | expectedPriority
'manual.drop' | true | PrioritySampling.USER_DROP
'manual.keep' | true | PrioritySampling.USER_KEEP
tagName | tagValue | expectedPriority
'manual.drop' | true | PrioritySampling.USER_DROP
'manual.keep' | true | PrioritySampling.USER_KEEP
}
def "not setting forced tracing via tag or setting it wrong value not causing exception"() {
@ -284,9 +289,9 @@ class DDSpanTest extends Specification {
span.finish()
where:
tagName | tagValue
tagName | tagValue
// When no tag is set default to
null | null
null | null
// Setting to not known value
'manual.drop' | false
'manual.keep' | false

View File

@ -1,5 +1,6 @@
package datadog.opentracing
import datadog.trace.agent.test.utils.ConfigUtils
import datadog.trace.api.Config
import datadog.trace.common.writer.ListWriter
import datadog.trace.util.gc.GCUtils
@ -14,6 +15,10 @@ import java.util.concurrent.atomic.AtomicInteger
import static datadog.trace.api.Config.PARTIAL_FLUSH_MIN_SPANS
class PendingTraceTest extends Specification {
static {
ConfigUtils.makeConfigInstanceModifiable()
}
def traceCount = new AtomicInteger()
def writer = new ListWriter() {
@Override

View File

@ -1,9 +1,14 @@
package datadog.opentracing
import datadog.trace.agent.test.utils.ConfigUtils
import datadog.trace.api.sampling.PrioritySampling
import datadog.trace.common.writer.ListWriter
class SpanFactory {
static {
ConfigUtils.makeConfigInstanceModifiable()
}
static newSpanOf(long timestampMicro, String threadName = Thread.currentThread().name) {
def writer = new ListWriter()
def tracer = new DDTracer(writer)

View File

@ -1,10 +1,14 @@
package datadog.opentracing
import datadog.trace.agent.test.utils.ConfigUtils
import datadog.trace.common.writer.ListWriter
import spock.lang.Shared
import spock.lang.Specification
class TraceCorrelationTest extends Specification {
static {
ConfigUtils.makeConfigInstanceModifiable()
}
static final WRITER = new ListWriter()

View File

@ -1,5 +1,6 @@
package datadog.opentracing
import datadog.trace.agent.test.utils.ConfigUtils
import datadog.trace.api.GlobalTracer
import datadog.trace.api.interceptor.MutableSpan
import datadog.trace.api.interceptor.TraceInterceptor
@ -9,6 +10,10 @@ import spock.lang.Specification
import java.util.concurrent.atomic.AtomicBoolean
class TraceInterceptorTest extends Specification {
static {
ConfigUtils.makeConfigInstanceModifiable()
}
def writer = new ListWriter()
def tracer = new DDTracer(writer)

View File

@ -3,6 +3,8 @@ package datadog.opentracing.decorators
import datadog.opentracing.DDSpanContext
import datadog.opentracing.DDTracer
import datadog.opentracing.SpanFactory
import datadog.trace.agent.test.utils.ConfigUtils
import datadog.trace.api.Config
import datadog.trace.api.DDSpanTypes
import datadog.trace.api.DDTags
import datadog.trace.common.sampling.AllSampler
@ -16,14 +18,23 @@ import static datadog.trace.api.DDTags.EVENT_SAMPLE_RATE
import static java.util.Collections.emptyMap
class SpanDecoratorTest extends Specification {
static {
ConfigUtils.updateConfig {
System.setProperty("dd.$Config.SPLIT_BY_TAGS", "sn.tag1,sn.tag2")
}
}
def cleanupSpec() {
ConfigUtils.updateConfig {
System.clearProperty("dd.$Config.SPLIT_BY_TAGS")
}
}
def tracer = new DDTracer(new LoggingWriter())
def span = SpanFactory.newSpanOf(tracer)
def "adding span personalisation using Decorators"() {
setup:
def decorator = new AbstractDecorator() {
@Override
boolean shouldSetTag(DDSpanContext context, String tag, Object value) {
return super.shouldSetTag(context, tag, value)
}
@ -69,6 +80,10 @@ class SpanDecoratorTest extends Specification {
"service" | "other-service" | "other-service"
Tags.PEER_SERVICE.key | "some-service" | "new-service"
Tags.PEER_SERVICE.key | "other-service" | "other-service"
"sn.tag1" | "some-service" | "new-service"
"sn.tag1" | "other-service" | "other-service"
"sn.tag2" | "some-service" | "new-service"
"sn.tag2" | "other-service" | "other-service"
mapping = ["some-service": "new-service"]
}
@ -310,7 +325,13 @@ class SpanDecoratorTest extends Specification {
def "decorators apply to builder too"() {
when:
def span = tracer.buildSpan("decorator.test").withTag("servlet.context", "/my-servlet").start()
def span = tracer.buildSpan("decorator.test").withTag("sn.tag1", "some val").start()
then:
span.serviceName == "some val"
when:
span = tracer.buildSpan("decorator.test").withTag("servlet.context", "/my-servlet").start()
then:
span.serviceName == "my-servlet"

View File

@ -3,6 +3,7 @@ package datadog.opentracing.decorators
import datadog.opentracing.DDSpanContext
import datadog.opentracing.DDTracer
import datadog.opentracing.PendingTrace
import datadog.trace.agent.test.utils.ConfigUtils
import datadog.trace.api.sampling.PrioritySampling
import datadog.trace.common.writer.ListWriter
import io.opentracing.tag.Tags
@ -10,6 +11,10 @@ import spock.lang.Specification
import spock.lang.Subject
class URLAsResourceNameTest extends Specification {
static {
ConfigUtils.makeConfigInstanceModifiable()
}
def writer = new ListWriter()
def tracer = new DDTracer(writer)

View File

@ -1,11 +1,15 @@
package datadog.opentracing.resolver
import datadog.opentracing.DDTracer
import datadog.trace.agent.test.utils.ConfigUtils
import datadog.trace.api.Config
import io.opentracing.contrib.tracerresolver.TracerResolver
import spock.lang.Specification
class DDTracerResolverTest extends Specification {
static {
ConfigUtils.makeConfigInstanceModifiable()
}
def resolver = new DDTracerResolver()

View File

@ -3,6 +3,7 @@ package datadog.opentracing.scopemanager
import datadog.opentracing.DDSpan
import datadog.opentracing.DDSpanContext
import datadog.opentracing.DDTracer
import datadog.trace.agent.test.utils.ConfigUtils
import datadog.trace.common.writer.ListWriter
import datadog.trace.context.ScopeListener
import datadog.trace.util.gc.GCUtils
@ -22,6 +23,9 @@ import java.util.concurrent.atomic.AtomicReference
import static java.util.concurrent.TimeUnit.SECONDS
class ScopeManagerTest extends Specification {
static {
ConfigUtils.makeConfigInstanceModifiable()
}
def latch
def writer
def tracer

View File

@ -2,6 +2,7 @@ package datadog.trace
import datadog.opentracing.DDTracer
import datadog.opentracing.propagation.HttpCodec
import datadog.trace.agent.test.utils.ConfigUtils
import datadog.trace.api.Config
import datadog.trace.common.sampling.AllSampler
import datadog.trace.common.sampling.RateByServiceSampler
@ -22,6 +23,10 @@ import static datadog.trace.api.Config.SPAN_TAGS
import static datadog.trace.api.Config.WRITER_TYPE
class DDTracerTest extends Specification {
static {
ConfigUtils.makeConfigInstanceModifiable()
}
@Rule
public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties()
@Rule