Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/analyse agent logs script #420

Merged
16 changes: 4 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,24 +153,16 @@ Note: In this case, if the service is staked, then it will not update the on-cha
cd trader; poetry run python ../report.py; cd ..
```

3. Use the following set of commands to investigate your agent's logs:
3. Use the `analyse_logs.py` script to investigate your agent's logs:

```bash
cd trader
service_dir="trader_service"
build_dir=$(ls -d "$service_dir"/abci_build_???? 2>/dev/null || echo "$service_dir/abci_build")
poetry run autonomy analyse logs --from-dir "$build_dir/persistent_data/logs/" --agent aea_0 --reset-db
cd ..
cd trader; poetry run python ../analyse_logs.py --agent aea_0 --reset-db; cd ..
```

For example, inspect the state transitions using the following set of commands:
For example, inspect the state transitions using the following command:

```bash
cd trader
service_dir="trader_service"
build_dir=$(ls -d "$service_dir"/abci_build_???? 2>/dev/null || echo "$service_dir/abci_build")
poetry run autonomy analyse logs --from-dir "$build_dir/persistent_data/logs/" --agent aea_0 --fsm --reset-db
cd ..
cd trader; poetry run python ../analyse_logs.py --agent aea_0 --fsm --reset-db; cd ..
```

This will output the different state transitions of your agent per period, for example:
Expand Down
145 changes: 145 additions & 0 deletions analyse_logs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import os
import subprocess
import sys
import argparse


def _parse_args():
"""Parse the script arguments."""
parser = argparse.ArgumentParser(description="Analyse agent logs.")

parser.add_argument(
"--service-dir",
default="trader_service",
help="The service directory containing build directories (default: 'trader_service')."
)
parser.add_argument(
"--from-dir",
help="Path to the logs directory. If not provided, it is auto-detected."
)
parser.add_argument(
"--agent",
default="aea_0",
help="The agent name to analyze (default: 'aea_0')."
)
parser.add_argument(
"--reset-db",
action="store_true",
help="Use this flag to disable resetting the log database."
)
parser.add_argument(
"--start-time",
help="Start time in `YYYY-MM-DD H:M:S,MS` format."
)
parser.add_argument(
"--end-time",
help="End time in `YYYY-MM-DD H:M:S,MS` format."
)
parser.add_argument(
"--log-level",
choices=["INFO", "DEBUG", "WARNING", "ERROR", "CRITICAL"],
help="Logging level."
)
parser.add_argument(
"--period",
type=int,
help="Period ID."
)
parser.add_argument(
"--round",
help="Round name."
)
parser.add_argument(
"--behaviour",
help="Behaviour name filter."
)
parser.add_argument(
"--fsm",
action="store_true",
help="Print only the FSM execution path."
)
parser.add_argument(
"--include-regex",
help="Regex pattern to include in the result."
)
parser.add_argument(
"--exclude-regex",
help="Regex pattern to exclude from the result."
)

return parser.parse_args()


def find_build_directory(service_dir):
"""Find the appropriate build directory within the service directory."""
try:
build_dirs = [
d for d in os.listdir(service_dir)
if d.startswith("abci_build_") and os.path.isdir(os.path.join(service_dir, d))
]
return os.path.join(service_dir, build_dirs[0]) if build_dirs else os.path.join(service_dir, "abci_build")
except FileNotFoundError:
print(f"Service directory '{service_dir}' not found")
sys.exit(1)


def run_analysis(logs_dir, **kwargs):
"""Run the log analysis command."""
command = [
"poetry", "run", "autonomy", "analyse", "logs",
"--from-dir", logs_dir,
]
if kwargs.get("agent"):
command.extend(["--agent", kwargs.get("agent")])
if kwargs.get("reset_db"):
command.extend(["--reset-db"])
if kwargs.get("start_time"):
command.extend(["--start-time", kwargs.get("start_time")])
if kwargs.get("end_time"):
command.extend(["--end-time", kwargs.get("end_time")])
if kwargs.get("log_level"):
command.extend(["--log-level", kwargs.get("log_level")])
if kwargs.get("period"):
command.extend(["--period", kwargs.get("period")])
if kwargs.get("round"):
command.extend(["--round", kwargs.get("round")])
if kwargs.get("behaviour"):
command.extend(["--behaviour", kwargs.get("behaviour")])
if kwargs.get("fsm"):
command.extend(["--fsm"])
if kwargs.get("include_regex"):
command.extend(["--include-regex", kwargs.get("include_regex")])
if kwargs.get("exclude_regex"):
command.extend(["--exclude-regex", kwargs.get("exclude_regex")])

try:
subprocess.run(command, check=True)
print("Analysis completed successfully.")
except subprocess.CalledProcessError as e:
print(f"Command failed with exit code {e.returncode}")
sys.exit(e.returncode)
except FileNotFoundError:
print("Poetry or autonomy not found. Ensure they are installed and accessible.")
sys.exit(1)


if __name__ == "__main__":
# Parse user arguments
args = _parse_args()

# Determine the logs directory
if args.from_dir:
logs_dir = args.from_dir
if not os.path.exists(logs_dir):
print(f"Specified logs directory '{logs_dir}' not found.")
sys.exit(1)
else:
# Auto-detect the logs directory
build_dir = find_build_directory(args.service_dir)
logs_dir = os.path.join(build_dir, "persistent_data", "logs")
if not os.path.exists(logs_dir):
print(f"Logs directory '{logs_dir}' not found.")
sys.exit(1)

# Run the analysis
run_analysis(logs_dir, **vars(args))