Clarify that AttributesBuilder.put allows nulls (#7271)

This commit is contained in:
Tyler Benson 2025-04-16 12:08:03 -04:00 committed by GitHub
parent 14e2fefe7a
commit d13f04d084
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 44 additions and 25 deletions

View File

@ -9,6 +9,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import javax.annotation.Nullable;
class ArrayBackedAttributesBuilder implements AttributesBuilder {
private final List<Object> data;
@ -37,7 +38,7 @@ class ArrayBackedAttributesBuilder implements AttributesBuilder {
}
@Override
public <T> AttributesBuilder put(AttributeKey<T> key, T value) {
public <T> AttributesBuilder put(AttributeKey<T> key, @Nullable T value) {
if (key == null || key.getKey().isEmpty() || value == null) {
return this;
}

View File

@ -18,6 +18,7 @@ import static io.opentelemetry.api.common.AttributeKey.stringKey;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import javax.annotation.Nullable;
/** A builder of {@link Attributes} supporting an arbitrary number of key-value pairs. */
public interface AttributesBuilder {
@ -35,18 +36,22 @@ public interface AttributesBuilder {
// version.
<T> AttributesBuilder put(AttributeKey<Long> key, int value);
/** Puts a {@link AttributeKey} with associated value into this. */
<T> AttributesBuilder put(AttributeKey<T> key, T value);
/**
* 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.
*/
<T> AttributesBuilder put(AttributeKey<T> key, @Nullable T value);
/**
* Puts a String attribute into this.
* Puts a String attribute into this if the value is non-null. Providing a null value does not
* remove or unset previously set values.
*
* <p>Note: It is strongly recommended to use {@link #put(AttributeKey, Object)}, and pre-allocate
* your keys, if possible.
*
* @return this Builder
*/
default AttributesBuilder put(String key, String value) {
default AttributesBuilder put(String key, @Nullable String value) {
return put(stringKey(key), value);
}

View File

@ -10,6 +10,7 @@ import io.opentelemetry.api.common.Value;
import io.opentelemetry.context.Context;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
class DefaultLogger implements Logger {
@ -77,7 +78,7 @@ class DefaultLogger implements Logger {
}
@Override
public <T> LogRecordBuilder setAttribute(AttributeKey<T> key, T value) {
public <T> LogRecordBuilder setAttribute(AttributeKey<T> key, @Nullable T value) {
return this;
}

View File

@ -16,6 +16,7 @@ import io.opentelemetry.api.common.Value;
import io.opentelemetry.context.Context;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
/**
* Used to construct and emit log records from a {@link Logger}.
@ -107,16 +108,20 @@ public interface LogRecordBuilder {
* Sets an 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.
*
* <p>Note: Providing a null value is a no-op and will not remove previously set values.
*
* @param key the key for this attribute.
* @param value the value for this attribute.
* @return this.
*/
<T> LogRecordBuilder setAttribute(AttributeKey<T> key, T value);
<T> LogRecordBuilder setAttribute(AttributeKey<T> key, @Nullable T value);
/**
* Sets a String 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.
*
* <p>Note: Providing a null value is a no-op and will not remove previously set values.
*
* <p>Note: It is strongly recommended to use {@link #setAttribute(AttributeKey, Object)}, and
* pre-allocate your keys, if possible.
*
@ -125,7 +130,7 @@ public interface LogRecordBuilder {
* @return this.
* @since 1.48.0
*/
default LogRecordBuilder setAttribute(String key, String value) {
default LogRecordBuilder setAttribute(String key, @Nullable String value) {
return setAttribute(stringKey(key), value);
}

View File

@ -8,6 +8,7 @@ package io.opentelemetry.api.trace;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
/**
@ -42,7 +43,7 @@ final class PropagatedSpan implements Span {
}
@Override
public Span setAttribute(String key, String value) {
public Span setAttribute(String key, @Nullable String value) {
return this;
}
@ -62,7 +63,7 @@ final class PropagatedSpan implements Span {
}
@Override
public <T> Span setAttribute(AttributeKey<T> key, T value) {
public <T> Span setAttribute(AttributeKey<T> key, @Nullable T value) {
return this;
}

View File

@ -88,7 +88,9 @@ public interface Span extends ImplicitContextKeyed {
* 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.
*
* <p>Empty String "" and null are valid attribute {@code value}, but not valid keys.
* <p>Empty String "" and null are valid attribute {@code value}s, but not valid keys.
*
* <p>Note: Providing a null value is a no-op and will not remove previously set values.
*
* <p>Note: It is strongly recommended to use {@link #setAttribute(AttributeKey, Object)}, and
* pre-allocate your keys, if possible.
@ -97,7 +99,7 @@ public interface Span extends ImplicitContextKeyed {
* @param value the value for this attribute.
* @return this.
*/
default Span setAttribute(String key, String value) {
default Span setAttribute(String key, @Nullable String value) {
return setAttribute(AttributeKey.stringKey(key), value);
}
@ -150,13 +152,13 @@ public interface Span extends ImplicitContextKeyed {
* 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.
*
* <p>Note: the behavior of null values is undefined, and hence strongly discouraged.
* <p>Note: Providing a null value is a no-op.
*
* @param key the key for this attribute.
* @param value the value for this attribute.
* @return this.
*/
<T> Span setAttribute(AttributeKey<T> key, T value);
<T> Span setAttribute(AttributeKey<T> key, @Nullable T value);
/**
* Sets an attribute to the {@code Span}. If the {@code Span} previously contained a mapping for

View File

@ -26,6 +26,7 @@ import java.util.LinkedHashMap;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Nullable;
import org.junit.jupiter.api.Test;
/** Unit tests for {@link Attributes}s. */
@ -565,7 +566,7 @@ class AttributesTest {
}
@Override
public <T> AttributesBuilder put(AttributeKey<T> key, T value) {
public <T> AttributesBuilder put(AttributeKey<T> key, @Nullable T value) {
return null;
}

View File

@ -13,6 +13,7 @@ import io.opentelemetry.api.logs.Severity;
import io.opentelemetry.context.Context;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
class ExtendedDefaultLogger implements ExtendedLogger {
@ -51,7 +52,7 @@ class ExtendedDefaultLogger implements ExtendedLogger {
}
@Override
public <T> ExtendedLogRecordBuilder setAttribute(AttributeKey<T> key, T value) {
public <T> ExtendedLogRecordBuilder setAttribute(AttributeKey<T> key, @Nullable T value) {
return this;
}

View File

@ -15,6 +15,7 @@ import io.opentelemetry.api.logs.Severity;
import io.opentelemetry.context.Context;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
/** Extended {@link LogRecordBuilder} with experimental APIs. */
public interface ExtendedLogRecordBuilder extends LogRecordBuilder {
@ -110,7 +111,7 @@ public interface ExtendedLogRecordBuilder extends LogRecordBuilder {
* attribute APIs.
*/
@Override
<T> ExtendedLogRecordBuilder setAttribute(AttributeKey<T> key, T value);
<T> ExtendedLogRecordBuilder setAttribute(AttributeKey<T> key, @Nullable T value);
/**
* Set an attribute.

View File

@ -15,6 +15,7 @@ import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
/**
* Delegates <i>all</i> {@link Span} methods to some underlying Span via {@link
@ -52,12 +53,12 @@ interface DelegatingSpan extends Span {
}
@Override
default <T> Span setAttribute(AttributeKey<T> key, T value) {
default <T> Span setAttribute(AttributeKey<T> key, @Nullable T value) {
return getDelegate().setAttribute(key, value);
}
@Override
default Span setAttribute(String key, String value) {
default Span setAttribute(String key, @Nullable String value) {
return getDelegate().setAttribute(key, value);
}

View File

@ -37,7 +37,7 @@ import io.opentelemetry.api.trace.StatusCode;
import java.util.EnumSet;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
final class OpenTelemetryNoRecordEventsSpanImpl extends Span
implements io.opentelemetry.api.trace.Span {
@ -110,7 +110,7 @@ final class OpenTelemetryNoRecordEventsSpanImpl extends Span
}
@Override
public io.opentelemetry.api.trace.Span setAttribute(String key, @Nonnull String value) {
public io.opentelemetry.api.trace.Span setAttribute(String key, @Nullable String value) {
return this;
}
@ -130,7 +130,7 @@ final class OpenTelemetryNoRecordEventsSpanImpl extends Span
}
@Override
public <T> io.opentelemetry.api.trace.Span setAttribute(AttributeKey<T> key, @Nonnull T value) {
public <T> io.opentelemetry.api.trace.Span setAttribute(AttributeKey<T> key, @Nullable T value) {
return this;
}

View File

@ -117,7 +117,7 @@ final class ExtendedSdkLogRecordBuilder extends SdkLogRecordBuilder
}
@Override
public <T> ExtendedSdkLogRecordBuilder setAttribute(AttributeKey<T> key, T value) {
public <T> ExtendedSdkLogRecordBuilder setAttribute(AttributeKey<T> key, @Nullable T value) {
if (key == null || key.getKey().isEmpty() || value == null) {
return this;
}

View File

@ -95,7 +95,7 @@ class SdkLogRecordBuilder implements LogRecordBuilder {
}
@Override
public <T> SdkLogRecordBuilder setAttribute(AttributeKey<T> key, T value) {
public <T> SdkLogRecordBuilder setAttribute(AttributeKey<T> key, @Nullable T value) {
if (key == null || key.getKey().isEmpty() || value == null) {
return this;
}

View File

@ -314,7 +314,7 @@ final class SdkSpan implements ReadWriteSpan {
}
@Override
public <T> ReadWriteSpan setAttribute(AttributeKey<T> key, T value) {
public <T> ReadWriteSpan setAttribute(AttributeKey<T> key, @Nullable T value) {
if (key == null || key.getKey().isEmpty() || value == null) {
return this;
}