Repository navigation
feat: cap span attributes at 128 keys - #38
Merged
Merged
Conversation
Previously, setAttribute accepted any number of distinct keys, so a span could grow without bound. Now a span keeps at most 128 distinct attributes, the OpenTelemetry SDK's default attributeCountLimit. A write to a key the span already has always lands. A new key past the cap is dropped and counted, and the count is exported with the span as the droppedAttributesCount OTLP field. Writing undefined to a key frees its slot. Spans below the cap track only the number of setAttribute calls, since distinct keys can never exceed the number of writes. Once writes reach the cap, the same field holds the exact key count and the dropped count. Signed-off-by: Bryan English <bryan@bryanenglish.com>
bengl
marked this pull request as ready for review
November 3, 2026 19:52
AbhiPrasad
approved these changes
Nov 4, 2026
AbhiPrasad
left a comment
Member
There was a problem hiding this comment.
we won't let this be configurable?
Member
Author
|
@AbhiPrasad I'll do that in another PR, since you've already approved this one. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
setAttribute()took any number of distinct keys, so one span could grow without bound. A span now keeps at most 128 distinct attributes, the OpenTelemetry SDK's defaultattributeCountLimit. A write to a key the span already has always lands. A new key past the cap is dropped and counted, and the count exports as the span'sdroppedAttributesCountwhen it's above zero.Edge cases. These follow the SDK wherever microtel's
setAttribute()lets a value through. A key counts toward the cap while it holds a value, since undefined values are never exported. Writing undefined to a key frees its slot, and dropping it counts nothing. A write of null lands and counts, since microtel exports it as a string.Keeping it cheap.
setAttribute()runs about ten times per span, so it can't afford a lookup per key on every call. A span below the cap only counts its writes, since distinct keys can never outnumber them. Once writes reach the cap, the same private field holds the exact key count and the dropped count, so an ordinary span initializes one field for the cap. A per-key check on every write cost 29% in the span benchmark, and three separate fields cost about twice as much on server spans as one. Past the cap, the field changes from a number to an object. In a process where one span went past the cap first, an ordinary span still cost the same, 88.1 ns against 87.4 ns, where three fields cost 89.5 ns and main 80.8 ns.Performance.
benchmark/span.bench.json Node 26.12.1, 8 interleaved runs against main on a quiet machine:That's about 7 ns per span, or roughly 0.04% of a traced HTTP request, which makes two spans.
Raw samples, M ops/s
Not taken.
Tests. 200 distinct keys export 128 attributes and a
droppedAttributesCountof 72. A write to an existing key lands past the cap, a cleared key frees its slot for itself or a new key, many writes to one key switch to exact counting correctly with a null value holding a slot, and a span under the cap exports nodroppedAttributesCount.