From 8da95c34863257699ebcf8e87cde7f6b9840cd57 Mon Sep 17 00:00:00 2001 From: Tomi Belan Date: Tue, 4 Jun 2019 20:47:06 +0200 Subject: [PATCH] Better validation and error reporting while processing logs. Invalid log files could be undetected until much later, such as until they're being converted from .xz to .tar.xz in create_archive(). Now process_logs() performs some basic validation: the log must be readable (not bad gzip), not empty, and every line must be valid JSON. It also tries to read every log file instead of stopping at the first error, and prints the bad filenames and the exceptions at the end. --- votrfront/logutil.py | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/votrfront/logutil.py b/votrfront/logutil.py index af68e28..c77dc6a 100644 --- a/votrfront/logutil.py +++ b/votrfront/logutil.py @@ -10,6 +10,7 @@ import subprocess import sys import time +import traceback from . import sessions @@ -123,18 +124,28 @@ def set_tags(app, sessid, lineno, tags_to_add, tags_to_remove): def process_logfiles(app, files): c = _connect(app).cursor() + errors = [] + for filename in files: sessid = os.path.basename(filename).partition('.')[0] - with sessions.lock(app, sessid), open_log(filename) as f: - lineno = 0 - for line in f: - lineno += 1 - if re.search(BASE_PATTERN, line): - try: - c.execute('INSERT INTO lines VALUES (?, ?, ?, ?)', - (sessid, lineno, 'new', line.strip())) - except sqlite3.IntegrityError: - pass # row already present + with sessions.lock(app, sessid): + try: + with open_log(filename) as f: + lineno = 0 + for line in f: + json.loads(line) # Validate JSON. + lineno += 1 + if re.search(BASE_PATTERN, line): + try: + c.execute( + 'INSERT INTO lines VALUES (?, ?, ?, ?)', + (sessid, lineno, 'new', line.strip())) + except sqlite3.IntegrityError: + pass # row already present + if lineno == 0: + raise Exception('Log file is empty') + except Exception: + errors.append((filename, sys.exc_info())) for line in get_lines(app): if line.tags == 'new': @@ -144,6 +155,15 @@ def process_logfiles(app, files): _connect(app).commit() + if errors: + msgs = ['{} errors occurred while processing logs:'.format(len(errors))] + for filename, exc_info in errors: + errmsg = ''.join(traceback.format_exception(*exc_info)) + msgs.append( + '{}:\n'.format(filename) + + '\n'.join(' ' + line for line in errmsg.split('\n'))) + raise Exception('\n\n'.join(msgs)) + @contextlib.contextmanager def wrap_pager(): if os.isatty(0) and os.isatty(1):