Les cinq types de métriques couvrent la plupart des cas d’usage, mais les métriques du monde réel nécessitent des patterns qui vont au-delà de la sélection de type de base. Les comparaisons période-sur-période, les métriques de segment filtrées et la gestion des lacunes dans les séries temporelles sont les trois patterns qui reviennent régulièrement une fois que l’on dépasse les agrégations simples.
Comparaisons période-sur-période
Le paramètre offset_window sur les métriques dérivées décale une métrique dans le temps. C’est la base des taux de croissance, des analyses d’écarts et de tout calcul « comparé à la période précédente ».
Le pattern de base compare une métrique à sa valeur à un point précédent :
metrics: - name: bookings_vs_last_week label: "Bookings Change vs Last Week" type: derived type_params: expr: bookings - bookings_7_days_ago metrics: - name: bookings - name: bookings offset_window: 7 days alias: bookings_7_days_agoLa même métrique (bookings) apparaît deux fois dans la liste metrics — une fois au moment actuel, une fois décalée de 7 jours. L’alias est requis car MetricFlow a besoin d’un moyen de les distinguer dans l’expression.
Pour un changement en pourcentage, encapsulez le dénominateur dans NULLIF pour gérer le cas de démarrage à froid où la période précédente n’avait pas de données :
metrics: - name: bookings_growth_wow label: "Bookings Growth % W/W" type: derived type_params: expr: (bookings - bookings_7_days_ago) / NULLIF(bookings_7_days_ago, 0) * 100 metrics: - name: bookings - name: bookings offset_window: 7 days alias: bookings_7_days_agoSans NULLIF, une période précédente à zéro bookings produit une erreur de division par zéro. NULLIF convertit zéro en null, et la division par null retourne null — ce qui est la bonne réponse. « Le taux de croissance est indéfini quand la période précédente n’avait pas d’activité » est plus exact que « le taux de croissance est infini ».
Fenêtres de décalage courantes
| Période | Décalage | Cas d’usage |
|---|---|---|
| Semaine-sur-semaine | 7 days | Métriques opérationnelles avec cycles hebdomadaires |
| Mois-sur-mois | 1 month | Revenus, croissance, KPIs métier |
| Trimestre-sur-trimestre | 3 months | Reporting exécutif |
| Année-sur-année | 1 year | Entreprises saisonnières, comparaisons annuelles |
On peut composer plusieurs décalages dans une seule métrique dérivée pour l’analyse de tendances :
metrics: - name: revenue_trend label: "Revenue Current vs 1W vs 4W" type: derived type_params: expr: > revenue - revenue_1w AS delta_1w, revenue - revenue_4w AS delta_4w metrics: - name: revenue - name: revenue offset_window: 7 days alias: revenue_1w - name: revenue offset_window: 28 days alias: revenue_4wMétriques filtrées
Les filtres utilisent le templating Jinja pour référencer les dimensions via leur chemin d’entité. C’est la syntaxe de MetricFlow pour dire « applique cette clause WHERE en utilisant le graphe sémantique ».
Filtres de dimension
metrics: - name: enterprise_revenue type: simple type_params: measure: revenue filter: - "{{ Dimension('customer__segment') }} = 'enterprise'"La fonction Dimension() se résout à la colonne et la table correctes en se basant sur les relations d’entités du modèle sémantique. On n’écrit pas des noms de colonnes bruts — MetricFlow gère le chemin de jointure du modèle sémantique de la métrique jusqu’à la source de la dimension.
C’est l’approche préférable à l’encodage des filtres dans les mesures. Une mesure générale revenue combinée avec des filtres au niveau de la métrique produit enterprise_revenue, smb_revenue, startup_revenue, et n’importe quel autre segment sans avoir à définir de nouvelles mesures.
Filtres de dimension temporelle
Pour le filtrage basé sur le temps avec une granularité spécifique :
filter: - "{{ TimeDimension('order__ordered_at', 'month') }} >= '2024-01-01'"Le second argument de TimeDimension() spécifie la granularité. C’est important car la troncature de date affecte les lignes correspondantes. Filtrer au grain day versus month produit des résultats différents quand la valeur du filtre est à la limite d’un mois.
Filtres sur les métriques ratio
Les filtres sur les métriques ratio peuvent cibler le numérateur, le dénominateur, ou les deux indépendamment :
metrics: - name: mobile_conversion_rate label: "Mobile Conversion Rate" type: ratio type_params: numerator: name: conversions filter: - "{{ Dimension('session__device_type') }} = 'mobile'" denominator: sessionsCeci calcule « conversions mobile divisées par toutes les sessions ». Si l’on veut « conversions mobile divisées par sessions mobile », il faut appliquer le filtre aux deux :
type_params: numerator: name: conversions filter: - "{{ Dimension('session__device_type') }} = 'mobile'" denominator: name: sessions filter: - "{{ Dimension('session__device_type') }} = 'mobile'"La distinction importe. « Taux de conversion mobile sur tout le trafic » et « taux de conversion mobile sur le trafic mobile » sont des métriques différentes avec des significations métier différentes. Le placement du filtre rend cela explicite.
Gestion des nulls dans les séries temporelles
Les métriques sans données pour une période de temps retournent null par défaut. Dans un rapport de revenus quotidien, un jour sans ventes retourne null, pas zéro. Cela crée des lacunes dans les graphiques et perturbe les consommateurs en aval qui interprètent null comme « données manquantes » plutôt que « rien ne s’est passé ».
Deux paramètres corrigent cela :
type_params: measure: name: revenue fill_nulls_with: 0 join_to_timespine: truejoin_to_timespine: true garantit que chaque date dans la plage de temps apparaît dans les résultats, même les dates sans données sous-jacentes. MetricFlow maintient une table de colonne vertébrale temporelle (une séquence de dates continue) et fait une jointure gauche sur vos résultats de métrique.
fill_nulls_with: 0 remplace les valeurs null par des zéros après la jointure avec la colonne vertébrale. Ensemble, ils produisent des séries temporelles complètes sans lacunes.
Quand utiliser chaque paramètre :
- Les deux ensemble pour les métriques opérationnelles où zéro est significatif (revenu quotidien, nombre de commandes, pages vues). Un jour sans commandes est un vrai point de données, pas des données manquantes.
join_to_timespineuniquement (sans fill) pour les métriques où null et zéro sont différents. Un capteur qui ne rapporte aucune lecture est différent d’un capteur qui rapporte zéro.- Aucun des deux pour les métriques basées sur des événements où on ne se soucie que des périodes avec de l’activité (performances de campagne, utilisation de fonctionnalités dans un produit pas toujours actif).
Configuration de la timespine
La table timespine doit exister dans le projet dbt. MetricFlow l’utilise comme épine dorsale pour la complétude des séries temporelles :
# Dans le projet dbtmodels: - name: metricflow_time_spine description: "Continuous date sequence for time series gap filling"La table est simplement une liste de dates couvrant la plage de données. MetricFlow s’attend à ce qu’elle existe et l’utilise automatiquement quand join_to_timespine est activé.
Combiner les patterns
Ces patterns se composent naturellement. Une comparaison période-sur-période d’une métrique filtrée avec le remplissage des lacunes de la timespine :
metrics: - name: enterprise_revenue_growth_mom label: "Enterprise Revenue Growth % M/M" type: derived type_params: expr: > (enterprise_rev - enterprise_rev_last_month) / NULLIF(enterprise_rev_last_month, 0) * 100 metrics: - name: enterprise_revenue alias: enterprise_rev - name: enterprise_revenue offset_window: 1 month alias: enterprise_rev_last_monthLa métrique enterprise_revenue (elle-même une métrique simple filtrée) est utilisée deux fois à différents décalages temporels. MetricFlow résout le filtre, le décalage et la dérivation dans le bon ordre. On exprime l’intention métier ; MetricFlow gère la complexité SQL.
Cette composabilité est la valeur fondamentale de définir les métriques-as-code. Chaque couche construit sur celle en dessous, et les changements se propagent automatiquement. Mettez à jour le filtre enterprise sur la métrique de base, et le calcul de croissance l’intègre sans modification.