Skip to content

Commit

Permalink
Decode resource attributes specified via otel.resource.attributes (#4756
Browse files Browse the repository at this point in the history
)
  • Loading branch information
jack-berg committed Oct 18, 2022
1 parent a3551e7 commit db1d065
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import io.opentelemetry.api.baggage.Baggage;
import io.opentelemetry.api.baggage.BaggageBuilder;
import io.opentelemetry.api.baggage.BaggageEntry;
import io.opentelemetry.api.internal.PercentEscaper;
import io.opentelemetry.api.internal.StringUtils;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.propagation.TextMapGetter;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@
* the License.
*/

package io.opentelemetry.api.baggage.propagation;
package io.opentelemetry.api.internal;

import io.opentelemetry.api.internal.TemporaryBuffers;
import javax.annotation.CheckForNull;

/**
Expand Down Expand Up @@ -59,10 +58,13 @@
* <p><b>Note:</b> This escaper produces <a
* href="https://url.spec.whatwg.org/#percent-encode">uppercase</a> hexadecimal sequences.
*
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
* at any time.
*
* @author David Beaumont
* @since 15.0
*/
final class PercentEscaper {
public final class PercentEscaper {

/** The amount of padding (chars) to use when growing the escape buffer. */
private static final int DEST_PAD = 32;
Expand All @@ -86,7 +88,7 @@ final class PercentEscaper {
private static final boolean[] safeOctets = createSafeOctets(SAFE_CHARS);

/** The default {@link PercentEscaper} which will *not* replace spaces with plus signs. */
static PercentEscaper create() {
public static PercentEscaper create() {
return new PercentEscaper();
}

Expand All @@ -109,7 +111,7 @@ private static boolean[] createSafeOctets(String safeChars) {
}

/** Escape the provided String, using percent-style URL Encoding. */
String escape(String s) {
public String escape(String s) {
int slen = s.length();
for (int index = 0; index < slen; index++) {
char c = s.charAt(index);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import edu.berkeley.cs.jqf.fuzz.JQF;
import edu.berkeley.cs.jqf.fuzz.junit.GuidedFuzzing;
import edu.berkeley.cs.jqf.fuzz.random.NoGuidance;
import io.opentelemetry.api.internal.PercentEscaper;
import java.net.URLDecoder;
import org.junit.jupiter.api.Test;
import org.junit.runner.Result;
Expand Down
1 change: 1 addition & 0 deletions sdk-extensions/autoconfigure/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ dependencies {
testImplementation(project(":sdk:testing"))
testImplementation("com.linecorp.armeria:armeria-junit5")
testImplementation("com.linecorp.armeria:armeria-grpc")
testImplementation("edu.berkeley.cs.jqf:jqf-fuzz")
testRuntimeOnly("io.grpc:grpc-netty-shaded")
testImplementation("io.opentelemetry.proto:opentelemetry-proto")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,17 @@
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
import io.opentelemetry.sdk.autoconfigure.spi.internal.ConditionalResourceProvider;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.resources.ResourceBuilder;
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;

Expand Down Expand Up @@ -68,7 +73,20 @@ private static Resource createEnvironmentResource(ConfigProperties config) {
// visible for testing
static Attributes getAttributes(ConfigProperties configProperties) {
AttributesBuilder resourceAttributes = Attributes.builder();
configProperties.getMap(ATTRIBUTE_PROPERTY).forEach(resourceAttributes::put);
try {
for (Map.Entry<String, String> entry :
configProperties.getMap(ATTRIBUTE_PROPERTY).entrySet()) {
resourceAttributes.put(
entry.getKey(),
// Attributes specified via otel.resource.attributes follow the W3C Baggage spec and
// characters outside the baggage-octet range are percent encoded
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/sdk.md#specifying-resource-information-via-an-environment-variable
URLDecoder.decode(entry.getValue(), StandardCharsets.UTF_8.displayName()));
}
} catch (UnsupportedEncodingException e) {
// Should not happen since always using standard charset
throw new ConfigurationException("Unable to decode resource attributes.", e);
}
String serviceName = configProperties.getString(SERVICE_NAME_PROPERTY);
if (serviceName != null) {
resourceAttributes.put(ResourceAttributes.SERVICE_NAME, serviceName);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.autoconfigure;

import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
import static java.util.Collections.singletonMap;

import edu.berkeley.cs.jqf.fuzz.Fuzz;
import edu.berkeley.cs.jqf.fuzz.JQF;
import edu.berkeley.cs.jqf.fuzz.junit.GuidedFuzzing;
import edu.berkeley.cs.jqf.fuzz.random.NoGuidance;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.internal.PercentEscaper;
import org.junit.jupiter.api.Test;
import org.junit.runner.Result;
import org.junit.runner.RunWith;

@SuppressWarnings("SystemOut")
class ResourceConfigurationFuzzTest {

@RunWith(JQF.class)
public static class TestCases {

private static final PercentEscaper escaper = PercentEscaper.create();

@Fuzz
public void getAttributesWithRandomValues(String value1, String value2) {
Attributes attributes =
ResourceConfiguration.getAttributes(
DefaultConfigProperties.createForTest(
singletonMap(
ResourceConfiguration.ATTRIBUTE_PROPERTY,
"key1=" + escaper.escape(value1) + ",key2=" + escaper.escape(value2))));

assertThat(attributes).hasSize(2).containsEntry("key1", value1).containsEntry("key2", value2);
}
}

// driver methods to avoid having to use the vintage junit engine, and to enable increasing the
// number of iterations:

@Test
void getAttributesWithFuzzing() {
Result result =
GuidedFuzzing.run(
TestCases.class,
"getAttributesWithRandomValues",
new NoGuidance(10000, System.out),
System.out);
assertThat(result.wasSuccessful()).isTrue();
}
}

0 comments on commit db1d065

Please sign in to comment.