Pruebas de brokers

Leer los logs del broker MQTT para depurar clientes

Cómo leer los logs de Mosquitto y EMQX: elige los niveles de log adecuados, interpreta las líneas de conexión y desconexión, traza un cliente y corrige.

Actualizado · 9 min de lectura

Leer los logs del broker MQTT para depurar clientes

Cuando un cliente dice connection lost, normalmente no tiene ni idea de por qué. El broker sí lo sabe. Cada login rechazado, timeout de keep-alive, client ID duplicado y publicación denegada deja una línea en el log del broker, siempre que el logging esté configurado para guardarla. Leer esas líneas suele ser la forma más rápida de depurar un cliente al que no puedes conectar un depurador.

Esta guía muestra dónde encontrar los logs, qué niveles de log activar, cómo leer las líneas de conexión y desconexión de Mosquitto, cómo trazar un cliente en EMQX y cómo convertir una línea de log en una solución.

Dónde están los logs

InstalaciónDónde mirar
Mosquitto desde un paquete Linux/var/log/mosquitto/mosquitto.log o journalctl -u mosquitto -f
Mosquitto en Dockerdocker logs -f mosquitto (con log_dest stdout)
EMQXSalida de consola en Docker (docker logs -f emqx); archivos en el directorio log/ de la instalación
HiveMQlog/hivemq.log, más log/event.log para los eventos de conexión y desconexión de clientes
Broker gestionadoNormalmente sin logs del broker en bruto: apóyate en reason codes y monitorización (ver más abajo)

Si el archivo de log de Mosquitto se queda vacío, revisa la salida de arranque en busca de Error: Unable to open log file /var/log/mosquitto/mosquitto.log for writing.: el usuario del broker no puede escribir en el directorio. La configuración del logging en detalle está en logging de Mosquitto.

Activa el nivel de log adecuado

El logging por defecto de Mosquitto oculta casi todo lo que necesitas para depurar clientes. Una configuración útil mientras investigas:

mosquitto.conf — logging durante la depuración
log_dest stdout
log_dest file /var/log/mosquitto/mosquitto.log

log_type error
log_type warning
log_type notice
log_type information
log_type subscribe
log_type unsubscribe
# Cada paquete de entrada y salida: muy verboso, actívalo solo al depurar
log_type debug

connection_messages true
log_timestamp true
log_timestamp_format %Y-%m-%dT%H:%M:%S

Reinicia el broker después de cambiar las opciones de logging. connection_messages true genera las líneas de conexión y desconexión en las que se basa casi toda esta guía, y un formato de marca de tiempo legible te ahorra convertir segundos Unix a mano. Puedes generar una configuración completa con el generador de mosquitto.conf.

En EMQX 5, sube el nivel de consola de un contenedor con la variable de entorno EMQX_LOG__CONSOLE__LEVEL=debug, o cámbialo en caliente:

EMQX: cambiar el nivel de log en caliente
emqx ctl log set-level debug
# ...reproduce el problema...
emqx ctl log set-level warning

Leer las líneas de conexión de Mosquitto

Una conexión correcta produce dos líneas:

Conexión correcta
2026-10-17T09:12:01: New connection from 192.168.1.20:52144 on port 1883.
2026-10-17T09:12:01: New client connected from 192.168.1.20:52144 as sensor-01 (p2, c1, k60, u'alice').

El paréntesis final describe el paquete CONNECT:

CampoSignificado
p2Protocolo: p2 = MQTT 3.1.1, p5 = MQTT 5 (p1 sería el antiguo 3.1)
c1Clean session / clean start: c1 = sesión nueva, c0 = reanudar sesión persistente
k60Intervalo de keep-alive en segundos
u'alice'Usuario enviado por el cliente (no aparece si no hay)

Estos cuatro campos responden a muchas preguntas de golpe: ¿usa el cliente de verdad la versión de protocolo que crees?, ¿pide una sesión persistente?, ¿qué keep-alive ha configurado realmente?

Las líneas de desconexión y su significado

La línea que imprime Mosquitto cuando un cliente se va es la más útil de todo el log:

Línea de logCausaSolución
Client sensor-01 disconnected.DISCONNECT limpio del clienteNada, es lo esperado
Client sensor-01 closed its connection.TCP cerrado sin DISCONNECTEl cliente se bloqueó, fue terminado o perdió la alimentación
Client sensor-01 has exceeded timeout, disconnecting.Ningún paquete durante 1,5 × keep-aliveArregla el bucle del cliente, la lógica de reposo o el timeout de NAT; consulta timeout de keep-alive
Client sensor-01 already connected, closing old connection.Un segundo cliente usó el mismo client IDID únicos por dispositivo; consulta client ID duplicado
Client sensor-01 disconnected, not authorised.Credenciales erróneas o sin permiso para conectarRevisa usuario, contraseña y plugin de autenticación
Client sensor-01 disconnected due to protocol error.Paquete mal formado o inesperadoBug de la librería, versión de protocolo equivocada o MQTT sin WebSocket en un listener WebSocket
Socket error on client sensor-01, disconnecting.La conexión se rompió a nivel de redCaída de red, error TLS o RST de un equipo intermedio
Outgoing messages are being dropped for client sensor-01.La cola del cliente está llenaConsumidor lento: sube los límites o consume más rápido

Cuando dos líneas con already connected, closing old connection se alternan cada pocos segundos, dos dispositivos se están disputando un client ID y reconectan en bucle. Genera ID únicos con el generador de client ID.

Seguir una sesión con nivel debug

