Por Lucas Yoris · Performate
k6 y observabilidad: métricas, tags y dashboards que aceleran el triage
Observabilidad en k6: métricas HTTP, tags, groups y alineación con APM—referencia Grafana k6 más correlation IDs para triage más rápido.
La prueba de carga terminó en verde, pero on-call igual tardó cuarenta minutos adivinando qué ruta regresó. La brecha suele ser alineación de observabilidad: k6 emitió http_req_duration agregado mientras los dashboards de Grafana parten por service, route y tenant—y nadie acordó el mismo vocabulario de tags antes de la corrida.
La observabilidad en k6 no trata de exportar más números. Trata de etiquetar requests de forma consistente para que métricas del cliente, umbrales y traces de APM cuenten una sola historia durante el triage. En esta guía verás qué métricas built-in importan, cómo diseñar tags de baja cardinalidad y cómo conectar la salida de k6 con dashboards que on-call ya usa.
Por qué los tags cambian la velocidad de triage—no solo la estética del reporte
Bajo carga, los fallos se agrupan por familia de ruta, dependencia o feature flag—no por «la API se sintió lenta». Sin tags, un umbral único en http_req_duration oculta que checkout está bien mientras search dispara:
- Métricas HTTP built-in—
http_req_duration,http_req_failed,http_reqs—agregan cada request sin tag (referencia de métricas). - Trends y Rates custom capturan pasos de negocio—añadir al carrito, autorizar pago—pero solo ayudan si van taggeados por fase del journey.
- Groups (
group()) estructuran flujos multipaso en summaries sin reemplazar tags a nivel request. - TSDBs downstream castigan labels de alta cardinalidad—IDs de usuario, tokens de sesión aleatorios y tags por VU explotan almacenamiento y lentifican queries.
Piensa en los tags como la leyenda de un mapa. Un heatmap bonito sin etiquetas manda a los ingenieros a vagar.
Cuando umbrales verdes igual pierden el incidente
Los checks prueban corrección; los umbrales prueban SLOs. Ninguno reemplaza latencia segmentada cuando una ruta arrastra el riesgo en cola. Combina métricas taggeadas con correlation IDs propagados (tracing distribuido con k6) para que iteraciones de k6 aparezcan en el mismo backend de traces que producción.
Alinea claves de tag con tipos de escenario cuando distintos executors ejercitan mezclas de rutas distintas—si no, los filtros del dashboard mienten sobre qué forma de tráfico causó el pico.
Implementación práctica con k6: tags, groups y umbrales segmentados
Define un esquema de tags pequeño y estable antes de escribir escenarios. Aplica las mismas claves en defaults de escenario, overrides por request y selectores de umbrales.
Script de ejemplo (ilustrativo—no es una prueba lista para producción). Rutas, tokens y números de SLO ficticios—adapta al naming de tu APM.
Qué demuestra este ejemplo:
- Claves de tag consistentes:
route,dependencyyenven cada request para que Grafana y summaries de k6 usen el mismo vocabulario. - Defaults a nivel escenario: tags en el escenario se propagan a métricas salvo override por request.
- Umbrales por ruta:
http_req_duration{route:search}vs{route:checkout}detecta regresiones localizadas. - Trend custom con tags: Trend
checkout_durationtaggeado porsteppara análisis de embudo sin explotar cardinalidad.
import http from 'k6/http';
import { check, group, sleep } from 'k6';
import { Trend } from 'k6/metrics';
const checkoutStep = new Trend('checkout_step_duration', true);
const BASE = __ENV.API_BASE || 'https://staging.example.com';
const HEADERS = {
'Content-Type': 'application/json',
Authorization: `Bearer ${__ENV.TOKEN}`,
'X-Correlation-Id': () => `k6-${__VU}-${__ITER}`,
};
export const options = {
scenarios: {
mixed_routes: {
executor: 'constant-arrival-rate',
rate: 20,
timeUnit: '1s',
duration: '5m',
preAllocatedVUs: 15,
maxVUs: 60,
tags: { env: __ENV.ENV_NAME || 'staging', suite: 'observability-demo' },
exec: 'mixedJourney',
},
},
thresholds: {
'http_req_duration{route:search}': ['p(95)<400', 'p(99)<700'],
'http_req_duration{route:checkout}': ['p(95)<900', 'p(99)<1400'],
'http_req_failed{route:checkout}': ['rate<0.005'],
checkout_step_duration: ['p(95)<1200'],
},
};
export function mixedJourney() {
group('browse', () => {
const res = http.get(`${BASE}/search?q=widget`, {
headers: HEADERS,
tags: { route: 'search', dependency: 'catalog' },
});
check(res, { 'search 2xx': (r) => r.status >= 200 && r.status < 300 });
sleep(0.5);
});
group('checkout', () => {
const start = Date.now();
const res = http.post(`${BASE}/checkout`, JSON.stringify({ sku: 'SKU-1', qty: 1 }), {
headers: HEADERS,
tags: { route: 'checkout', dependency: 'payments' },
});
checkoutStep.add(Date.now() - start, { step: 'submit' });
check(res, { 'checkout 2xx': (r) => r.status >= 200 && r.status < 300 });
sleep(0.3);
});
}
Patrones que funcionan
- Enum fijo de tags: documenta valores permitidos para
route,dependency,featureen un README del equipo—nunca taggees URLs crudas con query strings. - Headers de correlación: pasa
X-Correlation-Ido headers de trace context para enlazar spans del servidor con iteraciones k6. - Export a Grafana: usa
--out experimental-prometheus-rwo salida Cloud cuando ops ya dashboarddea SLIs HTTP (ideas de test desde observabilidad). - Umbrales en métricas taggeadas: frena releases en rutas que importan al producto, no en promedios globales.
Anti-patrones a evitar
- Taggear cada user ID o SKU—la cardinalidad mata TSDBs y el rendimiento del summary de k6.
- Claves de tag distintas por autor de script—
endpointvsroutevspathrompe dashboards cross-team. - Correr pruebas grandes sin compartir links de dashboard con on-call antes (staging vs producción).
Tip pro (comando de ejemplo): expone tendencias de percentiles por tag en el summary de terminal durante debug local.
k6 run observability-tags.js --summary-trend-stats="p(95),p(99)"
Qué demuestra este comando: k6 imprime tendencias de métricas taggeadas en el summary final para validar selectores de umbrales antes de empujar a CI.
Marco de decisión: qué tags y métricas priorizar
| Situación | Acción recomendada |
|---|---|
| API monolito, pocas rutas | Tag por route + method; umbral por ruta crítica |
| Microservicios detrás de un gateway | Tag route en el edge; suma dependency al llamar downstream desde el script |
| SaaS multi-tenant | Tag tenant_tier (free/pro)—nunca tenant IDs crudos en labels |
| Rollout con feature flags | Tag flag:on/off alineado a métricas canary |
| Solo smoke en CI | Tags mínimos: env, git_sha, route; pospone Trends custom hasta estabilizar |
Usa tags por ruta si on-call filtra APM por path HTTP u operation name.
Usa tags de dependencia si tu script llama varios backends y un stall de terceros no debería pasar desapercibido.
Usa tags env + git_sha si comparas regresiones entre builds en pruebas de carga en CI/CD.
Observabilidad, documentación y siguientes pasos
Las pruebas taggeadas solo sirven si los dashboards existen antes del incidente:
- Publica un doc de vocabulario de tags—claves permitidas, valores y campos de alta cardinalidad prohibidos.
- Verifica que correlation IDs aparecen en APM en un smoke de 1 minuto antes de escalar tráfico.
- Crea filas en Grafana (o equivalente) filtradas por los mismos tags de los umbrales k6.
- Alerta por divergencia de
p(99){route:critical}vs baseline, no solohttp_req_failedglobal. - Archiva metadata de corrida—set de tags, git SHA, JSON de escenario—para comparar regresiones.
Cómo Performate simplifica flujos de observabilidad k6
Los scripts crudos derivan cuando cada autor inventa nombres de tag. Abajo hay un ejemplo concreto de flujo para el journey mixto search/checkout—adapta nombres de ruta a tu catálogo.
Ejemplo: tags consistentes de import a reporte
- Importa una colección Postman con requests de search y checkout en carpetas separadas. Problema resuelto: nombres de operación se convierten en candidatos estables de tag en lugar de strings escritos a mano en cada script.
- Define tags de escenario en el editor visual:
env:staging,suite:checkout-regressionen el escenario;route:searchyroute:checkouten requests individuales. Problema resuelto: vocabulario de tags coincide con lo que exportas a k6—sin drift al editar. - Define umbrales por ruta en el panel de umbrales—p. ej. search
p(95)<400, checkoutp(95)<900. Problema resuelto: gates de SLO localizados sin leer docs de sintaxis de umbrales por cada ruta. - Corre el escenario y abre el reporte integrado filtrado por
route. Problema resuelto: QA y SRE revisan el mismo gráfico de latencia segmentada, no tres CSV exportados. - Exporta el script k6 generado con tags y umbrales embebidos para smoke gates en CI. Problema resuelto: iteración local y pipeline comparten un esquema de tags.
- Comparte el link del reporte con on-call antes de una corrida programada grande. Problema resuelto: nadie descubre un pico de saturación nuevo sin contexto.
Ese flujo conecta con el cta de este post: escenarios ejecutables, umbrales y reportes compartibles sin días de glue code.
Cierre
La observabilidad en pruebas de carga es primero un problema de vocabulario. Acuerda tags de baja cardinalidad, parte umbrales por ruta y propaga correlation IDs para que resultados de k6 caigan en los mismos dashboards que producción.
Corre un smoke taggeado de cinco minutos contra staging esta semana—y confirma que on-call puede filtrar las mismas etiquetas route en APM antes de tu próxima prueba a escala completa.
¿Listo para optimizar el rendimiento de tu API?
Usa Performate para convertir este playbook en escenarios k6 ejecutables, umbrales y reportes compartibles sin perder días en glue code.