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(