Connaissances

Construire des produits de données avec dbt

dbt est l'un des outils de transformation de données les plus répandus. Voici comment nous structurons les projets dbt en produits de données, avec une responsabilité claire, des Output Ports, des Data Contracts et des tests de qualité. Nous montrons aussi comment nous utilisons des agents de codage pour implémenter automatiquement ces produits de données.

Pourquoi dbt pour les produits de données ?

dbt (data build tool) est un framework de transformation SQL-first qui s'exécute au-dessus d'entrepôts de données comme Snowflake, BigQuery, Databricks, AWS Athena ou DuckDB. Il apporte à la data les bonnes pratiques du génie logiciel : gestion de versions, modularité, tests et documentation.

Ces propriétés font de dbt un choix naturel pour implémenter des produits de données. Un projet dbt peut représenter un produit de données : il a des entrées claires, une logique de transformation, des modèles de sortie, des tests et de la documentation, le tout dans un unique dépôt Git dont une seule équipe est responsable.

Commencer par un Data Contract

Prenons un exemple concret : un produit de données que nous utilisons en interne chez Entropy Data pour le customer success, afin de comprendre comment nos clients utilisent l'application et de savoir si nous pouvons les aider de façon proactive à construire de meilleurs produits de données avec des Data Contracts.

Avant d'écrire le moindre model dbt, nous commençons par définir un Data Contract pour le produit de données cible (plus précisément, pour son Output Port). Le Data Contract décrit les données à fournir, leur schéma, les garanties de qualité et les conditions d'utilisation. Voyez-le comme le cahier des charges de notre produit de données.

En concevant le contrat en premier, nous nous accordons sur les informations réellement nécessaires avant d'investir du temps dans l'implémentation. Cela garde le produit de données compact et maniable. Cette approche contract-first évite de construire des jeux de données que personne n'utilise ou qui ne répondent pas à nos attentes.

Le Data Contract est rédigé au format ODCS et stocké à côté du SQL qu'il régit, dans models/output_ports/v1/ :

# models/output_ports/v1/entropydata-customer-activity-v1.odcs.yaml

apiVersion: v3.1.0
kind: DataContract

id: entropydata-customer-activity-v1
name: Customer Activity
version: 1.0.0
status: draft

description:
  usage: analytics
  purpose: Customer activity within Entropy Data for customer success.

schema:
- name: customer_activity
  physicalType: table
  properties:
    - name: organization_id
      description: Unique identifier of the organization.
      logicalType: string
      required: true
      primaryKey: true
      examples:
        - 550e8400-e29b-41d4-a716-446655440000
    - name: organization_vanity_url
      description: Vanity URL of the organization.
      logicalType: string
      examples:
        - acme-corp
    - name: organization_created_by
      description: Email address of the user that created the organization.
      logicalType: string
      examples:
        - admin@acme.com
    - name: organization_created_at
      description: Timestamp when the organization was created.
      logicalType: timestamp
      examples:
        - "2024-03-15T10:00:00Z"
    - name: users_total
      description: Total number of users in the organization.
      logicalType: integer
      required: true
      examples:
        - 12
    - name: users_added_30d
      description: Number of users added in the last 30 days.
      logicalType: integer
      required: true
      examples:
        - 3
    - name: users_last_signed_up_at
      description: Timestamp when the last user signed up.
      logicalType: timestamp
      examples:
        - "2024-09-10T14:22:00Z"
    - name: dataproducts_total
      description: Total number of data products in the organization.
      logicalType: integer
      required: true
      examples:
        - 42
    - name: dataproducts_added_30d
      description: Number of data products added in the last 30 days.
      logicalType: integer
      required: true
      examples:
        - 5
    - name: dataproducts_outputports_total
      description: Total number of output ports across all data products.
      logicalType: integer
      required: true
      examples:
        - 58
    - name: dataproducts_outputports_with_datacontract_percentage
      description: Percentage of output ports that have an active data contract.
      logicalType: number
      required: true
      examples:
        - 72.5
    - name: dataproducts_outputports_with_testresults_percentage
      description: Percentage of output ports that have test results.
      logicalType: number
      required: true
      examples:
        - 65.0
    - name: dataproducts_last_updated_at
      description: Timestamp when the last data product was updated.
      logicalType: timestamp
      examples:
        - "2024-09-14T09:30:00Z"
    - name: assets_total
      description: Total number of assets in the organization.
      logicalType: integer
      required: true
      examples:
        - 87
    - name: data_platform
      description: The data contract / output port type used for most data products.
      logicalType: string
      examples:
        - bigquery
        - snowflake
        - s3
    - name: updated_at
      description: Timestamp when this record was written by the dbt execution.
      logicalType: timestamp
      required: true
      examples:
        - "2024-09-16T06:05:23Z"

