🎯 Objectif
Suivre qui a exécuté quoi, quand, avec quels résultats et combien de temps cela a pris.
Cela permet de :
- faire de l’audit trail (traçabilité réglementaire)
- surveiller la performance des modèles
- suivre les modifications exécutées par utilisateur ou pipeline
✅ Solution proposée : pre-hook
+ post-hook
+ LogHandler personnalisé
🧱 Étape 1 – Définir un LogHandler custom (dans un fichier .py
si tu développes un plugin)
👉 dbt permet aux adapters personnalisés ou aux environnements dbt-core avancés de rediriger les logs avec leur propre LogHandler
.
⚠️ Ceci n’est pas possible directement dans un projet dbt classique en YAML pur, mais c’est très courant dans les entreprises qui utilisent dbt comme brique intégrée dans un framework Python.
Exemple d’un LogHandler (dans un projet plugin) :
import logging
import datetime
class CustomAuditLogHandler(logging.Handler):
def emit(self, record):
log_entry = self.format(record)
with open("/logs/dbt_audit.log", "a") as f:
f.write(f"{datetime.datetime.now()} - {log_entry}\n")
🧱 Étape 2 – Utiliser des pre-hook
et post-hook
dans le dbt_project.yml
ou le modèle
models:
my_project:
mart:
+pre-hook:
- "{{ log_start('mart_clients') }}"
+post-hook:
- "{{ log_end('mart_clients') }}"
Et tu crées une macro dans macros/logging.sql
:
{% macro log_start(model_name) %}
insert into audit_logs(model, event, timestamp, user)
values ('{{ model_name }}', 'start', current_timestamp, '{{ target.user }}')
{% endmacro %}
{% macro log_end(model_name) %}
insert into audit_logs(model, event, timestamp, user)
values ('{{ model_name }}', 'end', current_timestamp, '{{ target.user }}')
{% endmacro %}
💡 Que permet cette méthode ?
pre-hook
→ enregistre le début de l’exécutionpost-hook
→ enregistre la fin- tu peux enrichir avec :
execution_time
target.environment
status
(viarun_results.json
)row_count
, etc.
🔐 Bonus : on peut auditer par utilisateur ou par contexte
insert into audit_logs(model, event, timestamp, user, environment)
values (
'{{ this.name }}',
'start',
current_timestamp,
'{{ target.user }}',
'{{ target.name }}'
)
✅ Résumé
Élément | Rôle |
---|---|
pre-hook | Journalise le début d’un modèle |
post-hook | Journalise la fin |
LogHandler personnalisé | Permet de formater ou rediriger les logs (fichier, S3, table, Kafka…) |
Audit table (optionnel) | Pour stocker les logs dans une table relationnelle |
Utilisable avec | dbt-core + macros, ou plugin Python personnalisé |
“using a custom LogHandler with pre_hook and post_hook implementation”
est ambiguë et même trompeuse si on la comprend littéralement dans le contexte d’un projet dbt standard.
✅ Voici la vérité technique claire :
✅ pre-hook
/ post-hook
:
- sont exécutés dans le SQL (via macros)
- te permettent de logguer dans une table (audit trail dans BigQuery, Snowflake…)
- sont 100% utilisables dans dbt-core / dbt Cloud
✅ Custom LogHandler
(en Python) :
- s’utilise uniquement si tu développes un outil Python autour ou au-dessus de dbt
- te permet de rediriger les logs Python de dbt vers un fichier, un endpoint, ou autre
- ne peut pas être combiné directement avec des
pre-hook
SQL, car ils n’exécutent pas de code Python
❌ Ce qui est faux (ou mal formulé) dans la phrase
La phrase dit :
“using a custom LogHandler with pre_hook and post_hook implementation”
Or :
pre-hook
etpost-hook
sont du SQL exécuté dans le warehouseLogHandler
est un objet Python attaché au logger dbt (dans le code source Python, pas dans le projet YAML)
👉 Il n’y a pas d’interaction directe entre les deux dans un projet dbt normal.
✅ Donc, deux scénarios bien distincts
1. Projet dbt classique (core ou cloud)
➡️ Tu utilises pre-hook
/ post-hook
+ macros pour insérer des logs dans une table d’audit SQL
+post-hook: ["{{ log_audit_end('fact_ventes') }}"]
-- dans macros/log_audit.sql
{% macro log_audit_end(model_name) %}
insert into logs_audit (model, event, user, timestamp)
values ('{{ model_name }}', 'end', '{{ target.user }}', current_timestamp)
{% endmacro %}
2. Outil Python qui pilote dbt (ex: Airflow, CLI wrapper, SDK)
➡️ Tu branches un LogHandler Python personnalisé pour logger en dehors de dbt
from dbt.logger import GLOBAL_LOGGER as logger
logger.addHandler(CustomAuditLogHandler())
Tu peux ensuite observer tous les logs de dbt comme :
2024-06-17 12:30:12 | Running model mart.ventes ...
✅ Conclusion
La phrase peut prêter à confusion.
Il serait plus juste de la reformuler ainsi :
🟩 Version corrigée :
For comprehensive audit tracking in dbt, combining SQL-based pre_hook and post_hook macros with a custom Python LogHandler (in adapter or orchestration layers) provides the most flexible and complete approach.
While hooks allow tracking inside the data warehouse, a LogHandler offers control over external logging and orchestration context.