Dozzle (log viewer)
Dozzle — visor de logs en tiempo real para los contenedores del stack. ⬆ Documentación AITHA
Dozzle expone los logs de todos los contenedores del host desde
el navegador. Está pensado para leer el JSON estructurado de los tres backends Python —
chat-server, user-service y things_extensions (eventos, req_id, duration_ms) —,
pero muestra igual los servicios que emiten texto plano. Los tres emiten el mismo JSON:
mismos campos de correlación (req_id, process, level, event, message, duration_ms)
y la misma disciplina de niveles, así que una traza cruzada entre servicios es posible
buscando el mismo req_id en los logs de ambos contenedores.
Acceso
- URL pública:
https://logs.<PUBLIC_BASE_DOMAIN>(p. ej.https://logs.aitha.es). - Local:
http://localhost:3090. - Login: usuario
admin; la contraseña esGLOBAL_DOZZLE_ADMIN_PASSWORD(.env.secretslocal / Ansible Vault remoto). - La sesión dura 48h (
DOZZLE_AUTH_TTL); el logout cierra la sesión de Dozzle. - La UI es de solo lectura:
DOZZLE_ENABLE_ACTIONS=falseyDOZZLE_ENABLE_SHELL=false(no hay botones de stop/restart ni shell).
Consultas que resuelven el 90% de los casos
-
Seguir un request completo por
req_id: pega elreq_iden el buscador y ordena por tiempo. Verás la narrativa en orden:pipeline.started→identity.*→llm.resolved→prompt.built→mode.classified→execution.*→llm.call.*→response.emitted→usage.recorded→pipeline.finished. -
Filtrar errores: filtro
level=error(los niveles canónicosinfo,debug,tracetambién funcionan). -
Etapas lentas: el buscador filtra por cualquier campo; para ver las etapas que pasan de 1s usa
duration_ms > 1000en el panel SQL (SELECT message.event, message.duration_ms FROM logs WHERE message.duration_ms > 1000). -
Traza cruzada por
req_identre backends: el mismoreq_idviaja dechat-serverauser-service/things_extensionscuando los llaman, así que una petición se sigue entera buscando ese id en cada contenedor. En terminal:docker logs user-service 2>&1 | jq -c 'select(.req_id=="<id>") | {t:.timestamp, ev:.event, ms:.duration_ms}'
docker logs things_extensions 2>&1 | jq -c 'select(.req_id=="<id>") | {t:.timestamp, ev:.event, ms:.duration_ms}'Y en Dozzle, SQL:
SELECT message.event, message.req_id, message.duration_ms FROM logs WHERE message.level = 'info' ORDER BY message.timestamp.
Los campos sensibles se muestran redactados (***) porque la redacción ocurre en
los backends (app/utils/logger.py) antes de emitir la línea; Dozzle solo pinta lo que llega.
En la terminal, sin Dozzle
./infra logs <proyecto> colorea el JSON automáticamente (reordena
TIMESTAMP LEVEL [logger] event key=val … y deja intacto lo que no es JSON).
Si quieres el equivalente directo sobre el contenedor:
docker logs -f chat-server | jq -R -r -f deployment/scripts/utils/pretty_logs.jq
Requiere jq en el host (ya se instala vía roles/common en los servidores).
Operación
./infra up dozzlegeneradata/users.yml(bcrypt) en el primer arranque desdeGLOBAL_DOZZLE_ADMIN_PASSWORD. En el deploy remoto lo renderiza Ansible conmode: 0600; el hash nunca sube desde el controlador../infra clean dozzle --databorradata/(usuarios + ajustes).- El visor sobrevive a
./infra down all(SKIP_BULK_STOP=true).