osbuild: make jsonseq montior creation more uniform
This changes the way monitors are initialized to always include a `manifest` and now they will always log a `start` message. This makes creation of a monitor symetric accross all monitors again and no special cases for JSONSeqMonitor are required. It means one needs to run the json-seq monitor with: ``` $ python3 -m osbuild --monitor=JSONSeqMonitor ``` Fwiw, I'm not 100% confident this is a win but it feels slightly more right then the special cases in `main_cli.py` that is replaces.
This commit is contained in:
parent
9bb42459aa
commit
16c1768780
2 changed files with 26 additions and 36 deletions
|
|
@ -87,10 +87,6 @@ def parse_arguments(sys_argv: List[str]) -> argparse.Namespace:
|
|||
help="object to export, can be passed multiple times")
|
||||
parser.add_argument("--json", action="store_true",
|
||||
help="output results in JSON format")
|
||||
parser.add_argument("--json-mode", metavar="MODE", type=str, default="batch",
|
||||
help=("output mode for JSON format; "
|
||||
"'batch' (default if unspecified) mode prints all the results when the build ends "
|
||||
"'jsonseq' prints status updates while building with each line being a JSON object"))
|
||||
parser.add_argument("--output-directory", metavar="DIRECTORY", type=os.path.abspath,
|
||||
help="directory where result objects are stored")
|
||||
parser.add_argument("--inspect", action="store_true",
|
||||
|
|
@ -167,19 +163,8 @@ def osbuild_cli() -> int:
|
|||
monitor_name = args.monitor
|
||||
if not monitor_name:
|
||||
monitor_name = "NullMonitor" if args.json else "LogMonitor"
|
||||
|
||||
outfd = sys.stdout.fileno()
|
||||
if args.json:
|
||||
if args.json_mode == "jsonseq":
|
||||
monitor = osbuild.monitor.JSONSeqMonitor(outfd, manifest)
|
||||
monitor.log("start", origin="org.osbuild.main")
|
||||
elif args.json_mode == "batch":
|
||||
monitor = osbuild.monitor.NullMonitor(outfd)
|
||||
else:
|
||||
print(f"unknown json mode {args.json_mode}")
|
||||
return 1
|
||||
else:
|
||||
monitor = osbuild.monitor.make(monitor_name, args.monitor_fd)
|
||||
monitor = osbuild.monitor.make(monitor_name, args.monitor_fd, manifest)
|
||||
monitor.log(f"starting {args.manifest_path}", origin="org.osbuild.main")
|
||||
|
||||
try:
|
||||
with ObjectStore(args.store) as object_store:
|
||||
|
|
@ -207,10 +192,9 @@ def osbuild_cli() -> int:
|
|||
export(pid, output_directory, object_store, manifest)
|
||||
|
||||
if args.json:
|
||||
if args.json_mode == "batch":
|
||||
r = fmt.output(manifest, r, object_store)
|
||||
json.dump(r, sys.stdout)
|
||||
sys.stdout.write("\n")
|
||||
r = fmt.output(manifest, r, object_store)
|
||||
json.dump(r, sys.stdout)
|
||||
sys.stdout.write("\n")
|
||||
else:
|
||||
if r["success"]:
|
||||
for name, pl in manifest.pipelines.items():
|
||||
|
|
|
|||
|
|
@ -207,9 +207,10 @@ class TextWriter:
|
|||
class BaseMonitor(abc.ABC):
|
||||
"""Base class for all pipeline monitors"""
|
||||
|
||||
def __init__(self, fd: int):
|
||||
def __init__(self, fd: int, manifest: Optional[osbuild.Manifest] = None) -> None:
|
||||
"""Logging will be done to file descriptor `fd`"""
|
||||
self.out = TextWriter(fd)
|
||||
self.manifest = manifest
|
||||
|
||||
def begin(self, pipeline: osbuild.Pipeline):
|
||||
"""Called once at the beginning of a pipeline"""
|
||||
|
|
@ -246,8 +247,8 @@ class LogMonitor(BaseMonitor):
|
|||
sequences will be used to highlight sections of the log.
|
||||
"""
|
||||
|
||||
def __init__(self, fd: int):
|
||||
super().__init__(fd)
|
||||
def __init__(self, fd: int, manifest: Optional[osbuild.Manifest] = None):
|
||||
super().__init__(fd, manifest)
|
||||
self.timer_start = 0
|
||||
|
||||
def result(self, result):
|
||||
|
|
@ -303,7 +304,7 @@ class JSONSeqMonitor(BaseMonitor):
|
|||
"""Monitor that prints the log output of modules wrapped in json-seq objects with context and progress metadata"""
|
||||
|
||||
def __init__(self, fd: int, manifest: osbuild.Manifest):
|
||||
super().__init__(fd)
|
||||
super().__init__(fd, manifest)
|
||||
self._ctx_ids: Set[str] = set()
|
||||
self._progress = Progress("pipelines", len(manifest.pipelines))
|
||||
self._context = Context(origin="org.osbuild")
|
||||
|
|
@ -317,32 +318,37 @@ class JSONSeqMonitor(BaseMonitor):
|
|||
self._progress.incr()
|
||||
|
||||
def stage(self, stage: osbuild.Stage):
|
||||
self._context.stage(stage)
|
||||
self._progress.incr(depth=1)
|
||||
self._module(stage)
|
||||
|
||||
def assembler(self, assembler):
|
||||
self.module(assembler)
|
||||
self._module(assembler)
|
||||
|
||||
def module(self, module):
|
||||
self.stage(module)
|
||||
def _module(self, module):
|
||||
self._context.stage(module)
|
||||
self._progress.incr(depth=1)
|
||||
|
||||
def log(self, message, origin: Optional[str] = None):
|
||||
oo = self._context.origin
|
||||
if origin is not None:
|
||||
self._context.origin = origin
|
||||
line = LogLine(message=message, context=self._context, progress=self._progress)
|
||||
# follow rfc7464 (application/json-seq)
|
||||
self.out.write(u"\x1e")
|
||||
json.dump(line.as_dict(), self.out)
|
||||
self.out.write("\n")
|
||||
self._jsonseq(line.as_dict())
|
||||
# needs to be here as LogLine has a ref to self._context so updates
|
||||
# before line.as_dict() will be have a different context
|
||||
self._context.origin = oo
|
||||
|
||||
def _jsonseq(self, data):
|
||||
# follow rfc7464 (application/json-seq)
|
||||
self.out.write("\x1e")
|
||||
json.dump(data, self.out)
|
||||
self.out.write("\n")
|
||||
|
||||
def make(name, fd):
|
||||
|
||||
def make(name, fd, manifest):
|
||||
module = sys.modules[__name__]
|
||||
monitor = getattr(module, name, None)
|
||||
if not monitor:
|
||||
raise ValueError(f"Unknown monitor: {name}")
|
||||
if not issubclass(monitor, BaseMonitor):
|
||||
raise ValueError(f"Invalid monitor: {name}")
|
||||
return monitor(fd)
|
||||
return monitor(fd, manifest)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue