Télémétrie
Le registre
Les événements migrés vers le registre se trouvent dans packages/@n8n/telemetry avec une entrée par événement — son nom exact émis, une description, et un schéma zod typant ses propriétés — organisés par domaine produit dans src/events/ et composés en TELEMETRY_EVENT.<DOMAIN>.<EVENT>. Le package définit les événements enregistrés et ne dépend jamais des SDKs de transport.
Pour trouver les événements enregistrés, leur signification, ou les propriétés qu'ils portent, lancez d'abord le catalogue :
pnpm --filter @n8n/telemetry catalog # lisible, groupé par domaine
pnpm --filter @n8n/telemetry catalog --json # structuré, pour usage programmatique
Le registre est adopté progressivement. Les événements non encore enregistrés n'apparaissent pas dans le catalogue, cherchez donc les sites d'appel track() quand le catalogue n'a pas de correspondance.
Passez l'entrée elle-même à track() — elle résout le nom émis en interne :
import { TELEMETRY_EVENT } from '@n8n/telemetry';
telemetry.track(TELEMETRY_EVENT.PLATFORM.USER_IS_PART_OF_EXPERIMENT, {
name: experimentName,
variant,
});
Les deux implémentations de track() acceptent les entrées du registre et les chaînes simples. Les chaînes simples restent supportées pour les événements non encore migrés :
- Frontend :
packages/frontend/editor-ui/src/app/plugins/telemetry/index.ts - Backend :
packages/cli/src/telemetry/index.ts
Les entrées obtiennent l'autocomplétion des propriétés et les vérifications à la compilation — des propriétés mal orthographiées, manquantes, ou mal typées échouent la vérification de type. Quand le transport de télémétrie est initialisé, track() valide également les payloads des événements enregistrés via getEventValidationError (partagé depuis @n8n/telemetry) et enregistre un avertissement en cas de discordance, incluant les propriétés non reconnues qui ont échappé au typage structurel. Un avertissement de validation n'empêche pas l'événement d'être émis.
Ajouter un événement
- Vérifiez le catalogue d'abord (
pnpm --filter @n8n/telemetry catalog). Si un événement existant couvre la même action utilisateur depuis une autre surface, augmentez-le avec une propriété au lieu d'ajouter un événement quasi-dupliqué. - Choisissez le domaine par le sujet de l'événement — ce dont parle l'événement, jamais la surface qui l'a déclenché.
User opened Credential modalest CREDENTIALS que ce soit ouvert depuis le NDV, la configuration de template, ou le chat. Le contexte du déclenchement va dans une propriétésource. - Nommez-le selon la grammaire maison : phrase case, acteur en premier, verbe au passé, objet spécifique (
User pinned node data). Pas d'interpolation de template dans les noms — la variabilité va dans les propriétés. Le nom doit se convertir en snake_case proprement en nom de table BigQuery : pas de ponctuation au-delà des espaces, pas de casse qui crée une collision après snake_casing. - Écrivez la
descriptionde l'entrée indiquant ce que signifie l'événement et quand il se déclenche — un test du registre rejette les descriptions vides. Documentez les propriétés individuelles avec.describe()où la clé seule n'est pas évidente. - Typez les propriétés avec zod (
import { z } from 'zod/v4') : clés ensnake_case,.optional()explicite où un site d'appel peut omettre une valeur,z.looseObject()/.catchall()pour les restes véritablement dynamiques. Les schémas doivent rester représentables en JSON-Schema — pas de transforms, refinements, ouz.date()(un test du registre applique cela viaz.toJSONSchema()). - Placez l'émission : frontend via
useTelemetry().track(...); backend soit par un handlerRelayEventMapdanspackages/cli/src/events/relays/telemetry.event-relay.ts(piloté par event-bus) soit par un appelTelemetry.track(...)direct — les deux référencent la même entrée du registre.
Règles strictes
- Ne renommez jamais un événement émis. BigQuery matérialise une table par nom d'événement ; un renommage orpheline l'historique en aval. Un renommage est suppression + création, les noms ne sont jamais réutilisés, et les suppressions doivent être coordonnées avec l'équipe data avant de supprimer l'entrée du registre.
- Ne dupliquez jamais un nom d'événement — une entrée par événement dans tous les domaines, référencée par chaque site d'appel (même FE + BE). Le CI échoue en cas de collision.
- Les propriétés évoluent additivement seulement. Changer le type d'une propriété divise les colonnes d'entrepôt même sous un nom stable. Marquez les dépréciations sur le schéma (
.meta({ deprecated: true })) au lieu de les supprimer. - Les breaking changes nécessitent une alerte de l'équipe data sur Slack plus une note Notion avant le déploiement.
Test
Ne redigitez pas les littéraux de noms d'événement dans les tests :
- Dans les tests du site d'appel, mockez
useTelemetry().trackou le service backendTelemetry.tracket attendez l'entrée du registre elle-même avec le payload. - Dans les tests de transport frontend, attendez que
window.rudderanalytics.trackreçoiveentry.nameet le payload augmenté. - Dans les tests de transport backend, attendez que le champ
eventdu payload RudderStack égaleentry.nameet que sonpropertiesinclue le payload de l'événement.
Connexes
L'exposition aux expériences et les événements de métrique suivent n8n:experiments (.agents/skills/experiments/SKILL.md).