diff --git a/.github/workflows/metabase_export.yml b/.github/workflows/metabase_export.yml index 9c4638d53..9d277ad6b 100644 --- a/.github/workflows/metabase_export.yml +++ b/.github/workflows/metabase_export.yml @@ -27,13 +27,10 @@ jobs: run: | ssh-keyscan -H ssh.osc-fr1.scalingo.com >> ~/.ssh/known_hosts - - name: Init environment variables - run: | - echo "SRC_DATABASE_URL=${{ secrets.METABASE_EXPORT_SRC_DATABASE_URL }}" >> .env.metabase - echo "DEST_METABASE_DATABASE_URL=${{ secrets.METABASE_EXPORT_DEST_METABASE_DATABASE_URL }}" >> .env.metabase - - name: Run export run: make ci_metabase_export env: METABASE_SRC_APP: ${{ vars.METABASE_EXPORT_SRC_APP }} + METABASE_SRC_DATABASE_URL: ${{ secrets.METABASE_EXPORT_SRC_DATABASE_URL }} METABASE_DEST_APP: ${{ vars.METABASE_EXPORT_DEST_APP }} + METABASE_DEST_DATABASE_URL: ${{ secrets.METABASE_EXPORT_DEST_DATABASE_URL }} diff --git a/Makefile b/Makefile index 49d2fdbd6..78393d26d 100644 --- a/Makefile +++ b/Makefile @@ -263,9 +263,8 @@ ci_bdtopo_migrate: ## Run CI steps for BD TOPO Migrate workflow ci_metabase_export: ## Export data to Metabase scalingo login --ssh --ssh-identity ~/.ssh/id_rsa - ./tools/scalingodbtunnel ${METABASE_SRC_APP} --host-url --port 10000 & ./tools/wait-for-it.sh 127.0.0.1:10000 ./tools/scalingodbtunnel ${METABASE_DEST_APP} --host-url --port 10001 & ./tools/wait-for-it.sh 127.0.0.1:10001 - ./tools/metabase-export.sh + ./tools/metabase-export.sh ${METABASE_SRC_DATABASE_URL} ${METABASE_DEST_DATABASE_URL} ## ## ---------------- diff --git a/docs/tools/metabase.md b/docs/tools/metabase.md index e512f9599..a26952972 100644 --- a/docs/tools/metabase.md +++ b/docs/tools/metabase.md @@ -10,18 +10,22 @@ Vous devez disposer d'un compte pour y accéder. Demandez pour cela à un membre Le Metabase de DiaLog est hébergé sur Scalingo sous l'application `dialog-metabase`. (Demandez à un membre de l'équipe de vous ajouter à cette application pour y avoir accès.) -Conformément aux recommendations Beta, une base de données dédiée aux données Metabase a été créée afin de la séparer des données de production. Elle est hébergée sur l'application `dialog-metabase` via un add-on PostgreSQL, comme indiqué dans [cette doc](https://doc.incubateur.net/communaute/les-outils-de-la-communaute/autres-services/metabase/metabase#connecter-metabase-a-une-base-de-donnees-anonymisee). +Cette application dispose de sa propre base de données où nous stockons les données nécessaires au calcul des indicateurs, conformément aux [recommendations Beta](https://doc.incubateur.net/communaute/les-outils-de-la-communaute/autres-services/metabase/metabase#connecter-metabase-a-une-base-de-donnees-anonymisee) -## Lancer l'export +La collecte des données d'indicateur est réalisée au moyen d'un [script](../../tools/metabase-export.sh). Ce script exécute des requêtes SQL depuis la base Metabase vers la base applicative. Pour cela un utilisateur `dialog_metabase` avec droits en lecture seule a été créé sur la base applicative (identifiants dans le Vaultwarden de l'équipe DiaLog). + +## Lancer l'export depuis GitHub Actions L'export Metabase peut être déclenché via [GitHub Actions](./github_actions.md) à l'aide du workflow [`metabase_export.yml`](../../.github/workflows/metabase_export.yml). -La configuration passe par diverses variables d'environnement listées ci-dessous : +### Configuration + +La configuration de la GitHub Action passe par diverses variables d'environnement listées ci-dessous : | Variable d'environnement | Configuration | Description | |---|---|---| | `METABASE_EXPORT_SRC_APP` | [Variable](https://docs.github.com/fr/actions/learn-github-actions/variables) au sens GitHub Actions | `dialog` (pour la production) | -| `METABASE_EXPORT_DEST_APP` | [Variable](https://docs.github.com/fr/actions/learn-github-actions/variables) au sens GitHub Actions | `dialog-metabase` | -| `METABASE_EXPORT_SRC_DATABASE_URL` | [Secret](https://docs.github.com/fr/actions/security-guides/using-secrets-in-github-actions) au sens GitHub Actions | L'URL d'accès à la base de données applicative par la CI (`./tools/scalingodbtunnel dialog --host-url`) | -| `METABASE_EXPORT_DEST_METABASE_DATABASE_URL` | [Secret](https://docs.github.com/fr/actions/security-guides/using-secrets-in-github-actions) au sens GitHub Actions | L'URL d'accès à la base de données Metabase par la CI (`./tools/scalingodbtunnel dialog-metabase --host-url --port 10001`) | +| `METABASE_EXPORT_SRC_DATABASE_URL` | [Secret](https://docs.github.com/fr/actions/security-guides/using-secrets-in-github-actions) au sens GitHub Actions | L'URL d'accès à la base de données applicative par la DB Metabase : utiliser la `METABASE_EXPORT_SRC_DATABASE_URL` de l'app `dialog` | +| `METABASE_EXPORT_DEST_APP` | Variable | `dialog-metabase` | +| `METABASE_EXPORT_DEST_DATABASE_URL` | Secret | L'URL d'accès à la base de données Metabase par la CI (`./tools/scalingodbtunnel dialog-metabase --host-url --port 10001`) | | `GH_SCALINGO_SSH_PRIVATE_KEY` | Secret | Clé SSH privée permettant l'accès à Scalingo par la CI | diff --git a/tools/metabase-export.sh b/tools/metabase-export.sh index 8f23fe48d..4e56c92bd 100755 --- a/tools/metabase-export.sh +++ b/tools/metabase-export.sh @@ -2,21 +2,15 @@ # Inspiré de : https://doc.incubateur.net/communaute/les-outils-de-la-communaute/autres-services/metabase/metabase#connecter-metabase-a-une-base-de-donnees-anonymisee set -euxo pipefail -source .env.metabase ## Créé dans le workflow GitHub Actions +# URL de la DB DiaLog du point de vue de la DB Metabase (sera utilisé avec dblink) +SRC_DATABASE_URL=$1 -# Création des tables (persistera dans la DB source jusqu'à prochaine exécution de ce script) +# URL de la DB Metabase du point de vue de ce script +DEST_DATABASE_URL=$2 -psql $SRC_DATABASE_URL -c "DROP TABLE IF EXISTS analytics_user" -psql $SRC_DATABASE_URL -c " -CREATE TABLE analytics_user AS -SELECT - uuid_generate_v4() AS id, - u.registration_date -FROM \"user\" AS u" -psql $SRC_DATABASE_URL -c "ALTER TABLE analytics_user ADD PRIMARY KEY (id)" +export PGOPTIONS="-c custom.src_database_url=${SRC_DATABASE_URL}" -# Création des index - -# Copie vers la DB Metabase - -pg_dump $SRC_DATABASE_URL -O -x -t analytics_user -c | psql "$DEST_METABASE_DATABASE_URL" +# ON_ERROR_STOP=1 s'assure que cette commande échoue (return code != 0) si le script SQL a des statements qui échouent. +# (Par défaut avec -f on a toujours un return code 0 et un statement en échec n'empêche pas les suivants de s'exécuter.) +# https://engineering.nordeus.com/psql-exit-on-first-error/ +psql $DEST_DATABASE_URL -v ON_ERROR_STOP=1 -f ./tools/metabase-export.sql diff --git a/tools/metabase-export.sql b/tools/metabase-export.sql new file mode 100644 index 000000000..4b2e50c04 --- /dev/null +++ b/tools/metabase-export.sql @@ -0,0 +1,31 @@ +-- metabase-export.sql +-- Ce script est conçu pour être exécuté sur la base de données PostgreSQL de l'instance Metabase (destination). +-- Il consiste à extraire des données de la base applicative (source) pour les charger dans des tables Metabase. + +-- Configuration générale +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; + +-- CONNEXION À LA DB APPLICATIVE (source) +-- Voir : https://www.postgresql.org/docs/current/contrib-dblink-connect.html +CREATE EXTENSION IF NOT EXISTS dblink; +SELECT dblink_connect('src', current_setting('custom.src_database_url')); + +-- COLLECTE DES DONNÉES D'INDICATEURS + +-- # Utilisateurs actifs +-- À chaque exécution, on ajoute la liste des dates de dernière activité pour chaque utilisateur, assortie de la date d'exécution. +-- Dans Metabase cela permet de calculer le nombre d'utilisateurs actif au moment de chaque exécution. +-- (Par exemple avec un filtre : "[last_active_at] >= [uploaded_at] - 7 jours", puis en groupant sur le uploaded_at.) +CREATE TABLE IF NOT EXISTS analytics_user_active (id UUID NOT NULL, uploaded_at TIMESTAMP(0), last_active_at TIMESTAMP(0), PRIMARY KEY(id)); +CREATE INDEX IF NOT EXISTS idx_analytics_user_active_uploaded_at ON analytics_user_active (uploaded_at); + +WITH params AS ( + -- Calculé 1 bonne fois pour toute pour que toutes les lignes utilisent exactement la même valeur à des fins de groupement dans Metabase + SELECT NOW() as current_date +) +INSERT INTO analytics_user_active(id, uploaded_at, last_active_at) +SELECT uuid_generate_v4() AS id, p.current_date AS uploaded_at, u.last_active_at AS last_active_at +FROM + dblink('src', 'SELECT last_active_at FROM "user"') AS u(last_active_at TIMESTAMP(0) WITH TIME ZONE), + params AS p +;