Skip to content

Conversation

@jjbayer
Copy link
Member

@jjbayer jjbayer commented Nov 14, 2025

Closes INGEST-610.

@linear
Copy link

linear bot commented Nov 14, 2025

metrics_extracted,
spans_extracted,
} = ctx;
// TODO(follow-up): this function should always extract metrics. Dynamic sampling should validate
Copy link
Member

Choose a reason for hiding this comment

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

Wanna link to a GH issue here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done: #5403

Comment on lines +136 to +137
#[cfg(debug_assertions)]
event.ensure_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.

Doesn't that mess with the Managed assertions and we may get misaccounting in prod, but not in tests because this is ran in tests but not in production?

Or is this there to specifically defuse these Managed assertions and it's okay if we misaccount in prod until the transaction is parsed?

Copy link
Member Author

Choose a reason for hiding this comment

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

Or is this there to specifically defuse these Managed assertions and it's okay if we misaccount in prod until the transaction is parsed?

Yes, I believe it's not worth shallow-parsing in prod, because it gets properly parsed immediately afterwards.

category: _,
} = self;
debug_assert!(flags.metrics_extracted);
let mut quantities = smallvec![(DataCategory::TransactionIndexed, 1),];
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
let mut quantities = smallvec![(DataCategory::TransactionIndexed, 1),];
let mut quantities = smallvec![(DataCategory::TransactionIndexed, 1)];

Comment on lines +471 to +473
let limits = rate_limiter
.try_consume(scoping.item(DataCategory::Transaction), 1)
.await;
Copy link
Member

Choose a reason for hiding this comment

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

If the transaction is limited, we can already drop the entire payload and don't need to consider attachments and profiles, right?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, I thought I had an early return here, good catch.

// If there is a transaction limit, drop everything.
// This also affects profiles that lost their transaction due to sampling.
let limits = rate_limiter
.try_consume(scoping.item(DataCategory::TransactionIndexed), 1)
Copy link
Member

Choose a reason for hiding this comment

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

I think you need to check both categories here, that's what the EnvelopeLimiter does.

Note fn is_event_active() checks both categories, indexed and non-indexed as well.

Copy link
Member

@Dav1dde Dav1dde Nov 21, 2025

Choose a reason for hiding this comment

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

Naivly I would now expect transaction rate limits never to apply, what is strange, I would've expected a test to fail here. Am I missing something?

The spans processor always only rate limits total + indexed, it extracts the metrics only after rate limiting. I think this is also what we should do here.

Then you also don't have to implement RateLimited twice.

($($variant:ident => $ty:ty,)*) => {
/// All known [`Processor`] outputs.
#[derive(Debug)]
#[allow(clippy::large_enum_variant)]
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
#[allow(clippy::large_enum_variant)]
#[expect(clippy::large_enum_variant), reason = "..."]

Alternatively we can also box the transaction output, I think that kinda depends why the lint triggers, if it's just because of a small-ish amount it's fine, if there is a large discrepancy maybe it's worth boxing.

}

Ok(())
}
Copy link

Choose a reason for hiding this comment

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

Bug: Rate limiting doesn't check indexed transaction quota

The rate limiting implementation for ExpandedTransaction<TotalAndIndexed> only checks the Transaction category quota, but the quantities() method reports both Transaction and TransactionIndexed categories. This means TransactionIndexed quota limits are never enforced for transactions before metrics extraction. In contrast, the ExpandedTransaction<Indexed> rate limiting correctly checks both categories (lines 537-546). Without checking the indexed category, rate limits on indexed transactions can be bypassed.

Additional Locations (1)

Fix in Cursor Fix in Web

@jjbayer jjbayer marked this pull request as draft December 4, 2025 13:43
@jjbayer jjbayer force-pushed the ref/use-new-processor branch from 3c0b62d to 1c0aea5 Compare January 9, 2026 12:29
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.

4 participants