Skip to main content

警报和报告

用户可以配置自动警报和报告,将仪表板或图表发送到 email 接收者或 Slack 频道。

  • 警报 在达到 SQL 条件时发送
  • 报告 按照计划发送

警报和报告默认是禁用的。要开启它们,你需要做一些设置,这里会描述。

需求

公共需求

在你的 superset_config.pysuperset_config_docker.py

  • "ALERT_REPORTS" 特性标志 必须设为 True。
  • CeleryConfig 中的 beat_schedule 必须包含 reports.scheduler 的计划表。
  • 至少需要配置以下之一,取决于你想要使用的功能:
    • 邮件:SMTP_* 设置
    • Slack 消息:SLACK_API_TOKEN
Disable dry-run mode

Screenshots will be taken but no messages actually sent as long as ALERT_REPORTS_NOTIFICATION_DRY_RUN = True, its default value in docker/pythonpath_dev/superset_config.py. To disable dry-run mode and start receiving email/Slack notifications, set ALERT_REPORTS_NOTIFICATION_DRY_RUN to False in superset config.

禁用 dry-run 模式

只要 ALERT_REPORTS_NOTIFICATION_DRY_RUN = True,其在 docker/pythonpath_dev/superset_config.py 中的默认值,截图会被截取,但实际上不会发送任何消息。为了禁用 dry-run 模式并开始接收 email/Slack 通知,在 superset 配置中将 ALERT_REPORTS_NOTIFICATION_DRY_RUN 设为 False

在你的 Dockerfile

  • 你必须安装一个无头浏览器,用于截取图表和仪表板的屏幕快照。目前仅支持 Firefox 和 Chrome。

    如果你选择 Chrome,你还需要将 WEBDRIVER_TYPE 的值改为 "chrome" 在你的 superset_config.py 中。

注意:所有必需的组件(无头 Firefox 浏览器、Redis、Postgres 数据库、celery worker 和 celery beat)都包含在 dev Docker 镜像中,如果你遵循本地安装 Superset。 你只需添加这个指南中描述的所需配置变量(参见详细配置)。

如果你运行的是非开发版 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 & Permissions” 部分,并为你的应用赋予以下权限:
    • incoming-webhook
    • files:write
    • chat:write
  4. 在 "OAuth and Permissions" 部分顶部,点击 "install to workspace"。
  5. 为你的应用选择一个默认频道并继续。 (你可以通过邀请你的 Superset app 进入该频道来向任意频道发布)。
  6. 应用现在应该已经安装在你的工作空间中,一个 "Bot User OAuth Access Token" 应该已经被创建。 将该令牌复制到你的 superset_config.py 中的 SLACK_API_TOKEN 变量中。
  7. 重启服务(或运行 superset init)以加载新的配置。

注意:当你配置警报或报告时,Slack 频道列表需要使用不带前导 '#' 的频道名称,例如使用 alerts 而不是 #alerts

Kubernetes 特定

  • 你必须有一个运行中的 celery beat pod。如果你使用的是 GitHub 仓库中 helm/superset 下包含的 chart, 你需要在你的值覆盖中放入 supersetCeleryBeat.enabled = true
  • 你可以查看关于 Kubernetes 安装的专用文档获取更多细节。

Docker Compose 特定

你必须在你的 docker-compose.yml 中有

  • Redis 消息代理
  • PostgreSQL 数据库而不是 SQLlite
  • 一个或多个 celery worker
  • 单个 celery beat

此过程同样适用于 Docker Swarm 环境,你只需要在 Superset、Redis 和 Postgres 服务中添加 Deploy: 以及你的特定 Swarm 配置即可。

详细配置

以下配置需要添加到 superset_config.py 文件中。当镜像运行时,会加载这个文件,其中的任何配置都会覆盖 config.py 中的默认配置。

你可以在 GitHub 仓库下的 superset/config.py 找到关于每个字段的文档。

你需要用自定义的 Redis、Slack 和/或 SMTP 配置替换默认值。

Superset 使用 Celery beat 和 Celery worker(s) 来发送警报和报告。

  • Beat 是 scheduler,告诉 worker 何时执行任务。这个 schedule 在你创建警报或报告时定义。
  • worker 将处理警报或报告触发时需要执行的任务。

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 = "http://localhost:8088"

你也需要 指定代表哪个用户名来渲染仪表板。通常情况下,仪表板和图表 对未经授权的请求是不可访问的,这就是为什么 worker 需要接管 现有用户的凭证来拍摄快照的原因。

