Apache supersetを使ってみた


# はじめに
「いい感じの画面のBIツールがある」と知人から紹介していただいたApache Supersetを試したいと思います。やりたいことは、下記の3つです。
- 楽にグラフを作りたい
- かっこいいグラフとかを表示したい
- 特定のレコード内に値が入っていないものがあったらそれをリスト選択で埋める(←できるか？)

3つ目はできたらいいな、レベルです。



# インストール

自前の環境を使いたいのでそのままのものを使用します。

https://superset.apache.org/docs/installation/installing-superset-from-pypi/

## 環境
検証する環境を記述します。

| key | value |
|:-:|:-|
| OS | macOS Sonoma14.4.1 |
| cpu | M3 |
| python | 3.11.8 |
| PostgreSQL | 14.11 |

## 必要なパッケージのインストール
mac OS内に必要なパッケージをインストールします。
はじめにxcodeをインストールします。
```zsh
xcode-select --install
```
次にHomebrewからパッケージをインストールします。
```zsh
brew install readline pkg-config libffi openssl postgresql@14
```
公式ページにはmysqlの記述があったのですが、私の環境ではmysqlは使用していないので今回はインストールしませんでした。

:::note warn
Homebrewをインストールしていない方は公式ページの記述を参考にインストールください。
https://brew.sh/
:::



その他のOSについては上記に記載した公式ページを参照ください。


## 仮想環境作成
### 環境の作成と有効化
```zsh
cd /any/directory/
python3.11 -m venv superset
source superset/bin/activate
```
### pipとsetuptoolsのアップグレード
最新にします。
```zsh
pip install --upgrade setuptools pip
```
### LDFLAGSとCFLAGSの作成
環境変数にLDFLAGSとCFLAGSを定義します。
(この部分、理解ができていない)
```zsh
export LDFLAGS="-L$(brew --prefix openssl)/lib"
export CFLAGS="-I$(brew --prefix openssl)/include"
```

## Supersetのインストール
supersetはPythonのモジュールのようです。今回はPyPiからインストールします。

```zsh
pip install apache-superset
pip install python-dotenv
pip install psycopg2-binary
```

## 初期設定
supersetを使用するには、設定用のファイルを作成する必要があります。
まずは設定用ファイルを作成します。
なお、ここからの内容は下記のサイトを元に設定しております。

https://superset.apache.org/docs/installation/configuring-superset

### 設定ファイルの作成
プロジェクトのディレクトリに移動し、設定ファイルを作成します。
なお、/any/path/to/appは、ご自身のプロジェクト内のディレクトリに設定してください。
```zsh
cd /any/path/to/app/
touch superset_config.py
touch .env
```


### SECRET_KEY用の文字列作成
環境設定ファイル .envに記載するSECRET_KEY用の文字列を作成します。
ここではopensslを使用した作成します。
```zsh
openssl rand -base64 42
```
ここで出力された文字列は、次のSUPERSET_SECRET_KEYに入れておいてください。

### 環境設定ファイルの編集
Supersetで使用する秘密情報を環境変数に入れておきます。
任意のエディタで.envを編集します。
```bash
SUPERSET_SECRET_KEY='YOUR_OWN_RANDOM_GENERATED_SECRET_KEY'
SUPERSET_DB_NAME='superset'
SUPERSET_DB_HOST='127.0.0.1'
SUPERSET_DB_PORT='5432'
SUPERSET_DB_USER_NAME='DB接続ユーザ名'
SUPERSET_DB_USER_PASS='DB接続ユーザパス'
SUPERSET_DATABASE_URI='postgresql://${SUPERSET_DB_USER_NAME}:${SUPERSET_DB_USER_PASS}@${SUPERSET_DB_HOST}:${SUPERSET_DB_PORT}/${SUPERSET_DB_NAME}'
```

### superset設定ファイルの編集
まず設定ファイルパスを環境変数内に入れておきます。
この環境変数名が存在しない場合、デフォルトの設定ファイルを見に行くようです。

```zsh
export SUPERSET_CONFIG_PATH='/any/path/to/superset_config.py'
```

次に設定ファイルに下記の内容を書き込みます。

