Skip to content

Commit

Permalink
Add Span#setAllAttributes method to add Attributes to a Span (#2799)
Browse files Browse the repository at this point in the history
  • Loading branch information
HaloFour authored Apr 27, 2021
1 parent f5c1e0d commit 7d31cdd
Show file tree
Hide file tree
Showing 8 changed files with 258 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ public <T> NoopSpanBuilder setAttribute(AttributeKey<T> key, T value) {
return this;
}

@Override
public NoopSpanBuilder setAllAttributes(Attributes attributes) {
return this;
}

@Override
public NoopSpanBuilder setSpanKind(SpanKind spanKind) {
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ public <T> Span setAttribute(AttributeKey<T> key, T value) {
return this;
}

@Override
public Span setAllAttributes(Attributes attributes) {
return this;
}

@Override
public Span addEvent(String name) {
return this;
Expand Down
17 changes: 17 additions & 0 deletions api/all/src/main/java/io/opentelemetry/api/trace/Span.java
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,23 @@ default Span setAttribute(AttributeKey<Long> key, int value) {
return setAttribute(key, (long) value);
}

/**
* Sets attributes to the {@link Span}. If the {@link Span} previously contained a mapping for any
* of the keys, the old values are replaced by the specified values.
*
* @param attributes the attributes
* @return this.
*/
@SuppressWarnings("unchecked")
default Span setAllAttributes(Attributes attributes) {
if (attributes == null || attributes.isEmpty()) {
return this;
}
attributes.forEach(
(attributeKey, value) -> this.setAttribute((AttributeKey<Object>) attributeKey, value));
return this;
}

/**
* Adds an event to the {@link Span}. The timestamp of the event will be the current time.
*
Expand Down
17 changes: 17 additions & 0 deletions api/all/src/main/java/io/opentelemetry/api/trace/SpanBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,23 @@ public interface SpanBuilder {
*/
<T> SpanBuilder setAttribute(AttributeKey<T> key, T value);

/**
* Sets attributes to the {@link SpanBuilder}. If the {@link SpanBuilder} previously contained a
* mapping for any of the keys, the old values are replaced by the specified values.
*
* @param attributes the attributes
* @return this.
*/
@SuppressWarnings("unchecked")
default SpanBuilder setAllAttributes(Attributes attributes) {
if (attributes == null || attributes.isEmpty()) {
return this;
}
attributes.forEach(
(attributeKey, value) -> setAttribute((AttributeKey<Object>) attributeKey, value));
return this;
}

/**
* Sets the {@link SpanKind} for the newly created {@code Span}. If not called, the implementation
* will provide a default value {@link SpanKind#INTERNAL}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ void doNotCrash() {
span.setAttribute(longArrayKey("NullArrayLong"), null);
span.setAttribute(doubleArrayKey("NullArrayDouble"), null);
span.setAttribute((String) null, null);
span.setAllAttributes(null);
span.setAllAttributes(Attributes.empty());
span.setAllAttributes(
Attributes.of(stringKey("MyStringAttributeKey"), "MyStringAttributeValue"));
span.addEvent("event");
span.addEvent("event", 0, TimeUnit.NANOSECONDS);
span.addEvent("event", Instant.EPOCH);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ void doNotCrash_NoopImplementation() {
spanBuilder.setAttribute("key", .12345);
spanBuilder.setAttribute("key", true);
spanBuilder.setAttribute(stringKey("key"), "value");
spanBuilder.setAllAttributes(Attributes.of(stringKey("key"), "value"));
spanBuilder.setAllAttributes(Attributes.empty());
spanBuilder.setAllAttributes(null);
spanBuilder.setStartTimestamp(12345L, TimeUnit.NANOSECONDS);
spanBuilder.setStartTimestamp(Instant.EPOCH);
spanBuilder.setStartTimestamp(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,118 @@ void setAttribute_nullAttributeValue() {
assertThat(span.toSpanData().getAttributes().size()).isEqualTo(9);
}

@Test
void setAllAttributes() {
RecordEventsReadableSpan span = createTestRootSpan();
Attributes attributes =
Attributes.builder()
.put("StringKey", "StringVal")
.put("NullStringKey", (String) null)
.put("EmptyStringKey", "")
.put(stringKey("NullStringAttributeValue"), null)
.put(stringKey("EmptyStringAttributeValue"), "")
.put("LongKey", 1000L)
.put(longKey("LongKey2"), 5)
.put(longKey("LongKey3"), 6L)
.put("DoubleKey", 10.0)
.put("BooleanKey", false)
.put(
stringArrayKey("ArrayStringKey"),
Arrays.asList("StringVal", null, "", "StringVal2"))
.put(longArrayKey("ArrayLongKey"), Arrays.asList(1L, 2L, 3L, 4L, 5L))
.put(doubleArrayKey("ArrayDoubleKey"), Arrays.asList(0.1, 2.3, 4.5, 6.7, 8.9))
.put(booleanArrayKey("ArrayBooleanKey"), Arrays.asList(true, false, false, true))
// These should be dropped
.put(stringArrayKey("NullArrayStringKey"), null)
.put(longArrayKey("NullArrayLongKey"), null)
.put(doubleArrayKey("NullArrayDoubleKey"), null)
.put(booleanArrayKey("NullArrayBooleanKey"), null)
// These should be maintained
.put(longArrayKey("ArrayWithNullLongKey"), Arrays.asList(new Long[] {null}))
.put(stringArrayKey("ArrayWithNullStringKey"), Arrays.asList(new String[] {null}))
.put(doubleArrayKey("ArrayWithNullDoubleKey"), Arrays.asList(new Double[] {null}))
.put(booleanArrayKey("ArrayWithNullBooleanKey"), Arrays.asList(new Boolean[] {null}))
.build();

try {
span.setAllAttributes(attributes);
} finally {
span.end();
}

SpanData spanData = span.toSpanData();
assertThat(spanData.getAttributes().size()).isEqualTo(16);
assertThat(spanData.getAttributes().get(stringKey("StringKey"))).isNotNull();
assertThat(spanData.getAttributes().get(stringKey("EmptyStringKey"))).isNotNull();
assertThat(spanData.getAttributes().get(stringKey("EmptyStringAttributeValue"))).isNotNull();
assertThat(spanData.getAttributes().get(longKey("LongKey"))).isNotNull();
assertThat(spanData.getAttributes().get(longKey("LongKey2"))).isEqualTo(5L);
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(stringArrayKey("ArrayStringKey"))).isNotNull();
assertThat(spanData.getAttributes().get(longArrayKey("ArrayLongKey"))).isNotNull();
assertThat(spanData.getAttributes().get(doubleArrayKey("ArrayDoubleKey"))).isNotNull();
assertThat(spanData.getAttributes().get(booleanArrayKey("ArrayBooleanKey"))).isNotNull();
assertThat(spanData.getAttributes().get(longArrayKey("ArrayWithNullLongKey"))).isNotNull();
assertThat(spanData.getAttributes().get(stringArrayKey("ArrayWithNullStringKey"))).isNotNull();
assertThat(spanData.getAttributes().get(doubleArrayKey("ArrayWithNullDoubleKey"))).isNotNull();
assertThat(spanData.getAttributes().get(booleanArrayKey("ArrayWithNullBooleanKey")))
.isNotNull();
assertThat(spanData.getAttributes().get(stringArrayKey("ArrayStringKey")).size()).isEqualTo(4);
assertThat(spanData.getAttributes().get(longArrayKey("ArrayLongKey")).size()).isEqualTo(5);
assertThat(spanData.getAttributes().get(doubleArrayKey("ArrayDoubleKey")).size()).isEqualTo(5);
assertThat(spanData.getAttributes().get(booleanArrayKey("ArrayBooleanKey")).size())
.isEqualTo(4);
}

@Test
void setAllAttributes_mergesAttributes() {
RecordEventsReadableSpan span = createTestRootSpan();
Attributes attributes =
Attributes.builder()
.put("StringKey", "StringVal")
.put("LongKey", 1000L)
.put("DoubleKey", 10.0)
.put("BooleanKey", false)
.build();

try {
span.setAttribute("StringKey", "OtherStringVal")
.setAttribute("ExistingStringKey", "ExistingStringVal")
.setAttribute("LongKey", 2000L)
.setAllAttributes(attributes);
} finally {
span.end();
}

SpanData spanData = span.toSpanData();
assertThat(spanData.getAttributes().size()).isEqualTo(5);
assertThat(spanData.getAttributes().get(stringKey("StringKey")))
.isNotNull()
.isEqualTo("StringVal");
assertThat(spanData.getAttributes().get(stringKey("ExistingStringKey")))
.isNotNull()
.isEqualTo("ExistingStringVal");
assertThat(spanData.getAttributes().get(longKey("LongKey"))).isNotNull().isEqualTo(1000L);
assertThat(spanData.getAttributes().get(doubleKey("DoubleKey"))).isNotNull().isEqualTo(10.0);
assertThat(spanData.getAttributes().get(booleanKey("BooleanKey"))).isNotNull().isEqualTo(false);
}

@Test
void setAllAttributes_nullAttributes() {
RecordEventsReadableSpan span = createTestRootSpan();
span.setAllAttributes(null);
assertThat(span.toSpanData().getAttributes().size()).isEqualTo(0);
}

@Test
void setAllAttributes_emptyAttributes() {
RecordEventsReadableSpan span = createTestRootSpan();
span.setAllAttributes(Attributes.empty());
assertThat(span.toSpanData().getAttributes().size()).isEqualTo(0);
}

@Test
void addEvent() {
RecordEventsReadableSpan span = createTestRootSpan();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,101 @@ public String getDescription() {
assertThat(span.toSpanData().getAttributes().get(stringKey("cat"))).isEqualTo("meow");
}

@Test
void setAllAttributes() {
Attributes attributes =
Attributes.builder()
.put("string", "value")
.put("long", 12345L)
.put("double", .12345)
.put("boolean", true)
.put(stringKey("stringAttribute"), "attrvalue")
.build();

SpanBuilder spanBuilder = sdkTracer.spanBuilder(SPAN_NAME).setAllAttributes(attributes);

RecordEventsReadableSpan span = (RecordEventsReadableSpan) spanBuilder.startSpan();
try {
SpanData spanData = span.toSpanData();
Attributes attrs = spanData.getAttributes();
assertThat(attrs.size()).isEqualTo(5);
assertThat(attrs.get(stringKey("string"))).isEqualTo("value");
assertThat(attrs.get(longKey("long"))).isEqualTo(12345L);
assertThat(attrs.get(doubleKey("double"))).isEqualTo(0.12345);
assertThat(attrs.get(booleanKey("boolean"))).isEqualTo(true);
assertThat(attrs.get(stringKey("stringAttribute"))).isEqualTo("attrvalue");
assertThat(spanData.getTotalAttributeCount()).isEqualTo(5);
} finally {
span.end();
}
}

@Test
void setAllAttributes_mergesAttributes() {
Attributes attributes =
Attributes.builder()
.put("string", "value")
.put("long", 12345L)
.put("double", .12345)
.put("boolean", true)
.put(stringKey("stringAttribute"), "attrvalue")
.build();

SpanBuilder spanBuilder =
sdkTracer
.spanBuilder(SPAN_NAME)
.setAttribute("string", "otherValue")
.setAttribute("boolean", false)
.setAttribute("existingString", "existingValue")
.setAllAttributes(attributes);

RecordEventsReadableSpan span = (RecordEventsReadableSpan) spanBuilder.startSpan();
try {
SpanData spanData = span.toSpanData();
Attributes attrs = spanData.getAttributes();
assertThat(attrs.size()).isEqualTo(6);
assertThat(attrs.get(stringKey("string"))).isEqualTo("value");
assertThat(attrs.get(stringKey("existingString"))).isEqualTo("existingValue");
assertThat(attrs.get(longKey("long"))).isEqualTo(12345L);
assertThat(attrs.get(doubleKey("double"))).isEqualTo(0.12345);
assertThat(attrs.get(booleanKey("boolean"))).isEqualTo(true);
assertThat(attrs.get(stringKey("stringAttribute"))).isEqualTo("attrvalue");
assertThat(spanData.getTotalAttributeCount()).isEqualTo(8);
} finally {
span.end();
}
}

@Test
void setAllAttributes_nullAttributes() {
SpanBuilder spanBuilder = sdkTracer.spanBuilder(SPAN_NAME).setAllAttributes(null);

RecordEventsReadableSpan span = (RecordEventsReadableSpan) spanBuilder.startSpan();
try {
SpanData spanData = span.toSpanData();
Attributes attrs = spanData.getAttributes();
assertThat(attrs.size()).isEqualTo(0);
assertThat(spanData.getTotalAttributeCount()).isEqualTo(0);
} finally {
span.end();
}
}

@Test
void setAllAttributes_emptyAttributes() {
SpanBuilder spanBuilder = sdkTracer.spanBuilder(SPAN_NAME).setAllAttributes(Attributes.empty());

RecordEventsReadableSpan span = (RecordEventsReadableSpan) spanBuilder.startSpan();
try {
SpanData spanData = span.toSpanData();
Attributes attrs = spanData.getAttributes();
assertThat(attrs.size()).isEqualTo(0);
assertThat(spanData.getTotalAttributeCount()).isEqualTo(0);
} finally {
span.end();
}
}

@Test
void recordEvents_default() {
Span span = sdkTracer.spanBuilder(SPAN_NAME).startSpan();
Expand Down

0 comments on commit 7d31cdd

Please sign in to comment.