Implement dropped attribute count in logs (#4697)
* Implement dropped attribute count in logs * PR feedback * PR feedback
This commit is contained in:
parent
591aff6c15
commit
a50ceb3959
|
|
@ -50,8 +50,7 @@ final class LogMarshaler extends MarshalerWithSize {
|
|||
MarshalerUtil.toBytes(logData.getSeverityText()),
|
||||
anyValueMarshaler,
|
||||
attributeMarshalers,
|
||||
// TODO (trask) implement droppedAttributesCount in LogRecord
|
||||
0,
|
||||
logData.getTotalAttributeCount() - logData.getAttributes().size(),
|
||||
spanContext.getTraceFlags(),
|
||||
spanContext.getTraceId().equals(INVALID_TRACE_ID) ? null : spanContext.getTraceId(),
|
||||
spanContext.getSpanId().equals(INVALID_SPAN_ID) ? null : spanContext.getSpanId());
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ class LogsRequestMarshalerTest {
|
|||
SpanContext.create(
|
||||
TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TraceState.getDefault()))
|
||||
.setAttributes(Attributes.of(AttributeKey.booleanKey("key"), true))
|
||||
.setTotalAttributeCount(2)
|
||||
.setEpoch(12345, TimeUnit.NANOSECONDS)
|
||||
.build()));
|
||||
|
||||
|
|
@ -111,6 +112,7 @@ class LogsRequestMarshalerTest {
|
|||
SpanContext.create(
|
||||
TRACE_ID, SPAN_ID, TraceFlags.getDefault(), TraceState.getDefault()))
|
||||
.setAttributes(Attributes.of(AttributeKey.booleanKey("key"), true))
|
||||
.setTotalAttributeCount(2)
|
||||
.setEpoch(12345, TimeUnit.NANOSECONDS)
|
||||
.build()));
|
||||
|
||||
|
|
@ -124,6 +126,7 @@ class LogsRequestMarshalerTest {
|
|||
.setKey("key")
|
||||
.setValue(AnyValue.newBuilder().setBoolValue(true).build())
|
||||
.build());
|
||||
assertThat(logRecord.getDroppedAttributesCount()).isEqualTo(1);
|
||||
assertThat(logRecord.getTimeUnixNano()).isEqualTo(12345);
|
||||
}
|
||||
|
||||
|
|
@ -148,6 +151,7 @@ class LogsRequestMarshalerTest {
|
|||
.isEqualTo(Severity.UNDEFINED_SEVERITY_NUMBER.getSeverityNumber());
|
||||
assertThat(logRecord.getBody()).isEqualTo(AnyValue.newBuilder().setStringValue("").build());
|
||||
assertThat(logRecord.getAttributesList()).isEmpty();
|
||||
assertThat(logRecord.getDroppedAttributesCount()).isZero();
|
||||
assertThat(logRecord.getTimeUnixNano()).isEqualTo(12345);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -163,4 +163,17 @@ public class LogDataAssert extends AbstractAssert<LogDataAssert, LogData> {
|
|||
// implementations.
|
||||
return actual.getAttributes().asMap().equals(attributes.asMap());
|
||||
}
|
||||
|
||||
/** Asserts the log has the given total attributes. */
|
||||
public LogDataAssert hasTotalAttributeCount(int totalAttributeCount) {
|
||||
isNotNull();
|
||||
if (actual.getTotalAttributeCount() != totalAttributeCount) {
|
||||
failWithActualExpectedAndMessage(
|
||||
actual.getTotalAttributeCount(),
|
||||
totalAttributeCount,
|
||||
"Expected log to have recorded <%s> total attributes but did not",
|
||||
totalAttributeCount);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ public abstract class TestLogData implements LogData {
|
|||
.setSpanContext(SpanContext.getInvalid())
|
||||
.setSeverity(Severity.UNDEFINED_SEVERITY_NUMBER)
|
||||
.setBody("")
|
||||
.setAttributes(Attributes.empty());
|
||||
.setAttributes(Attributes.empty())
|
||||
.setTotalAttributeCount(0);
|
||||
}
|
||||
|
||||
TestLogData() {}
|
||||
|
|
@ -86,5 +87,8 @@ public abstract class TestLogData implements LogData {
|
|||
|
||||
/** Set the attributes. */
|
||||
public abstract Builder setAttributes(Attributes attributes);
|
||||
|
||||
/** Set the total attribute count. */
|
||||
public abstract Builder setTotalAttributeCount(int totalAttributeCount);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ public class LogAssertionsTest {
|
|||
.setSeverityText("info")
|
||||
.setBody("message")
|
||||
.setAttributes(ATTRIBUTES)
|
||||
.setTotalAttributeCount(999)
|
||||
.build();
|
||||
|
||||
@Test
|
||||
|
|
@ -109,7 +110,8 @@ public class LogAssertionsTest {
|
|||
attributeEntry("colors", "red", "blue"),
|
||||
attributeEntry("conditions", false, true),
|
||||
attributeEntry("scores", 0L, 1L),
|
||||
attributeEntry("coins", 0.01, 0.05, 0.1)));
|
||||
attributeEntry("coins", 0.01, 0.05, 0.1)))
|
||||
.hasTotalAttributeCount(999);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -179,5 +181,7 @@ public class LogAssertionsTest {
|
|||
AttributeKey.stringKey("bear"),
|
||||
value -> assertThat(value).hasSize(2))))
|
||||
.isInstanceOf(AssertionError.class);
|
||||
assertThatThrownBy(() -> assertThat(LOG_DATA).hasTotalAttributeCount(11))
|
||||
.isInstanceOf(AssertionError.class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ abstract class SdkLogData implements LogData {
|
|||
Severity severity,
|
||||
@Nullable String severityText,
|
||||
Body body,
|
||||
Attributes attributes) {
|
||||
Attributes attributes,
|
||||
int totalAttributeCount) {
|
||||
return new AutoValue_SdkLogData(
|
||||
resource,
|
||||
instrumentationScopeInfo,
|
||||
|
|
@ -40,6 +41,7 @@ abstract class SdkLogData implements LogData {
|
|||
severity,
|
||||
severityText,
|
||||
body,
|
||||
attributes);
|
||||
attributes,
|
||||
totalAttributeCount);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,7 +115,8 @@ class SdkReadWriteLogRecord implements ReadWriteLogRecord {
|
|||
severity,
|
||||
severityText,
|
||||
body,
|
||||
getImmutableAttributes());
|
||||
getImmutableAttributes(),
|
||||
attributes == null ? 0 : attributes.getTotalAddedValues());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ package io.opentelemetry.sdk.logs.data;
|
|||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.trace.SpanContext;
|
||||
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
|
||||
import io.opentelemetry.sdk.logs.LogLimits;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
|
@ -44,4 +45,13 @@ public interface LogData {
|
|||
|
||||
/** Returns the attributes for this log, or {@link Attributes#empty()} if unset. */
|
||||
Attributes getAttributes();
|
||||
|
||||
/**
|
||||
* Returns the total number of attributes that were recorded on this log.
|
||||
*
|
||||
* <p>This number may be larger than the number of attributes that are attached to this log, if
|
||||
* the total number recorded was greater than the configured maximum value. See {@link
|
||||
* LogLimits#getMaxNumberOfAttributes()}.
|
||||
*/
|
||||
int getTotalAttributeCount();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import static org.mockito.Mockito.never;
|
|||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.common.AttributesBuilder;
|
||||
import io.opentelemetry.api.internal.StringUtils;
|
||||
|
|
@ -104,20 +105,20 @@ class SdkLogEmitterTest {
|
|||
() -> LogLimits.builder().setMaxNumberOfAttributes(maxNumberOfAttrs).build())
|
||||
.build();
|
||||
|
||||
AttributesBuilder attributesBuilder = Attributes.builder();
|
||||
LogRecordBuilder builder = logEmitterProvider.get("test").logRecordBuilder();
|
||||
AttributesBuilder expectedAttributes = Attributes.builder();
|
||||
for (int i = 0; i < 2 * maxNumberOfAttrs; i++) {
|
||||
attributesBuilder.put("key" + i, i);
|
||||
AttributeKey<Long> key = AttributeKey.longKey("key" + i);
|
||||
builder.setAttribute(key, (long) i);
|
||||
if (i < maxNumberOfAttrs) {
|
||||
expectedAttributes.put(key, (long) i);
|
||||
}
|
||||
}
|
||||
builder.emit();
|
||||
|
||||
logEmitterProvider
|
||||
.get("test")
|
||||
.logRecordBuilder()
|
||||
.setAllAttributes(attributesBuilder.build())
|
||||
.emit();
|
||||
|
||||
// NOTE: cannot guarantee which attributes are retained, only that there are no more that the
|
||||
// max
|
||||
assertThat(seenLog.get().toLogData().getAttributes()).hasSize(maxNumberOfAttrs);
|
||||
assertThat(seenLog.get().toLogData())
|
||||
.hasAttributes(expectedAttributes.build())
|
||||
.hasTotalAttributeCount(maxNumberOfAttrs * 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Reference in New Issue