team:
  name: customer-success

servers:
  - server: production
    type: databricks
    catalog: entropy_data_prod
    schema: dp_entropydata_customer_activity_v1

roles:
  - role: customer_success
    access: read

Un produit de données conforme à cette spécification aiderait notre équipe customer success à identifier l'activité d'un client et à connaître rapidement la plateforme de données qu'il vise.

Dans Entropy Data, le Data Contract peut être édité et géré via le Data Contract Editor :

Vue formulaire du Data Contract Editor montrant les propriétés du schéma, les informations de base et les conditions d'utilisation du Data Contract customer_activity.

Une fois le contrat en place, l'implémentation dbt devient simple : il suffit de construire les models qui remplissent le contrat.

Conception du produit de données

Notre produit de données Customer Activity est un produit consumer-aligned : il part de données opérationnelles brutes, les transforme et les met à disposition pour un cas d'usage précis, le customer success.

Conception du produit de données : l'application Entropy Data alimente un produit de données source-aligned de Postgres vers Databricks, qui alimente à son tour le produit de données consumer-aligned Customer Activity.

Les données partent de notre application Entropy Data Cloud (la base Postgres opérationnelle), passent par un produit de données brut source-aligned qui extrait les données de Postgres vers Databricks (avec dlt), puis alimentent le produit de données Customer Activity que nous voulons maintenant construire avec dbt.

Un projet dbt par produit de données

Notre approche recommandée : un projet dbt par produit de données. Chaque projet appartient à une seule équipe et vit dans son propre dépôt Git, de sorte que chaque produit de données puisse être implémenté et déployé indépendamment. Une bonne pratique héritée des Self-contained Systems. Cela garantit une responsabilité claire et de l'autonomie, deux principes fondamentaux du Data Mesh.

La structure typique d'un projet dbt de produit de données ressemble à ceci :

dp_entropydata_customer_activity/
├── dbt_project.yml
├── dp_entropydata_customer_activity.odps.yaml      # Data product spec (ODPS)
├── openlineage.yml                                 # OpenLineage transport config
├── profiles.yml.example
├── .github/workflows/data-product.yml              # CI: build, test, publish
├── models/
│   ├── input_ports/                                # External sources this product reads from
│   │   ├── _models.yml
│   │   ├── <provider-output-port-id>.source.yaml   # One file per active access agreement
│   │   └── <provider-output-port-id>.odcs.yaml     # Cached snapshot of upstream contract
│   ├── staging/                                    # Internal: 1:1 cleaned views over input ports
│   │   ├── _models.yml
│   │   ├── stg_organizations.sql
│   │   ├── stg_members.sql
│   │   ├── stg_data_products.sql
│   │   └── stg_assets.sql
│   ├── intermediate/                               # Internal: joined/shaped views with business logic
│   │   ├── _models.yml
│   │   └── int_customer_activity.sql
│   └── output_ports/v1/                            # Public: versioned output port models
│       ├── _models.yml
│       ├── customer_activity.sql
│       └── entropydata-customer-activity-v1.odcs.yaml   # Data contract (ODCS), colocated with the SQL
├── tests/                                          # Custom data tests
│   └── assert_users_total_non_negative.sql
├── analyses/
├── macros/
├── seeds/
└── snapshots/

