diff --git a/eth_defi/event_reader/fast_json_rpc.py b/eth_defi/event_reader/fast_json_rpc.py index 377c1a37..6dc2cd6d 100644 --- a/eth_defi/event_reader/fast_json_rpc.py +++ b/eth_defi/event_reader/fast_json_rpc.py @@ -5,12 +5,14 @@ import logging from json import JSONDecodeError -from typing import cast +from typing import Any, cast import ujson from web3 import Web3 +from web3._utils.request import get_response_from_post_request from web3.providers import JSONBaseProvider -from web3.types import RPCResponse +from web3.providers.rpc import HTTPProvider +from web3.types import RPCEndpoint, RPCResponse logger = logging.getLogger(__name__) @@ -20,7 +22,7 @@ class PartialHttpResponseException(JSONDecodeError): def _fast_decode_rpc_response(raw_response: bytes) -> RPCResponse: - """Uses ujson for speeded up JSON decoding instead of web3.py default JSON.""" + """Uses ujson for speeding up JSON decoding instead of web3.py default JSON.""" try: decoded = ujson.loads(raw_response) except ValueError as e: @@ -31,17 +33,39 @@ def _fast_decode_rpc_response(raw_response: bytes) -> RPCResponse: return cast(RPCResponse, decoded) -def patch_provider(provider: JSONBaseProvider): - """Monkey-patch web3.py provider for faster JSON decoding. +def _make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse: + """Add response headers logging in case of exception raised.""" - This greatly improves JSON-RPC API access speeds, when fetching - multiple and large responses. - """ + request_data = self.encode_rpc_request(method, params) + raw_response = get_response_from_post_request( + self.endpoint_uri, + data=request_data, + **self.get_request_kwargs(), + ) + raw_response.raise_for_status() + + try: + return _fast_decode_rpc_response(raw_response.content) + except Exception as e: + logger.error( + "Unexpected decode RPC response error: %s, current provider ID is %s", + str(e), + raw_response.headers.get("x-drpc-trace-id", ""), + extra={"response_headers": raw_response.headers}, + ) + logger.exception(e) + raise + + +def patch_provider(provider: JSONBaseProvider): + """Monkey-patch web3.py provider for faster JSON decoding and additional logging.""" + if isinstance(provider, HTTPProvider): + provider.make_request = _make_request.__get__(provider) provider.decode_rpc_response = _fast_decode_rpc_response def patch_web3(web3: Web3): - """Monkey-patch web3.py provider for faster JSON decoding. + """Monkey-patch web3.py provider for faster JSON decoding and additional logging. This greatly improves JSON-RPC API access speeds, when fetching multiple and large responses.