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"
+      }
+    ]
+  }
+}


Reply via email to