L'idée clé : les models input_ports/, staging/ et intermediate/ sont internes au produit de données. Seuls les models output_ports/ constituent l'interface publique consommée par les autres équipes. Les Output Ports sont versionnés (v1/, v2/, etc.), et le contrat ODCS se trouve dans le même répertoire que le model SQL qui l'implémente : le contrat vit ainsi à côté du code qu'il régit.

Nous maintenons cette organisation sous forme de skills pour agents de codage dans le plugin dataproduct-builder-dbt, afin que Claude Code, Codex ou Copilot CLI puissent initialiser un nouveau projet, générer les models à partir d'un Data Contract et synchroniser le tout avec Entropy Data.

Les Output Ports en tant que models dbt

Les models d'Output Port sont généralement implémentés sous forme de vues SQL ou de tables matérialisées qui servent d'API stable au produit de données. Ils masquent la logique interne de staging et de transformation et permettent de changer l'implémentation sans impacter les consommateurs.

Plutôt que d'écrire les définitions de model dbt à la main, la Data Contract CLI peut les générer directement à partir du Data Contract :

datacontract export dbt-models --output models/output_ports/v1/_models.yml models/output_ports/v1/entropydata-customer-activity-v1.odcs.yaml

Cela génère le YAML du model dbt avec les colonnes, les descriptions et les types de données :

# models/output_ports/v1/_models.yml (generated)

version: 2

models:
  - name: customer_activity
    description: Customer activity within Entropy Data for customer success.
    config:
      meta:
        data_contract:
          id: entropydata-customer-activity-v1
          file: models/output_ports/v1/entropydata-customer-activity-v1.odcs.yaml
        owner: customer-success
      materialized: table
      contract:
        enforced: true
    columns:
      - name: organization_id
        description: Unique identifier of the organization.
        data_type: STRING
        constraints:
          - type: not_null
          - type: unique
      - name: organization_vanity_url
        description: Vanity URL of the organization.
        data_type: STRING
      - name: organization_created_by
        description: Email address of the user that created the organization.
        data_type: STRING
      - name: organization_created_at
        description: Timestamp when the organization was created.
        data_type: TIMESTAMP
      - name: users_total
        description: Total number of users in the organization.
        data_type: BIGINT
        constraints:
          - type: not_null
      - name: users_added_30d
        description: Number of users added in the last 30 days.
        data_type: BIGINT
        constraints:
          - type: not_null
      - name: users_last_signed_up_at
        description: Timestamp when the last user signed up.
        data_type: TIMESTAMP
      - name: dataproducts_total
        description: Total number of data products in the organization.
        data_type: BIGINT
        constraints:
          - type: not_null
      - name: dataproducts_added_30d
        description: Number of data products added in the last 30 days.
        data_type: BIGINT
        constraints:
          - type: not_null
      - name: dataproducts_outputports_total
        description: Total number of output ports across all data products.
        data_type: BIGINT
        constraints:
          - type: not_null
      - name: dataproducts_outputports_with_datacontract_percentage
        description: Percentage of output ports that have an active data contract.
        data_type: DOUBLE
        constraints:
          - type: not_null
      - name: dataproducts_outputports_with_testresults_percentage
        description: Percentage of output ports that have test results.
        data_type: DOUBLE
        constraints:
          - type: not_null
      - name: dataproducts_last_updated_at
        description: Timestamp when the last data product was updated.
        data_type: TIMESTAMP
      - name: assets_total
        description: Total number of assets in the organization.
        data_type: BIGINT
        constraints:
          - type: not_null
      - name: data_platform
        description: The data contract / output port type used for most data products.
        data_type: STRING
      - name: updated_at
        description: Timestamp when this record was written by the dbt execution.
        data_type: TIMESTAMP
        constraints:
          - type: not_null
La génération du fichier de model dbt est en général une opération ponctuelle. Vous pouvez ensuite enregistrer le model dans Git et y ajouter les détails nécessaires.

Il reste à implémenter la logique de transformation SQL de chaque model de sortie :

