Skip to content

Commit 516613c

Browse files
committed
feat(sdk): support OTEL_ATTRIBUTE_COUNT_LIMIT env var
OTEL_ATTRIBUTE_COUNT_LIMIT is the spec-defined general fallback for the maximum span attribute count. Previously only the span-specific OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT was read, so the general variable had no effect. Read OTEL_ATTRIBUTE_COUNT_LIMIT in Config::default() and apply it to max_attributes_per_span, then let OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT override it when both are set, matching the precedence in the configuration spec. The general limit deliberately does not touch the per-event / per-link attribute limits, which have their own defaults per the spec. Part of #3374
1 parent ee359db commit 516613c

3 files changed

Lines changed: 88 additions & 1 deletion

File tree

opentelemetry-sdk/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## vNext
44

5+
- Added support for the `OTEL_ATTRIBUTE_COUNT_LIMIT` environment variable,
6+
the spec-defined general fallback for the maximum span attribute count. The
7+
span-specific `OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT` continues to take precedence
8+
when both are set.
59
- Default SDK Resource construction now falls back to `unknown_service` under
610
Miri instead of calling `std::env::current_exe()`, avoiding an abort in Miri
711
isolation mode while preserving the normal

opentelemetry-sdk/src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,17 @@
9494
//! | `OTEL_TRACES_SAMPLER` | Sampler to use. Valid values: `always_on`, `always_off`, `traceidratio`, `parentbased_always_on`, `parentbased_always_off`, `parentbased_traceidratio`. | `parentbased_always_on` |
9595
//! | `OTEL_TRACES_SAMPLER_ARG` | Argument for the sampler. Used when `OTEL_TRACES_SAMPLER` is `traceidratio` or `parentbased_traceidratio`. Must be a float between 0.0 and 1.0. | `1.0` |
9696
//!
97+
//! ### General Attribute Limits
98+
//!
99+
//! | Variable | Description | Default |
100+
//! |---|---|---|
101+
//! | `OTEL_ATTRIBUTE_COUNT_LIMIT` | Maximum number of attributes allowed on a span. Acts as the fallback for `OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT`, which takes precedence when both are set. | `128` |
102+
//!
97103
//! ### Trace: Span Limits
98104
//!
99105
//! | Variable | Description | Default |
100106
//! |---|---|---|
101-
//! | `OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT` | Maximum number of attributes allowed on a span. | `128` |
107+
//! | `OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT` | Maximum number of attributes allowed on a span. Overrides `OTEL_ATTRIBUTE_COUNT_LIMIT` when set. | `128` |
102108
//! | `OTEL_SPAN_EVENT_COUNT_LIMIT` | Maximum number of events allowed on a span. | `128` |
103109
//! | `OTEL_SPAN_LINK_COUNT_LIMIT` | Maximum number of links allowed on a span. | `128` |
104110
//!

opentelemetry-sdk/src/trace/config.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,19 @@ impl Default for Config {
3636
resource: Cow::Owned(Resource::builder().build()),
3737
};
3838

39+
// `OTEL_ATTRIBUTE_COUNT_LIMIT` is the general fallback for the maximum
40+
// span attribute count; the span-specific
41+
// `OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT` takes precedence when both are set.
42+
// It does not affect the per-event / per-link attribute limits, which
43+
// have their own defaults per the spec.
44+
// See https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#attribute-limits
45+
if let Some(max_attributes) = env::var("OTEL_ATTRIBUTE_COUNT_LIMIT")
46+
.ok()
47+
.and_then(|count_limit| u32::from_str(&count_limit).ok())
48+
{
49+
config.span_limits.max_attributes_per_span = max_attributes;
50+
}
51+
3952
if let Some(max_attributes_per_span) = env::var("OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT")
4053
.ok()
4154
.and_then(|count_limit| u32::from_str(&count_limit).ok())
@@ -135,3 +148,67 @@ impl Default for Config {
135148
config
136149
}
137150
}
151+
152+
#[cfg(test)]
153+
mod tests {
154+
use super::Config;
155+
use crate::trace::span_limit::{
156+
DEFAULT_MAX_ATTRIBUTES_PER_EVENT, DEFAULT_MAX_ATTRIBUTES_PER_LINK,
157+
DEFAULT_MAX_ATTRIBUTES_PER_SPAN,
158+
};
159+
160+
#[test]
161+
fn otel_attribute_count_limit_sets_span_attribute_limit() {
162+
temp_env::with_vars(
163+
[
164+
("OTEL_ATTRIBUTE_COUNT_LIMIT", Some("64")),
165+
("OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT", None::<&str>),
166+
],
167+
|| {
168+
let config = Config::default();
169+
assert_eq!(config.span_limits.max_attributes_per_span, 64);
170+
// The general limit must not touch the per-event / per-link
171+
// attribute limits, which keep their own defaults.
172+
assert_eq!(
173+
config.span_limits.max_attributes_per_event,
174+
DEFAULT_MAX_ATTRIBUTES_PER_EVENT
175+
);
176+
assert_eq!(
177+
config.span_limits.max_attributes_per_link,
178+
DEFAULT_MAX_ATTRIBUTES_PER_LINK
179+
);
180+
},
181+
);
182+
}
183+
184+
#[test]
185+
fn span_attribute_count_limit_overrides_general_limit() {
186+
temp_env::with_vars(
187+
[
188+
("OTEL_ATTRIBUTE_COUNT_LIMIT", Some("64")),
189+
("OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT", Some("32")),
190+
],
191+
|| {
192+
let config = Config::default();
193+
assert_eq!(config.span_limits.max_attributes_per_span, 32);
194+
},
195+
);
196+
}
197+
198+
#[test]
199+
fn default_span_attribute_limit_when_unset() {
200+
temp_env::with_vars(
201+
[
202+
("OTEL_ATTRIBUTE_COUNT_LIMIT", None::<&str>),
203+
("OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT", None::<&str>),
204+
],
205+
|| {
206+
let config = Config::default();
207+
assert_eq!(
208+
config.span_limits.max_attributes_per_span,
209+
DEFAULT_MAX_ATTRIBUTES_PER_SPAN
210+
);
211+
},
212+
);
213+
}
214+
}

0 commit comments

Comments
 (0)