Skip to content

Commit 838b761

Browse files
codecaeCurtis Bangert
authored andcommitted
[v3-1-test] Support Dynamic UI Alerts (#54677)
* feat: Dynamic UI Alerts * docs: updated ui customization docs to include dynamic alerts * docs: updated dynamic alerts documentation * fix: corrected whitespace in customize-ui.rst * fix: corrected whitespace in customize-ui.rst --------- (cherry picked from commit 12a9d7b) Co-authored-by: codecae <[email protected]> Co-authored-by: Curtis Bangert <[email protected]>
1 parent 431baac commit 838b761

File tree

2 files changed

+101
-18
lines changed

2 files changed

+101
-18
lines changed

airflow-core/docs/howto/customize-ui.rst

Lines changed: 98 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Customizing the UI
2121
.. _customizing-the-ui:
2222

2323
Customizing Dag UI Header and Airflow Page Titles
24-
==================================================
24+
-------------------------------------------------
2525

2626
Airflow now allows you to customize the Dag home page header and page title. This will help
2727
distinguish between various installations of Airflow or simply amend the page text.
@@ -61,17 +61,47 @@ After
6161

6262
.. image:: ../img/change-site-title/example_instance_name_configuration.png
6363

64+
|
6465
65-
Add custom alert messages on the dashboard
66-
------------------------------------------
66+
Adding Dashboard Alert Messages
67+
===============================
6768

68-
Extra alert messages can be shown on the UI dashboard. This can be useful for warning about setup issues
69-
or announcing changes to end users. The following example shows how to add alert messages:
69+
Extra alert messages can be shown on the Airflow dashboard. This can be useful for warning about setup issues, announcing changes
70+
to end users, or providing real-time status information. Dashboard alerts support both static and dynamic content.
7071

71-
1. Add the following contents to ``airflow_local_settings.py`` file under ``$AIRFLOW_HOME/config``.
72-
Each alert message should specify a severity level (``info``, ``warning``, ``error``) using ``category``.
72+
Basic Static Alerts
73+
-------------------
7374

74-
.. code-block:: python
75+
To add static alert messages that remain constant until the webserver is restarted:
76+
77+
1. Create an ``airflow_local_settings.py`` file and place it in ``$PYTHONPATH`` or in the ``$AIRFLOW_HOME/config`` folder.
78+
(Airflow adds ``$AIRFLOW_HOME/config`` to ``PYTHONPATH`` when Airflow is initialized)
79+
80+
2. Add the following contents to ``airflow_local_settings.py``:
81+
82+
.. note::
83+
See :ref:`Configuring local settings <set-config:configuring-local-settings>` for details on how to configure local settings.
84+
85+
.. code-block:: python
86+
87+
from airflow.www.utils import UIAlert
88+
89+
DASHBOARD_UIALERTS = [
90+
UIAlert("Welcome to Airflow"),
91+
]
92+
93+
3. Restart the Airflow webserver, and you should now see the alert message displayed on the dashboard.
94+
95+
Alert Categories
96+
----------------
97+
98+
You can control the category of the alert message. Available categories include:
99+
100+
- ``"info"`` (default) - Blue informational alerts
101+
- ``"warning"`` - Yellow warning alerts
102+
- ``"error"`` - Red error alerts
103+
104+
.. code-block:: python
75105
76106
from airflow.api_fastapi.common.types import UIAlert
77107
@@ -81,19 +111,70 @@ or announcing changes to end users. The following example shows how to add alert
81111
UIAlert(text="Critical error detected!", category="error"),
82112
]
83113
84-
See :ref:`Configuring local settings <set-config:configuring-local-settings>` for details on how to
85-
configure local settings.
114+
.. image:: ../img/ui-alert-message.png
86115

87-
2. Restart Airflow Webserver, and you should now see:
116+
Markdown Content in Alerts
117+
--------------------------
88118

89-
.. image:: ../img/ui-alert-message.png
119+
Markdown can be included in alert messages for richer formatting. In the following example, we show an alert
120+
message of heading 2 with a link included:
90121

