Merge pull request #719 from DataDog/tyler/trace-analytics-config

Trace Analytics Config
This commit is contained in:
Tyler Benson 2019-02-20 11:13:19 -08:00 committed by GitHub
commit 875d491638
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 85 additions and 15 deletions

View File

@ -10,6 +10,8 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.datadog.jmxfetch.App; import org.datadog.jmxfetch.App;
@ -116,9 +118,11 @@ public class JMXFetch {
final String configs = IOUtils.toString(metricConfigsStream, StandardCharsets.UTF_8); final String configs = IOUtils.toString(metricConfigsStream, StandardCharsets.UTF_8);
final String[] split = configs.split("\n"); final String[] split = configs.split("\n");
final List<String> result = new ArrayList<>(split.length); final List<String> result = new ArrayList<>(split.length);
final SortedSet<String> integrationName = new TreeSet<>();
for (final String config : split) { for (final String config : split) {
if (Config.integrationEnabled( integrationName.clear();
Collections.singleton(config.replace(".yaml", "")), false)) { integrationName.add(config.replace(".yaml", ""));
if (Config.integrationEnabled(integrationName, false)) {
final URL resource = JMXFetch.class.getResource("metricconfigs/" + config); final URL resource = JMXFetch.class.getResource("metricconfigs/" + config);
result.add(resource.getPath().split("\\.jar!/")[1]); result.add(resource.getPath().split("\\.jar!/")[1]);
} }

View File

@ -11,10 +11,10 @@ import datadog.trace.api.Config;
import java.security.ProtectionDomain; import java.security.ProtectionDomain;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.SortedSet;
import java.util.TreeSet;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.agent.builder.AgentBuilder; import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
@ -39,7 +39,7 @@ public interface Instrumenter {
@Slf4j @Slf4j
abstract class Default implements Instrumenter { abstract class Default implements Instrumenter {
private final Set<String> instrumentationNames; private final SortedSet<String> instrumentationNames;
private final String instrumentationPrimaryName; private final String instrumentationPrimaryName;
private final InstrumentationContextProvider contextProvider; private final InstrumentationContextProvider contextProvider;
protected final boolean enabled; protected final boolean enabled;
@ -48,7 +48,7 @@ public interface Instrumenter {
getClass().getPackage() == null ? "" : getClass().getPackage().getName(); getClass().getPackage() == null ? "" : getClass().getPackage().getName();
public Default(final String instrumentationName, final String... additionalNames) { public Default(final String instrumentationName, final String... additionalNames) {
instrumentationNames = new HashSet<>(Arrays.asList(additionalNames)); instrumentationNames = new TreeSet<>(Arrays.asList(additionalNames));
instrumentationNames.add(instrumentationName); instrumentationNames.add(instrumentationName);
instrumentationPrimaryName = instrumentationName; instrumentationPrimaryName = instrumentationName;

View File

@ -6,7 +6,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.SortedSet;
import java.util.UUID; import java.util.UUID;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import lombok.Getter; import lombok.Getter;
@ -44,6 +44,7 @@ public class Config {
public static final String GLOBAL_TAGS = "trace.global.tags"; public static final String GLOBAL_TAGS = "trace.global.tags";
public static final String SPAN_TAGS = "trace.span.tags"; public static final String SPAN_TAGS = "trace.span.tags";
public static final String JMX_TAGS = "trace.jmx.tags"; public static final String JMX_TAGS = "trace.jmx.tags";
public static final String TRACE_ANALYTICS_ENABLED = "trace.analytics.enabled";
public static final String TRACE_ANNOTATIONS = "trace.annotations"; public static final String TRACE_ANNOTATIONS = "trace.annotations";
public static final String TRACE_METHODS = "trace.methods"; public static final String TRACE_METHODS = "trace.methods";
public static final String HEADER_TAGS = "trace.header.tags"; public static final String HEADER_TAGS = "trace.header.tags";
@ -260,7 +261,7 @@ public class Config {
} }
public static boolean integrationEnabled( public static boolean integrationEnabled(
final Set<String> integrationNames, final boolean defaultEnabled) { final SortedSet<String> integrationNames, final boolean defaultEnabled) {
// If default is enabled, we want to enable individually, // If default is enabled, we want to enable individually,
// if default is disabled, we want to disable individually. // if default is disabled, we want to disable individually.
boolean anyEnabled = defaultEnabled; boolean anyEnabled = defaultEnabled;
@ -276,6 +277,24 @@ public class Config {
return anyEnabled; return anyEnabled;
} }
public static boolean traceAnalyticsIntegrationEnabled(
final SortedSet<String> integrationNames, final boolean defaultEnabled) {
// If default is enabled, we want to enable individually,
// if default is disabled, we want to disable individually.
boolean anyEnabled = defaultEnabled;
for (final String name : integrationNames) {
final boolean configEnabled =
getBooleanSettingFromEnvironment(
"integration." + name + ".analytics.enabled", defaultEnabled);
if (defaultEnabled) {
anyEnabled &= configEnabled;
} else {
anyEnabled |= configEnabled;
}
}
return anyEnabled;
}
/** /**
* Helper method that takes the name, adds a "dd." prefix then checks for System Properties of * Helper method that takes the name, adds a "dd." prefix then checks for System Properties of
* that name. If none found, the name is converted to an Environment Variable and used to check * that name. If none found, the name is converted to an Environment Variable and used to check
@ -316,6 +335,18 @@ public class Config {
return value == null ? defaultValue : Boolean.valueOf(value); return value == null ? defaultValue : Boolean.valueOf(value);
} }
/**
* Calls {@link #getSettingFromEnvironment(String, String)} and converts the result to a Float.
*
* @param name
* @param defaultValue
* @return
*/
public static Float getFloatSettingFromEnvironment(final String name, final Float defaultValue) {
final String value = getSettingFromEnvironment(name, null);
return value == null ? defaultValue : Float.valueOf(value);
}
private static Integer getIntegerSettingFromEnvironment( private static Integer getIntegerSettingFromEnvironment(
final String name, final Integer defaultValue) { final String name, final Integer defaultValue) {
final String value = getSettingFromEnvironment(name, null); final String value = getSettingFromEnvironment(name, null);

View File

@ -14,5 +14,6 @@ public class DDTags {
public static final String ERROR_TYPE = "error.type"; // string representing the type of the error public static final String ERROR_TYPE = "error.type"; // string representing the type of the error
public static final String ERROR_STACK = "error.stack"; // human readable version of the stack public static final String ERROR_STACK = "error.stack"; // human readable version of the stack
public static final String EVENT_SAMPLE_RATE = "_dd1.sr.eausr"; public static final String ANALYTICS_SAMPLE_RATE = "_dd1.sr.eausr";
@Deprecated public static final String EVENT_SAMPLE_RATE = ANALYTICS_SAMPLE_RATE;
} }

View File

@ -312,7 +312,41 @@ class ConfigTest extends Specification {
["test-prop", "disabled-prop"] | true | false ["test-prop", "disabled-prop"] | true | false
["disabled-env", "test-env"] | true | false ["disabled-env", "test-env"] | true | false
integrationNames = names.toSet() integrationNames = new TreeSet<>(names)
}
def "verify integration trace analytics config"() {
setup:
environmentVariables.set("DD_INTEGRATION_ORDER_ANALYTICS_ENABLED", "false")
environmentVariables.set("DD_INTEGRATION_TEST_ENV_ANALYTICS_ENABLED", "true")
environmentVariables.set("DD_INTEGRATION_DISABLED_ENV_ANALYTICS_ENABLED", "false")
System.setProperty("dd.integration.order.analytics.enabled", "true")
System.setProperty("dd.integration.test-prop.analytics.enabled", "true")
System.setProperty("dd.integration.disabled-prop.analytics.enabled", "false")
expect:
Config.traceAnalyticsIntegrationEnabled(integrationNames, defaultEnabled) == expected
where:
names | defaultEnabled | expected
[] | true | true
[] | false | false
["invalid"] | true | true
["invalid"] | false | false
["test-prop"] | false | true
["test-env"] | false | true
["disabled-prop"] | true | false
["disabled-env"] | true | false
["other", "test-prop"] | false | true
["other", "test-env"] | false | true
["order"] | false | true
["test-prop", "disabled-prop"] | false | true
["disabled-env", "test-env"] | false | true
["test-prop", "disabled-prop"] | true | false
["disabled-env", "test-env"] | true | false
integrationNames = new TreeSet<>(names)
} }
def "verify mapping configs on tracer"() { def "verify mapping configs on tracer"() {

View File

@ -3,16 +3,16 @@ package datadog.opentracing.decorators;
import datadog.opentracing.DDSpanContext; import datadog.opentracing.DDSpanContext;
import datadog.trace.api.DDTags; import datadog.trace.api.DDTags;
public class EventSampleRateDecorator extends AbstractDecorator { public class AnalyticsSampleRateDecorator extends AbstractDecorator {
public EventSampleRateDecorator() { public AnalyticsSampleRateDecorator() {
super(); super();
setMatchingTag(DDTags.EVENT_SAMPLE_RATE); setMatchingTag(DDTags.ANALYTICS_SAMPLE_RATE);
} }
@Override @Override
public boolean shouldSetTag(final DDSpanContext context, final String tag, final Object value) { public boolean shouldSetTag(final DDSpanContext context, final String tag, final Object value) {
if (value instanceof Number) { if (value instanceof Number) {
context.setMetric(DDTags.EVENT_SAMPLE_RATE, (Number) value); context.setMetric(DDTags.ANALYTICS_SAMPLE_RATE, (Number) value);
} }
return false; return false;
} }

View File

@ -11,7 +11,7 @@ public class DDDecoratorsFactory {
new DBStatementAsResourceName(), new DBStatementAsResourceName(),
new DBTypeDecorator(), new DBTypeDecorator(),
new ErrorFlag(), new ErrorFlag(),
new EventSampleRateDecorator(), new AnalyticsSampleRateDecorator(),
new OperationDecorator(), new OperationDecorator(),
new PeerServiceDecorator(), new PeerServiceDecorator(),
new ResourceNameDecorator(), new ResourceNameDecorator(),