Changeset 11187 in ntrip for trunk/BNC/tests/tools


Ignore:
Timestamp:
Nov 9, 2026, 5:37:55 PM (2 days ago)
Author:
stuerze
Message:

Structured logging improved

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/BNC/tests/tools/logcheck.py

    r11179 r11187  
    66Checks that every line of the JSON file is a JSON object and every line of the
    77logfmt file a sequence of key=value pairs, that both carry the same records,
    8 that the records have the mandatory keys in the documented order, that 'time'
    9 (UTC) is 'gpst' minus the GPS-UTC leap seconds and that the 'msg' of the
    10 records equals the text of the classic logfile line by line (classic lines
    11 without their "yy-mm-dd hh:mm:ss " prefix; the start line is skipped, it goes
    12 to the file of the current date). Prints a summary of the records per level,
     8that the records have the mandatory keys in the documented order (optional
     9'epoch' after 'time', GPS Time without 'Z'), that the 'msg' of the records
     10(for RTCM scan message types: 'mp', 'message_type', 'size') equals the text of
     11the classic logfile line by line (classic lines without
     12their "yy-mm-dd hh:mm:ss " prefix; the start line is skipped, it goes to the
     13file of the current date) and that 'time' (UTC) is the GPS Time stamp of the
     14classic line minus the GPS-UTC leap seconds. Prints a summary of the records per level,
    1315component and event; exit code 1 on any error.
    1416"""
    … …  
    2022import sys
    2123
    22 HEAD = ["time", "gpst", "level", "component", "event"]
     24HEAD = ["time", "level", "component", "event"]
    2325LEVELS = {"info", "warning", "error"}
    2426LEAP_GPS_UTC = 18          # valid since 2017-01-01
    … …  
    6870
    6971
     72def classic_text(r):
     73    """Text of the classic logfile line of a record: 'msg', except for the
     74    message types of the RTCM scan, which carry the short text 'Received message'
     75    and the details in their fields."""
     76    if r.get("event") == "stream_content" and "message_type" in r:
     77        if r["msg"] != "Received message":
     78            return "unexpected msg %r" % r["msg"]
     79        size = " (size %d)" % r["size"] if "size" in r else " "
     80        return "%s: Received message type %d%s" % (r["mp"], r["message_type"], size)
     81    return r.get("msg")
     82
     83
    7084def main():
    7185    errors = []
    72     classic = []
     86    classic, stamps = [], []
    7387    for line in open(sys.argv[1], encoding="latin-1", newline="").read().split("\r\n"):
    7488        if not line or "========== Start BNC" in line:
    7589            continue
    76         classic.append(line[18:] if re.match(r"\d\d-\d\d-\d\d \d\d:\d\d:\d\d ", line) else line)
     90        if re.match(r"\d\d-\d\d-\d\d \d\d:\d\d:\d\d ", line):
     91            classic.append(line[18:])
     92            stamps.append(datetime.datetime.strptime(line[:17], "%y-%m-%d %H:%M:%S"))
     93        else:
     94            classic.append(line)
     95            stamps.append(None)
    7796
    7897    recs = []
    … …  
    92111            errors.append("json %d records, logfmt %d" % (len(recs), len(lf)))
    93112        for k, (a, b) in enumerate(zip(recs, lf), 1):
    94             if list(a.keys()) != list(b.keys()) or any(a[x] != b[x] for x in a):
     113            # the start line carries the wall clock time of each run
     114            start = "========== Start BNC" in a.get("msg", "")
     115            if list(a.keys()) != list(b.keys()) or any(a[x] != b[x] for x in a
     116                                                        if not (start and x == "time")):
    95117                errors.append("record %d differs between json and logfmt" % k)
    96118
    … …  
    98120    for k, r in enumerate(recs, 1):
    99121        keys = list(r.keys())
    100         if keys[:5] != HEAD or keys[-2:] != ["msg", "v"]:
     122        if keys[1:2] == ["epoch"]:
     123            try:
     124                datetime.datetime.strptime(r["epoch"], "%Y-%m-%dT%H:%M:%S.%f")
     125            except ValueError:
     126                errors.append("record %d: epoch %s" % (k, r["epoch"]))
     127            keys = keys[:1] + keys[2:]
     128        if keys[:4] != HEAD or keys[-2:] != ["msg", "v"]:
    101129            errors.append("record %d: keys %s" % (k, keys))
    102130            continue
    103131        if r["level"] not in LEVELS:
    104132            errors.append("record %d: level %s" % (k, r["level"]))
    105         utc = datetime.datetime.strptime(r["time"], "%Y-%m-%dT%H:%M:%S.%fZ")
    106         gps = datetime.datetime.strptime(r["gpst"], "%Y-%m-%dT%H:%M:%S.%f")
    107         if (gps - utc).total_seconds() != LEAP_GPS_UTC:
    108             errors.append("record %d: time %s gpst %s" % (k, r["time"], r["gpst"]))
    109133        count[(r["level"], r["component"], r["event"])] += 1
    110134
    111     msgs = [r.get("msg") for r in recs if "========== Start BNC" not in r.get("msg", "")]
     135    body = [r for r in recs if "========== Start BNC" not in r.get("msg", "")]
     136    msgs = [classic_text(r) for r in body]
     137    for k, (r, st) in enumerate(zip(body, stamps), 1):
     138        utc = datetime.datetime.strptime(r["time"], "%Y-%m-%dT%H:%M:%S.%fZ")
     139        if st is not None and (st - utc.replace(microsecond=0)).total_seconds() != LEAP_GPS_UTC:
     140            errors.append("record %d: time %s, classic %s" % (k, r["time"], st))
    112141    if msgs != classic:
    113142        for k, (a, b) in enumerate(zip(msgs, classic), 1):
Note: See TracChangeset for help on using the changeset viewer.