Salta al contenuto principale

06 - Documentazione Automatica in dbt: Descrizioni YAML, Data Lineage e dbt Catalog

dbt 12 min Documentazione Automatica in dbt: Descrizioni YAML, Data Lineage e dbt Catalog dbt genera automaticamente documentazione e lineage graph dal...

Cosa ne pensi di questo articolo?

06 - Documentazione Automatica in dbt: Descrizioni YAML, Data Lineage e dbt Catalog
dbtFoto:Daniil KomovPexels

In Breve

dbt 12 min Documentazione Automatica in dbt: Descrizioni YAML, Data Lineage e dbt Catalog dbt genera automaticamente documentazione e lineage graph dal...

dbt 12 min

Documentazione Automatica in dbt: Descrizioni YAML, Data Lineage e dbt Catalog

dbt genera automaticamente documentazione e lineage graph dal codice: come aggiungere descrizioni YAML a modelli e colonne, il DAG interattivo che mostra le dipendenze, column-level lineage per tracciare ogni campo dalla sorgente al report finale.

dbt docs dbt lineage dbt catalog documentazione dbt column-level lineage

Il Problema della Documentazione nei Data Warehouse

Ogni data team conosce il problema: il warehouse cresce, arrivano nuovi analisti, e nessuno sa più cosa contiene la tabella fct_orders_v2_final o da dove viene la colonna adjusted_revenue. La documentazione esiste in Confluence, ma è disallineata dal codice reale da mesi.

dbt risolve questo problema alla radice: la documentazione è codice, vive nello stesso repository dei modelli, si aggiorna con ogni dbt run e genera automaticamente un catalogo interattivo con lineage graph. Non è una best practice aggiuntiva - è parte integrante del workflow.

Descrizioni YAML: Il Contratto Dati Dichiarativo

Il punto di partenza è il file schema.yml nella directory del modello. Ogni modello e ogni colonna può avere una descrizione in testo libero (o Markdown):

# models/marts/finance/schema.yml
version: 2

models:
  - name: fct_orders
    description: >
      Fatto degli ordini completati, granularità ordine. Ogni riga rappresenta
      un ordine con stato 'completed', arricchito con informazioni cliente, prodotto
      e canale di acquisizione. Aggiornato quotidianamente alle 06:00 UTC.

      **Fonte dati:** `stg_orders` (sorgente transazionale) + `dim_customers` + `dim_products`
      **Owner:** team Finance Analytics
      **SLA:** dati aggiornati entro le 07:00 UTC

    meta:
      owner: "finance-analytics@company.com"
      freshness_expected_hours: 25
      pii_columns: ["customer_email", "billing_address"]

    columns:
      - name: order_id
        description: >
          Identificatore univoco dell'ordine. Corrisponde all'`order_id` nel
          sistema transazionale. Formato: stringa UUID v4.

      - name: customer_id
        description: >
          Chiave esterna verso `dim_customers`. Ogni ordine appartiene
          a esattamente un cliente.

      - name: order_date
        description: >
          Data (senza ora) in cui l'ordine è stato completato.
          Usare questa colonna per aggregazioni temporali, non `created_at`.

      - name: gross_revenue
        description: >
          Ricavo lordo dell'ordine in EUR, prima di sconti e rimborsi.
          Formula: `SUM(line_quantity * unit_price)`.

      - name: net_revenue
        description: >
          Ricavo netto in EUR, dopo sconti applicati.
          Formula: `gross_revenue * (1 - discount_pct)`.

      - name: acquisition_channel
        description: >
          Canale tramite cui il cliente ha effettuato l'acquisto.
          Valori possibili: `organic`, `paid_search`, `email`, `referral`, `social`, `direct`.
          Derivato dalla sessione di acquisto tramite `dim_sessions`.

Descrizioni con doc() per Contenuti Riutilizzabili

Per descrizioni lunghe o condivise tra modelli, dbt supporta i doc block: file Markdown nella directory models/ che possono essere referenziati tramite la funzione doc():

-- models/docs/revenue_metrics.md
{% docs gross_revenue %}
Ricavo lordo dell'ordine in EUR, prima di sconti e rimborsi.

**Formula:** `SUM(line_quantity * unit_price)`

**Note contabili:** questo valore include l'IVA per i clienti IT/EU.
Per il ricavo netto IVA, usare `net_revenue_ex_vat`.

**Frequenza di aggiornamento:** giornaliera (06:00 UTC).
{% enddocs %}

{% docs customer_tier %}
Segmento di appartenenza del cliente al momento dell'ordine (SCD-2 snapshot).

| Valore   | Soglia annuale | Benefici |
|----------|---------------|----------|
| standard | < 1.000 EUR  | nessuno  |
| silver   | 1.000-5.000 EUR | spedizione gratuita |
| gold     | 5.000-20.000 EUR | 5% sconto + spedizione |
| platinum | > 20.000 EUR  | 10% sconto + account manager |
{% enddocs %}
# Uso nel schema.yml
columns:
  - name: gross_revenue
    description: "{{ doc('gross_revenue') }}"  # referenza al doc block
  - name: customer_tier
    description: "{{ doc('customer_tier') }}"

Generare il Catalogo: dbt docs generate e serve

Il catalogo dbt è un'applicazione web statica generata dai metadati del progetto e dal warehouse. Due comandi per usarlo:

-- 1. Genera il catalogo (interroga il warehouse per schema e statistiche)
dbt docs generate

-- 2. Avvia un server locale per navigare il catalogo
dbt docs serve
-- Apre automaticamente http://localhost:8080

-- In CI/CD: genera il catalogo e pubblica gli artifact
dbt docs generate --no-compile  -- più veloce se già compilato

-- Output dei file generati in target/:
-- target/catalog.json    -- metadati di tabelle e colonne
-- target/manifest.json   -- DAG del progetto, modelli, test
-- target/sources.json    -- metadati sorgenti
-- target/index.html      -- l'applicazione web statica

Il catalogo generato contiene:

  • Tutte le descrizioni di modelli e colonne scritte in YAML
  • Schema effettivo delle tabelle (tipi colonne, dimensioni)
  • Test configurati per ogni modello
  • Il lineage graph interattivo (DAG)
  • Statistiche di row count e dimensioni tabelle (dove supportato)

Il DAG Interattivo: Capire le Dipendenze

La feature più potente del catalogo dbt è il lineage graph: una visualizzazione interattiva del DAG completo del progetto. Ogni nodo è un modello, ogni arco è una dipendenza creata da ref() o source().

Dalla UI è possibile:

  • Filtrare per layer (staging, intermediate, marts) usando i selettori dbt standard
  • Espandere/collassare sotto-grafi
  • Cliccare su un nodo per vedere descrizione, colonne, test e SQL compilato
  • Vedere il lineage upstream (da dove arriva questo modello) e downstream (chi dipende da questo)

Selettori per Navigare il Lineage

-- Nella barra di ricerca del catalogo, puoi usare i selettori dbt:

-- Tutti i modelli che dipendono da stg_orders (downstream)
+stg_orders

-- stg_orders e tutti i suoi upstream (sorgenti incluse)
stg_orders+

-- Tutti i modelli in marts/ e il loro upstream immediato
+tag:marts

-- Solo i modelli con un certo owner nei meta
exposure:finance_dashboard

-- CLI equivalente (per capire il subset visivamente):
dbt ls --select +fct_orders+  -- mostra upstream E downstream di fct_orders

Column-Level Lineage: Tracciare un Campo dalla Sorgente al Report

Il column-level lineage (disponibile in dbt Cloud e con alcuni metadati aggiuntivi in dbt Core) traccia ogni colonna attraverso i modelli: da quale colonna sorgente deriva net_revenue nel report finale? dbt Cloud Explorer mostra questo automaticamente analizzando le SELECT.

# Per abilitare il column-level lineage in dbt Core,
# aggiungi le dipendenze colonne nei meta (opzionale ma utile):

models:
  - name: fct_orders
    columns:
      - name: net_revenue
        description: "Ricavo netto dopo sconti"
        meta:
          derived_from:
            - model: stg_orders
              column: total_amount
            - model: stg_orders
              column: discount_pct
          formula: "total_amount * (1 - discount_pct)"

In dbt Cloud Enterprise, il column-level lineage è automatico: il sistema analizza il SQL compilato di ogni modello e costruisce il grafo di dipendenze a livello di colonna. Utile per l'impact analysis: se cambia la definizione di discount_pct nella sorgente, quali report finali sono impattati?

Exposures: Documentare i Consumer del Warehouse

Le exposure documentano chi usa i modelli dbt - dashboard Tableau, report Power BI, notebook Python, API. Appaiono nel lineage graph come nodi finali e permettono di capire l'impatto di un cambiamento:

