警报与报告
用户可以配置自动警报和报告,将仪表板或图表发送到电子邮件收件人或 Slack 频道。
- 警报在达到 SQL 条件时发送
- 报告按计划发送
警报和报告默认是禁用的。要启用它们,您需要进行此处描述的一些设置。
要求
通用配置
在您的 superset_config.py
或 superset_config_docker.py
文件中
"ALERT_REPORTS"
功能标志必须设置为 True。- CeleryConfig 中的
beat_schedule
必须包含reports.scheduler
的计划。 - 以下至少一项必须配置,具体取决于您要使用的功能
- 电子邮件:
SMTP_*
设置 - Slack 消息:
SLACK_API_TOKEN
- 电子邮件:
- 用户可以通过包含日期代码占位符来自定义电子邮件主题,这些占位符在电子邮件发送时会自动替换为相应的 UTC 日期。要启用此功能,请激活
"DATE_FORMAT_IN_EMAIL_SUBJECT"
功能标志。这使得电子邮件主题中的日期格式化成为可能,防止所有报告电子邮件被分组到同一个线程中(报告功能的此项是可选的)。- 使用 strftime.org 的日期代码来创建电子邮件主题。
- 如果没有提供日期代码,则原始字符串将用作电子邮件主题。
禁用试运行模式
只要 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 worker 和 Celery beat)都包含在 dev Docker 镜像中。您只需添加本指南中描述的所需配置变量(参见 详细配置
)。
如果您正在运行非开发版 Docker 镜像,例如 apache/superset:3.1.0
这样的稳定版本,该镜像不包含无头浏览器。只有 superset_worker
容器需要此无头浏览器来访问目标图表或仪表板。您可以自行安装和配置无头浏览器(请参阅下面的“自定义 Dockerfile”部分),或者在使用 docker compose
部署时,修改您的 compose.yml
文件,使 worker 容器使用开发版镜像,而 superset_app
容器使用稳定版镜像。
注意:在此上下文中,“开发版镜像”与对应的非开发版镜像具有相同的应用软件,只是捆绑了额外的工具。因此,像 3.1.0-dev
这样的镜像在稳定性、功能和生产运行方面与 3.1.0
是相同的。Superset 实际的“开发中”版本(前沿且不稳定)在 Docker Hub 上没有版本号标记,并且在 Superset UI 中会显示版本 0.0.0-dev
。
Slack 集成
要将警报和报告发送到 Slack 频道,您需要在您的工作区中创建一个新的 Slack 应用程序。
- 连接到您的 Slack 工作区,然后前往 [https://api.slack.com/apps]。
- 创建一个新应用。
- 前往“OAuth & 权限”部分,并为您的应用授予以下范围
incoming-webhook
files:write
chat:write
channels:read
groups:read
- 在“OAuth 和权限”部分的顶部,点击“安装到工作区”。
- 为您的应用选择一个默认频道并继续。(您可以通过邀请您的 Superset 应用进入任何频道来发布到该频道)。
- 该应用现在应该已安装到您的工作区,并且已创建一个“机器人用户 OAuth 访问令牌”。将该令牌复制到您的
superset_config.py
文件的SLACK_API_TOKEN
变量中。 - 确保在
superset_config.py
中将功能标志ALERT_REPORT_SLACK_V2
设置为 True - 重启服务(或运行
superset init
)以加载新配置。
注意:当您配置警报或报告时,Slack 频道列表接收不带前导 '#' 的频道名称,例如使用 alerts
而不是 #alerts
。
Kubernetes 特有配置
- 您必须运行一个
Celery beat
pod。如果您使用的是 GitHub 仓库中 helm/superset 下的图表,您需要在您的 values override 中设置supersetCeleryBeat.enabled = true
。 - 有关更多详细信息,您可以查阅关于Kubernetes 安装的专门文档。
Docker Compose 特有配置
您的 compose.yml
中必须包含
- 一个 Redis 消息代理
- PostgreSQL 数据库(而不是 SQLite)
- 一个或多个
Celery worker
- 一个
Celery beat
此过程也适用于 Docker Swarm 环境,您只需在 Superset、Redis 和 Postgres 服务中添加 Deploy:
以及您的 Swarm 特定配置。
详细配置
以下配置需要添加到 superset_config.py
文件中。此文件在镜像运行时加载,其中的任何配置都将覆盖 config.py
中的默认配置。
您可以在 GitHub 仓库中 superset/config.py 路径下找到默认 config.py
中每个字段的文档。
您需要用您自定义的 Redis、Slack 和/或 SMTP 配置替换默认值。
Superset 使用 Celery beat 和 Celery worker(s) 来发送警报和报告。
- Beat 是调度器,它告诉 worker 何时执行其任务。此计划在您创建警报或报告时定义。
- 当警报或报告触发时,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 you're 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 需要借用现有用户的凭据来截取快照的原因。
默认情况下,警报和报告以警报/报告对象的所有者身份执行。要使用固定的用户帐户,只需按如下更改配置(本例中为 admin
)
from superset.tasks.types import FixedExecutor
ALERT_REPORTS_EXECUTORS = [FixedExecutor("admin")]
请参考代码库中的 ExecutorType
获取其他执行器类型。
重要说明
- 请注意 Celery 的并发设置(使用
-c 4
)。Selenium/webdriver 实例会消耗服务器大量的 CPU / 内存。 - 在某些情况下,如果您发现大量泄露的 geckodriver 进程,请尝试使用
celery worker --pool=prefork --max-tasks-per-child=128 ...
运行您的 Celery 进程。 - 建议为
sql_lab
和email_reports
任务运行单独的 worker。这可以通过task_annotations
中的queue
字段完成。 - 如果 Celery worker 无法通过
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_TYPE
和 WEBDRIVER_OPTION_ARGS
。
故障排除
报告可能无法工作的原因有很多。尝试以下步骤来检查特定问题。
确认功能标志已启用且您拥有足够的权限
如果您在 Superset UI 的“设置”下拉菜单的管理部分下没有看到“警报与报告”,则需要启用 ALERT_REPORTS
功能标志(见上文)。启用另一个功能标志并检查它是否生效,以验证您的配置文件是否正在加载。
以管理员用户身份登录,以确保您拥有足够的权限。
检查 Celery worker 的日志
这是有关问题的最佳信息来源。在 Docker Compose 部署中,您可以使用类似 docker logs superset_worker --since 1h
的命令来执行此操作。
检查 Web 浏览器和 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 应用程序可能更有意义,从而避免登录的需要。例如,对于 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://npmjs.net.cn/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://npmjs.net.cn/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 以外的调度器,可以轻松地在上述配置文件中添加额外的字段。