Skip to content

Commit 565aab3

Browse files
committed
Improve CLI logging
1 parent 6250515 commit 565aab3

File tree

2 files changed

+98
-48
lines changed

2 files changed

+98
-48
lines changed

antares-python/src/antares/cli.py

Lines changed: 81 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,112 @@
1+
import sys
12
import asyncio
2-
3+
import json
34
import typer
5+
import logging
46
from rich.console import Console
57
from rich.theme import Theme
68

7-
from antares import AntaresClient, ShipConfig
9+
from antares import ShipConfig, AntaresClient
810
from antares.config_loader import load_config
9-
10-
app = typer.Typer(help="Antares Simulation CLI")
11-
12-
console = Console(
13-
theme=Theme(
14-
{
15-
"info": "green",
16-
"warn": "yellow",
17-
"error": "bold red",
18-
}
19-
)
11+
from antares.errors import (
12+
ConnectionError,
13+
SimulationError,
14+
SubscriptionError
2015
)
21-
22-
23-
def build_client(config_path: str | None, verbose: bool) -> AntaresClient:
24-
settings = load_config(config_path)
25-
26-
if verbose:
27-
console.print(f"[info]Using settings: {settings.model_dump()}")
28-
29-
return AntaresClient(
30-
base_url=settings.base_url,
31-
tcp_host=settings.tcp_host,
32-
tcp_port=settings.tcp_port,
33-
timeout=settings.timeout,
34-
auth_token=settings.auth_token,
35-
)
16+
from antares.logger import setup_logging
17+
18+
app = typer.Typer(name="antares", help="Antares CLI for ship simulation")
19+
console = Console(theme=Theme({
20+
"info": "green",
21+
"warn": "yellow",
22+
"error": "bold red"
23+
}))
24+
25+
26+
def handle_error(message: str, code: int, json_output: bool = False):
27+
logger = logging.getLogger("antares.cli")
28+
if json_output:
29+
typer.echo(json.dumps({"error": message}), err=True)
30+
else:
31+
console.print(f"[error]{message}")
32+
logger.error("Exiting with error: %s", message)
33+
raise typer.Exit(code)
34+
35+
36+
def build_client(config_path: str | None, verbose: bool, json_output: bool) -> AntaresClient:
37+
setup_logging(level=logging.DEBUG if verbose else logging.INFO)
38+
logger = logging.getLogger("antares.cli")
39+
40+
try:
41+
settings = load_config(config_path)
42+
if verbose:
43+
console.print(f"[info]Using settings: {settings.model_dump()}")
44+
logger.debug("Loaded settings: %s", settings.model_dump())
45+
return AntaresClient(
46+
base_url=settings.base_url,
47+
tcp_host=settings.tcp_host,
48+
tcp_port=settings.tcp_port,
49+
timeout=settings.timeout,
50+
auth_token=settings.auth_token,
51+
)
52+
except Exception as e:
53+
handle_error(f"Failed to load configuration: {e}", code=1, json_output=json_output)
3654

3755

3856
@app.command()
3957
def reset(
40-
config: str = typer.Option(None, help="Path to config TOML file"),
58+
config: str = typer.Option(None),
4159
verbose: bool = typer.Option(False, "--verbose", "-v"),
60+
json_output: bool = typer.Option(False, "--json", help="Output in JSON format")
4261
):
43-
"""Reset the simulation."""
44-
client = build_client(config, verbose)
45-
client.reset_simulation()
46-
console.print("[info]✅ Simulation reset.")
62+
client = build_client(config, verbose, json_output)
63+
try:
64+
client.reset_simulation()
65+
msg = "✅ Simulation reset."
66+
typer.echo(json.dumps({"message": msg}) if json_output else msg)
67+
except (ConnectionError, SimulationError) as e:
68+
handle_error(str(e), code=2, json_output=json_output)
4769

4870

4971
@app.command()
5072
def add_ship(
5173
x: float,
5274
y: float,
53-
config: str = typer.Option(None, help="Path to config TOML file"),
75+
config: str = typer.Option(None),
5476
verbose: bool = typer.Option(False, "--verbose", "-v"),
77+
json_output: bool = typer.Option(False, "--json", help="Output in JSON format")
5578
):
56-
"""Add a ship to the simulation at (x, y)."""
57-
client = build_client(config, verbose)
58-
ship = ShipConfig(initial_position=(x, y))
59-
client.add_ship(ship)
60-
console.print(f"[info]🚢 Added ship at ({x}, {y})")
79+
client = build_client(config, verbose, json_output)
80+
try:
81+
ship = ShipConfig(initial_position=(x, y))
82+
client.add_ship(ship)
83+
msg = f"🚢 Added ship at ({x}, {y})"
84+
typer.echo(json.dumps({"message": msg}) if json_output else msg)
85+
except (ConnectionError, SimulationError) as e:
86+
handle_error(str(e), code=2, json_output=json_output)
6187

6288

6389
@app.command()
6490
def subscribe(
65-
config: str = typer.Option(None, help="Path to config TOML file"),
91+
config: str = typer.Option(None),
6692
verbose: bool = typer.Option(False, "--verbose", "-v"),
93+
json_output: bool = typer.Option(False, "--json", help="Output in JSON format"),
94+
log_file: str = typer.Option("antares.log", help="Path to log file")
6795
):
68-
"""Subscribe to simulation data stream."""
69-
client = build_client(config, verbose)
96+
setup_logging(log_file=log_file, level=logging.DEBUG if verbose else logging.INFO)
97+
logger = logging.getLogger("antares.cli")
98+
99+
client = build_client(config, verbose, json_output)
70100

71101
async def _sub():
72-
async for event in client.subscribe():
73-
console.print_json(data=event)
102+
try:
103+
async for event in client.subscribe():
104+
if json_output:
105+
typer.echo(json.dumps(event))
106+
else:
107+
console.print_json(data=event)
108+
logger.debug("Received event: %s", event)
109+
except SubscriptionError as e:
110+
handle_error(str(e), code=3, json_output=json_output)
74111

75112
asyncio.run(_sub())
76-
77-
78-
if __name__ == "__main__":
79-
app()
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import logging
2+
from pathlib import Path
3+
from rich.logging import RichHandler
4+
5+
def setup_logging(log_file: str = "antares.log", level: int = logging.INFO) -> None:
6+
"""Configure logging to both rich console and a file."""
7+
Path(log_file).parent.mkdir(parents=True, exist_ok=True)
8+
9+
logging.basicConfig(
10+
level=level,
11+
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
12+
datefmt="[%Y-%m-%d %H:%M:%S]",
13+
handlers=[
14+
RichHandler(rich_tracebacks=True, show_path=False),
15+
logging.FileHandler(log_file, encoding="utf-8")
16+
]
17+
)

0 commit comments

Comments
 (0)