Skip to content

Commit e1adfb8

Browse files
committed
enhance logging and script management for agents and binaries
1 parent 6e3c143 commit e1adfb8

File tree

13 files changed

+242
-49
lines changed

13 files changed

+242
-49
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ scripts/rcssserver
44
logs/
55
__pycache__/
66
utils/__pycache__/
7+
scripts/binary/

scripts/create_binary.sh

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/bin/bash
2+
3+
4+
# show error if binary directory already exists
5+
6+
if [ -d "binary" ]; then
7+
echo "binary directory already exists. Please remove it before running this script."
8+
exit 1
9+
fi
10+
11+
# create binary directory
12+
13+
mkdir binary
14+
15+
# copy scripts/proxy to binary directory
16+
17+
mkdir binary/scripts
18+
cp -r proxy binary/scripts/proxy
19+
20+
# copy formations directory to binary directory
21+
22+
mkdir binary/src
23+
cp -r ../src/formations binary/src/formations
24+
25+
# create binary
26+
27+
nuitka --standalone --onefile --output-dir=binary ../start_agent.py
28+
29+
# remove build directory
30+
31+
rm -rf binary/start_agent.build
32+
rm -rf binary/start_agent.dist
33+
rm -rf binary/start_agent.onefile-build
34+
35+
# copy start_agents.sh to binary directory
36+
37+
cp ../start_agents.sh binary/start_agents.sh
38+
39+
# change all `python3 start_agent.py`` to ./start_agent.bin in binary/start_agents.sh
40+
41+
sed -i 's/run_bin=false/run_bin=true/g' binary/start_agents.sh
42+
43+
# copy start to binary directory
44+
45+
cp start binary/start

scripts/start

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/bin/sh
2+
3+
HOST=$1
4+
BASEDIR=$2
5+
NUM=$3
6+
7+
teamname="CLSF"
8+
9+
cd $BASEDIR
10+
11+
options="--team_name $teamname --server-host $HOST --use-random-port --close-server --disable_log_file"
12+
13+
case $NUM in
14+
1)
15+
./start_agent.bin $options --goalie
16+
;;
17+
12)
18+
./start_agent.bin $options --coach
19+
;;
20+
*)
21+
./start_agent.bin $options
22+
;;
23+
esac

scripts/start_agents.sh

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#!/bin/bash
2+
3+
# active .venv
4+
source .venv/bin/activate
5+
6+
server_port=6000
7+
log_to_file=false
8+
9+
while [ $# -gt 0 ]
10+
do
11+
case $1 in
12+
--server-port)
13+
server_port=$2
14+
shift
15+
;;
16+
--log-to-file)
17+
log_to_file=true
18+
;;
19+
*)
20+
echo 1>&2
21+
echo "invalid option \"${1}\"." 1>&2
22+
echo 1>&2
23+
usage
24+
exit 1
25+
;;
26+
esac
27+
shift 1
28+
done
29+
30+
# Function to handle termination
31+
cleanup() {
32+
echo "Terminating all start_agent.py processes..."
33+
for pid in "${pids[@]}"; do
34+
kill $pid
35+
done
36+
exit 0
37+
}
38+
39+
# Trap SIGTERM and SIGINT signals
40+
trap cleanup SIGTERM SIGINT
41+
42+
# Init log directory
43+
log_dir="$(pwd)/logs/$(date +'%Y-%m-%d_%H-%M-%S')_$((RANDOM % 900000 + 100000))"
44+
mkdir -p $log_dir
45+
46+
# Initialize an empty array to store PIDs
47+
pids=()
48+
49+
# Run start_agent.py 11 times and store each PID in the array
50+
python3 start_agent.py --server-port $server_port --use-random-port --close-server --goalie --log-dir $log_dir &
51+
pids+=($!)
52+
53+
sleep 2
54+
55+
for i in {2..11}; do
56+
python3 start_agent.py --server-port $server_port --use-random-port --close-server --log-dir $log_dir &
57+
pids+=($!)
58+
done
59+
60+
python3 start_agent.py --server-port $server_port --use-random-port --close-server --coach --log-dir $log_dir &
61+
pids+=($!)
62+
63+
# Wait for all background processes to finish
64+
for pid in "${pids[@]}"; do
65+
wait $pid
66+
done

server.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616

1717

1818
console_logging_level = logging.INFO
19-
file_logging_level = logging.DEBUG
19+
file_logging_level = logging.INFO
2020
player_console_logging_level = logging.INFO
21-
player_file_logging_level = logging.DEBUG
21+
player_file_logging_level = logging.INFO
2222

