Preencode attribute keys into utf8 bytes. (#3576)

* Use constants for AttributeKeys in JMH

* Preencode attribute keys into utf8 bytes.

* Spot

* Ignore

* Be lazy

* Boil
This commit is contained in:
Anuraag Agrawal 2021-09-10 10:35:26 +09:00 committed by GitHub
parent 060e50ed5f
commit ece161f6e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 19 deletions

View File

@ -5,6 +5,7 @@
package io.opentelemetry.api.common;
import io.opentelemetry.api.internal.InternalAttributeKeyImpl;
import java.util.List;
import javax.annotation.concurrent.Immutable;
@ -27,41 +28,41 @@ public interface AttributeKey<T> {
/** Returns a new AttributeKey for String valued attributes. */
static AttributeKey<String> stringKey(String key) {
return AttributeKeyImpl.create(key, AttributeType.STRING);
return InternalAttributeKeyImpl.create(key, AttributeType.STRING);
}
/** Returns a new AttributeKey for Boolean valued attributes. */
static AttributeKey<Boolean> booleanKey(String key) {
return AttributeKeyImpl.create(key, AttributeType.BOOLEAN);
return InternalAttributeKeyImpl.create(key, AttributeType.BOOLEAN);
}
/** Returns a new AttributeKey for Long valued attributes. */
static AttributeKey<Long> longKey(String key) {
return AttributeKeyImpl.create(key, AttributeType.LONG);
return InternalAttributeKeyImpl.create(key, AttributeType.LONG);
}
/** Returns a new AttributeKey for Double valued attributes. */
static AttributeKey<Double> doubleKey(String key) {
return AttributeKeyImpl.create(key, AttributeType.DOUBLE);
return InternalAttributeKeyImpl.create(key, AttributeType.DOUBLE);
}
/** Returns a new AttributeKey for List&lt;String&gt; valued attributes. */
static AttributeKey<List<String>> stringArrayKey(String key) {
return AttributeKeyImpl.create(key, AttributeType.STRING_ARRAY);
return InternalAttributeKeyImpl.create(key, AttributeType.STRING_ARRAY);
}
/** Returns a new AttributeKey for List&lt;Boolean&gt; valued attributes. */
static AttributeKey<List<Boolean>> booleanArrayKey(String key) {
return AttributeKeyImpl.create(key, AttributeType.BOOLEAN_ARRAY);
return InternalAttributeKeyImpl.create(key, AttributeType.BOOLEAN_ARRAY);
}
/** Returns a new AttributeKey for List&lt;Long&gt; valued attributes. */
static AttributeKey<List<Long>> longArrayKey(String key) {
return AttributeKeyImpl.create(key, AttributeType.LONG_ARRAY);
return InternalAttributeKeyImpl.create(key, AttributeType.LONG_ARRAY);
}
/** Returns a new AttributeKey for List&lt;Double&gt; valued attributes. */
static AttributeKey<List<Double>> doubleArrayKey(String key) {
return AttributeKeyImpl.create(key, AttributeType.DOUBLE_ARRAY);
return InternalAttributeKeyImpl.create(key, AttributeType.DOUBLE_ARRAY);
}
}

View File

@ -3,18 +3,28 @@
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.api.common;
package io.opentelemetry.api.internal;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.AttributeType;
import java.nio.charset.StandardCharsets;
import javax.annotation.Nullable;
@SuppressWarnings("rawtypes")
final class AttributeKeyImpl<T> implements AttributeKey<T> {
/**
* Default AttributeKey implementation which preencodes to UTF8 for OTLP export.
*
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
* at any time.
*/
public final class InternalAttributeKeyImpl<T> implements AttributeKey<T> {
private final AttributeType type;
private final String key;
private final int hashCode;
private AttributeKeyImpl(AttributeType type, String key) {
private byte[] keyUtf8;
private InternalAttributeKeyImpl(AttributeType type, String key) {
if (type == null) {
throw new NullPointerException("Null type");
}
@ -38,8 +48,8 @@ final class AttributeKeyImpl<T> implements AttributeKey<T> {
// the class loader automatically resolves its super classes (interfaces), which in this case is
// Context, which would be the same class (interface) being instrumented at that time,
// which would lead to the JVM throwing a LinkageError "attempted duplicate interface definition"
static <T> AttributeKey<T> create(@Nullable String key, AttributeType type) {
return new AttributeKeyImpl<>(type, key != null ? key : "");
public static <T> AttributeKey<T> create(@Nullable String key, AttributeType type) {
return new InternalAttributeKeyImpl<>(type, key != null ? key : "");
}
@Override
@ -52,13 +62,23 @@ final class AttributeKeyImpl<T> implements AttributeKey<T> {
return key;
}
/** Returns the key, encoded as UTF-8 bytes. */
public byte[] getKeyUtf8() {
byte[] keyUtf8 = this.keyUtf8;
if (keyUtf8 == null) {
keyUtf8 = key.getBytes(StandardCharsets.UTF_8);
this.keyUtf8 = keyUtf8;
}
return keyUtf8;
}
@Override
public boolean equals(@Nullable Object o) {
if (o == this) {
return true;
}
if (o instanceof AttributeKeyImpl) {
AttributeKeyImpl<?> that = (AttributeKeyImpl<?>) o;
if (o instanceof InternalAttributeKeyImpl) {
InternalAttributeKeyImpl<?> that = (InternalAttributeKeyImpl<?>) o;
return this.type.equals(that.getType()) && this.key.equals(that.getKey());
}
return false;

View File

@ -7,6 +7,7 @@ package io.opentelemetry.api.common;
import static org.assertj.core.api.Assertions.assertThat;
import io.opentelemetry.api.internal.InternalAttributeKeyImpl;
import nl.jqno.equalsverifier.EqualsVerifier;
import org.junit.jupiter.api.Test;
@ -14,9 +15,12 @@ class AttributeKeyTest {
@Test
void equalsVerifier() {
EqualsVerifier.forClass(AttributeKeyImpl.class)
EqualsVerifier.forClass(InternalAttributeKeyImpl.class)
.withIgnoredFields("keyUtf8")
.withCachedHashCode(
"hashCode", "buildHashCode", (AttributeKeyImpl<?>) AttributeKey.stringKey("test"))
"hashCode",
"buildHashCode",
(InternalAttributeKeyImpl<?>) AttributeKey.stringKey("test"))
.verify();
}

View File

@ -7,6 +7,7 @@ package io.opentelemetry.exporter.otlp.internal;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.internal.InternalAttributeKeyImpl;
import io.opentelemetry.proto.common.v1.internal.AnyValue;
import io.opentelemetry.proto.common.v1.internal.ArrayValue;
import io.opentelemetry.proto.common.v1.internal.KeyValue;
@ -41,7 +42,14 @@ final class KeyValueMarshaler extends MarshalerWithSize {
@SuppressWarnings("unchecked")
static KeyValueMarshaler create(AttributeKey<?> attributeKey, Object value) {
byte[] keyUtf8 = MarshalerUtil.toBytes(attributeKey.getKey());
final byte[] keyUtf8;
if (attributeKey.getKey().isEmpty()) {
keyUtf8 = MarshalerUtil.EMPTY_BYTES;
} else if (attributeKey instanceof InternalAttributeKeyImpl) {
keyUtf8 = ((InternalAttributeKeyImpl<?>) attributeKey).getKeyUtf8();
} else {
keyUtf8 = attributeKey.getKey().getBytes(StandardCharsets.UTF_8);
}
switch (attributeKey.getType()) {
case STRING:
return new KeyValueMarshaler(