diff --git a/.changeset/shy-toys-fix.md b/.changeset/shy-toys-fix.md new file mode 100644 index 000000000..f0e48ee9c --- /dev/null +++ b/.changeset/shy-toys-fix.md @@ -0,0 +1,5 @@ +--- +"livekit-agents": patch +--- + +fix non pickleable log diff --git a/livekit-agents/livekit/agents/ipc/proc_main.py b/livekit-agents/livekit/agents/ipc/proc_main.py index 3c0565ebf..6d8ead956 100644 --- a/livekit-agents/livekit/agents/ipc/proc_main.py +++ b/livekit-agents/livekit/agents/ipc/proc_main.py @@ -26,7 +26,7 @@ class LogQueueHandler(logging.Handler): def __init__(self, duplex: utils.aio.duplex_unix._Duplex) -> None: super().__init__() self._duplex = duplex - self._send_q = queue.SimpleQueue[Optional[logging.LogRecord]]() + self._send_q = queue.SimpleQueue[Optional[bytes]]() self._send_thread = threading.Thread( target=self._forward_logs, name="ipc_log_forwarder" ) @@ -34,12 +34,12 @@ def __init__(self, duplex: utils.aio.duplex_unix._Duplex) -> None: def _forward_logs(self): while True: - record = self._send_q.get() - if record is None: + serialized_record = self._send_q.get() + if serialized_record is None: break try: - self._duplex.send_bytes(pickle.dumps(record)) + self._duplex.send_bytes(serialized_record) except duplex_unix.DuplexClosed: break @@ -47,6 +47,7 @@ def _forward_logs(self): def emit(self, record: logging.LogRecord) -> None: try: + # from https://github.com/python/cpython/blob/91b7f2e7f6593acefda4fa860250dd87d6f849bf/Lib/logging/handlers.py#L1453 msg = self.format(record) record = copy.copy(record) record.message = msg @@ -54,7 +55,15 @@ def emit(self, record: logging.LogRecord) -> None: record.args = None record.exc_info = None record.exc_text = None - self._send_q.put_nowait(record) + record.stack_info = None + + # https://websockets.readthedocs.io/en/stable/topics/logging.html#logging-to-json + # webosckets library add "websocket" attribute to log records, which is not pickleable + if hasattr(record, "websocket"): + record.websocket = None + + self._send_q.put_nowait(pickle.dumps(record)) + except Exception: self.handleError(record)