Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decode resource attributes specified via otel.resource.attributes #4756

Merged
merged 1 commit into from
Oct 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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();
jack-berg marked this conversation as resolved.
Show resolved Hide resolved
}
}