アラートとレポート
ユーザーは、自動アラートとレポートを設定して、ダッシュボードまたはチャートをメール受信者またはSlackチャンネルに送信できます。
- アラートは、SQL条件が満たされたときに送信されます。
- レポートは、スケジュールに基づいて送信されます。
アラートとレポートはデフォルトで無効になっています。有効にするには、ここで説明する設定を行う必要があります。
要件
共通
superset_config.pyまたはsuperset_config_docker.pyで
- "ALERT_REPORTS"フィーチャーフラグをTrueにする必要があります。
- CeleryConfigのbeat_scheduleに、reports.schedulerのスケジュールが含まれている必要があります。
- 使用する機能に応じて、少なくとも次のうち1つを設定する必要があります。
- メール:SMTP_*設定
- Slackメッセージ:SLACK_API_TOKEN
 
- メール:
ドライランモードの無効化
ALERT_REPORTS_NOTIFICATION_DRY_RUN = Trueである限り、スクリーンショットは撮影されますが、メッセージは実際には送信されません。これはdocker/pythonpath_dev/superset_config.pyのデフォルト値です。ドライランモードを無効にして、メール/Slack通知の受信を開始するには、superset configでALERT_REPORTS_NOTIFICATION_DRY_RUNをFalseに設定します。
Dockerfileで
- チャートとダッシュボードのスクリーンショットを撮影するために、ヘッドレスブラウザをインストールする必要があります。現在、FirefoxとChromeのみがサポートされています。
Chromeを選択した場合は、 superset_config.pyでWEBDRIVER_TYPEの値を"chrome"に変更する必要もあります。
注:必要なすべてのコンポーネント(Firefoxヘッドレスブラウザ、Redis、Postgres DB、celeryワーカー、celery beat)は、ローカルでのSupersetのインストールに従っている場合は、dev dockerイメージに存在します。このガイドで説明されている必要な構成変数(「詳細設定」を参照)を追加するだけです。
apache/superset:3.1.0のような安定版リリースなどの非dev dockerイメージを実行している場合、そのイメージにはヘッドレスブラウザは含まれていません。superset_workerコンテナのみが、ターゲットのチャートまたはダッシュボードを参照するためにこのヘッドレスブラウザを必要とします。ヘッドレスブラウザをインストールして構成するか(以下の「カスタムDockerfile」セクションを参照)、docker composeでデプロイするときに、docker-compose.ymlファイルを変更して、ワーカーコンテナにdevイメージを使用し、superset_appコンテナに安定版リリースイメージを使用することができます。
注:このコンテキストでは、「devイメージ」は、対応する非devイメージと同じアプリケーションソフトウェアですが、追加のツールがバンドルされています。したがって、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&Permissions」セクションに移動し、アプリに次のスコープを付与します。
- incoming-webhook
- files:write
- chat:write
 
- 「OAuth and Permissions」セクションの上部にある「install to workspace」をクリックします。
- アプリのデフォルトチャンネルを選択して続行します。(Supersetアプリをそのチャンネルに招待することで、任意のチャンネルに投稿できます)。
- アプリがワークスペースにインストールされ、「Bot User OAuth Access Token」が作成されたはずです。そのトークンをsuperset_config.pyのSLACK_API_TOKEN変数にコピーします。
- サービスを再起動するか(またはsuperset initを実行)、新しい構成をプルインします。
注:アラートまたはレポートを設定する場合、Slackチャンネルリストは、先頭の「#」なしでチャンネル名を取得します。たとえば、#alertsではなくalertsを使用します。
Kubernetes固有
- celery beatポッドが実行されている必要があります。GitHubリポジトリのhelm/supersetに含まれているチャートを使用している場合は、値の上書きで- supersetCeleryBeat.enabled = trueを設定する必要があります。
- 詳細については、Kubernetesインストールに関する専用ドキュメントを参照してください。
Docker Compose固有
docker-compose.ymlに次のものが必要です
- Redisメッセージブローカー
- SQLliteの代わりにPostgreSQL DB
- 1つ以上のcelery worker
- 単一のcelery beat
このプロセスはDocker Swarm環境でも機能します。Swarmの特定の設定とともに、Superset、Redis、PostgresサービスにDeploy:を追加するだけです。
詳細設定
次の構成を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://: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_labおよび- email_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
apache/superset:3.1.0-devのようなリリースされたSupersetイメージのdevバージョンを実行している場合は、上記の設定で完了です。
ただし、独自のイメージを構築している場合、または非devバージョンから開始している場合は、受信者に送信されるチャートとダッシュボードのスクリーンショットをキャプチャするために、webdriver(およびヘッドレスブラウザ)が必要です。以下に、FirefoxまたはChromeでスクリーンショットを撮るようにDockerfileを変更する方法を示します。
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ワーカーのログを確認します
これが問題に関する最良の情報源です。docker composeデプロイメントでは、docker logs superset_worker --since 1hのようなコマンドでこれを行うことができます。
Webブラウザとwebdriverのインストールを確認します
スクリーンショットを撮るために、ワーカーはヘッドレスブラウザを使用してダッシュボードまたはチャートにアクセスし、スクリーンショットを撮ります。チャートをCSVまたはテキストとして送信できるが、PNGとして送信できない場合は、問題がブラウザにある可能性があります。
-devで終わるタグを持つSuperset Dockerイメージには、Firefoxヘッドレスブラウザとgeckodriverがインストール済みです。Supersetワーカーに入り、firefox --headlessとgeckodriverを実行して、これらがインストールされており、正しいパスにあることを確認できます。どちらのコマンドもアプリケーションを起動するはずです。
ソフトウェアのインストールを自身で処理している場合、または代わりにChromiumを使用したい場合は、ワーカー環境でヘッドレスブラウザが正常に起動することを確認してください。
テストメールを送信する
メールサーバーへの接続が無効である兆候の1つは、レポートの送信時にログに[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認証情報セットを使用してください。
ワーカーからレポートを閲覧する
ワーカーがレポートにアクセスできない場合があります。レポートを閲覧するためにWEBDRIVER_BASEURLの値を使用します。そのルートが無効である場合、またはワーカーが通過できない認証チャレンジが発生する場合、レポートのスクリーンショットは失敗します。
ワーカーのエラーログに表示されるレポートのURLをcurlで試して確認してください。たとえば、ワーカー環境からcurl http://superset_app:8088/superset/dashboard/1/を実行します。ダッシュボードが存在するかどうかによって異なる応答が得られる場合があります。たとえば、URLの1を変更する必要がある場合があります。失敗したレポートのスクリーンショットのエラーログにURLがある場合は、そこから始めるのが良いでしょう。目標は、WEBDRIVER_BASEURLの有効な値を決定し、HTTPSや認証などの問題がワーカーをリダイレクトしているかどうかを判断することです。
HTTPSやシングルサインオンなどの認証対策が有効になっているデプロイでは、ワーカーがサインインする必要を避けて、同じ場所で実行されている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に「スケジュール」というメニュー項目を追加します。メニュー項目をクリックすると、ユーザーがクエリのスケジュールに必要なメタデータを追加できるモーダルが表示されます。
この情報は、エンドポイント/api/v1/saved_query/から取得でき、JSONメタデータにschedule_infoを持つクエリをスケジュールするために使用できます。Airflow以外のスケジューラの場合、追加のフィールドを上記の構成ファイルに簡単に追加できます。