1import asyncio
2import json
3import logging
4import os
5import sys
6from collections import deque
7from pathlib import Path
8from threading import Lock, Semaphore
9from typing import TypedDict
10
11import orjson
12from loguru import _defaults, logger
13from loguru._error_interceptor import ErrorInterceptor
14from loguru._file_sink import FileSink
15from loguru._simple_sinks import AsyncSink
16from platformdirs import user_cache_dir
17from rich.logging import RichHandler
18from typing_extensions import NotRequired, override
19
20from langflow.settings import DEV
21
…lines 22–150 unchanged (129 lines)
151 log_file: NotRequired[Path]
152 disable: NotRequired[bool]
153 log_env: NotRequired[str]
154 log_format: NotRequired[str]
155
156
157class AsyncFileSink(AsyncSink):
158 def __init__(self, file):
159 self._sink = FileSink(
160 path=file,
161 rotation="10 MB", # Log rotation based on file size
162 delay=True,
163 )
164 super().__init__(self.write_async, None, ErrorInterceptor(_defaults.LOGURU_CATCH, -1))
165
166 async def complete(self):
167 await asyncio.to_thread(self._sink.stop)
168 for task in self._tasks:
169 await self._complete_task(task)
170
171 async def write_async(self, message):
172 await asyncio.to_thread(self._sink.write, message)
173
174
175def is_valid_log_format(format_string) -> bool:
176 """Validates a logging format string by attempting to format it with a dummy LogRecord.
177
178 Args:
…lines 179–200 unchanged (22 lines)
201 log_level: str | None = None,
202 log_file: Path | None = None,
203 disable: bool | None = False,
204 log_env: str | None = None,
205 log_format: str | None = None,
206 async_file: bool = False,
207) -> None:
208 if disable and log_level is None and log_file is None:
209 logger.disable("langflow")
210 if os.getenv("LANGFLOW_LOG_LEVEL", "").upper() in VALID_LOG_LEVELS and log_level is None:
211 log_level = os.getenv("LANGFLOW_LOG_LEVEL")
212 if log_level is None:
213 log_level = "ERROR"
…lines 214–248 unchanged (35 lines)
249
250 if not log_file:
251 cache_dir = Path(user_cache_dir("langflow"))
252 logger.debug(f"Cache directory: {cache_dir}")
253 log_file = cache_dir / "langflow.log"
254 logger.debug(f"Log file: {log_file}")
255 try:
256 logger.add(
257 sink=AsyncFileSink(log_file) if async_file else log_file,
258 level=log_level.upper(),
259 format=log_format,
260 serialize=True,
261 )
262 except Exception: # noqa: BLE001
263 logger.exception("Error setting up log file")
264
265 if log_buffer.enabled():
266 logger.add(sink=log_buffer.write, format="{time} {level} {message}", serialize=True)
267
…lines 268–307 unchanged (40 lines)