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

Avoid logging debug info for invalid JSON-RPC methods #611

Merged
merged 1 commit into from
Oct 8, 2024

Conversation

m-Peter
Copy link
Collaborator

@m-Peter m-Peter commented Oct 8, 2024

Description

When the EVM Gateway receives requests with unknown JSON-RPC methods, we still log the following two lines:

{
    "level": "debug",
    "version": "development",
    "component": "API",
    "IP": "[::1]:60022",
    "url": "/",
    "id": 1,
    "jsonrpc": "2.0",
    "method": "eth_etc/passwd",
    "params": [],
    "is-ws": false,
    "time": "2024-10-08T17:08:57+03:00",
    "message": "API request"
}
{
    "level": "debug",
    "version": "development",
    "component": "API",
    "id": 1,
    "jsonrpc": "2.0",
    "method": "eth_etc/passwd",
    "params": [],
    "error": "the method eth_etc/passwd does not exist/is not available",
    "code": -32601,
    "data": null,
    "time": "2024-10-08T17:08:57+03:00",
    "message": "API error response"
}

This creates a lot of noise on the logged data, and in tools such as Grafana, so we completely avoid logging anything in this case.


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 method validation feature for JSON-RPC API, ensuring only valid methods are processed.
  • Improvements

    • Enhanced logging capabilities for better tracking of JSON-RPC requests and responses.
    • Improved error handling in response management to filter known errors from logs.
    • Refined WebSocket request handling for improved clarity and organization.
  • Code Cleanup

    • General code organization and formatting adjustments for clarity and maintainability.

Copy link
Contributor

coderabbitai bot commented Oct 8, 2024

Walkthrough

The changes introduce a new variable validMethods in api/api.go to store valid method names from the Ethereum JSON-RPC API. A corresponding function IsValidMethod is added to validate method names. In api/server.go, logging functionality is enhanced, focusing on JSON-RPC request handling, including improved error logging and reorganized WebSocket request handling. The overall structure of the code remains unchanged, with no modifications to public method signatures.

Changes

File Change Summary
api/api.go Added variable validMethods (map of valid method names) and function IsValidMethod (validates method names).
api/server.go Enhanced logging for JSON-RPC methods, adjusted response handling in Write method, reorganized WebSocket request handling, and performed general code cleanup.

Possibly related PRs

  • Improve error logging for eth_call JSON-RPC endpoint #242: This PR modifies the logging behavior in the BlockChainAPI function in api/api.go, which is directly related to the changes made in the main PR regarding JSON-RPC method validation and logging enhancements.
  • Debug log all errors #528: This PR enhances error logging in the Write method of the responseHandler struct in api/server.go, which aligns with the logging improvements introduced in the main PR for JSON-RPC request handling.

Suggested labels

Bugfix

Suggested reviewers

  • peterargue
  • sideninja

🐇 In the code, I hop and play,
Valid methods lead the way.
Logging clear, no errors stray,
JSON calls, we save the day!
With each change, we bounce and sway,
In the server's dance, we find our way! 🐇


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between f2b539d and 0324b75.

