Skip to content

Conversation

@tobias-wilfert
Copy link
Member

@tobias-wilfert tobias-wilfert commented Dec 11, 2025

Follow up to #5457 now adding fast path rate limiting for trace attachments.

Closes INGEST-645

@tobias-wilfert tobias-wilfert changed the title feat(processor): Fast path rate limiting for trace attachments WIP: feat(processor): Fast path rate limiting for trace attachments Dec 11, 2025
@tobias-wilfert tobias-wilfert self-assigned this Dec 11, 2025
@tobias-wilfert tobias-wilfert changed the title WIP: feat(processor): Fast path rate limiting for trace attachments feat(processor): Fast path rate limiting for trace attachments Dec 15, 2025
@tobias-wilfert tobias-wilfert marked this pull request as ready for review December 15, 2025 08:43
@tobias-wilfert tobias-wilfert requested a review from a team as a code owner December 15, 2025 08:43
Comment on lines 1113 to 1115
Event,
Span,
Trace,
Copy link
Member

Choose a reason for hiding this comment

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

Surprised clippy isn't mad at this, usually need to document every public symbol and enum variants are always public if the enum is.

Would be good to just add documentation of what we consider an Event attachment parent etc. (can also just be generic docs on the type) with an example.

}
}

/// The type of parent entity an attachment is associated with.
Copy link
Member

Choose a reason for hiding this comment

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

Would be good just to add some examples or what this is used for.

}

/// Recreates the category limit, regardless of if it is active, for a new category with the same reason.
pub fn clone_for_unchecked(&self, category: DataCategory, quantity: usize) -> CategoryLimit {
Copy link
Member

Choose a reason for hiding this comment

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

Discussed offline, we change the logic of clone_for instead if we change the implementation of is_active to self != Default::default().

/// Stronger check than [`!is_active`](Self::is_active) since this will return true only if the
/// limit has not be set. So setting an 'in_active' limit will this to return false.
pub fn is_default(&self) -> bool {
*self == Self::default()
Copy link
Member

Choose a reason for hiding this comment

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

Discussed offline, we want to have an explicit default state, e.g. Option<DataCategory>

Comment on lines 912 to 917
let span_limit = if !enforcement.spans.is_default() {
&enforcement.spans
} else {
&enforcement.spans_indexed
};
enforcement.attachments_limits.span.bytes = span_limit.clone_for_unchecked(
Copy link
Member

Choose a reason for hiding this comment

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

Discussed offline, the span_indexed limit is enough as it already inherits the total limit.

Comment on lines 909 to 910
if !summary.attachment_quantities.span.is_empty()
&& (!enforcement.spans.is_default() || !enforcement.spans_indexed.is_default())
Copy link
Member

Choose a reason for hiding this comment

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

Discussed offline, we can simplify that check to enforcement.span.is_active()

Will still need some local fixing but to have them all in before I start the local rework.

Co-authored-by: David Herberth <[email protected]>
Comment on lines 492 to 502
} else {
Some(ParentType::Event)
}
} else {
None
}
}

/// Returns the attachment payload size.
///
/// For AttachmentV2, returns only the size of the actual payload, excluding the attachment meta.

This comment was marked as outdated.

///
/// For standard attachments (V1) always returns [`ParentType::Event`].
pub fn attachment_parent_type(&self) -> Option<ParentType> {
let is_attachment = self.ty() == &ItemType::Attachment;
Copy link
Member

Choose a reason for hiding this comment

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

nit: I would make this an early return, i.e.

if self.ty() != &ItemType::Attachment { return None; }

Comment on lines 178 to 196
let AttachmentsQuantities {
event:
AttachmentQuantities {
count: event_count,
bytes: _,
},
trace:
AttachmentQuantities {
count: trace_count,
bytes: _,
},
span:
AttachmentQuantities {
count: span_count,
bytes: _,
},
} = self;

event_count + trace_count + span_count
Copy link
Member

Choose a reason for hiding this comment

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

nit: IMO it's OK to not destructure everything here, since you're only interested in the count field:

Suggested change
let AttachmentsQuantities {
event:
AttachmentQuantities {
count: event_count,
bytes: _,
},
trace:
AttachmentQuantities {
count: trace_count,
bytes: _,
},
span:
AttachmentQuantities {
count: span_count,
bytes: _,
},
} = self;
event_count + trace_count + span_count
let AttachmentsQuantities {event, trace, span} = self;
event.count + trace.count + span.count

///
/// Tracks both the count of attachments and size in bytes.
#[derive(Clone, Copy, Debug, Default)]
pub struct AttachmentQuantities {
Copy link
Member

Choose a reason for hiding this comment

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

nit(naming): I would name this AttachmentQuantity and the other thing AttachmentQuantities, just because multi-level plurals make code hard to read IMO.

false
}
},
None => true, // TODO: Not sure if we want to log an error here and if true makes sense rather than false?
Copy link
Member

Choose a reason for hiding this comment

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

Yes, let's make attachment_parent_type return a non-Optional ParentType and add a debug_assert inside that function.

@linear
Copy link

linear bot commented Dec 18, 2025

Comment on lines 186 to 204
let AttachmentQuantities {
event:
AttachmentQuantity {
count: _,
bytes: event_bytes,
},
trace:
AttachmentQuantity {
count: _,
bytes: trace_bytes,
},
span:
AttachmentQuantity {
count: _,
bytes: span_bytes,
},
} = self;

event_bytes + trace_bytes + span_bytes
Copy link
Member

Choose a reason for hiding this comment

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

nit: Same as above (no need to destructure).

Comment on lines 1207 to 1213
type RateLimitTestCase = (
&'static str, // name
&'static [DataCategory], // denied categories
bool, // expect attachment limit active
&'static [(DataCategory, usize)], // expected limiter calls
&'static [(DataCategory, usize)], // expected rate limit outcomes
);
Copy link
Member

Choose a reason for hiding this comment

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

nit: This tuple has so many entries it would be better to use a struct instead.

@tobias-wilfert tobias-wilfert added this pull request to the merge queue Dec 19, 2025
Merged via the queue into master with commit 324752e Dec 19, 2025
54 of 65 checks passed
@tobias-wilfert tobias-wilfert deleted the tobias-wilfert/feat/span-attachment-fast-path-ratelimiting branch December 19, 2025 07:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants