跳至主要內容
在 GitHub 上編輯此頁面

警報與報表

使用者可以設定自動化的警報和報表,將儀表板或圖表發送給電子郵件收件者或 Slack 頻道。

  • 警報會在達到 SQL 條件時發送
  • 報表會依排程發送

警報和報表預設為停用。要啟用它們,您需要進行一些設定,此處將說明。

需求

通用

在您的 superset_config.pysuperset_config_docker.py

  • "ALERT_REPORTS" 功能旗標必須設定為 True。
  • CeleryConfig 中的 beat_schedule 必須包含 reports.scheduler 的排程。
  • 至少必須設定其中一項,取決於您要使用哪一項
    • 電子郵件:SMTP_* 設定
    • Slack 訊息:SLACK_API_TOKEN
停用試執行模式

只要 ALERT_REPORTS_NOTIFICATION_DRY_RUN = True (其在 docker/pythonpath_dev/superset_config.py 中的預設值),就會擷取螢幕截圖,但實際上不會發送任何訊息。若要停用試執行模式並開始接收電子郵件/Slack 通知,請在superset 設定中將 ALERT_REPORTS_NOTIFICATION_DRY_RUN 設定為 False

在您的 Dockerfile

  • 您必須安裝無頭瀏覽器,以擷取圖表和儀表板的螢幕截圖。目前僅支援 Firefox 和 Chrome。

    如果您選擇 Chrome,您也必須在 superset_config.py 中將 WEBDRIVER_TYPE 的值變更為 "chrome"

注意:如果您遵循在本地安裝 Superset,所有需要的元件 (Firefox 無頭瀏覽器、Redis、Postgres 資料庫、celery 工作程式和 celery beat) 都存在於 _dev_ docker 映像檔中。您只需要新增本指南中描述的必要設定變數 (請參閱 詳細設定)。

如果您執行的是非開發 docker 映像檔,例如像 apache/superset:3.1.0 的穩定版本,該映像檔不包含無頭瀏覽器。只有 superset_worker 容器需要此無頭瀏覽器才能瀏覽至目標圖表或儀表板。您可以安裝和設定無頭瀏覽器 (請參閱下方的「自訂 Dockerfile」區段),或在使用 docker compose 部署時,修改您的 docker-compose.yml 檔案,以針對工作程式容器使用開發映像檔,並針對 superset_app 容器使用穩定版本映像檔。

注意:在此內容中,「開發映像檔」與其對應的非開發映像檔是相同的應用程式軟體,只是額外捆綁了其他工具。因此,當涉及穩定性、功能性和在生產環境中執行時,像 3.1.0-dev 的映像檔與 3.1.0 相同。Superset 實際「開發中」的版本 (最先進且不穩定) 不會在 Docker Hub 上標記版本號碼,並會在 Superset UI 內顯示版本 0.0.0-dev

Slack 整合