Con log_type debug, Mosquitto registra cada paquete. Un suscriptor y un publicador en un topic de prueba se ven más o menos así (Mosquitto 2.x, abreviado):

Log de depuración de una publicación
Received SUBSCRIBE from sub-01
    testmqtt/logs/# (QoS 1)
sub-01 1 testmqtt/logs/#
Sending SUBACK to sub-01
Received PUBLISH from pub-01 (d0, q1, r0, m1, 'testmqtt/logs/a', ... (5 bytes))
Sending PUBACK to pub-01 (m1, rc0)
Sending PUBLISH to sub-01 (d0, q1, r0, m1, 'testmqtt/logs/a', ... (5 bytes))
Received PUBACK from sub-01 (Mid: 1, RC:0)

El paréntesis de las líneas PUBLISH se lee así: d = flag DUP, q = QoS, r = retain, m = message ID, y después el topic y el tamaño del payload. Si ves Received PUBLISH pero ningún Sending PUBLISH, el broker aceptó el mensaje pero no había ninguna suscripción que coincidiera: comprueba el topic filter con el topic matcher. Una línea Denied PUBLISH significa que una ACL lo bloqueó; es el caso tratado en ACL denegada en silencio.

Para reproducir un caso rápidamente, deja el log abierto en una terminal y genera tráfico desde otra:

Depuración con dos terminales
# Terminal 1 — el lado del broker
docker logs -f mosquitto 2>&1 | grep --line-buffered -E 'sub-01|pub-01'

# Terminal 2 — el lado del cliente, con salida de depuración del cliente
mosquitto_sub -d -h localhost -i sub-01 -t 'testmqtt/logs/#' -q 1 &
mosquitto_pub -d -h localhost -i pub-01 -t 'testmqtt/logs/a' -q 1 -m 'hello'

-d hace que los clientes impriman su propio log de paquetes (Client sub-01 sending CONNECT, received CONNACK (0)), así puedes comparar ambas vistas línea por línea.

Trazar un cliente en EMQX

En un broker EMQX con mucho tráfico, el log de depuración global es demasiado ruidoso. Traza un solo cliente:

EMQX: trazar un client ID
emqx ctl trace start client sensor-01 /tmp/sensor-01.log
# ...deja que el cliente conecte, publique y falle...
emqx ctl trace stop client sensor-01

El archivo de trace contiene los eventos de conexión, autenticación, suscripción, publicación y desconexión de ese cliente, incluido el motivo cuando el broker cierra la conexión. El dashboard tiene una página de log trace que hace lo mismo y permite descargar el resultado. También puedes trazar por topic o por IP del cliente cuando no sabes qué client ID se está portando mal.

Unos pocos comandos cubren la mayoría de búsquedas en los logs:

Búsquedas útiles en los logs
# Todo sobre un cliente en la última hora
journalctl -u mosquitto --since "1 hour ago" | grep -F 'sensor-01'

# ¿Qué clientes dan timeout más a menudo?
grep -o 'Client [^ ]* has exceeded timeout' /var/log/mosquitto/mosquitto.log | sort | uniq -c | sort -rn

# Convertir una marca de tiempo Unix de una línea de log por defecto de Mosquitto
date -d @1792228321        # GNU date; en macOS: date -r 1792228321

Correlaciona la hora del broker con los logs del propio cliente. Si los relojes difieren, alinéalos con un evento que ambos lados vean, como el CONNACK.

Cuando no hay log del broker

Sin acceso a los logs del broker, construye la misma imagen desde el lado del cliente:

  • Registra cada reason code que reporte tu librería y búscalo en los reason codes de MQTT explicados o en la herramienta de reason codes.
  • Suscríbete a los topics $SYS del broker si están expuestos: los contadores de clientes conectados y de mensajes descartados suelen mostrar la misma tendencia que el log. Consulta monitorizar con topics $SYS.
  • Reproduce el problema con el cliente MQTT online contra el mismo broker. Si ahí funciona, la causa está en el código o la red del dispositivo, no en el broker.

Confirma la solución en el log

Una línea de log también es tu prueba de aceptación. Tras un cambio, reproduce el escenario original y vigila el log: la línea has exceeded timeout o already connected ya no debería aparecer, y la línea New client connected debería mostrar los parámetros que pretendías (protocolo, flag clean, keep-alive). Después vuelve a desactivar el log de depuración.

El broker ve los errores de todos los clientes, pero solo los apunta si se lo pides. Configura los mensajes de conexión y una marca de tiempo legible, sube el nivel solo mientras investigas y aprende el puñado de líneas de desconexión: corresponden casi una a una con la solución.

Preguntas frecuentes

¿Cómo activo el log de depuración en Mosquitto?

Añade log_type debug (o log_type all) a mosquitto.conf junto con un log_dest como stdout o file y reinicia el broker. El log de depuración imprime cada paquete que el broker recibe y envía, así que desactívalo cuando hayas encontrado el problema.

¿Qué significa 'has exceeded timeout, disconnecting' en Mosquitto?

El broker no recibió nada del cliente durante 1,5 veces su intervalo de keep-alive, así que cerró la conexión. El bucle de red del cliente se detuvo, el dispositivo se durmió o un gateway NAT cortó la conexión. Revisa el keep-alive en la línea 'New client connected' (k60 significa 60 segundos).

¿Cómo veo los logs de un solo cliente en EMQX?

Usa un log trace: emqx ctl trace start client <clientid> <archivo> registra todo lo de ese client ID en un archivo, y el dashboard de EMQX ofrece lo mismo en su página de log trace. Detenlo con emqx ctl trace stop client <clientid> al terminar.