Vous utilisez des APIs d'intelligence artificielle pour votre application et vous vous demandez parfois : "Mais où est passé ma requête ? Combien de temps a-t-elle mis ? Y a-t-il eu une erreur ?" Vous n'êtes pas seul. Aujourd'hui, nous allons apprendre ensemble à utiliser OpenTelemetry pour observer et tracer chaque requête envoyée vers une API IA.

Imaginez que vous envoyez une lettre par la poste. Sans numéro de suivi, vous ne savez jamais si elle est arrivée, ni combien de temps elle a mis. OpenTelemetry, c'est exactement ce numéro de suivi pour vos requêtes API. Et devinez quoi ? HolySheep AI offre une inscription ici avec des crédits gratuits pour commencer vos expérimentations !

Qu'est-ce qu'OpenTelemetry et pourquoi c'est utile ?

Avant de coder, comprenons simplement ce qu'est OpenTelemetry (souvent abrégé OTel). En termes simples, c'est un outil gratuit et open-source qui permet de collecter des données sur le fonctionnement de vos applications. Ces données se divisent en trois catégories principales :

Pour les développeurs beginners, la trace est le plus important. Elle vous montre exactement ce qui se passe quand votre code appelle une API IA.

Prérequis : ce dont vous avez besoin

Pas de panique, nous partons de zéro ! Voici ce qu'il vous faut :

Pourquoi HolySheep AI ? Parce que leurs serveurs sont optimisés avec une latence inférieure à 50ms, ce qui rend l'observation avec OpenTelemetry encore plus rapide et efficace ! De plus, leur taux de change avantageux (¥1 = $1) vous permet d'économiser plus de 85% par rapport aux tarifs standards.

Étape 1 : Créer votre premier projet Node.js

Ouvrez votre terminal (ou invite de commandes) et tapez ces commandes :

# Créer un nouveau dossier pour votre projet
mkdir mon-projet-otel
cd mon-projet-otel

Initialiser le projet Node.js

npm init -y

Installer les dépendances nécessaires

npm install @opentelemetry/sdk-node npm install @opentelemetry/auto-instrumentations-node npm install @opentelemetry/exporter-trace-otlp-http npm install axios npm install dotenv

💡 Indicateur : Votre terminal devrait afficher "added X packages" pour chaque installation réussie.

Étape 2 : Configurer OpenTelemetry

Créez un fichier nommé tracing.js à la racine de votre projet. Ce fichier va configurer OpenTelemetry pour qu'il surveille toutes vos requêtes HTTP :

// tracing.js - Configuration OpenTelemetry
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
const { Resource } = require('@opentelemetry/resources');
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');

// Configuration de l'exportateur vers un backend local (Jaeger)
const traceExporter = new OTLPTraceExporter({
  url: 'http://localhost:4318/v1/traces',
});

// Initialisation du SDK OpenTelemetry
const sdk = new NodeSDK({
  resource: new Resource({
    [SemanticResourceAttributes.SERVICE_NAME]: 'mon-api-ai-tracing',
    [SemanticResourceAttributes.SERVICE_VERSION]: '1.0.0',
  }),
  traceExporter: traceExporter,
  instrumentations: [
    getNodeAutoInstrumentations({
      '@opentelemetry/instrumentation-http': {
        enabled: true,
      },
      '@opentelemetry/instrumentation-axios': {
        enabled: true,
      },
    }),
  ],
});

// Démarrage automatique du SDK
sdk.start();

// Gestion gracieuse de l'arrêt
process.on('SIGTERM', () => {
  sdk.shutdown()
    .then(() => console.log('🔴 OpenTelemetry arrêté'))
    .catch((error) => console.error('Erreur arrêt OTel:', error))
    .finally(() => process.exit(0));
});

console.log('✅ OpenTelemetry initialisé - traces activées');

Ce code peut sembler long, mais chaque partie a un rôle précis : l'exportateur envoie vos données de trace, et les instrumentations automatiques capturent automatiquement toutes les requêtes HTTP et axios.

Étape 3 : Créer le script principal avec l'appel API HolySheheep AI

Créez maintenant un fichier .env pour stocker votre clé API en sécurité :

HOLYSHEEP_API_KEY=VOTRE_CLE_API_ICI

⚠️ Important : Remplacez VOTRE_CLE_API_ICI par votre vraie clé API obtenue lors de votre inscription sur HolySheep AI.

Ensuite, créez le fichier principal app.js :

