From 79bf3d28d88e78b0136ef3c3c9f8e7bb85d3cea9 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 28 May 2026 16:33:48 -0500 Subject: [PATCH] refac --- backend/open_webui/utils/logger.py | 49 ++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/backend/open_webui/utils/logger.py b/backend/open_webui/utils/logger.py index 845f98521c..d3f031ad0e 100644 --- a/backend/open_webui/utils/logger.py +++ b/backend/open_webui/utils/logger.py @@ -1,6 +1,7 @@ import json import logging import sys +import traceback from typing import TYPE_CHECKING from loguru import logger @@ -49,22 +50,44 @@ def _json_sink(message: 'Message') -> None: Used as a Loguru sink when LOG_FORMAT is set to "json". """ - record = message.record - log_entry = { - 'ts': record['time'].strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z', - 'level': _LEVEL_MAP.get(record['level'].name, record['level'].name.lower()), - 'msg': record['message'], - 'caller': f'{record["name"]}:{record["function"]}:{record["line"]}', - } + try: + record = message.record + log_entry = { + 'ts': record['time'].isoformat(timespec='milliseconds'), + 'level': _LEVEL_MAP.get(record['level'].name, record['level'].name.lower()), + 'msg': record['message'], + 'caller': f'{record["name"]}:{record["function"]}:{record["line"]}', + } - if record['extra']: - log_entry['extra'] = record['extra'] + if record['extra']: + log_entry['extra'] = record['extra'] - if record['exception'] is not None: - log_entry['error'] = ''.join(record['exception'].format_exception()).rstrip() + exc = record['exception'] + if exc is not None: + log_entry['error'] = { + 'type': exc.type.__name__ if exc.type else None, + 'message': str(exc.value) if exc.value else None, + 'stacktrace': ''.join( + traceback.format_exception(exc.type, exc.value, exc.traceback) + ).rstrip(), + } - sys.stdout.write(json.dumps(log_entry, ensure_ascii=False, default=str) + '\n') - sys.stdout.flush() + sys.stdout.write(json.dumps(log_entry, ensure_ascii=False, default=str) + '\n') + sys.stdout.flush() + except Exception: + # Last-resort fallback: never let a logging failure crash the application. + # Emit a minimal valid JSON line so the structured logging pipeline stays intact. + try: + fallback = { + 'ts': message.record['time'].isoformat(timespec='milliseconds'), + 'level': 'error', + 'msg': f'[logging error] failed to serialize log record: {message}', + } + sys.stdout.write(json.dumps(fallback, ensure_ascii=False, default=str) + '\n') + sys.stdout.flush() + except Exception: + sys.stderr.write(f'[logging error] _json_sink failed: {message}\n') + sys.stderr.flush() class InterceptHandler(logging.Handler):