```python
import os
from dotenv import load_dotenv

load_dotenv()

# Superset specific config
ROW_LIMIT = 5000

# Flask App Builder configuration
# Your App secret key will be used for securely signing the session cookie
# and encrypting sensitive information on the database
# Make sure you are changing this key for your deployment with a strong key.
# Alternatively you can set it with `SUPERSET_SECRET_KEY` environment variable.
# You MUST set this for production environments or the server will refuse
# to start and you will see an error in the logs accordingly.
SECRET_KEY = os.getenv('SUPERSET_SECRET_KEY')

# The SQLAlchemy connection string to your database backend
# This connection defines the path to the database that stores your
# superset metadata (slices, connections, tables, dashboards, ...).
# Note that the connection information to connect to the datasources
# you want to explore are managed directly in the web UI
# The check_same_thread=false property ensures the sqlite client does not attempt
# to enforce single-threaded access, which may be problematic in some edge cases
SQLALCHEMY_DATABASE_URI = os.getenv('SUPERSET_DATABASE_URI')

# Flask-WTF flag for CSRF
WTF_CSRF_ENABLED = False
# Add endpoints that need to be exempt from CSRF protection
WTF_CSRF_EXEMPT_LIST = []
# A CSRF token that expires in 1 year
WTF_CSRF_TIME_LIMIT = 60 * 60 * 24 * 365

# Set this API key to enable Mapbox visualizations
MAPBOX_API_KEY = ''
```

以上で設定は終了です。
なお、今回は立ち上げることを目的にしたので、CSRFはFalseにしました。
本番環境では設定してください。


<details>
<summary>【余談】 私がハマったところ</summary>

公式サイトを確認して進めていましたが、
**Then, you need to initialize the database**と書いてあるのに、次のコマンドが**superset db upgrade**なので、？マークでしたがきちんとエラーが出ました。
いくつかのサイトを確認したのですが、どうやらinitializeの意味するところが、初期設定用ファイル作成＆編集ということのようです。ここに気付かずに沼りました...

![公式サイトのインストール手順の記述](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671049/8d864e07-947e-088b-4f72-a81613fda2b4.png)

</details>


## Superset初期設定
初期設定を行います。
### ユーザの作成
```zsh
# Create an admin user in your metadata database (use `admin` as username to be able to load the examples)
export FLASK_APP=superset
superset fab create-admin
```
### サンプルデータの読み込み
(必要ないならいらないかも)
```zsh
# Load some data to play with
superset load_examples
```

### 初期化
```zsh
# Create default roles and permissions
superset init
```

## 立ち上げ確認
下記のコマンドを入力してsupersetを立ち上げます。
```zsh
superset run -p 8088 --with-threads --reload --debugger
```

問題がなければ無事に立ち上がります。

![supersetログイン](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671049/c88a6c01-b3f4-f73a-06d6-7a3f61bbc977.png)

![superset初期画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671049/c25a0566-980c-4718-9d68-b8ebe255aec7.png)


# Supersetを触ってみる
設定が終了したので手持ちのテストデータで触ってみます。

## Databaseの追加
右上の【＋】マークをクリックして、【Data】＞【Create dataset】を押下します。
![DBの追加](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671049/fa632964-6ffe-23d1-d4b1-61299292f54b.png)

サイドバーのDATABASEを押下し、DB接続情報を入力し、SchemaとTableを選択します。
【CREATE DATASET AND CREATE CHART】を押下します。

![DBの追加2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671049/71773217-177c-c93a-e449-76f86ffa0840.png)

![DB接続情報の入力](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671049/e1e9258a-a25c-f406-8b63-ce913117be55.png)

![DBの追加3](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671049/2afd0658-e066-80ee-70bc-4e6d7114519a.png)


## チャート作成〜ダッシュボードへの追加
dataset(table or view)を選択し、【CREATE NEW CHART】を押下します。

![チャート作成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671049/9beafdb7-6c1a-e789-7489-4a2fbd54dc41.png)

自分の作りたいチャートを作成します。私はStackしたバーチャートを作成しました。  
作り終わったら右上の【SAVE】を押下して、追加先のダッシュボードを選択し、【SAVE】を押下します。

![チャート作成2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671049/32bf8f16-c317-b921-2da1-fcfca24fec03.png)

![ダッシュボードへの追加](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671049/a6fe695b-7d8a-2da0-b098-04e1a68dbdf5.png)


![ダッシュボード](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671049/edecb39d-a6fd-f6ef-b101-240b04acaf4f.png)



# 感想
インストール処理に結構苦戦しましたが、それさえ済んでしまったら簡単にグラフ作成できました。
ただ、開発環境での立ち上げなので、本番環境はもう少し設定をしないといけないようです。また、レコードの空いている値を入力できるかどうかも気になるところです。この辺りを調査して使いこなしていこうかと思います。



# 参考
## モジュール群

今回インストールしたモジュール群とバージョンを記載しておきます。

<details>

<summary>
モジュール群 (開いてご確認ください)
</summary>

