diff --git a/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/ConfigProperties.java b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/ConfigProperties.java index 4d03ca108ad..9480b66ac84 100644 --- a/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/ConfigProperties.java +++ b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/ConfigProperties.java @@ -184,7 +184,7 @@ default List getList(String name, List defaultValue) { /** * Returns a Map configuration property. The format of the original value must be comma-separated * for each key, with an '=' separating the key and value. For instance, - * service.name=Greatest Service,host.name=localhost Empty values will be removed. + * service.name=Greatest Service,host.name=localhost. Empty values will be removed. * * @return an empty map if the property has not been configured. * @throws ConfigurationException for malformed map strings. diff --git a/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java index c9ed7305e8c..b8673993fe3 100644 --- a/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java +++ b/sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/DefaultConfigProperties.java @@ -9,6 +9,7 @@ import static java.util.stream.Collectors.joining; import io.opentelemetry.api.internal.ConfigUtil; +import io.opentelemetry.api.internal.StringUtils; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import java.time.Duration; @@ -209,16 +210,21 @@ public static Set getSet(ConfigProperties config, String name) { @Override public Map getMap(String name) { return getList(ConfigUtil.normalizePropertyKey(name)).stream() - .map(keyValuePair -> filterBlanksAndNulls(keyValuePair.split("=", 2))) .map( - splitKeyValuePairs -> { - if (splitKeyValuePairs.size() != 2) { + entry -> { + String[] split = entry.split("=", 2); + if (split.length != 2 || StringUtils.isNullOrEmpty(split[0])) { throw new ConfigurationException( "Invalid map property: " + name + "=" + config.get(name)); } - return new AbstractMap.SimpleImmutableEntry<>( - splitKeyValuePairs.get(0), splitKeyValuePairs.get(1)); + return filterBlanksAndNulls(split); }) + // Filter entries with an empty value, i.e. "foo=" + .filter(splitKeyValuePairs -> splitKeyValuePairs.size() == 2) + .map( + splitKeyValuePairs -> + new AbstractMap.SimpleImmutableEntry<>( + splitKeyValuePairs.get(0), splitKeyValuePairs.get(1))) // If duplicate keys, prioritize later ones similar to duplicate system properties on a // Java command line. .collect( diff --git a/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java b/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java index 528171b7b93..e0fe198dc9e 100644 --- a/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java +++ b/sdk-extensions/autoconfigure-spi/src/test/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ConfigPropertiesTest.java @@ -155,12 +155,6 @@ void uncleanMap() { @Test void invalidMap() { - assertThatThrownBy( - () -> - DefaultConfigProperties.createFromMap(Collections.singletonMap("map", "a=1,b=")) - .getMap("map")) - .isInstanceOf(ConfigurationException.class) - .hasMessage("Invalid map property: map=a=1,b="); assertThatThrownBy( () -> DefaultConfigProperties.createFromMap(Collections.singletonMap("map", "a=1,b")) @@ -281,7 +275,7 @@ private static Map makeTestProps() { properties.put("test.double", "5.4"); properties.put("test.boolean", "true"); properties.put("test.list", "cat,dog,bear"); - properties.put("test.map", "cat=meow,dog=bark,bear=growl"); + properties.put("test.map", "cat=meow,dog=bark,bear=growl,bird="); properties.put("test.duration", "1s"); return properties; } diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/ResourceConfigurationTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/ResourceConfigurationTest.java index 3fcf119afec..acff48b4ebc 100644 --- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/ResourceConfigurationTest.java +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/ResourceConfigurationTest.java @@ -30,7 +30,8 @@ class ResourceConfigurationTest { void customConfigResource() { Map props = new HashMap<>(); props.put("otel.service.name", "test-service"); - props.put("otel.resource.attributes", "food=cheesecake,drink=juice"); + props.put( + "otel.resource.attributes", "food=cheesecake,drink=juice,animal= ,color=,shape=square"); props.put("otel.experimental.resource.disabled-keys", "drink"); assertThat( @@ -42,6 +43,7 @@ void customConfigResource() { Resource.getDefault().toBuilder() .put(ResourceAttributes.SERVICE_NAME, "test-service") .put("food", "cheesecake") + .put("shape", "square") .setSchemaUrl(ResourceAttributes.SCHEMA_URL) .build()); }