DD_SERVICE; DD_ENV; DD_VERSION env vars support (#1341)

DD_SERVICE; DD_ENV; DD_VERSION env vars support

* Config.valueOf("", null, "") with throw NPE

* mark unused public fields @Deprecated in Config.java

* keep unused public fields untouched

* retrun 2arg Config ctor
This commit is contained in:
Lev Priima 2020-04-10 10:50:11 -07:00 committed by GitHub
parent 02555e5fcc
commit 7f146d74dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 255 additions and 86 deletions

View File

@ -6,6 +6,8 @@ import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
@ -25,6 +27,7 @@ import java.util.SortedSet;
import java.util.UUID;
import java.util.regex.Pattern;
import lombok.Getter;
import lombok.NonNull;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
@ -64,12 +67,13 @@ public class Config {
public static final String TRACE_RESOLVER_ENABLED = "trace.resolver.enabled";
public static final String SERVICE_MAPPING = "service.mapping";
private static final String ENV = "env";
private static final String VERSION = "version";
public static final String TAGS = "tags";
@Deprecated // Use dd.tags instead
public static final String GLOBAL_TAGS = "trace.global.tags";
public static final String SPAN_TAGS = "trace.span.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_EXECUTORS_ALL = "trace.executors.all";
@ -139,7 +143,8 @@ public class Config {
public static final String PROFILING_PROXY_PASSWORD = "profiling.proxy.password";
public static final String RUNTIME_ID_TAG = "runtime-id";
public static final String SERVICE_TAG = "service";
public static final String SERVICE = "service";
public static final String SERVICE_TAG = SERVICE;
public static final String HOST_TAG = "host";
public static final String LANGUAGE_TAG_KEY = "language";
public static final String LANGUAGE_TAG_VALUE = "jvm";
@ -338,7 +343,9 @@ public class Config {
}
}
site = getSettingFromEnvironment(SITE, DEFAULT_SITE);
serviceName = getSettingFromEnvironment(SERVICE_NAME, DEFAULT_SERVICE_NAME);
serviceName =
getSettingFromEnvironment(
SERVICE_NAME, getSettingFromEnvironment(SERVICE, DEFAULT_SERVICE_NAME));
traceEnabled = getBooleanSettingFromEnvironment(TRACE_ENABLED, DEFAULT_TRACE_ENABLED);
integrationsEnabled =
@ -357,7 +364,10 @@ public class Config {
getBooleanSettingFromEnvironment(TRACE_RESOLVER_ENABLED, DEFAULT_TRACE_RESOLVER_ENABLED);
serviceMapping = getMapSettingFromEnvironment(SERVICE_MAPPING, null);
tags = getMapSettingFromEnvironment(TAGS, null);
final Map<String, String> tagsPreMap = new HashMap<>(getMapSettingFromEnvironment(TAGS, null));
addPropToMapIfDefinedByEnvironment(tagsPreMap, ENV);
addPropToMapIfDefinedByEnvironment(tagsPreMap, VERSION);
tags = Collections.unmodifiableMap(tagsPreMap);
globalTags = getMapSettingFromEnvironment(GLOBAL_TAGS, null);
spanTags = getMapSettingFromEnvironment(SPAN_TAGS, null);
jmxTags = getMapSettingFromEnvironment(JMX_TAGS, null);
@ -405,17 +415,11 @@ public class Config {
RUNTIME_CONTEXT_FIELD_INJECTION, DEFAULT_RUNTIME_CONTEXT_FIELD_INJECTION);
propagationStylesToExtract =
getEnumSetSettingFromEnvironment(
PROPAGATION_STYLE_EXTRACT,
DEFAULT_PROPAGATION_STYLE_EXTRACT,
PropagationStyle.class,
true);
getPropagationStyleSetSettingFromEnvironmentOrDefault(
PROPAGATION_STYLE_EXTRACT, DEFAULT_PROPAGATION_STYLE_EXTRACT);
propagationStylesToInject =
getEnumSetSettingFromEnvironment(
PROPAGATION_STYLE_INJECT,
DEFAULT_PROPAGATION_STYLE_INJECT,
PropagationStyle.class,
true);
getPropagationStyleSetSettingFromEnvironmentOrDefault(
PROPAGATION_STYLE_INJECT, DEFAULT_PROPAGATION_STYLE_INJECT);
jmxFetchEnabled =
getBooleanSettingFromEnvironment(JMX_FETCH_ENABLED, DEFAULT_JMX_FETCH_ENABLED);
@ -597,13 +601,13 @@ public class Config {
properties, RUNTIME_CONTEXT_FIELD_INJECTION, parent.runtimeContextFieldInjection);
final Set<PropagationStyle> parsedPropagationStylesToExtract =
getPropertySetValue(properties, PROPAGATION_STYLE_EXTRACT, PropagationStyle.class);
getPropagationStyleSetFromPropertyValue(properties, PROPAGATION_STYLE_EXTRACT);
propagationStylesToExtract =
parsedPropagationStylesToExtract == null
? parent.propagationStylesToExtract
: parsedPropagationStylesToExtract;
final Set<PropagationStyle> parsedPropagationStylesToInject =
getPropertySetValue(properties, PROPAGATION_STYLE_INJECT, PropagationStyle.class);
getPropagationStyleSetFromPropertyValue(properties, PROPAGATION_STYLE_INJECT);
propagationStylesToInject =
parsedPropagationStylesToInject == null
? parent.propagationStylesToInject
@ -803,7 +807,8 @@ public class Config {
* @deprecated This method should only be used internally. Use the instance getter instead {@link
* #isIntegrationEnabled(SortedSet, boolean)}.
*/
public static boolean integrationEnabled(
@Deprecated
private static boolean integrationEnabled(
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.
@ -896,9 +901,10 @@ public class Config {
*/
private static String getSettingFromEnvironment(final String name, final String defaultValue) {
String value;
final String systemPropertyName = propertyNameToSystemPropertyName(name);
// System properties and properties provided from command line have the highest precedence
value = System.getProperties().getProperty(propertyNameToSystemPropertyName(name));
value = System.getProperties().getProperty(systemPropertyName);
if (null != value) {
return value;
}
@ -910,7 +916,7 @@ public class Config {
}
// If value is not defined yet, we look at properties optionally defined in a properties file
value = propertiesFromConfigFile.getProperty(propertyNameToSystemPropertyName(name));
value = propertiesFromConfigFile.getProperty(systemPropertyName);
if (null != value) {
return value;
}
@ -919,6 +925,7 @@ public class Config {
}
/** @deprecated This method should only be used internally. Use the explicit getter instead. */
@NonNull
private static Map<String, String> getMapSettingFromEnvironment(
final String name, final String defaultValue) {
return parseMap(
@ -931,7 +938,8 @@ public class Config {
*
* @deprecated This method should only be used internally. Use the explicit getter instead.
*/
public static List<String> getListSettingFromEnvironment(
@NonNull
private static List<String> getListSettingFromEnvironment(
final String name, final String defaultValue) {
return parseList(getSettingFromEnvironment(name, defaultValue));
}
@ -943,8 +951,7 @@ public class Config {
*/
public static Boolean getBooleanSettingFromEnvironment(
final String name, final Boolean defaultValue) {
final String value = getSettingFromEnvironment(name, null);
return value == null || value.trim().isEmpty() ? defaultValue : Boolean.valueOf(value);
return getSettingFromEnvironmentWithLog(name, Boolean.class, defaultValue);
}
/**
@ -953,13 +960,7 @@ public class Config {
* @deprecated This method should only be used internally. Use the explicit getter instead.
*/
public static Float getFloatSettingFromEnvironment(final String name, final Float defaultValue) {
final String value = getSettingFromEnvironment(name, null);
try {
return value == null ? defaultValue : Float.valueOf(value);
} catch (final NumberFormatException e) {
log.warn("Invalid configuration for " + name, e);
return defaultValue;
}
return getSettingFromEnvironmentWithLog(name, Float.class, defaultValue);
}
/**
@ -967,15 +968,10 @@ public class Config {
*
* @deprecated This method should only be used internally. Use the explicit getter instead.
*/
public static Double getDoubleSettingFromEnvironment(
@Deprecated
private static Double getDoubleSettingFromEnvironment(
final String name, final Double defaultValue) {
final String value = getSettingFromEnvironment(name, null);
try {
return value == null ? defaultValue : Double.valueOf(value);
} catch (final NumberFormatException e) {
log.warn("Invalid configuration for " + name, e);
return defaultValue;
}
return getSettingFromEnvironmentWithLog(name, Double.class, defaultValue);
}
/**
@ -983,9 +979,13 @@ public class Config {
*/
private static Integer getIntegerSettingFromEnvironment(
final String name, final Integer defaultValue) {
final String value = getSettingFromEnvironment(name, null);
return getSettingFromEnvironmentWithLog(name, Integer.class, defaultValue);
}
private static <T> T getSettingFromEnvironmentWithLog(
final String name, Class<T> tClass, final T defaultValue) {
try {
return value == null ? defaultValue : Integer.valueOf(value);
return valueOf(getSettingFromEnvironment(name, null), tClass, defaultValue);
} catch (final NumberFormatException e) {
log.warn("Invalid configuration for " + name, e);
return defaultValue;
@ -996,28 +996,22 @@ public class Config {
* Calls {@link #getSettingFromEnvironment(String, String)} and converts the result to a set of
* strings splitting by space or comma.
*/
private static <T extends Enum<T>> Set<T> getEnumSetSettingFromEnvironment(
final String name,
final String defaultValue,
final Class<T> clazz,
final boolean emptyResultMeansUseDefault) {
private static Set<PropagationStyle> getPropagationStyleSetSettingFromEnvironmentOrDefault(
final String name, final String defaultValue) {
final String value = getSettingFromEnvironment(name, defaultValue);
Set<T> result =
convertStringSetToEnumSet(
parseStringIntoSetOfNonEmptyStrings(value, SPLIT_BY_SPACE_OR_COMMA_REGEX), clazz);
Set<PropagationStyle> result =
convertStringSetToPropagationStyleSet(parseStringIntoSetOfNonEmptyStrings(value));
if (emptyResultMeansUseDefault && result.isEmpty()) {
if (result.isEmpty()) {
// Treat empty parsing result as no value and use default instead
result =
convertStringSetToEnumSet(
parseStringIntoSetOfNonEmptyStrings(defaultValue, SPLIT_BY_SPACE_OR_COMMA_REGEX),
clazz);
convertStringSetToPropagationStyleSet(parseStringIntoSetOfNonEmptyStrings(defaultValue));
}
return result;
}
private Set<Integer> getIntegerRangeSettingFromEnvironment(
private static Set<Integer> getIntegerRangeSettingFromEnvironment(
final String name, final Set<Integer> defaultValue) {
final String value = getSettingFromEnvironment(name, null);
try {
@ -1035,6 +1029,7 @@ public class Config {
* @param setting The setting name, e.g. `service.name`
* @return The public facing environment variable name
*/
@NonNull
private static String propertyNameToEnvironmentVariableName(final String setting) {
return ENV_REPLACEMENT
.matcher(propertyNameToSystemPropertyName(setting).toUpperCase())
@ -1048,10 +1043,41 @@ public class Config {
* @param setting The setting name, e.g. `service.name`
* @return The public facing system property name
*/
@NonNull
private static String propertyNameToSystemPropertyName(final String setting) {
return PREFIX + setting;
}
/**
* @param value to parse by tClass::valueOf
* @param tClass should contain static parsing method "T valueOf(String)"
* @param defaultValue
* @param <T>
* @return value == null || value.trim().isEmpty() ? defaultValue : tClass.valueOf(value)
* @throws NumberFormatException
*/
private static <T> T valueOf(
final String value, @NonNull final Class<T> tClass, final T defaultValue) {
if (value == null || value.trim().isEmpty()) {
log.debug("valueOf: using defaultValue '{}' for '{}' of '{}' ", defaultValue, value, tClass);
return defaultValue;
}
try {
return (T)
MethodHandles.publicLookup()
.findStatic(tClass, "valueOf", MethodType.methodType(tClass, String.class))
.invoke(value);
} catch (NumberFormatException e) {
throw e;
} catch (NoSuchMethodException | IllegalAccessException e) {
log.debug("Can't invoke or access 'valueOf': ", e);
throw new NumberFormatException(e.toString());
} catch (Throwable e) {
log.debug("Can't parse: ", e);
throw new NumberFormatException(e.toString());
}
}
private static Map<String, String> getPropertyMapValue(
final Properties properties, final String name, final Map<String, String> defaultValue) {
final String value = properties.getProperty(name);
@ -1066,29 +1092,25 @@ public class Config {
private static Boolean getPropertyBooleanValue(
final Properties properties, final String name, final Boolean defaultValue) {
final String value = properties.getProperty(name);
return value == null || value.trim().isEmpty() ? defaultValue : Boolean.valueOf(value);
return valueOf(properties.getProperty(name), Boolean.class, defaultValue);
}
private static Integer getPropertyIntegerValue(
final Properties properties, final String name, final Integer defaultValue) {
final String value = properties.getProperty(name);
return value == null || value.trim().isEmpty() ? defaultValue : Integer.valueOf(value);
return valueOf(properties.getProperty(name), Integer.class, defaultValue);
}
private static Double getPropertyDoubleValue(
final Properties properties, final String name, final Double defaultValue) {
final String value = properties.getProperty(name);
return value == null || value.trim().isEmpty() ? defaultValue : Double.valueOf(value);
return valueOf(properties.getProperty(name), Double.class, defaultValue);
}
private static <T extends Enum<T>> Set<T> getPropertySetValue(
final Properties properties, final String name, final Class<T> clazz) {
private static Set<PropagationStyle> getPropagationStyleSetFromPropertyValue(
final Properties properties, final String name) {
final String value = properties.getProperty(name);
if (value != null) {
final Set<T> result =
convertStringSetToEnumSet(
parseStringIntoSetOfNonEmptyStrings(value, SPLIT_BY_SPACE_OR_COMMA_REGEX), clazz);
final Set<PropagationStyle> result =
convertStringSetToPropagationStyleSet(parseStringIntoSetOfNonEmptyStrings(value));
if (!result.isEmpty()) {
return result;
}
@ -1097,7 +1119,7 @@ public class Config {
return null;
}
private Set<Integer> getPropertyIntegerRangeValue(
private static Set<Integer> getPropertyIntegerRangeValue(
final Properties properties, final String name, final Set<Integer> defaultValue) {
final String value = properties.getProperty(name);
try {
@ -1108,6 +1130,7 @@ public class Config {
}
}
@NonNull
private static Map<String, String> parseMap(final String str, final String settingName) {
// If we ever want to have default values besides an empty map, this will need to change.
if (str == null || str.trim().isEmpty()) {
@ -1137,9 +1160,9 @@ public class Config {
return Collections.unmodifiableMap(map);
}
private static Set<Integer> parseIntegerRangeSet(String str, final String settingName)
@NonNull
private static Set<Integer> parseIntegerRangeSet(@NonNull String str, final String settingName)
throws NumberFormatException {
assert str != null;
str = str.replaceAll("\\s", "");
if (!str.matches("\\d{3}(?:-\\d{3})?(?:,\\d{3}(?:-\\d{3})?)*")) {
log.warn(
@ -1169,10 +1192,26 @@ public class Config {
return Collections.unmodifiableSet(set);
}
@NonNull
private static Map<String, String> newHashMap(final int size) {
return new HashMap<>(size + 1, 1f);
}
/**
* @param map
* @param propName
* @return true if map was modified
*/
private static boolean addPropToMapIfDefinedByEnvironment(
final Map<String, String> map, final String propName) {
final String val = getSettingFromEnvironment(propName, null);
if (val != null) {
return !val.equals(map.put(propertyNameToSystemPropertyName(propName), val));
}
return false;
}
@NonNull
private static List<String> parseList(final String str) {
if (str == null || str.trim().isEmpty()) {
return Collections.emptyList();
@ -1186,13 +1225,13 @@ public class Config {
return Collections.unmodifiableList(Arrays.asList(tokens));
}
private static Set<String> parseStringIntoSetOfNonEmptyStrings(
final String str, final String regex) {
@NonNull
private static Set<String> parseStringIntoSetOfNonEmptyStrings(final String str) {
// Using LinkedHashSet to preserve original string order
final Set<String> result = new LinkedHashSet<>();
// Java returns single value when splitting an empty string. We do not need that value, so
// we need to throw it out.
for (final String value : str.split(regex)) {
for (final String value : str.split(SPLIT_BY_SPACE_OR_COMMA_REGEX)) {
if (!value.isEmpty()) {
result.add(value);
}
@ -1200,15 +1239,16 @@ public class Config {
return Collections.unmodifiableSet(result);
}
private static <V extends Enum<V>> Set<V> convertStringSetToEnumSet(
final Set<String> input, final Class<V> clazz) {
@NonNull
private static Set<PropagationStyle> convertStringSetToPropagationStyleSet(
final Set<String> input) {
// Using LinkedHashSet to preserve original string order
final Set<V> result = new LinkedHashSet<>();
final Set<PropagationStyle> result = new LinkedHashSet<>();
for (final String value : input) {
try {
result.add(Enum.valueOf(clazz, value.toUpperCase()));
result.add(PropagationStyle.valueOf(value.toUpperCase()));
} catch (final IllegalArgumentException e) {
log.debug("Cannot recognize config string value: {}, {}", value, clazz);
log.debug("Cannot recognize config string value: {}, {}", value, PropagationStyle.class);
}
}
return Collections.unmodifiableSet(result);
@ -1245,8 +1285,7 @@ public class Config {
return properties;
}
try {
final FileReader fileReader = new FileReader(configurationFile);
try (final FileReader fileReader = new FileReader(configurationFile)) {
properties.load(fileReader);
} catch (final FileNotFoundException fnf) {
log.error("Configuration file '{}' not found.", configurationFilePath);
@ -1259,8 +1298,8 @@ public class Config {
}
/** Returns the detected hostname. First tries locally, then using DNS */
private String getHostName() {
String possibleHostname = null;
private static String getHostName() {
String possibleHostname;
// Try environment variable. This works in almost all environments
if (System.getProperty("os.name").startsWith("Windows")) {
@ -1275,12 +1314,11 @@ public class Config {
}
// Try hostname command
try {
final Process process = Runtime.getRuntime().exec("hostname");
final BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
try (final BufferedReader reader =
new BufferedReader(
new InputStreamReader(Runtime.getRuntime().exec("hostname").getInputStream()))) {
possibleHostname = reader.readLine();
} catch (final Exception e) {
} catch (final Exception ignore) {
// Ignore. Hostname command is not always available
}

View File

@ -82,6 +82,8 @@ class ConfigTest extends DDSpecification {
private static final DD_WRITER_TYPE_ENV = "DD_WRITER_TYPE"
private static final DD_SERVICE_MAPPING_ENV = "DD_SERVICE_MAPPING"
private static final DD_TAGS_ENV = "DD_TAGS"
private static final DD_ENV_ENV = "DD_ENV"
private static final DD_VERSION_ENV = "DD_VERSION"
private static final DD_GLOBAL_TAGS_ENV = "DD_TRACE_GLOBAL_TAGS"
private static final DD_SPAN_TAGS_ENV = "DD_TRACE_SPAN_TAGS"
private static final DD_HEADER_TAGS_ENV = "DD_TRACE_HEADER_TAGS"
@ -951,6 +953,7 @@ class ConfigTest extends DDSpecification {
setup:
System.setProperty(PREFIX + CONFIGURATION_FILE, "src/test/resources/dd-java-tracer.properties")
environmentVariables.set("DD_SERVICE_NAME", "set-in-env")
environmentVariables.set("DD_SERVICE", "some-other-ignored-name")
when:
def config = new Config()
@ -961,7 +964,17 @@ class ConfigTest extends DDSpecification {
cleanup:
System.clearProperty(PREFIX + CONFIGURATION_FILE)
System.clearProperty(PREFIX + SERVICE_NAME)
environmentVariables.clear("DD_SERVICE_NAME")
}
def "verify fallback to DD_SERVICE"() {
setup:
environmentVariables.set("DD_SERVICE", "service-name-from-dd-service-env-var")
when:
def config = new Config()
then:
config.serviceName == "service-name-from-dd-service-env-var"
}
def "verify fallback to properties file that does not exist does not crash app"() {
@ -1218,4 +1231,120 @@ class ConfigTest extends DDSpecification {
config.getFinalProfilingUrl() == "https://some.new.url/goes/here"
}
def "fallback to DD_TAGS"() {
setup:
environmentVariables.set(DD_TAGS_ENV, "a:1,b:2,c:3")
when:
Config config = new Config()
then:
config.mergedSpanTags == [a: "1", c: "3", b: "2"]
}
def "precedence of DD_ENV and DD_VERSION"() {
setup:
environmentVariables.set(DD_ENV_ENV, "test_env")
environmentVariables.set(DD_VERSION_ENV, "1.2.3")
environmentVariables.set(DD_TAGS_ENV, "dd.env:production , dd.version:3.2.1")
when:
Config config = new Config()
then:
config.mergedSpanTags == ["dd.env": "test_env", "dd.version": "1.2.3"]
}
def "propertyNameToEnvironmentVariableName unit test"() {
expect:
Config.propertyNameToEnvironmentVariableName(Config.SERVICE) == "DD_SERVICE"
}
def "getProperty*Value unit test"() {
setup:
def p = new Properties()
p.setProperty("a", "42.42")
p.setProperty("intProp", "13")
expect:
Config.getPropertyDoubleValue(p, "intProp", 40) == 13
Config.getPropertyDoubleValue(p, "a", 41) == 42.42
Config.getPropertyIntegerValue(p, "b", 61) == 61
Config.getPropertyIntegerValue(p, "intProp", 61) == 13
Config.getPropertyBooleanValue(p, "a", true) == false
}
def "valueOf positive test"() {
expect:
Config.valueOf(value, tClass, defaultValue) == expected
where:
value | tClass | defaultValue | expected
"42.42" | Boolean | true | false
"42.42" | Boolean | null | false
"true" | Boolean | null | true
"trUe" | Boolean | null | true
"trUe" | Boolean | false | true
"tru" | Boolean | true | false
"truee" | Boolean | true | false
"true " | Boolean | true | false
" true" | Boolean | true | false
" true " | Boolean | true | false
" true "| Boolean | true | false
null | Float | 43.3 | 43.3
"42.42" | Float | 21.21 | 42.42f
null | Double | 43.3 | 43.3
"42.42" | Double | 21.21 | 42.42
null | Integer | 13 | 13
"44" | Integer | 21 | 44
"45" | Long | 21 | 45
"46" | Short | 21 | 46
}
def "valueOf negative test when tClass is null"() {
when:
Config.valueOf(value, tClass, defaultValue)
then:
def exception = thrown(NullPointerException)
exception.message == "tClass is marked non-null but is null"
where:
value | tClass | defaultValue
null | null | "42"
"" | null | "43"
" " | null | "44"
"1" | null | "45"
}
def "valueOf negative test"() {
when:
Config.valueOf(value, tClass, null)
then:
def exception = thrown(NumberFormatException)
println("cause: " : exception.message)
where:
value | tClass
"42.42" | Number
"42.42" | Byte
"42.42" | Character
"42.42" | Short
"42.42" | Integer
"42.42" | Long
"42.42" | Object
"42.42" | Object[]
"42.42" | boolean[]
"42.42" | boolean
"42.42" | byte
"42.42" | byte
"42.42" | char
"42.42" | short
"42.42" | int
"42.42" | long
"42.42" | double
"42.42" | float
}
}

View File

@ -3,6 +3,7 @@ package datadog.trace.common.writer.ddagent;
import com.lmax.disruptor.EventHandler;
import datadog.common.exec.DaemonThreadFactory;
import datadog.opentracing.DDSpan;
import datadog.opentracing.DDSpanContext;
import datadog.trace.common.writer.DDAgentWriter;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
@ -65,7 +66,7 @@ public class TraceProcessingDisruptor extends AbstractDisruptor<List<DDSpan>> {
// attempt to have agent scale the metrics properly
((DDSpan) event.data.get(0).getLocalRootSpan())
.context()
.setMetric("_sample_rate", 1d / event.representativeCount);
.setMetric(DDSpanContext.SAMPLE_RATE_KEY, 1d / event.representativeCount);
}
try {
final byte[] serializedTrace = api.serializeTrace(event.data);

View File

@ -2,6 +2,7 @@ package datadog.trace.api.sampling
import datadog.opentracing.DDSpan
import datadog.opentracing.DDSpanContext
import datadog.opentracing.DDTracer
import datadog.opentracing.SpanFactory
import datadog.trace.api.DDTags
@ -68,7 +69,7 @@ class RateByServiceSamplerTest extends DDSpecification {
// sets correctly on root span
span.getSamplingPriority() == PrioritySampling.SAMPLER_KEEP
// RateByServiceSamler must not set the sample rate
span.getMetrics().get("_sample_rate") == null
span.getMetrics().get(DDSpanContext.SAMPLE_RATE_KEY) == null
}
def "sampling priority set when service later"() {