Aller au contenu

ADR-0001 – Conversion des unités à la lecture

Contexte

Le service apps/api/legacy-metrics/src/metrics-v3 ingère les métriques des capteurs, applique historiquement les transformations lors de l'écriture, puis stocke les valeurs transformées dans InfluxDB.

Cette approche simplifie les lectures, mais rend tout changement d'unité extrêmement coûteux puisqu'il faudrait recalculer et réécrire l'ensemble de l'historique.

Afin de répondre aux nouveaux besoins de changement d'unité, les conversions doivent désormais être réalisées à la lecture, sans modifier les données stockées.


Problème

Les lectures de métriques sont aujourd'hui réparties dans plusieurs chemins legacy.

Pour une première version (V1), le périmètre est volontairement limité aux principales requêtes utilisateur :

  • getMetricsV3
  • getMetricsMultipleV3

La conversion doit être appliquée de manière cohérente sur l'ensemble de la réponse :

  • les séries (datasets)
  • les premières et dernières valeurs
  • les valeurs minimales et maximales
  • les seuils affichés
  • les métadonnées d'unité

En revanche, les calculs internes doivent continuer à utiliser les unités canoniques afin d'éviter toute régression métier :

  • données stockées dans InfluxDB
  • seuils persistés
  • calculs d'alerting

Décision

Introduire un mécanisme explicite de conversion d'unité à la lecture, piloté par la requête du client.

Le client peut envoyer un champ optionnel unitByField.

Exemple :

[
  {
    field: ANGLEX,
    unit: millimeter_per_meter,
  },
];

Si un champ n'est pas présent dans unitByField, il est retourné dans son unité canonique.

Chaque DatasetV3 expose les unités effectivement utilisées au travers d'un champ units.


Unités supportées (V1)

Angles

Champs supportés :

  • ROLL
  • PITCH
  • ANGLEX
  • ANGLEY

Unités supportées :

  • degree
  • millimeter_per_meter

Formules :

degree → millimeter_per_meter
= tan(degree × PI / 180) × 1000
millimeter_per_meter → degree
= atan(mmPerM / 1000) × 180 / PI

Température

Unités supportées :

  • celsius
  • fahrenheit

Formules :

celsius → fahrenheit
= (celsius × 9) / 5 + 32
fahrenheit → celsius
= ((fahrenheit - 32) × 5) / 9

Aucun arrondi n'est effectué côté backend.


Données converties

Les éléments suivants sont convertis avant d'être renvoyés au client :

  • datasets
  • MetricsValues.y
  • MetricsValues.yBrut
  • first_and_last_values
  • min_and_max_values
  • thresholds_values

Les éléments suivants restent toujours en unité canonique :

  • les données stockées dans InfluxDB
  • les seuils persistés
  • les calculs d'alerting
  • CurveEvent

Les valeurs minimales et maximales continuent d'être calculées en unité canonique avant d'être converties dans la réponse.


Validation

La validation est stricte.

Une erreur est retournée lorsque :

  • une unité est incompatible avec le champ demandé ;
  • un champ est présent dans unitByField mais n'a pas été demandé ;
  • un même champ apparaît plusieurs fois dans unitByField.

Exemple :

Duplicate unit requested for field ANGLEX

Pour cette V1, une erreur de validation classique est suffisante. Aucun type d'erreur métier spécifique n'est nécessaire.


Architecture

Contrat partagé (@feelbat/core/metrics)

Ajout de :

  • MetricUnitEnum
  • l'entrée unitByField
  • la sortie units

Service de métriques

Ajouter un service de conversion d'unités dans metrics-v3, réutilisable ultérieurement par MetricsV3TmpService.

MetricsV3Service devient le point central de la conversion :

  1. reçoit unitByField ;
  2. valide les unités après résolution des champs ;
  3. récupère les métriques en unité canonique ;
  4. construit le dataset existant ;
  5. convertit la réponse finale ;
  6. renseigne le champ units.

Les resolvers ne doivent contenir aucune logique de conversion. Ils se contentent de transmettre filter.unitByField.


Compatibilité

unitByField est optionnel.

Lorsqu'il est absent, les réponses restent strictement identiques au comportement actuel et utilisent les unités canoniques.

Cela garantit la rétrocompatibilité avec les clients existants.

Chaque DatasetV3, y compris ceux renvoyés par getMetricsMultipleV3, possède son propre champ units.


Conséquences

Avantages

  • Plus aucune réécriture de l'historique InfluxDB n'est nécessaire lors d'un changement d'unité.
  • Les unités d'affichage deviennent indépendantes du stockage.
  • La solution est rétrocompatible.
  • Le mécanisme pourra être réutilisé par les futurs endpoints de métriques.

Compromis

  • Les conversions sont désormais réalisées à chaque lecture, ce qui ajoute un faible coût CPU.
  • Les nouveaux endpoints devront utiliser le service de conversion afin de garantir un comportement homogène.

Tests recommandés

  • conversion des angles ;
  • conversion des températures ;
  • validation d'une unité incompatible ;
  • validation d'un champ non demandé ;
  • validation des doublons ;
  • conversion des datasets ;
  • conversion des first_and_last_values ;
  • conversion des min_and_max_values ;
  • conversion des thresholds_values ;
  • génération complète du champ units, y compris pour les champs non convertis explicitement.