rate-limit: create ShouldRateLimit() and tests [crashpad/crashpad : main]

4 views
Skip to first unread message

Jesse McKenna (Gerrit)

unread,
Oct 15, 2025, 7:34:08 PM (3 days ago) Oct 15
to Mark Mentovai, Crashpad LUCI CQ, crashp...@chromium.org
Attention needed from Mark Mentovai

Jesse McKenna added 1 comment

Patchset-level comments
File-level comment, Patchset 6 (Latest):
Jesse McKenna . resolved

PTAL, thanks!

Open in Gerrit

Related details

Attention is currently required from:
  • Mark Mentovai
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: crashpad/crashpad
Gerrit-Branch: main
Gerrit-Change-Id: I68268ee6ea76aa31961f3791c595503a204ec5b4
Gerrit-Change-Number: 7038272
Gerrit-PatchSet: 6
Gerrit-Owner: Jesse McKenna <jessem...@google.com>
Gerrit-Reviewer: Jesse McKenna <jessem...@google.com>
Gerrit-Reviewer: Mark Mentovai <ma...@chromium.org>
Gerrit-Attention: Mark Mentovai <ma...@chromium.org>
Gerrit-Comment-Date: Wed, 15 Oct 2025 23:34:02 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
unsatisfied_requirement
open
diffy

Mark Mentovai (Gerrit)

unread,
Oct 16, 2025, 12:04:15 PM (2 days ago) Oct 16
to Jesse McKenna, Crashpad LUCI CQ, crashp...@chromium.org
Attention needed from Jesse McKenna

Mark Mentovai added 12 comments

Patchset-level comments
Mark Mentovai . resolved

Thanks, Jesse!

File handler/crash_report_upload_rate_limit.h
Line 55, Patchset 6 (Latest): int32_t interval_seconds);
Mark Mentovai . unresolved

`int32_t`’s probably not right for this either. You can use `time_t` for time intervals in this code.