// app.js - Application principale avec tracing
require('./tracing'); // IMPORTANT: Charger la config OTel en premier

const axios = require('axios');
require('dotenv').config();

const HOLYSHEEP_BASE_URL = 'https://api.holysheep.ai/v1';

async function envoyerRequeteIA() {
  console.log('📤 Envoi de la requête vers HolySheep AI...');
  const debut = Date.now();

  try {
    const reponse = await axios.post(
      ${HOLYSHEEP_BASE_URL}/chat/completions,
      {
        model: 'gpt-4.1',
        messages: [
          {
            role: 'user',
            content: 'Explique-moi OpenTelemetry en une phrase simple.'
          }
        ],
        max_tokens: 150
      },
      {
        headers: {
          'Authorization': Bearer ${process.env.HOLYSHEEP_API_KEY},
          'Content-Type': 'application/json'
        }
      }
    );

    const tempsExecution = Date.now() - debut;
    
    console.log('\n📥 Réponse reçue !');
    console.log(⏱️ Temps d'exécution: ${tempsExecution}ms);
    console.log(💰 Modèle utilisé: ${reponse.data.model});
    console.log(💵 Coût estimé: ${reponse.data.usage?.total_tokens || 0} tokens);
    
    if (reponse.data.choices && reponse.data.choices[0]) {
      console.log('\n🤖 Réponse IA:');
      console.log(reponse.data.choices[0].message.content);
    }

  } catch (erreur) {
    console.error('❌ Erreur lors de la requête:', erreur.message);
    if (erreur.response) {
      console.error('Code HTTP:', erreur.response.status);
      console.error('Détails:', erreur.response.data);
    }
  }
}

// Exécuter la fonction
envoyerRequeteIA().then(() => {
  console.log('\n✨ Script terminé');
});

Remarquez comme nous utilisons HOLYSHEEP_BASE_URL = 'https://api.holysheep.ai/v1' ! C'est l'endpoint officiel de HolySheep AI qui offre des tarifs imbattables : GPT-4.1 à $8/1M tokens, Gemini 2.5 Flash à $2.50/1M tokens, et DeepSeek V3.2 à seulement $0.42/1M tokens.

Étape 4 : Installer Jaeger pour visualiser les traces

Pour voir concrètement vos traces, nous allons utiliser Jaeger, un outil gratuit de visualisation. Sans lui, vos traces sont envoyées mais vous ne pouvez pas les voir.

Installez d'abord Docker sur votre ordinateur, puis lancez Jaeger avec cette commande :

docker run -d --name jaeger \
  -e COLLECTOR_OTLP_ENABLED=true \
  -p 6831:6831/udp \
  -p 16686:16686 \
  -p 4317:4317 \
  -p 4318:4318 \
  -p 14250:14250 \
  jaegertracing/all-in-one:latest

Une fois Jaeger démarré, ouvrez votre navigateur et allez à l'adresse http://localhost:16686. Vous verrez l'interface de Jaeger où vos traces apparaîtront.

💡 Indicateur : L'écran Jaeger montre une barre de recherche en haut avec des options de service à gauche. C'est là que vous sélectionnerez "mon-api-ai-tracing".

Étape 5 : Lancer et observer

Maintenant, lancez votre application :

node app.js

Vous devriez voir s'afficher quelque chose comme :

✅ OpenTelemetry initialisé - traces activées
📤 Envoi de la requête vers HolySheep AI...
📥 Réponse reçue !
⏱️ Temps d'exécution: 145ms
💰 Modèle utilisé: gpt-4.1
💵 Coût estimé: 42 tokens

🤖 Réponse IA:
OpenTelemetry est un framework open-source qui permet de collecter et d'exporter des données d'observation...

✨ Script terminé

Ensuite, ouvrez Jaeger à http://localhost:16686, sélectionnez "mon-api-ai-tracing" dans le menu déroulant, et cliquez sur "Find Traces". Vous verrez apparaître une trace avec tous les détails de votre requête !

Comprendre ce que vous voyez dans Jaeger

Quand vous visualisez une trace dans Jaeger, vous verrez plusieurs "spans" (segments). Un span représente une opération. Pour notre requête API, nous aurons :

  • Span racine : le temps total de votre fonction
  • Span HTTP POST : la requête vers HolySheep AI
  • Span Axios : les détails de la bibliothèque utilisée

Chaque span affiche des informations précieuses :

  • La durée (combien de temps l'opération a duré)
  • Les headers HTTP envoyés
  • La réponse reçue
  • Les éventuelles erreurs

Ajouter des informations personnalisées à vos traces

Vous pouvez enrichir vos traces avec vos propres données. Modifiez app.js ainsi :

const { trace, SpanStatusCode } = require('@opentelemetry/api');

async function envoyerRequeteIA() {
  // Créer un span personnalisé
  const traceur = trace.getTracer('mon-traceur');
  
  return traceur.startActiveSpan('requete-holysheep', async (span) => {
    try {
      span.setAttribute('ai.model', 'gpt-4.1');
      span.setAttribute('ai.provider', 'holysheep');
      span.setAttribute('request.type', 'chat-completion');
      
      console.log('📤 Envoi de la requête vers HolySheep AI...');
      
      const reponse = await axios.post(
        ${HOLYSHEEP_API_URL}/chat/completions,
        // ... configuration de la requête
      );

      span.setAttribute('response.tokens', reponse.data.usage?.total_tokens || 0);
      span.setAttribute('response.model', reponse.data.model);
      span.setStatus({ code: SpanStatusCode.OK });
      
      console.log('✅ Requête réussie !');
      
    } catch (erreur) {
      span.setStatus({
        code: SpanStatusCode.ERROR,
        message: erreur.message,
      });
      span.recordException(erreur);
      console.error('❌ Erreur:', erreur.message);
    } finally {
      span.end();
    }
  });
}

Ces attributs personnalisés vous permettront de filtrer et analyser vos traces plus facilement dans Jaeger. Par exemple, vous pourriez filtrer toutes les traces utilisant le modèle GPT-4.1 ou toutes celles qui ont échoué.

Utiliser plusieurs modèles simultanément

Une technique puissante consiste à comparer plusieurs modèles sur la même requête. Voici comment faire :

async function comparerModeles() {
  const traceur = trace.getTracer('comparaison-modeles');
  
  return traceur.startActiveSpan('comparaison-ia', async (span) => {
    const modeles = [
      { nom: 'gpt-4.1', coutParToken: 8 },
      { nom: 'gemini-2.5-flash', coutParToken: 2.5 },
      { nom: 'deepseek-v3.2', coutParToken: 0.42 }
    ];
    
    const resultats = [];
    
    for (const modele of modeles) {
      const spanModele = traceur.startSpan(requete-${modele.nom});
      spanModele.setAttribute('model.name', modele.nom);
      spanModele.setAttribute('model.prix', modele.coutParToken);
      
      try {
        const debut = Date.now();
        
        const reponse = await axios.post(
          ${HOLYSHEEP_API_URL}/chat/completions,
          {
            model: modele.nom,
            messages: [{ role: 'user', content: 'Bonjour, présente-toi.' }],
            max_tokens: 50
          },
          {
            headers: {
              'Authorization': Bearer ${process.env.HOLYSHEEP_API_KEY},
              'Content-Type': 'application/json'
            }
          }
        );
        
        const duree = Date.now() - debut;
        const tokens = reponse.data.usage?.total_tokens || 0;
        
        spanModele.setAttribute('duree.ms', duree);
        spanModele.setAttribute('tokens.utilises', tokens);
        spanModele.setAttribute('cout.estimation', (tokens / 1000000) * modele.coutParToken);
        
        resultats.push({
          modele: modele.nom,
          duree,
          tokens,
          contenu: reponse.data.choices[0]?.message.content
        });
        
        console.log(✅ ${modele.nom}: ${duree}ms, ${tokens} tokens);
        
      } catch (erreur) {
        spanModele.setStatus({ code: SpanStatusCode.ERROR });
        console.error(❌ Erreur pour ${modele.nom}:, erreur.message);
      }
      
      spanModele.end();
    }
    
    span.end();
    return resultats;
  });
}

comparerModeles().then(resultats => {
  console.log('\n📊 Comparaison terminée !');
});

Cette approche vous permet de voir dans Jaeger exactement combien de temps chaque modèle a mis, combien de tokens il a utilisé, et de comparer leurs performances côte à côte.

Analyser les performances avec les métriques

Au-delà des traces, vous pouvez收集 des métriques. Créez un fichier metrics.js :

const { MeterProvider } = require('@opentelemetry/sdk-metrics');
const { PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics');
const { Resource } = require('@opentelemetry/resources');

// Configuration du lecteur de métriques
const metricReader = new PeriodicExportingMetricReader({
  exporter: new PeriodicExportingMetricReader({
    exportIntervalMillis: 60000, // Exporter toutes les minutes
    exporterOptions: {
      url: 'http