-- models/output_ports/v1/customer_activity.sql
-- Governed by entropydata-customer-activity-v1.odcs.yaml (ODCS id: entropydata-customer-activity-v1)

{{ config(
    materialized='table',
    schema='op_v1'
) }}

select
    organization_id,
    organization_vanity_url,
    organization_created_by,
    organization_created_at,
    users_total,
    users_added_30d,
    users_last_signed_up_at,
    dataproducts_total,
    dataproducts_added_30d,
    dataproducts_outputports_total,
    dataproducts_outputports_with_datacontract_percentage,
    dataproducts_outputports_with_testresults_percentage,
    dataproducts_last_updated_at,
    assets_total,
    data_platform
from {{ ref('int_customer_activity') }}

Input Ports

Un produit de données consomme généralement des données issues de systèmes opérationnels ou d'autres produits de données. Dans le nôtre, nous utilisons des données extraites via dlt depuis notre base Postgres opérationnelle vers un produit de données brut, source-aligned, sur la plateforme de données (Databricks).

Dans dbt, les entrées sont modélisées sous forme de sources. Chaque Data Contract actif que nous consommons devient un fichier dans models/input_ports/, nommé d'après l'identifiant de l'Output Port du fournisseur. À côté, nous mettons en cache le contrat ODCS du fournisseur amont comme instantané de confiance : git log montre ainsi quand un schéma ou une règle de qualité en amont a changé sans prévenir :

# models/input_ports/op_entropydata_postgres.source.yaml

version: 2

sources:
  - name: dp_entropydata_postgres_op_entropydata_postgres
    description: Operational database of the Entropy Data platform, extracted to Databricks via dlt.
    database: entropy_data_prod
    schema: entropydata_postgres
    config:
      meta:
        data_contract:
          id: entropydata-postgres-v1
          file: models/input_ports/op_entropydata_postgres.odcs.yaml
    tables:
      - name: organization
      - name: organization_member
      - name: data_product
      - name: asset

Le champ sources[].name combine <provider-data-product-id>_<provider-output-port-id>, si bien que deux accords avec le même fournisseur mais des Output Ports différents n'entrent jamais en collision. Le fichier op_entropydata_postgres.odcs.yaml mis en cache se trouve à côté du fichier source ; il est actualisé en relançant entropy-data datacontracts get et jamais édité à la main.

Transformation

Entre l'entrée et la sortie, les models internes réalisent le travail de transformation et portent la logique métier. Ils ne sont pas exposés aux consommateurs.

Les models de staging nettoient et normalisent les données sources brutes : déduplication vers la dernière version, conversion de types et renommage des colonnes.

-- models/staging/stg_organizations.sql

with source as (
    select *,
        row_number() over (partition by organization_id order by version desc) as _row_num
    from {{ source('dp_entropydata_postgres_op_entropydata_postgres', 'organization') }}
)

select
    organization_id,
    vanity_url as organization_vanity_url,
    created_by as organization_created_by,
    cast(created_at as timestamp) as organization_created_at
from source
where _row_num = 1
-- models/staging/stg_members.sql

with source as (
    select *,
        row_number() over (partition by organization_member_id order by version desc) as _row_num
    from {{ source('dp_entropydata_postgres_op_entropydata_postgres', 'organization_member') }}
)

select
    organization_member_id,
    organization_id,
    user_id,
    role,
    cast(created_at as timestamp) as created_at
from source
where _row_num = 1
-- models/staging/stg_data_products.sql

with source as (
    select *,
        row_number() over (partition by data_product_id order by version desc) as _row_num
    from {{ source('dp_entropydata_postgres_op_entropydata_postgres', 'data_product') }}
)

select
    data_product_id,
    organization_id,
    name,
    status,
    specification_type,
    cast(created_at as timestamp) as created_at,
    cast(updated_at as timestamp) as updated_at
from source
where _row_num = 1

Les models intermediate appliquent la logique métier : jointures de tables, enrichissement avec des données de référence, calcul de champs dérivés.

-- models/intermediate/int_customer_activity.sql

