observabilité pour assistants IA dans un SaaS multitenant : comment instrumenter traces et métriques
22/06/2026

observabilité pour assistants IA dans un SaaS multitenant : comment instrumenter traces et métriques
Les assistants IA intégrés à un SaaS multitenant posent des défis spécifiques pour la supervision : latence liée aux modèles, coûts d'appel d'API, isolement des incidents par client, et forte variabilité de charge. Cet article technique explique pas à pas comment instrumenter traces et métriques pour obtenir une observabilité fiable, scalable et sûre. Public : CTO, lead dev et ingénieurs backend travaillant sur un SaaS proposant un assistant/agent IA.
Ce que vous saurez faire à la fin
- exposer des métriques Prometheus et des traces OpenTelemetry depuis un service Node.js qui appelle un modèle IA ;
- taguer correctement les données pour multitenancy sans créer de cardinalité excessive ;
- déployer un collector central et configurer Prometheus/Grafana pour alerting et dashboards ;
- appliquer bonnes pratiques perf et sécurité (sampling, PII, quotas).
Architecture cible (vue synthétique)
- Services applicatifs (Express/Node.js) instrumentés → OpenTelemetry SDK + prom-client.
- OTel Collector central (OTLP) → export vers backend traces (Jaeger/Grafana Tempo) et metrics (Prometheus remote_write si nécessaire).
- Prometheus scrappe /metrics ou reçoit remote_write → Grafana pour dashboards et alerting.
Étapes détaillées
1. exposer des métriques opérationnelles (Prometheus)
Dans votre service Node.js, utilisez prom-client pour exposer un endpoint /metrics. Mesures minimales à collecter :
- request_count (labels: route, method, status_code, tenant_bucket)
- request_duration_seconds (histogram) pour p50/p95/p99
- external_api_latency_seconds (histogram) pour chaque appel au provider IA
- error_count (labels: error_type, tenant_bucket)
// snippet Node.js (Express) - prom-client
const express = require('express');
const client = require('prom-client');
const app = express();
const register = client.register;
const httpRequestDuration = new client.Histogram({
name: 'http_request_duration_seconds',
help: 'durée des requêtes HTTP',
labelNames: ['route','method','status','tenant_bucket'],
buckets: [0.01,0.05,0.1,0.3,1,3,10]
});
app.use((req,res,next) => {
const end = httpRequestDuration.startTimer({
route: req.path,
method: req.method,
tenant_bucket: computeTenantBucket(req.headers['x-tenant-id'])
});
res.on('finish', () => {
end({ status: String(res.statusCode) });
});
next();
});
app.get('/metrics', async (req,res) => {
res.set('Content-Type', register.contentType);
res.end(await register.metrics());
});
Astuce multitenant : ne taggez pas chaque métrant tenant_id brut (forte cardinalité). Utilisez un champ tenant_bucket (hash vers N buckets) ou ne taggez que les tenants « VIP » qui nécessitent un suivi dédié.
2. traces distribuées avec OpenTelemetry
Instrumentez les appels internes et externes (appel au modèle IA). Ajoutez un attribut de trace tenant.bucket et, si nécessaire, tenant.role. Configurez une règle de sampling adaptée (ex : 1% global + 100% pour erreurs ou VIP).
// pseudo-configuration OpenTelemetry Node
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const sdk = new NodeSDK({
traceExporter: /* OTLP exporter vers collector */,
instrumentations: [getNodeAutoInstrumentations()]
});
sdk.start();
Dans le middleware qui appelle l'API IA, créez un span nommé "call-model" et ajoutez des attributs : model_id, prompt_size_tokens, tenant_bucket, provider_cost_estimate.
3. collector central et pipeline
Déployez un OpenTelemetry Collector (container ou k8s) pour centraliser et filtrer données. Avantages :
- appliquer sampling ou redaction avant stockage
- router données vers plusieurs backends (Jaeger, Tempo, Prometheus, remote_write)
- contrôle d’accès centralisé
# docker-compose minimal (extrait) - otel collector + jaeger
services:
otel-collector:
image: otel/opentelemetry-collector:latest
ports: ["4318:4318","4317:4317"]
volumes: ["./collector-config.yaml:/etc/otel/config.yaml"]
jaeger:
image: jaegertracing/all-in-one:latest
ports: ["16686:16686","14268:14268"]
Note : remplacez 'latest' par un tag adapté selon votre politique interne.
4. Prometheus + Grafana : scrapping et alerting
Si vous exposez /metrics, Prometheus peut scrapper directement vos services. Exemple de règle d’alerte simple :
# alert rule - haute latence p95
groups:
- name: assistant-ai.rules
rules:
- alert: HighAssistantLatency
expr: histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le, route, tenant_bucket))
> 1.5
for: 5m
labels:
severity: warning
annotations:
summary: "p95 latency > 1.5s pour route {{ $labels.route }}"
Conseil : alertez d'abord par route globale, puis affinez par tenant_bucket uniquement si la fréquence le justifie.
Bonnes pratiques pour multitenancy et IA
- Limiter la cardinalité des labels : évitez tenant_id direct, utilisez buckets, tags systèmes ou dimensions agrégées.
- Sampling adaptatif : 100% des erreurs, 100% des traces des VIP, sampling plus bas sur traffic général pour maîtriser coûts.
- Redaction et conformité : ne loggez pas de prompts ou de réponses contenant des PII. Faites la redaction côté collector si besoin.
- Mesurer coût par requête IA : capturez tokens, temps et fournisseur pour estimer coût réel par tenant.
- Tests de charge ciblés : simulez spikes d’appels au modèle pour mesurer backpressure et impact sur latence.
Erreurs fréquentes et comment les corriger
- Pas de métriques visibles dans Prometheus : vérifier que /metrics est accessible depuis l’instance Prometheus (firewall, network policy).
- Cardinalité explosive : supprimer label fautif (tenant_id) et reconstruire métriques sur un nouvel endpoint si nécessaire.
- Traces absentes : s'assurer que l'OTLP exporter pointe vers l'IP/port du collector et que l'application transmet des spans (vérifier logs du SDK).
- Coût storage trop élevé : augmenter sampling ou réduire rétention au niveau du backend.
Métriques clés à suivre (tableau)
| Métrique | Pourquoi | alerte suggérée |
|---|---|---|
| p95 request_duration | Indique latence perçue par user | p95 > 1.5s pendant 5min |
| error_rate | Régression qualité ou dégradation fournisseur IA | error_rate > 2% sur 10min |
| external_api_latency | Performance fournisseur IA | p95 > seuil SLA |
| tokens_consumed per minute | Coût et anomalies de consommation | hausse > 3x baseline |
Sécurité et gouvernance
- sécurisez les endpoints OTLP (mTLS, network policies) et limitez exposition publique.
- redaction des spans/métriques contenant des données sensibles au niveau du collector.
- auditez accès aux dashboards et aux logs car ils peuvent révéler des données métier.
Exemples concrets d’implémentation
Pour un SaaS qui facture par utilisation, ajouter une métrique custom tokens_consumed permet de lier coût IA et facturation. Pour un client VIP, activez trace sampling à 100 % pour faciliter debug sans augmenter sampling global.
Conclusion
Mettre en place une observabilité robuste pour un assistant IA dans un SaaS multitenant est essentiel pour garantir performance, contrôle des coûts et isolation des incidents. Commencez par exposer métriques basiques et traces, centralisez via un collector et appliquez des règles strictes de cardinalité et de redaction. À partir de là, construisez dashboards et alertes ciblées pour piloter votre service.
Si vous voulez un audit technique ou un proof of concept pour instrumenter votre assistant IA, Novane peut aider à définir l'architecture et le pipeline. Voir nos offres SaaS et IA pour en discuter : services SaaS, services IA. Pour une mise en œuvre Node.js, consultez notre page technologie : Node.js.
Petit point action : commencez par ajouter /metrics et un span "call-model" dans une branche de test et mesurez p95 et error_rate sur 24 heures.

