Log tokens that gave errors interacting with their functions

pull/1078/head
Felipe Renan 6 years ago
parent 0fbda6c72f
commit 43b55ef688
  1. 2
      apps/explorer/config/config.exs
  2. 5
      apps/explorer/config/dev.exs
  3. 6
      apps/explorer/config/prod.exs
  4. 68
      apps/explorer/lib/explorer/token/functions_reader.ex
  5. 3
      config/config.exs

@ -11,7 +11,7 @@ config :ecto, json_library: Jason
config :explorer, config :explorer,
ecto_repos: [Explorer.Repo], ecto_repos: [Explorer.Repo],
coin: System.get_env("COIN") || "POA", coin: System.get_env("COIN") || "POA",
token_functions_reader_retry: 3 token_functions_reader_max_retries: 3
config :explorer, Explorer.Integrations.EctoLogger, query_time_ms_threshold: 2_000 config :explorer, Explorer.Integrations.EctoLogger, query_time_ms_threshold: 2_000

@ -13,6 +13,11 @@ config :logger, :explorer,
level: :debug, level: :debug,
path: Path.absname("logs/dev/explorer.log") path: Path.absname("logs/dev/explorer.log")
config :logger, :reading_token_functions,
level: :debug,
path: Path.absname("logs/dev/explorer/tokens/reading_functions.log"),
metadata_filter: [fetcher: :token_functions]
import_config "dev.secret.exs" import_config "dev.secret.exs"
variant = variant =

@ -14,6 +14,12 @@ config :logger, :explorer,
path: Path.absname("logs/prod/explorer.log"), path: Path.absname("logs/prod/explorer.log"),
rotate: %{max_bytes: 52_428_800, keep: 19} rotate: %{max_bytes: 52_428_800, keep: 19}
config :logger, :reading_token_functions,
level: :debug,
path: Path.absname("logs/prod/explorer/tokens/reading_functions.log"),
metadata_filter: [fetcher: :token_functions],
rotate: %{max_bytes: 52_428_800, keep: 19}
variant = variant =
if is_nil(System.get_env("ETHEREUM_JSONRPC_VARIANT")) do if is_nil(System.get_env("ETHEREUM_JSONRPC_VARIANT")) do
"parity" "parity"

@ -3,6 +3,8 @@ defmodule Explorer.Token.FunctionsReader do
Reads Token's fields using Smart Contract functions from the blockchain. Reads Token's fields using Smart Contract functions from the blockchain.
""" """
require Logger
alias Explorer.Chain.Hash alias Explorer.Chain.Hash
alias Explorer.SmartContract.Reader alias Explorer.SmartContract.Reader
@ -92,7 +94,7 @@ defmodule Explorer.Token.FunctionsReader do
decimals: 18 decimals: 18
} }
It will retry to fetch each function in the Smart Contract according to :token_fetcher_retry It will retry to fetch each function in the Smart Contract according to :token_functions_reader_max_retries
configured in the application env case one of them raised error. configured in the application env case one of them raised error.
""" """
@spec get_functions_of(Hash.t()) :: Map.t() @spec get_functions_of(Hash.t()) :: Map.t()
@ -110,39 +112,65 @@ defmodule Explorer.Token.FunctionsReader do
end end
defp fetch_functions_from_contract(contract_address_hash, contract_functions) do defp fetch_functions_from_contract(contract_address_hash, contract_functions) do
retry = Application.get_env(:explorer, :token_functions_reader_retry) max_retries = Application.get_env(:explorer, :token_functions_reader_max_retries)
functions_fetched = %{}
fetch_functions_from_contract(contract_address_hash, contract_functions, max_retries, functions_fetched)
end
defp fetch_functions_from_contract(contract_address_hash, contract_functions, retries_left, functions_fetched)
when retries_left == 0 do
contract_functions_result = Reader.query_contract(contract_address_hash, @contract_abi, contract_functions)
fetch_functions_from_contract(contract_address_hash, contract_functions, retry) Map.merge(functions_fetched, contract_functions_result)
end end
defp fetch_functions_from_contract(contract_address_hash, contract_functions, retry, result \\ %{}) do defp fetch_functions_from_contract(contract_address_hash, contract_functions, retries_left, functions_fetched)
when retries_left > 0 do
contract_functions_result = Reader.query_contract(contract_address_hash, @contract_abi, contract_functions) contract_functions_result = Reader.query_contract(contract_address_hash, @contract_abi, contract_functions)
contract_functions_with_errors = contract_functions_with_errors(contract_functions_result) functions_with_errors =
Enum.filter(contract_functions_result, fn function ->
case function do
{_, {:error, _}} -> true
{_, {:ok, _}} -> false
end
end)
if Enum.any?(functions_with_errors) do
log_functions_with_errors(contract_address_hash, functions_with_errors, retries_left)
contract_functions_with_errors =
Map.take(
contract_functions,
Enum.map(functions_with_errors, fn {function, _} -> function end)
)
if Enum.any?(contract_functions_with_errors) && retry > 0 do
fetch_functions_from_contract( fetch_functions_from_contract(
contract_address_hash, contract_address_hash,
contract_functions_with_errors, contract_functions_with_errors,
retry - 1, retries_left - 1,
Map.merge(result, contract_functions_result) Map.merge(functions_fetched, contract_functions_result)
) )
else else
Map.merge(result, contract_functions_result) Map.merge(functions_fetched, contract_functions_result)
end end
end end
defp contract_functions_with_errors(contract_functions) do defp log_functions_with_errors(contract_address_hash, functions_with_errors, retries_left) do
contract_functions error_messages =
|> Enum.filter(fn function -> Enum.map(functions_with_errors, fn {function, {:error, error_message}} ->
case function do "function: #{function} - error: #{error_message} \n"
{_, {:error, _}} -> true end)
{_, {:ok, _}} -> false
end Logger.debug(
end) [
|> Enum.reduce(%{}, fn {name, _error}, acc -> "<Token contract hash: #{contract_address_hash}> error while fetching metadata: \n",
Map.put(acc, name, []) error_messages,
end) "Retries left: #{retries_left}"
],
fetcher: :token_functions
)
end end
defp format_contract_functions_result(contract_functions, contract_address_hash) do defp format_contract_functions_result(contract_functions, contract_address_hash) do

@ -25,7 +25,8 @@ config :logger,
{LoggerFileBackend, :explorer}, {LoggerFileBackend, :explorer},
# only :indexer, but all levels # only :indexer, but all levels
{LoggerFileBackend, :indexer}, {LoggerFileBackend, :indexer},
{LoggerFileBackend, :indexer_token_balances} {LoggerFileBackend, :indexer_token_balances},
{LoggerFileBackend, :reading_token_functions}
] ]
config :logger, :console, config :logger, :console,

Loading…
Cancel
Save