This is an automated email from the ASF dual-hosted git repository.
wu-sheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-horizon-ui.git
The following commit(s) were added to refs/heads/main by this push:
new a1bc540 Add Airflow layer dashboards (SWIP-7) (#42)
a1bc540 is described below
commit a1bc540e1c9855ad4cd432c736cfbacee87e9c9f
Author: songzhendong <[email protected]>
AuthorDate: Thu Jun 11 11:54:49 2026 +0800
Add Airflow layer dashboards (SWIP-7) (#42)
---
CHANGELOG.md | 8 +
.../bff/src/bundled_templates/infra-3d/config.json | 5 +
.../bundled_templates/layers/airflow.i18n.de.json | 69 ++++
.../bundled_templates/layers/airflow.i18n.es.json | 69 ++++
.../bundled_templates/layers/airflow.i18n.fr.json | 69 ++++
.../bundled_templates/layers/airflow.i18n.ja.json | 69 ++++
.../bundled_templates/layers/airflow.i18n.ko.json | 69 ++++
.../bundled_templates/layers/airflow.i18n.pt.json | 69 ++++
.../layers/airflow.i18n.zh-CN.json | 98 ++++++
apps/bff/src/bundled_templates/layers/airflow.json | 372 +++++++++++++++++++++
10 files changed, 897 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ae6451c..764f0fd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -32,6 +32,14 @@ packages) plus the BFF's `HORIZON_VERSION` default.
tile — so it was dead config; the per-layer KPI strip is driven by the
layer-header columns.
+### Airflow monitoring layer (SWIP-7)
+
+- New **Airflow** layer under **Workflow Scheduler** — service dashboard
+ (scheduler / executor / pool KPIs and trends), Components dashboard
+ (per-host scheduler and triggerer metrics for **Airflow 3.x** native OTel),
+ and a 3D Infra Map load ring for **Tasks Executable**. Pairs with OAP backend
+ SWIP-7 (`meter_airflow_*` / `meter_airflow_instance_*`).
+
### Dashboard widget visibility
- Layer-dashboard widgets gain a structured **Visible when** gate (Layer
diff --git a/apps/bff/src/bundled_templates/infra-3d/config.json
b/apps/bff/src/bundled_templates/infra-3d/config.json
index 5c54f98..44d6852 100644
--- a/apps/bff/src/bundled_templates/infra-3d/config.json
+++ b/apps/bff/src/bundled_templates/infra-3d/config.json
@@ -73,6 +73,7 @@
"NGINX",
"KONG",
"FLINK",
+ "AIRFLOW",
"SO11Y_OAP",
"SO11Y_SATELLITE",
"SO11Y_BANYANDB",
@@ -259,6 +260,10 @@
"color": "#e6526f",
"metric": { "mqe": "latest(meter_flink_jobManager_running_job_number)",
"label": "Running Jobs", "unit": "jobs" }
},
+ "AIRFLOW": {
+ "color": "#017cee",
+ "metric": { "mqe": "latest(meter_airflow_scheduler_tasks_executable)",
"label": "Tasks Executable" }
+ },
"SO11Y_OAP": {
"color": "#69b1ff",
"$note": "Bundled SO11Y_OAP template has components.service=false; cube
renders without traffic until admin overrides."
diff --git a/apps/bff/src/bundled_templates/layers/airflow.i18n.de.json
b/apps/bff/src/bundled_templates/layers/airflow.i18n.de.json
new file mode 100644
index 0000000..8faf4a4
--- /dev/null
+++ b/apps/bff/src/bundled_templates/layers/airflow.i18n.de.json
@@ -0,0 +1,69 @@
+{
+ "alias": "Airflow",
+ "group": "Workflow-Scheduler",
+ "slots": {
+ "services": "Airflow-Cluster",
+ "instances": "Komponenten"
+ },
+ "layer-header": {
+ "columns": [
+ { "label": "DAG-Bag-Größe" },
+ { "label": "DAG-Gesamt-Parsezeit" },
+ { "label": "Freie Executor-Slots" },
+ { "label": "Geplante Slots" }
+ ]
+ },
+ "overview": {
+ "groups": [
+ {
+ "title": "Cluster",
+ "metrics": [
+ { "label": "Ausführbare Tasks", "tip": "Auf dem Cluster ausführbare
Tasks." },
+ { "label": "Wartende Tasks", "tip": "Tasks in der
Executor-Warteschlange." },
+ { "label": "Freie Executor-Slots", "tip": "Freie Executor-Slots,
keine Pool-Kapazität." }
+ ]
+ }
+ ]
+ },
+ "dashboards": {
+ "service": [
+ { "title": "Ausführbare Tasks" },
+ { "title": "Laufende Tasks" },
+ { "title": "Geplante Slots" },
+ { "title": "Wartende Tasks" },
+ { "title": "Freie Executor-Slots" },
+ { "title": "DAG-Datei-Warteschlange" },
+ { "title": "DAG-Importfehler" },
+ { "title": "DAG-Bag-Größe" },
+ { "title": "DAG-Gesamt-Parsezeit" },
+ { "title": "DAG-Datei-Refresh-Fehler" },
+ { "title": "Asset-Updates" }
+ ],
+ "instance": [
+ {
+ "title": "Pool offen / zurückgestellt / laufend",
+ "expressionLabels": ["pool open", "pool deferred", "pool running"]
+ },
+ {
+ "title": "Laufende Tasks / geplante Slots",
+ "expressionLabels": ["running tasks", "scheduled slots"]
+ },
+ { "title": "Scheduler-Heartbeat" },
+ {
+ "title": "Executor offen / wartend",
+ "expressionLabels": ["open slots", "queued tasks"]
+ },
+ { "title": "Asset-Updates" },
+ { "title": "Asset-ausgelöste DagRuns" },
+ { "title": "Triggerer-Heartbeat" },
+ {
+ "title": "Laufende Trigger / freie Kapazität",
+ "expressionLabels": ["triggers running", "capacity left"]
+ },
+ {
+ "title": "Trigger blockiert / fehlgeschlagen / erfolgreich",
+ "expressionLabels": ["blocked", "failed", "succeeded"]
+ }
+ ]
+ }
+}
diff --git a/apps/bff/src/bundled_templates/layers/airflow.i18n.es.json
b/apps/bff/src/bundled_templates/layers/airflow.i18n.es.json
new file mode 100644
index 0000000..c75ef92
--- /dev/null
+++ b/apps/bff/src/bundled_templates/layers/airflow.i18n.es.json
@@ -0,0 +1,69 @@
+{
+ "alias": "Airflow",
+ "group": "Programador de flujos",
+ "slots": {
+ "services": "Clústeres de Airflow",
+ "instances": "Componentes"
+ },
+ "layer-header": {
+ "columns": [
+ { "label": "Tamaño del DAG bag" },
+ { "label": "Tiempo total de parseo DAG" },
+ { "label": "Slots libres del executor" },
+ { "label": "Slots programados" }
+ ]
+ },
+ "overview": {
+ "groups": [
+ {
+ "title": "Clúster",
+ "metrics": [
+ { "label": "Tasks ejecutables", "tip": "Tasks listas para ejecutar
en el clúster." },
+ { "label": "Tasks en cola", "tip": "Tasks en espera en el executor."
},
+ { "label": "Slots libres del executor", "tip": "Slots libres del
executor, no capacidad de pool." }
+ ]
+ }
+ ]
+ },
+ "dashboards": {
+ "service": [
+ { "title": "Tasks ejecutables" },
+ { "title": "Tasks en ejecución" },
+ { "title": "Slots programados" },
+ { "title": "Tasks en cola" },
+ { "title": "Slots libres del executor" },
+ { "title": "Tamaño de cola de archivos DAG" },
+ { "title": "Errores de importación DAG" },
+ { "title": "Tamaño del DAG bag" },
+ { "title": "Tiempo total de parseo DAG" },
+ { "title": "Errores de refresco de archivos DAG" },
+ { "title": "Actualizaciones de assets" }
+ ],
+ "instance": [
+ {
+ "title": "Slots de pool abiertos / diferidos / en ejecución",
+ "expressionLabels": ["pool open", "pool deferred", "pool running"]
+ },
+ {
+ "title": "Tasks en ejecución / slots programados",
+ "expressionLabels": ["running tasks", "scheduled slots"]
+ },
+ { "title": "Heartbeat del scheduler" },
+ {
+ "title": "Slots del executor abiertos / en cola",
+ "expressionLabels": ["open slots", "queued tasks"]
+ },
+ { "title": "Actualizaciones de assets" },
+ { "title": "DagRuns activados por assets" },
+ { "title": "Heartbeat del triggerer" },
+ {
+ "title": "Triggers en ejecución / capacidad restante",
+ "expressionLabels": ["triggers running", "capacity left"]
+ },
+ {
+ "title": "Triggers bloqueados / fallidos / exitosos",
+ "expressionLabels": ["blocked", "failed", "succeeded"]
+ }
+ ]
+ }
+}
diff --git a/apps/bff/src/bundled_templates/layers/airflow.i18n.fr.json
b/apps/bff/src/bundled_templates/layers/airflow.i18n.fr.json
new file mode 100644
index 0000000..e2bf92e
--- /dev/null
+++ b/apps/bff/src/bundled_templates/layers/airflow.i18n.fr.json
@@ -0,0 +1,69 @@
+{
+ "alias": "Airflow",
+ "group": "Planificateur de workflows",
+ "slots": {
+ "services": "Clusters Airflow",
+ "instances": "Composants"
+ },
+ "layer-header": {
+ "columns": [
+ { "label": "Taille du DAG bag" },
+ { "label": "Temps total de parsing DAG" },
+ { "label": "Slots libres de l'executor" },
+ { "label": "Slots planifiés" }
+ ]
+ },
+ "overview": {
+ "groups": [
+ {
+ "title": "Cluster",
+ "metrics": [
+ { "label": "Tâches exécutables", "tip": "Tâches prêtes à l'exécution
sur le cluster." },
+ { "label": "Tâches en file", "tip": "Tâches en attente sur
l'executor." },
+ { "label": "Slots libres de l'executor", "tip": "Slots libres de
l'executor, pas la capacité du pool." }
+ ]
+ }
+ ]
+ },
+ "dashboards": {
+ "service": [
+ { "title": "Tâches exécutables" },
+ { "title": "Tâches en cours" },
+ { "title": "Slots planifiés" },
+ { "title": "Tâches en file" },
+ { "title": "Slots libres de l'executor" },
+ { "title": "Taille de file DAG" },
+ { "title": "Erreurs d'import DAG" },
+ { "title": "Taille du DAG bag" },
+ { "title": "Temps total de parsing DAG" },
+ { "title": "Erreurs de rafraîchissement DAG" },
+ { "title": "Mises à jour d'assets" }
+ ],
+ "instance": [
+ {
+ "title": "Slots pool ouverts / différés / en cours",
+ "expressionLabels": ["pool open", "pool deferred", "pool running"]
+ },
+ {
+ "title": "Tâches en cours / slots planifiés",
+ "expressionLabels": ["running tasks", "scheduled slots"]
+ },
+ { "title": "Heartbeat du scheduler" },
+ {
+ "title": "Slots executor ouverts / en file",
+ "expressionLabels": ["open slots", "queued tasks"]
+ },
+ { "title": "Mises à jour d'assets" },
+ { "title": "DagRuns déclenchés par assets" },
+ { "title": "Heartbeat du triggerer" },
+ {
+ "title": "Triggers en cours / capacité restante",
+ "expressionLabels": ["triggers running", "capacity left"]
+ },
+ {
+ "title": "Triggers bloqués / échoués / réussis",
+ "expressionLabels": ["blocked", "failed", "succeeded"]
+ }
+ ]
+ }
+}
diff --git a/apps/bff/src/bundled_templates/layers/airflow.i18n.ja.json
b/apps/bff/src/bundled_templates/layers/airflow.i18n.ja.json
new file mode 100644
index 0000000..bd5d285
--- /dev/null
+++ b/apps/bff/src/bundled_templates/layers/airflow.i18n.ja.json
@@ -0,0 +1,69 @@
+{
+ "alias": "Airflow",
+ "group": "ワークフロースケジューラ",
+ "slots": {
+ "services": "Airflow クラスタ",
+ "instances": "コンポーネント"
+ },
+ "layer-header": {
+ "columns": [
+ { "label": "DAG bag サイズ" },
+ { "label": "DAG 総パース時間" },
+ { "label": "Executor 空きスロット" },
+ { "label": "スケジュール済みスロット" }
+ ]
+ },
+ "overview": {
+ "groups": [
+ {
+ "title": "クラスタ",
+ "metrics": [
+ { "label": "実行可能タスク", "tip": "クラスタ全体で実行可能なタスク数。" },
+ { "label": "キュー待ちタスク", "tip": "Executor で待機中のタスク数。" },
+ { "label": "Executor 空きスロット", "tip": "Executor の空きスロット(プール容量ではない)。" }
+ ]
+ }
+ ]
+ },
+ "dashboards": {
+ "service": [
+ { "title": "実行可能タスク" },
+ { "title": "実行中タスク" },
+ { "title": "スケジュール済みスロット" },
+ { "title": "キュー待ちタスク" },
+ { "title": "Executor 空きスロット" },
+ { "title": "DAG ファイルキューサイズ" },
+ { "title": "DAG インポートエラー" },
+ { "title": "DAG bag サイズ" },
+ { "title": "DAG 総パース時間" },
+ { "title": "DAG ファイル更新エラー" },
+ { "title": "アセット更新" }
+ ],
+ "instance": [
+ {
+ "title": "プール空き / 延期 / 実行中スロット",
+ "expressionLabels": ["pool open", "pool deferred", "pool running"]
+ },
+ {
+ "title": "実行中タスク / スケジュール済みスロット",
+ "expressionLabels": ["running tasks", "scheduled slots"]
+ },
+ { "title": "スケジューラハートビート" },
+ {
+ "title": "Executor 空き / キュー待ちスロット",
+ "expressionLabels": ["open slots", "queued tasks"]
+ },
+ { "title": "アセット更新" },
+ { "title": "アセット起動 DagRun" },
+ { "title": "トリガラーハートビート" },
+ {
+ "title": "実行中トリガ / 残り容量",
+ "expressionLabels": ["triggers running", "capacity left"]
+ },
+ {
+ "title": "トリガ ブロック / 失敗 / 成功",
+ "expressionLabels": ["blocked", "failed", "succeeded"]
+ }
+ ]
+ }
+}
diff --git a/apps/bff/src/bundled_templates/layers/airflow.i18n.ko.json
b/apps/bff/src/bundled_templates/layers/airflow.i18n.ko.json
new file mode 100644
index 0000000..2bd9a3f
--- /dev/null
+++ b/apps/bff/src/bundled_templates/layers/airflow.i18n.ko.json
@@ -0,0 +1,69 @@
+{
+ "alias": "Airflow",
+ "group": "워크플로 스케줄러",
+ "slots": {
+ "services": "Airflow 클러스터",
+ "instances": "컴포넌트"
+ },
+ "layer-header": {
+ "columns": [
+ { "label": "DAG bag 크기" },
+ { "label": "DAG 총 파싱 시간" },
+ { "label": "Executor 사용 가능 슬롯" },
+ { "label": "예약된 슬롯" }
+ ]
+ },
+ "overview": {
+ "groups": [
+ {
+ "title": "클러스터",
+ "metrics": [
+ { "label": "실행 가능 작업", "tip": "클러스터에서 실행 가능한 작업 수." },
+ { "label": "대기 작업", "tip": "Executor에서 대기 중인 작업 수." },
+ { "label": "Executor 사용 가능 슬롯", "tip": "Executor 여유 슬롯(풀 용량 아님)." }
+ ]
+ }
+ ]
+ },
+ "dashboards": {
+ "service": [
+ { "title": "실행 가능 작업" },
+ { "title": "실행 중 작업" },
+ { "title": "예약된 슬롯" },
+ { "title": "대기 작업" },
+ { "title": "Executor 사용 가능 슬롯" },
+ { "title": "DAG 파일 큐 크기" },
+ { "title": "DAG 가져오기 오류" },
+ { "title": "DAG bag 크기" },
+ { "title": "DAG 총 파싱 시간" },
+ { "title": "DAG 파일 새로고침 오류" },
+ { "title": "Asset 업데이트" }
+ ],
+ "instance": [
+ {
+ "title": "풀 여유 / 지연 / 실행 슬롯",
+ "expressionLabels": ["pool open", "pool deferred", "pool running"]
+ },
+ {
+ "title": "실행 중 작업 / 예약 슬롯",
+ "expressionLabels": ["running tasks", "scheduled slots"]
+ },
+ { "title": "스케줄러 하트비트" },
+ {
+ "title": "Executor 여유 / 대기 슬롯",
+ "expressionLabels": ["open slots", "queued tasks"]
+ },
+ { "title": "Asset 업데이트" },
+ { "title": "Asset 트리거 DagRun" },
+ { "title": "트리거러 하트비트" },
+ {
+ "title": "실행 중 트리거 / 남은 용량",
+ "expressionLabels": ["triggers running", "capacity left"]
+ },
+ {
+ "title": "트리거 차단 / 실패 / 성공",
+ "expressionLabels": ["blocked", "failed", "succeeded"]
+ }
+ ]
+ }
+}
diff --git a/apps/bff/src/bundled_templates/layers/airflow.i18n.pt.json
b/apps/bff/src/bundled_templates/layers/airflow.i18n.pt.json
new file mode 100644
index 0000000..053b122
--- /dev/null
+++ b/apps/bff/src/bundled_templates/layers/airflow.i18n.pt.json
@@ -0,0 +1,69 @@
+{
+ "alias": "Airflow",
+ "group": "Agendador de workflows",
+ "slots": {
+ "services": "Clusters Airflow",
+ "instances": "Componentes"
+ },
+ "layer-header": {
+ "columns": [
+ { "label": "Tamanho do DAG bag" },
+ { "label": "Tempo total de parse DAG" },
+ { "label": "Slots livres do executor" },
+ { "label": "Slots agendados" }
+ ]
+ },
+ "overview": {
+ "groups": [
+ {
+ "title": "Cluster",
+ "metrics": [
+ { "label": "Tasks executáveis", "tip": "Tasks prontas para execução
no cluster." },
+ { "label": "Tasks enfileiradas", "tip": "Tasks aguardando no
executor." },
+ { "label": "Slots livres do executor", "tip": "Slots livres do
executor, não capacidade do pool." }
+ ]
+ }
+ ]
+ },
+ "dashboards": {
+ "service": [
+ { "title": "Tasks executáveis" },
+ { "title": "Tasks em execução" },
+ { "title": "Slots agendados" },
+ { "title": "Tasks enfileiradas" },
+ { "title": "Slots livres do executor" },
+ { "title": "Tamanho da fila de arquivos DAG" },
+ { "title": "Erros de importação DAG" },
+ { "title": "Tamanho do DAG bag" },
+ { "title": "Tempo total de parse DAG" },
+ { "title": "Erros de refresh de arquivos DAG" },
+ { "title": "Atualizações de assets" }
+ ],
+ "instance": [
+ {
+ "title": "Slots de pool abertos / adiados / em execução",
+ "expressionLabels": ["pool open", "pool deferred", "pool running"]
+ },
+ {
+ "title": "Tasks em execução / slots agendados",
+ "expressionLabels": ["running tasks", "scheduled slots"]
+ },
+ { "title": "Heartbeat do scheduler" },
+ {
+ "title": "Slots do executor abertos / enfileirados",
+ "expressionLabels": ["open slots", "queued tasks"]
+ },
+ { "title": "Atualizações de assets" },
+ { "title": "DagRuns acionados por assets" },
+ { "title": "Heartbeat do triggerer" },
+ {
+ "title": "Triggers em execução / capacidade restante",
+ "expressionLabels": ["triggers running", "capacity left"]
+ },
+ {
+ "title": "Triggers bloqueados / falhos / bem-sucedidos",
+ "expressionLabels": ["blocked", "failed", "succeeded"]
+ }
+ ]
+ }
+}
diff --git a/apps/bff/src/bundled_templates/layers/airflow.i18n.zh-CN.json
b/apps/bff/src/bundled_templates/layers/airflow.i18n.zh-CN.json
new file mode 100644
index 0000000..2d209bf
--- /dev/null
+++ b/apps/bff/src/bundled_templates/layers/airflow.i18n.zh-CN.json
@@ -0,0 +1,98 @@
+{
+ "alias": "Airflow",
+ "group": "工作流调度",
+ "slots": {
+ "services": "Airflow 集群",
+ "instances": "组件"
+ },
+ "layer-header": {
+ "columns": [
+ { "label": "DAG Bag 大小" },
+ { "label": "DAG 总解析时间" },
+ { "label": "Executor 空闲 Slot" },
+ { "label": "已调度 Slot" }
+ ]
+ },
+ "overview": {
+ "groups": [
+ {
+ "title": "集群",
+ "metrics": [
+ {
+ "label": "可执行任务",
+ "tip": "集群内待执行的任务数(airflow.scheduler.tasks.executable)。"
+ },
+ {
+ "label": "排队任务",
+ "tip": "Executor 上排队等待的任务数(airflow.executor.queued_tasks)。"
+ },
+ {
+ "label": "Executor 空闲 Slot",
+ "tip": "Executor 可用 slot,非 pool 容量(airflow.executor.open_slots)。"
+ }
+ ]
+ }
+ ]
+ },
+ "dashboards": {
+ "service": [
+ {
+ "title": "可执行任务",
+ "tip": "集群内待执行的任务数(airflow.scheduler.tasks.executable)。"
+ },
+ {
+ "title": "运行中任务",
+ "tip": "Executor 上正在运行的任务数(airflow.executor.running_tasks)。"
+ },
+ {
+ "title": "已调度 Slot",
+ "tip": "Pool 中已调度但未运行的 slot,跨 pool 聚合(airflow.pool.scheduled_slots)。"
+ },
+ {
+ "title": "排队任务",
+ "tip": "Executor 上排队等待的任务数(airflow.executor.queued_tasks)。"
+ },
+ {
+ "title": "Executor 空闲 Slot",
+ "tip": "Executor 可用 slot(airflow.executor.open_slots)。"
+ },
+ { "title": "DAG 文件队列大小", "tip": "待扫描的 DAG
文件数(airflow.dag_processing.file_path_queue_size)。" },
+ { "title": "DAG 导入错误", "tip": "解析失败的 DAG
文件数(airflow.dag_processing.import_errors)。" },
+ { "title": "DAG Bag 大小", "tip": "最近一次 scheduler 扫描发现的 DAG
数(airflow.dagbag_size)。" },
+ { "title": "DAG 总解析时间", "tip": "扫描并导入排队 DAG
文件的秒数(airflow.dag_processing.total_parse_time)。" },
+ { "title": "DAG 文件刷新错误", "tip": "每分钟 DAG
文件加载失败次数(airflow.dag_file_refresh_error)。" },
+ { "title": "Asset 更新", "tip": "每分钟 asset 更新事件数(airflow.asset.updates)。" }
+ ],
+ "instance": [
+ {
+ "title": "Pool 空闲 / 延迟 / 运行 Slot",
+ "tip": "Scheduler 上的 pool
容量(airflow.pool.open_slots、deferred_slots、running_slots)。",
+ "expressionLabels": ["pool open", "pool deferred", "pool running"]
+ },
+ {
+ "title": "运行中任务 / 已调度 Slot",
+ "tip": "Scheduler executor 队列深度及待运行的 pool slot。",
+ "expressionLabels": ["running tasks", "scheduled slots"]
+ },
+ { "title": "Scheduler 心跳", "tip": "Scheduler
每分钟心跳数(airflow.scheduler_heartbeat)。" },
+ {
+ "title": "Executor 空闲 / 排队 Slot",
+ "tip": "Scheduler 上 executor 容量与队列深度。",
+ "expressionLabels": ["open slots", "queued tasks"]
+ },
+ { "title": "Asset 更新", "tip": "Scheduler 上的 asset
更新事件(airflow.asset.updates)。" },
+ { "title": "Asset 触发的 DagRun", "tip": "Scheduler 上由 asset 事件触发的
DagRun(airflow.asset.triggered_dagruns)。" },
+ { "title": "Triggerer 心跳", "tip": "Triggerer
每分钟心跳数(airflow.triggerer_heartbeat)。" },
+ {
+ "title": "运行中 Trigger / 剩余容量",
+ "tip": "Triggerer 上 deferrable trigger 负载。",
+ "expressionLabels": ["triggers running", "capacity left"]
+ },
+ {
+ "title": "Trigger 阻塞 / 失败 / 成功",
+ "tip": "Triggerer 主机上 deferred trigger 结果。",
+ "expressionLabels": ["blocked", "failed", "succeeded"]
+ }
+ ]
+ }
+}
diff --git a/apps/bff/src/bundled_templates/layers/airflow.json
b/apps/bff/src/bundled_templates/layers/airflow.json
new file mode 100644
index 0000000..b74b15e
--- /dev/null
+++ b/apps/bff/src/bundled_templates/layers/airflow.json
@@ -0,0 +1,372 @@
+{
+ "key": "AIRFLOW",
+ "alias": "Airflow",
+ "group": "Workflow Scheduler",
+ "color": "var(--sw-cyan)",
+ "documentLink":
"https://skywalking.apache.org/docs/main/next/en/setup/backend/backend-airflow-monitoring/",
+ "aliases": {
+ "services": "Airflow clusters",
+ "instances": "Components"
+ },
+ "components": {
+ "service": true,
+ "instances": true,
+ "endpoints": false,
+ "topology": false,
+ "traces": false,
+ "logs": false
+ },
+ "layer-header": {
+ "orderBy": "dagbagSize",
+ "columns": [
+ {
+ "metric": "dagbagSize",
+ "label": "DAG Bag Size",
+ "mqe": "meter_airflow_dagbag_size",
+ "aggregation": "sum"
+ },
+ {
+ "metric": "dagTotalParseTime",
+ "label": "DAG Total Parse Time",
+ "mqe": "meter_airflow_dag_total_parse_time",
+ "aggregation": "sum",
+ "unit": "s"
+ },
+ {
+ "metric": "openSlots",
+ "label": "Executor Open Slots",
+ "mqe": "meter_airflow_executor_open_slots",
+ "aggregation": "sum"
+ },
+ {
+ "metric": "scheduledSlots",
+ "label": "Scheduled Slots",
+ "mqe": "aggregate_labels(meter_airflow_pool_scheduled_slots, sum)",
+ "aggregation": "sum"
+ }
+ ]
+ },
+ "overview": {
+ "groups": [
+ {
+ "title": "Cluster",
+ "size": "auto",
+ "metrics": [
+ {
+ "id": "tasksExecutable",
+ "label": "Tasks Executable",
+ "tip": "Tasks ready for execution across the cluster
(airflow.scheduler.tasks.executable).",
+ "mqe": "meter_airflow_scheduler_tasks_executable",
+ "aggregation": "sum"
+ },
+ {
+ "id": "queuedTasks",
+ "label": "Queued Tasks",
+ "tip": "Tasks waiting on the executor
(airflow.executor.queued_tasks).",
+ "mqe": "meter_airflow_executor_queued_tasks",
+ "aggregation": "sum"
+ },
+ {
+ "id": "openSlots",
+ "label": "Executor Open Slots",
+ "tip": "Free executor slots, not pool capacity
(airflow.executor.open_slots).",
+ "mqe": "meter_airflow_executor_open_slots",
+ "aggregation": "sum"
+ }
+ ]
+ }
+ ]
+ },
+ "dashboards": {
+ "service": [
+ {
+ "id": "tasks_executable",
+ "title": "Tasks Executable",
+ "tip": "Tasks ready for execution across the cluster
(airflow.scheduler.tasks.executable).",
+ "type": "card",
+ "expressions": [
+ "latest(meter_airflow_scheduler_tasks_executable)"
+ ],
+ "span": 3,
+ "rowSpan": 1,
+ "format": "int"
+ },
+ {
+ "id": "running_tasks",
+ "title": "Running Tasks",
+ "tip": "Tasks currently running on the executor
(airflow.executor.running_tasks).",
+ "type": "card",
+ "expressions": [
+ "latest(meter_airflow_executor_running_tasks)"
+ ],
+ "span": 3,
+ "rowSpan": 1,
+ "format": "int"
+ },
+ {
+ "id": "scheduled_slots",
+ "title": "Scheduled Slots",
+ "tip": "Pool slots scheduled but not yet running, aggregated across
pools (airflow.pool.scheduled_slots).",
+ "type": "card",
+ "expressions": [
+ "latest(aggregate_labels(meter_airflow_pool_scheduled_slots, sum))"
+ ],
+ "span": 3,
+ "rowSpan": 1,
+ "format": "int"
+ },
+ {
+ "id": "queued_tasks",
+ "title": "Queued Tasks",
+ "tip": "Tasks waiting on the executor
(airflow.executor.queued_tasks).",
+ "type": "card",
+ "expressions": [
+ "latest(meter_airflow_executor_queued_tasks)"
+ ],
+ "span": 3,
+ "rowSpan": 1,
+ "format": "int"
+ },
+ {
+ "id": "open_slots",
+ "title": "Executor Open Slots",
+ "tip": "Free executor slots (airflow.executor.open_slots).",
+ "type": "line",
+ "expressions": [
+ "meter_airflow_executor_open_slots"
+ ],
+ "span": 4,
+ "rowSpan": 2,
+ "format": "int"
+ },
+ {
+ "id": "dag_file_queue",
+ "title": "DAG File Queue Size",
+ "tip": "DAG files pending scan
(airflow.dag_processing.file_path_queue_size).",
+ "type": "line",
+ "expressions": [
+ "meter_airflow_dag_file_queue_size"
+ ],
+ "span": 6,
+ "rowSpan": 2,
+ "format": "int"
+ },
+ {
+ "id": "dag_import_errors",
+ "title": "DAG Import Errors",
+ "tip": "DAG files that failed to parse
(airflow.dag_processing.import_errors).",
+ "type": "line",
+ "expressions": [
+ "meter_airflow_dag_import_errors"
+ ],
+ "span": 6,
+ "rowSpan": 2,
+ "format": "int"
+ },
+ {
+ "id": "dagbag_size",
+ "title": "DAG Bag Size",
+ "tip": "DAGs found in the last scheduler scan (airflow.dagbag_size).",
+ "type": "line",
+ "expressions": [
+ "meter_airflow_dagbag_size"
+ ],
+ "span": 6,
+ "rowSpan": 2,
+ "format": "int"
+ },
+ {
+ "id": "dag_total_parse_time",
+ "title": "DAG Total Parse Time",
+ "tip": "Seconds to scan and import queued DAG files
(airflow.dag_processing.total_parse_time).",
+ "type": "line",
+ "unit": "s",
+ "expressions": [
+ "meter_airflow_dag_total_parse_time"
+ ],
+ "span": 6,
+ "rowSpan": 2,
+ "format": "decimal"
+ },
+ {
+ "id": "dag_file_refresh_error",
+ "title": "DAG File Refresh Errors",
+ "tip": "DAG file load failures per minute
(airflow.dag_file_refresh_error).",
+ "type": "line",
+ "unit": "/min",
+ "expressions": [
+ "meter_airflow_dag_file_refresh_error"
+ ],
+ "span": 6,
+ "rowSpan": 2,
+ "format": "int"
+ },
+ {
+ "id": "asset_updates",
+ "title": "Asset Updates",
+ "tip": "Asset update events per minute (airflow.asset.updates).",
+ "type": "line",
+ "unit": "/min",
+ "expressions": [
+ "meter_airflow_asset_updates"
+ ],
+ "span": 12,
+ "rowSpan": 2,
+ "format": "int"
+ }
+ ],
+ "instance": [
+ {
+ "id": "pool_slots",
+ "title": "Pool Open / Deferred / Running Slots",
+ "tip": "Pool capacity on the scheduler (airflow.pool.open_slots,
airflow.pool.deferred_slots, airflow.pool.running_slots).",
+ "type": "line",
+ "expressions": [
+ "meter_airflow_instance_pool_open_slots",
+ "meter_airflow_instance_pool_deferred_slots",
+ "meter_airflow_instance_pool_running_slots"
+ ],
+ "expressionLabels": [
+ "pool open",
+ "pool deferred",
+ "pool running"
+ ],
+ "visibleWhen": { "kind": "mqe", "expression":
"meter_airflow_instance_pool_open_slots", "op": "exists" },
+ "span": 6,
+ "rowSpan": 2,
+ "format": "int"
+ },
+ {
+ "id": "running_tasks",
+ "title": "Running Tasks / Scheduled Slots",
+ "tip": "Scheduler executor queue depth and pool slots waiting to run
(airflow.executor.running_tasks, airflow.pool.scheduled_slots).",
+ "type": "line",
+ "expressions": [
+ "meter_airflow_instance_executor_running_tasks",
+ "meter_airflow_instance_pool_scheduled_slots"
+ ],
+ "expressionLabels": [
+ "running tasks",
+ "scheduled slots"
+ ],
+ "visibleWhen": { "kind": "mqe", "expression":
"meter_airflow_instance_executor_running_tasks", "op": "exists" },
+ "span": 6,
+ "rowSpan": 2,
+ "format": "int"
+ },
+ {
+ "id": "scheduler_heartbeat",
+ "title": "Scheduler Heartbeat",
+ "tip": "Scheduler heartbeats per minute
(airflow.scheduler_heartbeat).",
+ "type": "line",
+ "unit": "/min",
+ "expressions": [
+ "meter_airflow_instance_scheduler_heartbeat"
+ ],
+ "visibleWhen": { "kind": "mqe", "expression":
"meter_airflow_instance_scheduler_heartbeat", "op": "exists" },
+ "span": 6,
+ "rowSpan": 2,
+ "format": "int"
+ },
+ {
+ "id": "executor_slots",
+ "title": "Executor Open / Queued Slots",
+ "tip": "Executor capacity and queue depth on the scheduler
(airflow.executor.open_slots, airflow.executor.queued_tasks).",
+ "type": "line",
+ "expressions": [
+ "meter_airflow_instance_executor_open_slots",
+ "meter_airflow_instance_executor_queued_tasks"
+ ],
+ "expressionLabels": [
+ "open slots",
+ "queued tasks"
+ ],
+ "visibleWhen": { "kind": "mqe", "expression":
"meter_airflow_instance_executor_open_slots", "op": "exists" },
+ "span": 6,
+ "rowSpan": 2,
+ "format": "int"
+ },
+ {
+ "id": "asset_updates",
+ "title": "Asset Updates",
+ "tip": "Asset update events on the scheduler (airflow.asset.updates).",
+ "type": "line",
+ "unit": "/min",
+ "expressions": [
+ "meter_airflow_instance_asset_updates"
+ ],
+ "visibleWhen": { "kind": "mqe", "expression":
"meter_airflow_instance_asset_updates", "op": "exists" },
+ "span": 6,
+ "rowSpan": 2,
+ "format": "int"
+ },
+ {
+ "id": "asset_triggered",
+ "title": "Asset Triggered DagRuns",
+ "tip": "DagRuns triggered by asset events on the scheduler
(airflow.asset.triggered_dagruns).",
+ "type": "line",
+ "unit": "/min",
+ "expressions": [
+ "meter_airflow_instance_asset_triggered_dagruns"
+ ],
+ "visibleWhen": { "kind": "mqe", "expression":
"meter_airflow_instance_asset_triggered_dagruns", "op": "exists" },
+ "span": 6,
+ "rowSpan": 2,
+ "format": "int"
+ },
+ {
+ "id": "triggerer_heartbeat",
+ "title": "Triggerer Heartbeat",
+ "tip": "Triggerer process heartbeats per minute
(airflow.triggerer_heartbeat).",
+ "type": "line",
+ "unit": "/min",
+ "expressions": [
+ "meter_airflow_instance_triggerer_heartbeat"
+ ],
+ "visibleWhen": { "kind": "mqe", "expression":
"meter_airflow_instance_triggerer_heartbeat", "op": "exists" },
+ "span": 6,
+ "rowSpan": 2,
+ "format": "int"
+ },
+ {
+ "id": "triggerer_capacity",
+ "title": "Triggers Running / Capacity Left",
+ "tip": "Live deferrable trigger load on the triggerer
(airflow.triggers.running, airflow.triggerer.capacity_left).",
+ "type": "line",
+ "expressions": [
+ "meter_airflow_instance_triggers_running",
+ "meter_airflow_instance_triggerer_capacity_left"
+ ],
+ "expressionLabels": [
+ "triggers running",
+ "capacity left"
+ ],
+ "visibleWhen": { "kind": "mqe", "expression":
"meter_airflow_instance_triggerer_heartbeat", "op": "exists" },
+ "span": 6,
+ "rowSpan": 2,
+ "format": "int"
+ },
+ {
+ "id": "triggers",
+ "title": "Triggers Blocked / Failed / Succeeded",
+ "tip": "Deferred trigger outcomes on the triggerer host
(airflow.triggers.blocked_main_thread, airflow.triggers.failed,
airflow.triggers.succeeded).",
+ "type": "line",
+ "unit": "/min",
+ "expressions": [
+ "meter_airflow_instance_triggers_blocked_main_thread",
+ "meter_airflow_instance_triggers_failed",
+ "meter_airflow_instance_triggers_succeeded"
+ ],
+ "expressionLabels": [
+ "blocked",
+ "failed",
+ "succeeded"
+ ],
+ "visibleWhen": { "kind": "mqe", "expression":
"meter_airflow_instance_triggerer_heartbeat", "op": "exists" },
+ "span": 6,
+ "rowSpan": 2,
+ "format": "int"
+ }
+ ]
+ }
+}