Cómo se prueba el proyecto a sí mismo
Un destino puede equivocarse en tres sitios, y cada uno pide una prueba distinta. Puede codificar los bytes equivocados. Puede codificar bytes que un almacén rechaza — algo que un servidor de captura nunca advierte, porque responde 204 a todo. Y puede escribir algo que el almacén guarda pero ningún panel puede volver a leer.
El proyecto tiene por eso tres capas, y son tres órdenes.
| Capa | Orden | Docker | Qué demuestra |
|---|---|---|---|
| 1, el contrato | make test-e2e |
no | los bytes exactos que cada destino pone en el cable |
| 2, los almacenes | make test-e2e-docker |
sí | que un almacén real los acepta y los devuelve sin cambiarlos |
| 3, los paneles | la misma orden | sí | que la consulta de cada panel responde contra lo que los destinos escribieron |
Desliza en horizontal para ver todas las columnas
Ninguna de las tres toca un router. Las capas 1 y 2 ejecutan el colector contra
un agente simulado que sirve muestras enlatadas, y la capa 1 ejecuta además el
binario real del agente contra testdata/proc/rb5009, un árbol /proc y
/sys capturado del equipo de referencia. Eso es lo que hace que una ejecución
sea reproducible en cualquier máquina, y lo que deja al router fuera del bucle.
Capa 1 — el contrato
Sección titulada «Capa 1 — el contrato»make test-e2e compila los dos binarios y apunta cada destino a un receptor
dentro del binario de prueba: servidores HTTP de captura para InfluxDB, Loki,
OTLP, Elasticsearch y Telegraf, escuchas TCP y UDP para Graphite y los modos de
socket de Telegraf, ficheros reales para los destinos de fichero y SQL, la
salida estándar del propio proceso, y un scrape del /metrics del colector
para Prometheus. Cada receptor comprueba lo que llegó, byte a byte.
No necesita router, ni Grafana, ni base de datos, ni contenedor, ni red: toda
dirección que enlaza o marca está en loopback. make test-e2e-offline lo
demuestra en vez de afirmarlo, ejecutando la batería entera dentro de un
espacio de nombres de red que no tiene más que lo.
Capa 2 — los almacenes
Sección titulada «Capa 2 — los almacenes»make test-e2e-docker levanta nueve almacenes con docker compose, ejecuta el
mismo colector contra el mismo agente simulado con todos los destinos apuntando
a ellos y luego le pregunta a cada almacén por su propia API. El JSONL del
destino de fichero es el oráculo contra el que se compara cada almacén, valor a
valor y no solo por recuento.
| Almacén | La pregunta que se le hace |
|---|---|
| InfluxDB 3 Core | SQL por HTTP: las tablas, un recuento de filas por tabla, cada valor ctxt |
| PostgreSQL 18 | el guion del destino SQL por psql, luego recuentos y el rango de ctxt |
| Elasticsearch 9 | _search con una agregación por tipo, y un documento entero |
| Loki 3 | query_range para las etiquetas de esta ejecución, y el texto de cada registro |
| Graphite | metrics/find para el árbol, render para los puntos y su orden |
| OpenTelemetry Collector | lo que decodificó, escrito de vuelta como OTLP/JSON |
| Telegraf 1.39 | el protocolo de línea que analizó: medidas, etiquetas, tipos de campo, marcas de tiempo |
| Prometheus 3 | un scrape del exportador, contra la exposición que sirvió |
Desliza en horizontal para ver todas las columnas
Cada uno está ahí porque ese producto rechaza algo que un servidor de captura acepta:
- InfluxDB 3 fija una columna como etiqueta o como campo la primera vez que ve la tabla y rechaza una escritura posterior que no coincida.
- Carbon no responde nada en absoluto: un punto más viejo que su archivo más largo, o un nombre del que whisper no puede hacer una ruta, se descarta en silencio.
- Loki responde 204 a un envío que no es consultable hasta que el trozo se vuelca, y rechaza entradas desordenadas por flujo, en el cuerpo.
- Elasticsearch infiere un mapeo del primer documento que ve para un campo y luego rechaza otro posterior que no encaje — por documento, dentro de una petición bulk que aun así responde 200.
- Telegraf es un analizador real de protocolo de línea: un espacio sin escapar en el valor de una etiqueta, o un campo sin tipo, se descarta y el lote sigue siendo 204.
- PostgreSQL es lo único que puede decir si el guion del destino SQL es SQL válido, si los tipos que eligió aguantan los valores que emite y si sus claves primarias chocan en una ejecución real.
Capa 3 — los paneles
Sección titulada «Capa 3 — los paneles»La misma orden importa después los dos dashboards en un Grafana real, apuntado
al almacén que la ejecución acaba de llenar, y pasa la consulta de cada panel
por la propia /api/ds/query de Grafana. Ahí es donde un panel falla por
motivos a los que ninguna prueba unitaria llega: un tipo que devuelve una
agregación y el complemento de la fuente de datos no sabe decodificar, una
macro que el complemento escapa, una columna que el almacén no tiene.
La primera ejecución completa, el 2026-09-16, encontró uno: la tabla de eventos
de puerto nombra label y role, que el destino escribe en una fila del
registro del kernel solo desde el inventario de la capa de la API. Una columna
que no está en la tabla no es una columna vacía en InfluxDB 3 — es
Schema error: No field named label y un panel que no puede dibujarse.
Cómo ejecutarlo
Sección titulada «Cómo ejecutarlo»make test-e2e-docker # todo; la pila se levanta y se apaga con la ejecuciónmake e2e-docker-up # deja la pila levantada, para una ejecución concretago test -v -tags dockere2e -run TestLoki ./test/e2e/docker/make e2e-docker-downEl paquete está tras la etiqueta de compilación dockere2e, así que make test y todos los trabajos por defecto de la CI no compilan nada de él: la
etiqueta es la forma de pedir nueve contenedores. make lint lo comprueba de
tipos para que no se pudra, y el flujo semanal de E2E y la puerta de publicación
lo ejecutan.
Medido en la máquina de desarrollo el 2026-09-16: la pila se levanta en 55 a 81 s con las imágenes ya descargadas, y la batería entera tarda de 75 a 100 s desde cero.