默认情况下,Alerts 和 Reports 作为警报/报告对象的所有者执行。要使用固定用户帐户, 只需按如下方式更改配置(此处以 admin 为例):

from superset.tasks.types import ExecutorType

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

请参阅代码库中的 ExecutorType 以了解其他执行器类型。

重要说明

  • 注意 celery 的并发设置(使用 -c 4)。Selenium/webdriver 实例可能 在你的服务器上消耗大量 CPU / memory。
  • 在某些情况下,如果你注意到大量泄漏的 geckodriver 进程,尝试使用 celery worker --pool=prefork --max-tasks-per-child=128 ... 运行你的 celery 进程。
  • 推荐为 sql_labemail_reports 任务分别运行 worker。这可以通过 在 task_annotations 中使用 queue 字段来完成。
  • 如果 celery workers 无法通过其默认值 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 && \
wget -q https://dl.google.com/linux/direct/google-chrome-stable_current_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://chromedriver.storage.googleapis.com/LATEST_RELEASE_102) && \
wget -q https://chromedriver.storage.googleapis.com/${CHROMEDRIVER_VERSION}/chromedriver_linux64.zip && \
unzip 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 的设置下拉菜单的 Manage 部分看不到 "Alerts & Reports", 你需要启用 ALERT_REPORTS 特性标志(见上文)。启用另一个特性标志并检查它是否生效,以验证你的配置文件是否已加载。

登录为管理员用户以确保你有足够的权限。

检查 Celery worker 的日志

这是关于问题的最佳信息来源。在 docker compose 部署中,你可以使用类似 docker logs superset_worker --since 1h 的命令来做到这一点。

检查 Web 浏览器和 webdriver 安装

为了拍摄 screenshot,worker 使用无头浏览器访问仪表板或图表,然后拍摄屏幕快照。如果你能够将图表作为 CSV 或文本发送,但不能作为 PNG 发送,你的问题可能出在浏览器上。

-dev 结尾的 Superset Docker 镜像已经安装了无头 Firefox 浏览器和 geckodriver。你可以通过进入你的 Superset worker 并运行 firefox --headless 然后运行 geckodriver 来测试这些是否已安装并在正确的路径中。这两个命令都应该启动这些应用程序。

如果你自己处理该软件的安装,或者希望使用 Chromium,进行自己的验证以确保无头浏览器在 worker 环境中成功打开。

发送测试邮件

无法连接到邮件服务器的一个症状是在日志中收到错误 [Errno 110] Connection timed out 当报告尝试发送时。

通过测试确认你的出站邮件配置正确。这是最简单的测试,对于在端口 25 上运行的未认证的邮件 SMTP 服务。如果你是通过 SSL 发送,例如,研究Superset 代码库如何发送邮件,然后使用那些命令和参数进行测试。

在你的工作进程环境中启动 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 浏览至你的 report

worker 可能无法访问到报告。它将使用 WEBDRIVER_BASEURL 的值来浏览至报告。如果该路由无效,或者呈现了一个 worker 无法通过的身份验证挑战,报告的屏幕快照将会失败。

通过尝试从你的 worker curl 你在 worker 错误日志中看到的报告 URL 来检查这个问题。例如,在 worker 环境中,运行 curl http://superset_app:8088/superset/dashboard/1/。根据仪表板是否存在,你可能会得到不同的响应——例如,你可能需要更改 URL 中的 1。如果在你的日志中有来自失败报告快照的 URL,那是一个很好的起点。目标是确定一个有效的 WEBDRIVER_BASEURL 值,并判断是否有 HTTPS 或身份验证等问题重定向了你的 worker。

在一个启用了如 HTTPS 和单点登录等身份验证措施的部署中,让 worker 直接导航至在同一位置运行的 Superset 应用程序可能是有意义的,这样可以避免登录的需求。例如,对于 docker compose 部署,你可以使用 WEBDRIVER_BASEURL="http://superset_app:8088",并在你的 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 中添加一个名为 “Schedule” 的菜单项。当点击该菜单项时,会弹出一个模态窗口,用户可以在其中添加用于安排查询所需的元数据。

此信息随后可以从 /api/v1/saved_query/ 端点检索,并用于安排 JSON 元数据中包含 schedule_info 的查询。对于除 Airflow 以外的调度器,可以轻松地在上述配置文件中添加额外的字段。