Testes de brokers

Lendo os logs do broker MQTT para depurar clientes

Como ler logs do Mosquitto e do EMQX: defina os níveis de log certos, interprete linhas de conexão e desconexão, rastreie um cliente e chegue à correção.

Atualizado · 9 min de leitura

Lendo os logs do broker MQTT para depurar clientes

Quando um cliente diz connection lost, normalmente ele não faz ideia do motivo. O broker sabe. Cada login recusado, timeout de keep-alive, client ID duplicado e publicação negada deixa uma linha no log do broker — desde que o logging esteja configurado para guardá-la. Ler essas linhas costuma ser a forma mais rápida de depurar um cliente ao qual você não consegue acoplar um debugger.

Este guia mostra onde encontrar os logs, quais níveis de log ativar, como ler as linhas de conexão e desconexão do Mosquitto, como rastrear um cliente no EMQX e como transformar uma linha de log em uma correção.

Onde ficam os logs

InstalaçãoOnde procurar
Mosquitto via pacote Linux/var/log/mosquitto/mosquitto.log ou journalctl -u mosquitto -f
Mosquitto no Dockerdocker logs -f mosquitto (com log_dest stdout)
EMQXSaída do console no Docker (docker logs -f emqx); arquivos no diretório log/ da instalação
HiveMQlog/hivemq.log, mais log/event.log para eventos de conexão e desconexão de clientes
Broker gerenciadoGeralmente sem logs brutos do broker — use reason codes e monitoramento (veja abaixo)

Se o arquivo de log do Mosquitto continua vazio, procure na saída de inicialização por Error: Unable to open log file /var/log/mosquitto/mosquitto.log for writing. — o usuário do broker não consegue escrever no diretório. A configuração de logging em detalhes está em logging do Mosquitto.

Ative o nível de log certo

O logging padrão do Mosquitto esconde quase tudo de que você precisa para depurar clientes. Uma configuração útil durante a investigação:

mosquitto.conf — logging durante o debug
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 pacote de entrada e saída — muito verboso, ative só durante o debug
log_type debug

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

Reinicie o broker depois de mudar as opções de logging. connection_messages true gera as linhas de conexão e desconexão em que quase todo este guia se baseia, e um formato de timestamp legível poupa a conversão manual de segundos Unix. Você pode gerar uma configuração completa com o gerador de mosquitto.conf.

No EMQX 5, aumente o nível do console de um container com a variável de ambiente EMQX_LOG__CONSOLE__LEVEL=debug, ou mude em tempo de execução:

EMQX: mudar o nível de log em tempo de execução
emqx ctl log set-level debug
# ...reproduza o problema...
emqx ctl log set-level warning

Lendo as linhas de conexão do Mosquitto

Uma conexão bem-sucedida gera duas linhas:

Conexão bem-sucedida
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').

O parêntese no final descreve o pacote CONNECT:

CampoSignificado
p2Protocolo: p2 = MQTT 3.1.1, p5 = MQTT 5 (p1 seria o antigo 3.1)
c1Clean session / clean start: c1 = sessão nova, c0 = retomar sessão persistente
k60Intervalo de keep-alive em segundos
u'alice'Username enviado pelo cliente (ausente se não houver)

Esses quatro campos respondem várias perguntas de uma vez: o cliente usa mesmo a versão de protocolo que você imagina? Ele pede uma sessão persistente? Qual keep-alive ele realmente definiu?

Linhas de desconexão e o que significam

A linha que o Mosquitto imprime quando um cliente sai é a mais útil de todo o log:

Linha de logCausaCorreção
Client sensor-01 disconnected.DISCONNECT limpo do clienteNada — é o esperado
Client sensor-01 closed its connection.TCP fechado sem DISCONNECTO cliente travou, foi encerrado ou perdeu energia
Client sensor-01 has exceeded timeout, disconnecting.Nenhum pacote por 1,5 × keep-aliveCorrija o loop do cliente, a lógica de sleep ou o timeout de NAT — veja timeout de keep-alive
Client sensor-01 already connected, closing old connection.Um segundo cliente usou o mesmo client IDIDs únicos por dispositivo — veja client ID duplicado
Client sensor-01 disconnected, not authorised.Credenciais erradas ou sem permissão para conectarVerifique username, password e plugin de autenticação
Client sensor-01 disconnected due to protocol error.Pacote malformado ou inesperadoBug da biblioteca, versão de protocolo errada ou MQTT puro em um listener WebSocket
Socket error on client sensor-01, disconnecting.A conexão quebrou no nível de redeQueda de rede, erro de TLS ou RST de um equipamento intermediário
Outgoing messages are being dropped for client sensor-01.A fila do cliente está cheiaConsumidor lento — aumente os limites ou consuma mais rápido

Quando duas linhas com already connected, closing old connection se alternam a cada poucos segundos, dois dispositivos estão disputando um client ID e reconectando em loop. Gere IDs únicos com o gerador de client ID.

