diff --git a/airflow-core/docs/howto/customize-ui.rst b/airflow-core/docs/howto/customize-ui.rst index 1eb393096100c..3681554f8aee8 100644 --- a/airflow-core/docs/howto/customize-ui.rst +++ b/airflow-core/docs/howto/customize-ui.rst @@ -21,7 +21,7 @@ Customizing the UI .. _customizing-the-ui: Customizing Dag UI Header and Airflow Page Titles -================================================== +------------------------------------------------- Airflow now allows you to customize the Dag home page header and page title. This will help distinguish between various installations of Airflow or simply amend the page text. @@ -61,17 +61,47 @@ After .. image:: ../img/change-site-title/example_instance_name_configuration.png +| -Add custom alert messages on the dashboard ------------------------------------------- +Adding Dashboard Alert Messages +=============================== -Extra alert messages can be shown on the UI dashboard. This can be useful for warning about setup issues -or announcing changes to end users. The following example shows how to add alert messages: +Extra alert messages can be shown on the Airflow dashboard. This can be useful for warning about setup issues, announcing changes +to end users, or providing real-time status information. Dashboard alerts support both static and dynamic content. -1. Add the following contents to ``airflow_local_settings.py`` file under ``$AIRFLOW_HOME/config``. - Each alert message should specify a severity level (``info``, ``warning``, ``error``) using ``category``. +Basic Static Alerts +------------------- - .. code-block:: python +To add static alert messages that remain constant until the webserver is restarted: + +1. Create an ``airflow_local_settings.py`` file and place it in ``$PYTHONPATH`` or in the ``$AIRFLOW_HOME/config`` folder. + (Airflow adds ``$AIRFLOW_HOME/config`` to ``PYTHONPATH`` when Airflow is initialized) + +2. Add the following contents to ``airflow_local_settings.py``: + + .. note:: + See :ref:`Configuring local settings ` for details on how to configure local settings. + + .. code-block:: python + + from airflow.www.utils import UIAlert + + DASHBOARD_UIALERTS = [ + UIAlert("Welcome to Airflow"), + ] + +3. Restart the Airflow webserver, and you should now see the alert message displayed on the dashboard. + +Alert Categories +---------------- + +You can control the category of the alert message. Available categories include: + +- ``"info"`` (default) - Blue informational alerts +- ``"warning"`` - Yellow warning alerts +- ``"error"`` - Red error alerts + +.. code-block:: python from airflow.api_fastapi.common.types import UIAlert @@ -81,19 +111,70 @@ or announcing changes to end users. The following example shows how to add alert UIAlert(text="Critical error detected!", category="error"), ] - See :ref:`Configuring local settings ` for details on how to - configure local settings. +.. image:: ../img/ui-alert-message.png -2. Restart Airflow Webserver, and you should now see: +Markdown Content in Alerts +-------------------------- -.. image:: ../img/ui-alert-message.png +Markdown can be included in alert messages for richer formatting. In the following example, we show an alert +message of heading 2 with a link included: -Alert messages also support Markdown. In the following example, we show an alert message of heading 2 with a link included. +.. code-block:: python - .. code-block:: python + from airflow.www.utils import UIAlert - DASHBOARD_UIALERTS = [ - UIAlert(text="## Visit [airflow.apache.org](https://airflow.apache.org)", category="info"), - ] + DASHBOARD_UIALERTS = [ + UIAlert(text="## Visit [airflow.apache.org](https://airflow.apache.org)", category="info"), + ] .. image:: ../img/ui-alert-message-markdown.png + +Dynamic Dashboard Alerts +------------------------ + +Dashboard alerts support dynamic content that updates each time the dashboard page is refreshed. This allows for real-time +status updates without requiring webserver restarts. Dynamic alerts must be defined as an instance of an iterable object. +The recommended approach is to create a class that subclasses ``list`` and implements a custom ``__iter__`` method that +yields fresh alerts each time Airflow iterates over the alerts. + +.. note:: + When implementing dynamic alerts it is important to keep alert generation logic lightweight to avoid + impacting dashboard load times. Consider caching results for expensive operations and handle exceptions + gracefully to prevent alert generation from breaking the UI. + +Dynamic alerts are particularly useful for: + +- **Real-time notifications**: Display current status updates or announcements +- **Deployment notifications**: Show current deployment status, build progress, or GitOps state +- **Temporary maintenance alerts**: Provide time-sensitive information about ongoing maintenance or issues +- **Environment-specific warnings**: Display different alerts based on current environment conditions +- **External service status**: Show the availability of dependent services or APIs + +Creating Dynamic Alerts +^^^^^^^^^^^^^^^^^^^^^^^ + +To create dynamic alerts, define ``DASHBOARD_UIALERTS`` as an instance of a class that subclasses ``list`` +and implements the ``__iter__`` method. The UI will iterate over any number ``UIAlert`` instances yielded by +this method and expose them as alerts on the dashboard page. + +The example below demonstrates how logic can be applied to yield alerts dynamically. More practical use +cases might include alerts yielded from APIs, database queries or files. + +.. code-block:: python + + import random + from airflow.www.utils import UIAlert + + + class DynamicAlerts(list): + def __iter__(self): + # This method is called each time Airflow iterates over DASHBOARD_UIALERTS + # Example: Flip a coin + if random.choice([True, False]): + yield UIAlert("Heads!", category="info") + else: + yield UIAlert("Tails!", category="warning") + + + # Create an instance of the class + DASHBOARD_UIALERTS = DynamicAlerts() diff --git a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/config.py b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/config.py index f4fe5d5c6658c..c0b7dd2e3b638 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/config.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/config.py @@ -21,6 +21,7 @@ from fastapi import Depends, status from airflow.api_fastapi.common.router import AirflowRouter +from airflow.api_fastapi.common.types import UIAlert from airflow.api_fastapi.core_api.datamodels.ui.config import ConfigResponse from airflow.api_fastapi.core_api.openapi.exceptions import create_openapi_http_exception_doc from airflow.api_fastapi.core_api.security import requires_authenticated @@ -54,7 +55,8 @@ def get_configs() -> ConfigResponse: additional_config: dict[str, Any] = { "instance_name": conf.get("api", "instance_name", fallback="Airflow"), "test_connection": conf.get("core", "test_connection", fallback="Disabled"), - "dashboard_alert": DASHBOARD_UIALERTS, + # Expose "dashboard_alert" using a list comprehension so UIAlert instances can be expressed dynamically. + "dashboard_alert": [alert for alert in DASHBOARD_UIALERTS if isinstance(alert, UIAlert)], "show_external_log_redirect": task_log_reader.supports_external_link, "external_log_name": getattr(task_log_reader.log_handler, "log_name", None), }