Skip to content

Commit

Permalink
Stabilize log any value (#6591)
Browse files Browse the repository at this point in the history
  • Loading branch information
jack-berg authored Aug 30, 2024
1 parent d37c1c7 commit 649f963
Show file tree
Hide file tree
Showing 65 changed files with 1,185 additions and 1,156 deletions.
25 changes: 25 additions & 0 deletions api/all/src/main/java/io/opentelemetry/api/common/KeyValue.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.api.common;

/**
* Key-value pair of {@link String} key and {@link Value} value.
*
* @see Value#of(KeyValue...)
*/
public interface KeyValue {

/** Returns a {@link KeyValue} for the given {@code key} and {@code value}. */
static KeyValue of(String key, Value<?> value) {
return KeyValueImpl.create(key, value);
}

/** Returns the key. */
String getKey();

/** Returns the value. */
Value<?> getValue();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.api.common;

import com.google.auto.value.AutoValue;

@AutoValue
abstract class KeyValueImpl implements KeyValue {

KeyValueImpl() {}

static KeyValueImpl create(String key, Value<?> value) {
return new AutoValue_KeyValueImpl(key, value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.api.common;

import static java.util.stream.Collectors.joining;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;

final class KeyValueList implements Value<List<KeyValue>> {

private final List<KeyValue> value;

private KeyValueList(List<KeyValue> value) {
this.value = value;
}

static Value<List<KeyValue>> create(KeyValue... value) {
Objects.requireNonNull(value, "value must not be null");
List<KeyValue> list = new ArrayList<>(value.length);
list.addAll(Arrays.asList(value));
return new KeyValueList(Collections.unmodifiableList(list));
}

static Value<List<KeyValue>> createFromMap(Map<String, Value<?>> value) {
Objects.requireNonNull(value, "value must not be null");
KeyValue[] array =
value.entrySet().stream()
.map(entry -> KeyValue.of(entry.getKey(), entry.getValue()))
.toArray(KeyValue[]::new);
return create(array);
}

@Override
public ValueType getType() {
return ValueType.KEY_VALUE_LIST;
}

@Override
public List<KeyValue> getValue() {
return value;
}

@Override
public String asString() {
return value.stream()
.map(item -> item.getKey() + "=" + item.getValue().asString())
.collect(joining(", ", "[", "]"));
}

@Override
public String toString() {
return "KeyValueList{" + asString() + "}";
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
return (o instanceof Value) && Objects.equals(this.value, ((Value<?>) o).getValue());
}

@Override
public int hashCode() {
return value.hashCode();
}
}
117 changes: 117 additions & 0 deletions api/all/src/main/java/io/opentelemetry/api/common/Value.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.api.common;

import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;

/**
* Value mirrors the proto <a
* href="https://github.com/open-telemetry/opentelemetry-proto/blob/ac3242b03157295e4ee9e616af53b81517b06559/opentelemetry/proto/common/v1/common.proto#L28">AnyValue</a>
* message type, and is used to model any type.
*
* <p>It can be used to represent:
*
* <ul>
* <li>Primitive values via {@link #of(long)}, {@link #of(String)}, {@link #of(boolean)}, {@link
* #of(double)}.
* <li>String-keyed maps (i.e. associative arrays, dictionaries) via {@link #of(KeyValue...)},
* {@link #of(Map)}. Note, because map values are type {@link Value}, maps can be nested
* within other maps.
* <li>Arrays (heterogeneous or homogenous) via {@link #of(Value[])}. Note, because array values
* are type {@link Value}, arrays can contain primitives, complex types like maps or arrays,
* or any combination.
* <li>Raw bytes via {@link #of(byte[])}
* </ul>
*
* <p>Currently, Value is only used as an argument for {@link
* io.opentelemetry.api.logs.LogRecordBuilder#setBody(Value)}.
*
* @param <T> the type. See {@link #getValue()} for description of types.
*/
public interface Value<T> {

/** Returns an {@link Value} for the {@link String} value. */
static Value<String> of(String value) {
return ValueString.create(value);
}

/** Returns an {@link Value} for the {@code boolean} value. */
static Value<Boolean> of(boolean value) {
return ValueBoolean.create(value);
}

/** Returns an {@link Value} for the {@code long} value. */
static Value<Long> of(long value) {
return ValueLong.create(value);
}

/** Returns an {@link Value} for the {@code double} value. */
static Value<Double> of(double value) {
return ValueDouble.create(value);
}

/** Returns an {@link Value} for the {@code byte[]} value. */
static Value<ByteBuffer> of(byte[] value) {
return ValueBytes.create(value);
}

/** Returns an {@link Value} for the array of {@link Value} values. */
static Value<List<Value<?>>> of(Value<?>... value) {
return ValueArray.create(value);
}

/** Returns an {@link Value} for the list of {@link Value} values. */
static Value<List<Value<?>>> of(List<Value<?>> value) {
return ValueArray.create(value);
}

/**
* Returns an {@link Value} for the array of {@link KeyValue} values. {@link KeyValue#getKey()}
* values should not repeat - duplicates may be dropped.
*/
static Value<List<KeyValue>> of(KeyValue... value) {
return KeyValueList.create(value);
}

/** Returns an {@link Value} for the {@link Map} of key, {@link Value}. */
static Value<List<KeyValue>> of(Map<String, Value<?>> value) {
return KeyValueList.createFromMap(value);
}

/** Returns the type of this {@link Value}. Useful for building switch statements. */
ValueType getType();

/**
* Returns the value for this {@link Value}.
*
* <p>The return type varies by {@link #getType()} as described below:
*
* <ul>
* <li>{@link ValueType#STRING} returns {@link String}
* <li>{@link ValueType#BOOLEAN} returns {@code boolean}
* <li>{@link ValueType#LONG} returns {@code long}
* <li>{@link ValueType#DOUBLE} returns {@code double}
* <li>{@link ValueType#ARRAY} returns {@link List} of {@link Value}
* <li>{@link ValueType#KEY_VALUE_LIST} returns {@link List} of {@link KeyValue}
* <li>{@link ValueType#BYTES} returns read only {@link ByteBuffer}. See {@link
* ByteBuffer#asReadOnlyBuffer()}.
* </ul>
*/
T getValue();

/**
* Return a string encoding of this {@link Value}. This is intended to be a fallback serialized
* representation in case there is no suitable encoding that can utilize {@link #getType()} /
* {@link #getValue()} to serialize specific types.
*
* <p>WARNING: No guarantees are made about the encoding of this string response. It MAY change in
* a future minor release. If you need a reliable string encoding, write your own serializer.
*/
// TODO(jack-berg): Should this be a JSON encoding?
String asString();
}
67 changes: 67 additions & 0 deletions api/all/src/main/java/io/opentelemetry/api/common/ValueArray.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.api.common;

import static java.util.stream.Collectors.joining;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

final class ValueArray implements Value<List<Value<?>>> {

private final List<Value<?>> value;

private ValueArray(List<Value<?>> value) {
this.value = value;
}

static Value<List<Value<?>>> create(Value<?>... value) {
Objects.requireNonNull(value, "value must not be null");
List<Value<?>> list = new ArrayList<>(value.length);
list.addAll(Arrays.asList(value));
return new ValueArray(Collections.unmodifiableList(list));
}

static Value<List<Value<?>>> create(List<Value<?>> value) {
return new ValueArray(Collections.unmodifiableList(value));
}

@Override
public ValueType getType() {
return ValueType.ARRAY;
}

@Override
public List<Value<?>> getValue() {
return value;
}

@Override
public String asString() {
return value.stream().map(Value::asString).collect(joining(", ", "[", "]"));
}

@Override
public String toString() {
return "ValueArray{" + asString() + "}";
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
return (o instanceof Value) && Objects.equals(this.value, ((Value<?>) o).getValue());
}

@Override
public int hashCode() {
return value.hashCode();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,25 @@
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.api.incubator.logs;
package io.opentelemetry.api.common;

import java.util.Objects;

final class AnyValueBoolean implements AnyValue<Boolean> {
final class ValueBoolean implements Value<Boolean> {

private final boolean value;

private AnyValueBoolean(boolean value) {
private ValueBoolean(boolean value) {
this.value = value;
}

static AnyValue<Boolean> create(boolean value) {
return new AnyValueBoolean(value);
static Value<Boolean> create(boolean value) {
return new ValueBoolean(value);
}

@Override
public AnyValueType getType() {
return AnyValueType.BOOLEAN;
public ValueType getType() {
return ValueType.BOOLEAN;
}

@Override
Expand All @@ -36,15 +36,15 @@ public String asString() {

@Override
public String toString() {
return "AnyValueBoolean{" + asString() + "}";
return "ValueBoolean{" + asString() + "}";
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
return (o instanceof AnyValue) && Objects.equals(this.value, ((AnyValue<?>) o).getValue());
return (o instanceof Value) && Objects.equals(this.value, ((Value<?>) o).getValue());
}

@Override
Expand Down
Loading

0 comments on commit 649f963

Please sign in to comment.