feat: make log format configurable (#4851)

* made logformat configurable

* [autofix.ci] apply automated fixes

* documentation of log format env var

* log stuff at one place in documentation

* added documentation of log environment

* check for log format

* [autofix.ci] apply automated fixes

* just load log format on custom logenv

* [autofix.ci] apply automated fixes

* no more invalid whitespaces

* fixed br s with escape

* logging error in case of invalid format string

---------

Co-authored-by: Kraxner Thomas <thomas.kraxner@illwerkevkw.at>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Thomas Kraxner 2024-11-27 15:28:50 +01:00 committed by GitHub
commit 1e6ada3a3a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 38 additions and 5 deletions

View file

@ -122,7 +122,10 @@ The following table lists the environment variables supported by Langflow.
| <a id="LANGFLOW_HEALTH_CHECK_MAX_RETRIES"></a>`LANGFLOW_HEALTH_CHECK_MAX_RETRIES` | Integer | `5` | Set the maximum number of retries for the health check.<br/>See [`--health-check-max-retries` option](./configuration-cli.md#run-health-check-max-retries). |
| <a id="LANGFLOW_HOST"></a>`LANGFLOW_HOST` | String | `127.0.0.1` | The host on which the Langflow server will run.<br/>See [`--host` option](./configuration-cli.md#run-host). |
| <a id="LANGFLOW_LANGCHAIN_CACHE"></a>`LANGFLOW_LANGCHAIN_CACHE` | `InMemoryCache`<br/>`SQLiteCache` | `InMemoryCache` | Type of cache to use.<br/>See [`--cache` option](./configuration-cli.md#run-cache). |
| <a id="LANGFLOW_MAX_FILE_SIZE_UPLOAD"></a>`LANGFLOW_MAX_FILE_SIZE_UPLOAD` | Integer | `100` | Set the maximum file size for the upload in megabytes.<br/>See [`--max-file-size-upload` option](./configuration-cli.md#run-max-file-size-upload). |
| <a id="LANGFLOW_LOG_ENV"></a>`LANGFLOW_LOG_ENV` | `container_json`<br/>`container_csv`<br/> | Not set | Set the log environment. Default (Not set) is json with color. If not set a format string can be provided.<br/> See [`LANGFLOW_LOG_FORMAT`](#LANGFLOW_CACHE_TYPE) |
| <a id="LANGFLOW_LOG_FILE"></a>`LANGFLOW_LOG_FILE` | String | `logs/langflow.log` | Set the path to the log file for Langflow.<br/>See [`--log-file` option](./configuration-cli.md#run-log-file). |
| <a id="LANGFLOW_LOG_FORMAT"></a>`LANGFLOW_LOG_FORMAT` | String | `<green>{time:YYYY-MM-DD HH:mm:ss}</green> - <level>{level: <8}</level> - {module} - <level>{message}</level>` | Configure the logformat.<br/>For example without colors: `{time:YYYY-MM-DD HH:mm:ss.SSS} {level} {file} {line} {function} {message}` <br/> If [`LANGFLOW_LOG_ENV`](#LANGFLOW_LOG_ENV) is set this configuration will be ignored.
| <a id="LANGFLOW_LOG_LEVEL"></a>`LANGFLOW_LOG_LEVEL` | `debug`<br/>`info`<br/>`warning`<br/>`error`<br/>`critical` | `critical` | Set the logging level.<br/>See [`--log-level` option](./configuration-cli.md#run-log-level). |
| <a id="LANGFLOW_MAX_FILE_SIZE_UPLOAD"></a>`LANGFLOW_MAX_FILE_SIZE_UPLOAD` | Integer | `100` | Set the maximum file size for the upload in megabytes.<br/>See [`--max-file-size-upload` option](./configuration-cli.md#run-max-file-size-upload). |
| <a id="LANGFLOW_OPEN_BROWSER"></a>`LANGFLOW_OPEN_BROWSER` | Boolean | `true` | Open the system web browser on startup.<br/> See [`--open-browser` option](./configuration-cli.md#run-open-browser). |

View file

@ -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 = (
"<green>{time:YYYY-MM-DD HH:mm:ss}</green> - <level>" "{level: <8}</level> - {module} - <level>{message}</level>"
)
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 = (
"<green>{time:YYYY-MM-DD HH:mm:ss}</green> - <level>"
"{level: <8}</level> - {module} - <level>{message}</level>"
)
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(