diff --git a/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/DeclarativeConfigPropertiesBridge.java b/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/DeclarativeConfigPropertiesBridge.java index 928a17f5bd..b22cd43f36 100644 --- a/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/DeclarativeConfigPropertiesBridge.java +++ b/declarative-config-bridge/src/main/java/io/opentelemetry/instrumentation/config/bridge/DeclarativeConfigPropertiesBridge.java @@ -9,12 +9,14 @@ import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties. import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; +import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import java.time.Duration; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.concurrent.TimeUnit; import java.util.function.BiFunction; import javax.annotation.Nullable; @@ -99,11 +101,77 @@ final class DeclarativeConfigPropertiesBridge implements ConfigProperties { @Nullable @Override public Duration getDuration(String propertyName) { - Long millis = getPropertyValue(propertyName, Long.class, DeclarativeConfigProperties::getLong); - if (millis == null) { + // If this is a raw integer number then assume it is the number of milliseconds + Long millis = getLong(propertyName); + if (millis != null) { + return Duration.ofMillis(millis); + } + + // If this is a string than it consists of value and time unit + String value = getString(propertyName); + if (value == null) { return null; } - return Duration.ofMillis(millis); + String unitString = getUnitString(value); + String numberString = value.substring(0, value.length() - unitString.length()); + try { + long rawNumber = Long.parseLong(numberString.trim()); + TimeUnit unit = getDurationUnit(unitString.trim()); + return Duration.ofNanos(TimeUnit.NANOSECONDS.convert(rawNumber, unit)); + } catch (NumberFormatException ex) { + throw new ConfigurationException( + "Invalid duration property " + + propertyName + + "=" + + value + + ". Expected number, found: " + + numberString, + ex); + } catch (ConfigurationException ex) { + throw new ConfigurationException( + "Invalid duration property " + propertyName + "=" + value + ". " + ex.getMessage()); + } + } + + /** Returns the TimeUnit associated with a unit string. Defaults to milliseconds. */ + private static TimeUnit getDurationUnit(String unitString) { + switch (unitString) { + case "us": + return TimeUnit.MICROSECONDS; + case "ns": + return TimeUnit.NANOSECONDS; + case "": // Fallthrough expected + case "ms": + return TimeUnit.MILLISECONDS; + case "s": + return TimeUnit.SECONDS; + case "m": + return TimeUnit.MINUTES; + case "h": + return TimeUnit.HOURS; + case "d": + return TimeUnit.DAYS; + default: + throw new ConfigurationException("Invalid duration string, found: " + unitString); + } + } + + /** + * Fragments the 'units' portion of a config value from the 'value' portion. + * + *
E.g. "1ms" would return the string "ms". + */ + private static String getUnitString(String rawValue) { + int lastDigitIndex = rawValue.length() - 1; + while (lastDigitIndex >= 0) { + char c = rawValue.charAt(lastDigitIndex); + if (Character.isDigit(c)) { + break; + } + lastDigitIndex--; + } + // Pull everything after the last digit. + return rawValue.substring(lastDigitIndex + 1); } @SuppressWarnings("unchecked") diff --git a/declarative-config-bridge/src/test/java/io/opentelemetry/instrumentation/config/bridge/DeclarativeConfigPropertiesBridgeTest.java b/declarative-config-bridge/src/test/java/io/opentelemetry/instrumentation/config/bridge/DeclarativeConfigPropertiesBridgeTest.java index 29f9d424cd..7aa15966d9 100644 --- a/declarative-config-bridge/src/test/java/io/opentelemetry/instrumentation/config/bridge/DeclarativeConfigPropertiesBridgeTest.java +++ b/declarative-config-bridge/src/test/java/io/opentelemetry/instrumentation/config/bridge/DeclarativeConfigPropertiesBridgeTest.java @@ -72,8 +72,10 @@ class DeclarativeConfigPropertiesBridgeTest { assertThat(bridge.getInt("otel.instrumentation.example-instrumentation.int_key")).isEqualTo(1); assertThat(bridge.getLong("otel.instrumentation.example-instrumentation.int_key")) .isEqualTo(1L); - assertThat(bridge.getDuration("otel.instrumentation.example-instrumentation.int_key")) - .isEqualTo(Duration.ofMillis(1)); + assertThat(bridge.getDuration("otel.instrumentation.example-instrumentation.duration_key1")) + .isEqualTo(Duration.ofMillis(123)); + assertThat(bridge.getDuration("otel.instrumentation.example-instrumentation.duration_key2")) + .isEqualTo(Duration.ofNanos(987)); assertThat(bridge.getDouble("otel.instrumentation.example-instrumentation.double_key")) .isEqualTo(1.1); assertThat(bridge.getList("otel.instrumentation.example-instrumentation.list_key")) diff --git a/declarative-config-bridge/src/test/resources/config.yaml b/declarative-config-bridge/src/test/resources/config.yaml index 5f8bbd1943..ad83ab3291 100644 --- a/declarative-config-bridge/src/test/resources/config.yaml +++ b/declarative-config-bridge/src/test/resources/config.yaml @@ -14,6 +14,8 @@ instrumentation/development: bool_key: true int_key: 1 double_key: 1.1 + duration_key1: 123 + duration_key2: 987ns list_key: - value1 - value2