with members_per_org as (
    select
        organization_id,
        count(*) as users_total,
        count(case when created_at >= date_sub(current_date(), 30) then 1 end) as users_added_30d,
        max(created_at) as users_last_signed_up_at
    from {{ ref('stg_members') }}
    group by organization_id
),

data_products_per_org as (
    select
        organization_id,
        count(*) as dataproducts_total,
        count(case when created_at >= date_sub(current_date(), 30) then 1 end) as dataproducts_added_30d,
        -- TODO: add output_port source table to compute these metrics
        cast(0 as bigint) as dataproducts_outputports_total,
        cast(0 as double) as dataproducts_outputports_with_datacontract_percentage,
        cast(0 as double) as dataproducts_outputports_with_testresults_percentage,
        max(updated_at) as dataproducts_last_updated_at,
        first(specification_type) as data_platform
    from {{ ref('stg_data_products') }}
    group by organization_id
),

assets_per_org as (
    select
        organization_id,
        count(*) as assets_total
    from {{ ref('stg_assets') }}
    group by organization_id
)

select
    o.organization_id,
    o.organization_vanity_url,
    o.organization_created_by,
    o.organization_created_at,
    coalesce(m.users_total, 0) as users_total,
    coalesce(m.users_added_30d, 0) as users_added_30d,
    m.users_last_signed_up_at,
    coalesce(dp.dataproducts_total, 0) as dataproducts_total,
    coalesce(dp.dataproducts_added_30d, 0) as dataproducts_added_30d,
    coalesce(dp.dataproducts_outputports_total, 0) as dataproducts_outputports_total,
    coalesce(dp.dataproducts_outputports_with_datacontract_percentage, 0) as dataproducts_outputports_with_datacontract_percentage,
    coalesce(dp.dataproducts_outputports_with_testresults_percentage, 0) as dataproducts_outputports_with_testresults_percentage,
    dp.dataproducts_last_updated_at,
    coalesce(a.assets_total, 0) as assets_total,
    dp.data_platform
from {{ ref('stg_organizations') }} o
left join members_per_org m on o.organization_id = m.organization_id
left join data_products_per_org dp on o.organization_id = dp.organization_id
left join assets_per_org a on o.organization_id = a.organization_id

Construire le produit de données

Lorsque nous exécutons dbt run, dbt matérialise tous les models et crée la table de sortie sur Databricks. Le résultat est une table customer_activity dans le schéma dp_entropydata_customer_activity_op_v1, prête à être consommée par l'équipe customer success.

La table customer_activity matérialisée dans Databricks, avec des colonnes comme organization_id, organization_vanity_url et users_total.

Tests

Ce sont les tests qui transforment un projet dbt en produit de données digne de confiance. Sans tests, les consommateurs n'ont aucune raison de faire confiance aux données : ils construiront leurs propres contrôles, dupliqueront la logique ou éviteront tout simplement d'utiliser le produit de données. Les tests automatisés rendent la qualité visible et donnent aux consommateurs l'assurance que les données sur lesquelles ils s'appuient sont correctes et complètes.

Tester un produit de données se fait à deux niveaux : des tests unitaires qui vérifient l'implémentation interne, et des tests de contrat qui vérifient la sortie du point de vue du consommateur.

Tests unitaires

Les tests dbt vérifient les différentes étapes du pipeline de données. Ils sont étroitement couplés à l'implémentation et évoluent avec les models dbt.

Les tests de schéma sont déclarés dans les fichiers YAML et valident not_null, unique, accepted_values et relationships sur chaque model. Les tests de données personnalisés sont des requêtes SQL placées dans le dossier tests/ qui vérifient des règles métier :

-- tests/assert_users_total_non_negative.sql

select organization_id
from {{ ref('customer_activity') }}
where users_total < 0

Si la requête renvoie des lignes, le test échoue. Les dbt contracts (depuis dbt 1.5) imposent en plus les noms de colonnes et les types de données au moment du build. Le model dbt généré contient déjà contract.enforced: true.

Tests de contrat