91-
Alert messages also support Markdown. In the following example, we show an alert message of heading 2 with a link included.
122+
.. code-block:: python
92123
93-
.. code-block:: python
124+
from airflow.www.utils import UIAlert
94125
95-
DASHBOARD_UIALERTS = [
96-
UIAlert(text="## Visit [airflow.apache.org](https://airflow.apache.org)", category="info"),
97-
]
126+
DASHBOARD_UIALERTS = [
127+
UIAlert(text="## Visit [airflow.apache.org](https://airflow.apache.org)", category="info"),
128+
]
98129
99130
.. image:: ../img/ui-alert-message-markdown.png
131+
132+
Dynamic Dashboard Alerts
133+
------------------------
134+
135+
Dashboard alerts support dynamic content that updates each time the dashboard page is refreshed. This allows for real-time
136+
status updates without requiring webserver restarts. Dynamic alerts must be defined as an instance of an iterable object.
137+
The recommended approach is to create a class that subclasses ``list`` and implements a custom ``__iter__`` method that
138+
yields fresh alerts each time Airflow iterates over the alerts.
139+
140+
.. note::
141+
When implementing dynamic alerts it is important to keep alert generation logic lightweight to avoid
142+
impacting dashboard load times. Consider caching results for expensive operations and handle exceptions
143+
gracefully to prevent alert generation from breaking the UI.
144+
145+
Dynamic alerts are particularly useful for:
146+
147+
- **Real-time notifications**: Display current status updates or announcements
148+
- **Deployment notifications**: Show current deployment status, build progress, or GitOps state
149+
- **Temporary maintenance alerts**: Provide time-sensitive information about ongoing maintenance or issues
150+
- **Environment-specific warnings**: Display different alerts based on current environment conditions
151+
- **External service status**: Show the availability of dependent services or APIs
152+
153+
Creating Dynamic Alerts
154+
^^^^^^^^^^^^^^^^^^^^^^^
155+
156+
To create dynamic alerts, define ``DASHBOARD_UIALERTS`` as an instance of a class that subclasses ``list``
157+
and implements the ``__iter__`` method. The UI will iterate over any number ``UIAlert`` instances yielded by
158+
this method and expose them as alerts on the dashboard page.
159+
160+
The example below demonstrates how logic can be applied to yield alerts dynamically. More practical use
161+
cases might include alerts yielded from APIs, database queries or files.
162+
163+
.. code-block:: python
164+
165+
import random
166+
from airflow.www.utils import UIAlert
167+
168+
169+
class DynamicAlerts(list):
170+
def __iter__(self):
171+
# This method is called each time Airflow iterates over DASHBOARD_UIALERTS
172+
# Example: Flip a coin
173+
if random.choice([True, False]):
174+
yield UIAlert("Heads!", category="info")
175+
else:
176+
yield UIAlert("Tails!", category="warning")
177+
178+
179+
# Create an instance of the class
180+
DASHBOARD_UIALERTS = DynamicAlerts()

airflow-core/src/airflow/api_fastapi/core_api/routes/ui/config.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from fastapi import Depends, status
2222

2323
from airflow.api_fastapi.common.router import AirflowRouter
24+
from airflow.api_fastapi.common.types import UIAlert
2425
from airflow.api_fastapi.core_api.datamodels.ui.config import ConfigResponse
2526
from airflow.api_fastapi.core_api.openapi.exceptions import create_openapi_http_exception_doc
2627
from airflow.api_fastapi.core_api.security import requires_authenticated
@@ -54,7 +55,8 @@ def get_configs() -> ConfigResponse:
5455
additional_config: dict[str, Any] = {
5556
"instance_name": conf.get("api", "instance_name", fallback="Airflow"),
5657
"test_connection": conf.get("core", "test_connection", fallback="Disabled"),
57-
"dashboard_alert": DASHBOARD_UIALERTS,
58+
# Expose "dashboard_alert" using a list comprehension so UIAlert instances can be expressed dynamically.
59+
"dashboard_alert": [alert for alert in DASHBOARD_UIALERTS if isinstance(alert, UIAlert)],
5860
"show_external_log_redirect": task_log_reader.supports_external_link,
5961
"external_log_name": getattr(task_log_reader.log_handler, "log_name", None),
6062
}

0 commit comments

Comments
 (0)