2323
main_logger = None
2424
log_dir = None
@@ -31,12 +31,11 @@ def __init__(self, agent_type, uniform_number, logger) -> None:
3131
self.agent: IAgent = None
3232
self.logger: logging.Logger = logger
3333
if self.agent_type == pb2.AgentType.PlayerT:
34-
self.agent = SamplePlayerAgent()
34+
self.agent = SamplePlayerAgent(self.logger)
3535
elif self.agent_type == pb2.AgentType.CoachT:
36-
self.agent = SampleCoachAgent()
36+
self.agent = SampleCoachAgent(self.logger)
3737
elif self.agent_type == pb2.AgentType.TrainerT:
38-
self.agent = SampleTrainerAgent()
39-
self.agent.set_logger(self.logger)
38+
self.agent = SampleTrainerAgent(self.logger)
4039
self.debug_mode: bool = False
4140

4241

@@ -189,13 +188,20 @@ def serve(port, shared_lock, shared_number_of_connections):
189188

190189

191190
def main():
192-
global main_logger, log_dir
191+
global main_logger, log_dir, file_logging_level, player_file_logging_level
193192
parser = argparse.ArgumentParser(description='Run play maker server')
194193
parser.add_argument('-p', '--rpc-port', required=False, help='The port of the server', default=50051)
195194
parser.add_argument('-l', '--log-dir', required=False, help='The directory of the log file',
196195
default=f'logs/{datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}')
196+
parser.add_argument('--disable-log-file', required=False, help='Disable logging to a file', default=False, action='store_true')
197+
197198
args = parser.parse_args()
199+
198200
log_dir = args.log_dir
201+
if args.disable_log_file:
202+
file_logging_level = None
203+
player_file_logging_level = None
204+
199205
main_logger = setup_logger("pmservice", log_dir, console_level=console_logging_level, file_level=file_logging_level)
200206
main_logger.info("Starting server")
201207
manager = Manager()

src/interfaces/IAgent.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66

77

88
class IAgent(ABC):
9-
def __init__(self) -> None:
9+
def __init__(self, logger) -> None:
1010
super().__init__()
1111
self.wm: Union[WorldModel, None] = None
1212
self.actions: list[Union[PlayerAction, CoachAction, TrainerAction]] = []
1313
self.server_params: Union[ServerParam, None] = None
1414
self.player_params: Union[PlayerParam, None] = None
1515
self.player_types: dict[PlayerType] = {}
1616
self.debug_mode: bool = False
17-
self.logger: logging.Logger= None
17+
self.logger: logging.Logger = logger
1818

1919
def set_server_params(self, server_param: ServerParam):
2020
self.server_params = server_param
@@ -87,8 +87,4 @@ def add_action(self, action: Union[PlayerAction, CoachAction, TrainerAction]):
8787
self.actions.append(action)
8888

8989
def get_actions(self) -> list[Union[PlayerAction, CoachAction, TrainerAction]]:
90-
return self.actions
91-
92-
def set_logger(self, logger):
93-
self.logger = logger
94-
self.logger.debug(f"IAgent.set_logger: {logger}")
90+
return self.actions

src/sample_coach_agent.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55

66
class SampleCoachAgent(IAgent, ABC):
7-
def __init__(self):
8-
super().__init__()
7+
def __init__(self, logger) -> None:
8+
super().__init__(logger)
9+
self.logger.info('SampleCoachAgent created')
910
self.wm: WorldModel = None
1011
self.first_substitution = True
1112

src/sample_player_agent.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66

77

88
class SamplePlayerAgent(IAgent, ABC):
9-
def __init__(self):
10-
super().__init__()
9+
def __init__(self, logger) -> None:
10+
super().__init__(logger)
11+
self.logger.info('SamplePlayerAgent created')
1112
self.decision_maker = DecisionMaker()
1213
self.strategy = FormationStrategy()
1314
self.wm: WorldModel = None

src/sample_trainer_agent.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55

66
class SampleTrainerAgent(IAgent, ABC):
7-
def __init__(self):
8-
super().__init__()
7+
def __init__(self, logger) -> None:
8+
super().__init__(logger)
9+
self.logger.info('SampleTrainerAgent created')
910
self.wm: WorldModel = None
1011
self.first_substitution = True
1112

start_agent.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def run_server_script(args):
2121
# Define a wrapper function to pass the arguments to the main function
2222
def server_main():
2323
import sys
24-
sys.argv = ['server.py', '--rpc-port', str(args.rpc_port), '--log-dir', log_dir]
24+
sys.argv = ['server.py', '--rpc-port', str(args.rpc_port), '--log-dir', log_dir, '--disable-log-file' if args.disable_log_file else '']
2525
main()
2626

2727
# Start the main function as a new process
@@ -32,7 +32,10 @@ def server_main():
3232
def run_start_script(args):
3333
# Start the start.sh script in its own directory as a new process group
3434
process = subprocess.Popen(
35-
['bash', 'start-agent.sh' if not args.debug else 'start-debug.sh', '-t', args.team_name, '--rpc-port', args.rpc_port, '--rpc-type', 'grpc', '-p', args.server_port,
35+
['bash', 'start-agent.sh' if not args.debug else 'start-debug.sh',
36+
'-t', args.team_name,
37+
'--rpc-port', args.rpc_port, '--rpc-type', 'grpc',
38+
'-p', args.server_port, '-h', args.server_host,
3639
'--coach' if args.coach else '--goalie' if args.goalie else '--player'],
3740
cwd='scripts/proxy', # Corrected directory to where start.sh is located
3841
preexec_fn=os.setsid, # Create a new session and set the process group ID
@@ -44,16 +47,19 @@ def run_start_script(args):
4447
stop_thread = threading.Event()
4548

4649

47-
def stream_output_to_file(process, name):
50+
def stream_output_to_file(process, name, args):
4851
# Stream output from the process and log it to a file with the given name
49-
with open(f"{log_dir}/{name}.log", "a") as f:
50-
while not stop_thread.is_set():
51-
output = process.stdout.readline()
52-
if output:
52+
f = None if args.disable_log_file else open(f"{log_dir}/{name}.log", "a")
53+
while not stop_thread.is_set():
54+
output = process.stdout.readline()
55+
if output:
56+
if f:
5357
f.write(output.decode())
5458
f.flush()
5559
else:
56-
break
60+
print(output.decode())
61+
else:
62+
break
5763
process.stdout.close()
5864

5965
def kill_process_group(process):
@@ -79,10 +85,12 @@ def kill_rpc_server_process(process):
7985
parser.add_argument('-d', '--debug', required=False, help='Enable debug mode', default=False, action='store_true')
8086
parser.add_argument('--use-random-port', required=False, help='Use a random port for the server', default=False, action='store_true')
8187
parser.add_argument('--use-random-name', required=False, help='Use a random team name', default=False, action='store_true')
88+
parser.add_argument('--server-host', required=False, help='The host of the server', default='localhost')
8289
parser.add_argument('--server-port', required=False, help='The port of the server', default='6000')
8390
parser.add_argument('--close-server', required=False, help='Close the server', default=False, action='store_true')
8491
parser.add_argument('--coach', required=False, help='Use coach instead of proxy', default=False, action='store_true')
8592
parser.add_argument('--goalie', required=False, help='Use goalie instead of proxy', default=False, action='store_true')
93+
parser.add_argument('--disable-log-file', required=False, help='Disable logging to a file', default=False, action='store_true')
8694
parser.add_argument('--log-dir', required=False, help='The directory to store logs', default=None)
8795
args = parser.parse_args()
8896

@@ -91,7 +99,8 @@ def kill_rpc_server_process(process):
9199
log_dir = os.path.join(os.getcwd(), 'logs', f"{datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}_{random.randint(100000, 999999)}")
92100
else:
93101
log_dir = args.log_dir
94-
start_team_logger = setup_logger('start-team', log_dir, console_level=logging.DEBUG, file_level=logging.DEBUG, console_format_str='%(message)s')
102+
start_team_logger = setup_logger('start-team', log_dir, console_level=logging.DEBUG, file_level=logging.DEBUG if not args.disable_log_file else None,
103+
console_format_str='%(message)s')
95104

96105
start_team_logger.debug(f"Arguments: {args=}")
97106

@@ -119,7 +128,7 @@ def kill_rpc_server_process(process):
119128
# Monitor both processes and log their outputs
120129
start_team_logger.debug("Monitoring processes...")
121130

122-
start_thread = threading.Thread(target=stream_output_to_file, args=(start_process, 'proxy'))
131+
start_thread = threading.Thread(target=stream_output_to_file, args=(start_process, 'proxy', args))
123132
start_thread.start()
124133

125134
def signal_handler(sig, frame):

0 commit comments

Comments
 (0)