```text
alembic==1.13.1
amqp==5.2.0
apache-superset==4.0.0
apispec==6.6.0
apsw==3.45.2.0
attrs==23.2.0
Babel==2.14.0
backoff==2.2.1
bcrypt==4.1.2
billiard==4.2.0
blinker==1.7.0
Bottleneck==1.3.8
Brotli==1.1.0
cachelib==0.9.0
cachetools==5.3.3
cattrs==23.2.3
celery==5.3.6
certifi==2024.2.2
cffi==1.16.0
charset-normalizer==3.3.2
click==8.1.7
click-didyoumean==0.3.1
click-option-group==0.5.6
click-plugins==1.1.1
click-repl==0.3.0
colorama==0.4.6
cron-descriptor==1.4.3
croniter==2.0.3
cryptography==42.0.5
Deprecated==1.2.14
deprecation==2.1.0
dnspython==2.6.1
email_validator==2.1.1
Flask==2.3.3
Flask-AppBuilder==4.4.1
Flask-Babel==2.0.0
Flask-Caching==2.1.0
Flask-Compress==1.14
Flask-JWT-Extended==4.6.0
Flask-Limiter==3.5.1
Flask-Login==0.6.3
Flask-Migrate==3.1.0
Flask-Session==0.8.0
Flask-SQLAlchemy==2.5.1
flask-talisman==1.1.0
Flask-WTF==1.2.1
func_timeout==4.3.5
geographiclib==2.0
geopy==2.4.1
google-auth==2.29.0
greenlet==3.0.3
gunicorn==21.2.0
h11==0.14.0
hashids==1.3.1
holidays==0.25
humanize==4.9.0
idna==3.7
importlib_metadata==7.1.0
importlib_resources==6.4.0
isodate==0.6.1
itsdangerous==2.1.2
Jinja2==3.1.3
jsonschema==4.21.1
jsonschema-specifications==2023.12.1
kombu==5.3.7
korean-lunar-calendar==0.3.1
limits==3.10.1
llvmlite==0.42.0
Mako==1.3.3
Markdown==3.6
markdown-it-py==3.0.0
MarkupSafe==2.1.5
marshmallow==3.21.1
marshmallow-sqlalchemy==0.28.2
mdurl==0.1.2
msgpack==1.0.8
msgspec==0.18.6
nh3==0.2.17
numba==0.59.1
numexpr==2.10.0
numpy==1.23.5
ordered-set==4.1.0
outcome==1.3.0.post0
packaging==24.0
pandas==2.0.3
paramiko==3.4.0
parsedatetime==2.6
pgsanity==0.2.9
platformdirs==4.2.0
polyline==2.0.2
prison==0.2.1
prompt-toolkit==3.0.43
psycopg2-binary==2.9.9
pyarrow==14.0.2
pyasn1==0.6.0
pyasn1_modules==0.4.0
pycparser==2.22
Pygments==2.17.2
PyJWT==2.8.0
PyNaCl==1.5.0
pyOpenSSL==24.1.0
pyparsing==3.1.2
PySocks==1.7.1
python-dateutil==2.9.0.post0
python-dotenv==1.0.1
python-geohash==0.8.5
pytz==2024.1
PyYAML==6.0.1
redis==4.6.0
referencing==0.34.0
requests==2.31.0
requests-cache==1.2.0
rich==13.7.1
rpds-py==0.18.0
rsa==4.9
selenium==4.9.1
shillelagh==1.2.19
shortid==0.1.2
simplejson==3.19.2
six==1.16.0
slack_sdk==3.27.1
sniffio==1.3.1
sortedcontainers==2.4.0
SQLAlchemy==1.4.52
SQLAlchemy-Utils==0.38.3
sqlglot==23.9.0
sqlparse==0.4.4
sshtunnel==0.4.0
tabulate==0.8.10
trio==0.25.0
trio-websocket==0.11.1
typing_extensions==4.11.0
tzdata==2024.1
url-normalize==1.4.3
urllib3==2.2.1
vine==5.1.0
wcwidth==0.2.13
Werkzeug==3.0.2
wrapt==1.16.0
wsproto==1.2.0
WTForms==3.1.2
WTForms-JSON==0.3.5
XlsxWriter==3.0.9
zipp==3.18.1
```
</details>




# references
## 公式
- https://superset.apache.org/
- https://github.com/apache/superset
## インストール記事
- https://i-fromdata.co.jp/tweet/698
- https://qiita.com/nw-engineer/items/79b4f7a640094e6746c9
- https://www.youtube.com/watch?v=yE5oFC0VAKo