Acompanhando uma sessão em nível debug

Com log_type debug, o Mosquitto registra cada pacote. Um subscriber e um publisher em um topic de teste ficam mais ou menos assim (Mosquitto 2.x, resumido):

Log de debug de uma publicação
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)

O parêntese das linhas PUBLISH se lê assim: d = flag DUP, q = QoS, r = retain, m = message ID, depois o topic e o tamanho do payload. Se você vê Received PUBLISH mas nenhum Sending PUBLISH, o broker aceitou a mensagem, mas não havia assinatura correspondente — confira o topic filter no topic matcher. Uma linha Denied PUBLISH significa que uma ACL bloqueou a mensagem; esse caso é tratado em ACL negada em silêncio.

Para reproduzir um caso rapidamente, deixe o log aberto em um terminal e gere tráfego em outro:

Debug com dois terminais
# Terminal 1 — o lado do broker
docker logs -f mosquitto 2>&1 | grep --line-buffered -E 'sub-01|pub-01'

# Terminal 2 — o lado do cliente, com saída de debug do 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'

O -d faz os clientes imprimirem o próprio log de pacotes (Client sub-01 sending CONNECT, received CONNACK (0)), então você compara as duas visões linha a linha.

Rastreando um cliente no EMQX

Em um broker EMQX movimentado, o log de debug global é barulhento demais. Rastreie um único cliente:

EMQX: rastrear um client ID
emqx ctl trace start client sensor-01 /tmp/sensor-01.log
# ...deixe o cliente conectar, publicar e falhar...
emqx ctl trace stop client sensor-01

O arquivo de trace contém os eventos de conexão, autenticação, assinatura, publicação e desconexão daquele cliente, incluindo o motivo quando o broker fecha a conexão. O dashboard tem uma página de log trace que faz o mesmo e permite baixar o resultado. Você também pode rastrear por topic ou pelo IP do cliente quando não sabe qual client ID está se comportando mal.

Alguns comandos cobrem a maioria das buscas nos logs:

Buscas úteis nos logs
# Tudo sobre um cliente na última hora
journalctl -u mosquitto --since "1 hour ago" | grep -F 'sensor-01'

# Quais clientes dão timeout com mais frequência?
grep -o 'Client [^ ]* has exceeded timeout' /var/log/mosquitto/mosquitto.log | sort | uniq -c | sort -rn

# Converter um timestamp Unix de uma linha de log padrão do Mosquitto
date -d @1792228321        # GNU date; no macOS: date -r 1792228321

Correlacione o horário do broker com os logs do próprio cliente. Se os relógios divergem, alinhe por um evento que os dois lados veem, como o CONNACK.

Quando não há log do broker

Sem acesso aos logs do broker, monte o mesmo quadro a partir do lado do cliente:

  • Registre cada reason code que sua biblioteca reportar e consulte em reason codes do MQTT explicados ou na ferramenta de reason codes.
  • Assine os topics $SYS do broker se estiverem expostos — contadores de clientes conectados e de mensagens descartadas costumam mostrar a mesma tendência do log. Veja monitoramento com topics $SYS.
  • Reproduza o problema com o cliente MQTT online no mesmo broker. Se lá funciona, a causa está no código ou na rede do dispositivo, não no broker.

Confirme a correção no log

Uma linha de log também é o seu teste de aceitação. Depois de uma mudança, reproduza o cenário original e observe o log: a linha has exceeded timeout ou already connected não deve mais aparecer, e a linha New client connected deve mostrar os parâmetros que você pretendia (protocolo, flag clean, keep-alive). Depois desative o log de debug novamente.

O broker vê os erros de todos os clientes, mas só os anota se você pedir. Configure as mensagens de conexão e um timestamp legível, aumente o nível só durante a investigação e aprenda o punhado de linhas de desconexão — elas correspondem quase uma a uma à correção.

Perguntas frequentes

Como ativar o log de debug no Mosquitto?

Adicione log_type debug (ou log_type all) ao mosquitto.conf junto com um log_dest como stdout ou file e reinicie o broker. O log de debug imprime cada pacote que o broker recebe e envia, então desative-o assim que encontrar o problema.

O que significa 'has exceeded timeout, disconnecting' no Mosquitto?

O broker não recebeu nada do cliente por 1,5 vez o intervalo de keep-alive e fechou a conexão. O loop de rede do cliente parou, o dispositivo dormiu ou um gateway NAT derrubou a conexão. Confira o keep-alive na linha 'New client connected' (k60 significa 60 segundos).

Como ver os logs de um único cliente no EMQX?

Use um log trace: emqx ctl trace start client <clientid> <arquivo> grava tudo daquele client ID em um arquivo, e o dashboard do EMQX oferece o mesmo na página de log trace. Pare com emqx ctl trace stop client <clientid> quando terminar.