若要將警報和報表傳送至 Slack 頻道,您需要在您的工作區上建立新的 Slack 應用程式。

  1. 連線至您的 Slack 工作區,然後前往 [https://api.slack.com/apps]。
  2. 建立新的應用程式。
  3. 前往「OAuth 與權限」區段,並為您的應用程式提供以下範圍
    • incoming-webhook
    • files:write
    • chat:write
  4. 在「OAuth 和權限」區段的頂端,按一下「安裝至工作區」。
  5. 為您的應用程式選取預設頻道並繼續。(您可以透過將您的 Superset 應用程式邀請至該頻道,將貼文發佈至任何頻道)。
  6. 現在應該已在您的工作區中安裝應用程式,並且應該已建立「Bot User OAuth Access Token」。將該權杖複製到您 superset_config.pySLACK_API_TOKEN 變數中。
  7. 重新啟動服務 (或執行 superset init) 以提取新的設定。

注意:當您設定警報或報表時,Slack 頻道清單會採用不含前置 '#' 的頻道名稱,例如,使用 alerts 而不是 #alerts

Kubernetes 特有

  • 您必須執行 celery beat pod。如果您使用的是 GitHub 儲存庫中 helm/superset 下包含的圖表,您需要在您的值覆寫中放入 supersetCeleryBeat.enabled = true
  • 您可以查看有關Kubernetes 安裝的專用文件,以取得更多詳細資料。

Docker Compose 特有

您必須在您的 docker-compose.yml 中擁有

  • Redis 訊息代理程式
  • PostgreSQL 資料庫,而不是 SQLlite
  • 一個或多個 celery worker
  • 單一 celery beat

此程序也適用於 Docker swarm 環境,您只需要將 Deploy: 新增至 Superset、Redis 和 Postgres 服務以及針對您的 swarm 的特定設定即可。

詳細設定

以下設定需要新增至 superset_config.py 檔案。當映像檔執行時會載入此檔案,且其中的任何設定都將覆寫在 config.py 中找到的預設設定。

您可以在 GitHub 儲存庫中 superset/config.py 下的預設 config.py 中找到每個欄位的相關文件。

您需要將預設值取代為您自訂的 Redis、Slack 和/或 SMTP 設定。

Superset 使用 Celery beat 和 Celery 工作程式來傳送警報和報表。

  • beat 是排程器,會告知工作程式何時執行其工作。當您建立警報或報表時,會定義此排程。
  • 當觸發警報或報表時,工作程式會處理需要執行的工作。

CeleryConfig 中,只有 beat_schedule 與此功能相關,CeleryConfig 的其餘部分可以根據您的需求變更。

from celery.schedules import crontab

FEATURE_FLAGS = {
"ALERT_REPORTS": True
}

REDIS_HOST = "superset_cache"
REDIS_PORT = "6379"

class CeleryConfig:
broker_url = f"redis://{REDIS_HOST}:{REDIS_PORT}/0"
imports = (
"superset.sql_lab",
"superset.tasks.scheduler",
)
result_backend = f"redis://{REDIS_HOST}:{REDIS_PORT}/0"
worker_prefetch_multiplier = 10
task_acks_late = True
task_annotations = {
"sql_lab.get_sql_results": {
"rate_limit": "100/s",
},
}
beat_schedule = {
"reports.scheduler": {
"task": "reports.scheduler",
"schedule": crontab(minute="*", hour="*"),
},
"reports.prune_log": {
"task": "reports.prune_log",
"schedule": crontab(minute=0, hour=0),
},
}
CELERY_CONFIG = CeleryConfig

SCREENSHOT_LOCATE_WAIT = 100
SCREENSHOT_LOAD_WAIT = 600

# Slack configuration
SLACK_API_TOKEN = "xoxb-"

# Email configuration
SMTP_HOST = "smtp.sendgrid.net" # change to your host
SMTP_PORT = 2525 # your port, e.g. 587
SMTP_STARTTLS = True
SMTP_SSL_SERVER_AUTH = True # If your using an SMTP server with a valid certificate
SMTP_SSL = False
SMTP_USER = "your_user" # use the empty string "" if using an unauthenticated SMTP server
SMTP_PASSWORD = "your_password" # use the empty string "" if using an unauthenticated SMTP server
SMTP_MAIL_FROM = "noreply@youremail.com"
EMAIL_REPORTS_SUBJECT_PREFIX = "[Superset] " # optional - overwrites default value in config.py of "[Report] "

# WebDriver configuration
# If you use Firefox, you can stick with default values
# If you use Chrome, then add the following WEBDRIVER_TYPE and WEBDRIVER_OPTION_ARGS
WEBDRIVER_TYPE = "chrome"
WEBDRIVER_OPTION_ARGS = [
"--force-device-scale-factor=2.0",
"--high-dpi-support=2.0",
"--headless",
"--disable-gpu",
"--disable-dev-shm-usage",
"--no-sandbox",
"--disable-setuid-sandbox",
"--disable-extensions",
]

# This is for internal use, you can keep http
WEBDRIVER_BASEURL = "http://superset:8088" # When running using docker compose use "http://superset_app:8088'
# This is the link sent to the recipient. Change to your domain, e.g. https://superset.mydomain.com
WEBDRIVER_BASEURL_USER_FRIENDLY = "https://127.0.0.1:8088"

您也需要指定代表哪個使用者名稱來呈現儀表板。一般而言,未經授權的請求無法存取儀表板和圖表,這就是為什麼工作程式需要接管現有使用者的憑證以擷取快照。

依預設,警報和報表會以警報/報表物件的擁有者身分執行。若要使用固定的使用者帳戶,只需如下變更設定 (在此範例中為 admin)

from superset.tasks.types import ExecutorType

THUMBNAIL_SELENIUM_USER = 'admin'
ALERT_REPORTS_EXECUTE_AS = [ExecutorType.SELENIUM]

請參閱程式碼中的 ExecutorType 以取得其他執行器類型。

重要注意事項

  • 請注意 celery 的並行設定 (使用 -c 4)。Selenium/webdriver 執行個體可能會在您的伺服器上消耗大量 CPU/記憶體。
  • 在某些情況下,如果您注意到許多洩漏的 geckodriver 程序,請嘗試使用 celery worker --pool=prefork --max-tasks-per-child=128 ... 執行您的 celery 程序
  • 建議為 sql_labemail_reports 工作執行個別的工作程式。這可以使用 task_annotations 中的 queue 欄位來完成。
  • 如果 celery 工作程式無法透過預設值 http://0.0.0.0:8080/ 存取 Superset,請在您的設定檔案中調整 WEBDRIVER_BASEURL

也可以透過設定檔案指定每個報表執行之間的最小間隔

# Set a minimum interval threshold between executions (for each Alert/Report)
# Value should be an integer
ALERT_MINIMUM_INTERVAL = int(timedelta(minutes=10).total_seconds())
REPORT_MINIMUM_INTERVAL = int(timedelta(minutes=5).total_seconds())

或者,您可以將函式指派給 ALERT_MINIMUM_INTERVAL 和/或 REPORT_MINIMUM_INTERVAL。這對於根據需要動態擷取值很有用

def alert_dynamic_minimal_interval(**kwargs) -> int:
"""
Define logic here to retrieve the value dynamically
"""

ALERT_MINIMUM_INTERVAL = alert_dynamic_minimal_interval

自訂 Dockerfile

如果您執行的是已發佈 Superset 映像檔的開發版本,例如 apache/superset:3.1.0-dev,您應該已完成以上操作。

但是,如果您要建置自己的映像檔,或從非開發版本開始,則需要 webdriver (和無頭瀏覽器) 來擷取圖表和儀表板的螢幕截圖,然後將其傳送給收件者。以下說明如何修改您的 Dockerfile,以使用 Firefox 或 Chrome 擷取螢幕截圖。

使用 Firefox

FROM apache/superset:3.1.0

USER root

RUN apt-get update && \
apt-get install --no-install-recommends -y firefox-esr

ENV GECKODRIVER_VERSION=0.29.0
RUN wget -q https://github.com/mozilla/geckodriver/releases/download/v${GECKODRIVER_VERSION}/geckodriver-v${GECKODRIVER_VERSION}-linux64.tar.gz && \
tar -x geckodriver -zf geckodriver-v${GECKODRIVER_VERSION}-linux64.tar.gz -O > /usr/bin/geckodriver && \
chmod 755 /usr/bin/geckodriver && \
rm geckodriver-v${GECKODRIVER_VERSION}-linux64.tar.gz

RUN pip install --no-cache gevent psycopg2 redis

USER superset

使用 Chrome

FROM apache/superset:3.1.0

USER root

RUN apt-get update && \
apt-get install -y wget zip libaio1

RUN export CHROMEDRIVER_VERSION=$(curl --silent https://googlechromelabs.github.io/chrome-for-testing/LATEST_RELEASE_116) && \
wget -O google-chrome-stable_current_amd64.deb -q http://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_${CHROMEDRIVER_VERSION}-1_amd64.deb && \
apt-get install -y --no-install-recommends ./google-chrome-stable_current_amd64.deb && \
rm -f google-chrome-stable_current_amd64.deb

RUN export CHROMEDRIVER_VERSION=$(curl --silent https://googlechromelabs.github.io/chrome-for-testing/LATEST_RELEASE_116) && \
wget -q https://storage.googleapis.com/chrome-for-testing-public/${CHROMEDRIVER_VERSION}/linux64/chromedriver-linux64.zip && \
unzip -j chromedriver-linux64.zip -d /usr/bin && \
chmod 755 /usr/bin/chromedriver && \
rm -f chromedriver-linux64.zip

RUN pip install --no-cache gevent psycopg2 redis

USER superset

如果您使用 Chrome,請勿忘記在您的設定中設定 WEBDRIVER_TYPEWEBDRIVER_OPTION_ARGS

疑難排解

報表可能無法運作的原因有很多。請嘗試下列步驟來檢查特定問題。

確認已啟用功能旗標,且您具有足夠的權限

如果您在 Superset UI 的「設定」下拉選單的 管理 區塊中沒有看到「警報與報表」,您需要啟用 ALERT_REPORTS 功能旗標(請參閱上方)。啟用另一個功能旗標並檢查是否生效,以驗證您的設定檔是否已載入。

請以管理員身分登入,以確保您擁有足夠的權限。

檢查您的 Celery worker 的日誌

這是關於問題的最佳資訊來源。在 docker compose 部署中,您可以使用類似 docker logs superset_worker --since 1h 的命令來執行此操作。

檢查網頁瀏覽器和 webdriver 的安裝

為了截取螢幕快照,worker 會使用無頭瀏覽器訪問儀表板或圖表,然後截取螢幕快照。如果您能夠以 CSV 或文字格式傳送圖表,但無法以 PNG 格式傳送,則問題可能出在瀏覽器上。

標籤以 -dev 結尾的 Superset docker 映像檔已預先安裝 Firefox 無頭瀏覽器和 geckodriver。您可以透過進入 Superset worker 並執行 firefox --headless,然後執行 geckodriver 來測試這些是否已安裝且位於正確的路徑中。這兩個命令都應該啟動這些應用程式。

如果您自行處理該軟體的安裝,或希望改用 Chromium,請自行驗證以確保無頭瀏覽器在 worker 環境中成功開啟。

傳送測試電子郵件

連接到電子郵件伺服器的無效連線的其中一個症狀是,當報表嘗試傳送時,您會在日誌中收到 [Errno 110] Connection timed out 的錯誤訊息。

透過測試確認您的外寄電子郵件設定正確。以下是最簡單的測試,適用於在連接埠 25 上執行的未驗證電子郵件 SMTP 電子郵件服務。例如,如果您是透過 SSL 傳送,請研究 Superset 的程式碼如何傳送電子郵件,然後使用這些命令和引數進行測試。

在您的 worker 環境中啟動 Python,取代所有範例值,然後執行

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

from_email = 'superset_emails@example.com'
to_email = 'your_email@example.com'
msg = MIMEMultipart()
msg['From'] = from_email
msg['To'] = to_email
msg['Subject'] = 'Superset SMTP config test'
message = 'It worked'
msg.attach(MIMEText(message))
mailserver = smtplib.SMTP('smtpmail.example.com', 25)
mailserver.sendmail(from_email, to_email, msg.as_string())
mailserver.quit()

這應該會傳送一封電子郵件。

可能的修正

  • 某些雲端主機會停用未經驗證的外寄 SMTP 電子郵件,以防止垃圾郵件。例如,Azure 預設會封鎖某些機器上的連接埠 25。啟用該連接埠或使用其他傳送方法。
  • 使用另一組您驗證可以在此設定中使用的 SMTP 認證。

從 worker 瀏覽至您的報表

worker 可能無法訪問報表。它會使用 WEBDRIVER_BASEURL 的值來瀏覽至報表。如果該路由無效,或出現 worker 無法通過的驗證挑戰,則報表螢幕快照將會失敗。

透過嘗試 curl 您的 worker 的錯誤日誌中看到的報表 URL 來檢查這一點。例如,從 worker 環境中執行 curl http://superset_app:8088/superset/dashboard/1/。根據儀表板是否存在,您可能會收到不同的回應 - 例如,您可能需要變更該 URL 中的 1。如果您的日誌中存在來自失敗報表螢幕快照的 URL,這是一個很好的起點。目標是確定 WEBDRIVER_BASEURL 的有效值,並確定 HTTPS 或驗證等問題是否正在重新導向您的 worker。

在啟用驗證措施(如 HTTPS 和單一登入)的部署中,讓 worker 直接導覽至在相同位置執行的 Superset 應用程式,避免登入的需要可能是有意義的。例如,您可以將 WEBDRIVER_BASEURL="http://superset_app:8088" 用於 docker compose 部署,並在您的 TALISMAN_CONFIG 中設定 "force_https": False,

將查詢排程為報表

您可以選擇性地允許您的使用者直接在 SQL Lab 中排程查詢。這透過將額外的中繼資料新增至已儲存的查詢來完成,然後這些查詢會由外部排程器(如 Apache Airflow)擷取。

若要允許排程查詢,請將以下內容新增至您的設定檔中的 SCHEDULED_QUERIES

SCHEDULED_QUERIES = {
# This information is collected when the user clicks "Schedule query",
# and saved into the `extra` field of saved queries.
# See: https://github.com/mozilla-services/react-jsonschema-form
'JSONSCHEMA': {
'title': 'Schedule',
'description': (
'In order to schedule a query, you need to specify when it '
'should start running, when it should stop running, and how '
'often it should run. You can also optionally specify '
'dependencies that should be met before the query is '
'executed. Please read the documentation for best practices '
'and more information on how to specify dependencies.'
),
'type': 'object',
'properties': {
'output_table': {
'type': 'string',
'title': 'Output table name',
},
'start_date': {
'type': 'string',
'title': 'Start date',
# date-time is parsed using the chrono library, see
# https://www.npmjs.com/package/chrono-node#usage
'format': 'date-time',
'default': 'tomorrow at 9am',
},
'end_date': {
'type': 'string',
'title': 'End date',
# date-time is parsed using the chrono library, see
# https://www.npmjs.com/package/chrono-node#usage
'format': 'date-time',
'default': '9am in 30 days',
},
'schedule_interval': {
'type': 'string',
'title': 'Schedule interval',
},
'dependencies': {
'type': 'array',
'title': 'Dependencies',
'items': {
'type': 'string',
},
},
},
},
'UISCHEMA': {
'schedule_interval': {
'ui:placeholder': '@daily, @weekly, etc.',
},
'dependencies': {
'ui:help': (
'Check the documentation for the correct format when '
'defining dependencies.'
),
},
},
'VALIDATION': [
# ensure that start_date <= end_date
{
'name': 'less_equal',
'arguments': ['start_date', 'end_date'],
'message': 'End date cannot be before start date',
# this is where the error message is shown
'container': 'end_date',
},
],
# link to the scheduler; this example links to an Airflow pipeline
# that uses the query id and the output table as its name
'linkback': (
'https://airflow.example.com/admin/airflow/tree?'
'dag_id=query_${id}_${extra_json.schedule_info.output_table}'
),
}

此設定基於 react-jsonschema-form,並會在 SQL Lab 中新增一個名為「排程」的功能表項目。當點擊功能表項目時,會顯示一個模式視窗,使用者可以在其中新增排程查詢所需的中繼資料。

然後可以從端點 /api/v1/saved_query/ 擷取此資訊,並用於排程 JSON 中繼資料中具有 schedule_info 的查詢。對於 Airflow 以外的排程器,可以輕鬆地將其他欄位新增至上面的設定檔中。