Line 53, Patchset 6 (Latest):ShouldRateLimitResult ShouldRateLimit(time_t now,
Mark Mentovai . unresolved

`#include <time.h>` to be able to use `time_t`.

Line 37, Patchset 6 (Latest): //! \brief If the crash should be skipped, the reason why. `std::nullopt`
Mark Mentovai . unresolved

Blank line before this, so that the line above doesn’t get lost.

Line 36, Patchset 6 (Latest): int32_t attempts_in_interval;
Mark Mentovai . unresolved

This structure isn’t written to disk or used for interchange beyond this process, so it doesn’t need precise sizing (`int32_t`). You can use an `int` or `unsigned int`. If a negative number would be meaningless, I prefer `unsigned int`, but wouldn’t object to `int`.

Line 18, Patchset 6 (Latest):#include <stdint.h>
Mark Mentovai . unresolved

Won’t be needed if you take the other suggestions in this file.

File handler/crash_report_upload_rate_limit.cc
Line 17, Patchset 6 (Latest):#include <stdint.h>
Mark Mentovai . unresolved

As in the .h.

Line 21, Patchset 6 (Latest):#include "base/check_op.h"
Mark Mentovai . unresolved

I don’t see this being used here.

Line 36, Patchset 6 (Latest): } else {
// The most recent upload attempt purportedly occurred in the future. If
// it “happened” at least `kBackwardsClockTolerance` in the future, assume
// that the last upload attempt time is bogus, and attempt to upload the
// report. If the most recent upload time is in the future but within
// `kBackwardsClockTolerance`, accept it and don’t attempt to upload the
// report.
if (last_upload_attempt_time - now < kBackwardsClockTolerance) {
Mark Mentovai . unresolved

You can collapse this into `else if`.

File handler/crash_report_upload_rate_limit_test.cc
Line 32, Patchset 6 (Latest):constexpr int32_t kOneHour = 60 * 60;
Mark Mentovai . unresolved

As elsewhere, `time_t` works for intervals of time—you can get rid of `<stdint.h>` if you make this change.

Line 39, Patchset 6 (Latest): EXPECT_EQ(kUploadThrottled, should_rate_limit.skip_reason);
Mark Mentovai . unresolved

You’ve flipped the `EXPECT_EQ`s! Chromium’s a bit all over the place on this, but I recommend writing these in natural English order. In Crashpad, we consistently write them in the natural English order:

```
EXPECT_EQ(should_rate_limit.skip_reason, kUploadThrottled);
```

Throughout this file.

Line 34, Patchset 6 (Latest):// Skip upload if the last attempt was under one interval ago.
TEST(CrashReportUploadRateLimitTest, ShouldRateLimit_AttemptWithinInterval) {
const time_t now = time(nullptr);

auto should_rate_limit = ShouldRateLimit(now, now, kOneHour);
EXPECT_EQ(kUploadThrottled, should_rate_limit.skip_reason);

should_rate_limit = ShouldRateLimit(now, now - kOneHour + 1, kOneHour);
EXPECT_EQ(kUploadThrottled, should_rate_limit.skip_reason);
}
Mark Mentovai . unresolved

For these sorts of tests, I like to test each boundary and each side of each boundary. That helps avoid off-by-one errors. So, more cases for things like `now - 1`, `now + 1`, `now - kOneHour - 1`, `now - kOneHour`, etc.

Open in Gerrit

Related details

Attention is currently required from:
  • Jesse McKenna
Submit Requirements:
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: crashpad/crashpad
    Gerrit-Branch: main
    Gerrit-Change-Id: I68268ee6ea76aa31961f3791c595503a204ec5b4
    Gerrit-Change-Number: 7038272
    Gerrit-PatchSet: 6
    Gerrit-Owner: Jesse McKenna <jessem...@google.com>
    Gerrit-Reviewer: Jesse McKenna <jessem...@google.com>
    Gerrit-Reviewer: Mark Mentovai <ma...@chromium.org>
    Gerrit-Attention: Jesse McKenna <jessem...@google.com>
    Gerrit-Comment-Date: Thu, 16 Oct 2025 16:04:12 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    unsatisfied_requirement
    open
    diffy

    Jesse McKenna (Gerrit)

    unread,
    Oct 16, 2025, 7:13:38 PM (2 days ago) Oct 16
    to Mark Mentovai, Crashpad LUCI CQ, crashp...@chromium.org
    Attention needed from Mark Mentovai

    Jesse McKenna voted and added 12 comments

    Votes added by Jesse McKenna

    Commit-Queue+1

    12 comments

    Patchset-level comments
    File-level comment, Patchset 7 (Latest):
    Jesse McKenna . resolved

    Thanks so much for the helpful review!

    File handler/crash_report_upload_rate_limit.h
    Line 55, Patchset 6: int32_t interval_seconds);
    Mark Mentovai . resolved

    `int32_t`’s probably not right for this either. You can use `time_t` for time intervals in this code.

    Jesse McKenna

    Done

    Line 53, Patchset 6:ShouldRateLimitResult ShouldRateLimit(time_t now,
    Mark Mentovai . resolved

    `#include <time.h>` to be able to use `time_t`.

    Jesse McKenna

    Done

    Line 37, Patchset 6: //! \brief If the crash should be skipped, the reason why. `std::nullopt`
    Mark Mentovai . resolved

    Blank line before this, so that the line above doesn’t get lost.

    Jesse McKenna

    Done

    Line 36, Patchset 6: int32_t attempts_in_interval;
    Mark Mentovai . resolved

    This structure isn’t written to disk or used for interchange beyond this process, so it doesn’t need precise sizing (`int32_t`). You can use an `int` or `unsigned int`. If a negative number would be meaningless, I prefer `unsigned int`, but wouldn’t object to `int`.

    Jesse McKenna

    Done

    Line 18, Patchset 6:#include <stdint.h>
    Mark Mentovai . resolved

    Won’t be needed if you take the other suggestions in this file.

    Jesse McKenna

    Done

    File handler/crash_report_upload_rate_limit.cc
    Line 17, Patchset 6:#include <stdint.h>
    Mark Mentovai . resolved

    As in the .h.

    Jesse McKenna

    Done

    Line 21, Patchset 6:#include "base/check_op.h"
    Mark Mentovai . resolved

    I don’t see this being used here.

    Jesse McKenna

    Done


    // The most recent upload attempt purportedly occurred in the future. If
    // it “happened” at least `kBackwardsClockTolerance` in the future, assume
    // that the last upload attempt time is bogus, and attempt to upload the
    // report. If the most recent upload time is in the future but within
    // `kBackwardsClockTolerance`, accept it and don’t attempt to upload the
    // report.
    if (last_upload_attempt_time - now < kBackwardsClockTolerance) {
    Mark Mentovai . resolved

    You can collapse this into `else if`.

    Jesse McKenna

    Done

    File handler/crash_report_upload_rate_limit_test.cc
    Line 32, Patchset 6:constexpr int32_t kOneHour = 60 * 60;
    Mark Mentovai . resolved

    As elsewhere, `time_t` works for intervals of time—you can get rid of `<stdint.h>` if you make this change.

    Jesse McKenna

    Done

    Line 39, Patchset 6: EXPECT_EQ(kUploadThrottled, should_rate_limit.skip_reason);
    Mark Mentovai . resolved

    You’ve flipped the `EXPECT_EQ`s! Chromium’s a bit all over the place on this, but I recommend writing these in natural English order. In Crashpad, we consistently write them in the natural English order:

    ```
    EXPECT_EQ(should_rate_limit.skip_reason, kUploadThrottled);
    ```

    Throughout this file.

    Jesse McKenna

    Done

    Line 34, Patchset 6:// Skip upload if the last attempt was under one interval ago.

    TEST(CrashReportUploadRateLimitTest, ShouldRateLimit_AttemptWithinInterval) {
    const time_t now = time(nullptr);

    auto should_rate_limit = ShouldRateLimit(now, now, kOneHour);
    EXPECT_EQ(kUploadThrottled, should_rate_limit.skip_reason);

    should_rate_limit = ShouldRateLimit(now, now - kOneHour + 1, kOneHour);
    EXPECT_EQ(kUploadThrottled, should_rate_limit.skip_reason);
    }
    Mark Mentovai . resolved

    For these sorts of tests, I like to test each boundary and each side of each boundary. That helps avoid off-by-one errors. So, more cases for things like `now - 1`, `now + 1`, `now - kOneHour - 1`, `now - kOneHour`, etc.

    Jesse McKenna

    Done - I combined the tests into one, added a few more test cases, and ordered them from newest to oldest to hopefully make it more readable.

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Mark Mentovai
    Submit Requirements:
      • requirement is not satisfiedCode-Owners
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedReview-Enforcement
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: crashpad/crashpad
      Gerrit-Branch: main
      Gerrit-Change-Id: I68268ee6ea76aa31961f3791c595503a204ec5b4
      Gerrit-Change-Number: 7038272
      Gerrit-PatchSet: 7
      Gerrit-Owner: Jesse McKenna <jessem...@google.com>
      Gerrit-Reviewer: Jesse McKenna <jessem...@google.com>
      Gerrit-Reviewer: Mark Mentovai <ma...@chromium.org>
      Gerrit-Attention: Mark Mentovai <ma...@chromium.org>
      Gerrit-Comment-Date: Thu, 16 Oct 2025 23:13:34 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: Yes
      Comment-In-Reply-To: Mark Mentovai <ma...@chromium.org>
      unsatisfied_requirement
      open
      diffy

      Mark Mentovai (Gerrit)

      unread,
      Oct 16, 2025, 11:27:07 PM (2 days ago) Oct 16
      to Jesse McKenna, Crashpad LUCI CQ, crashp...@chromium.org
      Attention needed from Jesse McKenna

      Mark Mentovai voted and added 3 comments

      Votes added by Mark Mentovai

      Code-Review+1

      3 comments

      Patchset-level comments
      Mark Mentovai . resolved

      Thanks, Jesse!

      File handler/crash_report_upload_rate_limit.h
      Line 37, Patchset 7 (Latest): //!
      Mark Mentovai . unresolved

      Blank line, not //!.

      File handler/crash_report_upload_rate_limit_test.cc
      Line 34, Patchset 6:// Skip upload if the last attempt was under one interval ago.
      TEST(CrashReportUploadRateLimitTest, ShouldRateLimit_AttemptWithinInterval) {
      const time_t now = time(nullptr);

      auto should_rate_limit = ShouldRateLimit(now, now, kOneHour);
      EXPECT_EQ(kUploadThrottled, should_rate_limit.skip_reason);

      should_rate_limit = ShouldRateLimit(now, now - kOneHour + 1, kOneHour);
      EXPECT_EQ(kUploadThrottled, should_rate_limit.skip_reason);
      }
      Mark Mentovai . resolved

      For these sorts of tests, I like to test each boundary and each side of each boundary. That helps avoid off-by-one errors. So, more cases for things like `now - 1`, `now + 1`, `now - kOneHour - 1`, `now - kOneHour`, etc.

      Jesse McKenna

      Done - I combined the tests into one, added a few more test cases, and ordered them from newest to oldest to hopefully make it more readable.

      Mark Mentovai

      Good call! I think this works well.

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Jesse McKenna
      Submit Requirements:
      • requirement satisfiedCode-Owners
      • requirement satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement satisfiedReview-Enforcement
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: crashpad/crashpad
      Gerrit-Branch: main
      Gerrit-Change-Id: I68268ee6ea76aa31961f3791c595503a204ec5b4
      Gerrit-Change-Number: 7038272
      Gerrit-PatchSet: 7
      Gerrit-Owner: Jesse McKenna <jessem...@google.com>
      Gerrit-Reviewer: Jesse McKenna <jessem...@google.com>
      Gerrit-Reviewer: Mark Mentovai <ma...@chromium.org>
      Gerrit-Attention: Jesse McKenna <jessem...@google.com>
      Gerrit-Comment-Date: Fri, 17 Oct 2025 03:27:04 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: Yes
      Comment-In-Reply-To: Mark Mentovai <ma...@chromium.org>
      Comment-In-Reply-To: Jesse McKenna <jessem...@google.com>
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy

      Jesse McKenna (Gerrit)

      unread,
      Oct 17, 2025, 5:09:07 PM (20 hours ago) Oct 17
      to Mark Mentovai, Crashpad LUCI CQ, crashp...@chromium.org

      Jesse McKenna voted and added 2 comments

      Votes added by Jesse McKenna

      Commit-Queue+2

      2 comments

      Patchset-level comments
      File-level comment, Patchset 8 (Latest):
      Jesse McKenna . resolved

      Thank you!

      File handler/crash_report_upload_rate_limit.h
      Line 37, Patchset 7: //!
      Mark Mentovai . resolved

      Blank line, not //!.

      Jesse McKenna

      Oops, done - thanks

      Open in Gerrit

      Related details

      Attention set is empty
      Submit Requirements:
        • requirement satisfiedCode-Owners
        • requirement satisfiedCode-Review
        • requirement satisfiedReview-Enforcement
        Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
        Gerrit-MessageType: comment
        Gerrit-Project: crashpad/crashpad
        Gerrit-Branch: main
        Gerrit-Change-Id: I68268ee6ea76aa31961f3791c595503a204ec5b4
        Gerrit-Change-Number: 7038272
        Gerrit-PatchSet: 8
        Gerrit-Owner: Jesse McKenna <jessem...@google.com>
        Gerrit-Reviewer: Jesse McKenna <jessem...@google.com>
        Gerrit-Reviewer: Mark Mentovai <ma...@chromium.org>
        Gerrit-Comment-Date: Fri, 17 Oct 2025 21:09:04 +0000
        satisfied_requirement
        open
        diffy

        Crashpad LUCI CQ (Gerrit)

        unread,
        Oct 17, 2025, 5:16:58 PM (20 hours ago) Oct 17
        to Jesse McKenna, Mark Mentovai, crashp...@chromium.org

        Crashpad LUCI CQ submitted the change with unreviewed changes

        Unreviewed changes

        7 is the latest approved patch-set.
        The change was submitted with unreviewed changes in the following files:

        ```
        The name of the file: handler/crash_report_upload_rate_limit.h
        Insertions: 1, Deletions: 1.

        @@ -34,7 +34,7 @@
        struct ShouldRateLimitResult {
        //! \brief The number of upload attempts in the past interval.
        unsigned int attempts_in_interval;
        - //!
        +

        //! \brief If the crash should be skipped, the reason why. `std::nullopt`
           //!     otherwise.
        std::optional<Metrics::CrashSkippedReason> skip_reason;
        ```

        Change information

        Commit message:
        rate-limit: create ShouldRateLimit() and tests

        This change moves the rate-limiting logic from ShouldRateLimitUpload()
        into a separate helper function with its own tests. The logic itself
        is unchanged.

        This is a precursor to changes that will experimentally change the
        rate limit. The new tests will help ensure that future changes don't
        unexpectedly break existing logic that should be kept (e.g., the
        CrashSkippedReason, which is emitted to a histogram).
        Bug: 42310127
        Change-Id: I68268ee6ea76aa31961f3791c595503a204ec5b4
        Commit-Queue: Jesse McKenna <jessem...@google.com>
        Reviewed-by: Mark Mentovai <ma...@chromium.org>
        Files:
        • M handler/BUILD.gn
        • A handler/crash_report_upload_rate_limit.cc
        • A handler/crash_report_upload_rate_limit.h
        • A handler/crash_report_upload_rate_limit_test.cc
        • M handler/crash_report_upload_thread.cc
        Change size: M
        Delta: 5 files changed, 199 insertions(+), 24 deletions(-)
        Branch: refs/heads/main
        Submit Requirements:
        • requirement satisfiedCode-Review: +1 by Mark Mentovai
        Open in Gerrit
        Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
        Gerrit-MessageType: merged
        Gerrit-Project: crashpad/crashpad
        Gerrit-Branch: main
        Gerrit-Change-Id: I68268ee6ea76aa31961f3791c595503a204ec5b4
        Gerrit-Change-Number: 7038272
        Gerrit-PatchSet: 9
        Gerrit-Owner: Jesse McKenna <jessem...@google.com>
        Gerrit-Reviewer: Crashpad LUCI CQ <crashpa...@luci-project-accounts.iam.gserviceaccount.com>
        open
        diffy
        satisfied_requirement
        Reply all
        Reply to author
        Forward
        0 new messages