Implement general attribute limits (#4495)
* Implement general attribute limits * Spotless
This commit is contained in:
parent
de824dc93a
commit
33d2c22260
|
@ -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
|
||||
|
||||
|
|
|
@ -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() {}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue