Skip to content

feat(sdk): enforce log record attribute count limit#3571

Open
Wassbdr wants to merge 1 commit into
open-telemetry:mainfrom
Wassbdr:feat/log-attribute-count-limit
Open

feat(sdk): enforce log record attribute count limit#3571
Wassbdr wants to merge 1 commit into
open-telemetry:mainfrom
Wassbdr:feat/log-attribute-count-limit

Conversation

@Wassbdr

@Wassbdr Wassbdr commented Jun 26, 2026

Copy link
Copy Markdown

Part of #3374. Prerequisite for #3568.

Context

In #3568 I added OTEL_ATTRIBUTE_COUNT_LIMIT for spans. @cijothomas pointed out that the general variable is meant to apply to logs too, and that the logs SDK does not enforce any attribute limit today — so exposing the general variable before logs support exists would mislead users. This PR adds that missing logs support first.

Change

SdkLoggerProvider now enforces a maximum attribute count per log record (default 128), dropping attributes added beyond the limit when the record is emitted. Configurable, in precedence order, via:

  1. LoggerProviderBuilder::with_max_attributes_per_log (code-based)
  2. OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT
  3. OTEL_ATTRIBUTE_COUNT_LIMIT (general fallback)
  4. default 128

Enforcement is done once in SdkLogger::emit, before the record is handed to processors, using a new GrowableArray::truncate. The limit is resolved at provider build time and stored on LoggerProviderInner.

This mirrors the span behavior (max_attributes_per_span + OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT) and keeps the hot path cheap: a single truncate per emitted record, a no-op when within the limit.

Notes / scope

  • Truncation drops the last-added attributes (keeping the first), matching the span limit semantics.
  • This PR does not surface a dropped_attributes_count on SdkLogRecord or wire it through OTLP (the proto transform currently sends 0). That's a separate, larger change and can follow; happy to do it if preferred.

Tests

  • GrowableArray::truncate unit test (inline region, overflow region, boundary, no-op, zero).
  • Logger provider tests: default limit truncates; within-limit kept; builder value wins; OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT over OTEL_ATTRIBUTE_COUNT_LIMIT; general var as fallback.

cargo test -p opentelemetry_sdk --all-features --lib, cargo clippy --all-targets --all-features -- -Dwarnings, and cargo fmt --all -- --check all pass.

The logs SDK did not enforce any attribute count limit, unlike spans.
SdkLoggerProvider now caps the number of attributes retained per log record
(default 128), dropping attributes added beyond the limit when the record is
emitted.

The limit is configurable, in precedence order, via:
- LoggerProviderBuilder::with_max_attributes_per_log
- OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT
- OTEL_ATTRIBUTE_COUNT_LIMIT (general fallback)

Enforcement happens once in SdkLogger::emit (before handing the record to
processors) via a new GrowableArray::truncate. Documented the new env var and
added a CHANGELOG entry.

Part of open-telemetry#3374
}
logger.emit(record);
provider.force_flush().unwrap();
count

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: no need to return the count here.


// Enforce the configured attribute count limit before handing the
// record to processors, dropping the attributes added last.
record.truncate_attributes(provider.max_attributes_per_log() as usize);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the original intend behind enforcing this limit is to protect the sdk from taking up too much memory when a mistaken code adds too much attributes, then we should prevent it from being added in the first place. Truncating afterwards won't help.
Could you try eagerly checking the limit in each add_attribute() call? That'd also make it relatively easy to track the dropped count.
Please do benchmark and see if we regress measurably.

/// Attributes added beyond this limit are dropped when the record is
/// emitted. When not set, this is read from the
/// `OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT` environment variable, which falls
/// back to `OTEL_ATTRIBUTE_COUNT_LIMIT`, and otherwise defaults to `128`.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: after this is merged, we should follow up immediately with your other PR so this variable will be consistently applied in spans too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants