Skip to content

Commit

Permalink
Adding anvil state to crash report (#1029)
Browse files Browse the repository at this point in the history
  • Loading branch information
slundqui authored and dpaiton committed Nov 1, 2023
1 parent 8b9b0a7 commit 71175d5
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 7 deletions.
3 changes: 3 additions & 0 deletions lib/agent0/agent0/base/config/environment_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ class EnvironmentConfig(FrozenClass):
halt_on_errors: bool = False
# if halt_on_errors is True, halt_on_slippage controls if we halt when slippage happens
halt_on_slippage: bool = False
# if true, will dump anvil state in crash report
# Defaults to false due to size
dump_state_on_crash: bool = False
# optional output filename for logging
log_filename: str = ".logging/agent0_logs.log"
# log level; should be in [logging.DEBUG, logging.INFO, logging.WARNING]
Expand Down
14 changes: 9 additions & 5 deletions lib/agent0/agent0/hyperdrive/crash_report/crash_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,6 @@ def default(self, o):
return json.JSONEncoder.default(self, o)


def _get_git_revision_hash() -> str:
"""Helper function for getting commit hash from git."""
return subprocess.check_output(["git", "rev-parse", "HEAD"]).decode("ascii").strip()


def setup_hyperdrive_crash_report_logging(log_format_string: str | None = None) -> None:
"""Create a new logging file handler with CRITICAL log level for hyperdrive crash reporting.
Expand Down Expand Up @@ -125,12 +120,16 @@ def log_hyperdrive_crash_report(trade_result: TradeResult, log_level: int | None
# NOTE if this crash report happens in a PR that gets squashed,
# we loose this hash.
("commit_hash", _get_git_revision_hash()),
("anvil_dump_state", trade_result.anvil_state),
]
),
indent=4,
cls=ExtendedJSONEncoder,
)

# TODO the anvil dump state blows up the output, should likely print to stdout
# without the state, and log the full crash report to a file. This allows us
# to default state dumps to true, while keeping the output sane.
logging.log(log_level, crash_report_json)


Expand Down Expand Up @@ -189,3 +188,8 @@ def _hyperdrive_trade_obj_to_dict(trade_obj: types.Trade[HyperdriveMarketAction]

def _hyperdrive_agent_to_dict(agent: HyperdriveAgent):
return {"address": agent.checksum_address, "policy": agent.policy.name}


def _get_git_revision_hash() -> str:
"""Helper function for getting commit hash from git."""
return subprocess.check_output(["git", "rev-parse", "HEAD"]).decode("ascii").strip()
1 change: 1 addition & 0 deletions lib/agent0/agent0/hyperdrive/exec/run_agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ def run_agents(
agent_accounts,
environment_config.halt_on_errors,
environment_config.halt_on_slippage,
environment_config.dump_state_on_crash,
last_executed_block,
liquidate,
)
Expand Down
15 changes: 15 additions & 0 deletions lib/agent0/agent0/hyperdrive/exec/trade_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def trade_if_new_block(
agent_accounts: list[HyperdriveAgent],
halt_on_errors: bool,
halt_on_slippage: bool,
dump_state_on_crash: bool,
last_executed_block: int,
liquidate: bool,
) -> int:
Expand Down Expand Up @@ -104,6 +105,8 @@ def trade_if_new_block(
if is_slippage:
log_hyperdrive_crash_report(trade_result, logging.WARNING)
else:
if dump_state_on_crash:
trade_result.anvil_state = _get_anvil_state_dump(hyperdrive.web3)
# Defaults to CRITICAL
log_hyperdrive_crash_report(trade_result)

Expand Down Expand Up @@ -304,3 +307,15 @@ def get_wait_for_new_block(web3: Web3) -> bool:
# do nothing, this will fail for non anvil nodes and we don't care.
automine = False
return not automine


def _get_anvil_state_dump(web3: Web3) -> str | None:
"""Helper function for getting anvil dump state"""
result: str | None = None
try:
response = web3.provider.make_request(method=RPCEndpoint("anvil_dumpState"), params=[])
result = response.get("result", False)
except Exception: # pylint: disable=broad-exception-caught
# do nothing, this is best effort crash reporting
pass
return result
3 changes: 3 additions & 0 deletions lib/agent0/agent0/hyperdrive/state/trade_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class TradeResult:
The information of the latest checkpoint
additional_info : dict[str, Any]
Additional information used for crash reporting
anvil_state: str | None
The anvil state dump when the exception occurred
"""

status: TradeStatus
Expand All @@ -53,3 +55,4 @@ class TradeResult:
pool_info: dict[str, Any] | None = None
checkpoint_info: dict[str, Any] | None = None
additional_info: dict[str, Any] | None = None
anvil_state: str | None = None
5 changes: 3 additions & 2 deletions tests/multi_trade_per_block_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,10 @@ def test_multi_trade_per_block(

# Build environment config
env_config = EnvironmentConfig(
delete_previous_logs=False,
delete_previous_logs=True,
halt_on_errors=True,
log_filename="system_test",
dump_state_on_crash=True,
log_filename=".logging/multi_trade_per_block_test.log",
log_level=logging.INFO,
log_stdout=True,
random_seed=1234,
Expand Down

0 comments on commit 71175d5

Please sign in to comment.