diff --git a/api/all/src/main/java/io/opentelemetry/api/logs/LogRecordBuilder.java b/api/all/src/main/java/io/opentelemetry/api/logs/LogRecordBuilder.java
index 21feb4d87ce..31c5fc07cb9 100644
--- a/api/all/src/main/java/io/opentelemetry/api/logs/LogRecordBuilder.java
+++ b/api/all/src/main/java/io/opentelemetry/api/logs/LogRecordBuilder.java
@@ -196,6 +196,21 @@ default LogRecordBuilder setAttribute(String key, int value) {
return setAttribute(key, (long) value);
}
+ /**
+ * Sets a {@link Value} attribute on the {@code LogRecord}. If the {@code LogRecord} previously
+ * contained a mapping for the key, the old value is replaced by the specified value.
+ *
+ *
Note: It is strongly recommended to use {@link #setAttribute(AttributeKey, Object)}, and
+ * pre-allocate your keys, if possible.
+ *
+ * @param key the key for this attribute.
+ * @param value the value for this attribute.
+ * @return this.
+ */
+ default LogRecordBuilder setAttribute(String key, Value> value) {
+ return setAttribute(AttributeKey.valueKey(key), value);
+ }
+
/**
* Sets the event name, which identifies the class / type of the Event.
*
diff --git a/api/all/src/main/java/io/opentelemetry/api/trace/Span.java b/api/all/src/main/java/io/opentelemetry/api/trace/Span.java
index 708bb1de077..39447b35be9 100644
--- a/api/all/src/main/java/io/opentelemetry/api/trace/Span.java
+++ b/api/all/src/main/java/io/opentelemetry/api/trace/Span.java
@@ -10,6 +10,7 @@
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.common.Value;
import io.opentelemetry.api.internal.ApiUsageLogger;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.ImplicitContextKeyed;
@@ -148,6 +149,21 @@ default Span setAttribute(String key, boolean value) {
return setAttribute(AttributeKey.booleanKey(key), value);
}
+ /**
+ * Sets a {@link Value} attribute on the {@code Span}. If the {@code Span} previously contained a
+ * mapping for the key, the old value is replaced by the specified value.
+ *
+ *
Note: It is strongly recommended to use {@link #setAttribute(AttributeKey, Object)}, and
+ * pre-allocate your keys, if possible.
+ *
+ * @param key the key for this attribute.
+ * @param value the value for this attribute.
+ * @return this.
+ */
+ default Span setAttribute(String key, Value> value) {
+ return setAttribute(AttributeKey.valueKey(key), value);
+ }
+
/**
* Sets an attribute to the {@code Span}. If the {@code Span} previously contained a mapping for
* the key, the old value is replaced by the specified value.
diff --git a/api/all/src/test/java/io/opentelemetry/api/trace/PropagatedSpanTest.java b/api/all/src/test/java/io/opentelemetry/api/trace/PropagatedSpanTest.java
index 7c3807775c7..ea33c957b42 100644
--- a/api/all/src/test/java/io/opentelemetry/api/trace/PropagatedSpanTest.java
+++ b/api/all/src/test/java/io/opentelemetry/api/trace/PropagatedSpanTest.java
@@ -15,6 +15,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.common.Value;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Test;
@@ -40,16 +41,17 @@ void doNotCrash() {
span.setAttribute(booleanKey("MyBooleanAttributeKey"), true);
span.setAttribute(longKey("MyLongAttributeKey"), 123L);
span.setAttribute(longKey("MyLongAttributeKey"), 123);
- span.setAttribute("NullString", null);
+ span.setAttribute("NullString", (String) null);
span.setAttribute("EmptyString", "");
span.setAttribute("long", 1);
span.setAttribute("double", 1.0);
span.setAttribute("boolean", true);
+ span.setAttribute("value", Value.of("val"));
span.setAttribute(stringArrayKey("NullArrayString"), null);
span.setAttribute(booleanArrayKey("NullArrayBoolean"), null);
span.setAttribute(longArrayKey("NullArrayLong"), null);
span.setAttribute(doubleArrayKey("NullArrayDouble"), null);
- span.setAttribute((String) null, null);
+ span.setAttribute((String) null, (String) null);
span.setAllAttributes(null);
span.setAllAttributes(Attributes.empty());
span.setAllAttributes(
diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-api.txt b/docs/apidiffs/current_vs_latest/opentelemetry-api.txt
index b9f67186813..07f0f56142c 100644
--- a/docs/apidiffs/current_vs_latest/opentelemetry-api.txt
+++ b/docs/apidiffs/current_vs_latest/opentelemetry-api.txt
@@ -3,6 +3,9 @@ Comparing source compatibility of opentelemetry-api-1.61.0-SNAPSHOT.jar against
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) boolean isEnabled(io.opentelemetry.api.logs.Severity, io.opentelemetry.context.Context)
+++ NEW METHOD: PUBLIC(+) boolean isEnabled(io.opentelemetry.api.logs.Severity)
+*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.api.logs.LogRecordBuilder (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+ +++ NEW METHOD: PUBLIC(+) io.opentelemetry.api.logs.LogRecordBuilder setAttribute(java.lang.String, io.opentelemetry.api.common.Value>)
*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.api.metrics.DoubleCounter (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) boolean isEnabled()
@@ -27,6 +30,9 @@ Comparing source compatibility of opentelemetry-api-1.61.0-SNAPSHOT.jar against
*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.api.metrics.LongUpDownCounter (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) boolean isEnabled()
+*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.api.trace.Span (not serializable)
+ === CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+ +++ NEW METHOD: PUBLIC(+) io.opentelemetry.api.trace.Span setAttribute(java.lang.String, io.opentelemetry.api.common.Value>)
*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.api.trace.Tracer (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) boolean isEnabled()
diff --git a/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/DelegatingSpan.java b/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/DelegatingSpan.java
index ad1f624795a..254fca4830b 100644
--- a/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/DelegatingSpan.java
+++ b/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/DelegatingSpan.java
@@ -8,6 +8,7 @@
import com.google.errorprone.annotations.MustBeClosed;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.common.Value;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.api.trace.StatusCode;
@@ -77,6 +78,11 @@ default Span setAttribute(String key, boolean value) {
return getDelegate().setAttribute(key, value);
}
+ @Override
+ default Span setAttribute(String key, Value> value) {
+ return getDelegate().setAttribute(key, value);
+ }
+
@Override
default Span setAttribute(AttributeKey key, int value) {
return getDelegate().setAttribute(key, value);
diff --git a/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenTelemetryNoRecordEventsSpanImpl.java b/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenTelemetryNoRecordEventsSpanImpl.java
index a1e48f5eb40..8ec2fc6296e 100644
--- a/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenTelemetryNoRecordEventsSpanImpl.java
+++ b/opencensus-shim/src/main/java/io/opentelemetry/opencensusshim/OpenTelemetryNoRecordEventsSpanImpl.java
@@ -33,6 +33,7 @@
import io.opencensus.trace.Status;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.common.Value;
import io.opentelemetry.api.trace.StatusCode;
import java.util.EnumSet;
import java.util.Map;
@@ -129,6 +130,11 @@ public io.opentelemetry.api.trace.Span setAttribute(String key, boolean value) {
return this;
}
+ @Override
+ public io.opentelemetry.api.trace.Span setAttribute(String key, Value> value) {
+ return this;
+ }
+
@Override
public io.opentelemetry.api.trace.Span setAttribute(AttributeKey key, @Nullable T value) {
return this;
diff --git a/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/DelegatingSpanTest.java b/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/DelegatingSpanTest.java
index 2843ed89061..55bb1a58d82 100644
--- a/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/DelegatingSpanTest.java
+++ b/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/DelegatingSpanTest.java
@@ -10,6 +10,7 @@
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.common.Value;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.api.trace.StatusCode;
@@ -95,6 +96,7 @@ static Stream delegateMethodsProvider() {
Arguments.of("setAttribute", new Class>[] {String.class, long.class}, times(1)),
Arguments.of("setAttribute", new Class>[] {String.class, double.class}, times(1)),
Arguments.of("setAttribute", new Class>[] {String.class, boolean.class}, times(1)),
+ Arguments.of("setAttribute", new Class>[] {String.class, Value.class}, times(1)),
Arguments.of(
"recordException", new Class>[] {Throwable.class, Attributes.class}, times(1)),
Arguments.of("recordException", new Class>[] {Throwable.class}, times(1)),
diff --git a/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/OpenTelemetryNoRecordEventsSpanImplTest.java b/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/OpenTelemetryNoRecordEventsSpanImplTest.java
index 8f6d67e5e36..9a14ad5fc15 100644
--- a/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/OpenTelemetryNoRecordEventsSpanImplTest.java
+++ b/opencensus-shim/src/test/java/io/opentelemetry/opencensusshim/OpenTelemetryNoRecordEventsSpanImplTest.java
@@ -38,6 +38,7 @@
import io.opencensus.trace.Tracestate;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.common.Value;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
@@ -93,6 +94,7 @@ public void doNotCrash() {
noRecordEventsSpan.setAttribute("OTelAttributeKeyLong", 123);
noRecordEventsSpan.setAttribute("OTelAttributeKeyDouble", 123.45);
noRecordEventsSpan.setAttribute("OTelAttributeKeyBoolean", true);
+ noRecordEventsSpan.setAttribute("OTelAttributeKeyValue", Value.empty());
noRecordEventsSpan.addEvent("OTel event 1");
noRecordEventsSpan.addEvent("OTel event 2", 29922310, TimeUnit.HOURS);
noRecordEventsSpan.addEvent(
diff --git a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilderTest.java b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilderTest.java
index 54f2d15199f..a89426c5363 100644
--- a/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilderTest.java
+++ b/sdk/logs/src/test/java/io/opentelemetry/sdk/logs/SdkLogRecordBuilderTest.java
@@ -9,6 +9,7 @@
import static io.opentelemetry.api.common.AttributeKey.doubleKey;
import static io.opentelemetry.api.common.AttributeKey.longKey;
import static io.opentelemetry.api.common.AttributeKey.stringKey;
+import static io.opentelemetry.api.common.AttributeKey.valueKey;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static org.mockito.ArgumentMatchers.eq;
@@ -160,6 +161,7 @@ void testConvenienceAttributeMethods() {
.setAttribute("dk", 12.123)
.setAttribute("bk", true)
.setAttribute("ik", 13)
+ .setAttribute("vk", Value.of(new byte[] {1, 2, 3}))
.emit();
assertThat(emittedLog.get().toLogRecordData())
.hasAttributesSatisfyingExactly(
@@ -167,7 +169,8 @@ void testConvenienceAttributeMethods() {
equalTo(longKey("lk"), 12L),
equalTo(doubleKey("dk"), 12.123),
equalTo(booleanKey("bk"), true),
- equalTo(longKey("ik"), 13L));
+ equalTo(longKey("ik"), 13L),
+ equalTo(valueKey("vk"), Value.of(new byte[] {1, 2, 3})));
}
@Test
diff --git a/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/SdkSpanBuilderTest.java b/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/SdkSpanBuilderTest.java
index 55eb81d0b20..c4615675b05 100644
--- a/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/SdkSpanBuilderTest.java
+++ b/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/SdkSpanBuilderTest.java
@@ -391,7 +391,7 @@ void setAttribute_nullAttributeValue_afterEnd() {
SdkSpan span = (SdkSpan) spanBuilder.startSpan();
assertThat(span.toSpanData().getAttributes().size()).isEqualTo(10);
span.end();
- span.setAttribute("emptyString", null);
+ span.setAttribute("emptyString", (String) null);
span.setAttribute(stringKey("emptyStringAttributeValue"), null);
span.setAttribute(longKey("longAttribute"), null);
span.setAttribute(booleanKey("boolAttribute"), null);
diff --git a/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/SdkSpanTest.java b/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/SdkSpanTest.java
index 12e35475a8f..207bcaebf07 100644
--- a/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/SdkSpanTest.java
+++ b/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/SdkSpanTest.java
@@ -548,7 +548,7 @@ void setAttribute() {
SdkSpan span = createTestRootSpan();
try {
span.setAttribute("StringKey", "StringVal");
- span.setAttribute("NullStringKey", null);
+ span.setAttribute("NullStringKey", (String) null);
span.setAttribute("EmptyStringKey", "");
span.setAttribute(stringKey("NullStringAttributeValue"), null);
span.setAttribute(stringKey("EmptyStringAttributeValue"), "");
@@ -557,6 +557,7 @@ void setAttribute() {
span.setAttribute(longKey("LongKey3"), 6L);
span.setAttribute("DoubleKey", 10.0);
span.setAttribute("BooleanKey", false);
+ span.setAttribute("BytesValueKey", Value.of(new byte[] {1, 2, 3}));
span.setAttribute(
stringArrayKey("ArrayStringKey"), Arrays.asList("StringVal", null, "", "StringVal2"));
span.setAttribute(longArrayKey("ArrayLongKey"), Arrays.asList(1L, 2L, 3L, 4L, 5L));
@@ -579,7 +580,7 @@ void setAttribute() {
span.end();
}
SpanData spanData = span.toSpanData();
- assertThat(spanData.getAttributes().size()).isEqualTo(17);
+ assertThat(spanData.getAttributes().size()).isEqualTo(18);
assertThat(spanData.getAttributes().get(stringKey("StringKey"))).isNotNull();
assertThat(spanData.getAttributes().get(stringKey("EmptyStringKey"))).isNotNull();
assertThat(spanData.getAttributes().get(stringKey("EmptyStringAttributeValue"))).isNotNull();
@@ -588,6 +589,8 @@ void setAttribute() {
assertThat(spanData.getAttributes().get(longKey("LongKey3"))).isEqualTo(6L);
assertThat(spanData.getAttributes().get(doubleKey("DoubleKey"))).isNotNull();
assertThat(spanData.getAttributes().get(booleanKey("BooleanKey"))).isNotNull();
+ assertThat(spanData.getAttributes().get(valueKey("BytesValueKey")))
+ .isEqualTo(Value.of(new byte[] {1, 2, 3}));
assertThat(spanData.getAttributes().get(stringArrayKey("ArrayStringKey"))).isNotNull();
assertThat(spanData.getAttributes().get(longArrayKey("ArrayLongKey"))).isNotNull();
assertThat(spanData.getAttributes().get(doubleArrayKey("ArrayDoubleKey"))).isNotNull();
@@ -630,7 +633,7 @@ void setAttribute_nullKeys() {
span.setAttribute(null, Collections.emptyList());
span.setAttribute(null, Collections.emptyList());
span.setAttribute(null, Collections.emptyList());
- span.setAttribute(null, Value.empty());
+ span.setAttribute((AttributeKey>) null, Value.empty());
assertThat(span.toSpanData().getAttributes().size()).isZero();
}
@@ -658,7 +661,7 @@ void setAttribute_emptyArrayAttributeValue() {
@Test
void setAttribute_nullStringValue() {
SdkSpan span = createTestRootSpan();
- span.setAttribute("nullString", null);
+ span.setAttribute("nullString", (String) null);
span.setAttribute("emptyString", "");
span.setAttribute(stringKey("nullStringAttributeValue"), null);
span.setAttribute(stringKey("emptyStringAttributeValue"), "");