Implement general attribute limits (#4495)

* Implement general attribute limits

* Spotless
This commit is contained in:
jack-berg 2022-05-26 09:25:14 -05:00 committed by GitHub
parent de824dc93a
commit 33d2c22260
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 118 additions and 29 deletions

View File

@ -235,16 +235,25 @@ Supported values for `otel.traces.sampler` are
- "parentbased_always_off": ParentBased(root=AlwaysOffSampler)
- "parentbased_traceidratio": ParentBased(root=TraceIdRatioBased). `otel.traces.sampler.arg` sets the ratio.
## Attribute limits
These properties can be used to control the maximum number and length of attributes.
| System property | Environment variable | Description |
|-----------------------------------|-----------------------------------|----------------------------------------------------------------------------------------------------------|
| otel.attribute.value.length.limit | OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT | The maximum length of attribute values. Applies to spans and logs. By default there is no limit. |
| otel.attribute.count.limit | OTEL_ATTRIBUTE_COUNT_LIMIT | The maximum number of attributes. Applies to spans, span events, span links, and logs. Default is `128`. |
## Span limits
These properties can be used to control the maximum size of recordings per span.
These properties can be used to control the maximum size of spans by placing limits on attributes, events, and links.
| System property | Environment variable | Description |
|----------------------------------------|----------------------------------------|------------------------------------------------------------------------|
| otel.span.attribute.value.length.limit | OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT | The maximum length of attribute values. By default there is no limit. |
| otel.span.attribute.count.limit | OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT | The maximum number of attributes per span. Default is `128`. |
| otel.span.event.count.limit | OTEL_SPAN_EVENT_COUNT_LIMIT | The maximum number of events per span. Default is `128`. |
| otel.span.link.count.limit | OTEL_SPAN_LINK_COUNT_LIMIT | The maximum number of links per span. Default is `128` |
| System property | Environment variable | Description |
|----------------------------------------|----------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------|
| otel.span.attribute.value.length.limit | OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT | The maximum length of span attribute values. Takes precedence over `otel.attribute.value.length.limit`. By default there is no limit. |
| otel.span.attribute.count.limit | OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT | The maximum number of attributes per span. Takes precedence over `otel.attribute.count.limit`. Default is `128`. |
| otel.span.event.count.limit | OTEL_SPAN_EVENT_COUNT_LIMIT | The maximum number of events per span. Default is `128`. |
| otel.span.link.count.limit | OTEL_SPAN_LINK_COUNT_LIMIT | The maximum number of links per span. Default is `128` |
## Exemplars

View File

@ -9,6 +9,8 @@ import static io.opentelemetry.sdk.autoconfigure.LogExporterConfiguration.config
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.logs.LogLimits;
import io.opentelemetry.sdk.logs.LogLimitsBuilder;
import io.opentelemetry.sdk.logs.LogProcessor;
import io.opentelemetry.sdk.logs.SdkLogEmitterProviderBuilder;
import io.opentelemetry.sdk.logs.export.BatchLogProcessor;
@ -28,6 +30,9 @@ final class LogEmitterProviderConfiguration {
MeterProvider meterProvider,
BiFunction<? super LogExporter, ConfigProperties, ? extends LogExporter>
logExporterCustomizer) {
logEmitterProviderBuilder.setLogLimits(() -> configureLogLimits(config));
Map<String, LogExporter> exportersByName =
configureLogExporters(config, meterProvider, logExporterCustomizer);
@ -55,5 +60,22 @@ final class LogEmitterProviderConfiguration {
return logProcessors;
}
// Visible for testing
static LogLimits configureLogLimits(ConfigProperties config) {
LogLimitsBuilder builder = LogLimits.builder();
Integer maxAttrLength = config.getInt("otel.attribute.value.length.limit");
if (maxAttrLength != null) {
builder.setMaxAttributeValueLength(maxAttrLength);
}
Integer maxAttrs = config.getInt("otel.attribute.count.limit");
if (maxAttrs != null) {
builder.setMaxNumberOfAttributes(maxAttrs);
}
return builder.build();
}
private LogEmitterProviderConfiguration() {}
}

View File

@ -106,14 +106,24 @@ final class TracerProviderConfiguration {
static SpanLimits configureSpanLimits(ConfigProperties config) {
SpanLimitsBuilder builder = SpanLimits.builder();
Integer maxLength = config.getInt("otel.span.attribute.value.length.limit");
if (maxLength != null) {
builder.setMaxAttributeValueLength(maxLength);
Integer maxAttrLength = config.getInt("otel.attribute.value.length.limit");
if (maxAttrLength != null) {
builder.setMaxAttributeValueLength(maxAttrLength);
}
Integer maxSpanAttrLength = config.getInt("otel.span.attribute.value.length.limit");
if (maxSpanAttrLength != null) {
builder.setMaxAttributeValueLength(maxSpanAttrLength);
}
Integer maxAttrs = config.getInt("otel.span.attribute.count.limit");
Integer maxAttrs = config.getInt("otel.attribute.count.limit");
if (maxAttrs != null) {
builder.setMaxNumberOfAttributes(maxAttrs);
builder.setMaxNumberOfAttributesPerEvent(maxAttrs);
builder.setMaxNumberOfAttributesPerLink(maxAttrs);
}
Integer maxSpanAttrs = config.getInt("otel.span.attribute.count.limit");
if (maxSpanAttrs != null) {
builder.setMaxNumberOfAttributes(maxSpanAttrs);
}
Integer maxEvents = config.getInt("otel.span.event.count.limit");

View File

@ -5,21 +5,34 @@
package io.opentelemetry.sdk.autoconfigure;
import static org.assertj.core.api.Assertions.as;
import static org.assertj.core.api.Assertions.assertThat;
import com.google.common.collect.ImmutableMap;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.logs.LogLimits;
import io.opentelemetry.sdk.logs.LogProcessor;
import io.opentelemetry.sdk.logs.SdkLogEmitterProvider;
import io.opentelemetry.sdk.logs.SdkLogEmitterProviderBuilder;
import io.opentelemetry.sdk.trace.SpanLimits;
import java.util.Collections;
import java.util.Map;
import java.util.function.Supplier;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.Test;
class LogEmitterProviderConfigurationTest {
private static final ConfigProperties EMPTY =
DefaultConfigProperties.createForTest(Collections.emptyMap());
@Test
void configureLogEmitterProvider() {
Map<String, String> properties = Collections.singletonMap("otel.logs.exporter", "none");
Map<String, String> properties =
ImmutableMap.of(
"otel.logs.exporter", "none",
"otel.attribute.count.limit", "5");
// We don't have any exporters on classpath for this test so check no-op case. Exporter cases
// are verified in other test sets like testFullConfig.
@ -35,12 +48,33 @@ class LogEmitterProviderConfigurationTest {
assertThat(logEmitterProvider)
.extracting("sharedState")
.satisfies(
sharedState ->
assertThat(sharedState)
.extracting("logProcessor")
.isEqualTo(LogProcessor.composite()));
sharedState -> {
assertThat(sharedState)
.extracting("logProcessor")
.isEqualTo(LogProcessor.composite());
assertThat(sharedState)
.extracting(
"logLimitsSupplier", as(InstanceOfAssertFactories.type(Supplier.class)))
.extracting(supplier -> (LogLimits) supplier.get())
.isEqualTo(LogLimits.builder().setMaxNumberOfAttributes(5).build());
});
} finally {
logEmitterProvider.shutdown();
}
}
@Test
void configureSpanLimits() {
assertThat(LogEmitterProviderConfiguration.configureLogLimits(EMPTY))
.isEqualTo(LogLimits.getDefault());
SpanLimits config =
TracerProviderConfiguration.configureSpanLimits(
DefaultConfigProperties.createForTest(
ImmutableMap.of(
"otel.attribute.value.length.limit", "100",
"otel.attribute.count.limit", "5")));
assertThat(config.getMaxAttributeValueLength()).isEqualTo(100);
assertThat(config.getMaxNumberOfAttributes()).isEqualTo(5);
}
}

View File

@ -9,6 +9,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableMap;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
@ -156,26 +157,39 @@ class TracerProviderConfigurationTest {
}
@Test
void configureTraceConfig_empty() {
void configureSpanLimits() {
assertThat(TracerProviderConfiguration.configureSpanLimits(EMPTY))
.isEqualTo(SpanLimits.getDefault());
}
@Test
void configureTraceConfig_full() {
Map<String, String> properties = new HashMap<>();
properties.put("otel.traces.sampler", "always_off");
properties.put("otel.span.attribute.value.length.limit", "100");
properties.put("otel.span.attribute.count.limit", "5");
properties.put("otel.span.event.count.limit", "4");
properties.put("otel.span.link.count.limit", "3");
SpanLimits config =
TracerProviderConfiguration.configureSpanLimits(
DefaultConfigProperties.createForTest(properties));
DefaultConfigProperties.createForTest(
ImmutableMap.of(
"otel.attribute.value.length.limit", "100",
"otel.attribute.count.limit", "5")));
assertThat(config.getMaxAttributeValueLength()).isEqualTo(100);
assertThat(config.getMaxNumberOfAttributes()).isEqualTo(5);
assertThat(config.getMaxNumberOfAttributesPerEvent()).isEqualTo(5);
assertThat(config.getMaxNumberOfAttributesPerLink()).isEqualTo(5);
assertThat(config.getMaxNumberOfEvents())
.isEqualTo(SpanLimits.getDefault().getMaxNumberOfEvents());
assertThat(config.getMaxNumberOfLinks())
.isEqualTo(SpanLimits.getDefault().getMaxNumberOfLinks());
config =
TracerProviderConfiguration.configureSpanLimits(
DefaultConfigProperties.createForTest(
ImmutableMap.of(
"otel.attribute.value.length.limit", "100",
"otel.span.attribute.value.length.limit", "200",
"otel.attribute.count.limit", "5",
"otel.span.attribute.count.limit", "10",
"otel.span.event.count.limit", "4",
"otel.span.link.count.limit", "3")));
assertThat(config.getMaxAttributeValueLength()).isEqualTo(200);
assertThat(config.getMaxNumberOfAttributes()).isEqualTo(10);
assertThat(config.getMaxNumberOfAttributesPerEvent()).isEqualTo(5);
assertThat(config.getMaxNumberOfAttributesPerLink()).isEqualTo(5);
assertThat(config.getMaxNumberOfEvents()).isEqualTo(4);
assertThat(config.getMaxNumberOfLinks()).isEqualTo(3);
}