Project Oxygen & Ideo-LabIDEO LAB Dashboard 2026

🚀 k6 – Test de Charge "Developer-Centric"

Guide complet IDEO-Lab sur l'outil de test de performance (Go/JS) de Grafana Labs.

1.1

Concept : "Tests as Code"

Go (backend), JS (scripts). Open source (Grafana Labs).

k6 Test de Charge Go
1.2

vs. JMeter / Gatling

Code (JS) vs GUI (XML). Event-Loop vs Thread-per-User.

JMeter Gatling Event-Loop
1.3

Installation

Binaire natif (apt, brew), Docker (grafana/k6).

Install Docker
2.1

Le Script (script.js)

Structure : Contexte init vs Contexte VU.

script.js init VU
2.2

VUs (Virtual Users)

Utilisateurs virtuels. Goroutines (légers).

VU Goroutine
2.3

options (Configuration)

Définition de la charge (vus, duration) dans le script.

options vus duration
3.1

http.get() / http.post()

Le "Sampler" HTTP (Params, Body, Headers).

http Sampler
3.2

check() (Assertion)

Vérification de la réponse (Status 200, Body JSON).

check() Assertion
3.3

thresholds (SLO/SLA)

CritÚres de réussite (Pass/Fail) du test (p(95), rate).

Thresholds SLO p(95)
4.1

scenarios (Exécuteurs)

options.scenarios. Gestion avancée des VUs.

Scenarios Executors
4.2

Exécuteur : ramping-vus

stages (Ramp-up, Hold, Ramp-down).

ramping-vus stages
4.3

Cycle de Vie (Setup/Teardown)

setup() (1 fois, avant), teardown() (1 fois, aprĂšs).

setup teardown
5.1

Métriques (Built-in)

http_req_duration, http_req_failed, checks.

Metrics http_req_duration
5.2

Métriques (Custom)

Counter, Gauge, Rate, Trend (le plus utile).

Custom Metrics Trend
5.3

group() (Transactions)

Grouper des requĂȘtes (ex: "Login").

group() Transaction
6.1

Exécution (CLI)

k6 run, -u, -d, -e (Variables d'env).

k6 run CLI -e
6.2

Sorties (Outputs)

--out json, Prometheus, InfluxDB, Datadog.

Output Prometheus
6.3

k6 Cloud (SaaS)

k6 cloud script.js. Scaling distribué, Dashboards.

k6 Cloud SaaS
7.1

k6-browser

Test Front-End (Chromium, Playwright). Core Web Vitals.

k6-browser Frontend
7.2

Extensions (xk6)

Builder (Go). k6-sql (BDD), k6-kafka (Events).

xk6 Go k6-sql
7.3

Script ModĂšle

Structure d'un bon script (Options, Thresholds, Check).

Cheatsheet Script
1.1 Concept : "Tests as Code"
Qu'est-ce que k6 ?

k6 est un outil de test de charge (load testing) open-source, moderne, acquis par Grafana Labs. Il est conçu pour ĂȘtre "Developer-Centric" (axĂ© sur les dĂ©veloppeurs) et s'intĂ©grer parfaitement dans les pipelines CI/CD.

Philosophie "Tests as Code"

Contrairement à JMeter (basé GUI), k6 adopte une approche "Tests as Code" :

  1. Les scénarios de test sont écrits en JavaScript (JS) (ES2015+), ce qui les rend faciles à lire, à versionner (Git) et à intégrer.
  2. Le moteur (le "cƓur") de k6 est Ă©crit en Go (Golang), le rendant extrĂȘmement performant (binaire unique, faible consommation mĂ©moire).
  3. Il est conçu pour le CI/CD (Intégration Continue). L'échec d'un test (basé sur des seuils/Thresholds) retourne un code d'erreur non-zéro, faisant échouer le pipeline.
Haute Performance (Event-Loop)

k6 (comme Gatling ou Node.js) utilise un modÚle asynchrone (event-loop). Un seul thread peut gérer des centaines d'utilisateurs virtuels (VUs). (JMeter, à l'inverse, utilise un modÚle "thread-per-user", beaucoup plus lourd).

