Skip to content

Commit

Permalink
refactor(server): replace print statements with logger
Browse files Browse the repository at this point in the history
- Introduced logging in `StackRun` to replace print-based messages
- Improved error handling for config file loading and parsing
- Replaced `cprint` with `logger.error` for consistent error messaging
- Ensured logging is used in `server.py` for startup, shutdown, and runtime messages
- Added missing exception handling for invalid providers

Signed-off-by: Sébastien Han <[email protected]>
  • Loading branch information
leseb committed Feb 25, 2025
1 parent 30f79fa commit 8eb4f7f
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 33 deletions.
41 changes: 21 additions & 20 deletions llama_stack/cli/stack/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
# the root directory of this source tree.

import argparse
import logging
import os
from pathlib import Path

from llama_stack.cli.subcommand import Subcommand

REPO_ROOT = Path(__file__).parent.parent.parent.parent

logger = logging.getLogger(__name__)


class StackRun(Subcommand):
def __init__(self, subparsers: argparse._SubParsersAction):
Expand Down Expand Up @@ -70,12 +73,10 @@ def _add_arguments(self):
type=str,
help="Image Type used during the build. This can be either conda or container or venv.",
choices=["conda", "container", "venv"],
default="conda",
)

def _run_stack_run_cmd(self, args: argparse.Namespace) -> None:
import yaml
from termcolor import cprint

from llama_stack.distribution.build import ImageType
from llama_stack.distribution.configure import parse_and_maybe_upgrade_config
Expand All @@ -85,10 +86,6 @@ def _run_stack_run_cmd(self, args: argparse.Namespace) -> None:
)
from llama_stack.distribution.utils.exec import formulate_run_args, run_with_pty

if not args.config:
self.parser.error("Must specify a config file to run")
return

config_file = Path(args.config)
has_yaml_suffix = args.config.endswith(".yaml")
template_name = None
Expand All @@ -115,11 +112,23 @@ def _run_stack_run_cmd(self, args: argparse.Namespace) -> None:
self.parser.error(
f"File {str(config_file)} does not exist.\n\nPlease run `llama stack build` to generate (and optionally edit) a run.yaml file"
)
return

print(f"Using run configuration: {config_file}")
config_dict = yaml.safe_load(config_file.read_text())
config = parse_and_maybe_upgrade_config(config_dict)
if not config_file.is_file():
self.parser.error(
f"Config file must be a valid file path, '{config_file}’ is not a file: type={type(config_file)}"
)

logger.info(f"Using run configuration: {config_file}")

try:
config_dict = yaml.safe_load(config_file.read_text())
except yaml.parser.ParserError as e:
self.parser.error(f"failed to load config file '{config_file}':\n {e}")

try:
config = parse_and_maybe_upgrade_config(config_dict)
except AttributeError as e:
self.parser.error(f"failed to parse config file '{config_file}':\n {e}")

run_args = formulate_run_args(args.image_type, args.image_name, config, template_name)

Expand All @@ -129,18 +138,10 @@ def _run_stack_run_cmd(self, args: argparse.Namespace) -> None:

for env_var in args.env:
if "=" not in env_var:
cprint(
f"Environment variable '{env_var}' must be in KEY=VALUE format",
color="red",
)
return
self.parser.error(f"Environment variable '{env_var}' must be in KEY=VALUE format")
key, value = env_var.split("=", 1) # split on first = only
if not key:
cprint(
f"Environment variable '{env_var}' has empty key",
color="red",
)
return
self.parser.error(f"Environment variable '{env_var}' has empty key")
run_args.extend(["--env", f"{key}={value}"])

if args.tls_keyfile and args.tls_certfile:
Expand Down
27 changes: 14 additions & 13 deletions llama_stack/distribution/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def handle_signal(app, signum, _) -> None:
not block the current execution.
"""
signame = signal.Signals(signum).name
print(f"Received signal {signame} ({signum}). Exiting gracefully...")
logger.info(f"Received signal {signame} ({signum}). Exiting gracefully...")

async def shutdown():
try:
Expand Down Expand Up @@ -184,9 +184,9 @@ async def shutdown():

@asynccontextmanager
async def lifespan(app: FastAPI):
print("Starting up")
logger.info("Starting up")
yield
print("Shutting down")
logger.info("Shutting down")
for impl in app.__llama_stack_impls__.values():
await impl.shutdown()

Expand Down Expand Up @@ -352,33 +352,33 @@ def main():
for env_pair in args.env:
try:
key, value = validate_env_pair(env_pair)
print(f"Setting CLI environment variable {key} => {value}")
logger.info(f"Setting CLI environment variable {key} => {value}")
os.environ[key] = value
except ValueError as e:
print(f"Error: {str(e)}")
logger.error(f"Error: {str(e)}")
sys.exit(1)

if args.yaml_config:
# if the user provided a config file, use it, even if template was specified
config_file = Path(args.yaml_config)
if not config_file.exists():
raise ValueError(f"Config file {config_file} does not exist")
print(f"Using config file: {config_file}")
logger.info(f"Using config file: {config_file}")
elif args.template:
config_file = Path(REPO_ROOT) / "llama_stack" / "templates" / args.template / "run.yaml"
if not config_file.exists():
raise ValueError(f"Template {args.template} does not exist")
print(f"Using template {args.template} config file: {config_file}")
logger.info(f"Using template {args.template} config file: {config_file}")
else:
raise ValueError("Either --yaml-config or --template must be provided")

with open(config_file, "r") as fp:
config = replace_env_vars(yaml.safe_load(fp))
config = StackRunConfig(**config)

print("Run configuration:")
logger.info("Run configuration:")
safe_config = redact_sensitive_fields(config.model_dump())
print(yaml.dump(safe_config, indent=2))
logger.info(yaml.dump(safe_config, indent=2))

app = FastAPI(lifespan=lifespan)
app.add_middleware(TracingMiddleware)
Expand All @@ -387,7 +387,8 @@ def main():

try:
impls = asyncio.run(construct_stack(config))
except InvalidProviderError:
except InvalidProviderError as e:
logger.error(f"Error: {str(e)}")
sys.exit(1)

if Api.telemetry in impls:
Expand Down Expand Up @@ -432,7 +433,7 @@ def main():
)
)

cprint(f"Serving API {api_str}", "white", attrs=["bold"])
logger.info(f"Serving API {api_str}")
for endpoint in endpoints:
cprint(f" {endpoint.method.upper()} {endpoint.route}", "white")

Expand Down Expand Up @@ -462,10 +463,10 @@ def main():
"ssl_keyfile": keyfile,
"ssl_certfile": certfile,
}
print(f"HTTPS enabled with certificates:\n Key: {keyfile}\n Cert: {certfile}")
logger.info(f"HTTPS enabled with certificates:\n Key: {keyfile}\n Cert: {certfile}")

listen_host = ["::", "0.0.0.0"] if not args.disable_ipv6 else "0.0.0.0"
print(f"Listening on {listen_host}:{port}")
logger.info(f"Listening on {listen_host}:{port}")

uvicorn_config = {
"app": app,
Expand Down

0 comments on commit 8eb4f7f

Please sign in to comment.