monitor: refactor class LogLine to log_entry()

The class LogLine() is purely used as a dataclass with no state
and the only function on it is `as_dict()`. This got refactored
into a new function `log_entry()` because there is no need for
this to be a class. The function that takes the same inputs.
This commit is contained in:
Michael Vogt 2023-11-22 08:53:41 +01:00 committed by Ondřej Budai
parent 16c1768780
commit ac16590838
2 changed files with 39 additions and 31 deletions

View file

@ -149,31 +149,21 @@ class Progress:
return d
class LogLine:
"""A single JSON serializable log line
Create a single log line with a given message, error message, context, and progress objects.
All arguments are optional. A timestamp is added to the dictionary when calling the 'as_dict()' method.
def log_entry(message: Optional[str] = None,
context: Optional[Context] = None,
progress: Optional[Progress] = None) -> dict:
"""
def __init__(self, *,
message: Optional[str] = None,
error: Optional[str] = None,
context: Optional[Context] = None,
progress: Optional[Progress] = None):
self.message = message
self.error = error
self.context = context
self.progress = progress
def as_dict(self):
return omitempty({
"message": self.message,
"error": self.error,
"context": self.context.as_dict(),
"progress": self.progress.as_dict(),
"timestamp": time.time(),
})
Create a single log entry dict with a given message, context, and progress objects.
All arguments are optional. A timestamp is added to the message.
"""
# we probably want to add an (optional) error message here too once the
# monitors support that
return omitempty({
"message": message,
"context": context.as_dict() if context else None,
"progress": progress.as_dict() if progress else None,
"timestamp": time.time(),
})
class TextWriter:
@ -331,16 +321,15 @@ class JSONSeqMonitor(BaseMonitor):
oo = self._context.origin
if origin is not None:
self._context.origin = origin
line = LogLine(message=message, context=self._context, progress=self._progress)
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
entry = log_entry(message=message, context=self._context, progress=self._progress)
self._jsonseq(entry)
# restore old origin
self._context.origin = oo
def _jsonseq(self, data):
def _jsonseq(self, entry):
# follow rfc7464 (application/json-seq)
self.out.write("\x1e")
json.dump(data, self.out)
json.dump(entry, self.out)
self.out.write("\n")

View file

@ -7,13 +7,14 @@ import json
import os
import sys
import tempfile
import time
import unittest
from collections import defaultdict
import osbuild
import osbuild.meta
from osbuild.monitor import LogMonitor
from osbuild.monitor import JSONSeqMonitor, Context, Progress, LogLine
from osbuild.monitor import JSONSeqMonitor, Context, Progress, log_entry
from osbuild.objectstore import ObjectStore
from osbuild.pipeline import Runner
@ -241,3 +242,21 @@ def test_json_progress_monitor():
assert logitem["message"] == "pipeline 2 starting"
assert logitem["context"]["origin"] == "org.osbuild"
assert logitem["context"]["pipeline"]["name"] == "test-pipeline-second"
def test_log_line_empty_is_fine():
empty = log_entry()
assert len(empty) == 1
assert empty["timestamp"] > time.time()-60
assert empty["timestamp"] < time.time()+60
def test_log_line_with_entries():
ctx = Context("some-origin")
progress = Progress(name="foo", total=2)
entry = log_entry("some-msg", ctx, progress)
assert len(entry) == 4
assert entry["message"] == "some-msg"
assert isinstance(entry["context"], dict)
assert isinstance(entry["progress"], dict)
assert entry["timestamp"] > 0