protocols/logging: support parsing multiline log messages

This commit is contained in:
Sebastien Bourdeauducq 2016-01-26 21:06:44 +01:00
parent 5aa4de8e89
commit 19c5e89b4d
1 changed files with 39 additions and 12 deletions

View File

@ -1,5 +1,6 @@
import asyncio import asyncio
import logging import logging
import re
from artiq.protocols.asyncio_server import AsyncioServer from artiq.protocols.asyncio_server import AsyncioServer
from artiq.tools import TaskObject from artiq.tools import TaskObject
@ -25,25 +26,51 @@ _name_to_level = {
def parse_log_message(msg): def parse_log_message(msg):
for name, level in _name_to_level.items(): lr = "|".join(_name_to_level.keys())
if msg.startswith(name + ":"): m = re.fullmatch('('+lr+')(<\d+>)?:([^:]*):(.*)', msg)
remainder = msg[len(name) + 1:] if m is None:
try: return 0, logging.INFO, "print", msg
idx = remainder.index(":") level = _name_to_level[m.group(1)]
except: if m.group(2):
continue multiline = int(m.group(2)[1:-1]) - 1
return level, remainder[:idx], remainder[idx+1:] else:
return logging.INFO, "print", msg multiline = 0
name = m.group(3)
message = m.group(4)
return multiline, level, name, message
class LogParser: class LogParser:
def __init__(self, source_cb): def __init__(self, source_cb):
self.source_cb = source_cb self.source_cb = source_cb
self.multiline_count = 0
self.multiline_level = None
self.multiline_name = None
self.multiline_message = None
def line_input(self, msg): def line_input(self, msg):
level, name, message = parse_log_message(msg) if self.multiline_count:
log_with_name(name, level, message, self.multiline_message += "\n" + msg
extra={"source": self.source_cb()}) self.multiline_count -= 1
if not self.multiline_count:
log_with_name(
self.multiline_name,
self.multiline_level,
self.multiline_message,
extra={"source": self.source_cb()})
self.multiline_level = None
self.multiline_name = None
self.multiline_message = None
else:
multiline, level, name, message = parse_log_message(msg)
if multiline:
self.multiline_count = multiline
self.multiline_level = level
self.multiline_name = name
self.multiline_message = message
else:
log_with_name(name, level, message,
extra={"source": self.source_cb()})
async def stream_task(self, stream): async def stream_task(self, stream):
while True: while True: