Skip to content

Metabase · Extractor de metadatos

Servicio Flask en Cloud Run que consulta la API de Metabase y sincroniza sus metadatos (dashboards, dashcards, cards, databases, tables) a BigQuery (metabase_metadata) vía MERGE. Sirve para analizar uso e inventario de dashboards. Volumen bajo.

¿Llegaste hasta acá desde…?

Si ves… Eso sale de… La lógica está en…
Inventario / uso de dashboards de Metabase solvento-data-prod.metabase_metadata.dashboards y .dashboard_dashcards metabase-extractor → bigquery_dashboards.py / bigquery_dashcards.py
Catálogo de preguntas (cards) y su SQL solvento-data-prod.metabase_metadata.metabase_cards metabase-extractor → bigquery_cards.py (+ openai_sql_analysis.py para query_description/tables)
Bases de datos y tablas registradas en Metabase metabase_databases · metabase_tables bigquery_databases.py / bigquery_tables.py

Resumen

Campo Valor
Origen API de Metabase (METABASE_BASE_URL, default https://solvento.metabaseapp.com)
Patrón Pull por HTTP (Flask en Cloud Run) → MERGE directo en BigQuery
Destino solvento-data-prod.metabase_metadata.*
Frecuencia Diaria 0 23 * * * UTC (job extract-metabase-daily, GET /sync-all-bigquery)
Criticidad 🟢 Baja
Dueño Diego (analytics) · infra/deploy Martin
Repos metabase-extractor

Diagrama de linaje

graph LR
    MB[["📊 Metabase API<br/>/api/dashboard · /api/card<br/>/api/database · …"]]
    SCH[["⏰ Trigger (confirmar)<br/>POST /…/sync-bigquery"]]

    subgraph svc["Cloud Run · metabase-extractor (Flask)"]
        S["/sync-all-bigquery<br/>(dashboards → cards → databases → tables)"]
        AI["openai_sql_analysis.py<br/><i>enriquece SQL de cards</i>"]
    end

    BQ[("solvento-data-prod.metabase_metadata.*<br/>dashboards · dashboard_dashcards<br/>metabase_cards · metabase_databases · metabase_tables")]

    SCH --> S
    MB -->|"GET metadatos"| S
    S -->|"MERGE ON id (lote 500)"| BQ
    AI -.->|"UPDATE query_description/tables"| BQ

    classDef src fill:#fde68a,stroke:#b45309,color:#000;
    classDef store fill:#bfdbfe,stroke:#1e40af,color:#000;
    classDef logic fill:#dcfce7,stroke:#15803d,color:#000;
    class MB,SCH src;
    class BQ store;
    class AI logic;

Paso a paso

  1. Disparo: Cloud Scheduler diario 0 23 * * * UTC (job extract-metabase-daily) que hace GET /sync-all-bigquery. También se puede llamar manual a los endpoints de sync. Endpoints:
    • GET / (índice), GET /health, GET /dashboards (lista, sin escribir).
    • POST /dashboards/sync-bigquery (MERGE dashboards; por defecto también baja el detalle por dashboard y MERGE de dashcards).
    • POST /cards/sync-bigquery, POST /databases/sync-bigquery, POST /tables/sync-bigquery.
    • POST /sync-all-bigquery (corre los cuatro en orden: dashboards+dashcards → cards → databases → tables).
    • GET /cards/bigquery-native-sql-log (lee cards con SQL nativo) · POST /cards/enrich-query-metadata-openai (enriquece con OpenAI).
  2. Extracción: consulta la API de Metabase (/api/dashboard, /api/card, /api/database, /api/database/:id/metadata, etc.) con METABASE_API_KEY. Entre llamadas de detalle aplica un throttle (METABASE_DETAIL_DELAY_SECONDS, default 0.35 s).
  3. MERGE a BigQuery: dedup por id en memoria, lotes de 500 (BIGQUERY_MERGE_BATCH_SIZE), carga a una tabla staging temporal y ejecuta MERGE … ON T.id = S.id (insert/update). En metabase_cards, las columnas de enriquecimiento (query_description, tables) se excluyen del UPDATE para no pisar lo generado por OpenAI.
  4. Enriquecimiento OpenAI (opcional): openai_sql_analysis.py manda el SQL nativo de cada card a un endpoint OpenAI-compatible (OPENAI_MODEL, default gpt-4o-mini) y devuelve {query_description, tables}, que POST /cards/enrich-query-metadata-openai escribe de vuelta en metabase_cards.

Nota: toda la lógica vive en el servicio (no en dbt). Criticidad baja, no se rastrean modelos.

Tablas que alimenta

Tabla Contenido Job que la carga
solvento-data-prod.metabase_metadata.dashboards Dashboards de Metabase POST /dashboards/sync-bigquery
solvento-data-prod.metabase_metadata.dashboard_dashcards Tarjetas dentro de cada dashboard POST /dashboards/sync-bigquery (sync_dashcards)
solvento-data-prod.metabase_metadata.metabase_cards Cards/preguntas (incl. SQL nativo + enriquecimiento OpenAI) POST /cards/sync-bigquery (+ enrich)
solvento-data-prod.metabase_metadata.metabase_databases Bases de datos registradas en Metabase POST /databases/sync-bigquery
solvento-data-prod.metabase_metadata.metabase_tables Tablas por base de datos POST /tables/sync-bigquery

Los nombres de tabla son configurables por env (BIGQUERY_*_TABLE); los valores arriba son los defaults del código.

Consumo aguas abajo

  • Análisis de uso e inventario de dashboards/cards de Metabase sobre solvento-data-prod.metabase_metadata.*. Criticidad baja; cualquier modelo dbt (si existe) vive en dbt-analytics.

Si falla 🛠️

Impacto: bajo. El inventario de metadatos de Metabase queda desactualizado.

Síntoma Dónde mirar Acción
No se actualizan dashboards/cards Logs Cloud Run metabase-extractor; ¿se llamó al endpoint de sync? Confirmar el trigger (Cloud Scheduler) y disparar manualmente
Error de auth contra Metabase METABASE_API_KEY / METABASE_BASE_URL Verificar API key y URL
Falla el enriquecimiento OpenAI OPENAI_API_KEY / OPENAI_MODEL El sync de metadatos no depende de esto; revisar la key
Error en el MERGE Logs del job BQ; dataset metabase_metadata Confirmar proyecto/dataset y permisos

Escalación: SQL / Metabase → Diego · Airbyte → Gero · resto → Martin.

Enlaces

  • 📊 Estado en vivo: dashboard "Data Processes" (Cloud Monitoring)
  • 📦 Servicio: metabase-extractor — main metabase_extractor.py, módulos bigquery_*.py, openai_sql_analysis.py

Última actualización: 2026-06-21 · Si cambia el flujo, los endpoints o el dataset destino, actualizar esta ficha en el mismo MR.