From 38c5c715feb303755dd11e0124dccc2b295ca87f Mon Sep 17 00:00:00 2001 From: Hieu Nguyen Date: Fri, 26 Apr 2024 01:01:02 +0300 Subject: [PATCH 1/2] Add response headers logging for dRPC --- eth_defi/provider/drpc.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 eth_defi/provider/drpc.py diff --git a/eth_defi/provider/drpc.py b/eth_defi/provider/drpc.py new file mode 100644 index 00000000..2c31bf89 --- /dev/null +++ b/eth_defi/provider/drpc.py @@ -0,0 +1,35 @@ +"""dRPC specific Web3.py functionality. +""" + +import logging +from typing import Any + +from web3 import HTTPProvider +from web3._utils.request import get_response_from_post_request +from web3.types import RPCEndpoint, RPCResponse + +logger = logging.getLogger(__name__) + + +class DRPCProvider(HTTPProvider): + """Add header logging capabilities to dRPC provider.""" + + def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse: + 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 self.decode_rpc_response(raw_response) + 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"), + ) + logger.exception(e, extra={"response_headers": raw_response.headers}) + raise From 3076460c1477e8d6cf6283500ae1adc8d7fa266a Mon Sep 17 00:00:00 2001 From: Hieu Nguyen Date: Fri, 26 Apr 2024 12:55:44 +0300 Subject: [PATCH 2/2] Different approach to log response headers on exception --- eth_defi/event_reader/fast_json_rpc.py | 42 ++++++++++++++++++++------ eth_defi/provider/drpc.py | 35 --------------------- 2 files changed, 33 insertions(+), 44 deletions(-) delete mode 100644 eth_defi/provider/drpc.py 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. diff --git a/eth_defi/provider/drpc.py b/eth_defi/provider/drpc.py deleted file mode 100644 index 2c31bf89..00000000 --- a/eth_defi/provider/drpc.py +++ /dev/null @@ -1,35 +0,0 @@ -"""dRPC specific Web3.py functionality. -""" - -import logging -from typing import Any - -from web3 import HTTPProvider -from web3._utils.request import get_response_from_post_request -from web3.types import RPCEndpoint, RPCResponse - -logger = logging.getLogger(__name__) - - -class DRPCProvider(HTTPProvider): - """Add header logging capabilities to dRPC provider.""" - - def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse: - 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 self.decode_rpc_response(raw_response) - 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"), - ) - logger.exception(e, extra={"response_headers": raw_response.headers}) - raise