# models/exposures.yml
version: 2

exposures:
  - name: finance_weekly_report
    label: "Report Finanziario Settimanale"
    type: dashboard              # dashboard | ml | notebook | analysis | application
    maturity: high               # low | medium | high
    url: https://tableau.company.com/views/FinanceWeekly
    description: >
      Dashboard Tableau aggiornata ogni lunedì mattina con KPI finanziari
      della settimana precedente. Usata dal CFO e dal team Finance per il report
      settimanale al board.

    owner:
      name: Finance Analytics Team
      email: finance-analytics@company.com

    depends_on:
      - ref('fct_orders')
      - ref('fct_order_line_items')
      - ref('dim_customers')
      - ref('dim_products')

  - name: ml_churn_model
    label: "Modello ML Churn Prediction"
    type: ml
    maturity: medium
    description: >
      Feature store per il modello di churn prediction. Addestrato settimanalmente,
      serve dati degli ultimi 90 giorni di comportamento cliente.

    owner:
      name: Data Science Team
      email: datascience@company.com

    depends_on:
      - ref('fct_customer_events_90d')
      - ref('dim_customers')

Sources: Documentare le Sorgenti Esterne

Le sorgenti raw del warehouse meritano la stessa cura documentativa dei modelli dbt. Il file sources.yml permette di documentarle e di attivare i freshness check:

# models/staging/sources.yml
version: 2

sources:
  - name: raw
    description: >
      Schema raw: dati grezzi caricati dai sistemi transazionali tramite Fivetran.
      Nessuna trasformazione applicata. Schema di appoggio - non usare direttamente
      nei report, usare i modelli staging/ come interfaccia stabile.
    database: analytics_db
    schema: raw

    loaded_at_field: _fivetran_synced   # colonna di timestamp per il freshness check

    freshness:
      warn_after:  {count: 12, period: hour}
      error_after: {count: 24, period: hour}

    tables:
      - name: orders
        description: "Ordini dal CRM, sincronizzati ogni 15 minuti."
        columns:
          - name: id
            description: "Primary key del sistema sorgente."
          - name: customer_id
            description: "FK verso la tabella customers."
          - name: status
            description: "Status dal CRM: created|paid|shipped|delivered|cancelled."
          - name: _fivetran_synced
            description: "Timestamp dell'ultima sincronizzazione Fivetran."

      - name: customers
        description: "Anagrafica clienti dal CRM."
        freshness:
          warn_after: {count: 24, period: hour}   # override per questa tabella
-- Verificare la freshness delle sorgenti:
dbt source freshness

-- Output esempio:
-- Found 3 sources, 7 tables
-- Checking freshness of 7 sources (7 checks)
-- OK freshness of raw.orders ..................... [ok in 0.34s]
-- WARN freshness of raw.customers ............... [warn in 0.41s]
-- ERROR freshness of raw.events ................. [error in 0.29s]

Meta: Metadati Custom per Governance

Il campo meta in YAML permette di aggiungere metadati strutturati custom che appaiono nel catalogo e possono essere usati da tool di governance esterni:

models:
  - name: fct_orders
    meta:
      owner: "finance-analytics@company.com"
      team: "Finance Analytics"
      tier: "gold"                    # bronze/silver/gold (data quality tier)
      sla_hours: 25                   # ore massime dall'ultimo aggiornamento
      pii: false                      # contiene PII?
      gdpr_relevant: true             # rilevante per GDPR?
      retention_days: 365             # giorni di retention
      business_glossary_link: "https://wiki.company.com/glossary/orders"
      downstream_systems:
        - "Tableau Finance Dashboard"
        - "Looker Revenue Report"
        - "ML Churn Feature Store"

Pubblicare il Catalogo in Produzione

In dbt Core, il catalogo generato è una cartella di file statici che puoi hostare su qualsiasi static file server. Ecco un pattern comune con GitHub Actions + GitHub Pages:

# .github/workflows/dbt-docs.yml
name: Publish dbt Docs

on:
  push:
    branches: [main]

jobs:
  docs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dbt
        run: pip install dbt-snowflake==1.8.0

      - name: dbt deps
        run: dbt deps
        env:
          DBT_PROFILES_DIR: .

      - name: dbt docs generate
        run: dbt docs generate --target prod
        env:
          SNOWFLAKE_ACCOUNT: ${{ secrets.SNOWFLAKE_ACCOUNT }}
          SNOWFLAKE_PASSWORD: ${{ secrets.SNOWFLAKE_PASSWORD }}

      - name: Deploy to GitHub Pages
        uses: peaceiris/actions-gh-pages@v4
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./target
          destination_dir: docs