📒 Files selected for processing (2)
  • api/api.go (1 hunks)
  • api/server.go (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • api/api.go
  • api/server.go

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 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

🧹 Outside diff range and nitpick comments (2)
api/api.go (2)

35-87: LGTM! Consider using a constant for the empty struct value.

The validMethods map is a comprehensive and memory-efficient implementation of a set containing all valid Ethereum JSON-RPC API methods. This is a good addition that will help in method validation.

Consider defining a constant for the empty struct value to improve readability:

+const void struct{}

 var validMethods = map[string]struct{}{
-	"eth_blockNumber":                         {},
+	"eth_blockNumber":                         void,
	// ... (apply to all entries)
 }

Line range hint 1-1191: Consider improving error handling and logging consistency.

While reviewing the existing API endpoint implementations, I noticed a few areas where improvements could be made:

  1. Error handling could be more consistent across different methods. Some methods use the handleError function, while others directly return errors.

  2. Some methods could benefit from additional logging, especially for debugging purposes.

  3. The handleError function (lines 1146-1166) could be simplified by using a switch statement instead of multiple if-else conditions.

Consider implementing these improvements to enhance the overall code quality and maintainability. Here's an example of how the handleError function could be refactored:

func handleError[T any](err error, log zerolog.Logger, collector metrics.Collector) (T, error) {
	var zero T
	var revertedErr *errs.RevertError

	switch {
	case errors.Is(err, errs.ErrEntityNotFound):
		return zero, nil
	case errors.Is(err, errs.ErrInvalid), errors.Is(err, errs.ErrFailedTransaction):
		return zero, err
	case errors.As(err, &revertedErr):
		return zero, revertedErr
	default:
		collector.ApiErrorOccurred()
		log.Error().Err(err).Msg("api error")
		return zero, errs.ErrInternal
	}
}

Additionally, consider adding more consistent logging across methods, especially for debugging purposes. For example:

func (b *BlockChainAPI) GetTransactionCount(
	ctx context.Context,
	address common.Address,
	blockNumberOrHash rpc.BlockNumberOrHash,
) (*hexutil.Uint64, error) {
	l := b.logger.With().
		Str("endpoint", "getTransactionCount").
		Str("address", address.String()).
		Logger()

	l.Debug().Msg("Processing getTransactionCount request") // Add debug logging

	// ... (rest of the method implementation)

	l.Debug().Uint64("nonce", nonce).Msg("Transaction count retrieved") // Add debug logging for the result

	return (*hexutil.Uint64)(&networkNonce), nil
}

Implementing these suggestions will improve code consistency, error handling, and debugging capabilities across the API.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 1f3f543 and f2b539d.

📒 Files selected for processing (2)
  • api/api.go (1 hunks)
  • api/server.go (3 hunks)
🧰 Additional context used
🔇 Additional comments (3)
api/api.go (2)

89-94: LGTM! The IsValidMethod function is well-implemented.

The IsValidMethod function is a simple and efficient way to check if a given method name is valid. It correctly utilizes the validMethods map for this purpose.


Line range hint 1-1191: Overall, the changes and existing code are well-implemented with room for minor improvements.

The introduction of the validMethods map and IsValidMethod function enhances the API's capability to validate incoming requests. The existing code is generally well-structured and follows consistent patterns.

Some suggestions for further improvement include:

  1. Enhancing error handling consistency across methods.
  2. Adding more debug logging for better traceability.
  3. Simplifying the handleError function.

These changes would further improve the code's maintainability and debugging capabilities.

api/server.go (1)

489-492: Logging adjustments for error responses look good

The updates to the error logging correctly prevent known errors, such as method not found, from generating unnecessary debug log entries. This helps reduce noise in the logs while still providing visibility into unexpected issues.

api/server.go Outdated
Comment on lines 252 to 264
method, ok := requestBody["method"]
// Do not log any debug info for methods that are not valid
// JSON-RPC methods.
if ok && IsValidMethod(method.(string)) {
h.logger.Debug().
Str("IP", r.RemoteAddr).
Str("url", r.URL.String()).
Fields(requestBody).
Bool("is-ws", isWebSocket(r)).
Msg("API request")

}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix potential panic due to unsafe type assertion

The type assertion method.(string) can cause a panic if method is not of type string. To prevent this, you should perform a safe type assertion to ensure the program does not crash if method is not a string.

Apply the following fix to safely handle the type assertion:

-method, ok := requestBody["method"]
-// Do not log any debug info for methods that are not valid
-// JSON-RPC methods.
-if ok && IsValidMethod(method.(string)) {
+if methodValue, ok := requestBody["method"]; ok {
+    if methodStr, ok := methodValue.(string); ok && IsValidMethod(methodStr) {
         h.logger.Debug().
             Str("IP", r.RemoteAddr).
             Str("url", r.URL.String()).
             Fields(requestBody).
             Bool("is-ws", isWebSocket(r)).
             Msg("API request")
+    }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
method, ok := requestBody["method"]
// Do not log any debug info for methods that are not valid
// JSON-RPC methods.
if ok && IsValidMethod(method.(string)) {
h.logger.Debug().
Str("IP", r.RemoteAddr).
Str("url", r.URL.String()).
Fields(requestBody).
Bool("is-ws", isWebSocket(r)).
Msg("API request")
}
if methodValue, ok := requestBody["method"]; ok {
if methodStr, ok := methodValue.(string); ok && IsValidMethod(methodStr) {
h.logger.Debug().
Str("IP", r.RemoteAddr).
Str("url", r.URL.String()).
Fields(requestBody).
Bool("is-ws", isWebSocket(r)).
Msg("API request")
}
}

Copy link
Contributor

@franklywatson franklywatson left a comment

Choose a reason for hiding this comment

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

We should add comments on the api.go, debug.go endpoint implementations to advise adding and new methods to the list here

@m-Peter m-Peter force-pushed the avoid-logs-for-unknown-json-rpc-methods branch from f2b539d to 0324b75 Compare October 8, 2024 17:04
@m-Peter
Copy link
Collaborator Author

m-Peter commented Oct 8, 2024

We should add comments on the api.go, debug.go endpoint implementations to advise adding and new methods to the list here

@franklywatson I have done that in this line: 0324b75#diff-bf98d5fab5bcfabded9769069e7318683f549ec91cff84c5f87a9ae3a3ca3d8dR37

@m-Peter m-Peter merged commit d460871 into main Oct 8, 2024
2 checks passed
@m-Peter m-Peter deleted the avoid-logs-for-unknown-json-rpc-methods branch October 8, 2024 17:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: ✅ Done
Development

Successfully merging this pull request may close these issues.

3 participants