Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add metric to count the rate-limited requests #763

Merged
merged 1 commit into from
Feb 24, 2025

Conversation

m-Peter
Copy link
Collaborator

@m-Peter m-Peter commented Feb 21, 2025

Closes: #762

Description

Add a new type, RateLimiter, which also encapsulates a metrics.Collector object.
Add a metric to count the number of rate-limited requests.


For contributor use:

  • Targeted PR against master branch
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
  • Code follows the standards mentioned here.
  • Updated relevant documentation
  • Re-reviewed Files changed in the Github PR explorer
  • Added appropriate labels

Summary by CodeRabbit

  • New Features

    • Introduced a unified rate limiting mechanism across API endpoints.
    • Enhanced metrics tracking to monitor rate-limiting events per API call.
  • Refactor

    • Streamlined request handling and error messaging for a more consistent API experience.
    • Consolidated rate limiting functionality into a single implementation for improved flexibility.
  • Chores

    • Removed legacy rate limiting components and updated initialization procedures for improved clarity and performance.

Copy link
Contributor

coderabbitai bot commented Feb 21, 2025

Walkthrough

The pull request refactors the rate limiting mechanism across several API components. The changes replace the old limiter.Store based implementation with a new abstracted RateLimiter interface and its concrete implementation in a new file. Constructors and method calls have been updated accordingly in the API, Debug, and Pull modules. Additionally, variables in the bootstrap component have been renamed for clarity. The metrics collection has been enhanced with new methods to track rate limit events.

Changes

File(s) Change Summary
api/api.go, api/debug.go, api/pull.go Replaced the limiter/ratelimiter field (of type limiter.Store) with a new rateLimiter field (of type RateLimiter). Updated constructor signatures and modified function calls from rateLimit to rateLimiter.Apply(ctx).
bootstrap/bootstrap.go Renamed variables in the rate limiter instantiation for clarity and updated error messages to reference the in-memory limiter store.
api/rate_limiter.go Added new file implementing the RateLimiter interface and its DefaultRateLimiter with the Apply(ctx) method for enforcing rate limiting.
api/ratelimiter.go Deleted the old rateLimit function that managed request limits using the previous limiter.Store implementation.
metrics/collector.go Added RequestRateLimited(method string) method and a new counter vector field (requestRateLimitedCounters) in DefaultCollector for tracking rate-limited requests per JSON-RPC method.
metrics/nop.go Added RequestRateLimited(method string) method to the nopCollector struct to align with the updated metrics collection interface.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client
    participant API as API Endpoint
    participant RL as RateLimiter
    Client->>API: Send request
    API->>RL: Apply(ctx)
    alt Token available
        RL-->>API: nil
        API-->>Client: Response OK
    else Token not available
        RL-->>API: ErrRateLimit
        API-->>Client: Error response
    end
Loading

Possibly related PRs

  • Rate limit requests #267: The changes in the main PR are related to those in the retrieved PR as both involve modifications to the rate limiting implementation in the BlockChainAPI struct within the api/api.go file, specifically transitioning from a limiter.Store to a RateLimiter.

Suggested labels

EVM, Compatibility

Suggested reviewers

  • peterargue
  • zhangchiqing
  • janezpodhostnik

Poem

In the code garden, I hop with glee,
RateLimiter prances, wild and free.
Old tokens put to rest with care,
New logic blossoms fresh and fair.
A happy bunny sings its praise,
Celebrating clean code in clever ways! 🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c4304ac and 8b90e95.

📒 Files selected for processing (8)
  • api/api.go (21 hunks)
  • api/debug.go (8 hunks)
  • api/pull.go (8 hunks)
  • api/rate_limiter.go (1 hunks)
  • api/ratelimiter.go (0 hunks)
  • bootstrap/bootstrap.go (4 hunks)
  • metrics/collector.go (5 hunks)
  • metrics/nop.go (1 hunks)
💤 Files with no reviewable changes (1)
  • api/ratelimiter.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • metrics/nop.go
  • api/pull.go
  • api/rate_limiter.go
  • bootstrap/bootstrap.go
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Test
🔇 Additional comments (7)
metrics/collector.go (3)

75-78: LGTM! Well-structured metric definition.

The new metric requestRateLimitedCounters follows the established naming convention and uses appropriate labels for tracking rate limits by JSON-RPC method.


108-108: LGTM! Interface update is consistent.

The new RequestRateLimited method is appropriately added to the Collector interface.


216-222: LGTM! Implementation is correct and consistent.

The RequestRateLimited method implementation in DefaultCollector follows the established pattern and correctly increments the counter with the method label.

api/api.go (2)

89-90: LGTM! Field type change is appropriate.

The change from limiter to rateLimiter with the new RateLimiter type improves clarity and aligns with the new rate limiting mechanism.


