Repository navigation
Expand file tree
/
Copy pathmain.py
More file actions
138 lines (112 loc) · 5.04 KB
/
Copy pathmain.py
File metadata and controls
138 lines (112 loc) · 5.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
"""
main.py - Entry point for the FLocKit application (FLock.io).
Top-level script that bootstraps the entire application: it parses CLI
arguments (so ``--version`` / ``--help`` exit cleanly before any logging
side-effects), sets up the centralised logger, loads and validates the YAML
configuration, initialises the selected template's task model, and wraps it
in the FLock SDK HTTP server before starting the request loop.
Key Functions:
main - Application entry point.
_resolve_logging_config - Pull optional logging settings out of common_args.
Usage:
python main.py --conf configs/my_config.yaml [--port 5000]
flockit --conf ... --port ... # after `pip install flockit`
"""
from __future__ import annotations
import sys
from flockit_logger import setup_logger, get_logger
from constants import (
DEFAULT_SDK_PORT,
PRODUCT_NAME,
PRODUCT_TAGLINE,
VENDOR,
get_product_version,
)
from arguments import load_arguments
from bootstrap import init
from flock_sdk import FlockSDK
logger = get_logger(__name__)
# Single brand prefix reused across every terminal-state log line so the
# FLock.io / FLocKit identity is the last thing in the operator's
# terminal (or log file) regardless of exit path.
_BRAND_PREFIX = PRODUCT_TAGLINE
def _resolve_logging_config(args) -> tuple[str | None, str | None]:
"""
Pull optional logging settings out of ``common_args``.
Accepts ``common_args.log_level`` and ``common_args.log_file``. Returning
``None`` means "use the environment variable or the compiled-in default"
so explicit CLI / env overrides still work.
"""
common = getattr(args, "common_args", None)
if common is None:
return None, None
level = getattr(common, "log_level", None)
log_file = getattr(common, "log_file", None)
return (
str(level) if level is not None else None,
str(log_file) if log_file is not None else None,
)
def main() -> None:
"""
Application entry point.
Loads configuration, initialises the task model, and starts the
FLock SDK Flask server. Exits with appropriate codes on error.
"""
try:
# Parse CLI first so ``--version`` / ``--help`` can exit cleanly
# without printing the brand banner or any Logger-initialised lines.
args = load_arguments()
# Bootstrap the logger now that we know the run is proceeding. The
# level and file sink can still be overridden below via
# ``common_args.log_level`` / ``common_args.log_file``.
setup_logger()
logger.info(
f"{PRODUCT_NAME} ({VENDOR}) v{get_product_version()} starting"
)
logger.info("Configuration loaded successfully")
# Re-initialise the logger with any user-provided level / file sink.
level_override, file_override = _resolve_logging_config(args)
if level_override is not None or file_override is not None:
setup_logger(level=level_override, log_file=file_override)
logger.info(
f"Logger reconfigured from config | level={level_override or 'default'} | "
f"file={file_override or 'stderr-only'}"
)
# Initialise the task model for the selected template.
template_name = getattr(args.common_args, "template_name", "unknown")
run_mode = getattr(args.common_args, "run_mode", "production")
logger.info(f"Initialising task | template={template_name} | run_mode={run_mode}")
task_model = init(args)
logger.info(f"Task model initialised | class={type(task_model).__name__}")
# Extract server settings.
configured_port = getattr(args.common_args, "port", None)
port = int(DEFAULT_SDK_PORT if configured_port is None else configured_port)
# Create and start the FLock SDK server.
sdk = FlockSDK(task_model, debug=False, port=port)
logger.info(f"Starting FLock SDK server | port={port} | template={template_name}")
sdk.run()
except FileNotFoundError as exc:
logger.critical(f"{_BRAND_PREFIX} — configuration file not found: {exc}")
sys.exit(1)
except ValueError as exc:
# Configuration errors: print traceback at DEBUG to keep the console
# uncluttered, but always emit the full context for file sinks.
logger.opt(exception=True).error(f"{_BRAND_PREFIX} — configuration error: {exc}")
sys.exit(1)
except ImportError as exc:
logger.opt(exception=True).critical(
f"{_BRAND_PREFIX} — missing dependency or module: {exc}"
)
sys.exit(1)
except KeyboardInterrupt:
logger.info(f"{_BRAND_PREFIX} — process interrupted by user (SIGINT)")
sys.exit(130)
except Exception as exc:
# loguru ignores stdlib's ``exc_info=True`` kwarg; ``opt(exception=True)``
# is the canonical way to attach a traceback to the log record.
logger.opt(exception=True).critical(
f"{_BRAND_PREFIX} — unexpected fatal error: {exc}"
)
sys.exit(1)
if __name__ == "__main__":
main()