Skip to content

Commit

Permalink
Merge pull request #5380 from CoinAlpha/bug/sc-27622/network-error-lo…
Browse files Browse the repository at this point in the history
…gs-from-gateway-node-api

Reduce log noise when hummingbot communicates with gateway
  • Loading branch information
JeremyKono committed Jun 29, 2022
2 parents 4d50bfa + 638cead commit 7213fbf
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 22 deletions.
6 changes: 4 additions & 2 deletions gateway/src/connectors/uniswap/uniswap.controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
LOAD_WALLET_ERROR_MESSAGE,
TOKEN_NOT_SUPPORTED_ERROR_CODE,
TOKEN_NOT_SUPPORTED_ERROR_MESSAGE,
PRICE_FAILED_ERROR_CODE,
PRICE_FAILED_ERROR_MESSAGE,
TRADE_FAILED_ERROR_CODE,
TRADE_FAILED_ERROR_MESSAGE,
SWAP_PRICE_EXCEEDS_LIMIT_PRICE_ERROR_CODE,
Expand Down Expand Up @@ -154,8 +156,8 @@ export async function price(
if (e instanceof Error) {
throw new HttpException(
500,
TRADE_FAILED_ERROR_MESSAGE + e.message,
TRADE_FAILED_ERROR_CODE
PRICE_FAILED_ERROR_MESSAGE + e.message,
PRICE_FAILED_ERROR_CODE
);
} else {
throw new HttpException(
Expand Down
3 changes: 3 additions & 0 deletions gateway/src/services/error-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export const SWAP_PRICE_LOWER_THAN_LIMIT_PRICE_ERROR_CODE = 1009;
export const SERVICE_UNITIALIZED_ERROR_CODE = 1010;
export const UNKNOWN_CHAIN_ERROR_CODE = 1011;
export const INVALID_NONCE_ERROR_CODE = 1012;
export const PRICE_FAILED_ERROR_CODE = 1013;
export const UNKNOWN_ERROR_ERROR_CODE = 1099;

export const NETWORK_ERROR_MESSAGE =
Expand Down Expand Up @@ -126,6 +127,8 @@ export const UNKNOWN_KNOWN_CHAIN_ERROR_MESSAGE = (chainName: any) =>

export const UNKNOWN_ERROR_MESSAGE = 'Unknown error.';

export const PRICE_FAILED_ERROR_MESSAGE = 'Price query failed: ';

export interface ErrorResponse {
stack?: any;
message: string;
Expand Down
74 changes: 54 additions & 20 deletions hummingbot/core/gateway/gateway_http_client.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import logging
import re
import ssl
from decimal import Decimal
from enum import Enum
Expand Down Expand Up @@ -29,6 +30,8 @@ class GatewayError(Enum):
SwapPriceLowerThanLimitPrice = 1009
ServiceUnitialized = 1010
UnknownChainError = 1011
InvalidNonceError = 1012
PriceFailed = 1013
UnknownError = 1099


Expand Down Expand Up @@ -100,29 +103,33 @@ def log_error_codes(self, resp: Dict[str, Any]):
error_code: Optional[int] = resp.get("errorCode")
if error_code is not None:
if error_code == GatewayError.Network.value:
self.logger().info("Gateway had a network error. Make sure it is still able to communicate with the node.")
self.logger().network("Gateway had a network error. Make sure it is still able to communicate with the node.")
elif error_code == GatewayError.RateLimit.value:
self.logger().info("Gateway was unable to communicate with the node because of rate limiting.")
self.logger().network("Gateway was unable to communicate with the node because of rate limiting.")
elif error_code == GatewayError.OutOfGas.value:
self.logger().info("There was an out of gas error. Adjust the gas limit in the gateway config.")
self.logger().network("There was an out of gas error. Adjust the gas limit in the gateway config.")
elif error_code == GatewayError.TransactionGasPriceTooLow.value:
self.logger().info("The gas price provided by gateway was too low to create a blockchain operation. Consider increasing the gas price.")
self.logger().network("The gas price provided by gateway was too low to create a blockchain operation. Consider increasing the gas price.")
elif error_code == GatewayError.LoadWallet.value:
self.logger().info("Gateway failed to load your wallet. Try running 'gateway connect' with the correct wallet settings.")
self.logger().network("Gateway failed to load your wallet. Try running 'gateway connect' with the correct wallet settings.")
elif error_code == GatewayError.TokenNotSupported.value:
self.logger().info("Gateway tried to use an unsupported token.")
self.logger().network("Gateway tried to use an unsupported token.")
elif error_code == GatewayError.TradeFailed.value:
self.logger().info("The trade on gateway has failed.")
self.logger().network("The trade on gateway has failed.")
elif error_code == GatewayError.PriceFailed.value:
self.logger().network("The price query on gateway has failed.")
elif error_code == GatewayError.InvalidNonceError.value:
self.logger().network("The nonce was invalid.")
elif error_code == GatewayError.ServiceUnitialized.value:
self.logger().info("Some values was uninitialized. Please contact dev@hummingbot.io ")
self.logger().network("Some values was uninitialized. Please contact dev@hummingbot.io ")
elif error_code == GatewayError.SwapPriceExceedsLimitPrice.value:
self.logger().info("The swap price is greater than your limit buy price. The market may be too volatile or your slippage rate is too low. Try adjusting the strategy's allowed slippage rate.")
self.logger().network("The swap price is greater than your limit buy price. The market may be too volatile or your slippage rate is too low. Try adjusting the strategy's allowed slippage rate.")
elif error_code == GatewayError.SwapPriceLowerThanLimitPrice.value:
self.logger().info("The swap price is lower than your limit sell price. The market may be too volatile or your slippage rate is too low. Try adjusting the strategy's allowed slippage rate.")
self.logger().network("The swap price is lower than your limit sell price. The market may be too volatile or your slippage rate is too low. Try adjusting the strategy's allowed slippage rate.")
elif error_code == GatewayError.UnknownChainError.value:
self.logger().info("An unknown chain error has occurred on gateway. Make sure your gateway settings are correct.")
self.logger().network("An unknown chain error has occurred on gateway. Make sure your gateway settings are correct.")
elif error_code == GatewayError.UnknownError.value:
self.logger().info("An unknown error has occurred on gateway. Please send your logs to dev@hummingbot.io")
self.logger().network("An unknown error has occurred on gateway. Please send your logs to dev@hummingbot.io")

async def api_request(
self,
Expand Down Expand Up @@ -153,21 +160,48 @@ async def api_request(
response = await client.post(url, json=params)
else:
raise ValueError(f"Unsupported request method {method}")
parsed_response = await response.json()
if response.status != 200 and not fail_silently:
self.log_error_codes(parsed_response)
if not fail_silently and response.status == 504:
self.logger().network(f"The network call to {url} has timed out.")
else:
parsed_response = await response.json()
if response.status != 200 and \
not fail_silently and \
not self.is_timeout_error(parsed_response):
self.log_error_codes(parsed_response)

if "error" in parsed_response:
raise ValueError(f"Error on {method.upper()} {url} Error: {parsed_response['error']}")
else:
raise ValueError(f"Error on {method.upper()} {url} Error: {parsed_response}")

if "error" in parsed_response:
raise ValueError(f"Error on {method.upper()} {url} Error: {parsed_response['error']}")
else:
raise ValueError(f"Error on {method.upper()} {url} Error: {parsed_response}")
except Exception as e:
if not fail_silently:
self.logger().error(e)
if self.is_timeout_error(e):
self.logger().network(f"The network call to {url} has timed out.")
else:
self.logger().network(
e,
exc_info=True,
app_warning_msg=f"Call to {url} failed. See logs for more details."
)
raise e

return parsed_response

@staticmethod
def is_timeout_error(e) -> bool:
"""
It is hard to consistently return a timeout error from gateway
because it uses many different libraries to communicate with the
chains with their own idiosyncracies and they do not necessarilly
return HTTP status code 504 when there is a timeout error. It is
easier to rely on the presence of the word 'timeout' in the error.
"""
error_string = str(e)
if re.search('timeout', error_string, re.IGNORECASE):
return True
return False

async def ping_gateway(self) -> bool:
try:
response: Dict[str, Any] = await self.api_request("get", "", fail_silently=True)
Expand Down

0 comments on commit 7213fbf

Please sign in to comment.