diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/opentelemetry/OpenTelemetryResourceAttributes.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/opentelemetry/OpenTelemetryResourceAttributes.java index c28a4446cb9a..4e94ed213f45 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/opentelemetry/OpenTelemetryResourceAttributes.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/opentelemetry/OpenTelemetryResourceAttributes.java @@ -16,7 +16,6 @@ package org.springframework.boot.actuate.autoconfigure.opentelemetry; -import java.io.ByteArrayOutputStream; import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.LinkedHashMap; @@ -78,8 +77,8 @@ public OpenTelemetryResourceAttributes(Environment environment, Map * If a key exists in both environment variables and user-defined resources, the value * from the user-defined resource takes precedence, even if it is empty. @@ -139,7 +138,7 @@ private Map getResourceAttributesFromEnv() { if (index > 0) { String key = attribute.substring(0, index); String value = attribute.substring(index + 1); - attributes.put(key.trim(), decode(value.trim())); + attributes.put(key.trim(), StringUtils.uriDecode(value.trim(), StandardCharsets.UTF_8)); } } String otelServiceName = getEnv("OTEL_SERVICE_NAME"); @@ -153,43 +152,4 @@ private String getEnv(String name) { return this.getEnv.apply(name); } - /** - * Decodes a percent-encoded string. Converts sequences like '%HH' (where HH - * represents hexadecimal digits) back into their literal representations. - *

- * Inspired by {@code org.apache.commons.codec.net.PercentCodec}. - * @param value value to decode - * @return the decoded string - */ - private static String decode(String value) { - if (value.indexOf('%') < 0) { - return value; - } - byte[] bytes = value.getBytes(StandardCharsets.UTF_8); - ByteArrayOutputStream bos = new ByteArrayOutputStream(bytes.length); - for (int i = 0; i < bytes.length; i++) { - byte b = bytes[i]; - if (b != '%') { - bos.write(b); - continue; - } - int u = decodeHex(bytes, i + 1); - int l = decodeHex(bytes, i + 2); - if (u >= 0 && l >= 0) { - bos.write((u << 4) + l); - } - else { - throw new IllegalArgumentException( - "Failed to decode percent-encoded characters at index %d in the value: '%s'".formatted(i, - value)); - } - i += 2; - } - return bos.toString(StandardCharsets.UTF_8); - } - - private static int decodeHex(byte[] bytes, int index) { - return (index < bytes.length) ? Character.digit(bytes[index], 16) : -1; - } - } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/opentelemetry/OpenTelemetryResourceAttributesTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/opentelemetry/OpenTelemetryResourceAttributesTests.java index 4b6f139ee34a..799c7175de6a 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/opentelemetry/OpenTelemetryResourceAttributesTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/opentelemetry/OpenTelemetryResourceAttributesTests.java @@ -121,7 +121,7 @@ void otelResourceAttributeValuesShouldBePercentDecoded() { void illegalArgumentExceptionShouldBeThrownWhenDecodingIllegalHexCharPercentEncodedValue() { this.environmentVariables.put("OTEL_RESOURCE_ATTRIBUTES", "key=abc%ß"); assertThatIllegalArgumentException().isThrownBy(this::getAttributes) - .withMessage("Failed to decode percent-encoded characters at index 3 in the value: 'abc%ß'"); + .withMessage("Invalid encoded sequence \"%ß\""); } @Test @@ -134,7 +134,7 @@ void replacementCharShouldBeUsedWhenDecodingNonUtf8Character() { void illegalArgumentExceptionShouldBeThrownWhenDecodingInvalidPercentEncodedValue() { this.environmentVariables.put("OTEL_RESOURCE_ATTRIBUTES", "key=%"); assertThatIllegalArgumentException().isThrownBy(this::getAttributes) - .withMessage("Failed to decode percent-encoded characters at index 0 in the value: '%'"); + .withMessage("Invalid encoded sequence \"%\""); } @Test