119-121: LGTM! Rate limit checks are consistently implemented.

All methods have been updated to use the new rate limiting mechanism with appropriate method names and consistent error handling.

Also applies to: 178-180, 203-205, 230-232, 259-261, 294-296, 334-336, 368-370, 402-404, 439-441, 485-487, 509-511, 546-548, 594-596, 683-685, 766-768, 882-884

api/debug.go (2)

54-54: LGTM! Field type change is appropriate.

The change to use RateLimiter type is consistent with the changes in other API components.


87-89: LGTM! Rate limit checks are consistently implemented.

All debug API methods have been updated to use the new rate limiting mechanism with appropriate method names and consistent error handling.

Also applies to: 99-101, 116-118, 134-136, 257-259

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between da6552b and 33fd540.

📒 Files selected for processing (8)
  • api/api.go (21 hunks)
  • api/debug.go (8 hunks)
  • api/pull.go (8 hunks)
  • api/rate_limiter.go (1 hunks)
  • api/ratelimiter.go (0 hunks)
  • bootstrap/bootstrap.go (4 hunks)
  • metrics/collector.go (4 hunks)
  • metrics/nop.go (1 hunks)
💤 Files with no reviewable changes (1)
  • api/ratelimiter.go
🔇 Additional comments (9)
metrics/nop.go (1)

26-26: LGTM!

The no-op implementation of RequestRateLimited correctly follows the established pattern.

api/rate_limiter.go (1)

16-18: LGTM! Clean interface design.

The RateLimiter interface is well-defined and focused on a single responsibility.

metrics/collector.go (1)

24-24: LGTM! Well-structured metrics implementation.

The rate limit metrics implementation follows Prometheus best practices:

  • Counter vector uses appropriate labels
  • Clear help text
  • Follows metric naming conventions

Also applies to: 43-43, 110-113, 211-217

api/debug.go (1)

54-54: LGTM! Consistent rate limit implementation.

The rate limiting has been properly integrated:

  • All methods consistently check rate limits
  • Error handling is appropriate
  • Rate limit checks are placed at the start of each method

Also applies to: 66-66, 77-77, 87-89, 99-101, 116-118, 134-136, 257-259

api/pull.go (1)

137-137: LGTM! The rate limiting changes look good.

The changes consistently replace the old rate limiting implementation with the new RateLimiter type across all API methods. The implementation:

  • Properly initializes the rate limiter in the struct and constructor
  • Consistently applies rate limiting using rateLimiter.Apply(ctx) before processing requests
  • Correctly handles error responses from rate limiting

Also applies to: 146-146, 155-155, 172-174, 200-202, 249-251, 293-295, 343-345

bootstrap/bootstrap.go (3)

274-279: LGTM! The rate limiter configuration is more readable.

The multi-line configuration structure improves readability while maintaining the same functionality.


281-282: LGTM! The error message is more descriptive.

The error message now specifically mentions "in-memory limiter store" which better describes the component that failed.


283-283: LGTM! The rate limiter is consistently used across API components.

The new RateLimiter is properly initialized and passed to all API components that require rate limiting.

Also applies to: 299-299, 321-321, 333-333

api/api.go (1)

89-89: LGTM! The rate limiting implementation is consistent.

The changes properly integrate the new RateLimiter type across all API methods:

  • Correctly initializes the rate limiter in the struct and constructor
  • Consistently applies rate limiting using rateLimiter.Apply(ctx) before processing requests
  • Properly handles error responses from rate limiting

Also applies to: 100-100, 112-112, 119-119, 178-180, 203-205, 230-232, 259-261, 294-296, 334-336, 368-370, 402-404, 439-441, 485-487, 509-511, 546-548, 594-596, 683-685, 715-717, 765-767, 881-883

@m-Peter m-Peter force-pushed the mpeter/rate-limited-requests-metric branch from 33fd540 to c4304ac Compare February 21, 2025 14:40
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
api/rate_limiter.go (1)

38-64: Apply method logic
Well-structured approach to rate limiting, with clear debug logs and a call to increment the new metric. Consider verifying the reliability of remote if rate-limiting is critical for security.

metrics/collector.go (1)

31-43: Add field requestRateLimitedCounters to DefaultCollector
The new counter vector is well-defined. Keep an eye on unbounded label cardinality if method is untrusted.

api/pull.go (1)

172-174: LGTM! Consistent rate limiter implementation across methods.

The rate limiter is consistently applied across all API methods, with proper error handling and method name tracking.

Consider using constants for method names.

To prevent typos and ensure consistency, consider defining the method names as constants.