dbt Cloud: Documentazione Integrata

In dbt Cloud, il catalogo viene generato automaticamente dopo ogni job di produzione e accessibile tramite il menu “Explore”. dbt Cloud Enterprise aggiunge column-level lineage automatico, ricerca full-text nelle descrizioni, e integrazione con tool di catalogo esterni (Alation, Collibra, Atlan).

Best Practices per la Documentazione dbt

Avere la possibilità di documentare non significa che la documentazione sia automaticamente buona. Ecco le pratiche che distinguono un catalogo utile da un catalogo abbandonato:

Scrivi Descrizioni Operative, Non Ovvie

# EVITA: descrizioni ridondanti che ripetono il nome della colonna
columns:
  - name: order_id
    description: "L'ID dell'ordine."  # inutile

# PREFERISCI: descrizioni operative con contesto, formato, vincoli
columns:
  - name: order_id
    description: >
      Identificatore univoco dell'ordine. UUID v4 generato dal sistema CRM.
      Usare questo campo come chiave di join con i sistemi transazionali.
      Non corrisponde all'order_number visibile all'utente (quello è in `order_number`).

  - name: gross_revenue
    description: >
      Ricavo lordo dell'ordine in EUR, centesimi di precisione.
      Include IVA per ordini EU, esclusa per ordini US.
      Per ricavo netto usare `net_revenue`. Per ricavo ex-IVA usare `net_revenue_ex_vat`.
      Non include spese di spedizione (vedi `shipping_amount`).

Documenta le Anomalie Note e le Limitazioni

models:
  - name: fct_orders
    description: >
      **NOTA (2024-03-15):** Gli ordini precedenti al 2022-01-01 hanno `acquisition_channel`
      sempre NULL: il tracking non era presente prima di quella data.
      Non filtrare su NULL in analisi pre-2022 o i risultati saranno distort.

      **LIMITAZIONE NOTA:** I rimborsi parziali non riducono `gross_revenue` in questo modello
      (feature pianificata per Q3 2024). Per analisi rimborsi usare `fct_refunds`.

      **DIPENDENZA CRITICA:** Questo modello dipende da `snap_customers` (snapshot SCD-2).
      Se lo snapshot non è aggiornato, la segmentazione cliente potrebbe essere
      basata su dati del giorno precedente.

Automazione: Generare Bozze di Documentazione

-- dbt Cloud e alcuni tool (dbt-osmosis, dbt-coverage) permettono di
-- generare automaticamente bozze di schema.yml per modelli non documentati

-- Installa dbt-osmosis per propagare automaticamente le descrizioni
-- dalle sorgenti fino ai modelli downstream:
pip install dbt-osmosis

-- Genera schema.yml per tutti i modelli privi di documentazione:
dbt-osmosis yaml generate --select path:models/staging/

-- Propaga le descrizioni dai modelli upstream ai downstream:
dbt-osmosis yaml refactor --select path:models/marts/

-- dbt-coverage: verifica la percentuale di documentazione nel progetto
pip install dbt-coverage
dbt-coverage compute doc --cov-report coverage.json
dbt-coverage check doc --cov-report coverage.json --min-coverage 80

Conclusioni e Prossimi Passi

La documentazione dbt non è documentazione nel senso tradizionale: è un contratto vivente che si evolve col codice, genera automaticamente un catalogo navigabile, e permette a ogni membro del team di capire da dove vengono i dati e come sono stati trasformati.

Investire nella qualità delle descrizioni YAML, nelle exposure e nella documentazione delle sorgenti ripaga in proporzione alla dimensione del team e alla complessità del warehouse.

Il prossimo modulo affronta un confronto pratico molto richiesto: dbt Core vs dbt Cloud. Quando il self-hosting è sufficiente e quando il managed service vale il costo.

Prova Questi Strumenti

Strumenti gratuiti correlati a questo argomento.

Commenti

Caricamento commenti...

Accedi per commentare

Discuti questo articolo nella community

Unisciti al gruppo Telegram per discutere con altri sviluppatori, fare domande e condividere le tue esperienze.

Ti è piaciuto questo articolo?

Esplora altri contenuti sul blog o scopri i miei progetti