Skip to content

Conversation

iambriccardo
Copy link
Contributor

@iambriccardo iambriccardo commented Jun 20, 2024

This PR correctly emits negative outcomes for rate-limited transactions with nested spans by also emitting negative outcomes for the nested spans themselves.

Closes: #3705

profile_chunks,
} = self;

let nested_spans = event.clone_for(DataCategory::Span, spans_length);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

In case spans_length is 0, we will have both categories filtered out downstream since they won't be active.

.and_then(|i| serde_json::from_slice::<PartialEvent>(&i.payload()).ok())
.map_or(0, |p| p.spans.0)
} else {
0
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not very nice, but I wanted to avoid unnecessary work in case the flag is not set.

Riccardo Busetti added 4 commits June 24, 2024 12:58
@iambriccardo iambriccardo marked this pull request as ready for review June 24, 2024 11:20
@iambriccardo iambriccardo requested a review from a team as a code owner June 24, 2024 11:21
@iambriccardo iambriccardo requested a review from Dav1dde June 24, 2024 11:21

@pytest.mark.parametrize(
"category,raises_rate_limited",
"category,hits_fast_path",
Copy link
Member

Choose a reason for hiding this comment

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

I prefer the raises_rate_limit.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, will change it back. I have changed it because of a test refactor but I rolled it back.

@iambriccardo iambriccardo requested a review from Dav1dde June 24, 2024 12:58
envelope_limiter.enforce(envelope.envelope_mut(), &scoping)?;

if check_nested_spans {
track_nested_spans_outcomes(&envelope, &enforcement, spans);
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 we should integrate the new logic a little bit more with the Enforcement, to prevent having multiple code paths that do similar things. It's a good call to not inject the span count into the envelope summary, but it could still be part of the Enforcement. That is:

  1. Pass a flag into enforce to conditionally check for spans in the transaction item and set Enforcement::spans.
  2. Enforcement::track_outcomes automatically does the right thing

Copy link
Member

Choose a reason for hiding this comment

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

We could possibly pass the managed envelope and some options to the track_outcomes and do it there, I preferred this at the moment, because track_outcomes already does work correctly for rate limits with the envelope. Modifying it will affect both cached/non-cached rate limits.

Having track_outcomes inspect the (managed) envelope seems like a footgun to me, since it is potentially built from completely different values than what the envelope contains (assume_event).

iambriccardo and others added 5 commits June 24, 2024 16:21
Co-authored-by: Joris Bayer <[email protected]>
…getsentry/relay into riccardo/feat/rate-limiting-improvement
Riccardo Busetti added 4 commits June 25, 2024 09:33
@iambriccardo iambriccardo requested review from jjbayer and Dav1dde June 25, 2024 08:17
Comment on lines -1261 to -1265
enforcement.track_outcomes(
state.envelope(),
&state.managed_envelope.scoping(),
self.inner.addrs.outcome_aggregator.clone(),
);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's now done inside apply_with_outcomes

Comment on lines -1256 to -1259
if enforcement.event_active() {
state.remove_event();
debug_assert!(state.envelope().is_empty());
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved up, since it requires enforcement which is consumed by the apply_with_outcomes. I verified that the ordering doesn't seem to impact the end result.

/// Rate limiting information for a data category.
#[derive(Debug)]
struct CategoryLimit {
#[cfg_attr(test, derive(Clone))]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wanted to have the clone() in tests. Either we implement manually the Clone in the tests or we go this route. Idk which would be preferred. The manual definition might be more verbose.

Copy link
Member

Choose a reason for hiding this comment

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

Fine with me!

}
}

fn enforce_and_apply(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Generalized all the code into this function, since I wanted tests to be leaner since a lot of repetition was there previously and some tests were also passing without calling the apply_with_outcomes so to avoid that risk in the future, I decided to have everything into one.

Comment on lines -356 to -359
let timestamp = relay_common::time::instant_to_date_time(envelope.meta().start_time());
let scoping = *scoping;
let event_id = envelope.event_id();
let remote_addr = envelope.meta().remote_addr();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I made sure the fields were all the same as the ones set by the track_outcome of the ManagedEnvelope.

Comment on lines +387 to +391
(
Outcome::RateLimited(limit.reason_code),
limit.category,
limit.quantity,
)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Felt like there was no need for a struct

Riccardo Busetti added 3 commits June 25, 2024 10:48
assert_eq!(outcome.category, expected_category);
assert_eq!(outcome.quantity, expected_quantity);
}
}
Copy link
Member

Choose a reason for hiding this comment

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

No python, nice!

/// Rate limiting information for a data category.
#[derive(Debug)]
struct CategoryLimit {
#[cfg_attr(test, derive(Clone))]
Copy link
Member

Choose a reason for hiding this comment

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

Fine with me!

/// to items in the envelope. This excludes rate limits applied to required attachments, since
/// clients are allowed to continue sending them.
///
/// # Example
Copy link
Member

Choose a reason for hiding this comment

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

Can we keep these docs, they seem to be still relevant? We just don't drop the items anymore directly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wanted to rewrite them in the new function. Will do in a follow up.

@iambriccardo iambriccardo merged commit bc3ce51 into master Jun 25, 2024
@iambriccardo iambriccardo deleted the riccardo/feat/rate-limiting-improvement branch June 25, 2024 10:55
jan-auer added a commit that referenced this pull request Jun 27, 2024
* master:
  chore(dynamic-sampling): Remove metrics for dsc tracking (#3766)
  feat(web-vitals): add support for mobile browsers (#3762)
  feat(profiles): Support profiler_id in context (#3714)
  ref(normalization): Add origin and event_type tags to normalization decision (#3764)
  feat(rate-limiting): Add back docs with examples on rate limiting (#3761)
  feat(spans): Correctly emit negative outcomes for rate limited transactions that have nested spans (#3749)
  ref(metrics): Remove unused sentry extra data (#3758)
  feat(statsd): Emit tokio runtime metrics via statsd (#3755)
  ref(metrics): Aggregate metrics before rate limiting (#3746)
  ref(cogs): Remove unused metric, revert to released usage accountant (#3756)
  build(cargo): Update curve25519-dalek from 4.0.0 to 4.1.3 (#3745)
  test(deps): Bump requests from 2.31.0 to 2.32.2 (#3752)
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.

Produce outcomes for spans in transactions
3 participants