---
title: "Correlation IDs y trazabilidad distribuida en pruebas de carga: corridas k6 depurables"
description: "Propaga headers de contexto de traza desde k6, alinea con spans del backend y depura colas de latencia más rápido."
publishDate: "2026-07-16"
draft: false
keyword: "correlation ids trazabilidad distribuida k6"
intent: "MOFU"
cta: "Usa Performate para compartir corridas etiquetadas donde los correlation IDs mapean limpio a trazas APM."
tags: ["k6", "pruebas-de-carga", "rendimiento-api", "correlación"]
translationOf: correlation-ids-distributed-tracing-k6
---

Tu prueba soak muestra p99 de checkout a 2,4 segundos durante una hora—pero cuando on-call abre el dashboard APM, cada span parece tráfico anónimo desde `10.0.0.0`. Sin contexto de traza, los fallos bajo carga se vuelven arqueología: grep en logs, adivinar números de VU y esperar que alguien guardó el timestamp correcto.

Los picos de latencia se vuelven accionables cuando cada iteración de k6 emite **traceparent** y **baggage** opcional compatibles con OpenTelemetry ([W3C Trace Context](https://www.w3.org/TR/trace-context/)). En esta guía verás por qué los correlation IDs cambian la respuesta a incidentes bajo carga, cómo generar headers de traza válidos en k6, y qué checks de observabilidad demuestran que tu generador y backend acuerdan la misma traza.

## Por qué las pruebas de carga necesitan contexto de traza—no solo tags

Los tags de k6 separan métricas por ruta y escenario; el APM separa spans por trace ID. Sin un puente entre ambos, optimizas a ciegas:

- **Tráfico anónimo:** los backends agrupan generadores en una cuenta de servicio—los spans carecen del contexto de iteración que necesitas.
- **La cola de latencia oculta causalidad:** picos p99 pueden ser waits de BD, saltos de mesh o cachés frías—los tags solos no los distinguen ([análisis de cuellos de botella](/es/blog/analisis-cuellos-de-botella-api)).
- **Los soak corren largo:** fugas de memoria y acumulación en colas aparecen tras decenas de minutos; necesitas trace IDs duraderos por familia de request ([playbook soak](/es/blog/playbook-soak-testing-memory-leaks)).
- **Flujos multi-salto:** checkout puede tocar auth, inventario y pago—un correlation ID debe coser el grafo.

Piensa en los headers de traza como códigos de barras en cada request sintético: los escáneres downstream deben leer el mismo ID que imprimió tu herramienta de carga.

### Cuando las métricas dicen lento pero los logs no dicen nada

Los equipos suelen añadir `X-Request-Id` manualmente mientras el service mesh espera `traceparent` W3C. Los gateways eliminan headers desconocidos; el APM muestra trazas parciales. Alinea con el estándar que exporta tu plataforma—Jaeger, Tempo, Datadog y New Relic ingieren contexto W3C cuando está configurado ([tags de observabilidad](/es/blog/k6-observabilidad-metricas-tags)).

## Implementación práctica con k6: traceparent W3C por iteración

Genera un trace ID fresco por request (o por iteración de VU en flujos multi-paso), formatea `traceparent` correctamente y pasa baggage opcional con metadata de carga como `vu` e `iter`. El middleware del backend debe continuar la traza—no iniciar un root span nuevo en silencio.

**Ejemplo de script (ilustrativo—no listo para producción).** El fragmento usa URLs, tokens y números SLO ficticios. Adapta base URL, auth, payloads y umbrales a tu entorno.

**Qué demuestra este ejemplo:**

- **traceparent W3C válido:** versión `00`, trace ID hex de 32 chars, span ID hex de 16 chars, flag sampled `01`.
- **Baggage para metadata de carga:** `vu`, `iter` y `scenario` propagan cuando tu collector soporta baggage W3C.
- **Header de correlación legacy:** `X-Correlation-Id` opcional para servicios aún sin OpenTelemetry.
- **Métricas etiquetadas + trace IDs:** tags de ruta k6 para resúmenes; trace IDs para flame graphs APM en la misma corrida.

```javascript
import http from 'k6/http';
import { check, sleep } from 'k6';
import { randomBytes } from 'k6/crypto';

const BASE = __ENV.API_BASE || 'https://staging.example.com';
const TOKEN = __ENV.TOKEN || 'staging-token-replace-me';

function hex(bytes) {
  return Array.from(new Uint8Array(bytes))
    .map((b) => b.toString(16).padStart(2, '0'))
    .join('');
}

function traceparent() {
  const traceId = hex(randomBytes(16)); // 32 hex chars
  const spanId = hex(randomBytes(8)); // 16 hex chars
  return `00-${traceId}-${spanId}-01`;
}

function correlationId() {
  return `k6-${__VU}-${__ITER}-${hex(randomBytes(4))}`;
}

function traceHeaders() {
  const tp = traceparent();
  const cid = correlationId();
  return {
    traceparent: tp,
    tracestate: 'k6=load',
    baggage: `vu=${__VU},iter=${__ITER},scenario=checkout`,
    'X-Correlation-Id': cid,
  };
}

export const options = {
  scenarios: {
    traced_checkout: {
      executor: 'constant-arrival-rate',
      rate: Number(__ENV.CHECKOUT_RPS || 8),
      timeUnit: '1s',
      duration: '10m',
      preAllocatedVUs: 10,
      maxVUs: 40,
      tags: { route: 'checkout', trace: 'w3c' },
      exec: 'checkoutTraced',
    },
  },
  thresholds: {
    'http_req_duration{route:checkout}': ['p(95)<900', 'p(99)<1400'],
    http_req_failed: ['rate<0.01'],
  },
};

export function checkoutTraced() {
  const body = JSON.stringify({ sku: `SKU-${__VU}`, qty: 1 });
  const headers = {
    'Content-Type': 'application/json',
    Authorization: `Bearer ${TOKEN}`,
    ...traceHeaders(),
  };

  const res = http.post(`${BASE}/checkout`, body, {
    headers,
    tags: { route: 'checkout', trace: 'w3c' },
  });

  check(res, { 'checkout 2xx': (r) => r.status >= 200 && r.status < 300 });
  sleep(0.5);
}
```

**Patrones que funcionan**

- **Una traza por journey de usuario** cuando los flujos llaman auth y luego checkout—reutiliza traceparent entre pasos en la misma iteración.
- **Filtra APM por baggage `vu=`** para saltar de outliers del resumen k6 a flame graphs exactos.
- **Depura PII del baggage** antes de exportar trazas a tenants compartidos ([datos de prueba GDPR](/es/blog/datos-prueba-rendimiento-gdpr)).
- **Combina con sampling específico de env** para que collectors de staging retengan 100% de trazas de carga durante investigaciones ([variables de entorno](/es/blog/gestion-entornos-variables-k6)).

**Anti-patrones a evitar**

- Reutilizar un `X-Request-Id` estático para todos los VUs—colapsa miles de requests en una traza lógica.
- Enviar `traceparent` mal formado (hex de longitud incorrecta)—el APM descarta contexto en silencio.
- Loguear trace IDs completos en artefactos CI públicos cuando las trazas contienen payloads de clientes.
- Ignorar sidecars de mesh que sobrescriben headers de traza salvo que inyectes en el salto correcto.

**Pro tip (comando de ejemplo):** la línea siguiente exporta JSON de resumen k6 junto a una corrida que correlacionarás manualmente en APM—no es flag obligatorio en cada soak.

```bash
k6 run traced-checkout.js --summary-export=run-summary.json --tag git_sha=$GIT_SHA
```

**Qué demuestra este comando:** los resúmenes exportados incluyen tags de escenario y git SHA—pega timestamps de ventanas lentas en búsqueda APM con baggage `git_sha` o marcadores de deploy coincidentes.

## Marco de decisión: request ID vs traza W3C completa

| Situación | Acción recomendada |
|:---|:---|
| Monolito con solo correlación en logs | `X-Correlation-Id` + logs estructurados; migra a W3C cuando llegue APM |
| OpenTelemetry / mesh ya desplegado | `traceparent` + baggage en cada request k6; verifica retención del collector |
| Flujos multi-paso checkout/auth | Un trace ID por iteración en todas las llamadas HTTP del default function |
| Soak largo buscando fugas | Traza única por request; filtra outliers p99 en APM por ventana temporal + tag de ruta |
| Datos regulados en payloads | Minimiza baggage; depura IDs de logs exportados ([datos GDPR](/es/blog/datos-prueba-rendimiento-gdpr)) |

**Usa traceparent W3C si** tu backend o service mesh ya exporta OpenTelemetry—es el default en plataformas API modernas.

**Usa headers de correlación legacy si** servicios antiguos solo loguean `X-Request-Id`—pero planifica migración antes de que headers duales confundan a on-call.

**Usa metadata en baggage si** tu collector lo soporta y necesitas mapear `__VU`/`__ITER` de k6 a spans sin adivinar timestamps.

## Observabilidad, documentación y próximos pasos

La propagación de trazas solo ayuda cuando collectors, retención y runbooks coinciden. Antes de escalar tráfico:

- [ ] Verifica que APM de staging retenga trazas durante todo el soak—no solo los primeros quince minutos.
- [ ] Documenta qué headers pasan los gateways; listas de strip han bloqueado `traceparent` antes.
- [ ] Añade paso en runbook: «filtrar trazas por ventana temporal `route:checkout`, abrir trace IDs del peor p99».
- [ ] Confirma que IPs del generador están allowlisted sin forzar todos los spans a un nodo de servicio anónimo.
- [ ] Archiva JSON de resumen k6, git SHA y tags de escenario por corrida para que postmortems enlacen métricas y trazas.

## Cómo Performate simplifica pruebas de carga alineadas a trazas

Escribir headers de traza a mano en cada script exportado deriva cuando alguien copia una plantilla vieja sin baggage. Abajo un **ejemplo concreto de flujo** para checkout trazado bajo soak.

**Ejemplo: corridas etiquetadas que mapean a APM**

1. **Importa requests de checkout** desde Postman u OpenAPI—el mismo flujo que soakas por fugas de memoria. *Problema resuelto:* una definición de request; sin bloques HTTP duplicados «trazado» vs «sin trazar».
2. **Añade headers custom en el panel de escenario:** notas placeholder de `traceparent` y `tracestate=k6=load` estático donde documentas estándares—or exporta y añade el helper una vez. *Problema resuelto:* los revisores ven intención de headers antes del export, no enterrada en git.
3. **Aplica tags `route:checkout` y `trace:w3c`** en el escenario para que resúmenes k6 coincidan con filtros APM. *Problema resuelto:* compara colas de métricas y de trazas con el mismo vocabulario.
4. **Corre soak de 10 minutos** y exporta reporte integrado más script k6 para CI. *Problema resuelto:* comparte un enlace con on-call que incluye tags de escenario y fallos de umbral.
5. **Pega timestamps de ventana lenta en APM** y busca por correlation ID o baggage `vu=` de la peor iteración. *Problema resuelto:* minutos hasta causa raíz en lugar de arqueología en logs.
6. **Re-exporta tras cambios de headers** para que CI y desktop queden alineados—especialmente cuando la plataforma mejora soporte baggage W3C.

Ese flujo mapea al `cta`: corridas etiquetadas donde los correlation IDs mapean limpio a trazas APM.

## Conclusión

Las pruebas de carga sin contexto de traza optimizan agregados, no incidentes. Propaga `traceparent` W3C, añade baggage seguro con metadata k6 y verifica que tu mesh reenvíe headers antes del próximo soak.

Corre un soak de checkout trazado esta semana—filtra APM por el peor minuto p99 y confirma que puedes abrir un flame graph de un checkout sintético sin adivinar números de VU.

[Try Performate free](https://performate.app) | [Reservar demo](/demo) | [Escenarios k6](https://k6.io/docs/using-k6/scenarios/)
