diff --git a/docs/docs/Configuration/environment-variables.md b/docs/docs/Configuration/environment-variables.md index fa1d907b6..40215504a 100644 --- a/docs/docs/Configuration/environment-variables.md +++ b/docs/docs/Configuration/environment-variables.md @@ -122,7 +122,10 @@ The following table lists the environment variables supported by Langflow. | `LANGFLOW_HEALTH_CHECK_MAX_RETRIES` | Integer | `5` | Set the maximum number of retries for the health check.
See [`--health-check-max-retries` option](./configuration-cli.md#run-health-check-max-retries). | | `LANGFLOW_HOST` | String | `127.0.0.1` | The host on which the Langflow server will run.
See [`--host` option](./configuration-cli.md#run-host). | | `LANGFLOW_LANGCHAIN_CACHE` | `InMemoryCache`
`SQLiteCache` | `InMemoryCache` | Type of cache to use.
See [`--cache` option](./configuration-cli.md#run-cache). | +| `LANGFLOW_MAX_FILE_SIZE_UPLOAD` | Integer | `100` | Set the maximum file size for the upload in megabytes.
See [`--max-file-size-upload` option](./configuration-cli.md#run-max-file-size-upload). | +| `LANGFLOW_LOG_ENV` | `container_json`
`container_csv`
| Not set | Set the log environment. Default (Not set) is json with color. If not set a format string can be provided.
See [`LANGFLOW_LOG_FORMAT`](#LANGFLOW_CACHE_TYPE) | | `LANGFLOW_LOG_FILE` | String | `logs/langflow.log` | Set the path to the log file for Langflow.
See [`--log-file` option](./configuration-cli.md#run-log-file). | +| `LANGFLOW_LOG_FORMAT` | String | `{time:YYYY-MM-DD HH:mm:ss} - {level: <8} - {module} - {message}` | Configure the logformat.
For example without colors: `{time:YYYY-MM-DD HH:mm:ss.SSS} {level} {file} {line} {function} {message}`
If [`LANGFLOW_LOG_ENV`](#LANGFLOW_LOG_ENV) is set this configuration will be ignored. | `LANGFLOW_LOG_LEVEL` | `debug`
`info`
`warning`
`error`
`critical` | `critical` | Set the logging level.
See [`--log-level` option](./configuration-cli.md#run-log-level). | | `LANGFLOW_MAX_FILE_SIZE_UPLOAD` | Integer | `100` | Set the maximum file size for the upload in megabytes.
See [`--max-file-size-upload` option](./configuration-cli.md#run-max-file-size-upload). | | `LANGFLOW_OPEN_BROWSER` | Boolean | `true` | Open the system web browser on startup.
See [`--open-browser` option](./configuration-cli.md#run-open-browser). | diff --git a/src/backend/base/langflow/logging/logger.py b/src/backend/base/langflow/logging/logger.py index 080ccd1b3..b4cc10435 100644 --- a/src/backend/base/langflow/logging/logger.py +++ b/src/backend/base/langflow/logging/logger.py @@ -20,6 +20,10 @@ from typing_extensions import NotRequired from langflow.settings import DEV VALID_LOG_LEVELS = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] +# Human-readable +DEFAULT_LOG_FORMAT = ( + "{time:YYYY-MM-DD HH:mm:ss} - " "{level: <8} - {module} - {message}" +) class SizedLogBuffer: @@ -147,6 +151,7 @@ class LogConfig(TypedDict): log_file: NotRequired[Path] disable: NotRequired[bool] log_env: NotRequired[str] + log_format: NotRequired[str] class AsyncFileSink(AsyncSink): @@ -166,12 +171,37 @@ class AsyncFileSink(AsyncSink): await asyncio.to_thread(self._sink.write, message) +def is_valid_log_format(format_string) -> bool: + """Validates a logging format string by attempting to format it with a dummy LogRecord. + + Args: + format_string (str): The format string to validate. + + Returns: + bool: True if the format string is valid, False otherwise. + """ + record = logging.LogRecord( + name="dummy", level=logging.INFO, pathname="dummy_path", lineno=0, msg="dummy message", args=None, exc_info=None + ) + + formatter = logging.Formatter(format_string) + + try: + # Attempt to format the record + formatter.format(record) + except (KeyError, ValueError, TypeError): + logger.error("Invalid log format string passed, fallback to default") + return False + return True + + def configure( *, log_level: str | None = None, log_file: Path | None = None, disable: bool | None = False, log_env: str | None = None, + log_format: str | None = None, async_file: bool = False, ) -> None: if disable and log_level is None and log_file is None: @@ -195,11 +225,11 @@ def configure( elif log_env.lower() == "container_csv": logger.add(sys.stdout, format="{time:YYYY-MM-DD HH:mm:ss.SSS} {level} {file} {line} {function} {message}") else: - # Human-readable - log_format = ( - "{time:YYYY-MM-DD HH:mm:ss} - " - "{level: <8} - {module} - {message}" - ) + if os.getenv("LANGFLOW_LOG_FORMAT") and log_format is None: + log_format = os.getenv("LANGFLOW_LOG_FORMAT") + + if log_format is None or not is_valid_log_format(log_format): + log_format = DEFAULT_LOG_FORMAT # Configure loguru to use RichHandler logger.configure(