diff --git a/semconv/src/main/java/io/opentelemetry/semconv/AttributeKeyTemplate.java b/semconv/src/main/java/io/opentelemetry/semconv/AttributeKeyTemplate.java new file mode 100644 index 0000000..6870a7c --- /dev/null +++ b/semconv/src/main/java/io/opentelemetry/semconv/AttributeKeyTemplate.java @@ -0,0 +1,120 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.semconv; + +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.common.AttributeType; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.function.Function; + +/** + * This class provides a handle for creating and caching dynamic / template-type attributes of the + * form <prefix>.<key>. The <prefix> is fixed for a template instance while + * {@link AttributeKey}s can be created and are cached for different values of the <key> part. + * + *

An example template-type attribute is the set of attributes for HTTP headers: + * http.request.header.<key> + * + * @param The type of the nested {@link AttributeKey}s. + */ +public final class AttributeKeyTemplate { + + private final String prefix; + private final Function> keyBuilder; + private final ConcurrentMap> keysCache = new ConcurrentHashMap<>(1); + + private AttributeKeyTemplate(String prefix, Function> keyBuilder) { + this.prefix = prefix; + this.keyBuilder = keyBuilder; + } + + /** + * Create an {@link AttributeKeyTemplate} with type {@link AttributeType#STRING} and the given + * {@code prefix}. + */ + public static AttributeKeyTemplate stringKeyTemplate(String prefix) { + return new AttributeKeyTemplate<>(prefix, AttributeKey::stringKey); + } + + /** + * Create an {@link AttributeKeyTemplate} with type {@link AttributeType#STRING_ARRAY} and the + * given {@code prefix}. + */ + public static AttributeKeyTemplate> stringArrayKeyTemplate(String prefix) { + return new AttributeKeyTemplate<>(prefix, AttributeKey::stringArrayKey); + } + + /** + * Create an {@link AttributeKeyTemplate} with type {@link AttributeType#BOOLEAN} and the given + * {@code prefix}. + */ + public static AttributeKeyTemplate booleanKeyTemplate(String prefix) { + return new AttributeKeyTemplate<>(prefix, AttributeKey::booleanKey); + } + + /** + * Create an {@link AttributeKeyTemplate} with type {@link AttributeType#BOOLEAN_ARRAY} and the + * given {@code prefix}. + */ + public static AttributeKeyTemplate> booleanArrayKeyTemplate(String prefix) { + return new AttributeKeyTemplate<>(prefix, AttributeKey::booleanArrayKey); + } + + /** + * Create an {@link AttributeKeyTemplate} with type {@link AttributeType#LONG} and the given + * {@code prefix}. + */ + public static AttributeKeyTemplate longKeyTemplate(String prefix) { + return new AttributeKeyTemplate<>(prefix, AttributeKey::longKey); + } + + /** + * Create an {@link AttributeKeyTemplate} with type {@link AttributeType#LONG_ARRAY} and the given + * {@code prefix}. + */ + public static AttributeKeyTemplate> longArrayKeyTemplate(String prefix) { + return new AttributeKeyTemplate<>(prefix, AttributeKey::longArrayKey); + } + + /** + * Create an {@link AttributeKeyTemplate} with type {@link AttributeType#DOUBLE} and the given + * {@code prefix}. + */ + public static AttributeKeyTemplate doubleKeyTemplate(String prefix) { + return new AttributeKeyTemplate<>(prefix, AttributeKey::doubleKey); + } + + /** + * Create an {@link AttributeKeyTemplate} with type {@link AttributeType#DOUBLE_ARRAY} and the + * given {@code prefix}. + */ + public static AttributeKeyTemplate> doubleArrayKeyTemplate(String prefix) { + return new AttributeKeyTemplate<>(prefix, AttributeKey::doubleArrayKey); + } + + private AttributeKey createAttributeKey(String keyName) { + String key = prefix + "." + keyName; + return keyBuilder.apply(key); + } + + /** + * Returns an {@link AttributeKey} object for the given attribute key whereby the key is the + * variable part of the full attribute name in a template-typed attribute, for example + * http.request.header.<key>. + * + *

{@link AttributeKey} objets are being created and cached on the first invocation of this + * method for a certain key. Subsequent invocations of this method with the same key return the + * cached object. + * + * @param key The variable part of the template-typed attribute name. + * @return An {@link AttributeKey} object for the given key. + */ + public AttributeKey getAttributeKey(String key) { + return keysCache.computeIfAbsent(key, this::createAttributeKey); + } +}