La Data Contract CLI teste l'Output Port du point de vue du consommateur, face au Data Contract. Il s'agit d'un test d'acceptation : il se connecte à la plateforme de données réelle, interroge les tables de sortie et vérifie le schéma, le nombre de lignes et les règles de qualité définies dans le contrat.

datacontract test models/output_ports/v1/entropydata-customer-activity-v1.odcs.yaml
Résultats de tests de la Data Contract CLI montrant les contrôles de schéma et de qualité d'un produit de données client

Les tests de contrat sont plus stables que les tests dbt. Ils ne changent pas lorsque vous refactorez les models internes de staging ou intermediate. Tant que l'Output Port remplit le contrat, les tests passent. Cela les rend idéaux pour les pipelines CI/CD et pour installer la confiance des consommateurs.

Data lineage avec OpenLineage

Le wrapper dbt d'OpenLineage (dbt-ol) émet des événements de lineage à la fin de chaque exécution dbt. Entropy Data ingère ces événements et affiche un graphe de data lineage interactif sur la page du produit de données, montrant comment les tables d'entrée brutes traversent les models de staging, intermediate et de sortie.

Configurez le transport dans un fichier openlineage.yml à la racine du projet, en encodant les identifiants du produit de données et de l'Output Port comme paramètres de requête sur l'endpoint :

# openlineage.yml

transport:
  type: http
  url: https://api.entropy-data.com
  endpoint: api/v1/lineage?dataProductId=dp_entropydata_customer_activity&outputPortId=customer_activity
  auth:
    type: api_key

