Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,9 @@ static AttributeKey<List<Long>> longArrayKey(String key) {
static AttributeKey<List<Double>> doubleArrayKey(String key) {
return InternalAttributeKeyImpl.create(key, AttributeType.DOUBLE_ARRAY);
}

/** Returns a new AttributeKey for generic {@link Value} valued attributes. */
static AttributeKey<Value<?>> valueKey(String key) {
return InternalAttributeKeyImpl.create(key, AttributeType.VALUE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,15 @@ public enum AttributeType {
STRING_ARRAY,
BOOLEAN_ARRAY,
LONG_ARRAY,
DOUBLE_ARRAY
DOUBLE_ARRAY,
/**
* Simple attributes ({@link AttributeType#STRING}, {@link AttributeType#LONG}, {@link
* AttributeType#DOUBLE}, {@link AttributeType#BOOLEAN}, {@link AttributeType#STRING_ARRAY},
* {@link AttributeType#LONG_ARRAY}, {@link AttributeType#DOUBLE_ARRAY}, {@link
* AttributeType#BOOLEAN_ARRAY}) SHOULD be used whenever possible. Instrumentations SHOULD assume
* that backends do not index individual properties of complex attributes, that querying or
* aggregating on such properties is inefficient and complicated, and that reporting complex
* attributes carries higher performance overhead.
*/
VALUE
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,57 @@
@Immutable
public interface Attributes {

/** Returns the value for the given {@link AttributeKey}, or {@code null} if not found. */
/**
* Returns the value for the given {@link AttributeKey}, or {@code null} if not found.
*
* <p>Note: this method will automatically return the corresponding {@link Value} instance when
* passed a key of type {@link AttributeType#VALUE} and a simple attribute is found. This is the
* inverse of {@link AttributesBuilder#put(AttributeKey, Object)} when the key is {@link
* AttributeType#VALUE}.
*
* <ul>
* <li>If {@code put(AttributeKey.stringKey("key"), "a")} was called, then {@code
* get(AttributeKey.valueKey("key"))} returns {@code Value.of("a")}.
* <li>If {@code put(AttributeKey.longKey("key"), 1L)} was called, then {@code
* get(AttributeKey.valueKey("key"))} returns {@code Value.of(1L)}.
* <li>If {@code put(AttributeKey.doubleKey("key"), 1.0)} was called, then {@code
* get(AttributeKey.valueKey("key"))} returns {@code Value.of(1.0)}.
* <li>If {@code put(AttributeKey.booleanKey("key"), true)} was called, then {@code
* get(AttributeKey.valueKey("key"))} returns {@code Value.of(true)}.
* <li>If {@code put(AttributeKey.stringArrayKey("key"), Arrays.asList("a", "b"))} was called,
* then {@code get(AttributeKey.valueKey("key"))} returns {@code Value.of(Value.of("a"),
* Value.of("b"))}.
* <li>If {@code put(AttributeKey.longArrayKey("key"), Arrays.asList(1L, 2L))} was called, then
* {@code get(AttributeKey.valueKey("key"))} returns {@code Value.of(Value.of(1L),
* Value.of(2L))}.
* <li>If {@code put(AttributeKey.doubleArrayKey("key"), Arrays.asList(1.0, 2.0))} was called,
* then {@code get(AttributeKey.valueKey("key"))} returns {@code Value.of(Value.of(1.0),
* Value.of(2.0))}.
* <li>If {@code put(AttributeKey.booleanArrayKey("key"), Arrays.asList(true, false))} was
* called, then {@code get(AttributeKey.valueKey("key"))} returns {@code
* Value.of(Value.of(true), Value.of(false))}.
* </ul>
*
* Further, if {@code put(AttributeKey.valueKey("key"), Value.of(emptyList()))} was called, then
*
* <ul>
* <li>{@code get(AttributeKey.stringArrayKey("key"))}
* <li>{@code get(AttributeKey.longArrayKey("key"))}
* <li>{@code get(AttributeKey.booleanArrayKey("key"))}
* <li>{@code get(AttributeKey.doubleArrayKey("key"))}
* </ul>
*
* all return an empty list (as opposed to {@code null}).
*/
@Nullable
<T> T get(AttributeKey<T> key);

/** Iterates over all the key-value pairs of attributes contained by this instance. */
/**
* Iterates over all the key-value pairs of attributes contained by this instance.
*
* <p>Note: {@link AttributeType#VALUE} attributes will be represented as simple attributes if
* possible. See {@link AttributesBuilder#put(AttributeKey, Object)} for more details.
*/
void forEach(BiConsumer<? super AttributeKey<?>, ? super Object> consumer);

/** The number of attributes contained in this. */
Expand All @@ -46,7 +92,12 @@ public interface Attributes {
/** Whether there are any attributes contained in this. */
boolean isEmpty();

/** Returns a read-only view of this {@link Attributes} as a {@link Map}. */
/**
* Returns a read-only view of this {@link Attributes} as a {@link Map}.
*
* <p>Note: {@link AttributeType#VALUE} attributes will be represented as simple attributes in
* this map if possible. See {@link AttributesBuilder#put(AttributeKey, Object)} for more details.
*/
Map<AttributeKey<?>, Object> asMap();

/** Returns a {@link Attributes} instance with no attributes. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,40 @@ public interface AttributesBuilder {
/**
* Puts an {@link AttributeKey} with an associated value into this if the value is non-null.
* Providing a null value does not remove or unset previously set values.
*
* <p>Simple attributes ({@link AttributeType#STRING}, {@link AttributeType#LONG}, {@link
* AttributeType#DOUBLE}, {@link AttributeType#BOOLEAN}, {@link AttributeType#STRING_ARRAY},
* {@link AttributeType#LONG_ARRAY}, {@link AttributeType#DOUBLE_ARRAY}, {@link
* AttributeType#BOOLEAN_ARRAY}) SHOULD be used whenever possible. Instrumentations SHOULD assume
* that backends do not index individual properties of complex attributes, that querying or
* aggregating on such properties is inefficient and complicated, and that reporting complex
* attributes carries higher performance overhead.
*
* <p>Note: This method will automatically convert complex attributes ({@link
* AttributeType#VALUE}) to simple attributes when possible.
*
* <ul>
* <li>Calling {@code put(AttributeKey.valueKey("key"), Value.of("a"))} is equivalent to calling
* {@code put(AttributeKey.stringKey("key"), "a")}.
* <li>Calling {@code put(AttributeKey.valueKey("key"), Value.of(1L))} is equivalent to calling
* {@code put(AttributeKey.longKey("key"), 1L)}.
* <li>Calling {@code put(AttributeKey.valueKey("key"), Value.of(1.0))} is equivalent to calling
* {@code put(AttributeKey.doubleKey("key"), 1.0)}.
* <li>Calling {@code put(AttributeKey.valueKey("key"), Value.of(true))} is equivalent to
* calling {@code put(AttributeKey.booleanKey("key"), true)}.
* <li>Calling {@code put(AttributeKey.valueKey("key"), Value.of(Value.of("a"), Value.of("b")))}
* is equivalent to calling {@code put(AttributeKey.stringArrayKey("key"),
* Arrays.asList("a", "b"))}.
* <li>Calling {@code put(AttributeKey.valueKey("key"), Value.of(Value.of(1L), Value.of(2L)))}
* is equivalent to calling {@code put(AttributeKey.longArrayKey("key"), Arrays.asList(1L,
* 2L))}.
* <li>Calling {@code put(AttributeKey.valueKey("key"), Value.of(Value.of(1.0), Value.of(2.0)))}
* is equivalent to calling {@code put(AttributeKey.doubleArrayKey("key"),
* Arrays.asList(1.0, 2.0))}.
* <li>Calling {@code put(AttributeKey.valueKey("key"), Value.of(Value.of(true),
* Value.of(false)))} is equivalent to calling {@code
* put(AttributeKey.booleanArrayKey("key"), Arrays.asList(true, false))}.
* </ul>
*/
<T> AttributesBuilder put(AttributeKey<T> key, @Nullable T value);

Expand Down
Loading