Skip to content

Commit a6c3e5c

Browse files
committed
properly parse all structured log messages
1 parent d35423a commit a6c3e5c

1 file changed

Lines changed: 21 additions & 5 deletions

File tree

meshtastic/slog/slog.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ def __init__(self, code: str, fields: list[tuple[str, pa.DataType]]) -> None:
5151
"" if f[1] == pa.string() else ":d"
5252
) # treat as a string or an int (the only types we have so far)
5353
fmt += "{" + f[0] + suffix + "}"
54-
self.format = parse.compile(fmt)
54+
self.format = parse.compile(
55+
fmt
56+
) # We include a catchall matcher at the end - to ignore stuff we don't understand
5557

5658

5759
"""A dictionary mapping from logdef code to logdef"""
@@ -60,7 +62,7 @@ def __init__(self, code: str, fields: list[tuple[str, pa.DataType]]) -> None:
6062
for d in [
6163
LogDef("B", [("board_id", pa.uint32()), ("sw_version", pa.string())]),
6264
LogDef("PM", [("pm_mask", pa.uint64()), ("pm_reason", pa.string())]),
63-
LogDef("PS", [("ps_state", pa.uint64())]),
65+
LogDef("PS", [("ps_state", pa.uint32())]),
6466
]
6567
}
6668
log_regex = re.compile(".*S:([0-9A-Za-z]+):(.*)")
@@ -139,11 +141,14 @@ def __init__(self, client: MeshInterface, dir_path: str, include_raw=True) -> No
139141
def listen_glue(line, interface): # pylint: disable=unused-argument
140142
self._onLogMessage(line)
141143

142-
self.listener = pub.subscribe(listen_glue, TOPIC_MESHTASTIC_LOG_LINE)
144+
self._listen_glue = (
145+
listen_glue # we must save this so it doesn't get garbage collected
146+
)
147+
self._listener = pub.subscribe(listen_glue, TOPIC_MESHTASTIC_LOG_LINE)
143148

144149
def close(self) -> None:
145150
"""Stop logging."""
146-
pub.unsubscribe(self.listener, TOPIC_MESHTASTIC_LOG_LINE)
151+
pub.unsubscribe(self._listener, TOPIC_MESHTASTIC_LOG_LINE)
147152
self.writer.close()
148153
f = self.raw_file
149154
self.raw_file = None # mark that we are shutting down
@@ -162,14 +167,25 @@ def _onLogMessage(self, line: str) -> None:
162167
if m:
163168
src = m.group(1)
164169
args = m.group(2)
165-
args += " " # append a space so that if the last arg is an empty str it will still be accepted as a match
166170
logging.debug(f"SLog {src}, args: {args}")
167171

168172
d = log_defs.get(src)
169173
if d:
174+
last_field = d.fields[-1]
175+
last_is_str = last_field[1] == pa.string()
176+
if last_is_str:
177+
args += " "
178+
# append a space so that if the last arg is an empty str
179+
# it will still be accepted as a match for a str
180+
170181
r = d.format.parse(args) # get the values with the correct types
171182
if r:
172183
di = r.named
184+
if last_is_str:
185+
di[last_field[0]] = di[last_field[0]].strip() # remove the trailing space we added
186+
if di[last_field[0]] == "":
187+
# If the last field is an empty string, remove it
188+
del di[last_field[0]]
173189
else:
174190
logging.warning(f"Failed to parse slog {line} with {d.format}")
175191
else:

0 commit comments

Comments
 (0)