Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions src/aerie_cli/__main__.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
"""Programmatic entrypoint for CLI application.
"""
import sys
from rich.console import Console

import logging
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know I went back and forth on this, but I decided I like the ergonomics better if we configure a specific child logger in /src/utils/logger.py. Then, it's clearer in the code that the logger we import has been specifically configured for this application. For example:

from aerie_cli.utils.logger import aerie_cli_logger as logger

...

logger.info("Whatever")

import traceback

from aerie_cli.app import app
from aerie_cli.persistent import NoActiveSessionError
from aerie_cli.persistent import NoActiveSessionError, CURRENT_LOG_PATH
from aerie_cli.__version__ import __version__


def main():
try:
app()
except NoActiveSessionError:
Console().print(
logging.error(
"There is no active session. Please start a session with aerie-cli activate"
)
sys.exit(-1)
except Exception:
Console().print_exception()
except Exception as e:
logging.error(f"{type(e).__name__}\n"
"Check log file for more information:\n"
f"{CURRENT_LOG_PATH}")
# We don't want to print the full traceback,
# so we use debug
logging.debug(traceback.format_exc())
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
logging.debug(traceback.format_exc())
logging.debug(traceback.format_exc())
sys.exit(-1)



if __name__ == "__main__":
Expand Down
52 changes: 44 additions & 8 deletions src/aerie_cli/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
`app` is the CLI application with which all commands, subcommands, and callbacks are registered.
"""
import typer
import logging
import sys
from typing import Optional

from aerie_cli.commands import models
Expand All @@ -18,13 +20,16 @@
from aerie_cli.persistent import (
PersistentConfigurationManager,
PersistentSessionManager,
clear_old_log_files,
CURRENT_LOG_PATH
)
from aerie_cli.utils.prompts import select_from_list
from aerie_cli.utils.sessions import (
start_session_from_configuration,
get_active_session_client,
)
from aerie_cli.utils.configurations import find_configuration
from aerie_cli.utils.logger import TyperLoggingHandler

app = typer.Typer()
app.add_typer(plans.plans_app, name="plans")
Expand All @@ -38,7 +43,7 @@

def print_version(print_version: bool):
if print_version:
typer.echo(__version__)
logging.info(__version__)
raise typer.Exit()


Expand All @@ -53,9 +58,40 @@ def set_alternate_configuration(configuration_identifier: str):
def setup_global_command_context(hasura_admin_secret: str):
CommandContext.hasura_admin_secret = hasura_admin_secret

def setup_logging(debug: bool):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest centralizing this logic in src/utils/logger.py. Ideally, that module can have a function like set_log_level which is the callback for the --debug option.

clear_old_log_files()
file_formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
)
file_handler = logging.FileHandler(filename=str(CURRENT_LOG_PATH),
mode='w',
encoding='utf-8')
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(file_formatter)

console_formatter = logging.Formatter(
'%(message)s'
)
console_handler = TyperLoggingHandler()
level = logging.DEBUG if debug else logging.INFO
console_handler.setLevel(level) # Set the level of the stream and file handlers to different ones
# Debug should be in file, others should go into stdout
# unless verbose/debug option is selected
console_handler.setFormatter(console_formatter)
logging.basicConfig(level=logging.DEBUG,
handlers=[file_handler,
console_handler])


@app.callback()
def app_callback(
debug: Optional[bool]=typer.Option(
False,
"--debug",
"-d",
callback=setup_logging,
help="View the debug output",
),
version: Optional[bool] = typer.Option(
None,
"--version",
Expand Down Expand Up @@ -108,7 +144,7 @@ def activate_session(
if role in session.aerie_jwt.allowed_roles:
session.change_role(role)
else:
typer.echo(f"Role {role} not in allowed roles")
logging.info(f"Role {role} not in allowed roles")

PersistentSessionManager.set_active_session(session)

Expand All @@ -120,9 +156,9 @@ def deactivate_session():
"""
name = PersistentSessionManager.unset_active_session()
if name is None:
typer.echo("No active session")
logging.info("No active session")
else:
typer.echo(f"Deactivated session: {name}")
logging.info(f"Deactivated session: {name}")


@app.command("role")
Expand All @@ -137,14 +173,14 @@ def change_role(
client = get_active_session_client()

if role is None:
typer.echo(f"Active Role: {client.aerie_host.active_role}")
logging.info(f"Active Role: {client.aerie_host.active_role}")
role = select_from_list(client.aerie_host.aerie_jwt.allowed_roles)

client.aerie_host.change_role(role)

PersistentSessionManager.set_active_session(client.aerie_host)

typer.echo(f"Changed role to: {client.aerie_host.active_role}")
logging.info(f"Changed role to: {client.aerie_host.active_role}")


@app.command("status")
Expand All @@ -156,6 +192,6 @@ def print_status():
client = CommandContext.get_client()

if client.aerie_host.configuration_name:
typer.echo(f"Active configuration: {client.aerie_host.configuration_name}")
logging.info(f"Active configuration: {client.aerie_host.configuration_name}")

typer.echo(f"Active role: {client.aerie_host.active_role}")
logging.info(f"Active role: {client.aerie_host.active_role}")
8 changes: 4 additions & 4 deletions src/aerie_cli/commands/configurations.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"""

import typer
import logging
import json
from pathlib import Path
from rich.console import Console
Expand Down Expand Up @@ -79,10 +80,10 @@ def upload_configurations(
raise e

if len(new_confs):
Console().print(f"Added configurations: {', '.join(new_confs)}")
logging.info(f"Added configurations: {', '.join(new_confs)}")

if len(updated_confs):
Console().print(f"Updated configurations: {', '.join(updated_confs)}")
logging.info(f"Updated configurations: {', '.join(updated_confs)}")


@app.command('list')
Expand All @@ -98,8 +99,7 @@ def list_configurations():
except NoActiveSessionError:
active_config = None

typer.echo(f"Configuration file location: {CONFIGURATION_FILE_PATH}")
typer.echo()
logging.info(f"Configuration file location: {CONFIGURATION_FILE_PATH}")

table = Table(title='Aerie Host Configurations',
caption='Active configuration in red')
Expand Down
9 changes: 5 additions & 4 deletions src/aerie_cli/commands/constraints.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json

import arrow
import logging
import typer
from rich.console import Console
from rich.table import Table
Expand Down Expand Up @@ -34,7 +35,7 @@ def upload(
"definition": str_contents
}
constraint_id = client.upload_constraint(constraint)
typer.echo(f"Created constraint: {constraint_id}")
logging.info(f"Created constraint: {constraint_id}")

@app.command()
def delete(
Expand All @@ -44,7 +45,7 @@ def delete(

client = CommandContext.get_client()
client.delete_constraint(id)
typer.echo(f"Successfully deleted constraint {id}")
logging.info(f"Successfully deleted constraint {id}")

@app.command()
def update(
Expand All @@ -66,7 +67,7 @@ def update(
"definition": str_contents
}
constraint_id = client.update_constraint(id, constraint)
typer.echo(f"Updated constraint: {constraint_id}")
logging.info(f"Updated constraint: {constraint_id}")

@app.command()
def violations(
Expand All @@ -75,7 +76,7 @@ def violations(

client = CommandContext.get_client()
constraint_violations = client.get_constraint_violations(plan_id)
typer.echo(f"Constraint violations: {constraint_violations}")
logging.info(f"Constraint violations: {constraint_violations}")



7 changes: 4 additions & 3 deletions src/aerie_cli/commands/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import arrow
import typer
import logging
from rich.console import Console
from rich.table import Table

Expand Down Expand Up @@ -30,7 +31,7 @@ def upload(
contents = in_file.read()
schema_data = json.loads(contents)
result = client.add_directive_metadata_schemas(schema_data["schemas"])
typer.echo(f"{len(schema_data['schemas'])} new schema have been added.")
logging.info(f"{len(schema_data['schemas'])} new schema have been added.")


@app.command()
Expand All @@ -41,7 +42,7 @@ def delete(
):
"""Delete a metadata schema by its name."""
resp = CommandContext.get_client().delete_directive_metadata_schema(schema_name)
typer.echo(f"Schema `{resp}` has been removed.")
logging.info(f"Schema `{resp}` has been removed.")


@app.command()
Expand Down Expand Up @@ -72,4 +73,4 @@ def clean():
for schema in resp:
client.delete_directive_metadata_schema(schema["key"])

typer.echo(f"All metadata schemas have been deleted")
logging.info(f"All metadata schemas have been deleted")
9 changes: 5 additions & 4 deletions src/aerie_cli/commands/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json

import arrow
import logging
import typer
from rich.console import Console
from rich.table import Table
Expand Down Expand Up @@ -63,9 +64,9 @@ def upload(

# Attach sim template to model
client.upload_sim_template(model_id=model_id, args=json_obj, name=name)
typer.echo(f"Attached simulation template to model {model_id}.")
logging.info(f"Attached simulation template to model {model_id}.")

typer.echo(f"Created new mission model: {model_name} with Model ID: {model_id}")
logging.info(f"Created new mission model: {model_name} with Model ID: {model_id}")


@app.command()
Expand All @@ -77,7 +78,7 @@ def delete(
"""Delete a mission model by its model id."""

model_name = CommandContext.get_client().delete_mission_model(model_id)
typer.echo(f"Mission Model `{model_name}` with ID: {model_id} has been removed.")
logging.info(f"Mission Model `{model_name}` with ID: {model_id} has been removed.")


@app.command()
Expand All @@ -89,7 +90,7 @@ def clean():
for api_mission_model in resp:
client.delete_mission_model(api_mission_model.id)

typer.echo(f"All mission models have been deleted")
logging.info(f"All mission models have been deleted")


@app.command()
Expand Down
Loading