1.2 Comparaison : k6 vs. JMeter
CritĂšrek6 (Grafana Labs)Apache JMeter
Langage (CƓur)Go (Golang)Java (JVM)
Langage (Script)JavaScript (ES2015+)GUI (Drag & Drop) -> XML (.jmx)
PhilosophieTests as Code (CI/CD natif)GUI-driven (Focus sur l'UI pour la création)
ModĂšle (VUs)Event-Loop / Asynchrone (Goroutines)Thread-per-User (Bloquant)
Performance (Injecteur)TrĂšs ÉlevĂ©e (Faible conso RAM/CPU)LimitĂ©e (Haute conso RAM/CPU)
ProtocolesHTTP/S, WebSocket, gRPC, (Browser, SQL via xk6)ExtrĂȘme (HTTP, JDBC, FTP, TCP, LDAP, JMS...)
Pass/Fail (SLA)Thresholds (IntĂ©grĂ©, puissant)Assertions (par requĂȘte), Listeners (basique)
RapportsRésumé CLI, JSON/CSV, Intégration (Prometheus, Cloud)Rapport HTML (-e -o), Listeners GUI (lourds)
1.3 Installation (Binaire ou Docker)
Installation Native (Binaire)

k6 est un binaire unique sans dépendance (sauf glibc).

# macOS (via Homebrew)
brew install k6

# Linux (Debian/Ubuntu)
sudo gpg -k ... (Ajouter la clé GPG k6)
echo "deb https://dl.k6.io/deb stable main" | sudo tee ...
sudo apt-get update
sudo apt-get install k6

# Windows (via winget ou Chocolatey)
winget install k6

# Vérifier l'installation
k6 version
Docker (Utilisation CI/CD)

C'est la méthode préférée pour l'intégration continue (GitLab CI, Jenkins, GitHub Actions).

# Syntaxe
docker run -i --rm -v [DOSSIER_LOCAL]:/scripts grafana/k6 [commande]

# Exemple d'exécution
# 1. 'pwd' (Linux/Mac) monte le dossier courant
# 2. '--rm' détruit le conteneur aprÚs l'exécution
# 3. 'run /scripts/mon_test.js' exécute le script

docker run -i --rm -v "$(pwd):/scripts" grafana/k6 run /scripts/mon_test.js
2.1 Le Script k6 (init vs VU)

Le script (.js) est le cƓur de k6. Il a deux "contextes" d'exĂ©cution :

import http from 'k6/http';
import { sleep } from 'k6';

// ---------------------------------------------
// 1. CONTEXTE "INIT"
// ---------------------------------------------
// (Exécuté 1 SEULE fois, au tout début, par 1 seul thread)
// (Utilisé pour importer les modules,
//  charger les fichiers de test (open()),
//  définir les 'options' globales)
console.log("Contexte INIT (1 fois)");

export const options = {
  vus: 10,
  duration: '30s',
};

// Chargement des données (payload) depuis le disque
const data = open('./payload.json');

// ---------------------------------------------
// 2. CONTEXTE "VU" (Default Function)
// ---------------------------------------------
// (Exécuté en BOUCLE par chaque VU (Utilisateur Virtuel))
// (C'est le scénario de test)
export default function () {
  console.log("Contexte VU (en boucle)");
  
  // La requĂȘte (Sampler)
  http.post('https://api.test.com/login', data, {
    headers: { 'Content-Type': 'application/json' },
  });

  // "Think time" (Pause)
  sleep(1); // Pause de 1 seconde
}
2.2 VUs (Virtual Users)

Les VUs (Utilisateurs Virtuels) sont l'équivalent des "Threads" dans JMeter. C'est l'unité de concurrence.

Chaque VU est une goroutine (un thread "léger" Go) qui exécute votre export default function () en boucle, de maniÚre indépendante et parallÚle.

ModĂšle Asynchrone (Event-Loop)

k6 étant basé sur un event-loop Go (similaire à Node.js), les VUs sont trÚs légers en RAM/CPU. Un seul thread physique peut gérer des centaines, voire des milliers, de VUs (connexions parallÚles).

Différence JMeter : JMeter utilise 1 Thread Java (lourd) par VU. 1000 VUs = 1000 Threads Java (consomme beaucoup de RAM). k6 (1000 VUs) n'utilisera qu'une fraction des ressources.

2.3 L'objet options (Configuration)

L'objet options (exportĂ© depuis le contexte init) dĂ©finit la configuration du test de charge (le "comment"). Ces valeurs peuvent ĂȘtre surchargĂ©es en CLI (-u, -d).

Options Simples (vus / duration)

Pour un test simple (charge fixe).

// Fait un "Ramp-up" (montée) de 10 VUs en 5 sec
// Maintient 10 VUs (Hold) pendant 30 sec
// Fait un "Ramp-down" (descente) Ă  0 en 5 sec
export const options = {
  vus: 10,
  duration: '30s',
  
  // (Optionnel) ContrÎle de la montée/descente
  rampUp: '5s',
  rampDown: '5s',
};
Options Avancées (stages)

Pour un test par paliers (voir 4.2). (Si stages est défini, vus/duration/ramp* sont ignorés).

Options de CritĂšres (thresholds)

Pour définir les SLA (voir 3.3).

export const options = {
  thresholds: {
    'http_req_duration': ['p(95)<500'], // P95 < 500ms
    'http_req_failed': ['rate<0.01'],    // Erreurs < 1%
  },
};
3.1 Sampler : k6/http

Le module k6/http est le "Sampler" principal pour les tests web.

http.get(url, [params])
import http from 'k6/http';

export default function () {
  const params = {
    headers: {
      'Authorization': 'Bearer 12345',
      'X-My-Header': 'MyValue',
    },
    tags: {
      name: 'GetUsers', // Tag la métrique (pour filtrer les résultats)
    },
  };
  const res = http.get('https://api.test.com/users', params);
}
http.post(url, [body], [params])
import http from 'k6/http';

export default function () {
  const url = 'https://api.test.com/login';
  
  // Le 'body' (payload)
  const payload = JSON.stringify({
    email: 'user@example.com',
    password: '123',
  });

  const params = {
    headers: {
      'Content-Type': 'application/json',
    },
  };
  
  const res = http.post(url, payload, params);
}
3.2 check() (Assertion)

check() est l'équivalent des "Assertions" (JMeter). C'est ce qui vérifie si la réponse reçue est correcte (validation fonctionnelle).

Important : Un check() qui Ă©choue n'arrĂȘte pas l'exĂ©cution du VU. Il incrĂ©mente simplement la mĂ©trique checks (en Ă©chec). C'est une vĂ©rification "soft".

Exemple de check()
import http from 'k6/http';
import { check } from 'k6';

export default function () {
  const res = http.get('https://api.test.com/users/1');
  
  // 'check' prend la réponse (res) et un objet
  // de vérifications (Titre -> Fonction booléenne)
  check(res, {
    '1. Statut est 200': (r) => r.status === 200,
    
    '2. Le corps contient du texte': (r) => r.body.includes('Alice'),
    
    '3. Le JSON est correct': (r) => {
      // (Test coûteux, uniquement si nécessaire)
      const j = r.json(); 
      return j.id === 1;
    },
  });
}

Résultat (CLI) :

     ✓ 1. Statut est 200
     ✓ 2. Le corps contient du texte
     ✗ 3. Le JSON est correct
       ↳ (r.json().id === 1) returned false
       
     checks..................: 66.67% ✓ 2 ✗ 1
3.3 thresholds (SLO/SLA)

Les Thresholds (Seuils) sont la fonctionnalité la plus importante de k6. C'est ce qui définit les critÚres de réussite (Pass/Fail) (SLA/SLO) de l'ensemble du test.

Si check() (3.2) vérifie la *correction fonctionnelle*, thresholds vérifie la *performance*.

Syntaxe (dans options)

[métrique]: [conditions (array de strings)]

Exemple Complet
export const options = {
  thresholds: {
    // 1. Métrique Standard (Durée)
    // "p(95)" = 95e percentile. (95% des requĂȘtes
    // doivent ĂȘtre < 500ms).
    'http_req_duration': ['p(95)<500', 'p(99)<1500'],

    // 2. Métrique Standard (Erreurs)
    // "rate" = Taux. (Moins de 1% des requĂȘtes
    // doivent ĂȘtre en Ă©chec (non-2xx/3xx)).
    'http_req_failed': ['rate<0.01'],

    // 3. Métrique Standard (Checks)
    // (Plus de 98% de nos "checks" (3.2)
    // doivent réussir).
    'checks': ['rate>0.98'],
    
    // 4. Métrique Custom (voir 5.2)
    // (P90 de notre "Trend" custom < 100ms)
    'my_custom_trend': ['p(90)<100'],
  },
};

Si un seul de ces seuils n'est pas atteint Ă  la fin du test, k6 s'arrĂȘtera avec un code d'erreur (non-zĂ©ro), ce qui fera Ă©chouer le pipeline CI/CD.

4.1 scenarios (Exécuteurs)

L'objet options simple (vus/duration) est un raccourci. Pour des tests complexes (plusieurs "Thread Groups"), on utilise l'objet scenarios.

Un "Scénario" lie un Exécuteur (Executor) (comment la charge est appliquée) à une fonction JS (ce qu'il faut exécuter).

Types d'Exécuteurs (Executors)
ExécuteurDescription
ramping-vus(Le plus courant) Montée/Palier/Descente basé sur le nombre de VUs. (Voir 4.2).
ramping-arrival-rate(RPS) MontĂ©e/Palier/Descente basĂ© sur le nombre de requĂȘtes/sec (RPS).
constant-vusNombre fixe de VUs (ex: 10 VUs) pendant X temps.
constant-arrival-rate(RPS) Nombre fixe de requĂȘtes/sec.
per-vu-iterationsChaque VU exécute le scénario N fois (ex: 10 VUs, 5 itérations = 50 runs).
Exemple (2 Scénarios)
export function adminLogin() { /* ... */ }
export function userSearch() { /* ... */ }

export const options = {
  scenarios: {
    // Scénario 1 (Charge de base)
    search_users: {
      executor: 'ramping-vus',
      exec: 'userSearch', // Fonction Ă  appeler
      stages: [
        { duration: '1m', target: 100 },
      ],
    },
    // Scénario 2 (Spike test)
    login_admin: {
      executor: 'per-vu-iterations',
      exec: 'adminLogin',
      vus: 5,
      iterations: 10,
    },
  },
};
4.2 Exécuteur : ramping-vus (Stages)

L'exécuteur ramping-vus est le plus utilisé pour simuler un test de charge réaliste (montée en charge, palier, descente).

Il est défini par un tableau (array) stages.

Exemple de Scénario (30 min)
export const options = {
  scenarios: {
    my_load_test: {
      executor: 'ramping-vus',
      startTime: '0s',
      
      stages: [
        // 1. Ramp-up (Montée en charge)
        // (De 0 Ă  100 VUs en 5 minutes)
        { duration: '5m', target: 100 },
        
        // 2. Hold (Palier)
        // (Maintient 100 VUs pendant 20 minutes)
        { duration: '20m', target: 100 },
        
        // 3. Ramp-down (Descente)
        // (De 100 Ă  0 VUs en 5 minutes)
        { duration: '5m', target: 0 },
      ],
    },
  },
};
4.3 Cycle de Vie (Setup/Teardown)

En plus du code init (1 fois, 1 thread) et VU (N fois, N threads), k6 offre deux fonctions spéciales pour la préparation et le nettoyage.

export function setup()

S'exécute 1 seule fois au tout début du test (aprÚs init, avant VU).

Usage : Préparer l'environnement de test (ex: insérer des données en BDD) ou récupérer un token d'authentification global.

La valeur retournée (return) par setup() est passée en argument à la fonction default (VU).

export function teardown(data)

S'exécute 1 seule fois à la toute fin du test (aprÚs que tous les VUs aient terminé).

Usage : Nettoyer l'environnement (ex: supprimer les données de test en BDD).

L'argument data (optionnel) est la valeur qui a été retournée par setup().

Exemple de Cycle de Vie
export function setup() {
  // 1. (Exécuté 1 fois)
  const res = http.post('https://api.test.com/auth', { ... });
  const token = res.json().token;
  
  // 2. Passe le token aux VUs
  return { authToken: token };
}

export default function (data) {
  // 3. (Exécuté N fois)
  // 'data' est { authToken: "..." }
  const params = { headers: { 'Authorization': `Bearer ${data.authToken}` } };
  http.get('https://api.test.com/profile', params);
}

export function teardown(data) {
  // 4. (Exécuté 1 fois)
  // 'data' est { authToken: "..." }
  http.post('https://api.test.com/cleanup', ...);
}
5.1 Métriques (Built-in)

k6 collecte automatiquement un ensemble de métriques systÚme, utilisées pour les thresholds et le résumé final.

Nom de la MétriqueTypeDescription
vusGaugeNombre d'utilisateurs virtuels (VUs) actifs.
http_reqsCounterNombre total de requĂȘtes HTTP effectuĂ©es.
http_req_durationTrend(La plus importante) Temps de réponse total (ms) (sans le DNS/Connect).
http_req_waitingTrend(TTFB - Time To First Byte). Temps d'attente de la réponse.
http_req_failedRateTaux de requĂȘtes Ă©chouĂ©es (non-2xx/3xx).
checksRateTaux de check() (assertions) réussis.
data_sentCounterOctets envoyés.
data_receivedCounterOctets reçus.
5.2 Métriques (Custom)

Vous pouvez (et devriez) créer vos propres métriques pour mesurer des aspects spécifiques de votre application.

TypeDescriptionUsage
Counter (Compteur)Une valeur qui ne fait qu'augmenter (ex: total de logins).myCounter.add(1)
Gauge (Jauge)Une valeur qui peut monter ou descendre (ex: nb items dans le panier).myGauge.add(5)
Rate (Taux)Un pourcentage de "vrai" (ex: % de logins réussis).myRate.add(true), myRate.add(false)
Trend (Tendance)(Le plus utile) Stocke des valeurs de temps (ms). Calcule automatiquement Min, Max, Moy, P90, P95.myTrend.add(res.timings.waiting)
Exemple (Trend)
import { Trend } from 'k6/metrics';

// 1. (Contexte INIT) Définir la métrique (Trend)
const loginTrend = new Trend('login_response_time');

export default function () {
  // 2. (Contexte VU) Ajouter une valeur
  const res = http.post('/login', ...);
  loginTrend.add(res.timings.duration);
}

// 3. (Contexte INIT) Définir un seuil
export const options = {
  thresholds: {
    'login_response_time': ['p(95)<800'], // P95 des logins < 800ms
  },
};
5.3 group() (Transactions)

group() est l'Ă©quivalent du "Transaction Controller" de JMeter. Il permet de grouper logiquement plusieurs requĂȘtes (Samplers) en une seule action mĂ©tier.

Fonctionnement

Les métriques (ex: http_req_duration) collectées à l'intérieur du group() sont aussi taguées avec le nom du groupe.

import http from 'k6/http';
import { group, sleep } from 'k6';

export default function () {
  // Action 1: Login
  group('01_Login_Process', function () {
    http.get('https://test.k6.io/login');
    sleep(1);
    const res = http.post('https://test.k6.io/login', ...);
    // (Les mĂ©triques de ces 2 requĂȘtes sont taguĂ©es
    //  "group:01_Login_Process")
  });

  sleep(5);

  // Action 2: Search
  group('02_Search_Users', function () {
    http.get('https://test.k6.io/search?q=test');
    // (Tagué "group:02_Search_Users")
  });
}

Résultat : Permet de filtrer les résultats (ex: "Quel est le P95 de http_req_duration uniquement pour le groupe '01_Login_Process' ?").

6.1 Exécution (CLI)

L'exécution se fait via la commande k6 run.

Commandes Courantes
# Exécuter un script (utilise les 'options' du .js)
$ k6 run script.js

# Surcharger les 'options' (Test rapide)
# -u (vus)
# -d (duration)
$ k6 run -u 10 -d 30s script.js

# Passer des variables d'environnement
# (-e ou --env)
$ k6 run -e MY_API_KEY="12345" script.js
// (Dans le script : __ENV.MY_API_KEY)
Exemple de Sortie (Résumé CLI)
     ✓ 1. Statut est 200

     checks..................: 100.00% ✓ 180   ✗ 0   
     data_received...........: 1.5 MB  50 kB/s
     data_sent...............: 22 kB   725 B/s
     http_req_duration.......: avg=300ms min=150ms med=280ms p(90)=450ms p(95)=490ms
     http_req_failed.........: 0.00%   ✓ 0     ✗ 180 
     http_reqs...............: 180     5.9/s
     vus.....................: 10      min=10  max=10
6.2 Sorties (Outputs) (Intégration Monitoring)

La force de k6 (pour l'observabilité) est sa capacité à "streamer" (envoyer) les résultats en temps réel vers d'autres plateformes (via l'option --out).

Fichiers Locaux
# 1. JSON (format structuré)
k6 run script.js --out json=results.json

# 2. CSV
k6 run script.js --out csv=results.csv
Plateformes de Monitoring (Temps Réel)

Permet de corréler le test de charge (k6) avec la performance de l'infra (Prometheus/Grafana).

# 1. InfluxDB (Push)
k6 run script.js --out influxdb=http://influx-server:8086/k6

# 2. Prometheus (Remote Write - Push)
k6 run script.js --out prometheusremotewrite=http://prom-server/api/v1/write

# 3. Datadog / New Relic (Agent)
# (Nécessite l'agent StatsD (Datadog) ou l'API (New Relic))
k6 run script.js --out datadog
k6 run script.js --out newrelic
6.3 k6 Cloud (SaaS)

k6 Cloud est la plateforme SaaS (payante) de Grafana Labs, conçue pour gérer et scaler les tests k6.

Fonctionnement

Au lieu de k6 run, vous utilisez k6 cloud :

# Authentification (1 fois)
k6 login cloud

# Exécuter le script sur le Cloud
k6 cloud script.js
Avantages
  • Scaling (DistribuĂ©) : (L'avantage n°1) Vous n'ĂȘtes plus limitĂ© par votre injecteur local. Vous pouvez demander Ă  k6 Cloud de simuler 1 Million de VUs depuis 10 rĂ©gions du monde (AWS, GCP...).
  • Dashboards : Fournit une interface web (Grafana) pour analyser les rĂ©sultats (Pass/Fail, Graphes).
  • Historique : Stocke l'historique de tous vos tests (comparaison).
  • IntĂ©gration CI/CD : Facilite l'intĂ©gration dans GitLab/GitHub Actions (ex: "Fail si p95 > 500ms").
7.1 k6-browser (Test Front-End)

k6 (par défaut) est un testeur de protocole (Back-end). Il ne charge pas le HTML, n'exécute pas le JS, ne rend pas le CSS.

Le module k6-browser (inclus dans k6) ajoute le "Real Browser Testing" (Front-end). Il utilise Chromium (via Playwright) pour piloter un vrai navigateur.

Usage : Test Hybride

Permet de mesurer la performance perçue par l'utilisateur (Core Web Vitals) et de combiner des tests L7 (API) et des tests Browser (Front) dans le mĂȘme scĂ©nario.

import { browser } from 'k6/browser';
import { check } from 'k6';

export const options = {
  scenarios: {
    browser_test: {
      executor: 'constant-vus',
      vus: 1,
      duration: '30s',
      options: {
        browser: {
          type: 'chromium',
        },
      },
    },
  },
};

export default async function () {
  const page = await browser.newPage();
  await page.goto('https://test.k6.io/');
  
  check(page, {
    'Page title': p => p.locator('h1').textContent() == 'Welcome!',
  });
  
  // Collecte automatiquement les métriques Core Web Vitals
  // (browser_web_vital_lcp, browser_web_vital_cls...)
  
  await page.close();
}
7.2 Extensions (xk6)

k6 (par défaut) ne supporte pas tout (ex: SQL, Kafka). Pour ajouter des protocoles, il faut recompiler le binaire k6 avec des extensions (écrites en Go).

xk6 est l'outil (le "builder") utilisé pour compiler k6 avec ces extensions.

Exemple (k6-sql)

Objectif : Tester une base de données PostgreSQL.

# 1. (Prérequis) Installer Go, Git

# 2. Installer xk6
$ go install go.k6.io/xk6/cmd/xk6@latest

# 3. Compiler un binaire k6 "personnalisé" (avec l'extension sql)
$ xk6 build --with github.com/loadimpact/k6-extension-sql

# (Résultat : un nouveau binaire "k6" est créé)
Script (sql.js)
import sql from 'k6/x/sql';

const db = sql.open('postgres', 'postgres://user:pass@host/db');

export default function () {
  sql.query(db, 'SELECT * FROM users WHERE id=1;');
}

// 4. Exécuter (avec le binaire personnalisé)
$ ./k6 run sql.js
7.3 Script ModĂšle (Bonnes Pratiques)

Un script de test de charge "propre" (ex: load-test.js) :

import http from 'k6/http';
import { sleep, check, group } from 'k6';
import { Trend } from 'k6/metrics';

// --- 1. CONTEXTE INIT ---
// (Charger les données, définir les métriques custom)
const loginData = JSON.parse(open('./data/users.json'));
const myCustomTrend = new Trend('custom_api_time');

// --- 2. OPTIONS (La Charge) ---
export const options = {
  // Scénario par paliers
  scenarios: {
    my_scenario: {
      executor: 'ramping-vus',
      stages: [
        { duration: '2m', target: 50 }, // Ramp-up
        { duration: '5m', target: 50 }, // Hold
        { duration: '1m', target: 0 },  // Ramp-down
      ],
    },
  },
  
  // CritÚres de réussite (SLA/SLO)
  thresholds: {
    'http_req_duration': ['p(95)<1000'], // P95 < 1s
    'http_req_failed': ['rate<0.02'],    // Erreurs < 2%
    'checks': ['rate>0.95'],             // Checks > 95%
    'custom_api_time': ['p(90)<800'],
  },
};

// --- 3. SETUP / TEARDOWN (Optionnel) ---
export function setup() {
  // (Ex: Récupérer un token admin)
  return { token: 'abc123' };
}

// --- 4. VU CODE (Le Scénario) ---
export default function (data) {
  // Utiliser la variable d'environnement (passée par -e)
  const host = __ENV.TARGET_HOST || 'https://test.k6.io';
  
  const params = {
    headers: { 'Authorization': `Bearer ${data.token}` },
  };

  group('01_Homepage', function () {
    const res = http.get(`${host}/`, params);
    
    check(res, {
      'Homepage status 200': (r) => r.status === 200,
    });
    
    myCustomTrend.add(res.timings.duration);
    
    sleep(2); // Think time 2 sec
  });
  
  group('02_Profile_Page', function () {
    // (Autre requĂȘte...)
  });
}