From 9398f77308cca7164617e0f8db31be467a6d6a1a Mon Sep 17 00:00:00 2001 From: Curtis Bangert Date: Tue, 19 Aug 2025 09:08:17 -0400 Subject: [PATCH 1/5] feat: Dynamic UI Alerts --- .../src/airflow/api_fastapi/core_api/routes/ui/config.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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), } From 6113b5f2dca161e761064f56c64984a583e98e00 Mon Sep 17 00:00:00 2001 From: Curtis Bangert Date: Wed, 10 Sep 2025 12:18:58 -0400 Subject: [PATCH 2/5] docs: updated ui customization docs to include dynamic alerts --- airflow-core/docs/howto/customize-ui.rst | 110 +++++++++++++++++++---- 1 file changed, 93 insertions(+), 17 deletions(-) diff --git a/airflow-core/docs/howto/customize-ui.rst b/airflow-core/docs/howto/customize-ui.rst index 1eb393096100c..0b59f6339c77b 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,65 @@ 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: + +.. 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() From bb3a8c99ba334bc8a84261cc55832ddd84d4a572 Mon Sep 17 00:00:00 2001 From: Curtis Bangert Date: Wed, 24 Sep 2025 22:02:37 -0400 Subject: [PATCH 3/5] docs: updated dynamic alerts documentation --- airflow-core/docs/howto/customize-ui.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/airflow-core/docs/howto/customize-ui.rst b/airflow-core/docs/howto/customize-ui.rst index 0b59f6339c77b..76fc4b3aa02e2 100644 --- a/airflow-core/docs/howto/customize-ui.rst +++ b/airflow-core/docs/howto/customize-ui.rst @@ -153,7 +153,12 @@ Dynamic alerts are particularly useful for: Creating Dynamic Alerts ^^^^^^^^^^^^^^^^^^^^^^^ -To create dynamic alerts, define ``DASHBOARD_UIALERTS`` as an instance of a class that subclasses ``list`` and implements the ``__iter__`` method: +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 @@ -173,3 +178,4 @@ To create dynamic alerts, define ``DASHBOARD_UIALERTS`` as an instance of a clas # Create an instance of the class DASHBOARD_UIALERTS = DynamicAlerts() + From a2ed91ba16dcc570c3fef6d8f228c3a526ed3053 Mon Sep 17 00:00:00 2001 From: Curtis Bangert Date: Mon, 29 Sep 2025 11:18:40 -0400 Subject: [PATCH 4/5] fix: corrected whitespace in customize-ui.rst --- airflow-core/docs/howto/customize-ui.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airflow-core/docs/howto/customize-ui.rst b/airflow-core/docs/howto/customize-ui.rst index 76fc4b3aa02e2..1390d0363328a 100644 --- a/airflow-core/docs/howto/customize-ui.rst +++ b/airflow-core/docs/howto/customize-ui.rst @@ -158,7 +158,7 @@ and implements the ``__iter__`` method. The UI will iterate over any number ``UI 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. +cases might include alerts yielded from APIs, database queries or files. .. code-block:: python From d9bf0b3638f63da2f36e61a860da15f57be9cc2c Mon Sep 17 00:00:00 2001 From: Curtis Bangert Date: Mon, 29 Sep 2025 13:07:15 -0400 Subject: [PATCH 5/5] fix: corrected whitespace in customize-ui.rst --- airflow-core/docs/howto/customize-ui.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/airflow-core/docs/howto/customize-ui.rst b/airflow-core/docs/howto/customize-ui.rst index 1390d0363328a..3681554f8aee8 100644 --- a/airflow-core/docs/howto/customize-ui.rst +++ b/airflow-core/docs/howto/customize-ui.rst @@ -178,4 +178,3 @@ cases might include alerts yielded from APIs, database queries or files. # Create an instance of the class DASHBOARD_UIALERTS = DynamicAlerts() -