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_always_off": ParentBased(root=AlwaysOffSampler)
- "parentbased_traceidratio": ParentBased(root=TraceIdRatioBased). `otel.traces.sampler.arg` sets the ratio. - "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 ## 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 | | 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.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. Default is `128`. | | 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.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` | | otel.span.link.count.limit | OTEL_SPAN_LINK_COUNT_LIMIT | The maximum number of links per span. Default is `128` |
## Exemplars ## Exemplars

View File

@ -9,6 +9,8 @@ import static io.opentelemetry.sdk.autoconfigure.LogExporterConfiguration.config
import io.opentelemetry.api.metrics.MeterProvider; import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; 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.LogProcessor;
import io.opentelemetry.sdk.logs.SdkLogEmitterProviderBuilder; import io.opentelemetry.sdk.logs.SdkLogEmitterProviderBuilder;
import io.opentelemetry.sdk.logs.export.BatchLogProcessor; import io.opentelemetry.sdk.logs.export.BatchLogProcessor;
@ -28,6 +30,9 @@ final class LogEmitterProviderConfiguration {
MeterProvider meterProvider, MeterProvider meterProvider,
BiFunction<? super LogExporter, ConfigProperties, ? extends LogExporter> BiFunction<? super LogExporter, ConfigProperties, ? extends LogExporter>
logExporterCustomizer) { logExporterCustomizer) {
logEmitterProviderBuilder.setLogLimits(() -> configureLogLimits(config));
Map<String, LogExporter> exportersByName = Map<String, LogExporter> exportersByName =
configureLogExporters(config, meterProvider, logExporterCustomizer); configureLogExporters(config, meterProvider, logExporterCustomizer);
@ -55,5 +60,22 @@ final class LogEmitterProviderConfiguration {
return logProcessors; 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() {} private LogEmitterProviderConfiguration() {}
} }

View File

@ -106,14 +106,24 @@ final class TracerProviderConfiguration {
static SpanLimits configureSpanLimits(ConfigProperties config) { static SpanLimits configureSpanLimits(ConfigProperties config) {
SpanLimitsBuilder builder = SpanLimits.builder(); SpanLimitsBuilder builder = SpanLimits.builder();
Integer maxLength = config.getInt("otel.span.attribute.value.length.limit"); Integer maxAttrLength = config.getInt("otel.attribute.value.length.limit");
if (maxLength != null) { if (maxAttrLength != null) {
builder.setMaxAttributeValueLength(maxLength); 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) { if (maxAttrs != null) {
builder.setMaxNumberOfAttributes(maxAttrs); 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"); Integer maxEvents = config.getInt("otel.span.event.count.limit");

View File

@ -5,21 +5,34 @@
package io.opentelemetry.sdk.autoconfigure; package io.opentelemetry.sdk.autoconfigure;
import static org.assertj.core.api.Assertions.as;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import com.google.common.collect.ImmutableMap;
import io.opentelemetry.api.metrics.MeterProvider; 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.LogProcessor;
import io.opentelemetry.sdk.logs.SdkLogEmitterProvider; import io.opentelemetry.sdk.logs.SdkLogEmitterProvider;
import io.opentelemetry.sdk.logs.SdkLogEmitterProviderBuilder; import io.opentelemetry.sdk.logs.SdkLogEmitterProviderBuilder;
import io.opentelemetry.sdk.trace.SpanLimits;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.function.Supplier;
import org.assertj.core.api.InstanceOfAssertFactories;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
class LogEmitterProviderConfigurationTest { class LogEmitterProviderConfigurationTest {
private static final ConfigProperties EMPTY =
DefaultConfigProperties.createForTest(Collections.emptyMap());
@Test @Test
void configureLogEmitterProvider() { 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 // 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. // are verified in other test sets like testFullConfig.
@ -35,12 +48,33 @@ class LogEmitterProviderConfigurationTest {
assertThat(logEmitterProvider) assertThat(logEmitterProvider)
.extracting("sharedState") .extracting("sharedState")
.satisfies( .satisfies(
sharedState -> sharedState -> {
assertThat(sharedState) assertThat(sharedState)
.extracting("logProcessor") .extracting("logProcessor")
.isEqualTo(LogProcessor.composite())); .isEqualTo(LogProcessor.composite());
assertThat(sharedState)
.extracting(
"logLimitsSupplier", as(InstanceOfAssertFactories.type(Supplier.class)))
.extracting(supplier -> (LogLimits) supplier.get())
.isEqualTo(LogLimits.builder().setMaxNumberOfAttributes(5).build());
});
} finally { } finally {
logEmitterProvider.shutdown(); 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.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableMap;
import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.MeterProvider; import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
@ -156,26 +157,39 @@ class TracerProviderConfigurationTest {
} }
@Test @Test
void configureTraceConfig_empty() { void configureSpanLimits() {
assertThat(TracerProviderConfiguration.configureSpanLimits(EMPTY)) assertThat(TracerProviderConfiguration.configureSpanLimits(EMPTY))
.isEqualTo(SpanLimits.getDefault()); .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 = SpanLimits config =
TracerProviderConfiguration.configureSpanLimits( 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.getMaxAttributeValueLength()).isEqualTo(100);
assertThat(config.getMaxNumberOfAttributes()).isEqualTo(5); 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.getMaxNumberOfEvents()).isEqualTo(4);
assertThat(config.getMaxNumberOfLinks()).isEqualTo(3); assertThat(config.getMaxNumberOfLinks()).isEqualTo(3);
} }