+const (
+    MethodNewPendingTransactionFilter = "NewPendingTransactionFilter"
+    MethodNewBlockFilter             = "NewBlockFilter"
+    MethodNewFilter                  = "NewFilter"
+    MethodGetFilterLogs             = "GetFilterLogs"
+    MethodGetFilterChanges          = "GetFilterChanges"
+)

 func (api *PullAPI) NewPendingTransactionFilter(ctx context.Context, fullTx *bool) (rpc.ID, error) {
-    if err := api.rateLimiter.Apply(ctx, "NewPendingTransactionFilter"); err != nil {
+    if err := api.rateLimiter.Apply(ctx, MethodNewPendingTransactionFilter); err != nil {

Also applies to: 200-202, 249-251, 293-295, 343-345

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 33fd540 and c4304ac.

📒 Files selected for processing (8)
  • api/api.go (21 hunks)
  • api/debug.go (8 hunks)
  • api/pull.go (8 hunks)
  • api/rate_limiter.go (1 hunks)
  • api/ratelimiter.go (0 hunks)
  • bootstrap/bootstrap.go (4 hunks)
  • metrics/collector.go (4 hunks)
  • metrics/nop.go (1 hunks)
💤 Files with no reviewable changes (1)
  • api/ratelimiter.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • metrics/nop.go
  • bootstrap/bootstrap.go
  • api/debug.go
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Test
🔇 Additional comments (30)
api/api.go (20)

89-113: Introduce rateLimiter field and constructor parameter
The addition of the rateLimiter field and its constructor parameter looks cleanly integrated into the BlockChainAPI. It aligns well with the new rate limiting strategy.


119-119: Enforce rate limit in BlockNumber
No issues here. Ensuring rate limits on this endpoint seems appropriate.


138-138: Enforce rate limit in Syncing
Properly applies rate limiting for the sync status check.


178-178: Enforce rate limit in SendRawTransaction
Good practice to rate-limit transaction submissions.


203-203: Enforce rate limit in GetBalance
Looks good. This prevents excessively frequent balance queries.


230-230: Enforce rate limit in GetTransactionByHash
No concerns.


259-259: Enforce rate limit in GetTransactionByBlockHashAndIndex
Consistent usage of rate limiting.


294-294: Enforce rate limit in GetTransactionByBlockNumberAndIndex
Implementation remains straightforward.


334-334: Enforce rate limit in GetTransactionReceipt
No issues noted.


368-368: Enforce rate limit in GetBlockByHash
Approach is consistent with other functions.


402-402: Enforce rate limit in GetBlockByNumber
Looks correct.


439-439: Enforce rate limit in GetBlockReceipts
No issues.


485-485: Enforce rate limit in GetBlockTransactionCountByHash
Implementation follows the pattern.


509-509: Enforce rate limit in GetBlockTransactionCountByNumber
No concerns here.


546-546: Enforce rate limit in Call
This is a sensible point to apply rate limiting.


594-594: Enforce rate limit in GetLogs
All good.


683-683: Enforce rate limit in GetTransactionCount
Implementation appears consistent.


716-716: Enforce rate limit in EstimateGas
No issues found.


765-765: Enforce rate limit in GetCode
Matches the pattern in other calls.


881-881: Enforce rate limit in GetStorageAt
Implementation looks straightforward.

api/rate_limiter.go (3)

16-19: Define RateLimiter interface
The interface is concise and clearly expresses the contract for rate limiting.


20-24: Declare DefaultRateLimiter struct
Struct fields align well with the intended limiting behavior and metrics collection.


26-36: NewRateLimiter constructor
Constructs the default rate limiter with the expected dependencies. No issues found.

metrics/collector.go (5)

24-24: Add RequestRateLimited to Collector
This new method appropriately extends the interface for rate limit metrics.


110-113: Initialize requestRateLimitedCounters
The name and help text are descriptive, which is good for metric clarity.


128-128: Register requestRateLimitedCounters
Ensures the new counter is properly registered.


136-148: Update DefaultCollector constructor
Initialization logic is consistent, and the code is readable.


211-218: Implement RequestRateLimited method
Incrementing the counter with the method label completes the metrics flow for rate-limiting events.

api/pull.go (2)

137-137: LGTM! Field name follows Go conventions.

The change from ratelimiter limiter.Store to rateLimiter RateLimiter follows Go naming conventions and suggests a more focused, custom implementation.


146-156: LGTM! Constructor changes are consistent.

The constructor parameter and field initialization changes align with the struct field changes, maintaining a consistent order.

@m-Peter m-Peter force-pushed the mpeter/rate-limited-requests-metric branch from c4304ac to 8b90e95 Compare February 24, 2025 09:30
@m-Peter m-Peter merged commit 35d2260 into main Feb 24, 2025
2 checks passed
@m-Peter m-Peter deleted the mpeter/rate-limited-requests-metric branch February 24, 2025 09:40
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.

Add metric to track rate limit enforcement
3 participants