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