From 1f22cccd22ce91c05a970666c33866ae39a95bbd Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Tue, 11 Aug 2026 07:13:52 +0200 Subject: [PATCH] perf: stop formatting every exported log record twice under OTEL log export (#27840) With ENABLE_OTEL and ENABLE_OTEL_LOGS set, InterceptHandler builds the message once for loguru and then hands the same LogRecord to the OpenTelemetry handler, whose _translate calls record.getMessage() a second time. That used to be free, because the message was already a finished f-string with nothing to substitute. Now that log calls pass lazy %-args, the second call re-runs the whole interpolation, so every exported record is formatted twice. The two getMessage() calls on a 78 kB retrieval record: before 373.0 us after 0.1 us Stamping the built message back onto the record makes the second call a plain string return. msg and args are both in OpenTelemetry's _RESERVED_ATTRS, so neither ever reaches the exported attributes. The isinstance guard matters: _translate exports a non-str msg such as the dicts routers/audio.py logs as a typed body rather than a string, so those records are left untouched, and they have no %-args to format twice anyway. Body, attributes and severity were compared against LoggingHandler._translate for str, dict, list, int, None, exception and exc_info records. --- backend/open_webui/utils/logger.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/open_webui/utils/logger.py b/backend/open_webui/utils/logger.py index eec16f8079..f54b7f9840 100644 --- a/backend/open_webui/utils/logger.py +++ b/backend/open_webui/utils/logger.py @@ -112,10 +112,14 @@ class InterceptHandler(logging.Handler): frame = frame.f_back depth += 1 - logger.opt(depth=depth, exception=record.exc_info).bind(**self._get_extras()).log(level, record.getMessage()) + message = record.getMessage() + logger.opt(depth=depth, exception=record.exc_info).bind(**self._get_extras()).log(level, message) if ENABLE_OTEL and ENABLE_OTEL_LOGS: from open_webui.utils.telemetry.logs import otel_handler + # reuse the message we built so %-args format once; a non-str msg is left alone, otel exports it structured + if isinstance(record.msg, str): + record.msg, record.args = message, None otel_handler.emit(record) def _get_extras(self):