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
- Disparo: Cloud Scheduler diario
0 23 * * *UTC (jobextract-metabase-daily) que haceGET /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).
- Extracción: consulta la API de Metabase (
/api/dashboard,/api/card,/api/database,/api/database/:id/metadata, etc.) conMETABASE_API_KEY. Entre llamadas de detalle aplica un throttle (METABASE_DETAIL_DELAY_SECONDS, default 0.35 s). - MERGE a BigQuery: dedup por
iden memoria, lotes de 500 (BIGQUERY_MERGE_BATCH_SIZE), carga a una tabla staging temporal y ejecutaMERGE … ON T.id = S.id(insert/update). Enmetabase_cards, las columnas de enriquecimiento (query_description,tables) se excluyen del UPDATE para no pisar lo generado por OpenAI. - Enriquecimiento OpenAI (opcional):
openai_sql_analysis.pymanda el SQL nativo de cada card a un endpoint OpenAI-compatible (OPENAI_MODEL, defaultgpt-4o-mini) y devuelve{query_description, tables}, quePOST /cards/enrich-query-metadata-openaiescribe de vuelta enmetabase_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 endbt-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— mainmetabase_extractor.py, módulosbigquery_*.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.