La clé apiKey est volontairement absente du fichier (elle ne peut pas être renseignée par templating depuis des variables d'environnement) ; elle est injectée à l'exécution via OPENLINEAGE__TRANSPORT__AUTH__APIKEY, pour que le secret n'atterrisse jamais dans le dépôt.

Pipeline CI/CD

Chaque produit de données dispose de son propre pipeline CI/CD, exécuté à chaque push et périodiquement :

  1. dbt-ol run matérialise tous les models et envoie les événements OpenLineage à Entropy Data
  2. dbt test exécute tous les tests de schéma et les tests de données personnalisés
  3. publication du produit de données et du Data Contract dans Entropy Data
  4. datacontract test exécute les tests de contrat sur l'Output Port

Nous utilisons pour cela un workflow GitHub Actions :

# .github/workflows/data-product.yml

name: Customer Activity Data Product
on:
  push:
    branches: [main]
  schedule:
    - cron: "0 6 * * *"

env:
  API: https://api.entropy-data.com/api
  DBT_DATABRICKS_HOST: ${{ secrets.DBT_DATABRICKS_HOST }}
  DBT_DATABRICKS_HTTP_PATH: ${{ secrets.DBT_DATABRICKS_HTTP_PATH }}
  DBT_DATABRICKS_TOKEN: ${{ secrets.DBT_DATABRICKS_TOKEN }}
  DATACONTRACT_DATABRICKS_TOKEN: ${{ secrets.DBT_DATABRICKS_TOKEN }}
  DATACONTRACT_DATABRICKS_SERVER_HOSTNAME: ${{ secrets.DBT_DATABRICKS_HOST }}
  DATACONTRACT_DATABRICKS_HTTP_PATH: ${{ secrets.DBT_DATABRICKS_HTTP_PATH }}

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

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - name: Install dependencies
        run: pip install dbt-databricks openlineage-dbt datacontract-cli[databricks] entropy-data

      - name: Create profiles.yml
        run: |
          mkdir -p ~/.dbt
          cat > ~/.dbt/profiles.yml <<EOF
          dp_entropydata_customer_activity:
            target: prod
            outputs:
              prod:
                type: databricks
                catalog: entropy_data_prod
                schema: dp_entropydata_customer_activity
                host: ${DBT_DATABRICKS_HOST}
                http_path: ${DBT_DATABRICKS_HTTP_PATH}
                token: ${DBT_DATABRICKS_TOKEN}
                threads: 4
          EOF

      - name: dbt deps
        run: dbt deps

      - name: dbt run
        run: dbt-ol run --target prod
        env:
          OPENLINEAGE__TRANSPORT__AUTH__APIKEY: ${{ secrets.ENTROPY_DATA_API_KEY }}

      - name: dbt test
        run: dbt test --target prod

      - name: Publish data product
        run: entropy-data dataproducts put dp_entropydata_customer_activity --file dp_entropydata_customer_activity.odps.yaml
        env:
          ENTROPY_DATA_API_KEY: ${{ secrets.ENTROPY_DATA_API_KEY }}

      - name: Publish data contract
        run: entropy-data datacontracts put entropydata-customer-activity-v1 --file models/output_ports/v1/entropydata-customer-activity-v1.odcs.yaml
        env:
          ENTROPY_DATA_API_KEY: ${{ secrets.ENTROPY_DATA_API_KEY }}

      - name: Data contract test
        run: |
          datacontract test models/output_ports/v1/entropydata-customer-activity-v1.odcs.yaml \
            --server production \
            --publish $API/test-results
        env:
          ENTROPY_DATA_API_KEY: ${{ secrets.ENTROPY_DATA_API_KEY }}

dbt-ol run matérialise les models et envoie les événements OpenLineage à Entropy Data, dbt test exécute les tests unitaires. Les métadonnées du produit de données et du Data Contract sont ensuite publiées avec la CLI entropy-data, qui encapsule l'API REST de la plateforme et lit la clé d'API depuis la variable d'environnement ENTROPY_DATA_API_KEY. Enfin, datacontract test valide l'Output Port du point de vue du consommateur.

Entropy Data

Entropy Data est une marketplace de produits de données qui gère les produits de données, les Data Contracts et les demandes d'accès. Elle s'intègre parfaitement pour offrir une expérience complète autour des produits de données :

  • Découverte : les consommateurs parcourent et trouvent les produits de données dans une marketplace en self-service
  • Gestion des accès : les consommateurs demandent un accès, et les approbations peuvent déclencher le provisionnement RBAC sur la plateforme de données
  • Gouvernance : suivre la responsabilité, la qualité et le data lineage sur l'ensemble des produits de données

Voici à quoi ressemble notre produit de données Customer Activity dans la marketplace Entropy Data :

Le produit de données Customer Activity dans la marketplace Entropy Data, avec le flux de données, les Output Ports, les informations de base et la piste d'audit.

Implémenter avec des agents de codage grâce au Data Product Builder

Toute la structure décrite dans cet article (organisation du projet dbt, contrats d'Input Port et d'Output Port, workflow CI, publication du data lineage et des tests) peut être générée automatiquement avec le Data Product Builder.

Commencez par un Data Contract. Confiez-le à Claude Code, OpenAI Codex ou GitHub Copilot CLI. L'agent initialise exactement ce projet dbt, écrit les models, met en place les tests, configure le workflow de déploiement et branche l'intégration avec Entropy Data. La structure reste personnalisable : si vous préférez Airflow à GitHub Actions, ou d'autres conventions de nommage, forkez le template et l'agent utilisera votre fork.

Cette page explique ce que produit ce scaffolding, comment chaque pièce s'emboîte et comment l'étendre aux conventions de votre organisation.

Valeur métier

Avec ce produit de données en place, notre équipe customer success (en réalité, nos co-fondateurs...) peut désormais interroger directement la table customer_activity sur Databricks pour comprendre l'engagement de chaque client : combien d'utilisateurs il compte, s'il ajoute activement des produits de données et quelle plateforme de données il utilise. Cela permet de contacter de façon proactive les clients en phase de montée en charge, de détecter tôt les comptes inactifs et de prioriser le support à partir des données. Cela peut alimenter les activités CRM et des agents IA qui identifient de façon proactive où nous pouvons aider les clients à construire de meilleurs produits de données ou à mettre en place des intégrations.

Le Data Contract garantit le schéma et la qualité : nos équipes peuvent donc construire par-dessus des tableaux de bord, des agents et des automatisations en toute confiance.

Inscrivez-vous gratuitement, ou explorez la démo cliquable d'Entropy Data.